Outils pour utilisateurs

Outils du site


issue106:tutoriel1

In the early days of computers, a company called Digital Equipment Corporation (DEC) created its 32-bit VAX computer using openVMS as its operating system. Because a VAX/VMS computer is so reliable, there are today - after more than 25 years - still a large number of them in use. But in the end, even these reliable computers will have to be replaced. As described in part 1, you could migrate from VAX/VMS to Linux because the way Linux works is largely compatible with VAX/VMS. If you use Pascal as your programming language, you will find that Lazarus/Free Pascal is a good replacement. But there are technical functions used in VMS with no apparent replacement in Linux. In this article, I will describe how I replace logicals. File-system philosophy? To understand logicals, I have to explain the philosophy behind the file-system of VMS. In Linux there is one “device” ('/') and all physical devices are mounted to become a virtual folder (the mounting points). VMS uses a totally opposite approach: Devices are separate items, and you are allowed to create a new (virtual or pseudo) device pointing to a folder.

Au début des ordinateurs, une société appelée Digital Equipment Corporation (DEC) créa son ordinateur 32-bit VAX avec open VMS comme système d'exploitation. Comme un ordinateur VAS/VMS est vraiment fiable, aujourd'hui, après plus de 25 ans, ils sont encore très nombreux à être en service. Mais, à la longue, mêmes ces ordinateurs fiables devront être remplacés. Comme décrit dans la Partie 1, vous pourriez migrer de VAX/VMS vers Linux, car le fonctionnement de Linux est en grande partie compatible avec VAX/VMS. Si votre langage de programmation est Pascal, vous trouverez que Lazarus/Free Pascal est une bonne alternative. Mais il y a des fonctions techniques dans VMS sans remplacement évident sous Linux. Dans cet article, je décrirai comment je remplace des « logicals ».

La philosophie du système de fichiers ?

Pour comprendre les « logicals », je dois vous expliquer la philosophie derrière le système de fichiers de VMS. Sous linux, il y a un « dispositif » ('/') et tous les dispositifs physiques sont montés pour devenir un dossier virtuel (les points de montage). VMS utilise une approche diamétralement opposée : les dispositifs sont des éléments séparés et vous avez le droit de créer un nouveau dispositif (virtuel ou pseudo) qui pointe vers un dossier.

As an example, this is how you would address a file in VMS: DEVICE:[DIRECTORY.SUBDIR1.SUBDIR2]FILENAME.EXT;123 The same file in Linux would look like: /mountingpoint/directory/subdir1/subdir2/filename.ext Note all the uppercase characters in VMS, and the number at the end (the file version, described in part 4). What are logicals? A logical is a name/value pair maintained by the system, consisting of strings of up to 255 characters. As with eventflags, the reason why they are important is they are used consistently throughout the entire system in VMS. Whenever you access a device, the system will first look if the device name you specified is a logical. If so, the device name is replaced with the value of the logical (in VMS we say: the logical is translated), and that process is repeated up to 10 times (to prevent loops).

Par exemple, voici le chemin d'un fichier dans VMS :

DEVICE:[DIRECTORY.SUBDIR1.SUBDIR2]FILENAME.EXT;123

Le même fichier dans Linux serait :

/mountingpoint/directory/subdir1/subdir2/filename.ext

Remarquez les majuscules dans VMS et le numéro à la fin (la version du fichier, décrite dans la partie 4).

Que sont les logicals ?

Un logical est une paire nom/valeur maintenue par le système, composée de chaînes contenant jusqu'à 255 caractères. Comme pour les eventflags, ils sont importants parce qu'ils sont utilisés régulièrement partout dans le système VMS. Chaque fois que vous accéderez à un dispositif, le système regardera d'abord si le nom du dispositif que vous avez spécifié est un logical. Si c'est le cas, le nom du dispositif est remplacé par la valeur du logical (dans VMS, nous disons que le logical est traduit) et ce procédé est répété jusqu'à 10 fois (pour empêcher des boucles).

This mechanism is very versatile. You can influence what device is accessed by changing the corresponding logical (give it another value), and the value can contain more information than just a device: it can also contain the path to a folder (directory), or other information like TRUE, FALSE, OPEN, CLOSED, etc, etc. More than one translation. The value is not limited to one string. You are allowed to specify more than one string, separated by a comma to get a search list. If the system does not find the file in the folder resulting from the first “translation”, it will continue the search by following the second “translation”, and the third, and so on. Though very useful, be warned: this can have a nasty side-effect. If you access a file through a search list, and you don't have permission to access the file (due to file protection, root is the owner, etc), the system will continue the search, but does not find it in the other folders. Then it reports to you the FINAL error of “file not found”. But you can see the file and you will think: is that computer crazy or am I? Luckily, neither; the fault is in the message. It should be “access denied” (VMS: “file protection violation”), and I thought VMS was perfect!

Ce mécanisme est très souple. Vous pouvez modifier le dispositif auquel vous accédez en changeant le logical correspondant (lui donner une autre valeur), et la valeur peut contenir plus d'informations qu'un simple dispositif : il peut aussi contenir le chemin vers un dossier (répertoire) ou d'autres informations comme TRUE, FALSE, OPEN, CLOSED, etc., etc.

Plus d'une traduction.

La valeur n'est pas limitée à une seule chaîne. Vous pouvez spécifier plus d'une chaîne, séparée par une virgule pour avoir une liste de choses à rechercher. Si le système ne trouve pas le fichier dans le dossier qui résulte de la première « traduction », il continuera sa recherche en suivant la seconde « traduction », puis la troisième et ainsi de suite. Quoique très utile, soyez prévenu : cela peut avoir un effet secondaire désagréable. Si vous accédez à un fichier au moyen d'une liste de choses à rechercher et que vous n'avez pas les droits pour accéder au fichier (il est protégé, son propriétaire est root, etc.), le système continuera sa recherche, mais ne le trouvera pas dans les autres dossiers. Puis il vous indiquera l'erreur FINAL de « file not found » (fichier introuvable). Mais vous voyez le fichier et vous vous demandez : est-ce moi ou l'ordinateur qui est fou ? Ni l'un ni l'autre heureusement ; la faute est dans le message d'erreur. Cela devrait être « Accès non autorisé » (VMS : « file protection violation » (violation de la protection du fichier)) et dire que je pensais que VMS était parfait !

In part 1, I mentioned that I have had bad experiences with frequent, but random, errors on Charon-VAX. These errors involved the translation of a logical which contained a search list. One in every hundred or so translations failed. It was impossible to find what was wrong, because the next time the same logical was translated, there was no error. It was because of the randomness of the error that we decided not to use Charon-VAX on our production computers, only the development computers were emulated. Not as simple as it sounds… The implementation of logicals in VMS is very complex: a logical is part of a table and there are many different tables. Which tables and the order in which the system looks for the logical is specified in yet another logical. I will not try to explain all of this – it would be outside the scope of this article. Let me only mention that the most used tables are process, job (session), group (GID) and system tables, and they are searched in that order. This makes it possible to create a pointer to a folder for your group in the group table, and temporarily create the same pointer to a different folder for test purposes in your job or process table for your own use - without disturbing the other users or services, as would be the case when using hard links. Examples of use To clarify this complex instrument I will show some examples of how logicals are or could be used: • In Linux, the system is located on '/'; in VMS the system is on disk “SYS$SYSDEVICE”. • In VMS, the logical “TT” points to the terminal you work on. This could be a physical terminal (TTAxxx), a network terminal using the LAT protocol (LTAxxx), a telnet terminal (TNAxxx), an Xterm terminal (FTAxxx), or a remote terminal using the DecNet protocol (RTAxxx). Your program does not need to know which device started the program; it just reads from and writes to “TT:” (note the colon, this signals that TT is a device, not a file). Do not confuse this with stdin and stdout. These are file handles and they open the file “TT:”.

Dans la partie 1, je mentionné que j'ai eu de mauvaises expériences avec des erreurs fréquentes, mais aléatoires, sur Charon-VAX. Ces erreurs impliquaient la traduction d'un logical qui contenait une liste de recherche. Une sur cent traductions échouait. Il était impossible de trouver ce qui était faux, parce que la fois suivante où la même logique était traduite, il n'y avait pas d'erreur. C'est à cause du caractère aléatoire de l'erreur que nous avons décidé de ne pas utiliser CHARON-VAX sur nos ordinateurs de production, seuls les ordinateurs de développement ont été émulés.

Pas aussi simple que ça en a l'air…

L'implémentation de logicals dans VMS est très complexe : un logical fait partie d'une table et il y a beaucoup de tables diverses. Encore un autre logical précise dans quelles tables et quel ordre le système doit chercher le logical. Je n'essaierai pas d'expliquer tout ceci, car je dépasserais le cadre de cet article. Je vais dire seulement que les tables les plus utilisées sont process [processus], job (session) [tâche], group (GID) [groupe] et system [système], et que les recherches se font dans cet ordre-là. Cela rend possible la création d'un pointeur vers un dossier pour votre groupe dans la table group et la création temporaire du même pointeur vers un autre dossier à des fins de test, dans votre table job ou process pour votre seule utilisation, sans déranger les autres utilisateurs ou services, comme ce serait le cas si vous utilisiez des liens matériels.

Exemples d'utilisation

Pour clarifier cet outil complexe, je donnerai quelques exemples de la manière d'utiliser les logicals ou comment on pourrait les utiliser :

• Dans Linux, le système se trouve sur « '/' » ; dans VMS, le système est sur disque « SYS$SYSDEVICE ».

• Dans VMS, le logical « TT » pointe vers le terminal sur lequel vous travaillez, que ce soit un terminal physique (TTAxxx), un terminal réseau utilisant le protocole LAT (LTAxxx), un terminal telnet (TNAxxx), un terminal Xterm (FTAxxx) ou un terminal à distance utilisant le protocole (RTAxxx). Votre programme n'a pas besoin de connaître le dispositif qui l'a démarré ; il ne fait que lire sur et écrire vers « TT: » (remarquez le deux-points qui indique que TT est un dispositif, pas un dossier). À ne pas confondre avec stdin et stdout. Ceux-ci sont des poignées de dossier qui ouvrent le fichier « TT: ».

• Suppose you made a process that reads files with file-type XML from 3 folders (placed there by 3 other process), and put the result in another. You could define 2 group logicals pointing to these folders: define/group INPUT_FOLDER SYS$DISK3:[QUEUES.FROM_PROCESS_1],SYS$DISK3:[QUEUES.FROM_PROCESS_2],SYS$DISK3:[QUEUES.FROM_PROCESS_3] define/group OUTPUT_FOLDER SYS$DISK4:[PROCESSED_DATA] Then your process would look for input using the file specification INPUT_FOLDER:*.XML, and write the result to OUTPUT_FOLDER:RESULT_'DATE'_'TIME'.DAT Now you made a change to your process and want to test it. Reading files from the input folder(s) would interfere with your system, so you define 2 new logicals at job level: define/job INPUT_FOLDER MYDISK0:[TEST_QUEUE] define/job OUTPUT_FOLDER MYDISK0:[RESULTS] Now you can run the new process and test it by copying files to MYDISK0:[TEST_QUEUE] and examine the resulting files in MYDISK0:[RESULTS].

• Supposons que vous ayez créé un processus qui lit des fichiers de type XML dans trois dossiers (où ils ont été placés par trois autres processus), puis mis le résultat dans un autre dossier. Vous pourriez définir 2 logicals de type group qui pointent vers ses dossiers :

define/group INPUT_FOLDER SYS$DISK3:[QUEUES.FROM_PROCESS_1],SYS$DISK3:[QUEUES.FROM_PROCESS_2],SYS$DISK3:[QUEUES.FROM_PROCESS_3]

define/group OUTPUT_FOLDER SYS$DISK4:[PROCESSED_DATA]

Votre processus chercherait alors des entrées en utilisant la spécification de fichier INPUT_FOLDER:*.XML, puis il écrirait le résultat dans OUTPUT_FOLDER:RESULT_'DATE'_'TIME'.DAT

Mais vous avez modifié votre processus et voulez le tester. Lire des fichiers à partir de dossier(s) input pourrait perturber votre système ; vous définissez donc deux nouveaux logicals au niveau job :

define/job INPUT_FOLDER MYDISK0:[TEST_QUEUE]

define/job OUTPUT_FOLDER MYDISK0:[RESULTS]

Vous pouvez maintenant exécuter le nouveau processus et le tester en copiant des fichiers sur MYDISK0:[TEST_QUEUE] et en regardant les fichiers résultants dans MYDISK0:[RESULTS].

• Suppose you measure the weight of your product with an old scale, and then you purchase a new scale. In the first few weeks, you want to be able to switch between the scales. You could have 2 different executables, and stop the process that reads the scale and restart it using the other executable when you want to switch scale, or you could put the following code in your program: new_scale := $TRNLNM (“NEW_SCALE”); (TRNLNM = translate logical name) if new_scale = 'ACTIVE' then weight := read_new_scale() else weight := read_old_scale(); You could use the following terminal command to use the new scale: define/system NEW_SCALE ACTIVE and, to use the old scale: define/system NEW_SCALE INACTIVE (or 'FALSE' or 'USE_OLD_SCALES' or anything else) To use version control, I create a new folder tree for every version and use a logical to specify which version is active. As an example: My current version is 7.2, so I create the folder APP$DISK:[V7-02] and the sub-folders DATA and EXEC: APP$DISK:[V7-02.EXEC] and APP$DISK:[V7-02.DATA]

• Supposons que vous mesurez le poids de votre produit avec une vieille balance (scale) et que vous achetez ensuite une nouvelle balance. Au cours des premières semaines, vous voudrez pouvoir basculer entre les balances. Vous pourriez avoir deux programmes exécutables et arrêter le processus qui lit la balance, puis le redémarrer avec l'autre exécutable quand vous voulez changer de balance, ou vous pourriez mettre le code suivant dans votre programme :

new_scale := $TRNLNM (“NEW_SCALE”); (TRNLNM = translate logical name) [nouvelle_balance := $TRNLNM (“NEW_SCALE”); (TRLNM = traduire nom du logical)]

if new_scale = 'ACTIVE' then weight := read_new_scale() else weight := read_old_scale(); [si nouvelle_balance = 'ACTIVE', alors poids : = lire_nouvelle_balance() sinon poids := lire_vieille_balance();]

Vous pourriez vous servir de la commande terminal suivante pour utiliser la nouvelle balance :

define/system NEW_SCALE ACTIVE

et, pour vous servir de la vieille balance :

define/system NEW_SCALE INACTIVE (ou 'FALSE' ou 'USE_OLD_SCALES' ou ce que vous voulez)

Afin de pouvoir utiliser le contrôle de version, je crée une nouvelle arborescence de dossiers pour chaque version et j'utilise un logical pour indiquer la version active. Par exemple : ma version actuelle est la 7.2 et je crée donc le dossier APP$DISK:[V7-02], puis les sous-dossiers DATA et EXEC: APP$DISK:[V7-02.EXEC] et APP$DISK:[V7-02.DATA]

The logical KW21 used as pointer to the current version is created with: define/group KW21 APP$DISK:[V7-02.]/translation=concealed (note the dot at the end!) The switch “translation=concealed” makes the logical KW21 a pseudo device, so the sub-folders can be addressed with KW21:[EXEC] and KW21:[DATA]. To use version 7.3, I would create APP$DISK:[V7-03.EXEC] and APP$DISK:[V7-03.DATA] and define KW21 as APP$DISK:[V7-03.] – without changing anything in my applications. The only drawback of this method is that you have to use KW21:[000000] if you want to address the folder where the logical KW21 is pointing to. There is a lot more to tell about logicals. If you want to read more about logicals and have some time on your hands, try google with “VMS logicals”.

Le logical KW21 utilisé comme pointeur vers la version actuelle est créé par :

define/group KW21 APP$DISK:[V7-02.]/translation=concealed (remarquez le point à la fin du numéro de version !)

L'interrupteur « translation=concealed » fait du logical KW21 un pseudo-dispositif afin que l'adresse des sous-dossiers devienne KW21:[EXEC] et KW21:[DATA].

Pour utiliser la version 7.3, je créerais APP$DISK:[V7-03.EXEC] et APP$DISK:[V7-03.DATA] et je définirais KW21 comme APP$DISK:[V7-03.], sans changer quoi que ce soit dans mes applications.

Le seul inconvénient de cette méthode est qu'il faut utiliser KW21:[000000] si vous voulez vous adresser au dossier vers lequel le logical KW21 pointe.

Il y a bien plus de choses à dire sur les logicals. Si vous voulez en lire davantage et avez un peu de temps libre, faites une recherche sur Google de « VMS logicals ».

How to handle logicals? I tried replacing the logicals using hard links, but that works only for logicals with only 1 translation. And - as with eventflags - you can ask the system what the value of a logical is – a feature that cannot be implemented with hard links. This way, you could also define a kind of “system parameters” to be used by running processes. This makes it possible to implement software changes that can be switched on and off by changing the value of a logical instead of stopping a process and restarting it using a different executable. Or changing to or from daylight saving time without setting the clock. The list of other possible uses in VMS is long. For the search list, you can use environment variables (PATH), but these are valid within only one process and cannot be changed by another process. Also not an option…

Comment gérer les logicals ?

J'ai essayé de remplacer des logicals par des liens matériels, mais cela ne fonctionne qu'avec une seule traduction. Et - comme c'est le cas pour les eventflags - vous pouvez demander la valeur d'un logical au système - une fonction qui est impossible à implémenter avec des liens matériels. De cette manière, vous pourriez également définir un genre de « paramètres système » que les processus en train de s'exécuter pourraient utiliser. Cela rend possible l'implémentation de modifications de logiciels qui peuvent être démarrés ou arrêtés en changeant la valeur d'un logical au lieu d'arrêter un processus, puis de le redémarrer avec un exécutable différent. Ou changer de ou vers l'heure d'été sans toucher à l'horloge. La liste des utilisations possibles de logicals dans VMS est très longue.

Pour la liste de recherche, vous pouvez utiliser des variables d'environnement (PATH), mais celles-ci ne sont valables qu'à l'intérieur d'un seul processus et ne se modifient pas par un autre processus. Egalement hors de question…

My solution To use logicals on Linux, I created a few procedures in my library to replace the VMS functions to define, delete (“deassign”) and translate logicals. In VMS, the logicals are part of the kernel and located in the kernel's “paged memory”. This part of the kernel’s memory can grow in size and can be temporarily swapped out (VMS: paged out). As my solution is created in user-space, without the kernel controlling which process has access to which table, I decided to take a different approach: I placed the tables in separate data files. Upon program start, the shared tables (system, group and job) are opened (or created if necessary), and mapped into shared memory, so they can be accessed directly. This happens only as soon as any of the logical-library routines is called for the first time. Any changes due to (re)defining or removing of logicals are written back to the corresponding file and are immediately visible by other processes as it's mapped into shared memory. The process local table (LNM_PROCESS) is created and also mapped into memory, but not shared. And here lies a little problem:

Ma solution

Pour utiliser des logicals sous Linux, j'ai créé quelques procédures dans ma bibliothèque pour remplacer les fonctions de VMS pour définir, supprimer (« dé-assigner ») et traduire des logicals. Dans VMS, les logicals font partie du noyau et se trouvent dans la « mémoire paginée » de celui-ci. La taille de cette partie de la mémoire du noyau peut croître ; cette partie de la mémoire peut aussi être temporairement placée dans le swap (VMS: paged out). Puisque ma solution est créée dans l'espace utilisateur, sans que le noyau contrôle quel processus peut accéder à quelle table, j'ai décidé de faire les choses différemment : j'ai mis les tables dans des fichiers de données séparés.

Lors du démarrage d'un programme, les tables partagées (system, group et job) sont ouvertes - ou créées si nécessaire - et mappées dans la mémoire partagée, ce qui les rend accessibles directement. Cela a lieu uniquement quand n'importe laquelle des routines de la bibliothèque des logicals est appelée pour la première fois. Tous les changements causés par la (re)définition ou la suppression de logicals sont écrits dans le fichier correspondant et sont tout de suite visibles par d'autres processus, car mappés dans la mémoire partagée. Le processus local table (LNM_PROCESS) est créé et également mappé dans la mémoire, mais pas partagé. Et là, il y a un petit problème :

LNM_PROCESS is not a table. It's a logical pointing to another table containing the process ID (pid) in its name to separate the many process tables from each other. The behavior of Linux concerning process ID's is different from that of VMS (I will go into more detail on this in part 5 about DCL). DCL (Digital Command Language) is a real shell: it wraps around a process, and every time an executable (“image” in VMS) is started, it runs within this shell, within the same memory, with the same logicals and symbols (environment variables) and with the same process ID. Bash is called a shell, but it is NOT! It is a CLI (Command Line Interpreter). Every time an executable is started in Linux, it's started in a new subprocess. Besides the greater overhead of the creation of a new process, it also gets a new process ID. And therein is the problem: A different process ID means a different process table. In VMS, you can define a process logical and then start an executable that would use this logical. In Linux, the defined process logical will be gone on exit of the program defining the logical. To circumvent this problem I decided to use the process ID of the parent instead. This will be the same every time you start a new executable from the same terminal. Because this causes a different problem (having the same process table) when starting several background (“detached” in VMS) programs from a single terminal or program, I created the program “RunDetached” to do this for you. This again causes all programs to use process ID 1 from the init program, but that is easily detected. In that case its own process ID minus 1 is used.

LNM_PROCESS n'est pas une table. C'est un logical qui pointe vers une autre table contenant l'ID du processus (pid) dans son nom pour pouvoir différencier les nombreuses tables de processus. Le comportement de Linux concernant les ID de processus n'est pas le même que celui de VMS (j'en parlerai avec plus de détails dans la partie 5 qui a pour sujet le DCL). Le DCL (Digital Command Language est un vrai shell : il entoure un processus et, chaque fois qu'un exécutable (« image » dans VMS) est lancé, il tourne à l'intérieur de ce shell, à l'intérieur de la même mémoire, avec les mêmes logicals et symboles (des variables d'environnement) et avec le même process ID. On dit que Bash est un shell, mais ce n'est PAS vrai ! Bash est un CLI (Command Line Interpreter ou interpréteur de ligne de commande). Chaque fois qu'un exécutable est lancé dans Linux, il est lancé dans un nouveau subprocess (sous-processus). Mis à part les frais plus élevés de création d'un nouveau processus, il reçoit aussi un nouveau process ID. Et c'est là que se situe le problème : un process ID différent entraîne une table de processus différente. Dans VMS, vous pouvez définir un logical de type process, puis démarrer un exécutable qui utilisera ce logical. Dans Linux, le logical du processus défini n'existera plus lorsque l'on quitte le programme qui l'a défini.

Pour contourner ce problème, j'ai décidé d'utiliser le process ID du parent à la place. Ce sera le même chaque fois que vous lancerez un nouvel exécutable du même terminal. Parce que cela cause un autre problème (même process table), quand je lance plusieurs programmes en arrière-plan (« detached » dans VMS) d'un même terminal ou programme, j'ai créé un programme qui s'appelle « RunDetached » pour le faire à votre place. À nouveau, en conséquence, tous les programmes utilisent process ID 1 du programme init, mais cela est facilement détectable. Dans ce cas-là, son propre process ID minus 1 est utilisé.

As mentioned before, logicals are used consistently throughout the entire system in VMS. This means that whenever you want to access a device, VMS will first try to translate the name of the device. To get the same behavior, I created a library function named OPEN to substitute the file access function of VAX-pascal, but this works only for TEXT handles. If another type of file handle is used, than it will be used to determine the file attributes (like record size), and I cannot mimic that. In this case the best solution is to manually replace the OPEN statement by a sequence of: • Call to “translate name” to get the VMS behavior; • Call to ASSIGN to open the file, while specifying the correct file handle. I am hoping that I can incorporate this into my conversion software later on. The above mentioned functions (“define”, etc.) can also be accomplished from the terminal, so I created the three corresponding programs too. They are – of course – available as open source just like RunDetached. Next month: In the next article I will go more in-depth about other functions such as mailboxes (IPC), what you MUST know about the difference in the way VAX-pascal and Free Pascal handle “PACKED ARRAY OF CHAR” (strings), and how to deal with file version numbers.

Comme je l'ai déjà dit, les logicals sont utilisés partout dans le système de VMS. Cela veut dire que, chaque fois que vous voudrez accéder à un dispositif, VMS essayera d'abord de traduire le nom du dispositif. Pour avoir le même comportement, j'ai créé une fonction bibliothèque nommée OPEN pour se substituer à la fonction d'accès aux fichiers de VAX-pascal, mais cela ne marche que pour les poignées TEXT. Si un autre type de poignée de fichier est utilisé, il servira à déterminer les attributs du fichier (comme la taille des enregistrements) et je ne sais pas simuler cela. Dans ce cas, la meilleure solution est de remplacer l'argument OPEN à la main par une séquence de : • Appel à « translate name » pour avoir le comportement de VMS ; • Appel à ASSIGN pour ouvrir le fichier, tout en précisant la bonne poignée de fichier. J'espère pouvoir incorporer ceci dans mes logiciels de conversion plus tard.

Les fonctions mentionnées ci-dessus (« define », etc.) peuvent aussi être réalisées à partir du terminal et j'ai donc créé aussi les trois programmes correspondants. Ils sont - bien entendu - disponibles comme Open Source, tout comme RunDetached.

Le mois prochain : dans le prochain article, je vais approfondir mes explications d'autres fonctions telles que des « mailboxes » (boîtes aux lettres (IPC)), ce qu'il FAUT absolument savoir au sujet de la façon dont VAX-pascal et Free Pascal gèrent « PACKED ARRAY OF CHAR » (des chaînes), et comment traiter les numéros de version des fichiers.

issue106/tutoriel1.txt · Dernière modification : 2016/04/16 14:59 de andre_domenech