C'est un dimanche pluvieux. Avachi devant votre écran de TV, qui ne fait que de couper vos pubs préférées par des séries débiles et ricaines, vous vous dites :
Tiens, si aujourd'hui je faisais un super programme méga-génial sur mon Miga, avec tout plein de couleurs, de fenêtres et de gadgets et de ..." Mais non! Ca vous revient maintenant: vous ne savez pas programmer l'Amiga. Horreur, malheur!
Non car tel le Zorro moyen, me voici accourir pour vous apporter un peu de lumière dans ce monde de brutes, où Billou a fermé la fenêtre...
ATTENTION: Certains des listings de cet article peuvent planter. C'est pourquoi sauvegardez ce qui doit l'être avant de les exécuter! ! Bon, c'est pour les besoins de l'initiation (elle a bon dos !) et uniquement dans cet article, les suivants ne poseront plus de problème... enfin normalement ;-D
Le C a toujours été le langage de prédilection sur Amiga, c'est pourquoi un large choix de compilateurs s'offre à nous, qu'ils soient commerciaux ou dans le DP. Evidemment, chaque programmeur dira que le compilo qu'il utilise est le meilleur, cependant, pour le néophyte qui n'est pas encore équipé, voici ceux que je préconise. Ce sont simplement ceux installés sur mes Amiga et dont je parlerai souvent dans mes articles...
Vous avez un Amiga accéléré
(68020 ou plus), beaucoup de mémoire (au moins 8 Mo,
10 de préférence),
de la place sur votre disque dur ou un CD-ROM et vous savez ce qu'est un compilateur C :
GCC est celui qu'il vous faut !
Pour le même prix, c'est-à-dire rien, il est
gratuit, vous aurez droit au C, C++, Objective C, Ada
et même Fortran.
Conçu à l'origine pour Unix, vous le retrouverez comme compilateur natif des OS libres comme Linux,
NetBSD, FreeBSD, ... mais il existe aussi des portages sur des Unix commerciaux (HP-UX,
AIX, Solaris, Digital Unix, ... en fait, je ne crois pas qu'il existe un Unix récent sur lequel il n'ait pas été porté!). On le retrouve aussi sur Vax/VMS, Mac,
ST et même sur les Prehistoric Computers !
Outre le fait qu'il soit toujours plaisant d'utiliser le même compilo d'une machine à l'autre, je lui trouve de nombreux avantages dont :
Allez, première astuce : par défaut, il inclut les informations de débugage dans les exécutables qu'il génère, l'option
'-s
' ajoutée dans sa ligne de commande diminuera la taille de vos programmes de plusieurs dizaines de Ko. De même, vous pouvez virer sans problème les Hunks "Debug" et "Symbols" de ses propres exécutables ce qui, en plus de libérer de la place sur le disque, accélérera les compilations, le chargement en mémoire...
Ce fut mon premier compilo C sur Amiga. On préférera aller le chercher sur Aminet car la dernière archive en date contient la version professionnelle avec TOUTES les sources ! Elle comporte une GUI très bien faite et une interface AREXX complète.
Relisez mes articles dans les
anciens AmigaNews (qui sont aussi présents sur ce site)
et vous verrez qu'on peut même l'utiliser sur un simple Amiga
68000 muni d'1 Mo de RAM et sans disque dur !
Comme avantage supplémentaire, la doc est très bien foutue et comporte une initiation pour débutant, accompagnée d'exemples pour la création d'une librairie, d'un device.
Il est aussi très bien intégré au système et gère pour vous l'ouverture automatique des librairies, les arguments du WorkBench... Bon, il contient aussi quelques bugs et l'exécutable n'est pas vraiment optimisé.
Ce vieux compilo, bien que plus vendu depuis un bail, continue à être supporté par ses développeurs qui fournissent régulièrement des patchs. Il possède un avantage indéniable : Commodore l'a utilisé pour développer le système, on trouve donc beaucoup d'exemples de programmation l'utilisant.
Le voici, le voilà, la hantise de tous les débutants : le fameux Hello World !
En voici le source:
|
On compile ici avec GCC, et on l'exécute depuis un shell : "Ça marche !"
Génial, on a réussi à compiler un programme tout con, que même un PC sait faire! Et en plus ça fonctionne ...
"Décidément, on se moque vraiment de notre gueule !! N'importe quoi !" allez vous dire !
Je répond : Que nénni
! Exécutez le maintenant depuis le Workbench ... juste pour voir.
3 Possibilités:
Explication : Comme vous le savez, le printf() va afficher ses arguments sur le flux de sortie standard, le très connu 'stdout'. Le problème est que si le programme est lancé depuis le WorkBench, ce stdout n'existe pas (ben ouais, on les affiche où ces messages?), d'où le plantage dans le cas de l'Aztec. Le SAS et GCC ont contourné le problème en créant une fenêtre de sortie : Bon c'est une bonne idée mais ça explique pas pourquoi un simple
|
Regardez bien la doc de votre compilo, elle vous indiquera comment le supprimer et diminuer ainsi la taille de votre exécutable.
Dice, lui, a créé deux entrées dans le programme : le classique main() lorsqu'il s'exécute depuis un shell ou un wbmain()lorsque c'est depuis le Workbench. Si l'utilisateur n'en fournit pas une, il utilise celle par défaut qui ne fait que terminer le programme... C'est elle qui s'exécute dans notre cas.
Moralité : Dans un programme devant s'exécuter depuis le Workbench, de printf(), puts() et dérivés tu n'utiliseras ...
Après avoir fait ce que tout le monde sait faire, innovons et créons notre propre générateur de... Guru. La fonction DisplayAlert() permet en effet de générer un écran noir, avec un cadre rouge ou jaune (à partir du KS 2.0 uniquement), avec le ou les messages de notre choix.
Voici le listing tant attendu :
|
Evidemment, on ne va pas programmer comme des porcs (on n'est pas chez M$),les deux premières lignes permettent d'inclure le prototype de DisplayAlert() ainsi que les définitions associées. En particulier, notez bien le premier <exec/types.h>
, qui définit tous les types couramment utilisés par le système. Les autres includes sont classiques.
Le prototype de la fonction est le suivant :
BOOL DisplayAlert( unsigned long type, UBYTE *message, unsigned long hauteur );
avec
NUL
, c'est fini, sinon on retrouve une autre chaîne qui reprend la même structure.
Vous pouvez maintenant compiler le listing. Si une erreur de compilation s'affiche, l'explication arrive, sinon, lancez-le ... après avoir sauvegardé tout ce qu'il y avait à sauvegarder !
Il se peut que ça marche tel quel (!), mais vous avez plus de (mal)chance que ça se termine par le réveil du vrai Guru...
Comme vous le savez certainement, l'AmigaDos n'est pas un bloc monolithique, genre le fameux 'kernel' cher aux UNIX, mais est composé de plusieurs librairies partagées dont chacune a une fonction précise. Si ça plante, il faut regarder la compilation avec GCC pour en trouver la raison.
Tiens, manquerait-il quelque chose ?
DisplayAlert() est une fonction qui fait partie d'Intuition.librairie, et pour l'appeler, le compilo a besoin de savoir où se trouve cette librairie. Hé oui, contrairement à ce qui se passe avec les machines 8 bits, dans l'Amiga rien (ou presque),
n'est fixé à priori. A chaque boot de la machine, les librairies se placent où le système leur dit.
DisplayAlert() se trouve donc à
une adresse qui est relative à
IntuitionBase, que nous devons initialiser, sinon ...Guru.
Voici le nouveau listing, qui fonctionne lui!
|
La seule partie logiciel fixe dans le système est l'adresse d'exec, c'est-à-dire la librairie qui s'occupe du système (allocation mémoire, chargement des librairies, et autres ...).
Ben oui, on a beau être relatif à fond, il faut toujours garder une référence.
L'adresse où se trouve Exec est placée à l'adresse 4 de la mémoire et doit être stockée dans une variable nommée... SysBase (logique non?).
On peut ensuite ouvrir Intuition.
Apprenez-lui le caniveau
on doit rendre le système comme on l'a trouvé : Libérer la mémoire, fermer les écrans et les fenêtres... sont des choses auxquelles on pense.
N'oubliez pas de fermer aussi les librairies ouvertes!
C'est ici le rôle de la fonction fini() appelé par un atexit(). On est ainsi sûr que quoi qu'il se passe, elle sera appelée.
Notez que OpenLibrary(), outre le nom, demande aussi un entier, qui est le numéro minimum de version de la librairie. Si elle est antérieure, la fonction échoue en renvoyant un NULL. On verra l'utilité plus tard lorsque nous utiliserons des spécificités du 2.0 ou du 3.0. C'est aussi une des forces de l'Amiga par rapport à d'autres systêmes utilisant des librairies partagées : Ici l'AmigaOS nous impose d'avoir une compatibilité ascendante des versions des librairies. Ceux qui programment ou qui gèrent un parc sous windaube savent de quoi je veux parler : l'installation d'un nouveau programme entraine généralement l'écrasement de librairies systême et on met trois semaines à récupérer un truc un minimum stable ... BBBhhhhhaaaaaaa !!!!.
Avec l'Amiga, pas de problème : tout programme d'installation doit (devrait) verifier la version de la librairie.
0
, n'importe quelle version fonctionne et ça devrait même marcher avec un Workbench 1.0 !!!
On notera aussi dans ce listing le cas particulier d'exec. Nous ne l'avons pas ouverte, mais trouvée grâce à son adresse. Ne jamais tenter de la refermer, sinon ... bon vous connaissez la suite !
IInutile de préciser que ce programme ne fonctionne que depuis un Shell, vous l'aurez deviné tous seul. Non ? Bon, d'accord pour cette fois : Il y a un puts() qui utilise le stdout. En plus, mais vous ne pouviez pas le savoir, les arguments du Workbench ne sont pas traités de la même façon.
"Tout bon programmeur doit être un peu feignant !"
C'est chiant de devoir ouvrir nous-mêmes les librairies, non? Beaucoup de compilos permettent de les ouvrir et de les fermer automatiquement, sans intervention du programmeur.
-lauto
.Attention : c'est comme tout, en abuser se révèle dangereux, car à force, vous allez oublier de le faire. Et quand il s'agit d'une librairie rajoutée (genre req.librairie), le compilo ne saura pas comment se dépatouiller tout seul...
Bon, voilà, c'est fini pour aujourd'hui.
Grand merci à mes très courageux correcteurs :
Evidemment, comme ceci est le premier article de cette serie, il ne devrait pas y avoir de "Courriers des lecteurs". Voici cependant quelques questions qui m'ont été posées par mes (très) courageux correcteurs :
*((short *)buff) = 50;
est obscure.
buff a été déclaré comme un tableau de caractères, alors qu'il doit contenir en
premier un entier court (2 octets) la position en abcisse du premier caractère.
Ici nous souhaitons que ce soit à partir de la 50eme ligne.
La solution "crade" aurrait été d'initialiser les octets à la main, c'est été dire
avec le code suivant
buff[0] = 0; buff[1] = 50;
donc on met 0 dans l'octet de poid fort et 50 dans celui de poid faible, donc
0*256 + 50*1 = 50
Pour la solution la plus propre, celle employée ci-dessus, la première étape
est de faire croire au compilo, par un cast (short *)
que buff est un pointeur
sur un entier court. La ligne devient donc
*buff = 50;
qui se traduirait par
"L'entier court pointé par 'buff' prend la valeur 50".
On a la même construction, mais en plus sioux, avec
SysBase = *(struct ExecBase **)4; /* Recherche d'exec */
Ici le cast indique qu'a l'adresse 4 se trouve le pointeur sur un pointeur
(donc double indirection !) qui pointe sur une structure ExecBase ... Comme résultat, on a SysBase qui contient un pointeur sur la structure en question (ouf).
Sans entrer trop dans la téchnique, les fichiers exécutables sont découpés en
plusieurs partie appelés 'Hunks'. On y trouve entre autre celui du code, "Code
",
celui des variables initialisées, "Data
", des variables non initialisées, "BBS
",
et d'autres qui servent au relogement en mémoire (ceux qui font que les exécutables
puissent se placer n'importe où en mémoire). On trouve aussi les 2 qui nous
interresse ici :
Symbol
", comme sont nom l'indique, contient les informations qui
permettent un debuggueur, un assembleur, ... de faire la correspondance entre
les adresses où sont stockées les variables et les fonctions et leur nom.
Debug
" quant à lui contient des informations de débugguage, en
particulier la correspondance entre les codes 68000 et les lignes du sources.
Ca dépend de la version de GCC et la maniere dont il est configuré. Le mien
à la version 2.7.0 et se trouve sur le CD Fred Fish 10...
De toutes façons, il vaut mieux éviter de lancer l'exécution de programme
shell depuis le workbench, c'est beaucoup plus prudent !