   Les outils de developpement sous FreeBSD : Guide de l'utilisateur

  James Raynard

               <jraynard@freebsd.org>
             

   17 Aout 1997

   Copyright (c) James Raynard, 1997.

   Ce document est une introduction `a l'utilisation de quelques-uns
   des outils de programmation fournis avec FreeBSD, quoique
   l'essentiel reste aussi valable pour de nombreuses autres versions
   d'Unix. Il ne cherche pas `a expliquer en detail comment coder. La
   plus grande partie du document suppose que vous n'avez aucune ou
   peu de notions prealables de programmation, bien que l'on espere
   que la plupart des programmeurs y trouveront quelque chose qui
   leur sera utile.

   CE DOCUMENT EST FOURNI ``TEL QU'EN L'ETAT'' PAR LE PROJET DE
   DOCUMENTATION FRANC,AISE DE FreeBSD ET IL N'EST DONNE AUCUNE
   GARANTIE, IMPLICITE OU EXPLICITE, QUANT A SON UTILISATION
   COMMERCIALE, PROFESSIONNELLE OU AUTRE. LES COLLABORATEURS DU
   PROJET DE DOCUMENTATION FRANC,AISE DE FreeBSD NE PEUVENT EN AUCUN
   CAS ETRE TENUS POUR RESPONSABLES DE QUELQUE DOMMAGE OU PREJUDICE
   DIRECT, INDIRECT, SECONDAIRE OU ACCESSOIRE (Y COMPRIS LES PERTES
   FINANCIeRES DUES AU MANQUE A GAGNER, A L'INTERRUPTION D'ACTIVITES,
   OU LA PERTE D'INFORMATIONS ET AUTRES) DECOULANT DE L'UTILISATION
   DE LA DOCUMENTATION OU DE L'IMPOSSIBILITE D'UTILISER CELLE-CI, ET
   DONT L'UTILISATEUR ACCEPTE L'ENTIERE RESPONSABILITE.

   Version franc,aise de Frederic Haby
   <frederic.haby@mail.dotcom.fr>.

     --------------------------------------------------------------

1. Introduction

   FreeBSD fournit un excellent environnement de developpement. Le
   systeme de base comprend des compilateurs C, C++ et Fortran, et un
   assembleur, pour ne pas mentionner l'interpreteur Perl et les
   outils Unix classiques comme sed et awk. Si cela ne vous suffit
   pas, il y a beaucoup d'autres compilateurs et interpreteurs au
   catalogue des logiciels portes. FreeBSD est tres largement
   compatible avec les standards comme POSIX et ANSI C, de meme
   qu'avec son propre heritage BSD, il est donc possible d'ecrire des
   applications qui compilent et s'executent sur une grande variete
   de plates-formes.

   Toute cette puissance, toutefois, peut submerger au premier abord,
   si vous n'avez jamais auparavant ecrit de programme sur une
   plate-forme Unix. Ce document vise `a vous aider `a vous y mettre,
   sans approfondir trop les questions les plus avancees. L'intention
   est de vous fournir suffisamment de bases pour vous permettre de
   tirer ensuite profit de la documentation.

   La plus grande partie du document ne demande aucune ou peu de
   connaissance de la programmation mais suppose une competence de
   base dans l'utilisation d'Unix et la volonte d'apprendre!

     --------------------------------------------------------------

2. Introduction `a la programmation

   Un programme est une serie d'instructions qui dit `a l'ordinateur
   de faire des choses diverses; l'instruction qu'il doit executer
   depend parfois de ce qui s'est passe lorsqu'il a execute une
   instruction precedente. Cette section vous donne un aperc,u des
   deux principales methodes pour transmettre ces instructions, ou
   ``commandes'' comme on les appellent. L'une est d'utiliser un
   interpreteur, l'autre de se servir d'un compilateur. Comme les
   langues humaines sont trop compliquees pour etre comprises sans
   ambiguite par un ordinateur, les commandes sont generalement
   ecrites dans l'un ou l'autre des languages specialement conc,us `a
   cet effet.

     --------------------------------------------------------------

  2.1. Interpreteurs

   Dans le cas d'un interpreteur, le langage s'accompagne d'un
   environnement, sous lequel vous tapez des commandes `a son invite
   et qui les execute pour vous. Pour des programmes plus compliques,
   vous pouvez saisir les commandes dans un fichier et le faire
   charger et executer les commandes qu'il contient par
   l'interpreteur. Si quelque chose se passe mal, la plupart des
   interpreteurs passeront le controle `a un debogueur pour vous
   aider `a trouver l'origine du probleme.

   Cela a l'avantage de vous permettre de voir immediatement le
   resultat de vos commandes et de corriger sur le champ vos erreurs.
   Le principal inconvenient survient lorsque vous voulez partager
   vos programmes avec d'autres. Il faut qu'ils aient le meme
   interpreteur que vous ou que vous ayez le moyen de leur fournir
   cet interpreteur; il faut aussi qu'ils comprennent comment s'en
   servir. Les utilisateurs peuvent aussi ne pas apprecier de se
   retrouver sous un debogueur s'ils appuient sur la mauvaise touche!
   Du point de vue de la performance, les interpreteurs utilisent
   parfois beaucoup de memoire et ne generent habituellement pas le
   code aussi efficacement que les compilateurs.

   A mon avis, les langages interpretes sont le meilleur moyen de
   debuter si vous n'avez jamais programme auparavant. On trouve
   typiquement ce genre d'environnement avec des langages tels que
   Lisp, Smalltalk, Perl et Basic. On peut aussi avancer que le shell
   Unix est lui-meme un interpreteur, beaucoup ecrivent en fait avec
   des procedures - scripts - pour se faciliter le travail
   d'administration de leur machine. De fait, une partie de la
   philosophie d'origine d'Unix etait de fournir nombre de petits
   programmes utilitaires qui puissent etre utilises de concert dans
   des procedures pour effectuer des taches utiles.

     --------------------------------------------------------------

  2.2. Interpreteurs disponibles pour FreeBSD

   Voici une liste des interpreteurs disponibles sous forme de
   ``paquetages'' FreeBSD, accompagnee d'une breve description des
   langages interpretes les plus repandus.

   Pour vous procurer l'un de ces ``paquetages'', il vous suffit de
   cliquer sur le lien correspondant et d'executer ensuite:

 # pkg_add nom_du_paquetage

   sous le compte super-utilisateur root. Il faut bien evidemment que
   vous ayez un systeme FreeBSD 2.1.0 ou ulterieur en etat de marche
   pour que le logiciel fonctionne.

   BASIC

           Abreviation pour ``Beginner's All-purpose Symbolic
           Instruction Code'' - code d'instructions symbolique
           universel pour les debutants. Developpe dans les annees 50
           pour apprendre la programmation aux etudiants des
           Universites et fourni avec tout ordinateur personnel qui
           se respectait dans les annees 80, BASIC a ete le premier
           langage pour de nombreux programmeurs. C'est aussi la base
           de Visual Basic(TM).

           L'interpreteur Basic Bywater et l'interpreteur Basic de
           Phil Cockroft (appele auparavant ``Rabbit Basic'') sont
           disponibles sous forme de ``paquetages'' FreeBSD.

   Lisp

           Un langage developpe `a la fin des annees 1950 comme
           alternative aux langages ``devoreurs de nombres'' qui
           e'taient populaires `a l'epoque. Au lieu d'etre base sur
           les nombres, Lisp repose sur les listes; de fait, son nom
           est une abreviation pour ``List Processing'' - traitement
           de listes. Tres repandu dans les milieux de l'IA
           (Intelligence Artificielle).

           Lisp est un langage tres puissant et sophistique, mais
           peut etre assez lourd et bavard.

           FreeBSD dispose de GNU Common Lisp sous forme de
           ``paquetage''.

   Perl

           Tres employe par les administrateurs systeme pour ecrire
           des procedures; et souvent aussi sur les serveurs World
           Wide Web pour ecrire des procedures CGI.

           La Version 4, qui est probablement encore la version la
           plus largement repandue est fournie avec FreeBSD; le plus
           recent Perl Version 5 est disponible sous forme de
           ``paquetage''.

   Scheme

           Un dialecte de Lisp qui est plutot plus compact et plus
           propre que Common Lisp. Courant dans les Universites parce
           qu'il est assez facile `a enseigner en premier cycle comme
           langage d'initiation et presente un niveau d'abstraction
           suffisant pour etre utilise pour du travail de recherche.

           FreeBSD offre en ``paquetages'' l'Interpreteur Scheme Elk,
           l'Interpreteur Scheme du MIT et l'Interpreteur Scheme SCM.

   Icon

           Le langage de programmation Icon.

   Logo

           L'interpreteur LOGO de Brian Harvey.

   Python

           Le langage de programmation oriente objet Python.

     --------------------------------------------------------------

  2.3. Compilateurs

   Les compilateurs sont assez differents. Vous ecrivez d'abord votre
   code dans un(des) fichiers(s) `a l'aide d'un editeur. Vous
   executez ensuite le compilateur et voyez s'il valide votre
   programme. S'il ne le compile pas, serrez les dents et retournez
   sous l'editeur. S'il le compile et vous en fait un programme, vous
   pouvez l'utiliser soit `a l'invite de l'interpreteur de commande,
   soit en vous servant d'un debogueur pour voir s'il fonctionne
   correctement[1].

   Ce n'est evidemment pas aussi immediat que de se servir d'un
   interpreteur. Cela vous permet cependant de faire beaucoup de
   choses qui sont tres difficiles ou meme irrealisables avec un
   interpreteur, comme ecrire du code qui interagisse etroitement
   avec le systeme d'exploitation -  ou meme ecrire votre propre
   systeme d'exploitation! C'est aussi utile si vous avez besoin
   d'ecrire du code tres efficace, parce que le compilateur peut
   prendre son temps et optimiser le code, ce qui ne serait pas
   acceptable d'un interpreteur. Distribuer un programme ecrit pour
   un compilateur est generalement plus facile - il suffit de livrer
   une copie de l'executable, en supposant que les destinataires
   aient le meme systeme d'exploitation que vous.

   Les langages compiles incluent Pascal, C et C++. C et C++ sont des
   langages qui pardonnent assez peu, et plus adaptes aux
   programmeurs plus experimentes. Pascal, d'un autre cote, a ete
   conc,u pour l'enseignement, et est un assez bon langage avec
   lequel commencer. Malheureusement, FreeBSD n'a aucun support pour
   Pascal, `a l'exception d'un convertisseur de Pascal en C, au
   catalogue des logiciels portes.

   Comme le cycle ``edition-compilation-execution-debogage'' est
   assez fastidieux, de nombreux fournisseurs de compilateurs
   commerciaux ont produit des Environnements de Developpement
   Integres (EDI en abrege). FreeBSD ne dispose pas d'EDI en tant que
   tel; il est cependant possible d'utiliser Emacs `a cet effet.
   C'est explique `a la section Utiliser Emacs comme environnement de
   developpement.

     --------------------------------------------------------------

3. Compiler avec cc

   Cette section ne s'occupe que du compilateur GNU pour C et C++,
   qui est fourni de base avec le systeme FreeBSD. Il peut etre
   appele soit avec la commande cc, soit avec gcc. Les details de la
   realisation d'un programme avec un interpreteur varient
   considerablement d'un interpreteur `a l'autre, est sont
   generalement bien decrits par l'aide en ligne de l'interpreteur.

   Une fois que vous avez ecrit votre chef-d'oeuvre, l'etape suivante
   consiste `a le convertir en quelque chose qui (esperons-le!)
   s'executera sous FreeBSD. Cela demande habituellement plusieurs
   operations successives, dont chacune est confiee `a un programme
   different.

    1. Pre-processer votre code source pour en eliminer les
       commentaires et faire diverses autres choses, comme la
       substitution des macros-instructions en C.

    2. Verifier la syntaxe de votre code pour s'assurer que vous avez
       respecte les regles du langage. Si ce n'est pas le cas, il
       rouspetera.

    3. Convertir le code source en langage assembleur - c'est tres
       proche du code machine, mais encore comprehensible par des
       etres humains. C'est du moins ce que l'on pretend[2].

    4. Convertir le langage assembleur en code machine - oui, nous
       parlons ici de bits et d'octets, de zeros et de uns.

    5. Verifier que vous avez utilise de fac,on coherente les
       fonctions et les variables globales. Si, par exemple, vous
       avez appele une fonction qui n'existe pas, il s'en plaindra.

    6. Si vous essayez de generer un programme `a partir de plusieurs
       fichiers de source, faire ce qu'il faut pour les regrouper.

    7. S'arranger pour produire quelque chose que le chargeur de
       programmes du systeme pourra mettre en memoire et executer.

   Le mot compiler est souvent utilise pour ne designer que les
   etapes 1 `a 4 - les autres sont appelees edition de liens. L'etape
   1 est parfois appelee pre-processer et les etapes 3-4 assembler.

   Heureusement, pratiquement tous ces details vous sont
   transparents, car la commande cc est une interface qui gere pour
   vous l'appel de ces differents programmes avec les bons arguments;
   taper simplement:

 % cc foobar.c

   effectue la compilation de foobar.c en passant par toutes les
   etapes decrites ci-dessus. Si vous avez `a compiler plus d'un
   fichier, faites simplement quelque chose comme:

 % cc foo.c bar.c

   Notez que la verification syntaxique ne consiste qu'en cela:
   verifier la syntaxe. Il n'y aura pas de controle sur les erreurs
   logiques que vous auriez commises, comme faire executer au
   programme une boucle infinie ou utiliser un tri `a bulles au lieu
   d'un tri par arbre binaire[3].

   cc dispose d'une quantite d'options, qui sont toutes decrites dans
   les pages de manuel. En voici quelques-unes des plus importantes,
   et la fac,on de les utiliser.

   -o nom_de_fichier

           Le nom du fichier resultat. Si vous n'utilisez pas cette
           option, cc generera un executable appele a.out[4].

 % cc foobar.c               l'executable est a.out
 % cc -o foobar foobar.c     l'executable est foobar

   -c

           Uniquement compiler le fichier, ne pas faire l'edition de
           liens. Utile pour des programmes d'essai, quand vous
           voulez simplement verifier la syntaxe, ou si vous vous
           servez d'un Makefile.

 % cc -c foobar.c

           Cela generera un fichier objet (et non un executable)
           appele foobar.o. Il pourra etre lie avec d'autres fichiers
           objet pour constituer un executable.

   -g

           Cree une version debogable de l'executable Le compilateur
           inclut alors dans l'executable des informations de
           correspondance entre les numeros de ligne du fichier
           source et les fonctions appelees. Un debogueur peut alors
           utiliser ces informations pour vous afficher le code
           source tandis que vous executez pas `a pas le programme,
           ce qui est tres utile; l'inconvenient est que toutes ces
           informations augmentent considerablement la taille du
           programme. Normalement, vous compilez avec -g quand vous
           developpez le programme, et compilez ensuite une ``version
           de livraison'' quand vous etes satisfait parce qu'il
           fonctionne correctement.

 % cc -g foobar.c

           Cela produira une version debogable du programme[5].

   -O

           Genere une version optimisee de l'executable. Le
           compilateur effectue alors diverses operations bien
           pensees pour essayer de construire un programme qui aille
           plus vite que normalement. Vous pouvez faire suivre -O
           d'un nombre pour demander un degre plus important
           d'optimisation, mais cela met souvent en evidence des
           bogues dans l'optimiseur du compilateur. Par exemple, on
           sait que la version de cc de FreeBSD 2.1.0 produit du code
           incorrect avec l'option -O2 dans certaines circonstances.

           On n'active en general l'optimisation qu'`a la compilation
           de la version de livraison.

 % cc -O -o foobar foobar.c

           Cela construira une version optimisee de foobar.

   Les trois indicateurs suivants demanderont `a cc de verifier que
   votre code est conforme `a la norme internationale, souvent
   appelee norme ANSI, bien que ce soit `a proprement parler une
   norme ISO.

   -Wall

           Active tous les messages d'avertissement que les auteurs
           du compilateur cc ont juges interessants. Malgre son nom
           (``all'' - tous), cela n'active pas tous les messages
           d'avertissement dont le compilateur est capable.

   -ansi

           Desactive la plupart, mais pas toutes, les possibilites
           non-ANSI C fournies par cc. Malgre son nom, cela ne
           garantit pas absolument que votre code soit conforme `a la
           norme.

   -pedantic

           Desactive toutes les possibilites non-ANSI C de cc.

   Sans ces indicateurs, cc vous permet d'utiliser ses extensions
   non-standard de la norme. Quelques-unes sont tres utiles, mais ne
   se retrouveront pas sur d'autres compilateurs - de fait, l'un des
   objectifs principaux de la norme est de permettre l'ecriture de
   code qui puissent etre reutilise avec n'importe quel compilateur
   sur n'importe quel systeme. C'est cela que l'on appelle du code
   portable.

   En general, vous devriez vous efforcer de rendre votre code aussi
   portable que possible, sans quoi vous risquez de devoir recrire
   entierement votre programme par la suite pour qu'il fonctionne
   ailleurs - et qui peut dire ce que vous utiliserez dans quelques
   annees?

 % cc -Wall -ansi -pedantic -o foobar foobar.c

   Cela generera un executable foobar apres avoir verifie que
   foobar.c respecte la norme.

   -lbibliotheque

           Definit une bibliotheque de fonctions `a utiliser pour
           l'edition de liens.

           L'exemple le plus courant est la compilation d'un
           programme qui utilise certaines des fonctions
           mathematiques de C. A l'inverse de la plupart des autres
           plates-formes, ces fonctions sont dans une bibliotheque
           differente de la bibliotheque C standard et vous devez
           preciser au compilateur qu'il doit l'utiliser.

           La regle est que si la bibliotheque s'appelle
           libquelque_chose.a, vous donnez `a cc l'argument
           -lquelque_chose. Par exemple, la bibliotheque mathematique
           s'appelle libm.a, vous donnez donc `a cc l'argument -lm.
           Un detail `a connaitre `a propos de la bibliotheque
           mathematique est que ce doit generalement etre la derniere
           sur la ligne de commande.

 % cc -o foobar foobar.c -lm

           Cela ajoutera `a l'edition de liens de foobar des
           fonctions de la bibliotheque mathematique.

           Si vous compilez du code C++, vous devrez ajouter -lg++,
           ou -lstdc++ si vous utilisez la version 2.2 de FreeBSD ou
           une version ulterieure, `a la ligne de commande pour
           editer les liens avec les fonctions de la bibliotheque
           C++. Au lieu de cela, vous pouvez utiliser la commande c++
           au lieu de cc, qui fera la meme chose `a votre place. Sous
           FreeBSD, c++ peut aussi etre appele avec g++.

 % cc -o foobar foobar.cc -lg++     Avec FreeBSD 2.1.6 et anterieurs
 % cc -o foobar foobar.cc -lstdc++  Avec FreeBSD 2.2 et ulterieurs
 % c++ -o foobar foobar.cc

           Chacun de ces exemples construira un executable foobar `a
           partir du fichier source C++ foobar.cc. Remarquez que, sur
           les systemes Unix, les fichiers sources C++ ont
           traditionnellement l'extension .C, .cxx ou .cc, plutot que
           l'extension .cpp de sytle MS-DOS(TM) (qui est dej`a
           utilisee pour autre chose). gcc se fiait autrefois `a
           l'extension pour savoir quel type de compilateur utiliser
           avec le fichier source, mais cette restriction ne
           s'applique plus, vous pouvez donc appeler vos fichiers C++
           .cpp en toute impunite!

     --------------------------------------------------------------

  3.1. Questions et problemes cc

   Q. J'essaie d'ecrire un programme qui utilise la fonction sin() et
   j'obtiens une erreur qui ressemble `a ce qui suit. Qu'est-ce que
   cela veut dire?

 /var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment

   R. Quand vous utilisez des fonctions mathematiques telles que
   sin(), vous devez dire `a cc d'inclure la bibliotheque
   mathematique `a l'edition de liens, comme ceci:

 % cc -o foobar foobar.c -lm

   Q. D'accord, j'ai ecrit ce petit programme pour m'entrainer `a
   utiliser -lm. Il ne fait que calculer 2.1 `a la puissance 6:

 #include <stdio.h>

 int main() {
       float f;

       f = pow(2.1, 6);
       printf("2.1 ^ 6 = %f\n", f);
       return 0;
 }
            

   et l'ai compile comme ceci:

 % cc temp.c -lm

   comme vous avez dit qu'il fallait le faire, mais voil`a ce que
   j'obtiens `a l'execution:

 % ./a.out
 2.1 ^ 6 = 1023.000000

   Ce n'est pas la bonne reponse! Que se passe-t-il?

   R. Quand le compilateur voit que vous appelez une fonction, il
   regarde s'il en a dej`a vu un prototype. Si ce n'est pas le cas,
   il suppose que la fonction retourne un int - entier, ce qui n'est
   evidemment pas ce que vous souhaitez dans ce cas.

   Q. Comment alors regler ce probleme?

   R. Les prototypes des fonctions mathematiques sont dans math.h. Si
   vous incluez ce fichier, le compilateur trouvera le prototype et
   cessera de vous fournir un resultat bizarre!

 #include <math.h>
 #include <stdio.h>

 int main() {
 ...
            

   Apres l'avoir recompile de la meme fac,on qu'auparavant,
   executez-le:

 % ./a.out
 2.1 ^ 6 = 85.766121

   Si vous utilisez la moindre fonction mathematique, incluez
   toujours math.h et n'oubliez pas d'utiliser la bibliotheque
   mathematique `a l'edition de liens.

   Q. J'ai compile un fichier appele foobar.c et je ne trouve pas
   d'executable appele foobar. Ou est-il passe?

   R. N'oubliez pas, cc appellera l'executable a.out `a moins que
   vous ne lui disiez de faire autrement. Utilisez l'option
   -o nom_de_fichier:

 % cc -o foobar foobar.c

   Q. OK, si j'ai un executable appele foobar, je le vois avec ls,
   mais quand je tape foobar sur la ligne de commande, il me dit que
   le fichier n'existe pas. Pourquoi ne le trouve-t-il pas?

   R. A l'inverse de MS-DOS, Unix ne regarde pas dans le repertoire
   courant quand il cherche le programme que vous voulez executer, `a
   moins que vous ne le lui disiez. Soit tapez ./foobar, ce qui veut
   dire ``executer le fichier appele foobar du repertoire courant'',
   ou modifiez votre variable d'environnement PATH pour qu'elle
   ressemble `a:

 bin:/usr/bin:/usr/local/bin:.

   Le dernier point signifie ``chercher dans le repertoire courant si
   le fichier n'est pas dans les autres repertoires''.

   Q. J'ai appele mon executable test, mais il ne se passe rien quand
   je le lance. Pourquoi?

   R. Il y a un programme appele test dans /usr/bin sur la plupart
   des systemes Unix et c'est celui-l`a que trouve l'interpreteur de
   commandes avant de regarder dans le repertoire courant. Soit
   tapez:

 % ./test

   ou choisissez un meilleur nom pour votre programme!

   Q. J'ai compile et tout a commence `a fonctionner correctement,
   puis il y a eu une erreur et il m'a dit quelque chose `a propos de
   "core dumped". Qu'est-ce que cela veut dire?

   A. L'expression core dump date des tous premiers jours d'Unix,
   quand les machines utilisaient la memoire centrale - ``core
   memory'' pour stocker les informations. Essentiellement, si le
   programme ``plantait'' dans certaines conditions, le systeme
   enregistrait sur disque le contenu de la memoire centrale dans un
   fichier appele core, que le programmeur pouvait ensuite dissequer
   pour trouver ou les choses avaient mal tournees.

   Q. Fascinant, mais que suis-je cense faire maintenant?

   A. Servez-vous de gdb pour analyser l'image memoire (Reportez-vous
   `a la section Deboguer).

   R. Quand mon programme a genere une image memoire, il a dit
   quelque chose `a propose de "segmentation fault" - ``erreur de
   segmentation''. Qu'est-ce que c'est?

   Q. Cela signifie essentiellement que votre programme a essaye
   d'effectuer une quelconque operation illegale sur la memoire; Unix
   est conc,u pour proteger le systeme d'exploitation des programmes
   mal eduques.

   Les raisons les plus courantes en sont:

     * Essayer d'ecrire en memoire adressee par un pointeur NULL,
       e.g.:

 char *foo = NULL;
 strcpy(foo, "bang!");
               

     * Utiliser un pointeur qui n'a pas ete initialise, e.g.:

 char *foo;
 strcpy(foo, "bang!");
               

       Le pointeur aura une valeur aleatoire qui, avec de la chance,
       adressera une zone memoire non accessible `a votre programme,
       de sorte que le noyau tuera ce dernier avant qu'il ne provoque
       de degat. Si vous manquez de chance, il pointera quelque part
       `a l'interieur de votre programme et endommagera l'une de vos
       structures de donnees, provoquant un dysfonctionnement
       mysterieux de votre programme.

     * Tenter d'acceder au-del`a du dernier element d'un tableau,
       e.g.:

 int bar[20];
 bar[27] = 6;
             

     * Essayer d'enregistrer quelque chose dans une zone de memoire
       accessible en lecture seule, e.g.:

 char *foo = "Mon texte";
 strcpy(foo, "bang!");
               

       Les compilateurs Unix stockent souvent les chaines de
       caracteres constantes comme "Mon texte" en memoire accessible
       en lecture seule.

     * Utiliser incorrectement les fonctions malloc() et free(),
       e.g.:

 char bar[80];
 free(bar);
              

       ou:

 char *foo = malloc(27);
 free(foo);
 free(foo);
              

   Commettre l'une de ces fautes ne provoquera pas toujours une
   erreur, mais ce sont malgre tout des choses `a ne pas faire.
   Certains systemes et compilateurs sont plus tolerants que
   d'autres, ce qui fait que des programmes qui s'executent
   correctement sur un systeme peuvent ne plus fonctionner sur un
   autre.

   Q. Parfois, le programme provoque la generation d'une image
   memoire avec le message "bus error". Mon manuel Unix dit qu'il
   s'agit d'un erreur materiel, mais l'ordinateur fonctionne
   apparemment correctement. Est-ce vrai?

   R. Fort heureusement, non (`a moins bien sur que vous n'ayez aussi
   un probleme materiel). C'est habituellement une autre fac,on de
   dire que vous avez accede incorrectement `a la memoire.

   Q. Il me semble que cette histoire de core dump peut etre tres
   utile, si je peux la provoquer quand je veux. Est-ce possible, ou
   dois-je attendre qu'il se produise une erreur?

   R. Oui, allez simplement sur une autre console ou fenetre xterm et
   tapez:

 % ps

   pour connaitre l'IDentifiant de processus de votre programme,
   puis:

 % kill -ABRT pid

   ou pid est l'ID de processus que vous avez recherche.

   C'est par exemple utile si votre programme est parti dans une
   boucle infinie. Au cas ou votre programme piegerait les
   interruptions SIGABRT, il y a plusieurs autres signaux qui auront
   le meme effet.

     --------------------------------------------------------------

4. Make

  4.1. Qu'est-ce que make?

   Lorsque vous travaillez sur un programme simple avec seulement un
   ou deux fichiers de source, taper:

 % cc fichier1.c fichier2.c

   n'est pas trop genant, mais cela devient rapidement tres
   fastidieux lorsqu'il y a plusieurs fichiers - et cela peut aussi
   mettre du temps `a compiler.

   Un fac,on d'eviter ces problemes est d'utiliser des fichiers
   objets et de ne recompiler que les fichiers de source dont le
   contenu a change. Nous pourrions alors avoir quelque chose du
   style:

 % cc fichier1.o fichier2.o ... file37.c ...

   si nous avons modife fichier37.c, et celui-l`a uniquement, depuis
   notre compilation precedente. Cela peut serieusement accelerer la
   compilation, mais ne resout pas le probleme de saisie `a
   repetition de la commande.

   Nous pourrions aussi ecrire une procedure pour resoudre ce dernier
   probleme, mais ne ne pourrions alors que lui faire tout
   recompiler, ce qui serait tres peu efficace sur un gros projet.

   Que ce passe-t-il si nous avons des centaines de fichiers de
   sources? Si nous travaillons en equipe et que d'autres oublient de
   nous prevenir des modifications qu'ils ont apportees `a un des
   fichiers que nous utilisons?

   Peut-etre pourrions-nous rassembler les deux solutions et ecrire
   quelque chose qui ressemble `a une procedure et comporte une sorte
   de regle magique qui dise quand tel fichier de source doit etre
   compile. Nous n'aurions plus besoin que d'un programme qui
   comprennent ces regles, parce que c'est un peu trop complique pour
   une procedure.

   Ce programme s'appelle make. Il lit un fichier, qu'on appelle un
   makefile, qui lui dit quelles sont les dependances entre les
   differents fichiers, et en deduit lesquels ont besoin ou non
   d'etre recompiles. Par exemple, une regle peut signifier quelque
   chose comme ``si fromboz.o est plus ancien que fromboz.c, cela
   veut dire que fromboz.c doit avoir ete modifie, il faut donc le
   recompiler''. Le fichier ``makefile'' inclut aussi des regles qui
   lui disent comment recompiler, ce qui en fait un outil encore plus
   puissant.

   Ces fichiers ``makefiles'' sont habituellement ranges dans le meme
   repertoire que les sources auxquels ils s'appliquent, et peuvent
   etre appeles makefile, Makefile ou MAKEFILE. La plupart des
   programmeurs utilisent le nom Makefile, ce qui fait qu'ils se
   trouvent alors vers le debut de la liste des fichiers et sont
   ainsi facilement reperables [6].

     --------------------------------------------------------------

  4.2. Exemple d'utilisation de make

   Voici un fichier Makefile elementaire :

 foo: foo.c
       cc -o foo foo.c
        

   Il contient deux lignes, une pour la dependance et une pour la
   generation.

   La ligne decrivant la dependance contient le nom du programme
   (qu'on appelle la cible), suivi de ``deux points'', puis d'un
   blanc et du nom du fichier source. Quand make lit cette ligne, il
   regarde si foo existe; s'il existe, il compare la date de derniere
   modification de foo `a celle de derniere modification de foo.c. Si
   foo n'existe pas, ou s'il est anterieur `a foo.c, il regarde alors
   la ligne de generation pour savoir ce qu'il faut faire. En
   d'autres termes, c'est la regle `a appliquer pour savoir si foo.c
   doit etre recompile.

   La ligne de generation commence par une tabulation (appuyez sur la
   touche Tab) suivie de la commande que vous taperiez pour compiler
   foo si vous le faisiez sur la ligne de commande. Si foo n'est pas
   `a jour ou s'il n'existe pas, make execute alors cette commande
   pour le creer. En d'autres termes, c'est la regle qui dit `a make
   comment recompiler foo.c.

   Ainsi, quand vous tapez make, il fera en sorte que foo soit en
   phase avec les dernieres modifications que vous avez apportees `a
   foo.c. Ce principe s'etend aux Makefiles avec des centaines de
   cibles - de fait, sur FreeBSD, il est possible de compiler tout le
   systeme d'exploitation en tapant simplement make world dans le
   repertoire adequat!

   Une autre particularite de Makefiles est que les cibles ne sont
   pas necessairement des programmes. Nous pourrions par exemple
   avoir le Makefile suivant:

 foo: foo.c
       cc -o foo foo.c

 install:
       cp foo /home/me
        

   Nous pouvons dire `a make quelle cible nous voulons atteindre en
   tapant:

 % make cible

   make examinera alors cette cible et ignorera toutes les autres.
   Par exemple, si, avec le Makefile precedent, nous tapons make foo,
   make ignorera la cible install.

   Si nous tapons simplement make tout court, il examinera toujours
   la premiere cible et s'arretera ensuite sans s'occuper des autres.
   Si nous avions tape make dans ce cas, il serait simplement alle `a
   la cible foo, aurait recompile foo si necessaire, et se serait
   arrete sans passer `a la cible install.

   Remarquez que la cible install ne depend en fait de rien du tout!
   Cela signifie que la commande sur la ligne suivante est toujours
   executee si nous essayons de reconstruire cette cible en tapant
   make install. Dans ce cas, il copiera foo dans le repertoire de
   l'utilisateur. C'est souvent utilise par les Makefiles de
   logiciels, de sorte que l'application soit installee dans le bon
   repertoire, une fois correctement compilee.

   C'est un point un peu delicat `a expliquer. Si vous ne comprenez
   pas exactement comment make fonctionne, la meilleure chose `a
   faire est d'ecrire un programme simple comme le classique
   ``Bonjour, le monde!'', un fichier Makefile et de faire des
   essais. Compilez ensuite en utilisant plus d'un fichier source, ou
   en ayant un fichier source qui inclut un fichier d'en-tete. La
   commande touch vous sera tres utile - elle modifie la date d'un
   fichier sans que vous ayez `a l'editer.

     --------------------------------------------------------------

  4.3. Makefiles FreeBSD

   L'ecriture de Makefiles peut etre assez compliquee. Heureusement,
   les systemes bases sur BSD, comme FreeBSD, en fournissent de tres
   puissants, integres au systeme. Le catalogue des logiciels portes
   de FreeBSD en est un excellent exemple. Voici l'essentiel d'un de
   leurs Makefiles typiques:

 MASTER_SITES=   ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/
 DISTFILES=      scheme-microcode+dist-7.3-freebsd.tgz

 .include <bsd.port.mk>
        

   Si nous allons maintenant dans le repertoire associe `a ce
   logiciel et tapons make, voici ce qui se passe:

    1. Il regarde si le code source de ce logiciel est dej`a present
       sur le systeme.

    2. S'il n'y est pas, une connexion FTP `a l'URL indiquee par
       MASTER_SITES est etablie pour telecharger le source.

    3. La somme de controle est calculee sur le source et comparee `a
       celle calculee sur une version connue et validee. Cela pour
       s'assurer que le source n'a pas ete corrompu pendant le
       transfert.

    4. Les modifications necessaires pour que le code fonctionne sous
       FreeBSD sont appliquees - c'est ce que l'on appelle patcher.

    5. Les operations particulieres de configuration du source sont
       effectuees. (De nombreuses distributions de programmes Unix
       essayent de determiner sur quel systeme elles sont compilees
       et de quelles fonctionnalites Unix optionnelles il
       dispose - c'est `a ce stade du scenario d'installation de
       logiciels sous FreeBSD que leur sont fournies ces
       informations).

    6. Le code source du programme est compile. De fait, on passe
       dans le repertoire ou le code a ete decompacte et make y est
       execute - le Makefile du programme lui-meme contient les
       informations necessaires `a sa compilation.

    7. Nous disposons maintenant d'une version compilee du programme.
       Si nous le voulons, nous pouvons maintenant la tester; si nous
       avons confiance dans le programme, nous pouvons taper make
       install. Cela recopiera le programme et tous les fichiers
       d'environnement dont il a besoin `a l'endroit adequat; une
       entree sera aussi creee dans une base de donnees des
       logiciels, de fac,on `a ce qu'il puisse etre desinstalle par
       la suite, si nous changeons d'avis.

   Je pense que vous serez maintenant d'accord pour trouver que c'est
   assez impressionnant pour une simple procedure de quatre lignes!

   Le secret se trouve `a la derniere ligne, qui dit `a make d'aller
   voir ce qu'il y a dans le Makefile appele bsd.port.mk. Il est
   facile de rater cette ligne, mais c'est pourtant de l`a que vient
   toute la mecanique subtile. Quelqu'un a ecrit un Makefile qui dit
   `a make de faire tout ce qui a ete decrit ci-dessus (plus deux ou
   trois autres choses dont je n'ai pas parle, dont le traitement des
   erreurs qui pourraient se produire) et tout le monde peut
   l'utiliser en mettant simplement cette unique ligne dans son
   propre Makefile!

   Si vous voulez jeter un oeil `a ces Makefiles systemes, ils sont
   dans le repertoire /usr/share/mk, mais il vaut mieux attendre
   d'avoir un peu d'experience des Makefiles, parce qu'ils sont tres
   compliques (et si vous les regardez, ayez sous la main une bonne
   dose de cafe serre!).

     --------------------------------------------------------------

  4.4. Utilisation plus poussee de make

   make est un outil tres puissant, et peut faire beaucoup plus que
   l'exemple elementaire que nous avons donne. Il y a malheureusement
   plusieurs versions de make, et elles sont tres differentes. La
   meilleure fac,on de savoir ce qu'elles peuvent faire est
   certainement de lire la documentation - esperons que cette
   introduction vous aura fourni les bases pour le faire.

   La version de make fournie avec FreeBSD est Berkeley make; elle
   s'accompagne d'un guide dans /usr/share/doc/psd/12.make. Pour le
   visualiser, tapez:

 % zmore paper.ascii.gz

   dans ce repertoire.

   Il y a des nombreux logiciels du catalogue des logiciels portes
   qui utilisent GNU make, qui est tres bien documente dans les pages
   ``info''. Si vous avez installe un de ces logiciels, GNU make sera
   automatiquement installe sont le nom gmake. Il est aussi
   disponible sous forme de logiciel porte ou precompile autonome.

   Pour visualiser les pages ``info'' de GNU make, il vous faut
   editer le fichier dir du repertoire /usr/local/info et y ajouter
   une ligne pour ce programme. C'est une ligne du genre:

  * Make: (make).                 L'utilitaire GNU Make.
      

   Une fois que c'est fait, vous pouvez taper info puis selectionner
   make dans le menu (ou sous Emacs, taper C-h i).

     --------------------------------------------------------------

5. Deboguer

  5.1. Le debogueur

   Le debogueur qui est fourni avec FreeBSD s'appelle gdb (GNU
   debogueur). Vous le lancez en tapant:

 % gdb nom_du_programme

   bien que la plupart des gens preferent l'executer sous Emacs. Ce
   qui se fait avec:

 M-x gdb RET progname RET

   Se servir d'un debogueur vous permet d'executer le programme sous
   controle. Vous pouvez typiquement l'executer pas `a pas, inspecter
   les valeurs des variables, les modifier, dire au debogueur
   d'executer le programme jusqu'`a un certain endroit et de s'y
   arreter, et ainsi de suite. Vous pouvez meme le rattacher `a un
   programme qui est dej`a en cours d'execution, ou charger une image
   memoire - ``core''. Il est meme possible de deboguer le noyau,
   bien que cela soit un peu plus complique que dans le cas des
   programmes utilisateurs, dont nous parlerons dans cette section.

   gdb dispose d'une assez bonne aide en ligne, ainsi que d'un jeu de
   pages ``info'', cette section se concentrera donc sur quelques
   commandes de base.

   Enfin, si le mode de fonctionnement en ligne de commande vous
   rebute, il existe une interface graphique appelee xxgdb au
   catalogue des logiciels portes.

   Cette section est destinee `a servir d'introduction `a
   l'utilisation du debogueur et ne couvre pas les questions
   specialisees comme le debogage du noyau.

     --------------------------------------------------------------

  5.2. Executer un programme sous le debogueur

   Il faudra que vous ayez compile le programme avec l'option -g pour
   tirer le meilleur parti de gdb. Cela fonctionnera sans cela, mais
   vous ne verrez que le nom de la fonction dans laquelle vous etes,
   au lieu du code source. Si vous avez un message du genre:

 ... (no debugging symbols found) ...

   au demarrage de gdb, vous saurez que le programme n'a pas ete
   compile avec l'option -g.

   A l'invite de gdb, tapez break main. Cela dira au debogueur
   d'executer le code preliminaire de mise en oeuvre dans le
   programme et de s'arreter au debut de votre programme. Tapez
   maintenant run pour lancer le programme - il commencera au debut
   du code preliminaire et sera interrompu par le debogueur sur
   l'appel de main(). (Si vous vous etiez jamais demande d'ou la
   fonction main() etait appelee, vous le savez maintenant!).

   Vous pouvez maintenant executer le programme une ligne `a la fois,
   en appuyant sur n. Si vous arrivez sur un appel de fonction, vous
   pouvez passer dans la fonction en appuyant sur s. Une fois dans la
   fonction, vous pouvez terminer son execution et en sortir en
   tapant f. Vous pouvez aussi utiliser up et down pour jeter un coup
   d'oeil au code appelant.

   Voici un exemple simple de la maniere de diagnostiquer une erreur
   dans un programme avec gdb. Voici notre programme
   (intentionnellement faux):

 #include <stdio.h>

 int bazz(int un_entier);

 main() {
       int i;

       printf("C'est mon programme\n");
       bazz(i);
       return 0;
 }

 int bazz(int un_entier) {
       printf("Vous m'avez donne %d\n", un_entier);
       return un_entier;
 }
        

   Ce programme affecte `a i la valeur 5 et la passe `a la fonction
   bazz() qui affiche la valeur que nous lui donnons en parametre.

   Quand nous compilons et executons le programme, nous obtenons:

 % cc -g -o temp temp.c
 % ./temp
 C'est mon programme
 Vous m'avez donne 4231

   Ce n'est pas ce `a quoi nous nous attendions! C'est le moment
   d'aller voir ce qui ce passe!

 % gdb temp
 GDB is free software and you are welcome to distribute copies of it
  under certain conditions; type "show copying" to see the conditions.
 There is absolutely no warranty for GDB; type "show warranty" for details.
 GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
 (gdb) break main                                Executer le code d'initialisation
 Breakpoint 1 at 0x160f: file temp.c, line 9.    gdb met un pont d'arret `a l'appel de main()
 (gdb) run                                       Executer jusqu'`a main()
 Starting program: /home/james/tmp/temp          Le programme demarre

 Breakpoint 1, main () at temp.c:9               gdb s'arrete `a main()
 (gdb) n                                         Aller `a la ligne suivante
 C'est mon programme                             Le programme imprime
 (gdb) s                                         Aller dans bazz()
 bazz (un_entier=4231) at temp.c:17              gdb affiche la position dans la pile d'appel
 (gdb)

   Une minute! Comment un_entier peut-il valoir 4231? Ne l'avons-nous
   pas initialise `a 5 dans main()? Revenons `a main() et jetons un
   oeil.

 (gdb) up                                        Remonter d'un cran dans la pile d'appel
 #1  0x1625 in main () at temp.c:11              gdb affiche la position dans la pile d'appel
 (gdb) p i                                       Afficher la valeur de i
 $1 = 4231                                       gdb affiche 4231

   Et oui! Si nous regardons le code, nous avons oublie d'initialiser
   i. Nous voulions mettre:

 ...
 main() {
       int i;

       i = 5;
       printf("C'est mon programme\n");
 ...
      

   mais nous avons oublie la ligne i=5;. Comme nous n'avons pas
   initialise i, il prend la valeur qui se trouve `a cet endroit de
   la memoire quand le programme s'execute, dans notre cas, il s'est
   trouve que c'etait 4231.

     Note : gdb affiche l'endroit ou nous nous trouvons dans la pile
     d'appel, chaque fois que nous entrons ou sortons d'une fonction,
     meme si nous utilisons up et down pour nous deplacer dans la
     pile. Cela nous donne le nom de la fonction et les valeurs de
     ses parametres, ce qui nous aide `a reperer ou nous sommes et ce
     qu'il se passe. (La pile d'appel est une zone de memoire ou le
     programme enregistre les informations sur les parametres passes
     aux fonctions et ou aller quand il ressort d'un fonction
     appelee.)

     --------------------------------------------------------------

  5.3. Examiner un fichier ``core''

   Un fichier ``core'' est essentiellement un fichier qui contient
   l'etat complet du programme au moment ou il s'est ``plante''. Au
   ``bon vieux temps'', les programmeurs devaient imprimer le contenu
   en hexadecimal des fichiers ``core'' et transpirer sur des manuels
   de code machine, mais la vie est aujourd'hui un peu plus facile.
   Au passage, sous FreeBSD et les autres systemes 4.4BSD, un fichier
   ``core'' s'appelle nom_du_programme.core, et non core tout court,
   de fac,on `a ce que l'on sache `a quel programme il correspond.

   Pour examiner un fichier ``core'', lancez gdb comme d'habitude. Au
   lieu de taper break ou run, tapez:

 (gdb) core nom_du_programme.core

   Si vous n'etes pas dans le meme repertoire que le fichier
   ``core'', vous devrez d'abord faire dir
   /ou/se/trouve/le/fichier/core.

   Vous devriez voir quelque chose comme:

 % gdb a.out
 GDB is free software and you are welcome to distribute copies of it
  under certain conditions; type "show copying" to see the conditions.
 There is absolutely no warranty for GDB; type "show warranty" for details.
 GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
 (gdb) core a.out.core
 Core was generated by `a.out'.
 Program terminated with signal 11, Segmentation fault.
 Cannot access memory at address 0x7020796d.
 #0  0x164a in bazz (un_entier=0x5) at temp.c:17
 (gdb)

   Dans ce cas, le programme s'appelait a.out, le fichier ``core''
   s'appelle donc a.out.core. Nous constatons que le programme s'est
   termine en erreur `a cause d'une tentative d'acces `a une zone de
   memoire qui n'etait pas accessible dans une fonction appele bazz.

   Il est parfois utile de pouvoir savoir comment une fonction a ete
   appelee, parce que le probleme peut s'etre produit bien au-dessus
   dans la pile d'appel dans un programme complexe. La commande bt
   dit `a gdb d'imprimer en remontant la pile d'appel:

 (gdb) bt
 #0  0x164a in bazz (un_entier=0x5) at temp.c:17
 #1  0xefbfd888 in end ()
 #2  0x162c in main () at temp.c:11
 (gdb)

   La fonction end() est appelee quand un programme echoue; dans le
   cas present, la fonction bazz() a ete appelee par main().

     --------------------------------------------------------------

  5.4. Prendre le controle d'un programme en cours d'execution

   Une des possibilites les plus interessantes de gdb est qu'il peut
   se rattacher `a un programme en cours d'execution. Il faut bien
   sur que vous ayez les autorisations suffisantes pour le faire. Le
   cas d'un programme qui ``fourche'' - fork - est un probleme
   classique, lorsque vous voulez suivre le deroulement du processus
   fils, alors que le debogueur ne vous permet que de tracer le
   processus pere.

   Vous lancez alors un autre gdb, utilisez ps pour connaitre
   l'IDentifiant de processus du fils, puis faites:

 (gdb) attach pid

   sous gdb, et deboguez alors comme d'habitude.

   ``Tout cela est bien beau'', vous dites vous peut-etre, ``mais le
   temps que j'ai fait tout c,a, le processus fils aura dej`a fait un
   bon bout de chemin''. Rien `a craindre, aimable lecteur, voici ce
   qu'il faut faire (emprunte aux pages ``info'' de gdb):

 ...
 if ((pid = fork()) < 0)         /* _Toujours_ effectuer se controle */
       error();
 else if (pid == 0) {            /* C'est le processus fils */
       int PauseMode = 1;

       while (PauseMode)
             sleep(10);          /* Attendre que quelqu'un se rattache `a nous */
       ...
 } else {                        /* parent */
       ...

   Il n'y a plus qu'`a se rattacher au fils, positionner PauseMode `a
   0, et attendre que l'appel de sleep() nous rende la main!

     --------------------------------------------------------------

6. Utiliser Emacs comme environnement de developpement

  6.1. Emacs

   Les systemes Unix ne s'accompagnent malheureusement pas du type
   d'environnement de developpement integre du genre ``tout ce que
   vous avez toujours voulu et encore beaucoup plus en un seul
   monstrueux paquetage'' dont disposent d'autres systemes[7]. Il est
   cependant possible de mettre au point votre propre environnement.
   Il ne sera peut-etre pas aussi esthetique et il ne sera peut-etre
   pas aussi integre, mais vous pourrez le configurer comme vous le
   voulez. Et il est gratuit. En plus, vous en avez les sources.

   Emacs est la cle de tout. Il y a bien des gens qui le decrient,
   mais nombreux sont ceux qui l'aiment. Si vous etes des premiers,
   j'ai peur que cette section n'ait que peu d'interet pour vous. Il
   vous faudra aussi pas mal de memoire pour l'utiliser. Je conseille
   8Mo en mode texte et 16Mo sous X comme strict minimum pour avoir
   des temps de reponse raisonnables.

   Emacs est essentiellement un editeur extremement configurable - il
   a de fait ete configure au point de ressembler plus `a un systeme
   d'exploitation qu'`a un editeur! De nombreux developpeurs et
   administrateurs systeme passent le plus clair de leur temps `a
   travailler sous Emacs, le quittant seulement pour se deconnecter.

   Il est impossible de meme resumer ici tout ce qu'Emacs est capable
   de faire, mais voici quelques fonctionnalites qui interessent les
   developpeurs:

     * Editeur tres puissant qui permet et de rechercher et remplacer
       des chaines de caracteres et d'utiliser pour le faire des
       expressions regulieres (motifs), d'aller au debut ou `a la fin
       de blocs syntaxiques, etc, etc.

     * Menus deroulants et aide en ligne.

     * Mise en valeur et indentation en fonction de la syntaxe du
       langage utilise.

     * Completement configurable.

     * Vous pouvez compiler et deboguer des programmes depuis Emacs.

     * En cas d'erreur `a la compilation, vous pouvez aller
       directement `a la ligne qui en est la cause.

     * Interface ergonomique au programme info qui sert `a lire la
       documentation hypertexte GNU, dont celle d'Emacs lui-meme.

     * Interface conviviale pour gdb, qui vous permet de visualiser
       le code source en meme temps que vous executez pas `a pas le
       programme.

     * Vous pouvez lire les ``news'' Usenet et votre courrier
       electronique pendant que votre programme compile.

   Et sans aucun doute bien d'autres choses qui m'ont echappees.

   Emacs peut etre installe sous FreeBSD sous forme de logiciel
   porte.

   Une fois qu'il est installe, lancez-le et tapez C-h t - ce qui
   signifie maintenir enfoncee la touche Ctrl, taper h, relacher la
   touche Ctrl, et appuyer ensuite sur t -  pour lire le guide
   d'Emacs (Vous pouvez aussi utiliser la souris pour selectionner
   Emacs Tutorial - ``Guide Emacs'' - depuis le menu
   Help - ``Aide'').

   Bien qu'Emacs ait des menus, il vaut la peine d'apprendre `a
   utiliser les raccourcis claviers, parce qu'il est bien plus rapide
   quand vous editez quelque chose d'appuyer sur deux ou trois
   touches que de courir apres la souris et cliquer ensuite au bon
   endroit. Si, par ailleurs, vous discutez avec des utilisateurs
   experimentes d'Emacs, vous vous apercevrez qu'ils utilisent assez
   couramment des expressions comme ``M-x replace-s RET foo RET bar
   RET'', il peut donc servir de comprendre ce qu'ils veulent dire.
   Et de toute fac,on, Emacs a bien plus de fonctions utiles qu'il ne
   peut en tenir sur une barre de menus.

   Il est heureusement assez facile de decouvrir les raccourcis
   claviers, ils sont affiches dans les menus. Je vous conseille
   d'utiliser les menus pour, par exemple, ouvrir un fichier jusqu'`a
   ce que vous compreniez comment cela marche et ayez suffisamment
   confiance en vous, puis d'essayer C-x C-f. Une fois que cela vous
   convient, passez `a une autre des commandes des menus.

   Si vous ne vous rappelez pas ce que fait une combinaison donnee de
   touches, choisissez Describe Key - ``Description d'une
   touche'' - dans le menu Help - ``Aide'' - et tapez cette
   combinaison - Emacs vous dira ce qu'elle fait. Vous pouvez aussi
   utiliser le choix Command Apropos - ``A propos d'une
   commande'' - pour connaitre toutes les commandes comportant un mot
   donne et les touches qui leur correspondent.

   Au fait, l'expression plus haut signifie: enfoncer la touche Meta,
   appuyer sur x, relacher la touche Meta, taper replace-s
   (abreviation de replace-string - ``remplacer une chaine de
   caracteres'' - une autre caracteristique d'Emacs est de vous
   permettre d'abreger les commandes), appuyer sur Entree, taper foo
   (la chaine que vous voulez remplacer), appuyer sur Entree, taper
   bar (la chaine avec laquelle vous voulez remplacer foo) et appuyer
   encore sur Entree. Emacs effectuera alors l'operation de recherche
   et remplacement que vous venez de demander.

   Si vous vous demandez ce qu'est la touche Meta, c'est une touche
   speciale qu'ont beaucoup de stations Unix. Malheureusement, les
   PCs n'en ont pas, c'est habituellement la touche Alt qui est
   utilisee (ou si vous n'avez pas de chance, la touche Echap).

   Oh, et pour sortir d'Emacs, tapez C-x C-c (Ce qui signifie:
   enfoncer la touche Ctrl, appuyer sur c, appuyer sur x et relacher
   la touche Ctrl). S'il y a des fichiers ouverts que vous n'avez pas
   sauvegardes, Emacs vous demandera si vous voulez les sauvegarder.
   (Oubliez que la documentation dit que la methode habituelle pour
   quitter Emacs est d'utiliser C-z - cela laisse Emacs actif en
   tache de fond et n'est reellement utile que si vous etes sur un
   systeme qui ne gere pas de terminaux virtuels).

     --------------------------------------------------------------

  6.2. Configurer Emacs

   Emacs fait des choses admirables; certaines fonctionnalites sont
   incorporees, d'autres doivent etre configurees.

   Au lieu d'utiliser un langage de macros-instructions
   proprietaires, Emacs se sert d'une version de Lisp specialement
   adaptee aux editeurs, connue sous le nom de Emacs Lisp. Ce peut
   etre tres utile si vous voulez aller plus loin et apprendre
   ensuite par exemple Common Lisp, parce qu'il est considerablement
   plus leger que Common Lisp (quoique qu'encore assez imposant!).

   La meilleure fac,on d'apprendre Emacs Lisp est de telecharger le
   Guide Emacs Lisp.

   Il n'y a cependant pas besoin de connaitre quoique ce soit `a Lisp
   pour commencer `a configurer Emacs, parce que j'ai inclu un
   fichier .emacs d'exemple, qui devrait suffire au debut. Copiez-le
   simplement dans votre repertoire utilisateur et relancez Emacs,
   s'il s'execute dej`a; il lira les commandes du fichier et (je
   l'espere) vous fournira une configuration de base utile.

     --------------------------------------------------------------

  6.3. Un exemple de fichier .emacs

   Il contient malheureusement beaucoup trop de choses pour tout
   expliquer en details; il y a cependant un ou deux points
   interessants `a mentionner.

     * Tout ce qui commence par un ; est en commentaire et est ignore
       par Emacs.

     * La premiere ligne, -*- Emacs-Lisp -*- permet d'editer le
       fichier .emacs lui-meme sous Emacs et de profiter de toutes
       les fonctionnalitees liees `a l'edition de code Emacs Lisp.
       Emacs tente habituellement de deviner le type de fichier en
       fonction de son nom, mais risque de ne pas y arriver pour le
       fichier .emacs.

     * La touche Tab est utilisee pour l'indentation dans certains
       modes, de sorte que si vous appuyez sur cette touche cela
       indente la ligne de code courante. Si vous voulez mettre un
       caractere tabulation dans votre texte, enfoncer la touche Ctrl
       en meme temps que vous appuyez sur Tab.

     * Ce fichier permet le mise en valeur syntaxique de code C, C++,
       Perl, Lisp et Scheme, en determinant le langage d'apres le nom
       du fichier edite.

     * Emacs a dej`a une fonction predefinie appelee
       next-error - ``erreur suivante''. Dans la fenetre de resultats
       d'une compilation, cela vous permet d'aller d'une erreur `a la
       suivante avec M-n; nous definissons la fonction complementaire
       previous-error - ``erreur precedente'', qui vous permet de
       retourner `a l'erreur precedente avec M-p. Le plus sympathique
       est que C-c C-c ouvrira le fichier source ou l'erreur s'est
       produite et ira `a la ligne concernee.

     * Nous activons la possibilite qu'a Emacs d'agir comme serveur,
       de fac,on `a ce que si vous travaillez hors d'Emacs et voulez
       editer un fichier, il vous suffise de taper:

 % emacsclient nom_du_fichier

       pour pouvoir ensuite le modifier avec Emacs![8].

   Exemple 1. Un exemple de fichier .emacs

 ;; -*-Emacs-Lisp-*-

 ;; Ce fichier est conc,u pour etre relu; la variable
 ;; first-time est utilisee pour eviter les problemes
 ;; que cela pourra poser.
 (defvar first-time t
   "Indicateur signifiant que le fichier .emacs est lu pour la premiere fois")

 ;; Meta
 (global-set-key "\M- " 'set-mark-command)
 (global-set-key "\M-\C-h" 'backward-kill-word)
 (global-set-key "\M-\C-r" 'query-replace)
 (global-set-key "\M-r" 'replace-string)
 (global-set-key "\M-g" 'goto-line)
 (global-set-key "\M-h" 'help-command)

 ;; Touches fonction
 (global-set-key [f1] 'manual-entry)
 (global-set-key [f2] 'info)
 (global-set-key [f3] 'repeat-complex-command)
 (global-set-key [f4] 'advertised-undo)
 (global-set-key [f5] 'eval-current-buffer)
 (global-set-key [f6] 'buffer-menu)
 (global-set-key [f7] 'other-window)
 (global-set-key [f8] 'find-file)
 (global-set-key [f9] 'save-buffer)
 (global-set-key [f10] 'next-error)
 (global-set-key [f11] 'compile)
 (global-set-key [f12] 'grep)
 (global-set-key [C-f1] 'compile)
 (global-set-key [C-f2] 'grep)
 (global-set-key [C-f3] 'next-error)
 (global-set-key [C-f4] 'previous-error)
 (global-set-key [C-f5] 'display-faces)
 (global-set-key [C-f8] 'dired)
 (global-set-key [C-f10] 'kill-compilation)

 ;; Touches curseur
 (global-set-key [up] "\C-p")
 (global-set-key [down] "\C-n")
 (global-set-key [left] "\C-b")
 (global-set-key [right] "\C-f")
 (global-set-key [home] "\C-a")
 (global-set-key [end] "\C-e")
 (global-set-key [prior] "\M-v")
 (global-set-key [next] "\C-v")
 (global-set-key [C-up] "\M-\C-b")
 (global-set-key [C-down] "\M-\C-f")
 (global-set-key [C-left] "\M-b")
 (global-set-key [C-right] "\M-f")
 (global-set-key [C-home] "\M-<")
 (global-set-key [C-end] "\M->")
 (global-set-key [C-prior] "\M-<")
 (global-set-key [C-next] "\M->")

 ;; Souris
 (global-set-key [mouse-3] 'imenu)

 ;; Divers
 (global-set-key [C-tab] "\C-q\t")       ; Ctrl tab = caractere tabulation.
 (setq backup-by-copying-when-mismatch t)

 ;; 'y' ou <CR> equivaut `a yes, 'n' `a no.
 (fset 'yes-or-no-p 'y-or-n-p)
     (define-key query-replace-map [return] 'act)
     (define-key query-replace-map [?\C-m] 'act)

 ;; Paquetages `a charger
 (require 'desktop)
 (require 'tar-mode)

 ;; Mode diff evolue
 (autoload 'ediff-buffers "ediff" "Interface Emacs intelligente pour diff" t)
 (autoload 'ediff-files "ediff" "Interface Emacs intelligente pour diff" t)
 (autoload 'ediff-files-remote "ediff"
   "Interface Emacs intelligente pour diff")

 (if first-time
     (setq auto-mode-alist
           (append '(("\\.cpp$" . c++-mode)
                      ("\\.hpp$" . c++-mode)
                      ("\\.lsp$" . lisp-mode)
                      ("\\.scm$" . scheme-mode)
                      ("\\.pl$" . perl-mode)
                      ) auto-mode-alist)))

 ;; Mise en valeur syntaxique automatique
 (defvar font-lock-auto-mode-list
   (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'lisp-mode 'perl-mode 'scheme-mode)
   "Listes des modes `a demarrer toujours avec mise en valeur")

 (defvar font-lock-mode-keyword-alist
   '((c++-c-mode . c-font-lock-keywords)
     (perl-mode . perl-font-lock-keywords))
   "Associations entre modes et mots-cles")

 (defun font-lock-auto-mode-select ()
   "Selectionne automatiquement type de mise en valeur si le major mode courant est dans font-lock-auto-mode-list"
   (if (memq major-mode font-lock-auto-mode-list)
       (progn
       (font-lock-mode t))
     )
   )

 (global-set-key [M-f1] 'font-lock-fontify-buffer)

 ;; Nouveau dabbrev
 ;(require 'new-dabbrev)
 (setq dabbrev-always-check-other-buffers t)
 (setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
 (add-hook 'emacs-lisp-mode-hook
           '(lambda ()
             (set (make-local-variable 'dabbrev-case-fold-search) nil)
             (set (make-local-variable 'dabbrev-case-replace) nil)))
 (add-hook 'c-mode-hook
           '(lambda ()
             (set (make-local-variable 'dabbrev-case-fold-search) nil)
             (set (make-local-variable 'dabbrev-case-replace) nil)))
 (add-hook 'text-mode-hook
           '(lambda ()
             (set (make-local-variable 'dabbrev-case-fold-search) t)
             (set (make-local-variable 'dabbrev-case-replace) t)))

 ;; Mode C++ et C...
 (defun my-c++-mode-hook ()
   (setq tab-width 4)
   (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
   (define-key c++-mode-map "\C-ce" 'c-comment-edit)
   (setq c++-auto-hungry-initial-state 'none)
   (setq c++-delete-function 'backward-delete-char)
   (setq c++-tab-always-indent t)
   (setq c-indent-level 4)
   (setq c-continued-statement-offset 4)
   (setq c++-empty-arglist-indent 4))

 (defun my-c-mode-hook ()
   (setq tab-width 4)
   (define-key c-mode-map "\C-m" 'reindent-then-newline-and-indent)
   (define-key c-mode-map "\C-ce" 'c-comment-edit)
   (setq c-auto-hungry-initial-state 'none)
   (setq c-delete-function 'backward-delete-char)
   (setq c-tab-always-indent t)
 ;; indentation style BSD
   (setq c-indent-level 4)
   (setq c-continued-statement-offset 4)
   (setq c-brace-offset -4)
   (setq c-argdecl-indent 0)
   (setq c-label-offset -4))

 ;; Mode Perl...
 (defun my-perl-mode-hook ()
   (setq tab-width 4)
   (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
   (setq perl-indent-level 4)
   (setq perl-continued-statement-offset 4))

 ;; Mode Scheme...
 (defun my-scheme-mode-hook ()
   (define-key scheme-mode-map "\C-m" 'reindent-then-newline-and-indent))

 ;; Mode Emacs-Lisp...
 (defun my-lisp-mode-hook ()
   (define-key lisp-mode-map "\C-m" 'reindent-then-newline-and-indent)
   (define-key lisp-mode-map "\C-i" 'lisp-indent-line)
   (define-key lisp-mode-map "\C-j" 'eval-print-last-sexp))

 ;; Ajouts des precedents
 (add-hook 'c++-mode-hook 'my-c++-mode-hook)
 (add-hook 'c-mode-hook 'my-c-mode-hook)
 (add-hook 'scheme-mode-hook 'my-scheme-mode-hook)
 (add-hook 'emacs-lisp-mode-hook 'my-lisp-mode-hook)
 (add-hook 'lisp-mode-hook 'my-lisp-mode-hook)
 (add-hook 'perl-mode-hook 'my-perl-mode-hook)

 ;; L'inverse de next-error
 (defun previous-error (n)
   "Aller `a l'erreur de compilation precedente et au code correspondant."
   (interactive "p")
   (next-error (- n)))

 ;; Divers...
 (transient-mark-mode 1)
 (setq mark-even-if-inactive t)
 (setq visible-bell nil)
 (setq next-line-add-newlines nil)
 (setq compile-command "make")
 (setq suggest-key-bindings nil)
 (put 'eval-expression 'disabled nil)
 (put 'narrow-to-region 'disabled nil)
 (put 'set-goal-column 'disabled nil)

 ;; Recherche dans les archives Elisp
 (autoload 'format-lisp-code-directory "lispdir" nil t)
 (autoload 'lisp-dir-apropos "lispdir" nil t)
 (autoload 'lisp-dir-retrieve "lispdir" nil t)
 (autoload 'lisp-dir-verify "lispdir" nil t)

 ;; Mise en valeur syntaxique
 (defun my-make-face (face colour &optional bold)
   "Creer une apparence pour une couleur, eventuellement en gras"
   (make-face face)
   (copy-face 'default face)
   (set-face-foreground face colour)
   (if bold (make-face-bold face))
   )

 (if (eq window-system 'x)
     (progn
       (my-make-face 'blue "blue")
       (my-make-face 'red "red")
       (my-make-face 'green "dark green")
       (setq font-lock-comment-face 'blue)
       (setq font-lock-string-face 'bold)
       (setq font-lock-type-face 'bold)
       (setq font-lock-keyword-face 'bold)
       (setq font-lock-function-name-face 'red)
       (setq font-lock-doc-string-face 'green)
       (add-hook 'find-file-hooks 'font-lock-auto-mode-select)

       (setq baud-rate 1000000)
       (global-set-key "\C-cmm" 'menu-bar-mode)
       (global-set-key "\C-cms" 'scroll-bar-mode)
       (global-set-key [backspace] 'backward-delete-char)
                                        ;      (global-set-key [delete] 'delete-char)
       (standard-display-european t)
       (load-library "iso-transl")))

 ;; X11 ou PC ecrivant directement `a l'ecran
 (if window-system
     (progn
       ;;      (global-set-key [M-f1] 'hilit-repaint-command)
       ;;      (global-set-key [M-f2] [?\C-u M-f1])
       (setq hilit-mode-enable-list 
              '(not text-mode c-mode c++-mode emacs-lisp-mode lisp-mode
                    scheme-mode)
              hilit-auto-highlight nil
              hilit-auto-rehighlight 'visible
              hilit-inhibit-hooks nil
              hilit-inhibit-rebinding t)
       (require 'hilit19)
       (require 'paren))
   (setq baud-rate 2400)                 ; Pour les connections serie lentes
   )

 ;; Terminal type TTY
 (if (and (not window-system)
          (not (equal system-type 'ms-dos)))
     (progn
       (if first-time
           (progn
             (keyboard-translate ?\C-h ?\C-?)
             (keyboard-translate ?\C-? ?\C-h)))))

 ;; Sous UNIX
 (if (not (equal system-type 'ms-dos))
     (progn
       (if first-time
           (server-start))))

 ;; Ajouter ici toute modification d'apparence des caracteres
 (add-hook 'term-setup-hook 'my-term-setup-hook)
 (defun my-term-setup-hook ()
   (if (eq window-system 'pc)
       (progn
 ;;      (set-face-background 'default "red")
         )))

 ;; Restaurer le "bureau" - le faire le plus tard possible
 (if first-time
     (progn
       (desktop-load-default)
       (desktop-read)))

 ;; Indique que le fichier a ete lu au moins une fois
 (setq first-time nil)

 ;; Plus besoin de deboguer quoi que ce soit maintenant.
 (setq debug-on-error nil)

 ;; C'est tout
 (message "OK, %s%s" (user-login-name) ".")

     --------------------------------------------------------------

  6.4. Permettre `a Emacs de comprendre de nouveaux langages

   Bon, tout cela est tres bien si vous ne voulez programmer qu'avec
   les langages dej`a introduits dans le fichier .emacs (C, C++,
   Perl, Lisp et Scheme), mais que se passe-t-il quand un nouveau
   langage appele ``whizbang'' fait son apparition, avec plein de
   nouvelles fonctionnalites attrayantes?

   La premiere chose `a faire est de regarder si whizbang
   s'accompagne de fichiers de configuration d'Emacs pour ce langage.
   Ces fichiers ont generalement comme extension .el, raccourci pour
   ``Emacs Lisp''. Par exemple, si whizbang est un logiciel porte
   pour FreeBSD, ces fichiers peuvent etre reperes par:

 % find /usr/ports/lang/whizbang -name "*.el" -print

   et il faut les installer en le copiant dans le repertoire du
   ``site Lisp'' d'Emacs. Sous FreeBSD 2.1.0-RELEASE, c'est le
   repertoire /usr/local/share/emacs/site-lisp.

   Ainsi par exemple, si la commande precedente nous donnait:

 /usr/ports/lang/whizbang/work/misc/whizbang.el

   nous le copierions alors comme suit:

 % cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp

   Decidons ensuite de l'extension que doivent avoir les fichiers
   source whizbang. Supposons, pour les besoins de l'exemple, qu'ils
   se terminent tous par .wiz. Il faut ajouter une entree `a notre
   fichier .emacs, pour etre sur qu'Emacs puisse utiliser les
   informations du fichier whizbang.el.

   Recherchons l'entree auto-mode-alist dans .emacs et ajoutons une
   ligne pour whizbang, par exemple:

 ...
 ("\\.lsp$" . lisp-mode)
 ("\\.wiz$" . whizbang-mode)
 ("\\.scm$" . scheme-mode)
 ...
        

   Cela signifie qu'Emacs passera automatiquement en whizbang-mode `a
   l'edition d'un fichier d'extension .wiz.

   Juste apres, il y a une entree font-lock-auto-mode-list. Ajoutez-y
   whizbang-mode comme ceci:

 ;; Auto font-lock-mode
 (defvar font-lock-auto-mode-list
   (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'whizbang-mode 'lisp-mode 'perl-mode 'scheme-mode)
   "Listes des modes `a demarrer toujours en font-lock-mode")
        

   Ce qui signifie qu'Emacs activera toujours le font-lock-mode
   (i.e., la mise en valeur syntaxique) `a l'edition d'un fichier
   .wiz.

   Cela suffit. S'il y a autre chose que vous voulez automatiser `a
   l'ouverture d'un fichier .wiz, vous pouvez ajouter un
   whizbang-mode hook (voyez mon my-scheme-mode-hook pour avoir un
   exemple simple qui ajoute un auto-indent - indentation
   automatique).

     --------------------------------------------------------------

7. A lire pour aller plus loin

     * Brian Harvey et Matthew Wright Simply Scheme MIT 1994. ISBN
       0-262-08226-8

     * Randall Schwartz Learning Perl O'Reilly 1993 ISBN
       1-56592-042-2

     * Patrick Henry Winston et Berthold Klaus Paul Horn Lisp (3rd
       Edition) Addison-Wesley 1989 ISBN 0-201-08319-1

     * Brian W. Kernighan et Rob Pike The Unix Programming
       Environment Prentice-Hall 1984 ISBN 0-13-937681-X

     * Brian W. Kernighan et Dennis M. Ritchie The C Programming
       Language (2nd Edition) Prentice-Hall 1988 ISBN 0-13-110362-8

     * Bjarne Stroustrup The C++ Programming Language Addison-Wesley
       1991 ISBN 0-201-53992-6

     * W. Richard Stevens Advanced Programming in the Unix
       Environment Addison-Wesley 1992 ISBN 0-201-56317-7

     * W. Richard Stevens Unix Network Programming Prentice-Hall 1990
       ISBN 0-13-949876-1

  Notes

   [1] Dans le cas contraire, si vous l'executez sur la ligne de      
       commande, il peut eventuellement planter - ``core dump''.      
   [2] Pour etre rigoureusement exact, cc convertit le code source en 
       un P-code qui lui est propre, et ne depend pas de la machine,  
       et non en assembleur `a ce stade.                              
   [3] Au cas ou vous ne le sauriez pas, un tri par arbre binaire est 
       une maniere efficace d'ordonner des donnees, ce qui n'est pas  
       le cas du tri `a bulles.                                       
   [4] Les raisons de cela se sont perdues dans les brumes de         
       l'histoire.                                                    
   [5] Remarquez que nous n'avons pas utilise l'indicateur -o pour    
       preciser le nom de l'executable, celui-ci s'appellera donc     
       a.out. Generer une version debogable appelee foobar est laisse 
       `a titre d'exercice aux soins du lecteur!                      
   [6] Ils n'utilisent pas la variante MAKEFILE parce que les noms en 
       majuscules servent souvent `a designer les fichiers de         
       documentation comme README.                                    
   [7] Au moins, pas `a moins que vous ne soyez pret `a les payer une 
       somme astronomique.                                            
   [8] De nombreux utilisateurs d'Emacs affectent `a leur variable    
       d'environnement EDITOR la valeur emacsclient de fac,on `a ce   
       que ce soit ce qui se produise chaque fois qu'ils ont besoin   
       d'editer un fichier.                                           

     --------------------------------------------------------------

        Ce document, ainsi que d'autres peut etre telecharge sur
                   ftp.FreeBSD.org/pub/FreeBSD/doc/.

Pour toutes questions `a propos de FreeBSD, lisez la documentation avant
                 de contacter <questions@FreeBSD.org>.
Pour les questions sur cette documentation, contactez <doc@FreeBSD.org>.
