|
|||||||||||||||||||||||||||||||||||||||||||||
|
Comme nous l'avions promis précédemment, nous allons maintenant réaliser et analyser un programme ARexx. Plusieurs concepts nouveaux d'ARexx y seront abordés, que nous présenterons dans le détail le moment venu. Le programme que nous proposons est une application d'ARexx en tant que langage de programmation (c'est-à-dire en laissant momentanément de côté ses qualités de "langage du multitâche"), ce qui est l'une de ses possibilités. Nous allons donc réaliser un programme qui extrait le répertoire d'un disque dur ou souple et le présente de façon plus agréable que celle du Workbench standard. Le programme est divisé en trois modules fonctionnels indépendants qui s'interfacent les uns avec les autres et permettent, pourvu que l'on respecte cet interfaçage, d'en modifier un sans avoir à réécrire les autres. Ces trois modules se chargent respectivement de la prise en compte de la demande de l'opérateur, de l'analyse du contenu du disque sélectionné et de la mise en forme des informations obtenues précédemment. Nous n'analyserons aujourd'hui que la partie "prise en compte de la demande de l'opérateur" ; le reste viendra après. Avertissement Nous avons cherché à utiliser le maximum de fonctions ARexx sans nous préoccuper d'une solution astucieuse. Ce qui signifie que nous ne soutiendrons pas de polémique sur le bien-fondé de telle ou telle méthode. Cependant et à titre d'exercice, il n'est pas interdit de réfléchir à d'autres solutions... Définition du module d'acquisition Ce module permet de déterminer le disque choisi par l'opérateur et d'acquérir certaines informations relatives à ce disque. Trois types d'opérateurs ont été envisagés : le vétéran, qui sait ce qu'il veut et ne se trompe pas dans l'appel ; l'indécis, qui ne sait pas ce qu'il veut : et le novice, qui se trompe dans sa demande. Pour éviter la typographie, les caractères du type guillemet (") ou deux points (:) ne sont pas obligatoirement demandés. L'interfaçage avec les autres modules est réalisé au moyen des variables suivantes :
Imaginons que ce programme ait été placé en RAM: avec le nom "Repertoire". Le disque en DF1: existe et se nomme "Disque Essais" (en deux mots pour la cause). Les commandes suivantes sont directement acceptées :
Les commandes suivantes provoquent une proposition de ce qui existe :
Enfin, certaines formes folkloriques sont corrigées : "DF1 :" ou encore "::". Dans ce domaine, il est difficile d'être exhaustif tant l'ingéniosité, éventuellement maladroite, est variée. Quant à l'ingéniosité maligne elle est carrément infinie ! Il faut donc se limiter aux cas les plus probables. Saisie du programme "Repertoire" Le listing source du programme est proposé ici ; les lignes ont été numérotées pour en faciliter l'analyse. Lors de la saisie du programme, il ne faudra bien entendu pas saisir les numéros de lignes. Certaines instructions sont suffisamment documentées dans le listing. D'autres nécessitent un complément. Ligne 3 Si l'invocation contient un paramètre, il est placé dans la variable Disque. Ligne 4 Comme la variable Disque va être traitée, on mémorise ce qui a été réellement tapé par l'opérateur. Ligne 5 ARexx permet d'émettre une commande vers l'hôte, ici le DOS. Il suffit d'informer ARexx par ADDRESS COMMAND et d'encadrer la commande par des apostrophes ('). Ici, on crée en RAM: un fichier nommé "liste" qui contiendra le résultat de la commande DOS Info. C'est un fichier texte. Ligne 6 ARexx ne touche pas directement un fichier. On crée un fichier tampon nommé "infos" qui permettra les transactions avec le fichier réel précédemment créé en RAM:. Le paramètre "R" indique qu'on effectuera seulement une lecture. Pour une écriture, on indiquerait "W". Ligne 7 Le fichier en RAM: est un fichier texte. On va donc pouvoir le lire ligne à ligne avec READLN(). Chaque ligne sera placée dans un tableau nommé "Ligne". La forme WHILE ~EOF('infos') veut dire : "tant que la fin du fichier tampon 'infos' n'est pas atteinte". Enfin, "BY 1" indique le pas d'avance de la fonction DO. En ligne 9, on trouve la fin classique de la boucle. La forme DO est particulièrement riche en paramètres. Ligne 8 On lit chaque ligne du fichier infos, et on la place dans le tableau ligne.x, l'incrément étant réalisé par la boucle. Ligne 10 Ce n'est pas nécessaire, mais c'est un bon usage que de placer en ligne.0 le nombre de lignes du tableau. Lignes 11 et 12 C'est aussi un bon usage que de laisser une place nette en fermant les fichiers dès qu'ils deviennent inutiles. Ligne 14 L'instruction PRAGMA est assez ésotérique. Elle permet en général de définir le répertoire courant, mais sert ici à "désactiver" le Workbench de sorte qu'il ne présente pas de requête lorsqu'on demandera un disque qui n'existe pas. Le retour au Workbench s'effectuera ligne 47. Lignes 15 et 16 Ouverture des boucles de traitement du nom de disque fourni. Leurs fins respectives sont en lignes 38 et 19. Ligne 18 On peut appeler un sous-programme de deux façons. La première, celle utilisée ici, suppose qu'on n'attend pas de réponse du sous-programme. L'autre forme est utilisée en ligne 36. Ligne 20 L'instruction STRIP ôte d'une chaîne donnée, soit les différents caractères définis en fin de parenthèses, soit les "blancs" du début, de fin, ou des deux comme ici. C'est utile pour les comparaisons car les blancs, bien réels, ne sont pas visibles. Ici, on essaye de parer aux excentricités de frappe en extrayant le texte du nom du disque seulement. Pour en faire un nom légal, il faut concaténer le caractère ":" en fin de chaîne exactement. C'est le rôle de l'opérateur de concaténation "||". On trouve ici un exemple de la possibilité d'associer plusieurs instructions à l'intérieur d'autres. Enfin, il existe une autre méthode pour "nettoyer" une chaîne, par l'intermédiaire de l'instruction COMPRESS. La différence entre STRIP et COMPRESS réside dans le fait qu'alors que STRIP peut agir en début et fin de chaîne de caractères, COMPRESS peut agir aussi à l'intérieur. Ligne 21 Teste l'existence du disque demandé. S'il existe, application de la branche THEN DO, sinon saut à ELSE en ligne 32. Ligne 22 Analyse de la ligne "i" avec tri par variable, par position absolue, et élimination des variables de la ligne non souhaitées par l'usage du point ".". Ligne 23 Calcul de la taille en octets à partir de la variable "Used" lorsqu'elle est réputée numérique ('NUM'). Ligne 24 La forme, de la ligne 24 à la ligne 28, est obligatoire. Mais derrière le "WHEN... THEN" on peut placer un "DO... END" par exemple qui font de SELECT une instruction de sélection puissante. OTHERWISE permet d'en sortir avec élégance si aucune des conditions n'est vérifiée. On l'utilise ici pour déterminer si le nom du disque est un périphérique logique ou un nom propre. Ligne 30 Pour sortir des boucles avant leur fin officielle, il y a deux méthodes : LEAVE(variable_optionnelle), qui permet de sortir d'une boucle itérative nommée, et BREAK, qui sort de la boucle la plus intérieure d'une imbrication de boucles. Ligne 32 Alternative négative du test IF de la ligne 21. A ce propos, dans les boucles imbriquées de "IF... ELSE", il est prudent de toujours placer une alternative ELSE même si elle n'a pas d'utilité fonctionnelle dans le programme. Dans ce cas, on lui associe NOP (comme dans ELSE NOP) qui précise qu'il n'y a rien à effectuer, mais qui permet à l'interpréteur de retrouver ses niveaux de IF. Ligne 51 C'est la définition d'un sous-programme. Ici, l'emploi est simple, mais on peut aussi envoyer des paramètres. On peut également définir deux types de variables utilisées dans le sous-programme : celles qui sont communes à l'ensemble du programme, c'est le cas par défaut ; et celles qui sont propriété du sous-programme définies par le terme PROCEDURE. La différence consiste dans le fait que les variables ainsi définies ne sont accessibles que par le sous-programme lui-même. Nous y reviendrons plus en détails, lorsque nous étudierons la suite de ce programme.
|