Obligement - L'Amiga au maximum

Samedi 20 avril 2024 - 09:18  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in english


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : DICE - les passages de paramètres
(Article écrit par Laurent Faillie et extrait d'Amiga News - avril 1994)


Tels des explorateurs sans peur et sans reproche, nous allons continuer notre voyage au pays des compilateurs C, dans la contrée de DICE en particulier...

Aujourd'hui, nous allons nous arrêter sur les passages des paramètres... Beaucoup de programmes ont besoin d'avoir des informations pour pouvoir s'exécuter et il est souvent plus simple pour l'utilisateur de les passer en paramètres plutôt que de répondre à une requête ou une invite de commande (pour par exemple automatiser un processus). Sur Amiga, nous devons séparer le problème en deux, suivant que le programme est lancé depuis le Workbench ou depuis un Shell.

Le premier monde : le Shell

Nous sommes dans le monde des privilégiés car la majorité des environnements sont de ce type : Unix, OS9, VMS... C'est le mode de communication le plus simple à réaliser (même un PC de base gère ceci avec le MS-DOS, c'est tout dire !). Sur Amiga, cette interface rudimentaire s'appelait d'abord le CLI pour "Command Line Interface", soit interface à ligne de commande en bon français. Très vite, elle s'est transformée en Shell. Que ce soit celui de Commodore ou ceux du DP tels que CSH, ils apportent un confort d'utilisation et une puissance dont il serait dommage de se passer.

Je parlais du monde des privilégiés : n'importe quel programme de C pur (qui n'appelle aucune fonction système) peut être porté vers l'AmigaShell quelle que soit la machine sur laquelle il a été créé par une simple recompilation (vive le C !) alors que ce n'est pas le cas depuis le Workbench. Nous y reviendrons, mais pour le moment, occupons-nous de nos arguments. Comme tout programmeur de C le sait, l'exécution d'un programme commence par une fonction main() dont le prototype est le suivant :

int maintint ac,char **av);

Tiens, mais comment la première fonction d'un programme peut-elle avoir des arguments ? Eh bien, c'est par eux que le Shell indique au programme quels sont les paramètres : "av" est un tableau de chaînes de caractères (on aurait pu le prototyper "char av[][]"). Dans chacune se trouve un argument. Attention, dans "av[0], il y a toujours le nom du programme. "ac" contient le nombre d'arguments. Petite devinette : quelle est la valeur minimale de ac (sous Shell) ? La réponse est 1 évidemment, il s'agit du nom du programme.

DICE

Testons ce programme :

DICE

Remarquez que chaque mot est considéré comme un argument différent. Les espaces comme les tabulations sont considérés comme des séparateurs et le nombre d'espaces entre les mots est sans importance. Si nous voulons utiliser une phrase entière, il faut l'entourer de guillemets :

DICE

Si notre programme doit utiliser des fichiers, il est souvent pratique de pouvoir utiliser les jokers (alias "wildcards" : ?, #?, etc.). Pour les utilisateurs de CSH, pas de problème, car c'est le Shell qui s'occupe de tout... Pour les autres (ou dans le cas où l'utilisateur désire utiliser les jokers de Commodore qui ne sont pas gérés par les CSH inférieurs à 5.31), DICE dispose d'une fonction nommée "expand_args()" et qui fait tout le travail pour nous :

DICE

"xac" et "xav" sont les paramètres fournis par main(), "ac" et "av" sont leurs équivalents une fois que tous les paramètres ont été étendus. Tout est fait automatiquement, le programmeur n'a à s'inquiéter de rien.

DICE

Pour connaître toutes les bibliothèques et tous les périphériques logiques qui se trouvent dans un sous-répertoire (de niveau 1) de Sys:, tapez :

DICE

Notez, au passage, que j'ai mis l'expression entre guillemets sinon CSH fera tout le travail et je n'aurai rien démontré... On remarque ici aussi la puissance des jokers d'AmigaDOS (comparez avec le MS-DOS...). Avec AmigaOS 2.0, la dos.library nous permet de créer des programmes dans le style des commandes de Commodore avec les fonctions FindArg(), ReadItem(), FreeArgs() et ReadArgs(). Elles ont été vues dans cet article.

Quelques précisions, l'auteur préconise l'utilisation de "_main()" au lieu de "main" pour récupérer la ligne de commande avant transformation en "av[][]. Je rappelle que dans ce cas, les printf(), scanf et tout ce qui gère les entrées/sorties dans la bibliothèque du compilateur, mais aussi la gestion de la mémoire par malloc(), calloc(), realloc(), free(), strdup()... n'est plus utilisable.

Il y a de toute façon une méthode beaucoup plus simple : chaque programme du CLI est un processus, et on peut récupérer la ligne de commande dans sa structure de description grâce à la fonction GetArgStr(void) ou directement dans sa structure CLI (voir les includes du 2.0 ou plus). Des erreurs se sont d'ailleurs introduites dans cet article. Contrairement à ce qui est dit, le mot long qui correspond à un argument absent n'est pas NULL mais garde la valeur qu'il contenait avant l'appel de ReadArgs(). Il ne contient pas la valeur pour un /N mais un pointeur sur cette valeur... Je vais donc reprendre l'exemple d'Emmanuel Buu :

DICE
DICE

D'abord, remarquez que j'ai utilisé les fonctions de la dos.library pour les E/S (Printf(), PutStr()). C'est pourquoi les entiers sont affichés par "%ld" car je vous rappelle que les fonctions de la ROM utilisent des entiers sur 16 bits par défaut alors que tous les compilateurs modernes passent les arguments sur des mots longs.

Remarquez aussi le "%lc" qui peut paraître assez bizarre. Le fait de tout passer sur des mots longs peut choquer mais il faut savoir que c'est beaucoup plus rapide ainsi pour les processeurs 32 bits (à partir du 68020) et ne ralentit pas beaucoup les 16/32 (68000/68010). Dernière chose, contrairement au puts(), PutStr() ne rajoute pas automatiquement de "\n" en fin de ligne.

Bon passons maintenant à nos arguments. Suivant le type argr[x] contient :
  • "\A" ou "\K" contient un pointeur sur la chaîne donnée en argument.
  • "\N" contient un pointeur sur un long (pourquoi ne pas y stocker directement la valeur, monsieur Commodore ?).
  • "\S" ou "\T" TRUE si l'option est sélectionnée.
Remarquez que vos données ne seront jamais modifiées (par exemple, "del" du programme précédent contiendra toujours 0), ce ne sont que les pointeurs de argr qui changent (sans doute pour faciliter la programmation de commande PURE). Pour conclure, je dirai qu'il est très important d'initialiser le tableau argr pour tous les mots clefs qui ne sont pas /A avant d'appeler la fonction ReadArgs() sous peine d'avoir des valeurs bidons en retour...

Le second monde : le Workbench

Ah, le Workbench... C'est la petite touche pro d'un programme. Si un simple double-clic de souris suffit à le lancer, c'est déjà bien, mais si en plus il accepte des arguments de cette interface, c'est vraiment le summum !

Avant de donner un petit plus à nos programmes, une remarque : il est très important de se souvenir qu'un programme lancé depuis le Workbench ne possède pas de canaux d'entrée/sortie standard (stdin, stdout, stderr) et toute tentative de printf(), scanf(), puts() mais aussi les perrors() ou fprintf(stderr,...) se solderont par le réveil de notre ami le Guru... Chez Sas (ex-Lattice), le problème est contourné en ouvrant automatiquement une fenêtre d'entrée/sortie mais c'est vraiment disgracieux...

Avec tout autre compilateur, le lancement depuis le Workbench n'est signalé que par "ac == 0". Tout le reste du travail doit être fait par le programmeur mais avec DICE, c'est plus simple : si le programme est lancé depuis son icône, il débute par wbmain(). Notez que main() doit quand même exister sinon dlink renverra une erreur. Le programme suivant est l'équivalent du précédent : il affiche ses arguments.

DICE

Voici les fameuses structures utilisées lors du passage des arguments :

DICE

On voit tout de suite qu'il y a beaucoup d'informations dans ces structures, mais nous n'allons voir que celles qui nous intéressent ici : wbarg->sm_NumArgs et wbarg->sm_ArgList.
  • wbarg->sm_NumArgs contient le nombre d'arguments, et comme pour le CLI, le programme lui-même est inclu dans ce nombre...
  • wbarg->sm_ArgList est un tableau de structure WBArg qui contient les arguments eux-mêmes. Devinez qui est wbarg->sm_ArgList[O] ? Il s'agit de l'exécutable que nous lançons. Comme vous pouvez le voir, ça ne change pas vraiment par rapport à main()...
Pourquoi cette structure WBArg alors qu'une simple chaîne, contenant à la fois le path (chemin) et le nom du fichier, aurait suffi par argument ? Contrairement à la majorité des systèmes d'exploitation, l'Amiga a une notion de volume et non d'unité physique. Cela signifie qu'un fichier est défini par son nom (évidemment) mais aussi par le volume sur lequel il se trouve. Si, par exemple, vous chargez un fichier avec l'éditeur AZ, lorsque vous voudrez le sauver en remplaçant l'original, l'Amiga saura sur quelle disquette le sauver, même si vous l'avez changé de lecteur, ou la demandera si elle n'est plus "montée". C'est cela la notion de volume et plus encore car la disquette est aussi trouvée si une autre avec le même nom est aussi présente.

Un volume est caractérisé par un "lock" (verrou) qui est propre à chaque fichier. Bon, ça n'arrange pas nos affaires car un chemin aurait été plus facile à gérer mais comme d'habitude, la dos.library fournit la fonction adéquate : CurrentDir() qui place le répertoire courant sur celui fourni par un "lock". Voici, schématiquement, comment procéder pour ouvrir le premier fichier passé en paramètres :

DICE

Bon, il est évident que des tests doivent être rajoutés mais je vous laisse le faire vous-même...

Erratum :

Le caractère "\" est manquant dans certaines lignes de cet article. Explication : Professional Page se sert du "\" comme code de contrôle, et il est nécessaire, avant l'importation du texte, d'en mettre deux "\\". Excusez-nous pour cet oubli, voici les rectifications.

DICE

DICE


[Retour en haut] / [Retour aux articles] [Article précédent]