|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
AmigaOS possède deux interfaces utilisateur principales : le Workbench et le Shell. Le Workbench utilise la souris, les icônes, les fenêtres, les menus... tous les trucs sympathiques. Parlons donc de l'autre : le Shell. Il est plus traditionnel, utilise le clavier, une seule fenêtre et est moins intuitif à utiliser. Apparemment - et comme c'est généralement le cas - les manuels sont mis de côté et rarement lus. Malheureusement, cela signifie que vous risquez de manquer beaucoup des nouvelles fonctionnalités qui ont été introduites dans AmigaOS 3.9. Cet article, dans un ordre approximatif, présentera les "fonctionnalités moins connues" du Shell Amiga. Sauf indication contraire, cet article utilise le Shell AmigaOS du dernier Boing Bag d'Amiga 3.9, et la console d'AmigaOS 3.9, ViNCEd. Une ancienne version de ViNCEd peut être trouvée sur Aminet, bien que la plupart du temps, vous aurez besoin de la dernière. Toutes les astuces suivantes commencent par l'ouverture d'une fenêtre du Shell. Il est généralement placé en évidence sur le disque du Workbench, avec une icône nommée "Shell". "SYS:System" contient également une icône, généralement nommée "CLI". Il s'agit du même Shell, mais d'une interface utilisateur moins utile qui manque de certaines fonctionnalités. Nous avons besoin de la première. L'emplacement exact de ces icônes est bien sûr une question de goût. 1. Les scripts Shell Nous allons commencer avec les scripts Shell. Le Shell prend des commandes, sous la forme "d'arguments de commande". Si vous tapez "list", dans la fenêtre du Shell, cela exécute la commande "list". Si vous tapez "copy s:startup-sequence to ram:", cela copie la startup-sequence sur le RAM Disk. "S:Startup-sequence" est un script Shell, une série de commandes, l'une exécutée après l'autre. Ce script en particulier est important car il est exécuté par le système pour démarrer. La première bidouille de cet article est une fonctionnalité particulièrement "sympathique" : le débogage interactif et le traçage des scripts Shell. Le traçage signifie que le Shell vous montre quelle commande il est sur le point d'exécuter, et vous pouvez exécuter la commande, l'ignorer ou arrêter le traçage. Pour activer le traçage, utilisez la commande suivante dans le Shell :
Si cette commande est placée en haut d'un script Shell, par exemple dans la startup-sequence (avec un éditeur de texte de votre choix), le Shell vous fera une demande pour chaque commande qu'il va exécuter. Si vous appuyez sur "Entrée", le Shell exécutera la commande. Si vous appuyez sur "N" ou "Suppr", le Shell l'ignorera. Si vous appuyez sur "Échap", le Shell interrompra le traçage et exécutera le reste du script sans vous déranger davantage. Si vous appuyez sur "Ctrl+D", le script sera interrompu. 2. La redirection L'astuce suivante porte sur la redirection. Elle est moins utile sur AmigaOS que sur Unix - elle permet de diriger la sortie d'une commande vers un autre fichier (au lieu de la console), ou de prendre l'entrée d'une commande depuis un fichier plutôt que depuis la console. Tout le monde connaît les classiques :
Maintenant, pour rediriger la sortie d'erreur, AmigaOS ajoute "*>filename", se lisant comme "la console va vers le fichier". C'est très utile si le "fichier" cible est en fait un type de terminal interactif, par exemple AUX: (la console série), ainsi "*>AUX:" fait de la console la console série, et par là aussi la sortie d'erreur standard. Quel ">>" est pour ">" est "*>>" vers "*>" : la redirection "*>>filename" redirige la sortie d'erreur vers un fichier, mais au lieu d'écraser ce qui s'y trouve, elle ajoute à la fin. Ensuite, nous avons "*<>", qui redirige l'erreur standard dans le même flux vers lequel va la sortie standard. Il ne prend pas d'argument. C'est-à-dire que la sortie d'erreur va dans le même fichier vers lequel va la sortie standard. Ainsi, "command >ram:fool *<>" redirige également la sortie d'erreur vers le RAM Disk. Enfin et surtout, il y a "<<". Cela redirige l'entrée standard, mais c'est un peu spécial. Il ne prend pas d'entrée à partir d'un fichier, mais plutôt à partir d'un script dans lequel une commande est placée. Avec "<<", une partie du script devient l'entrée, à savoir tout ce qui se trouve sous la ligne de commande actuelle et un "marqueur de fin", une séquence de caractères spéciale qui est également placée comme argument derrière "<<". Pour donner un exemple, considérons le script Shell suivant :
Il redirige l'entrée de "command" vers le même script, et tout jusqu'à "END" est l'entrée de la commande, et la ligne "foobar" est l'entrée littérale du fichier. C'est très utile si vous devez fournir des entrées complexes à une commande, mais que vous ne voulez pas créer un fichier temporaire en RAM:. À la place, le Shell le fait pour vous. Si vous connaissez le Shell "bash" de Linux, c'est à peu près comme ça que cela fonctionne. Sous Linux, "*>" s'écrirait "2>", "*>>" serait "2>>" et "*<>" serait "2<&1", mais comme le Shell Amiga n'a pas de "descripteurs de fichiers" comme Linux, et n'a que "deux descripteurs et demi" standards (CIS, COS, CERR) au lieu des nombreux que Linux a, "2" était un choix particulièrement mauvais (et peu intuitif) pour la sortie d'erreur. "*>" a été choisi car c'est tout simplement l'inverse de ">*". Le premier redirige la console vers un fichier, le second redirige la sortie vers une console, il est donc facile à retenir. 3. C'est plein d'étoiles ! "*" Connaissez-vous la signification de "*" dans un Shell Amiga ? En fait, il y en a beaucoup, et il n'est pas toujours facile de les distinguer. Donc, tout d'abord, si vous mettez l'étoile "*" en dehors des guillemets, cela signifie la console actuelle. Ainsi, par exemple, si je place une...
...cela signifie : copier le contenu du fichier sur l'écran. Étrange, car l'étoile signifie généralement un joker pour de nombreux autres systèmes d'exploitation. Les choses changent cependant si vous mettez l'étoile entre guillemets. Dans ce cas, l'étoile est le "caractère d'échappement" de BCPL, un peu comme la barre oblique inverse en C. Comme AmigaOS était traditionnellement basé sur Tripos, écrit en BCPL, cela fonctionne toujours comme cela aujourd'hui. C'est-à-dire :
...place le curseur à la position initiale, c'est-à-dire en haut à gauche. C'est parce que "*e" est la séquence d'échappement pour le caractère ASCII "escape" (hex 0x1c, décimal 27), Escape-[ est le "CSI", l'introducteur de la séquence de contrôle, et "CSI-H" est la commande de la console, comprise par la fenêtre de la console, pour mettre le caractère en position supérieure gauche. Ainsi, l'étoile signifie quelque chose de différent entre guillemets par rapport aux guillemets extérieurs. Si vous utilisez...
...à la place, cela revient simplement à mettre la chaîne littérale sur la console. Maintenant, dans AmigaOS 2.x, Commodore a réécrit la bibliothèque DOS. Ou plutôt, ils ont simplement pris ARP, le "Amiga Replacement Project", ont fait quelques modifications, et l'ont utilisé comme nouvelle base. Dans ARP, un indicateur existe pour changer l'interprétation des caractères génériques, c'est-à-dire des motifs qui correspondent à plusieurs fichiers pour exécuter une tâche plus efficacement. Par exemple...
...copie tous les fichiers du répertoire courant sur la console, "#?" correspondant à tous les fichiers. L'expansion du caractère générique pour le joker "#?" est fait par la commande "copy", pas par le Shell (contrairement à d'autres systèmes d'exploitation, Linux par exemple, où cette extension est sous contrôle du Shell). Nous arrivons maintenant à la troisième signification de l'étoile. Malheureusement, ARP a inclus une option dans sa correspondance de motifs pour utiliser "*" en remplacement de "#?" "à la demande générale". Ainsi, si une commande utilise le comparateur de motifs d'ARP (maintenant dos.library), alors "*" peut (par choix de l'utilisateur) obtenir une autre signification, à savoir "correspondre à chaque fichier". Cela devient maintenant vraiment déroutant, car vous devez vous rappeler quand une commande utilise le comparateur de motifs (alors *=#?) et quand il ne l'utilise pas (alors *=console actuelle). Ainsi, par exemple, avec l'indicateur ARP-"*" défini (plusieurs correctifs fournissent cette option)...
...signifie "copier tous les fichiers sur la console", où le premier "*" est vu par le comparateur de motifs, donc cela signifie "#?" (tout), et la deuxième étoile ne l'est pas, donc cela signifie "console". Malheureusement, vous devez savoir cela, mais très peu de personnes le savent (comment, le pouvez-vous ?), ce n'est généralement pas une bonne idée d'activer cette option. Il existe déjà deux significations de l'étoile, et en ajouter une troisième n'est pas un choix particulièrement judicieux, d'autant plus qu'elle dépend des décisions d'implémentation de la commande Shell et n'est pas sous le contrôle direct de l'utilisateur. Évitez ce genre de choses, et apprenez que l'Amiga est un peu spécial et utilise "#?" comme caractère générique, et non "*". "*" est la séquence d'échappement BCPL entre guillemets, ou la console comme nom de fichier en dehors des guillemets. 4. "*" ou "CONSOLE:" Peut-on remplacer "*" par "CONSOLE:" ? La réponse est "peut-être pas, cela dépend". En fait, si vous utilisez "*" ou "CONSOLE:", la bibliothèque dos.library fait à peu près la même chose : elle vérifie le processus de console enregistré pour le processus en cours d'exécution et lui transmet la requête. Ce qui se passe dans la console dépend alors de l'implémentation de la console, et cela "dépend". Pour ViNCEd (voir ci-dessus pour les conseils d'installation), l'utilisation de "CONSOLE:" est liée au contrôle des tâches. ViNCEd peut exécuter plusieurs Shells dans la même fenêtre et peut basculer entre eux. Il n'y en a qu'un au premier plan, et ce Shell peut afficher dans la fenêtre de la console. Tous les autres restent en arrière-plan, et une fois qu'ils essaient d'afficher des données dans la fenêtre, ils sont suspendus. La façon dont ViNCEd peut distinguer les Shells est par le "nom de la console" (ou plutôt, la façon dont ViNCEd l'appelle, par le "propriétaire"). Essayons donc ceci : ouvrir un Shell ViNCEd. Pour mon système, le nouveau Shell s'ouvre en tant que processus Shell n°7, il m'affiche donc l'invite suivante :
Il s'agit du "Shell n°7" et le répertoire est SCSI:, qui est le nom de mon disque dur. Démarrons un nouveau Shell sous un nouveau propriétaire de console :
Maintenant, le "&" à la fin indique au Shell de détacher la commande suivante, c'est-à-dire que cela est similaire à "run". De manière équivalente, nous aurions pu utiliser :
Le résultat de cette commande est un message tel que celui-ci :
Cela signifie : un nouveau Shell a été créé, le Shell n°8, et le Shell a été suspendu car il a essayé de générer quelque chose, bien que le propriétaire actif soit actuellement le Shell n°7, celui que vous saisissez. Vous pouvez lister les Shells actifs avec la commande status :
Cela affichera la liste de tous les Shells actuellement actifs et les commandes qu'ils exécutent. Le Shell n°7 exécute la commande status (clairement), le Shell n°8 est actuellement inactif (suspendu) et n'exécute aucune commande. Passons maintenant au Shell n°8 :
"fg" est un petit script dans s:. S'il n'est pas présent, vous pouvez également taper :
C'est exactement ce que fait le script. Il déplace le Shell n°8 au premier plan et le Shell n°7 en arrière-plan. L'invite vous indique maintenant que vous êtes dans le Shell n°8 :
Vous pouvez remettre ce Shell en arrière-plan en appuyant sur "fg 7", ou simplement sur "bg", ce qui signifie "veuillez remettre le Shell actuel en arrière-plan".
Nous revenons maintenant au Shell n°7. Pour créer un nouveau Shell, ViNCEd dispose d'un raccourci. Il s'agit de la combinaison de touches "Ctrl+Z". Elle ne fonctionne que si le Shell actuel est occupé, c'est-à-dire que vous n'êtes pas en mesure de soumettre une commande. Cette combinaison de touches permet en interne de choisir d'abord un nom unique, puis d'appeler "newshell console:xxxx" en remplaçant "xxxx" par ce nom, juste pour vous donner la possibilité de saisir à nouveau une commande. Revenons maintenant aux consoles et aux noms de console. Ci-dessus, nous avons créé un nouveau Shell avec "newshell console:myname". De toute évidence, tout programme qui souhaite afficher dans "console:newname" ou qui utilise cela comme nom de chemin s'identifie désormais comme faisant partie de ce nouveau Shell. "newname" identifie le "propriétaire de la console", et le nom de ce propriétaire est "newname". Si vous écrivez dans "console:newname", et que ce propriétaire de console n'est pas actuellement au premier plan, la commande est suspendue. Essayons ceci : revenons d'abord au Shell n° 7, puis affichons quelque chose au propriétaire de la console 8, qui n'est pas au premier plan :
En conséquence, la commande "echo" est suspendue. Comme elle est suspendue, le Shell ne revient pas et vous vous retrouvez sans Shell dans la fenêtre. Que pouvons-nous faire ? Eh bien, en chercher un libre. C'est ce que fait "Ctrl+Z", donc appuyez sur la touche "Ctrl", maintenez-la enfoncée et appuyez sur "Z", puis relâchez les deux touches. Vous revenez à un Shell libre, qui est le Shell 8.
Maintenant, si vous placez ceci en arrière-plan, la commande "echo" est enfin autorisée à afficher. Maintenant, si "CONSOLE:" s'adresse à une console nommée, que signifie "CONSOLE:" ? C'est la "console de démarrage", c'est-à-dire la console qui a été démarrée avec la fenêtre. Et à quoi sert "*" ? C'est la "console actuelle", à savoir la console qui est actuellement active et au premier plan. Ainsi, "CONSOLE:" et "*" ne sont pas nécessairement identiques, ou plutôt, ils ne sont identiques que si la console actuelle est la console qui a été créée avec la fenêtre - ou la seule console. Ainsi, il est généralement sûr de sortir vers "*", car elle est toujours au premier plan, et il n'est pas toujours sûr de sortir vers "CONSOLE:" car cette console peut être en arrière-plan, et vous pourriez être suspendu. Ainsi, "CONSOLE:" != "*", et le nom de fichier derrière "CONSOLE:" a une signification spécifique, il identifie l'une des nombreuses consoles qui partagent la même fenêtre en sortie. Tout le contrôle des tâches et le contrôle de sortie sont effectués par ViNCEd, et vous pouvez basculer entre les consoles avec le programme SetVNC ou de petits scripts dans S:. Il y a, bien sûr, des "paquets DOS" correspondants qui effectuent la commutation, c'est-à-dire qu'il n'y a pas "d'interface magique", mais plutôt des "commandes de contrôle de travail" envoyées à la console de la même manière que la sortie est écrite sur la console. 5. Skip et Lab A présent, je vais essayer de couvrir un peu le côté sombre du Shell Amiga, et ce sont les deux commandes "skip" et "lab", et pourquoi elles ne fonctionnaient parfois pas avant AmigaOS 3.9. Des deux, "lab" n'est en fait pas du tout une commande - ou plutôt, c'en est une, mais elle ne fait rien, tout en étant nécessaire. Le contrôle de flux - c'est une fonctionnalité clé de tout langage de programmation. C'est-à-dire, contrôler où va le flux du programme. "if-then", "for-next", "do-while", "repeat-until", ce genre de choses. Malheureusement, la seule chose qu'AmigaOS possède est "if-then" et "goto", même si ce dernier se prononce "skip". C'est la même commande laide qui a été bannie de nombreux langages plus raisonnables pour une bonne raison - elle crée du code spaghetti. Quoi qu'il en soit, c'est tout ce que nous avons, alors voici comment cela fonctionne : si vous avez un "lab foo" quelque part dans un script Shell, alors un "skip foo" continue le contrôle à cette position même dans le script. Assez simple ? Pas tout à fait. Si l'étiquette est au-dessus de la commande "skip", c'est-à-dire sur une ligne "plus haut dans le code", vous devez dire "skip BACK foo". Assez simple ? Pas tout à fait. S'il y a un "execte" quelque part entre l'étiquette, ou si vous appelez un script Shell par un autre moyen - probablement parce que vous avez un fichier dont l'attribut "s" est activé, cela ne fonctionne pas du tout. Ou du moins, cela ne fonctionnait pas avant la dernière version du Boing Bag d'AmigaOS 3.9. Pourquoi maintenant le foutu Shell se soucie-t-il d'exécuter ou non ? C'est encore une des tristes histoires de "mauvaise décision de conception". Rappelez-vous, les commandes ont un flux d'entrée et un flux de sortie, vous pouvez rediriger avec "<" ou ">". Dans un sens, le Shell a la même chose : il a une entrée interactive, qui est la console sur laquelle l'utilisateur tape et le Shell connecte l'entrée des commandes qu'il exécute. C'est la console. Ce flux est utilisé pour la commande "ask", par exemple, pour lire l'entrée utilisateur. Mais le Shell a aussi une entrée de commande, et c'est de là que viennent les commandes du Shell. C'est généralement aussi la console, car le Shell exécute les commandes au fur et à mesure que vous les saisissez. Maintenant, cependant, si vous exécutez un script (explicitement, ou implicitement par un attribut "s" activé), le Shell fait ce qui suit : il connecte son "entrée de commande" au fichier du script. Cela semble être la chose la plus simple à faire : comme par magie, l'entrée vient maintenant du fichier de script. Puisque l'entrée interactive est toujours connectée à la console, la commande "ask" et toutes les autres commandes la reçoivent toujours comme entrée standard, et lisent donc leur entrée à partir de la console comme elles le devraient. C'est assez simple et clair, sauf si... vous voulez exécuter un script à partir d'un script. Oups, que faisons-nous maintenant, ont dit les ingénieurs de Commodore ? Ils ont trouvé la bidouille la plus moche à laquelle vous puissiez penser : prenez le script à exécuter, copiez-le sur le RAM Disk (en fait, T:), et ajoutez le reste du script qui est en cours d'exécution (et donc, le script qui appelle l'autre script) et ajoutez-le en bas, puis exécutez le nouveau script. Vous voyez où je veux en venir ? Puisque le début du script actuel est perdu, et donc toute commande "lab" est perdue, un "retour en arrière" vers une étiquette qui se trouve sous toute commande d'exécution ne peut plus voir le "lab" et donc, ne peut pas revenir en arrière. Heureusement, le Shell 3.9 est plus intelligent et fait ce que tout langage de programmation approprié fait avec la récursivité : il conserve une pile. Ainsi, oui, vous pouvez "revenir en arrière". Au cas où cela vous intéresserait, la pile est conservée dans certaines variables du Shell (vous pouvez les voir avec la commande "set", qui sera abordée dans une prochaine astuce). Ce que le Shell 3.9 ne fait pas, c'est de s'en sortir avec "skip", et d'introduire un contrôle de flux utile, comme dans "for" ou "while". Ce ne serait pas trop difficile à faire, mais cela n'a tout simplement pas été fait. Un peu de tradition devait quand même rester, je dirais. 6. Append files Juste au cas où quelqu'un se demande où se trouve la bidouille "append files" : c'est en fait une partie de la commande "execute". "execute" est vraiment source de miracles partout. Il a un "chemin d'exécution simple" et un "chemin d'exécution élaboré". Dans le chemin simple, il modifie simplement l'entrée de commande du Shell en cours d'exécution, lui permettant de récupérer les commandes du fichier script. Cependant, si le script contient des "commandes à points", c'est-à-dire comme ".key blabla" pour autoriser les arguments, alors c'est le "chemin élaboré". De plus, si "execute" découvre qu'il est lui-même exécuté à partir d'un script, il exécute le chemin élaboré, qui fait tout le bazar avec la copie et l'ajout de fichiers. Ce dernier cas n'est plus nécessaire avec les Boing Bag d'AmigaOS 3.9. 7. La console ViNCEd Bon, maintenant regardons la console dans laquelle tourne le Shell. La console originale de Commodore, "CON:", était vraiment une piètre excuse. Elle ne pouvait pas faire grand-chose à part déplacer le curseur vers l'arrière et vers la droite, et offrir un éditeur de ligne sans historique. Puis, avec le Kickstart 1.3, "NEWCON" a été introduit, qui incluait au moins un historique. Au même moment, ViNCEd (à l'époque VNC=VeryNewCon) a vu le jour, et proposait un éditeur plein écran permettant de déplacer le curseur où l'on veut, un historique et une extension TAB. Pour les prochaines astuces de ce petit article, nous aurons besoin de cette console, à savoir la version fournie avec AmigaOS 3.9. Il existe des versions antérieures sur Aminet qui sont un peu moins puissantes. ViNCEd a souvent été critiqué pour n'être "pas exactement comme XYZ", bien que ce soit à peu près le but - être différent. Après tout, Amiga est différent aussi. Donc, de toute façon, voici - en guise de début - quelques instructions pour le rendre "moins différent". Les extensions TAB vont ensuite dans la fenêtre de la console (au lieu d'une requête) et le curseur haut/bas navigue dans l'historique (au lieu de déplacer le curseur). C'est à peu près les paramètres fournis avec AmigaOS 3.9, même si les gens l'ont probablement installé autrement. Tout d'abord, démarrez le Shell et cliquez sur "Settings" (Paramètres) en haut à droite de la bordure de la fenêtre. SetVNC apparaît. Naviguez maintenant vers la page du Shell : [image manquante] Pour cela, cliquez sur l'onglet "Shell" (élément 1 dans l'image ci-dessus), puis appuyez sur la "flèche avant" (élément 2 dans l'image ci-dessus) jusqu'à ce que vous voyiez "Shell page 3 (sur 7)" à l'écran. Cliquez ensuite sur "Requester if expansion is ambiguous" (Requête si l'expansion est ambiguë) (élément 3) qui vous donnera déjà les fichiers correspondants sur le premier "TAB", puis appuyez à nouveau sur la flèche avant (élément 4). Cela vous donne la page Shell 4 : [image manquante] Sur cette page, sélectionnez "List expansions on the console" (Liste des extensions sur la console) (élément 5), ce qui désactivera la requête, mais affichera simplement les fichiers correspondants dans la console, et - si vous le souhaitez - "Do not match characters behind cursor" (Ne pas faire correspondre les caractères derrière le curseur) (élément 6). Cela ne fera correspondre que le début du fichier devant le curseur, mais pas les caractères derrière lui. Regardons maintenant les touches de curseur. Pour cela, cliquez sur l'onglet "Keyboard". [image manquante] ...qui est l'élément 1 dans la figure ci-dessus. Ensuite, cliquez sur la case "2", et appuyez sur la touche de curseur vers le haut de la console. Le mot "Up" apparaît dans la case. Cela signifie que vous allez maintenant modifier la définition de la touche "Up". Enfin, cliquez sur la flèche vers l'avant (élément 3) pour aller à la deuxième page du clavier : [image manquante] Dans la liste (élément 4), sélectionnez "History up" (Historique vers le haut), puis cliquez sur "Accept" (Accepter) (élément 5), puis revenez à la page précédente (élément 6) avec la flèche arrière. Là, cliquez à nouveau dans la boîte, appuyez sur la touche "Down", puis avancez à nouveau et sélectionnez "Histoty down" (Historique vers le bas). Enfin, cliquez sur "Save" (Enregistrer) pour rendre les modifications permanentes, sur "USe" (Utiliser) pour les tester dans toutes les fenêtres Shell ouvertes, ou sur "To Window" (Vers la fenêtre) pour les tester uniquement dans la fenêtre actuelle. Cela vous donne une console Shell "plus standard". Plus d'informations sur tout cela dans l'astuce suivante. 8. Comment le Shell exécute les commandes Regardons à présent comment le Shell exécute les commandes. Cela semble ennuyeux ? Vous tapez la commande, le Shell la localise dans le "path" (chemin) et l'exécute, n'est-ce pas ? Eh bien, pas tout à fait. Il y a quelques pièges. Tout d'abord, il y a le signe "+" à la fin de la ligne. Il est souvent mal compris de continuer la ligne de commande actuelle à la ligne suivante, mais alors pourquoi...
...affiche uniquement "hello" et non "hello world" ? D'un autre côté...
...exécute effectivement la commande "list". Alors, quelle est la différence entre "echo" et "run" ? Eh bien, le signe plus insère également un saut de ligne dans la ligne de commande, et "echo" arrête simplement d'analyser ses arguments de commande à cet endroit. Le reste de la chaîne reste dans l'entrée standard de la commande, au moins si elle utilise des entrées/sorties en mémoire tampon, et attend d'être récupéré après l'analyse. "Run" analyse plusieurs lignes, mais toutes les autres commandes s'arrêtent simplement au premier saut de ligne. Quoi qu'il en soit, pour revenir au "+", ce qui suit le démontre :
Le Shell va maintenant vous demander gentiment de saisir le numéro, alors faites-le avec plaisir :
Ce numéro est-il arrivé ?
Oui, c'est bien. Mais nous pouvons également insérer la réponse directement dans "ask" en utilisant cette petite astuce :
À ce stade, "ask" n'attend même pas que vous répondiez, mais prend le "54" de la ligne suivante et le pousse dans son entrée. Ainsi, la commande "ask" revient immédiatement. Il existe un autre jeton magique comme "+", à savoir "&". Cela fonctionne comme "run", en fait très similaire, car il exécute une commande en arrière-plan :
Ainsi, la commande "list" est démarrée, exécutée en arrière-plan, mais comme elle essaie d'écrire quelque chose sur la console, mais n'est pas le propriétaire actuel de la console (voir l'astuce 4.), elle est suspendue. Pour continuer, placez-la au premier plan :
Si vous souhaitez simplement exécuter une commande en arrière-plan, redirigez son entrée et sa sortie vers NIL:. Bien sûr, cela n'a pas beaucoup de sens avec "list", mais de toute façon :
...démarre "list" en arrière-plan et retourne au Shell. Maintenant, en plus des commandes, nous avons aussi des scripts. Un script est un fichier dont l'attribut de protection "s" est activé ; ceux-ci se trouvent généralement dans S:, par exemple la commande "fg" en est un. Si l'attribut "s" est activé, le Shell fait autre chose. Habituellement, vous diriez "exécutez ceci comme un script Shell", mais attendez, ce n'est pas aussi simple. Il essaie d'abord de déterminer le type du script. Si les deux premiers caractères du fichier sont "/*", c'est-à-dire barre oblique, étoile, alors le nom du fichier est pris tel quel, un "rx" est ajouté au début, et le résultat est exécuté. Par conséquent, l'exécution n'est pas effectuée par le Shell, mais par ARexx. Ces deux "caractères magiques" identifient les scripts REXX plutôt que les scripts Shell. Il existe plus de caractères magiques que "/*". Ce sont "#!" et ";!", tous deux fonctionnent de manière identique. Si un fichier dont l'attribut "s" est activé les a comme premiers caractères de la première ligne, le reste de la ligne indique le nom d'une commande à exécuter pour exécuter le script, et le reste de la ligne de commande serait donné à cette commande. Par exemple, si AmigaOS avait un interpréteur Python, la ligne initiale "#! C:python" exécuterait l'interpréteur Python. Mais nous pouvons essayer quelque chose de similaire :
Cela fait croire au Shell que "ram:test" est un script dont l'interpréteur est l'éditeur Ed, et en l'exécutant, il est exécuté avec le nom du "script à exécuter", à savoir "ram:test", comme premier argument. Maintenant, c'est l'attribut "s". Mais il y a plus. Vous connaissez bien sûr la fonctionnalité selon laquelle le Shell exécute implicitement un "cd" - changement de répertoire - si vous tapez simplement le nom d'un répertoire ou d'un périphérique :
Mais que fait-il si le fichier n'est pas exécutable et n'est pas un répertoire ? Eh bien, même dans ce cas, le Shell peut faire quelque chose, même si cela dépend de la définition des bonnes variables. Aidons donc un peu le Shell :
Maintenant, pour que cela fonctionne, je suppose que vous avez "Shell.guide" dans une assignation nommée "Guides:", et que l'attribut "e", pour "executable", de ce guide n'est pas activé. S'il est activé, le Shell essaiera d'exécuter le "Shell.guide" en binaire, et cela vous donnera bien sûr un "l'objet n'est pas exécutable". Cependant, de la manière dont cela est organisé ici, le Shell déterminera que l'entrée est un datatype, et exécutera ce datatype via le visualisateur, qui est Multiview. Ce paramètre de variable "VIEWER" peut être rendu permanent dans ENVARC: si vous le souhaitez :
...et si l'exemple ci-dessus ne fonctionne pas, supprimez l'attribut "e" :
Maintenant, une dernière "fonctionnalité" du Shell. Supposons que vous ayez la bibliothèque mmu.library dans "Libs:" :
Que fait ce qui suit ?
Il affiche mmu.library: Commande inconnue", même si la "commande" est juste devant la face du Shell, et c'est même un binaire AmigaOS, et il a même son attribut "e" activé, donc il devrait être exécutable. Pourquoi le Shell n'essaie-t-il pas alors d'exécuter le fichier ? Le fait est qu'il le fait réellement. Cependant, les bibliothèques et les périphériques ne sont pas chargés dans le système comme cela, du moins pas normalement (vnc.library est une exception). Donc ce que fait le "code de démarrage" de la bibliothèque est de simplement renvoyer un "-1" comme code de retour au Shell. Et ce code de retour magique, non documenté à ma connaissance, dit au Shell "eh, je ne suis en fait pas un exécutable, affiche une erreur à l'utilisateur". Même s'il est réellement exécuté, il ne fait rien d'utile. 9. Variables du Shell Que savez-vous des variables de l'interpréteur de commandes ? Celles-ci fonctionnent comme dans n'importe quel autre langage de programmation, REXX par exemple. Vous leur attribuez une valeur comme ceci :
...et vous récupérez leur valeur d'une manière un peu différente, notamment en plaçant un signe de dollar ($) devant leur nom :
D'où viennent ces variables ? Eh bien, de plusieurs endroits. Tout d'abord, si vous utilisez simplement "set" comme ci-dessus, elles proviennent d'une base de données interne à l'interpréteur de commandes. Celle-ci est différente pour chaque interpréteur de commandes et, par conséquent, ces variables sont "locales" à l'interpréteur de commandes dans lequel vous les utilisez. Un deuxième type de variables est constitué par les "variables d'environnement globales". Elles sont définies avec "setenv" au lieu de "set", mais fonctionnent de la même manière :
...et vous récupérez leur valeur d'une manière un peu différente, à savoir en plaçant un signe dollar ($) devant leur nom :
Si deux variables du même nom existent, c'est-à-dire une variable d'environnement et une variable locale de l'interpréteur de commandes, c'est cette dernière qui est utilisée. En fait, les variables d'environnement existent sous la forme d'un fichier dans ENV:, une asignation à un répertoire dans le RAM Disk, qui est généralement copié depuis ENVARC: lors du démarrage. Vous pouvez donc rendre les variables d'environnement permanentes en copiant leur fichier de ENV: à ENVARC:. Vous pouvez également le faire en une seule étape :
...le mot clé "save" rend également la modification permanente et place le fichier variable dans ENVARC: et dans ENV:, de sorte qu'il survivra à un redémarrage. Maintenant, y a-t-il plus de choses à dire sur les variables ? Que faire si nous voulons écrire "$foo" sur la console, en tant que chaîne littérale, et que nous ne voulons pas parler de la variable ? Eh bien, nous utilisons le caractère d'échappement BCPL, qui est l'astérisque :
Maintenant, voici la partie la plus étrange : n'ai-je pas dit que le "*" ne fonctionne que comme caractère d'échappement entre guillemets ? Oui, mais... pour "*$" c'est différent, il fonctionne toujours :
Pourquoi cette incohérence ? Eh bien, l'interpréteur de commandes BPCL d'origine a été perfectionné à maintes reprises et, apparemment, Commodore ne savait pas très bien ce qu'il faisait, de sorte que la cohérence n'était apparemment pas une option, ou que l'incohérence n'a pas été reconnue. Dans l'ancien code Shell, l'analyse et l'expansion des variables et l'analyse des chaînes de caractères et des guillemets étaient gérées en deux étapes distinctes, de sorte que le code ne savait même pas si le "$" se trouvait à l'intérieur ou à l'extérieur d'un guillemet double. En parlant de guillemets doubles, saviez-vous qu'un guillemet double à l'intérieur d'une chaîne de caractères n'est pas compris comme un guillemet double ?
S'il y avait eu un espace devant le guillemet, il aurait agi comme un guillemet, mais ce n'est pas le cas. Tout langage de programmation sain aurait créé une erreur "chaîne non terminée" pour la ligne ci-dessus. AmigaDOS ne le fait pas. Un guillemet au milieu d'une chaîne n'est pas un guillemet. Pourquoi ? Personne ne le sait... Revenons aux variables : si vous souhaitez que le nom de la variable contienne d'autres caractères, tels que des espaces, ou si vous voulez vous assurer que le nom de la variable est séparé de la chaîne de caractères, vous pouvez inclure le nom entre accolades :
Sans les accolades, le Shell aurait essayé d'étendre la variable "foobar", qui n'existe pas. Si une variable n'existe pas, elle se développe simplement à partir de son nom, alors essayons ceci :
Maintenant, comment savoir si une variable existe ? C'est à cela que sert "$" ?
Ainsi, "$?var" se développe à 1 si la variable existe, et à 0 sinon, et le dernier exemple vient de montrer que les accolades fonctionnent également avec "$?" pour séparer le nom de la variable "foo" du reste de la chaîne "bar". 10. Exécution et alias Nous avons déjà parlé des variables et de leur utilisation dans les scripts, mais il y a d'autres endroits où des éléments de l'interpréteur de commandes sont remplacés par des éléments qui ressemblent à des variables, mais qui n'en sont pas. Tout d'abord, il y a la commande "alias", un élément intégré à l'interpréteur de commandes :
Cette commande crée un alias, c'est-à-dire un "nouveau nom pour une commande". Désormais, lorsque vous tapez "ls", l'interpréteur de commandes le remplace par "list". Où sont stockés les alias ? Dans la même liste que les variables locales, ce qui leur confère à peu près le même statut : ils sont locaux à l'interpréteur de commandes actuel. Ainsi, si vous voulez établir un alias pour tous les interpréteurs de commandes, vous devez le placer dans s:shell-startup où l'interpréteur de commandes le récupérera à chaque fois que vous en démarrerez un depuis le Workbench. Les alias peuvent également prendre des arguments. Ou plutôt, un seul argument. Sans autre préparation, les arguments de l'alias sont simplement ajoutés au contenu de l'alias, par exemple :
...se transforme en "list df0:" car l'alias est étendu. Si vous voulez placer les arguments de l'alias ailleurs, vous devez indiquer à l'interpréteur de commandes où il doit les placer en utilisant une paire de crochets (pourquoi pas "${arg}" ou "$*" ou quelque chose comme ça ? Oh, Commodore, cohérence, cohérence !). Par exemple :
...crée un nouvel alias "xd" (probablement l'abréviation de "hex dump") qui, lorsqu'il est développé, place ses arguments entre "type" et "hex". D'où :
...se développe en "type c:copy hex", et affiche un fichier hexadécimal de la commande "copy" dans C:. Ainsi, [] est une sorte de variable, mais pas vraiment, puisqu'il n'est utilisé que pour les alias et nulle part ailleurs. Les alias peuvent-ils être récursifs ? En partie :
...se développe en (normalement) "type list hex", parce qu'il développe l'alias "xd" et l'alias "ls". A moins que vous ne soyez dans C: ou que vous ayez un "list" dans le répertoire courant, cela créera bien sûr une erreur. Ce qui suit, cependant, ne fonctionne pas :
...qui se développera en "type xd". La règle est simple : dans une seule ligne d'argument, un alias donné ne peut être développé qu'une seule fois. C'est simplement parce que l'interpréteur de commandes pourrait sinon se retrouver dans une récursion infinie, en essayant d'étendre le même alias encore et encore. Alors, que faites-vous si vous voulez un "[" littéral quelque part dans un alias ? Vous avez deviné, mettez un astérisque devant. C'est le caractère d'échappement BCPL, et comme pour les variables, il fonctionne aussi en dehors des guillemets et pas seulement à l'intérieur des guillemets. Ensuite, nous avons un troisième élément qui a quelque chose de "presque comme mais pas tout à fait" des variables. Il s'agit de "execute", et des scripts Shell. Vous pouvez définir des arguments pour les scripts Shell en définissant un "modèle d'argument" dans la première ligne d'un script :
Il s'agit d'un script simple qui prend un seul argument, noté "keyname", et qui affiche ensuite le contenu du fichier en hexadécimal, un peu comme le faisait "xd". Maintenant, que font les crochets ici ? Il ne s'agit pas d'une redirection de commande, mais d'une "substitution d'argument". Encore une fois, une incohérence. "type ${filename} hex" aurait été bien plus agréable. À ce stade, l'interpréteur de commandes est complètement innocent. Les arguments ne sont même pas touchés ou jamais vus par l'interpréteur de commandes. Ce qui se passe ici, c'est toute la magie de la commande "execute" : elle analyse elle-même le script d'entrée avant de le transmettre à l'interpréteur de commandes, et définit son propre mécanisme de substitution des arguments, sans même utiliser ou regarder les variables de l'interpréteur de commandes. En fait, le signe "$" (dollar) que l'interpréteur de commandes utilise pour indiquer les variables a une signification complètement différente dans les scripts d'exécution. Il indique une valeur par défaut au cas où un argument n'est pas défini, c'est-à-dire :
...utilise "c:copy" par défaut si "filename" est laissé vide. Ai-je dit que Commodore était très incohérent ? Ai-je dit que cela signifie que la redirection des entrées/sorties dans les scripts exécutés est difficile parce que les crochets ont une autre signification ? L'auteur de execute devrait probablement être... exécuté ? Bon, au moins on peut faire quelque chose, à savoir définir d'autres caractères pour de telles fonctions :
...ce qui est beaucoup plus joli. Vous avez donc maintenant "{" et "}" comme séparateurs d'arguments, et la barre verticale comme indicateur par défaut, bien que cela signifie que vous devez épeler les variables sans les accolades, sinon vous obtenez des absurdités :
...ne fera pas ce qu'il devrait faire. C'est la catastrophe ! Chers ingénieurs de Commodore, il s'agit là d'un véritable non-sens. La prochaine fois que vous tenterez de "concevoir" quelque chose, réfléchissez-y à deux fois. Pourquoi ne pas simplement mettre les arguments des scripts dans des variables normales, et utiliser ces variables pour les passer dans les commandes ? Bon, pour être honnête, ce n'est pas tout à fait comme ça que ça a fonctionné. "execute" est apparu en premier, et il a été étendu de l'exécution pure de scripts à l'expansion d'arguments, puis aux variables Shell. Ainsi, Commodore aurait probablement dû rendre les variables cohérentes avec les arguments d'exécution, ce qui aurait signifié la perte de la redirection entrée/sortie. Non, attendez, ce n'est pas non plus une alternative... D'une manière ou d'une autre, quelqu'un a bousillé "execute" et il n'y a que des moyens limités pour le contourner. Seules certaines parties peuvent être contournées par le Shell, voir l'astuce "5. Skip et Lab". "execute" n'exécute pas réellement quelque chose. Il exécute d'abord un algorithme de substitution très simple, place le résultat de la substitution dans T:, puis exécute l'interpréteur de commandes sur le résultat analysé. Au lieu d'analyser manuellement les arguments, il aurait été plus agréable de laisser cela à l'interpréteur de commandes, mais alors... Pendant que nous y sommes : comment fonctionnent les commandes ".bra" ".ket" ".key" et ".dollar" ? En fait, elles ne fonctionnent pas. Elles ne font rien. Si vous regardez le code de ces commandes dans le source de l'interpréteur de commandes, elles ne font rien. Au lieu de cela, elles alimentent simplement l'analyseur d'arguments de "execute", de sorte que "execute" les lit et fait ce qui est indiqué, mais pas l'interpréteur de commandes. Si l'interpréteur de commandes trouve un ".bra", il hausse les épaules et dit "ok, tant mieux pour vous, ignorons ce genre de choses..." 11. Avez-vous fait un "sparwed" aujourd'hui ? Ou "h" n'est pas pour "hidden" Non, ce n'est pas une publicité pour un nouveau fétiche alimentaire. C'est sur les attributs de protection Amiga, ou du moins comment le (pas si) FastFileSystem les définit et le Shell les utilise. Les attributs de protection peuvent être ajoutés ou supprimés par la commande "protect", par exemple :
...active l'attribut de protection "s". Si vous remplacez "add" par "remove", l'attribut est à nouveau supprimé. Au total, nous en avons huit : hsparwed. Les attributs de protection sont interprétés en partie par le Shell, et en partie par le système de fichiers. Voici maintenant la signification, l'un après l'autre : Si "d" est activé, le fichier peut être supprimé, ou "délié". S'il n'est pas défini, l'opération de suppression du fichier échoue. Cela implique également que le fichier ne peut pas être ouvert pour être écrasé, c'est-à-dire que MODE_NEWFILE pour Open échoue si l'attribut est désactivé. Ce que cela signifie pour les répertoires dépend en grande partie du système de fichiers. Le FFS actuel interprète "d" comme "le répertoire ne peut pas être supprimé", mais vous pouvez y créer des fichiers. Avant de passer à "e", commençons par "w" : s'il n'est pas activé, cela signifie qu'on ne peut pas écrire dans le fichier. Enfin, presque. Vous pouvez ajouter quelque chose au fichier, mais vous ne pouvez pas l'écraser, du moins c'est ainsi que le FFS l'interprète actuellement, et j'appellerais probablement cela un bogue, car cela signifie que vous pouvez écrire dans un fichier, même si "w" n'est pas activé. Le RAM Disk a le même problème. Il est intéressant de noter que cela a probablement changé avec le FFS lorsqu'il a été réimplémenté en assembleur, à partir du code BCPL d'OFS. Pour les répertoires, "w" devrait probablement impliquer que vous ne pouvez pas créer de fichiers à l'intérieur. Mais ce n'est pas le cas. En fait, je crois me souvenir que les premières versions du FFS ne stockaient pas de drapeaux (attributs) pour les répertoires. Indépendamment de "w", les fichiers ou les répertoires peuvent être supprimés, ce qui donne au moins un peu de cohérence. "r" signifie que le fichier peut être ouvert en lecture. Au moins pour les fichiers. Pour les répertoires, on est tenté de dire que cela signifie que le contenu du répertoire ne peut pas être lu, mais AmigaOS n'est pas Linux, et la cohérence n'est pas son point fort de toute façon, donc "r" ne veut rien dire pour les répertoires. Il en va de même pour "e". En fait, "e" n'est pas du tout interprété par le système de fichiers. Il n'est interprété que par l'interpréteur de commandes. Si l'attribut "e" est activé, l'interpréteur de commandes considère un fichier comme un "exécutable binaire" et le charge. Ou plutôt, il essaie de le faire. En cas d'échec, une erreur est affichée. En fait, si "e" et "s" sont tous deux activés, "s" est prioritaire et "e" est ignoré. En fait, ce qui précède n'est pas tout à fait vrai : si "e" est activé dans un répertoire, l'interpréteur de commandes n'essaie évidemment pas d'exécuter le répertoire (comment ?). Au lieu de cela, il ignore tous les autres attributs et change implicitement de répertoire. Ou plutôt, il charge la commande "cd" à partir de sa liste de commandes intégrée, puis lui passe l'exécution. Les attributs "rwed" sont en fait stockés à l'envers dans le descripteur de fichier - si les attributs sont clairs, ils sont affichés comme "set", et vice versa. Ainsi, si vous ne faites rien d'autre avec le fichier, la valeur par défaut est "rwed". En fait, ce n'est pas une très bonne valeur par défaut. "rwd" aurait été mieux, car il aurait évité que vous essayiez d'exécuter un fichier texte lambda. Commodore dans toute sa splendeur, une fois de plus. Que se passe-t-il si "e" n'est pas activé ? L'interpréteur de commandes vérifie si le fichier peut être ouvert par un datatype, et si c'est le cas, il vérifie si la variable "$VIEWER" est définie, puis il passe le contrôle à la commande enregistrée dans cette variable. Ainsi, si "$VIEWER" est définie, par exemple à "Multiview", vous pouvez voir des images, du texte, des fichiers AmigaGuide... sur l'interpréteur de commandes en tapant simplement leurs noms. Ce n'est pas sympathique, ça ? L'attribut suivant est l'attribut "a". Il ne fait pas grand-chose, si ce n'est qu'il est effacé à chaque fois que le fichier est modifié. Ainsi, on peut l'activer par :
...et chaque fois qu'un programme modifie "foo", l'attribut "a" disparaît. Cela semble inutile ? Non, ce n'est pas le cas. Cela signifie qu'un programme de sauvegarde peut ignorer tous les fichiers dont l'attribut "a" est activé, car ils n'ont pas été touchés depuis, et pendant qu'il copie tous les programmes sur un autre disque, il active en même temps l'attribut "a" de tous les fichiers. Ainsi, il ne copie que ce qui n'a pas été modifié - ce qui est très utile. En fait, c'est exactement ce que fait "SortCopy" (sur Aminet). Le "s" est pour "script". C'est l'un des attributs dont seul le Shell se préoccupe, et non le système de fichiers. S'il est activé, le Shell tente d'exécuter le fichier en tant que "script", indépendamment de l'attribut "e". Pour ce faire, il vérifie d'abord les deux premiers caractères du fichier. S'il s'agit de "/*", le fichier est transmis à ARexx. S'ils sont ";!" ou "#!", le fichier script est transmis à la commande Shell qui suit ces deux caractères magiques. C'est ce que Linux fait tout le temps, ce "#!" est le "hash-bang" magique. AmigaOS l'a aussi. Si ni "/*", ni "#!", ni ";!" ne se trouve dans la première ligne, alors AmigaOS passe le contrôle à "execute". Ce qui, comme nous le savons maintenant, ne fait rien de spécial si ce n'est qu'embrouiller le fichier une fois de plus en substituant des arguments d'une manière complètement incohérente, et ensuite renvoyer le résultat dans le Shell pour exécution. "execute" ne fait pas le sale boulot lui-même. Il ne fait que créer le désordre... L'attribut "s" et tous les attributs suivants sont relativement nouveaux. Le Shell BCPL ne les avait pas, et ils sont arrivés relativement tard. "p" est pour "pure". Ce qui ne veut pas dire autant qu'on pourrait le croire. C'est une invention du "AmigaDOS Replacement Project" (ARP) dont nous avons déjà entendu parler. L'idée était bonne : pourquoi devons-nous charger des commandes depuis le disque à chaque fois que nous en avons besoin ? Au lieu de cela, si une commande ne change pas son exécutable, sa section de données, et est réentrante - peut être appelée à partir d'elle-même et par plusieurs tâches à la fois - son code peut simplement être gardé en mémoire, au lieu d'avoir à le charger du disque vers la mémoire à chaque fois. ARP disposait d'un mécanisme à cet effet : le fichier était vérifié, et si la somme de contrôle ne correspondait pas, il était rejeté la fois suivante. Bien sûr, tout cela était trop pour Commodore, et la somme de contrôle a donc disparu. Au lieu de cela, il s'agit simplement d'une promesse. Si "p" est activé, la commande fait la promesse suivante : "Je jure par la présente que je ne modifierai pas mes données et mon code. Et si je le fais, je risque de me planter la prochaine fois". Bon travail, c'est une excellente interface stable. Par conséquent, si "p" est activé, vous pouvez charger la commande dans la liste des résidents du DOS (nous y reviendrons plus tard), et le Shell la trouve là, et l'exécute à partir de là plutôt que de la charger à partir du disque. Et si "p" n'est pas activé, vous pouvez l'activer avec "protect" néanmoins et essayer ce qui se passe si vous la rendez résidente... Errr, il vaut mieux ne pas le faire. Seul l'auteur du programme peut le savoir et peut donc définir "p". Et s'il n'est pas défini, vous feriez mieux de ne pas vous en mêler et de ne pas le rendre résident. C'est ainsi que l'on peut rendre la startup-sequence un peu plus rapide, notamment en rendant résidentes les commandes souvent utilisées :
Ainsi, elles ne sont pas chargées encore et encore. Et en fait, il y a une meilleure façon de faire cela, sans "résident" : Ce qui nous amène au dernier élément, souvent mal compris : "h". Certains programmes le lisent comme "caché" et ne listent pas les entrées de répertoire qui ont cet attribut activé. C'est tout simplement faux. "h" ne signifie pas "caché", "h" signifie "conserver". Cela signifie ce qui suit : Si un fichier a les attributs "h", "p" et "e" activés, de sorte qu'il promet d'être pur et peut être exécuté, la prochaine fois que l'interpréteur de commandes chargera la commande, il la fera résider toute seule. Ainsi, les lignes ci-dessus peuvent être évitées dans la startup-sequence simplement en mettant l'attribut "h" pour toutes les commandes que vous voulez garder en mémoire de toute façon, et que vous avez prévu de rendre résidentes, sauf que vous n'avez plus besoin d'une commande résidente. Malheureusement, en raison de contraintes de taille, cette fonctionnalité intéressante a été "jetée" du Shell V40 à la dernière minute, et le Shell d'AmigaOS 3.1 ne la gère donc pas. La version 3.9 le fait, car il n'y a pas de contrainte de taille de ROM, et "h" signifie en réalité "hold" (conserver). 12. Comment aimeriez-vous votre console aujourd'hui ? Bleue, à l'anglaise, à point ou bien cuite ? (CON:, RAW: et VNC:) Dans cette astuce, j'aimerais à nouveau parler de la console, ou de ce que l'on appelle CON:, RAW: ou VNC:. En fait, vous connaissez peut-être les deux gestionnaires de console qu'AmigaOS propose : CON: et RAW:. Pour CON:, chaque ligne est mise en mémoire tampon, le périphérique logique attend et donne à l'utilisateur la possibilité d'éditer la ligne complète, jusqu'à ce qu'il appuie sur "Entrée", et à ce moment-là, la ligne entière est transférée au programme qui attend une entrée ; généralement le Shell, comme on l'appelle. On appelle cela aussi le mode "cooked" (cuit), car l'entrée utilisateur est "bien préparée jusqu'à ce qu'elle soit servie", à savoir au programme récepteur. C'est un nom qui vient d'Unix, et l'Amiga l'a repris. Ensuite, nous avons RAW:. Contrairement à CON:, il ne fournit aucun type de mise en mémoire tampon de ligne. Chaque appui sur une touche est transférée au programme récepteur, et l'appui sur une touche n'est même pas affichée sur l'écran. Au lieu de cela, le programme récepteur doit le faire. Comme AmigaShell ne le fait pas, RAW: n'est pas utile pour le Shell. Certains Shells tiers ont fourni de meilleures fonctionnalités d'édition, et l'ont fait en implémentant tout l'historique et en s'éditant eux-mêmes, en s'appuyant sur RAW: plutôt que sur CON:, car les services d'édition de CON: sont (ou étaient) plutôt limités. Au moins jusqu'à ViNCEd, qui offre un éditeur très riche et fait bien plus que CON: d'ailleurs. Ce qui est probablement moins connu, c'est que CON: et RAW: sont deux "saveurs" du même gestionnaire de console. On peut ouvrir un gestionnaire de console en mode "raw" (cru ou brut), et le passer en mode "cooked" (cuit) par une commande spécifique, et aussi revenir en arrière. Cela fonctionne presque, pour CON: du moins. Dans une fenêtre RAW, un programme peut, par exemple, demander à la console d'envoyer des informations chaque fois que l'utilisateur redimensionne la fenêtre. En mode "cooked" (cuit), cela ne fonctionne pas. En mode "raw" (cru), un programme peut demander à la console d'envoyer une chaîne lorsque l'utilisateur clique quelque part. En mode "cooked" (cuit), cela ne fonctionne pas. Ou du moins, ne fonctionnait pas. Bien sûr, ViNCEd ne fait aucune différence et peut être à la fois "raw" (cru) ou "cooked" (cuit) - ou comme on l'appelle ici "rare" (bleu) ou "well done" (bien cuit), comme si on ne "cuisait" pas de steak. Dans ViNCEd, tout cela fonctionne correctement et vous recevez de tels messages, peu importe si la console est "raw" (crue) ou "cooked" (cuite) - euh - "rare" (bleu) ou "well done" (bien cuite). Si un programme demande des informations sur les redimensionnements de fenêtre, il les obtient. Bien sûr, le mode "cooked" (cuit), euh, "well done" (bien cuit) de ViNCEd est vraiment très riche : il offre non seulement la mise en mémoire tampon des lignes, mais aussi l'édition en plein écran. Il fait aussi l'expansion des tabulations et la gestion des tâches. Il conserve un historique des commandes. C'est probablement tout ce qui devrait être mis dans le Shell, car c'est le Shell (et non la console) qui gère ce qui se passe sur la ligne de commande. Ce n'était pas le cas, car l'AmigaShell a évolué plus lentement que la console. Comme je n'ai pas aimé cette architecture non plus, et que je voulais ouvrir la possibilité de déplacer l'extension des tabulations, l'historique et le contrôle des tâches dans le Shell, ViNCEd a quatre modes au lieu de deux : "rare" (bleu), "english" (à l'anglaise), "medium" (à point) et "well done" (bien cuit). Le mode "medium" (à point) est légèrement moins cuit que "bien cuit" : la console gère toujours l'édition de l'écran complet, mais laisse l'extension des tabulations, la gestion des tâches et l'historique au Shell. Ainsi, ce qui se passe ici est que - au lieu d'étendre les noms de fichiers avec TAB - la console récupère le nom du fichier à étendre à partir de la console, place le nom du fichier dans une séquence de contrôle et transmet la demande au Shell. Il en va de même pour le contrôle des tâches et l'historique. Ainsi, c'est le Shell qui doit recevoir ces séquences de contrôle et agir en conséquence. Bien sûr, l'AmigaShell est actuellement incapable de le faire, donc le mode "medium" (à point) reste actuellement inutilisé. Ensuite, nous avons le mode "english" (à l'anglaise), qui est légèrement plus cuit que "raw" (cru), euh, "rare" (bleu). Ce mode fonctionne de manière très similaire au mode "raw" (cru), à ceci près que les fonctions du Shell telles que l'extension TAB, l'historique et le contrôle des tâches reçoivent des séquences de contrôle spéciales, permettant à l'utilisateur de déplacer ces fonctions vers d'autres touches du clavier, et le Shell (à nouveau) reçoit ces séquences de clavier au lieu des séquences "crues pures". Ainsi, si l'utilisateur appuie sur "TAB", une console "raw" (crue) enverrait le caractère ASCII pour TAB (08). Dans le mode "english" (à l'anglaise), la console enverrait plutôt une séquence de contrôle indiquant "Hé, l'utilisateur veut faire l'extension TAB", et si l'utilisateur redéfinit le clavier, la même fonction serait liée à - par exemple - F1, et TAB continuerait à envoyer le caractère ASCII pour la tabulation. Ainsi, le mode "english" (à l'anglaise) fait la distinction entre les "fonctions du clavier" qui peuvent être liées à d'autres touches, et les "codes du clavier bruts" qui restent liés aux touches natives, à moins qu'ils ne soient remplacés par une fonction. La redéfinition du clavier reste donc, en mode "english" (à l'anglaise), à la console, l'exécution de telles séquences au Shell. Bien entendu, ce mode est également totalement inutilisé à ce jour. Il est juste présent. Maintenant finalement, comment la console distingue-t-elle réellement tous ces modes ? Essentiellement, c'est dans la liste de montage, c'est-à-dire la partie dans DEVS:DOSDrivers qui définit comment un gestionnaire est chargé. Pour l'ancienne console CON:, ce fichier est en ROM (ou plutôt, son équivalent binaire). Pour ViNCEd, il est dans DEVS:DOSDrivers. Pour le mode "well done" (bien cuit), ce fichier se présente comme suit :
Il est intéressant de noter que le gestionnaire ne se trouve pas dans L:, mais plutôt dans LIBS: car c'est aussi une bibliothèque (une astuce intéressante, il n'y a qu'un seul fichier pour les deux fonctions, ce qui est tout à fait possible). Pour une console "raw" (crue) (généralement appelée VNR: au lieu de VNC: ou NEWCON:), cela se lit comme suit :
La différence est dans la ligne "startup". Startup = 0 (ou pas de démarrage) est "well done" (bien cuit), Startup = 1 est "raw" (cru). Startup avec "2" et "3" sont les deux nouveaux modes cachés. En fait, la même astuce, à savoir utiliser "Startup" pour basculer entre différentes "saveurs", est également utilisée dans différents bords du système d'exploitation. SER:, PAR: et PRT: sont tous implémentés par le même gestionnaire, à savoir le Port-Handler. Il se trouve dans L:. La seule différence entre les trois saveurs est la valeur de "Startup". Bien sûr, vous ne le voyez généralement pas car il n'y a pas d'entrée dans la liste de montage. Au lieu de cela, il existe un équivalent binaire de cette entrée de montage intégré dans la ROM. Il existe cependant un petit programme qui affiche ces paramètres de montage. Il s'appelle "Devices" et peut être trouvé dans Aminet. Il vous montre à quoi ressemblent les entrées, même sans liste de montage explicite à consulter. 13. Rediriger la sortie de "execute" vers un fichier ? Il sera probablement temps d'élargir un peu ce tutoriel avec plus de "connaissances". Saviez-vous que vous ne pouvez pas rediriger la sortie de "execute" vers un fichier ? Ainsi, si vous écrivez un petit script comme suit : .KEY DIR List <DIR> ...enregistrez cela sous "T:myList" puis lancez la commande "execute T:List", puis, étonnamment, un...
...ne redirige pas la sortie du script vers "result". Au lieu de cela, la liste des répertoires apparaît simplement sur le terminal. Bizarre ? Enfin, peut-être, à moins que vous ne sachiez pourquoi. Le fait est que ce n'est pas réellement "execute" qui exécute le script. Pas du tout. "execute" analyse simplement le script (de manière incorrecte, en fait, jusqu'à une version récente), crée un fichier temporaire dans T:, puis laisse le Shell faire l'exécution. Donc tout le "travail sanglant" est laissé au Shell. "execute ne fait pas grand-chose du tout. Au moment où "execute" revient, l'exécution du script n'a même pas commencé, mais la redirection de sortie est annulée par le Shell avant même que le Shell n'essaie de lire le fichier temporaire dans T:. Il en va de même bien sûr pour la redirection d'entrée, ou la redirection de console (le truc avec "*>", voir l'astuce 2. La redirection). Du moins jusqu'à récemment car j'ai corrigé cela : j'ai fait en sorte que "c:execute" soit résident (idéalement dans la startup-sequence), puis ouvre un nouveau Shell, et ensuite (et seulement alors) la redirection d'entrée et de sortie fonctionne, même pour "execute". C'est plus une solution de contournement qu'une vraie solution, compte tenu de l'implémentation ci-dessus, mais au moins un désagrément en moins. Au fait : le script ci-dessus ("T:myList") contient au moins un problème potentiel. Le voyez-vous ? Pouvez-vous le corriger ? Nous en parlerons probablement davantage dans une prochaine astuce... 14. Execute Revenons à "execute", comme annoncé précédemment. Vous le savez probablement, les scripts Shell peuvent prendre des arguments, et tout comme les "vraies" commandes Shell, les scripts Shell utilisent également un "modèle" qui définit le type des arguments, s'ils sont obligatoires ou facultatifs, s'il s'agit de commutateurs, de bascules et d'éléments similaires. C'est ce que fait la pseudo-commande ".key" sur la première ligne d'un script :
...serait un simple adaptateur de la commande "copy", où "FROM" est un argument obligatoire, et plusieurs d'entre eux peuvent être spécifiés. "/A" signifie "obligatoire", et "/M" signifie "un ou plusieurs d'entre eux". "TO" est également un argument obligatoire, et "CLONE" est un commutateur. Identique aux commandes binaires, la lettre derrière la barre oblique définit le type et les exigences de l'argument, et donc...
...prendrait un argument numérique et refuserait tout ce qui n'est pas un nombre. C'est ainsi que cela est documenté et que fonctionnent les arguments. "execute" utilise la fonction dos.library "ReadArgs()" pour analyser les arguments, donc tous les sympathiques types "/" sont gratuits. Malheureusement, aucun des exemples ci-dessus ne fonctionne si vous les essayez avec la commande "execute" d'origine (v37), et c'est celle qui est fournie avec le Workbench 3.1. Maintenant, comment est-ce possible ? N'ai-je pas juste dit que "execute" utilise la fonction dos.library "ReadArgs()", et que pour cette raison l'analyse des arguments devrait fonctionner, car "ReadArgs()" fonctionne certainement ? Pourquoi cela ne fonctionne-t-il pas pour "execute" alors ? Eh bien, cela nécessite un peu de contexte. Ce que fait ReadArgs(), c'est qu'il remplit un tableau de pointeurs de chaîne, un pour chaque argument. Ou du moins, c'est ce que "rdargs()", le pendant BCPL dans Tripos, faisait à l'époque du Kickstart 1.3. Donc le "execute" en BCPL du système 1.3 fonctionnait parfaitement. Le problème est que le Kickstart 2.0 a ajouté quelques nouveaux types d'arguments. Ainsi, par exemple, "/N" pour "argument numérique" est nouveau, et "/M" pour "arguments multiples" est nouveau. Il n'existait pas dans le système 1.3, et ces deux types ont été ajoutés par ARP, l'Amiga Replacement Project, et sont devenus plus tard une partie d'AmigaDOS. Ce que ARP a également fait, c'est qu'il a changé un peu la convention de fonctionnement de "ReadArgs()". Ainsi, par exemple, pour un argument "/N", il est bien sûr beaucoup plus pratique de renvoyer le nombre directement au lieu d'une chaîne, donc "ReadArgs()" remplit un pointeur vers un LONG au lieu d'un pointeur vers un tableau de caractères. C'est certainement beaucoup plus pratique que de devoir analyser le nombre à nouveau dans le programme - ReadArgs() peut déjà le faire. De même, pour "/M", ReadArgs() ne laisse pas de pointeur de chaîne dans son vecteur de retour, mais renvoie plutôt un pointeur vers un tableau de chaînes, c'est-à-dire un pointeur vers un pointeur de caractères. Il doit le faire, car "/M" peut prendre plusieurs arguments sur la console, donc une chaîne ne suffit pas. Malheureusement, personne n'a dit "execute" sur la syntaxe modifiée, et personne n'a osé toucher aux sources de "execute" non plus. Ainsi, si le ".KEY" contient un argument "/N", "execute" v37 (version officielle dans AmigaOS 3.1, notez qu'il n'y a pas de "execute" v40) attend un pointeur de chaîne dans les arguments, mais trouve juste un pointeur vers un nombre à cet endroit. Et fait, des choses étranges et merveilleuses, dont une "alerte Enforcer" est probablement la plus inoffensive. Ouille ! Ainsi, quelqu'un (Software Distillery, en l'occurrence) a modifié l'interface d'une fonction du système d'exploitation derrière le "dos d'execute", et a ainsi cassé une commande. Ou plutôt, ils ont oublié de mettre à jour "execute". Malheureusement, ce changement signifie que, maintenant, "execute" doit également être conscient du type d'arguments qu'il doit analyser et doit reconvertir les nombres ou les chaînes multiples en une seule chaîne, à savoir ceux dont il a besoin pour la substitution des paramètres du script, c'est-à-dire les éléments entre crochets. Par conséquent, pour "execute" v45 (et aussi v44), deux choses se produisent malheureusement deux fois : d'abord, ReadArgs() convertit les chaînes en nombres pour les arguments "/N" (car il le fait toujours), et "eExecute" doit les reconvertir (pour la substitution de paramètres) de telle sorte que la commande dans le script doit les reconvertir de chaîne en nombre à nouveau. Il existe d'autres types comme celui-ci : "/S" laisse simplement un indicateur booléen au lieu d'une chaîne, donc "execute" doit réinsérer le nom du commutateur au lieu de la valeur booléenne. Il en va de même pour "/T", qui n'est en fait pas vraiment un commutateur, mais prend deux valeurs, "ON" ou "OFF", ou alternativement "YES" ou "NO". La documentation n'est pas tout à fait appropriée. "/M" renvoie un pointeur vers un tableau de chaînes, donc "execute" doit fusionner toutes les chaînes ensemble. Et enfin, n'oubliez pas que "execute" doit également prendre en charge les arguments de guillemets appropriés avec des espaces à l'intérieur - et l'échappement de l'astérisque et du guillemet dans les chaînes elles-mêmes. Nous avons déjà eu ce problème. Donc, c'est en fait un peu plus compliqué qu'il n'y paraît.
|