============================================================================

                         Pascal PCQ version 1.2
                   Un compilateur Pascal pour l'Amiga
                           de Patrick Quaid


============================================================================

Le  Pascal PCQ est un compilateur Pascal simplifié destiné à l'ordinateur
individuel  Amiga.   Le  compilateur  est librement distribuable, mais je
garde le copyright du compilateur, de la bibliothèque de l'exécutable, du
code  source du compilateur et de la bibliothèque, ainsi que le copyright
de  cette  documentation.  Ce compilateur pourra être distribué librement
tant  qu'on  ne le fera pas payer trop cher (pour plus de renseignements,
voir  la  dernière section).  Il existe désormais une version enregistrée
(anglaise) du compilateur - consultez aussi le dernier chapitre pour plus
d'informations  à  son sujet.  Pour résumer voici les caractéristiques du
compilateur:

Les mauvais côtés :

    o  Le compilateur n'accepte pas les ensembles.
    o  Il n'est pas compatible avec le Turbo Pascal, bien qu'il en soit
       très proche.
    o  Pour certaines choses, il est légèrement diffférent du Pascal
       Standard.
    o  Le compilateur a beaucoup de lacunes pour ce qui concerne les
       messages d'erreur.

Les bons côtés :

    o  Il marche.
    o  Il accepte les fichiers 'include'.
    o  Il permet de faire des compilations séparées, bien qu'on doive en
       faire la vérification (après tout, ce n'est pas un Modula-2).
    o  Il accepte les enregistrements, les types énumérés, les pointeurs,
       les tableaux et les chaînes de caractères du C.
    o  Il accepte la conversion de types ['cast'] telle qu'on la trouve en
       Modula-2. En d'autres termes, il autorise qu'on fasse quelque chose
       comme "Byte('d')".
    o  Il accepte plusieurs caractéristiques du Turbo et du Quick Pascal,
       telles que les procédures Exit, les opérateurs Shl et Shr ainsi que
       les constantes typées.
    o  Vous pourrez avoir autant de blocs de constantes, de variables, de
       types, de procédures et de fonctions que vous le souhaitez et ce
       dans un ordre quelconque.
    o  Il est gratuit !




============================================================================

                            Table des Matières

============================================================================


Ce manuel est conçu pour être lu avec un lecteur de fichiers ou un éditeur
de textes, par conséquent cette table des matières se base sur le numéro des
lignes plutôt que sur le numéro des pages. Voyez la dernière section pour
avoir une version orientée page.


              Sections                        Numéro de la ligne      VO
    --------------------------------------------------------------------

        Installation de PCQ .........................  164            160
            Ce qui est en votre possession ..........  168            164
            Réalisation d'une disquette de travail ..  214            208
        Compilation d'un Programme ..................  387            377
        Incompatibilités ............................  525            513

        Programmes en PCQ ...........................  591            582
        Mots Réservés ...............................  607            597
        Structure des Programmes en Pascal ..........  638            626

        Déclarations de Types .......................  711            699
            Types Numériques ........................  745            733
            Autres Types Ordinaux ...................  780            766
            Types Pointeur ..........................  806            792
            Types Fichiers ..........................  825            809
            Compatibilité de Types ..................  847            832

        Déclarations de Constantes ..................  876            861
            Constantes Typées .......................  913            897
            Constantes Standard .....................  993            972

        Déclarations de Variables ................... 1034           1016
            Variables Standard ...................... 1068           1049

        Déclaration de Fonctions et de Procédures ... 1120           1102
            Passage de Paramètres ................... 1152           1133
            Procedures 'Forward' et Fonctions ....... 1198           1177
            Procédures Externes ..................... 1224           1203
            Procédures Standard ..................... 1247           1226
            Fonctions Standard ...................... 1405           1370

        Déclaration d'Etiquettes .................... 1574           1544

        Expressions ................................. 1598           1568
            Ordre d'Evaluation et Court-Circuit ..... 1773           1734
            Expressions de Constantes ............... 1827           1789
            Références Variables .................... 1837           1799

        Instructions ................................ 1875           1837
            Instructions If.......................... 1895           1857
            Instructions While ...................... 1919           1882
            Instructions Repeat ..................... 1935           1898
            Instructions For ........................ 1955           1917
            Instructions Case ....................... 1999           1961
            Instructions With ....................... 2032           1994
            Instructions Composées .................. 2071           2030
            Instructions d'Assignation .............. 2087           2046
            Appels de Procédures .................... 2100           2059
            Instructions Return ..................... 2127           2085
            Instructions Goto ....................... 2146           2105

        Entrées/Sorties ............................. 2178           2137
            E/S du Pascal ........................... 2183           2142
            Fichiers Typés et Fichiers Texte ........ 2221           2180
            Ouverture de Fichiers ................... 2274           2230
            Ecriture de Fichiers .................... 2364           2324
            Lecture de Fichiers ..................... 2429           2391
            Tampons de Fichiers ..................... 2511           2475
            Vérification des E/S .................... 2576           2539
            E/S Standard ............................ 2605           2566

        Chaînes de Caractères ....................... 2681           2641
            Allocation d'Espace pour les Chaînes .... 2718           2677
            Utilisation des Caractères Escape ....... 2766           2724
            StringLib ............................... 2806           2763

        Gestion de la Mémoire ....................... 2820           2777
            HeapError [Erreur dans le Tas] .......... 2857           2813

        Procédures de Sortie ........................ 2892           2847
            Erreurs de l'Exécutable ................. 2942           2891

        Directives de Compilation ................... 3044           2963

        Conversion de Types ......................... 3183           3097

        Code d'Initialisation Réduit................. 3230           3141

        Fichiers Externes ........................... 3300           3205

        Notes Destinés aux Programmeurs en Assembleur 3374           3278

        Erreurs ..................................... 3404           3309

        Sources ..................................... 3440           3340

        Améliorations Urgentes à Venir .............. 3530           3427

        Historique des Mises à Jour ................. 3560           3454

        Notes Supplémentaires, Copyright et Adresse . 3800           3645




============================================================================

                          Installation de PCQ

============================================================================

Ce qui est en votre possession
------------------------------

Ce qui sera présent dans la distribution de PCQ dépendra de l'endroit où
vous vous le serez procuré. Si vous vous êtes procuré la disquette auprès de
moi, celui-ci, très vraisemblablement, comprendra tout. Si vous l'avez
téléchargé, celui-ci, probablement, ne comprendra pas différents fichiers
courants et ne comprendra ni le source du compilateur ni la bibliothèque de
l'exécutable. Il contiendra, cependant, une combinaison des fichiers
suivants :

        Pascal          Le compilateur lui-même
        Peep            L'optimiseur 'peephole'
        Pascal.DOC      Ce fichier de documentation
        Readme.PCQ      Une courte description de PCQ
        PCQ.lib         La bibliothèque de l'exécutable
        Include.LZH     La bibliothèque des fichiers 'include', compressée
                        avec le programme LHArc
        Examples.LZH    Divers programmes d'exemple, eux aussi compressés
                        avec LHArc
        IDList.LZH      Un répertoire pour les fichiers 'include'
        Source.LZH      Le code source en Pascal du compilateur (1)
        Runtime.LZH     Le code source en Pascal et en assembleur de
                        PCQ.lib. (1)

        A68k            L'assembleur de Charlie Gibbs (2)
        A68k.doc        La documentation de l'A68k (2)
        A68k2do.txt     Les améliorations prévues pour l'A68k (2)
        History.log     Les changements version-après-version de l'A68k (2)

        Blink           L'éditeur de liens de la Software Distillery (2)
        Blink.doc       La documentation de Blink (2)

    (1) Comme ces fichiers sont assez grands et qu'ils n'intéressent qu'un
        nombre de personnés limité, normalement je ne les mets sur disquette
        que si l'on m'en fait la demande. Si vous souhaitez les avoir,
        envoyez-moi seulement une disquette (cf. dernière section).
    (2) Ces fichiers sont souvents omis dans la version de type archive des
        BBS de la distribution pour abréger le temps de chargement. Ils sont
        déjà disponibles sur plusieurs systèmes, mais si vous chargez PCQ
        à partir d'un système, vous voudrez signaler que A68k et Blink sont
        aussi indispensables et vérifier qu'ils sont eux aussi disponibles.
       

Réalisation d'une disquette de travail
--------------------------------------

Heureux que vous me posiez la question. Et la réponse est que je ne sais pas
y répondre. Il existe des myriades de configurations différentes pour un
système, par conséquent il m'est impossible de vous dire exactement comment
mettre en place votre propre système. Cependant, je peux vous donner des
instructions d'ordre général.

Tout d'abord, dans votre chemin de recherche des commandes, vous aurez
besoin du compilateur, de l'assembleur, de l'éditeur de liens et d'un
éditeur de textes. D'ordinaire, ceux-ci devraient être dans le répertoire
C:, mais si vous vous servez de la commande AmigaDOS PATH, ils pourront se
trouver dans n'importe quel répertoire indiqué par le chemin de recherche.

Si vous ne possédez pas d'éditeur de textes, je voõs recommande du fond du
coeur CygnusEd Professional d'ASDG. On suppose que TxEd est presque aussi
bon, mais personnellement je ne l'ai jamais employé. Les programmeurs avec
un budget serré pourront utiliser MEMACS de la disquette Extras, ED de la
disquette Workbench, ou toute une foule d'éditeurs librement distribués,
comme DME. ED n'est pas un excellent choix, MEMACS peut aller et, d'après ce
que j'ai entendu dire, DME est vraiment excellent. Faites votre choix.

L'autre fichier dont vous aurez en définitive besoin est la bibliothèque de
l'exécutable ['runtime library'] qu'on peut mettre n'importe où. Je garde la
mienne dans mon répertoire de travail, mais d'autres préfèrent la mettre
dans le répertoire LIBS:. Cela dépend de vous, mais n'oubliez pas l'endroit
où vous la mettez.

Tous ces fichiers sont absolument nécessaires même pour les programmes les
plus simples. Si vous voulez employer quelques routines Amiga ou vous servir
des routines particulières de PCQ.lib, vous aurez aussi besoin d'installer
la bibliothèque de fichiers 'include'. C'est ici que ça devient quelque peu
difficile car l'ensemble des fichiers 'include' occupe environ 800 blocs de
la disquette (un peu moins de 400 Ko). C'est juste la moitié d'une disquette
souple. La taille de ces fichiers rendra difficile l'emploi de PCQ avec un
système pourvu d'un seul lecteur de disquettes. Si vous souhaitez installer
ces fichiers 'include', il vous faudra aussi trouver une copie de LHArc (ou
un archiveur compatible). LHArc est disponible sur presque toutes les BBS,
ainsi vous ne devriez pas avoir trop de problèmes pour vous en procurer une
copie (si vous ne l'avez pas encore fait, faites-vous plaisir et payez-vous
un modem. C'est le meilleur investissement que vous pourriez faire).

Alors, comment organiser tout ceci ?  Naturellement, cela dépendra de votre
système, mais voici quelques exemples. Si vous voulez installer le programme
sur un disque dur, vous pourrez essayer ce qui suit. D'abord, copiez Pascal,
A68k et Blink dans le répertoire C: (copiez aussi un éditeur de textes, s'il
n'y en a pas déjà un). Créez, ensuite, un répertoire de travail. Copiez
PCQ.lib dans ce nouveau répertoire. Faites maintenant un sous-répertoire
dans votre répertoire de travail et donnez-lui un nom comme "Include". Il 
n'est pas vraiment nécessaire qu'on fasse un sous-répertoire, mais ceci vous
aidera à garder une structure de disque linéaire. Utilisez ensuite la
commande AmigaDOS ASSIGN pour faire l'assignation d' "Include" dans votre
nouveau répertore 'include'. Maintenant, vous aurez à décompresser la
bibliothèque des fichiers 'include' à l'aide d'une commande comme 

        LHArc -x -r x DisquetteDistribution:Include Include:

Naturellement, servez-vous du nom véritable de l'archive 'include'. Chaque
fois que vous vous servirez du compilateur, vous devrez vous assurer que
vous ASSIGNEZ le répertoire "Include" de façon correcte - vous aurez
probablement envie de mettre cette assignation dans la 'startup-sequence' ou
dans un fichier 'script' destiné à l'initialisation.

Si vous n'avez qu'un lecteur de disquettes, je vous recommande la structure
de disquette ci-dessous. Le problème est que je n'ai pas un système avec un
seul lecteur de disquettes pour pouvoir faire des essais et que, par
conséquent, vous devrez peut-être modifier quelque peu cette structure.

    Racine:
        PCQ.lib
        C (dir)
            A68k                             Assign
            Avail                            Blink
            CD                               Copy
            Date                             Delete
            Echo                             Ed
            Else                             EndCLI
            EndIf                            EndSkip
            Execute                          Failat
            If                               Info
            Join                             Lab
            List                             LoadWB
            Makedir                          NewShell
            Pascal                           Path
            Prompt                           Protect
            Quit                             Relabel
            Rename                           Resident
            Run                              SetPatch
            Stack                            Type
        Libs (dir)
            diskfont.library                 icon.library
            mathtrans.library                version.library
        Devs (dir)
            ramdrive.device                  system-configuration
        S (dir)
            Startup-Sequence                 Make
        L (dir)
            Disk-Validator                   Newcon-Handler
            Port-Handler                     Ram-Handler
            Shell-Seg                        
        Include (dir)
            Tous les fichiers 'include'...
        Trashcan (dir)


Pour faire une disquette comme celle-ci, faites tout d'abord une copie de la
disquette Workbench standard. Ensuite, fichez en l'air tout, je veux dire
tout ce dont vous n'avez aucunement besoin. Par exemple, vous aurez remarqué
dans la liste ci-dessus qu'il n'y a pas de 'serial.device' ni de
parallel.device et que, par conséquent, vous ne pourrez utiliser ni modem ni
imprimante. On devra faire ce type de sacrifices. Ensuite, copiez Pascal,
A68k et Blink dans le répertoire :c, puis copiez Make dans le répertoire :s
et PCQ.lib dans la racine de la nouvelle disquette. Créez un nouveau
répertoire "Include", puis faites une commande CD sur celui-ci. Décompressez
le répertoire du fichier 'Include' par la commande suivante :

    LHArc -x -r x Distribution:Include DisquetteDeTravail:Include/

Utilisez le vrai chemin de recherche pour LHArc et pour l'archive elle-même.
Vous pourriez avoir à appliquer une commande Install sur la disquette pour
que celle-ci puisse lancer le système, mais vous aurez pour vous-même une
disquette de travail à peine utilisable pour le Pascal. Virtuellement, vous
n'aurez pas de place libre sur celle-ci, par conséquent vous devrez éditer
et compiler vos fichier en RAM:, en les copiant aussi souvent que possible
sur une disquette à part. Ce sera bien pénible. Tant que vous écrirez des
programmes Pascal standard, très simples, n'utilisant aucune des
caractéristiques particulières de l'Amiga, vous pourrez ne pas mettre le
répertoire 'include' (ce qui libère environ 400 Ko), mais vous n'aurez pas
la possibilité de créer des programmes très intéressants. Probablemet, les
utilisateurs avec un seul lecteur de disquettes ont plusieurs tours dans
leur sac pour s'accomoder des problèmes d'espace sur une disquette, donc,
si vous avez une idée pour une meilleure disposition, servez-vous en par
tous les moyens.

Si vous possédez deux lecteurs de disquettes, je recommenderais une mise en
place semblable à celle d'un système avec un seul lecteur. Toutefois,
déplacez le répertoire "include" dans la seconde disquette et augmentez les
fichiers système sur la disquette de lancement (ainsi, en particulier, vous
pourrez vous servir de l'imprimante). Utilisez les 400 Ko environ d'espace
libre de la deuxième disquette comme espace de travail. C'est le type
d'installation que j'ai utilisée au début quand j'ai développé PCQ.

Si vous avez beaucoup de RAM (disons un méga-octet ou plus), vous pourriez
vouloir copier une partie de tout ceci en RAM: ou en RAD: pour libérer
de l'espace de travail. Par exemple, si vous avez un méga-octet de RAM,
vous pourriez copier tout le répertoire "Include" dans la disquette RAM: et
avoir encore assez de mémoire pour pouvoir compiler des programmes de taille
moyenne.

La seule partie optionnelle du système est l'optimiseur 'peephole', Peep. Ce
programme prend en charge la sortie assembleur du compilateur et la rend un
peu plus efficace et en réduit légèrement la taille. Si vous êtes en train
de compiler sur disquette, probablement, vous aurez envie de ne pas vous
servir de l'optimiseur, mais -si vous travaillez en RAM ou sur disque dur-
ce dernier n'augmente pas tellement le temps de compilation. On peut copier
Peep au même endroit que Pascal.

Peu importe la façon dont vous acheverez la configuration du système, vous
devrez toujours définir l'assignation d' "Include" pour que celui-ci pointe
sur votre répertoire de fichiers 'include'. Cette assignation n'est qu'une
convention dont je me suis servi dans les fichiers 'include' et dans les
programmes d'exemple -en d'autres termes, elle n'est pas intégrée au
compilateur-, ainsi, si vous voulez modifier chaque fichier de tous les
fichiers 'include', vous pouvez employer l'assignation de votre choix. La
seule autre assignation digne d'intérêt est le répertoire T:. Celui-ci est
créé automatiquement par l'AmigaDOS et, puisqu'il est utilisé par Make pour
y entreposer des fichiers temporaires, le fait de l'assigner à un répertoire
RAM: augmente considérablement le cycle de la compilation tout entier.




============================================================================

                       Compilation d'un Programme

============================================================================

Transformer un fichier source Pascal en un programme exécutable est (en
définitive) un processus en quatre étapes. Vous commencez par votre code
source (par exemple, l'un des programme d'exemple), dont le suffixe sera un
.p. La première étape est l'utilisation du compilateur pour transformer ce
fichier source en un programme équivalent en assembleur. Pour ce faire,
invoquez le compilateur par le format de commande suivant :

        Pascal EntréePascal SortieAssembleur [-q] [-s] [-b]

On devra remplacer "EntréePascal" par le nom du fichier complet (y compris
le chemin de recherche, si nécessaire) de votre fichier source, tandis que
"SortieAssembleur" est le nom d'un fichier (avec un chemin de recherche en
option) de sortie en langage assembleur. Pour ce qui concerne le fichier de
sortie, j'emploie habituellement le suffixe ".asm". Les arguments de la
ligne de commande peuvent être écrits dans n'importe quel ordre dans la
ligne de commande elle-même, en majuscules ou en minuscules, et ont les
significations suivantes :

     -q      Lance le mode "quiet" [silencieux], c'est-à-dire que le
             compilateur n'affichera rien à l'écran sauf les messages
             d'erreur. Ceci rend plus aisée l'analyse syntaxique de la
             sortie du compilateur dans un 'script' Arrex, par exemple.

     -s      Initialisation réduite. Les petits programmes emploient
             une routine d'initialisation différente qui n'a pas toute
             la surcharge de la routine standard, ce qui veut dire que 
             vous ne pourrez employer les E/S Pascal (c'est-à-dire
             Writeln(), Readln(), etc.).

     -b      Invalide le court-circuit des expressions booléennes.
             D'ordinaire, PCQ abandonne l'évaluation d'une expression
             booléenne dès qu'il en connaît la valeur d'ensemble (par
             exemple, si la partie gauche d'une expression AND est
             fausse, il n'y aura pas d'indication pour évaluer la
             partie droite). Ainsi, certaines parties du programme ne
             seront pas exécutées. Cette option force PCQ à évaluer
             intégralement toutes les expressions booléennes.

Lors d'une seconde étape, on prend le fichier en langage assembleur et l'on
crée un nouveau fichier un peu plus efficace. Ceci se fait à l'aide du
programme Peep, qu'on invoque par le format de commande suivant :

        Peep EntréeAssembleur SortieAssembleur

Normalement, j'emploie le suffixe .s pour les fichiers en assembleur qui
ont été lancés par l'optimiseur 'peephole', mais vous pouvez choisir tout à
fait autre chose.

Lors d'une troisième étape, on prend le fichier .s ou .asm et l'on crée un
fichier objet. En général, un fichier objet a les mêmes données et les mêmes
instructions lisibles par la machine qu'un fichier exécutable, mais il ne
contient pas toutes les routines dont aura besoin le programme final.
L'assembleur -dans ce cas, l'A68k de Charlie Gibbs- convertit les programmes
assembleur en fichiers objet et on l'invoque avec la ligne de commande
suivante :

        A68k EntréeAssembleur SortieObjet

A68k est un programme souple et très puissant, avec beaucoup d'options -
assurez-vous de lire son fichier de documentation pour avoir une description
détaillée. 

Si franchissez toutes ces étapes sans faire d'erreurs, vous pourrez faire
l'édition de liens du fichier objet avec toutes les routines nécessaires de
la bibliothèque de l'exécutable pour que le fichier devienne un programme
exécutable. L'éditeur de liens Blink de Software Distillery gère cette
partie du processus. On l'invoque avec la ligne de commande suivante :

        Blink EntréeObjet to SortieExécutable library PCQ.lib

Blink aussi possède plusieurs options et il est livré avec un fichier de
documentation qui donne tout le détail de ces options. Remarquez que vous
pourriez avoir à fournir un chemin de recherche complet pour indiquer
l'endroit où se trouve la PCQ.lib -par exemple, si elle se trouve dans le
répertoire LIBS:, vous devrez employer LIBS:PCQ.lib. Maintenant, vous avez
enfin un fichier exécutable fini. Cela semble faire beaucoup d'étapes et
beaucoup de choses dont il faut se souvenir, pour réaliser un programme.
C'est vrai. Par conséquent, j'utilise, et je l'ai mise dans la distribution,
une paire de 'scripts' en AmigaDOS qui permettent d'automatiser tout ce
processus. Le premier s'appelle Make et compile un programme qui se trouve
dans le répertoire T: pour écrire sur la disquette seulement le programme
exécutable. Voila comment il se présente :

                .key source
                Pascal <source>.p T:<source>.asm
                A68k T:<source>.asm T:<source>.o
                Delete T:<source>.asm
                Blink T:<source>.o to <source> library PCQ.lib
                Delete T:<source>.o

Vous remarquerez que mes préférences -pour ce qui est des suffixes- sont
incorporées dans ce 'script' - le fichier Pascal se termine par .p, le
fichier en langage assembleur se termine par .asm et le fichier objet se
termine par .o. Si vous préférez avoir des noms différents, faites les
changements dans le seul 'script'. Remarquez aussi que vous pourriez avoir à
changer le 'script' si le compilateur, l'assembleur et l'éditeur de liens ne
sont pas dans le répertoire courant ou si la PCQ.lib n'est pas dans ce même
répertoire (dans les deux cas, utilisez le chemin de recherche détaillé au
lieu du nom du fichier). Pour lancer ce 'script', il vous faudra l'invoquer
comme ci-dessous :

        Make NomDuProgramme

Notez qu'on ne met aucun suffixe. Si tout fonctionne comme il se doit,
vous trouverez un programme exécutable qui s'appellera NomDuProgramme dans
le répertoire courant. Un problème avec ce 'script' est que vous ne pourrez
employer les options de la ligne de commande du compilateur. Actuellement,
j'ai plusieurs versions différentes du 'script' Make qui gèrent toutes les
combinaisons dont je me sers.

L'autre 'script', OMake, est virtuellement le même, si l'on excepte que
celui-ci invoque l'optimiseur 'peephole' pour réaliser des programmes un peu
plus efficaces. Voici comment il se présente :

                .key source
                Pascal <source>.p T:<source>.asm
                Peep T:<source>.asm T:<source>.s
                Delete T:<source>.asm
                A68k T:<source>.s T:<source>.o
                Delete T:<source>.s
                Blink T:<source>.o to <source> library PCQ.lib
                Delete T:<source>.o

En outre, vous pourriez avoir à faire des modifications pour adapter votre
installation. Si vous travaillez sur un projet assez complexe, vous
trouverez probablement qu'il vaudra mieux réaliser un ensemble de 'scripts'
personnalisés pour automatiser le processus de compilation, d'assemblage et
d'édition des liens.




============================================================================

                            Incompatibilités

============================================================================

    Le Pascal PCQ est incompatible avec le Pascal standard et par extension
avec le Turbo Pascal, et ce sur plusieurs points. Voici ces points en bref :
                                                     
    (1) Les ensembles ne sont pas supportés.
    (2) La déclaration Pascal standard de pointeurs sur des enregistrements
        n'est pas acceptée. Par exemple, la syntaxe suivante est autorisée
        en Pascal standard :

            type
                WindowPtr = ^Window;
                Window = record
                    NextWindow : WindowPtr;
                    ...

        C'est d'ailleurs une exception en Pascal standard - c'est la seule
        fois où l'on peut utiliser un identificateur sans l'avoir déclaré.
        En Pascal PCQ, cette syntaxe échouera avec un 'Unknown ID error'.
        A sa place, employez quelque chose comme

           type
               Window = record
                   NextWindow : ^Window;
                   ....
               end;
               WindowPtr = ^Window;

    (3) Les enregistrements avec des parties variables ne sont pas acceptés.
    (4) La syntaxe familière pour indiquer un caractère apostrophe qui est
        '''' en Pascal n'est pas acceptée. A sa place, le Pascal PCQ emploie
        les conventions 'escape' du C, qui seront expliquées dans la section
        "Chaînes de Caractères".
    (5) La manière d'ouvrir un fichier est différente de celle du Pascal
        Standard, même si, une fois les fichiers ouverts, les commandes sont
        en gros les mêmes.

Bien que le Pascal PCQ n'ait pas été conçu pour être compatible avec Turbo
Pascal, afin de rendre plus facile le portage des programmes, j'esquisserai
quelques unes des différences plus importantes (en plus de celles déjà
mentionnées).

    (1) Le Pascal PCQ gère les chaînes de caractères d'une façon totalement
        différente de Turbo Pascal. En PCQ, les chaînes de caractères sont
        semblables aux chaînes du C, qu'on manipule moins facilement qu'en
        Turbo Pascal. En réalité, les chaînes PCQ sont les plus difficiles
        des trois. Elles seront expliquées en détail dans la section
        "Chaînes de Caractères".
    (2) Dans une fonction Pascal PCQ, le fait d'assigner une valeur au nom
        de la fonction provoque la sortie de la fonction. En Turbo Pascal,
        le nom de la fonction est traité comme une variable destinée
        seulement à l'écriture et vous devrez utiliser la commande Exit de
        façon explicite. Tous les exemples du Rapport Pascal évitent cette
        sortie en assignant la valeur comme dernière instruction.
    (3) En parlant d'Exit, en Pascal PCQ, Exit abandonne le programme, là
        où, en Turbo Pascal, il abandonne la fonction ou la procédure
        courantes. L' "Exit" de Turbo Pascal est comme le 'return" de PCQ
        et le "Halt" de Turbo est comme l' "Exit" de PCQ. Compris ?




============================================================================

                            Programmes en PCQ

============================================================================

En grande partie, les programmes en Pascal PCQ ressemblent beaucoup aux
programmes écrits en Pascal standard. Si l'on excepte les incompatibilités
dont j'ai fait état ci-dessus, dans les faits, PCQ devrait pouvoir compiler
directement des programmes Pascal simples. Toutefois, PCQ ajoute beaucoup
d'extensions au Pascal, donc, pour pouvoir les expliquer, je parlerai de ce
qui est autorisé et de ce qui n'est pas autorisé dans un programme PCQ.




============================================================================

                              Mots Réservés

============================================================================

Les mots réservés sont des symboles qu'il n'est pas permis d'utiliser comme
identificateurs dans ses propres programmes. Ces mots ont une signification
particulière pour le compilateur et on ne peut en déroger. Voici les mots
réservés de PCQ :

                    and         for         procedure
                    array       forward     program
                    begin       function    record
                    by          goto        repeat
                    case        if          return
                    const       in          set
                    div         label       then
                    do          mod         to
                    downto      not         type
                    else        of          until
                    end         or          var
                    external    packed      while
                    file        private     with

Comme vous pouvez le voir, même des parties non encore implémentées sont
déjà réservées.




============================================================================

                     Structure des programmes en Pascal

============================================================================

La structure normale d'un programme Pascal est la suivante :


<Programme> ::= Program <Identificateur> ; <Bloc>.  |
                Program <Identificateur> (<Liste des Identif.s>) ; <Bloc>.

<Bloc>      ::= <Déclarations> begin <Instructions> end |
                begin <Instructions> end

<Liste des Identificateurs> ::= <Identificateur> , <Liste des Identif.s> |
                      <Identificateurs>


Est-ce que tout le monde sait lire les diagrammes de Backus-Naur ?  L'idée
qui en est à la base est que les objets à gauche du signe de définition ::=
sont définis par la règle à la droite du signe. Les objets entre parenthèses
sont définis ailleurs dans la liste, tandis que le caractère barre verticale
sépare les alternatives. Tout ce qui reste est à prendre en considération à
la lettre. Ainsi, un programme Pascal commence par le mot littéral Program,
suivi d'un identificateur, suivi d'un point-virgule, suivi d'un bloc (quel
qu'il soit) et se termine par un point. D'autre part, un programme peut être
constitué du mot Program, suivi d'un identificateur, suivi d'une parenthèse
ouverte, suivi d'une liste d'identificateurs, suivi d'une parenthèse fermée,
d'un point-virgule, d'un bloc et, pour finir, d'un point. Quand vous vous
serez habitués aux diagrammes BNF, ceux-ci vous diront exactement ce qu'il
faut savoir sur la syntaxe d'un programme. Les grammaires BNF peuvent aussi
être représentées par des "diagrammes en forme de rail" et ce serait ce que
j'emploierais ici si ce document n'était pas orienté texte.

Nous avons laissé peu de choses indéterminées pour pouvoir mieux commencer
à les remplir.

<Déclarations> ::= <Déclaration> , <Déclarations> | <Déclaration>

<Déclaration> ::= <Déclaration de Types>       |
                  <Déclaration de Constantes>  |
                  <Déclaration de Variables>   |
                  <Déclaration d'Etiquettes>   |
                  <Déclaration de Procédures>  |
                  <Déclaration de Fonctions>

Remarquez que le Pascal standard impose un ordre dans les déclarations : il
affirme qu'il devrait y avoir un bloc de constantes, suivi d'un bloc de
types, etc.. Le Pascal PCQ élimine cette restriction; vous pourrez donc
avoir autant de déclarations qu'il vous conviendra dans un ordre quelconque.

Sujet à la définition de la suite de ces objets, celui-ci est le format d'un
programme normal en Pascal PCQ. Il existe une exception (naturellement) :
les fichiers qu'on compile séparément. Turbo Pascal fournit une structure
"Unit" : vous avez donc la possibilité d'écrire, de compiler et de déboguer
chaque unité, puis de vous en servir à nouveau dans plusieurs programmes.
PCQ présente une caractéristique similaire, bien que celle-ci ne soit pas
aussi puissante, sous forme de fichiers externes. Examinez l'extension
suivante de notre règle élémentaire :

<Programme> ::= Program <Identificateur> ; <Bloc>.  |
                Program <Identificateur> (<Liste des Identif.s>) ; <Bloc>.
                External ; <Déclarations>

Il en ressort qu'un fichier externe n'est rien d'autre que le mot réservé
'External' suivi d'un point-virgule, puis d'une succession de procédures, de
fonctions, de toute sorte de choses. Voyez la section "Fichiers Externes"
pour plus de renseignements.




============================================================================

                          Déclarations de Types

============================================================================

Les déclarations de types prennent la forme suivante :

<Déclaration de Type> ::= Type <Définitions de Types>;

<Définitions de Types> ::= <Définition de Type>; <Définitions de Types> |
                           <Définition de Type>

<Définition de Type>  ::= <Identificateur> = <Spécification de Type>

<Spécification de Type> ::= <Identificateur>                 |
                            <Intervalle>                     |
                            ^<Spécification de Type>         |
                            (<Liste des Identificateurs>)    |
                            <Définition de Tableau>          |
                            <Définition d'Enregistrement>    |
                            file of <Spécification de Type>

<Intervalle> ::= <Expression de Constantes> .. <Expression de Constantes>

<Définition de Tableau> ::= array [<Intervalle>] of <Spécification de Type> |
                       array <Identificateur> of <Spécification de Type>

<Définition d'Enregistrement> ::= record <Définitions de Variables> end


Dès que vous aurez assimilé la notation BNF, je pense que vous trouverez
tout ceci très limpide. Les expressions de constantes seront analysées dans
la section "Expressions" ci-dessous - pour l'instant, regardons les types
prédéfinis en Pascal PCQ.

 Types Numériques
------------------

Le Pascal PCQ possede une variété de types numériques qui devraient vous
donner la souplesse dont vous avez besoin pour mener à bon terme tout type
de calcul dont vous pourriez avoir besoin. Du plus petit au plus grand
intervalle, voici tous ces types :

Byte      C'est un entier non signé sur un octet pouvant contenir une valeur
          de 0 à 255.

Short     C'est un entier signé sur deux octets (16 bits), pouvant contenir
          des valeurs dans l'intervalle de -32768 à 32767.

Integer   C'est le type ordinal le plus grand. Il contient un entier signé
          sur 32 bits, dans l'intervalle de -2 billions à 2 billions.

Real      C'est une valeur en virgule flottante, au format 'Fast Floating
          Point' [Virgule Flottante Rapide] de Motorola. Une valeur 'Real'
          se situe sur 4 octets (32 bits) et peut exprimer des valeurs en
          virgule flottante positives ou négatives qui vont de 10 x 10^18
          à 5 x 10^-20 environ. Je ne suis pas certain de la précision du
          format FFP, mais je ne compte pas sur une précision supérieure à
          4 ou 5 chiffres.

Dans une expression, les types numériques sont interchangeables. Si vous
utilisez deux types différents dans -par exemple- une expression plus, le
compilateur élèvera automatiquement les deux valeurs au "type conteneur"
de plus petite taille. Un type conteneur est un type numérique dont
l'intervalle couvre les deux arguments. Par exemple, le résultat d'une
addition entre un type 'Short' et un type 'Integer' sera un type 'Integer'.
Le résultat de la plupart des opérations binaires comportant des valeurs
'Real' est représenté par une Valeur réelle.


 Autres Types Ordinaux
-----------------------

'Integer', 'Short' et 'Byte' sont tous des types 'Ordinal'. Ceci signifie
qu'il s'agit de valeurs discrètes qui peuvent être représentées exactement
en binaire (inversement aux valeurs en virgule flottante qui sont des
valeurs approchées). Voici les autres types ordinaux :

Char        Valeur sur un octet, stockée sous forme de valeur ASCII.

Boolean     Il s'agit toujours d'une valeur sur un octet, une valeur Boolean
            est égale à -1 (tous les bits à 1) si elle est vraie ou égale à
            0 si elle fausse. Tout autre chose pourrait donner des résultats
            imprévisibles. Incidemment, le type 'Boolean' peut être
            considéré comme un type énuméré comprenant les valeurs 'True' et
            'False'. Dans plusieurs implémentations, on a False < True and
            Succ(False) = True, mais ce n'est pas le cas en PCQ.

Enumerated  Les valeurs d'un type énuméré sont indiquées à l'intérieur d'un
            programme. S'il y a 256 valeurs, ou moins de 256, le type
            énuméré sera stocké dans un octet. S'il y a plus de 256 valeurs,
            le type énuméré sera stocké dans deux octets. Dans tout autre
            cas, chaque énumération sera associée à une valeur entière, qui
            commence à 0.


 Types Pointeur
----------------

Les types pointeur contiennent l'adresse d'une autre variable. Ce sont des
valeurs 32 bits. Voici les types pointeur prédéfinis :

Address     'Address' est un pointeur d'un type particulier compatible avec
            tous les autres types pointeur. Vous ne pourrez le libérer en ne
            lui faisant plus référence, mais vous pourrez vous en servir
            pour vous éviter des conversions de types ['casts'] lourdes à
            mettre en place.

String      En PCQ, le type 'String' est actuellement défini comme pointeur
            sur un caractère, bien qu'il possède d'autres qualités propres
            comme celle d'autoriser les indices de type tableau. Les chaines
            de caractères seront expliquées dans la section "Chaînes de
            Caractères".


 Types Fichier
---------------

En PCQ, les fichiers sont basés sur les fichiers AmigaDOS normaux, mais ils
pourvoient un tamponnage automatique et ont accès aux routines d'E/S du
Pascal qui sont bien pratiques (Writeln, etc.). Les variables de fichiers
sont de deux types :

Text        Un fichier 'Text' est un fichier ASCII normal (par exemple,
            cette documentation).

Typed Files Un fichier de types, déclaré en tant que "File of Type", ne
            stocke que des valeurs du type indiqué. Si vous envoyez une
            commande Write() sur un fichier de types, PCQ affichera la
            représentation binaire réelle de l'objet dans le fichier. Par
            exemple, si vous avez un "File of Integer", le fichier de types
            stockera chaque 'Integer' sous une forme binaire sur 4 octets.
            Par contre, un fichier texte stockera chaque 'Integer' comme une
            succession de caractères ASCII de '0' jusqu'à '9'. On ne peut
            employer Writeln et Readln avec des fichiers de types.


 Compatibilité de Types
------------------------

Il y a deux sortes de vérification des types. La première est la
compatibilité de type ordinaire. Celle-ci est employée pour comparer les
arguments d'une expression ou pour comparer les paramètres réels et formels
des valeurs. La deuxième vérifie les types identiques et est employée dans
des circonstances plus strictes : pour les opérations d'assignation et dans
les paramètres formels et réels passés par référence (en utilisant le mot
réservé VAR). Par rapport au Pascal standard, PCQ est généreux dans la mise
en application de ces règles. Pour une compatibilité de types simple, les
deux types doivent passer les tests suivants :

      o  Ils ont le même type, ou
      o  Ils ont le même type de nombre (réel, entier, etc.), ou
      o  Ils ont le même tableau avec une même taille et le type des
         éléments est compatible, ou
      o  Ils ont le même pointeur sur des types compatibles, ou
      o  Ils ont le même fichier de type compatible

Les types synonymes (c'est-à-dire "TYPE ByteSynonym = Byte") sont considerés
comme des types identiques. Pour une vérification d'identité de type
beaucoup plus stricte, supprimez la deuxième règle.




============================================================================

                      Declarations de Constantes

============================================================================


Normalement, les constantes sont déclarées à la manière du Pascal standard,
qui, selon la notation BNF, se presente ainsi :

<Bloc de Const> ::= Const <Déclarations de Const>;

<Déclarations de Const> ::= <Déclaration de Const> |
                            <Déclaration de Const> ; <Déclarations de Const>

<Déclaration de Const> ::= <Identificateur> = <Expression de Constante> |
                           <Identificateur> : <Spécification de Types> =
                                        <Valeur Constante Typée>

<Valeur Constante Typée> ::= <Expression de Constante>    |
                           ( <Expressions de Constante> )  |
                           @ <Identificateur>

Les expressions de constantes seront définies par la suite, mais vous pouvez
vous les imaginer comme des expressions normales qui sont entièrement
évaluées pendant la compilation (c'est-à-dire qu'elles n'utilisent aucune
fonction définie par l'utilisateur et qu'elles n'ont accès à aucune
variable).

Les constantes normales sont faciles à comprendre - il ne s'agit que de
variables destinées à la lecture n'occupant vraiment pas de place en
mémoire. La valeur d'une constante est simplement insérée dans le programme
à la place de l'identificateur. Etant donné qu'elles sont constituées
d'expressions de constantes, les constantes normales ne pourront être que de
l'un des quelques types suivants : integer, real, char, Boolean, string et
array of char. Celles-ci ne pourront être d'aucun autre type défini par
l'utilisateur et ne pourront être de type 'record' ou 'array'.


 Constantes Typées
-------------------

Et voilà l'endroit pour introduire les constantes typées. On s'imagine mieux
ces constantes si l'on pense à des variables pré-initialisées; elles peuvent
être de tout type qu'on pourra définir, excepté le type fichier. Je n'ai
aucune idée de la raison pour laquelle Turbo Pascal a décidé qu'on devrait
appeler ces objets constantes au lieu de variables, mais je me sers de cette
même dénomination. Votre programme se charge avec ces valeurs déjà en place
et celles-ci ne seront pas rafraîchies tant que le programme ne sera chargé
à nouveau. Toutefois, si l'on s'en sert de manière incorrecte, celles-ci
délogent les programmes résidents.

Un effet collatéral pratique est que ces variables locales à une procédure
peuvent garder leur valeur pendant l'exécution d'un programme (comme les
variables 'static' en C, d'accord ?). En d'autres termes, si vous déclarez
une constante typée à l'intérieur d'une procédure, celle-ci ne sera
accessible à aucune partie du programme à l'extérieur de cette portée et ne
perdra pas sa valeur entre des appels à la procédure. Elle ressemble à une
variable locale et se comporte comme une variable globale.

La déclaration de constantes typées est sujette à l'erreur et, d'une manière
invariable, l'on passe le plus clair de son temps à compter une liste de
chiffres ou à tenter de faire concorder des parenthèses ou quelque chose qui
est pareillement engourdissant pour l'esprit. Malgré tout, elles sont
vraiment pratiques. La syntaxe correspond à la deuxième alternative de
<Déclaration de Const>, mais ceci n'explique pas tout. Il vaut peut-être
mieux regarder quelques exemples :

    Type
        ExempleEnreg = record
                         Champ1 : Integer;
                         Champ2 : Char;
                         Champ3 : Boolean;
                         Champ4 : ^Integer;
                         Champ5 : Array [-1..1] of Byte;
                     end;
        MultiDim = Array [0..1,0..1] of Integer;

    Const
        Message1 : String = "Une chaîne d'exemple";
        Message2 : Array [0..9] of Char = 'Chaîne2   ';
        Message3 : Array [0..9] of Char = ('a','b','c','d','e',
                                           'f','g','h','i','j');
        Valeur1  : Integer = 456;
        Enreg1   : ExempleEnreg =
                        (34, 'r', True, @Valeur1, (34,56,12));
        Multi1   : MultiDim = ((34,12), (45,15));


Notez que toutes les constantes "Message" et "Valeur1" pourraient aussi être
spécifiées sous forme de constantes normales. Message1 et Valeur1, dans ce
cas, n'occuperont pas de mémoire, tandis que Message2 et Message3 seraient
identiques. Le format de la déclaration Message3 est typique des tableaux,
tandis que le format Message2 est une abréviation particulière propre aux
tableaux de caractères.

Il existe plusieurs différences entre cette syntaxe et celle de Turbo Pascal
(toutes, si je peux dire, en faveur de PCQ). 

En premier lieu, la définition d'enregistrements de constantes en Turbo
Pascal exige que l'on emploie l'identificateur de champ, suivi d'un
point-virgule, de la valeur et, souvent, d'un autre point virgule. C'est
beaucoup trop compliqué pour moi, par conséquent je me sers de la même idée
sous forme de tableaux : vous indiquez chaque champ, en le séparant du
suivant avec une virgule.

La seconde différence avec Turbo Pascal est que, jusqu'à la version 6.0,
celui-ci permettait d'initialiser les types pointeur avec 'Nil'. Le Pascal
PCQ vous permet d'initialiser un type pointeur en tant que 'Nil' ou en tant
qu'adresse de la variable globale précédente ou de la constante typée. Pour
faire ceci, normalement, on utilise l'opérateur '@', qui retourne l'adresse
de la variable indiquée.

La dernière différence est que l'on peut employer des valeurs de constantes
typées dans des expressions de constantes ultérieures. Vous ne pourrez
employer aucun type structuré (c'est-à-dire, des enregistrements et des
tableaux), mais vous aurez la possibilité d'employer des entiers, des réels
et d'autres types qu'on appelle "simples".

 Constantes Standard
---------------------

Il existe plusieurs constantes standard (c'est-à-dire, des constantes qui
sont incorporés au compilateur lui-même qu'il ne faut pas déclarer ou pour
lesquelles il ne faut pas utiliser un fichier 'include'). Les voici :

False    Celle-ci est une une énumération de type Booléen et a une valeur
         égale à 0.

MaxInt   MaxInt est l'entier le plus grand qu'on puisse stocker dans un type
         Integer 32 bits. Cet entier est égal à 2 147 483 647, c'est-à-dire
         $7FFFFFFF en hexa. Ainsi, il est possible de dire que l'étendue
         d'une variable Integer va de +MaxInt à -MaxInt.

MaxShort MaxShort est l'entier le plus grand qu'on puisse stocker dans un
         type Short 16 bits. Celui-ci s'avère être 32 767 ou $7FFF en hexa.
         Comme pour MaxInt, il est possible d'affirmer que l'étendue d'une
         variable Short va de +MaxShort à -MaxShort (pour être exact,
         l'intervalle se situe réellement entre +MaxShort et -(MaxShort+1),
         ce qui est analogue à MaxInt).

Nil      Nil est une constante de type Address. Elle est définie sous la
         forme suivante :

                Nil = Address(0);

         En Pascal Standard, "Nil" est un mot réservé. En Pascal PCQ il ne
         l'est pas pour la simple raison qu'il n'a pas à l'être.

True     True est une énumeration de type Booléen et actuellement sa valeur
         est égale à -1. Dans certains cas, n'importe quel chiffre -dont la
         valeur sera différente de zéro- fera l'affaire, mais l'opérateur
         "not" se comportera de façon capricieuse, si l'on emploie des
         valeurs erronées.




============================================================================

                        Déclarations de Variables

============================================================================

Les déclarations de variables sont gérées comme en Pascal standard :

<Déclaration de Var> ::= Var <Définitions de Var> ;

<Définitions de Var> ::= <Définition de Var> |
                         <Définition de Var> ; <Définitions de Var>

<Définition de Var>  ::= <Liste des Identif.rs> : <Spécification de Types>

Les variables globales, c'est-à-dire celles déclarées dans la partie plus
extérieure, sont réservées en tant que mémoire statique. Toutes les
variables déclarées à l'intérieur d'une procédure ou d'une fonction sont
réservées sur la pile, par conséquent, si vous êtes en train d'êcrire des
routines "ré-entrantes", assurez-vous d'éviter d'écrire dans les variables
globales.

Les variables d'une taille supérieure à un octet sont toujours réservées
dans la limite d'un mot (et non dans la limite d'un mot long - nous devrons
donc utiliser AllocMem pour garantir cette limite). En Turbo Pascal, ceci
est optionnel, mais le 68000 rend cela obligatoire dans un programme Amiga.
Notez que ceci s'applique aussi bien aux tableaux qu'aux enregistrements,
par conséquent soyez attentif si vous faites des hypothèses sur la taille
et sur l'emplacement des variables.

N'oubliez pas que les variables locales (et non les constantes typées)
disparaissent lorsqu'on quitte la fonction, ainsi vous ne devriez pas
essayer d'y accéder par la suite (avec une variable pointeur, par exemple).
Cela ne marcherait pas. 


 Variables Standard
--------------------

Il y a plusieurs variables incorporées dans le Pascal PCQ. Celles-ci sont
toujours disponibles et sont traitées comme variables globales. Les voici :

CommandLine     C'est une variable 'String' qui pointe sur la ligne de
                commande tapée par l'utilisateur (avec le nom du programme
                et tous les paramètres d'indirection invalidés). Si le
                programme a été lancé à partir du Workbench, cette valeur
                ne sera pas définie. Remarquez que, pour ne pas prendre de
                risques, cette variable devrait être utilisée seulement en
                lecture. Faites-en une copie, si vous voulez lui faire subir
                des modifications.

ExitAddr        ExitAddr est l'emplacement à l'intérieur du programme où
                s'est produite une erreur lors de l'exécution. S'il n'y a
                pas eu d'erreur, cette valeur sera indéfinie. Pour plus de
                renseignements, voyez la section "Procédures de Sortie".

ExitCode        Il s'agit d'une valeur 'Integer' qu'on retournera à
                l'AmigaDOS à la fin du programme. Celle-ci n'est définie
                qu'à l'intérieur d'une procédure de sortie.

ExitProc        Il s'agit d'une variable 'Address' contenant l'adresse de
                la première procédure à exécuter lorsque le programme prend
                fin. Pour plus de renseignements, voyez la section
                "Procédures de Sortie".

HeapError       HeapError est une variable 'Address' contenant l'adresse
                d'une fonction à appeler lorsque New() ou AllocString() sont
                dans l'impossibilité d'allouer un bloc de mémoire. Pour plus
                de renseignements, voyez la section "Gestion de la Mémoire".

Input           Input est un fichier de type 'Text'. Il correspond au canal
                d'entrée standard du programme, c'est-à-dire le CLI d'où on
                a lancé le programme. En PCQ, les programmes instaurent
                toujours une espèce de fichier Input standard à moins qu'on
                ne leur dise de ne pas le faire de manière spécifique. Pour
                plus de renseignements, voyez la section "Entrées/Sorties".

Output          Output est un type de fichier 'Text'. Il correspond au canal
                de sortie standard du programme, qui, dans la plupart des
                cas, est le CLI d'où on a lancé le programme. En Pascal PCQ,
                les programmes instaurent toujours un fichier de sortie à
                moins qu'on ne leur dise de ne pas le faire.




============================================================================

                 Déclarations de Procédures et de Fonctions

============================================================================

Les procédures et les fonctions vous permettent de définir des routines
communes à l'intérieur d'un bloc plus grand. Les procédures sont exécutées
par les instructions de procédure et les fonctions sont exécutées quand
elles sont employées dans des expressions. Le format de définition des
procédures et des fonctions et le suivant :


<Déclaration de Proc> ::= Procédure <Identificateur> ; <Corps> |
                          Procédure <Identificateur>
                                ( <Paramètres Formels> ); <Corps>

<Corps> ::= <Bloc> | External | Forward

<Paramètres Formels> ::= <Liste d'Identif.rs> : <Spécification de Types> |
                         var <Liste d'Identif.rs> : <Spécification de Types>

<Déclaration de Fonc> ::= Fonction <Identificateur> :
                                   <Spécification de Types> ; <Corps> |
                          Fonction <Identificateur> ( <Param.s Formels> ) :
                                   <Spécification de Types> ; <Corps>


Au risque de me répéter, n'oubliez pas que vous avez la possibilité de vous
servir des procédures seulement là où la notation BNF fait appel à une
<Instruction> et que vous avez la possibilité d'appeler des fonctions
seulement là où la notation BNF fait appel à une <Expression>.


 Passage de Paramètres
-----------------------

Pascal offre deux manières différentes pour le passage de paramètres. Le
premier type de paramètres s'appelle paramètres de valeur. C'est le cas
normal. Quand vous passez un paramètre par valeur, le compilateur fait une
copie de la valeur et la met en circulation. C'est comme si quelqu'un vous
disait d'étudier le portrait de Mona Lisa, en vous donnant des photos à
regarder. Vous pourrez dessiner une paire de moustaches sur la photo, mais
ceci n'affectera aucunement l'original; de même, quoi qu'elles fassent au
paramètre, la procédure ou la fonction, cela n'affectera en rien les valeurs
originales. Quand vous appelerez la procédure, vous pourrez employer toute
sorte d'expressions (naturellement, d'un type correct) comme paramètre réel.

L'autre type de paramètres s'appelle paramètres de référence. On les
spécifie en faisant précéder le nom du paramètre par le mot réservé "var",
dans l'en-tête de la procédure ou de la fonction. Quand vous employez les
paramètres de référence, c'est comme si quelqu'un vous demandait d'étudier
le portrait de Mona Lisa, qu'il vous envoie au Louvre et qu'il vous dise où
se trouve le tableau. Dans ce cas, vous travaillerez sur l'original et il
vaudra mieux que vous fassiez attention au tableau. Les paramètres de
référence devront être fournis comme références à des variables - ils ne
pourront être représentés par des expressions complètes. En outre, les
paramètres de référence devront subir un test de compatibilité de type plus
sévère que celui que subissent les paramètres de valeur, étant donné que
nous ne pouvons admettre une procédure qui essaie d'écrire un entier sur 4
octets dans l'espace d'un octet.

Habituellement, vous devriez préférer les paramètres de valeur à ceux de
référence (ils ont tendance à réduire les bogues), sauf dans trois cas. Le
premier quand vous voulez réellement affecter la valeur d'une variable. Le
deuxième quand le paramètre est grand. Si vous employez un paramètre de
valeur, le compilateur devra faire une copie complète de celui-ci sur la
pile avant d'appeler la routine, ce qui prend du temps et consomme de
l'espace dans la pile. Si vous employez un paramètre de référence, le
compilateur se limite à mettre l'adresse sur la pile. Le troisième cas se
vérifie quand le paramètre est de type fichier et, dans ce cas, il devra
être passé par référence.

Le Pascal PCQ pousse les arguments sur la pile de gauche à droite. Les
compilateurs C, étant donné qu'ils doivent supporter un nombre variable
d'arguments, poussent les arguments de droite à gauche. Par conséquent, si
vous envisagez d'appeler des routines écrites en C, il vous faudra ordonner
à nouveau soit l'ordre de l'appel soit l'ordre de la routine.


 Procédures 'Forward ' et Fonctions
------------------------------------

En Pascal, chaque identificateur doit être déclaré avant qu'on puisse
l'utiliser. Ceci crée des problèmes lorsque des procédures ou des fonctions
dépendent l'une de l'autre; par conséquent, le Pascal permet de pré-définir
des procédures et des fonctions qui seront entièrement définies par la suite
dans le code source.

Une référence 'forward' ressemble à une procédure ou à une déclaration de
procédure ou fonction normale, mais présente le mot réservé "Forward" sur sa
droite après l'en-tête. L'en-tête contient toute l'information dont a besoin
le compilateur pour appeler correctement une routine, ce qui fait qu'on peut
se servir d'une routine après une déclaration 'forward'. Eventuellement, si
la routine est définie, le compilateur s'assure qu'elle correspond à la
définition donnée auparavant. Cela signifie qu'elle devra avoir le même
nombre de paramètres, que le type des paramètres devra être identique et,
s'il s'agit d'une fonction, que le type du résultat devra être le même.
Remarquez que le vrai nom des paramêtres peut être différent - seuls sont
comparés le nombre, l'ordre et le type.

Une référence 'forward' doit être résolue à l'intérieur du bloc où elle a
été déclarée et il n'est pas permis de faire une référence 'forward' sur une
même routine plus d'une fois.


 Références Externes
---------------------

Les références externes ressemblent beaucoup plus au références 'forward' -
ce sont des déclarations de routines qui ne sont pas vraiment tout à fait
définies. La différence est que les références 'forward' devront être
définies plus loin dans le même fichier programme, tandis que les références
externes ne sont aucunement définies dans le fichier source.

La déclaration d'une référence externe se fait de la même manière que celle
d'une référence 'forward', mais on emploie le mot réservé "External" au lieu
du mot "Forward".

On emploie les références externes dans deux buts bien précis. En premier
lieu, celles-ci permettent d'utiliser des procédures et des fonctions qu'on
aura définies dans des fichiers externes. Toutes les routines système,
déclarées dans les fichiers 'include', par exemple, sont en réalité définies
dans des fichiers externes. Elles permettent aussi d'appeler des routines
compilées dans d'autres langages, tant que vous suivrez certaines règles
dans le passage des paramètres. Pour plus de renseignement sur l'emploi des
routines externes, voyez la section "Fichiers Externes".


 Procédures Standard
---------------------

Il existe plusieurs procédures incorporées dans le Pascal PCQ. Celles-ci
comprennent :


               Close(VariableFichier : Tout type de fichier)

La procédure "Close" dissocie la VariableFichier du fichier qui se trouve
physiquement sur la disquette et libère toutes les ressources du systèmes
utilisées pour garder le fichier ouvert. Pour plus de renseignements, voyez
la section "Entrées/Sorties".


   Dec(V : Tout ordinal ou pointeur) ou Dec(V, Total : Integer)

Dec (qui est 'short' dans une décrémentation) soustrait un (ou plus) d'une
variable.  "Dec(x,n)" est identique à "x := x-n", mais un peu plus efficace.
La variable doit être un type ordinal comme Char, Byte, Integer, etc., ou un
type pointeur. Le paramètre Total, qui est optionnel, doit être de type
entier - si on n'en met pas, on prend en considération la valeur un.

Si la variable est un type ordinal, la valeur sera soustraite d'une manière
normale. Toutefois, si la variable est un type pointeur, Dec() multiplie le
Total par la taille du type à qui le pointeur fait référence. En d'autres
termes, si vous avez un pointeur p de type ^Integer, l'instruction Dec(p)
soustrait en réalité 4 du pointeur.


                  Dispose(Variable : ^NImporteQuoi)

La procédure "Dispose" libère une partie de mémoire réservée au préalable
par la procédure "New" (cf. ci-dessous). Pour plus de renseignements sur
les routines de PCQ qui gèrent la mémoire, voyez la section "Gestion de la
Mémoire".


                   Exit ou Exit(CodeRetour : Integer)

Exit, comme les fonctions C et AmigaDOS de même nom, met fin à un programme.
Si l'on indique un code retour, celui-ci sera retourné à l'AmigaDOS. Par
convention, d'ordinaire, le code retour est égal à 5, en cas de petits
inconvénients (avertissements), égal à 10 pour des problèmes plus importants
(erreurs) et égal à 20 quand rien ne va plus (échecs). L'emploi d'Exit sans
code retour est identique à Exit(0), qui indique que tout va bien.

Pour le système, Exit est une façon sûre d'abandonner un programme - vous
n'aurez pas à appeler la routine DOSExit() de l'AmigaDOS. Quand on appelle
Exit, toutes les procédures de sortie sont appelées à leur tour. Cet appel
comprend la routine normale qui ferme tous les fichiers et libère la mémoire
ainsi que tout ce qu'on aurait pu définir auparavant.


                Get(var VariableFichier : Un type fichier)

La procédure "Get" déplace le pointeur du fichier sur l'élément suivant du
fichier sans vraiment lire chaque élémént. On peut accéder à l'élément qui
se trouve dans le tampon du fichier par la syntaxe VariableFichier^. Pour
des détails, voyez la section "Entrées/Sorties".


                Inc(RéférenceVar: Type Ordinal ou Pointer) ou
           Inc(RéférenceVar : Ordinal ou Pointeur, Total : Integer)

La commande "Inc" additionne un Total entier à la variable RéférenceVar. Si
l'on n'indique aucun Total, on considère que celui-ci est égal à un. Si la
variable est un type ordinal, l'addition est exécutée normalement, mais si
la variable est un type pointeur le Total est d'abord multiplié par la
taille de l'objet à qui le pointeur se réfère. En d'autres mots, Inc(p), où
p est un pointeur sur 'Integer', additionne en réalité 4 (la taille d'un
'Integer' en octets) à p.


                   New(VariablePointeur : ^NImporteQuoi)

La procédure "New" réserve un bloc de mémoire égal en taille au type sur qui
pointe la variable (qui doit être un type pointeur). L'adresse du bloc
nouvellement réservé sera assigné à la variable. Pour plus de renseignements
voyez la section "Gestion de la Mémoire".


                 Put(var VariableFichier : Un type fichier)

La routine "Put" fait avancer le pointeur de fichier après l'élément courant
et, si nécessaire, écrit ce dernier sur disquette. On peut mettre en place
l'élément courant par la syntaxe VariableFichier^. Pour plus de détails,
voyez la section "Entrées/Sorties".


    Read(var VariableFichier :  Texte ou Fichier, Références Variables...)

La procédure "Read" introduit l'information en partant d'un fichier
AmigaDOS. La VariableFichier est optionnelle et la procédure est l'une des
très rares procédures qui peuvent accepter un nombre d'arguments variable.
Pour plus de renseignements, voyez la section "Entrées/Sorties".


          Readln(var VariableFichier : Texte, Références Variables...)

La procédure "Readln" est très semblable à "Read", mais ne peut être
employée qu'avec des fichiers 'Text'; après avoir lu tous les arguments dont
elle a besoin, elle continue à "avaler" des caractères jusqu'au début de la
ligne suivante. Pour plus de renseignements, voyez ci-dessous la section
"Entrées/Sorties".


                  Reset(var VarFichier : File ou Text;
                          NomDeFichier : String;
                          TailleTampon : Integer);

La procédure "Reset" ouvre un fichier en lecture. Le paramètre TailleTampon
est optionnel. Si vous vous êtes servi de la directive {$I-} pour indiquer
une vérification manuelle, vous devez vous assurer que vous avez bien fait
la vérification de IOResult pour voir si le fichier a été ouvert de façon
correcte. Si vous êtes en train de vous servir d'une vérification d'E/S
automatique, le programme prendra fin avec une erreur de l'exécutable si le
fichier ne s'est pas ouvert d'une manière correcte. Pour plus de détails,
voyez ci-dessous la section "Entrées/Sorties".


                Rewrite(var VarFichier : File ou Text;
                          NomDeFichier : String;
                          TailleTampon : Integer);

La procédure "Rewrite" ouvre un fichier en sortie, en effaçant tout autre
fichier existant ayant le même nom. L'argument TailleTampon est optionnel.
Si le fichier ne peut être ouvert, IOResult prendra une valeur différente de
zéro. Si vous employez une vérification automatique des E/S, ceci provoque
l'arrêt du programme avec une erreur de l'exécutable. Si vous vous servez
d'une vérification manuelle, assurez-vous de regarder IOResult pour être
certain que le fichier est ouvert. Pour plus de détails, voyez ci-dessous la
section "Entrées/Sorties".


                     Trap(NuméroDuTrap : Integer)

La procédure "Trap" peut être utilisée par certains débogueurs comme une
sorte de point d'arrêt automatique. Si vous insérez un trappage correct, le
débogueur pourrait s'arrêter à cette adresse. Par la suite, il pourrait ne
plus s'y arrêter.


             Write(VariableFichier : Text ou File, Expressions...)

La procédure "Write" envoie une information en sortie sur un fichier
AmigaDOS. La VariableFichier est optionnelle et peut prendre un nombre
d'arguments variable. Pour des détails, voyez la section "Entrées/Sorties".


                Writeln(VariableFichier : Text, Expressions....)

La procédure "Writeln" est très semblable à "Write", mais ne fonctionne
qu'avec les fichiers Text et met fin à la ligne après écriture de tous ses
arguments. Encore un fois, pour plus de renseignements, voyez la section
"Entrées/Sorties".


 Fonctions Standard
--------------------

Il existe un paquet de fonctions qui sont incorporées au compilateur Pascal.
Les voici :

                  Adr(Référence Variable) : Address

La fonction Adr() retourne la véritable adresse en mémoire du paramètre.
Cette fonction est équivalente à la fonction Addr() de Turbo Pascal et comme
en Turbo Pascal vous pouvez employer aussi l'opérateur @.

             Abs(expression numérique) : même type numérique

L'appel à la fonction Abs(n) retourne n, si n est positif et -n si n est
négatif.

               ArcTan(Expression numérique) : Real radiants

La fonction ArcTan() retourne l'arc-tangente approchée d'un paramètre en
radiants.

                    Bit(NuméroDuBit) : Masque Integer

La fonction Bit() retourne un Integer dont elle aura mis à 1 le bit indiqué.
Elle est équivalente à (1 shl NuméroDuBit).

                     Chr(expression numérique) : Char

La fonction Chr() transforme n'importe quel type numérique en son caractère
ASCII équivalent.

                     Ceil(expression réelle) : Real

Ceil() retourne le plus petit entier supérieur ou égal au paramètre fourni.

              Cos(expression numérique en radiants) : Real

La fonction Cos() retourne le cosinus d'un angle donné mesuré en radiants.

                  EOF(variable File ou Text) : Boolean

EOF retourne True si le fichier est parvenu à la position fin-de-fichier ou
alors elle retourne False. La fonction EOF n'est valide que pour les
fichiers ouverts en entrée. Pour plus de renseignements, voyez la section
"Entrées/Sorties".

                      Exp(expression numérique) : Real

La fonction Exp(x) retourne e élevé à la nième puissance. Au cas où cela
vous échapperait, e est égal à 2,71828... environ.

                      Float(expression entière) : Real

La fonction Float() transforme toute expression de type entier en sa
représentation en virgule flottante. Si l'entier est trop grand, on pourra
avoir une valeur approchée. Ainsi "Trunc(Float(VarEntière)) = VarEntière"
n'est pas toujours vrai.

                       Floor(expression Real) : Real

La fonction Floor() retourne le plus grand nombre entier inférieur ou égal
au paramètre fourni.

                           IOResult : Integer

La fonction IOResult() vérifie pour voir si une erreur est intervenue depuis
qu'on a fait la dernière vérification. Normalement, le Pascal PCQ insère des
instructions pour vérifier IOResult de façon automatique, mais, si vous avez
invalidé la vérification des E/S (par l'emploi de la directive {$I-}), vous
devrez faire la vérification de manière explicite. L'action de vérification
efface le résultat de la vérification elle-même, ainsi s'il vous faut
réemployer le résultat, vous devrez le sauvegarder dans une variable. Pour
plus de renseignements, voyez la section "Entrées/Sorties".

                     Ln(expression numérique) : Real

La fonction Ln() retourne le logarithme naturel (c'est-à-dire le logarithme
en base e) du paramètre fourni.

                   Odd(expression numérique) : Boolean
              
La fonction Odd() retourne TRUE si son argument est impair, autrement elle
retourne FALSE.

                     Open(nomfichier  : String;
                       var varfichier : file ou Text;
                       TailleTampon   : Integer) : Boolean;

Open représente la forme fonction de la procédure Rewrite. Elle ouvre un
fichier en sortie en effaçant tout autre fichier existant ayant le même nom.
Si le fichier s'ouvre correctement, Open retourne True. En cas contraire,
elle retourne False. Le paramètre TailleTampon est optionnel. Pour plus de
renseignements, voyez la section "Entrées/Sorties".

                     Ord(expression ordinale) : Integer

La fonction Ord() retourne la valeur ordinale de l'argument sous forme d'un
Integer. En d'autres termes, elle peut transformer des types Caractères,
Booléens et énumérés en leurs types numériques équivalents. Comme elle
transforme réellement le type de l'argument en un Integer, on fait référence
à cette fonction comme à une fonction de transfert.

                   Pred(expression ordinale) : même type

La fonction Pred() retourne la prochaine plus petite valeur ordinale de même
type. Par exemple, Pred(2) est égale à 1. Si l'argument est la plus petite
valeur à l'intérieur de ce type (telle que Pred(VarOctet), où VarOctet est
égale à zéro), le comportement de la fonction sera indéterminé.

                      ReOpen(nom fichier    : String;
                        var varfichier : file ou text;
                        TailleTampon : Integer) : Boolean

ReOpen représente la forme fonction de Reset. Elle ouvre un fichier en
lecture et retourne True si tout s'est bien passé. Si, pour une raison
quelconque, le fichier ne s'est pas ouvert correctement, ReOpen retournera
False. Le paramètre TailleTampon est optionnel et peut prendre n'importe
quelle valeur. Pour plus de détails, voyez la section "Entrées/Sorties".

                    Round(expression réelle) : Integer

La fonction Round() arrondit une expression réelle à l'entier le plus
proche. En réalité, la fonction est implémentée sous la forme Trunc(valeur +
 0.5), ce qui fait qu'elle met un peu plus de temps à s'exécuter que la 
fonction Trunc. En outre, elle arrondit toujours au-dessus de 0,5.

               Sin(expression numérique en radiants) : Real

La fonction Sin() calcule le sinus d'un angle mesuré en radiants.

                 SizeOf(Identificateur de type) : Integer

La fonction SizeOf() retourne la taille réelle d'un type donné. Notez que le
type devra être spécifié en tant qu'identificateur unique.

                  Sqr(expression numérique) : même type

La fonction Sqr(x) retourne x*x.

                   Sqrt(expression numérique) : Real

La fonction Sqrt(x) retourne la racine carrée de x. En d'autres termes,
Sqrt(x) * Sqrt(x) = x.

                 Succ(expression ordinale) : même type

La fonction Succ() retourne la valeur ordinale suivante plus grande à
l'intérieur d'un même type. Si la valeur n'a pas été définie (par exemple,
Succ(n), où n est une énumération plus grande à l'intérieur d'un type), la
fonction n'est pas déterminée.

              Tan(expression numérique en radiants) : Real

Retourne la tangente de l'angle mesurée en radiants. Si le paramètre est un
multiple impair de Pi/2, la fonction prendra des valeurs sans signification
(la fonction tangente est indéterminée pour les multiples impairs de Pi/2).

                   Trunc(expression réelle) : Integer

La fonction Trunc() retourne la partie entière d'un nombre en virgule
flottante. C'est la manière plus rapide pour transformer une valeur réelle
en une valeur entière.




============================================================================

                          Déclaration d'Etiquettes

============================================================================

On doit déclarer les étiquettes dans la partie déclaration avant de pouvoir
s'en servir dans un programme. La partie déclaration d'étiquettes a la forme
suivante :

<Déclarations d'Etiquettes> ::= Etiquette <Identificateurs> ;

<Identificateurs> ::= <Identificateur> | <Identificateur> , <Identif.rs>

Notez que le Pascal Standard et le Turbo Pascal permettent aussi d'avoir des
étiquettes avec des valeurs numériques, mais que seul le Pascal PCQ permet
d'employer des identificateurs normaux. Si vous étiez en train de parcourir
un programme avec des étiquettes numériques, vous n'auriez qu'à mettre des
lettres devant les identificateurs autorisés. Remarquez que, peut-être, une
meilleur solution serait de balancer le programme.




============================================================================

                               Expressions

============================================================================

Le Pascal PCQ accepte des expressions très proches dans leur forme par
rapport à toute autre implémentation du Pascal. Ces expressions vous seront
probablement très familières, mais pour qu'il n'y ait pas d'erreur possible
nous allons les définir. Commençons par les constantes que PCQ accepte :

<chiffre>           ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

<chiffres>          ::= <chiffre> | <chiffre> <chiffres>

<chiffre binaire>   ::= 0 | 1

<chiffres binaires> ::= <chiffre binaire> |
                        <chiffre binaire> <chiffres binaires>

<chiffre hexa>      ::= <chiffre> | a | b | c | d | e | f

<chiffres hexa>     ::= <chiffre hexa> | <chiffre hexa> <chiffres hexa>

<Const Float>       ::= <chiffres> . <chiffres>

<Const Integer>     ::= <chiffres> | $ <chiffres hexa> | % <chiffres bin.es>

<Valeur Char>       ::= <caractère ASCII> | \ <séquence 'escape'>

<Valeurs Char>      ::= <Valeur Char> | <Valeur Char> <Valeurs Char>

<Const Nombre>      ::= <Const Integer> | <Const Float>

<Const Char>        ::= ' <Valeur Char> '

<Const String>      ::= " <Valeurs Char> "
                    
<Const Array Char>  ::= ' <Valeurs Char> '


Ceci devrait embrouiller un peu les choses. Cela veut dire que bien que le
compilateur s'attende à un entier, il est possible d'employer une
réprésentation décimale, hexadécimale ou binaire. Cela veut dire aussi que
les constantes en virgule flottante ne sont reconnues que sous leur forme
normale 23.23, sans aucun exposant à la fin. Pour conclure, cela veut dire
qu'il est possible d'employer des séquences 'escape' dans le style du C pour
n'importe quelle constante texte - ces séquences 'escape' seront traitées
dans la section "Chaînes de Caractères".

Quelles sont toutes ces choses regroupées dans des expressions complètes ?
Analisez les définitions suivantes :

<expression>  ::= <simple> <op relation> <simple> | <simple>

<op relation> ::= = | <> | < | > | <= | >=

<simple>      ::= <terme> <op addition> <terme> | <terme>

<op addition> ::= + | - | or | xor

<terme>       ::= <facteur> <op multiplication> <facteur> | <facteur>

<op multiplication> ::= * | / | div | mod | and | shr | shl

<facteur>     ::= <Const Nombre>           |
                  <Signe> <Const Nombre>   |
                  <Const Char>             |
                  <Const String>           |
                  <Const Array Char>       |
                  <Référence Variable>   |
                  @ <Référence Variable> |
                  not <facteur>            |
                  ( <Expression> )         |
                  <Appel de Fonction>

[NdT. op = opérateur].


Qu'est-ce que tout cela signifie ?  Cela signifie que les expressions sont
construites à partir de facteurs, qui sont les blocs élémentaires d'une
expression. Un facteur peut être une constante, une expression mise entre
parenthèses et toute autre chose listée ci-dessous. Les exemples suivants
représentent tous des facteurs :

                                 23
                            (4.0 - 2.3)
                             %01000001
                                'a'
                      PtrEnreg^.Champ1[45,23]
                               @Var1
                             Abs(Var2)

Les facteurs peuvent avoir un opérateur unaire (un opérateur qui s'applique
à une seule valeur, à la différence de l'opérateur binaire qui s'applique à
deux valeurs). Voici ces opérateurs :

        @   Cet opérateur est l'opérateur d'adresse. Il retourne
            l'adresse de la référence variable qui le suit
            immédiatement. Il est équivalent à la fonction Adr().
        -   Négation de signe. Prend la négation du facteur qui le
            suit immédiatement.
        +   Identité de signe. Il est accepté, mais ne produit aucun
            effet.
       not  Négation booléenne ou de bit. Si le facteur est une
            valeur booléenne, il retournera l'inverse. S'il s'agit
            d'un type entier, il retournera le bit complémenté.

Ces facteurs sont intégrés à l'intérieur de termes. Les termes sont soit
identiques aux facteurs, soit deux facteurs avec un signe de multiplication
entre eux. Les opérations de multiplications sont les suivantes :

        *   Multiplication
        /   Division en virgule flottante. Les deux arguments de cet
            opérateur sont transformés en valeurs en virgule flottante
            avant d'exécuter l'opération.
       div  Division d'entiers. Les deux arguments de cet opérateur
            sont transformés sous forme d'entiers, avant d'exécuter
            l'opération.
       mod  L'opération reste. Si nécessaire, les deux arguments sont
            transformés en entiers.
       and  Fonction logique AND. Si les deux arguments sont des
            valeurs booléennes et que le facteur de gauche donne une
            évaluation FALSE, l'opération sera "court-circuitée".
            Tous les facteurs réels sont transformés en entiers.
       shl  Décalage à gauche. Décale les bits de l'opérande gauche
            du nombre de positions indiqué par l'opérande droite.
            Si nécessaire, les deux arguments sont transformés en
            entiers.
       shr  Décalage à droite. Décale les bits de l'opérande droite
            du nombre de positions indiqué par l'opérande droite.
            Il s'agit d'un décalage logique et non arithmétique, par
            conséquent, on assigne 0 au bit le plus à gauche. Ainsi,
            si l'on décale un nombre négatif pour faire une division,
            vous obtenez un résultat sans signification (à la place,
            servez-vous de div - il emploiera les décalages si cela
            est possible). Les deux arguments sont transformés en
            entiers.

A leur tour, les termes sont intégrés dans des expressions simples. Les
expressions simples sont soit identiques aux termes, soit deux termes
regroupés par un opérateur d'addition. Voici les opérateurs d'addition :

        +   Additionne deux opérandes.
        -   Soustrait la deuxième opérande de la première.
        or  OR logique. Si les deux opérandes sont des valeurs
            booléennes et que l'opérande de gauche donne une
            évaluation TRUE, l'opérande de droite ne sera pas
            évaluée. Si nécessaire, les deux arguments sont
            transformés en entiers.
       xor  OR exclusif. Génère le terme gauche à qui on aura
            appliqué une opération OR exclusif avec le terme
            droit. Cette opération n'est jamais court-circuitée.
            Si les deux arguments ont une valeur réelle, ils
            sont transformés en entiers.

Ces expressions simples sont intégrées dans des expressions complètes. Les
expressions sont soit identiques aux expressions simples, soit deux
expressions simples regroupées par un opérateur relationnel. Ces opérateurs
produisent des résultats booléens, et sont définis ci-dessous :

        =   Retourne TRUE "iff" les deux arguments sont égaux.
        <>  Retourne TRUE "iff" les deux arguments ne sont pas égaux.
        >   Retourne TRUE "iff" l'argument de gauche est supérieur à
            l'argument de droite.
        <   Retourne TRUE "iff" l'argument de gauche est inférieur à
            l'argument de droite.
        >=  Retourne TRUE "iff" l'argument de gauche est supérieur ou
            égal à l'argument de droite (celui-ci, évidemment, n'accepte
            qu'une seule comparaison).
        <=  Retourne TRUE "iff" l'argument de gauche est inférieur ou
            égal à l'argument de droite.

        ("iff" est une abréviation pour "if and only if", c'est-à-dire "si
         et seulement si".)


 Ordre d'Evaluation et Court-Circuits
--------------------------------------

Les règles mathématiques habituelles sont intégrées dans la grammaire des
expressions. En premier lieu, on évalue les opérateurs unaires, puis toutes
les opérations de multiplication, celles d'addition et enfin les opérations
relationnelles. Donc, la priorité ressemble à ce qui suit :

                    Opérateur           Priorité
                  -------------------------------------
                    @,not,unary +/-     Premier (plus haute)

                    *,/,div,mod,
                    and,shr,shl         Deuxième

                    +,-,or,xor          Troisième

                    =,<>,<,>,>=,<=      Quatrième (plus basse)

Naturellement, toutes les expressions entre parenthèses sont évaluées en
premier. En outre, il ne faut pas oublier que tous ces opérateurs obéissent
à une règle associative à partir de la gauche - en d'autres mots, un facteur
entre deux opérateurs de priorité égale est associé au facteur de gauche
(par ex., "x+y+z" est traité en tant que "(x+y)+z").

Vous ne devrez tirer aucune conclusion sur l'ordre dans lequel sont évaluées
deux opérandes dans un opérateur binaire. Si, par exemple, vous aviez une
expression de type "fonction1 + fonction2" dans votre programme, il n'est
pas dit quelle fonction sera évaluée en premier.

Une exception à cette règle est constituée par les équations booléennes,
mais seulement si vous employez des évaluations "court-circuitées" (celles
existant par défaut). Qu'est-ce qu'un court-circuit ?  Imaginons que vous
ayiez l'expression "A or B" dans votre programme. Si celui-ci évalue A et
trouve que A est True, le programme connaîtra déjà la valeur finale de
l'expression toute entière. Un cas analogue intervient avec "A and B"
lorsque A est évalué en tant que False. Dans une expression booléenne, on
peut vous assurer que le deux opérandes de "and" et "or" seront évaluées de
gauche à droite.

Les évaluations "court-circuitées" sont souvent plus rapides que celles
normales, mais elle offrent en outre l'avantage de protéger le programmeur.
Par exemple, l'instruction

        if OpenMyWindow(w) and (w^.Width = whatever) then ...

... deviendrait un problème sans une évaluation "court-circuitée" car, par
exemple, la variable w ne pourrait être définie si l'appel à la fonction
venait à échouer. La valeur de la fonction ne changerait pas, mais si W
pointait sur une adresse impaire il pourrait provoquer un gourou. Grâce aux
évaluations "court-circuitées", le deuxième facteur ne sera pas évalué tant
que le premier retournera une valeur True.


 Expressions de Constantes
---------------------------

Les expressions de constantes sont identiques aux expressions normales, mais
doivent être entièrement évaluées lors de la compilation. Par conséquent,
elles ne pourront faire appel à aucune fonction externe ou à des références
variables, mais pourront toutes faire appel aux mêmes opérateurs et aux
fonctions standard (c'est-à-dire celles intégrées au compilateur).


 Références Variables
----------------------

Les références variables peuvent paraître horriblement complexes avec tous
leurs pointeurs, leurs enregistrements, leurs tableaux et avec tout ce qui
s'ensuit. Leur syntaxe élémentaire est la suivante :

<Référence Variable> ::= <Marque de Variable> |
                           <Marque de Variable> <Sélecteurs>

<Marque de Variable> ::= <ID de la Variable> |
                         <ID du Type> ( <Référence Variable> )

<Sélecteurs>  ::= <Sélecteur> | <Sélecteur> <Sélecteurs>

<Sélecteur>   ::= ^ | .<Id du Champ> | [ <Expressions indexées> ]


En général, une référence variable est composée d'un identificateur, d'une
d'une variable globale ou locale, suivi d'un nombre quelconque de sélecteurs
selon une combinaison quelconque. L'autre possibilité, qui est quelque peu
différente par rapport à la version 1.2 du compilateur, est qu'on a la
possibilité de mettre en place une conversion de type au beau milieu de tout
cela. Ci-dessous, nous donnons des exemples de références variables :

                          Var1
                          Var1^
                          Var1^.Champ1[34,56]
                          Type2(Var1)^.Champ2^^[23]

Si vous commencez à écrire un programme comme celui que nous donnons dans le
dernier exemple, vous aurez quelques restes.




============================================================================

                              Instructions

============================================================================

Les instructions sont le plat de résistance d'un programme - c'est ce qu'on
trouve entre le 'begin' et le 'end'. Elles ont la forme suivante :

<Instruction>   ::= <Instruction If>             |
                    <Instruction While>          |
                    <Instruction Repeat>         |
                    <Instruction For>            |
                    <Instruction Case>           |
                    <Instruction With>           |
                    <Instruction Composée>       |
                    <Instruction d'Assignation>  |
                    <Appel de Procédure>         |
                    <Instruction Return>         |
                    <Instruction Goto>


 Instructions If
-----------------

L'instruction if vous permet de tester les alternatives. Elle a la forme
suivante :

<Instruction if> ::= if <Expr Booléenne> then <Instruction> |
                     if <Expr Booléenne> then <Instruction>
                                         else <Instruction>

Si l'expression booléenne évalue True, l'instruction qui suit le mot "then"
est exécutée. Si l'expression booléenne évalue False, on évalue alors
l'instruction présente dans la clause "else", si celle-ci existe. S'il n'y a
pas de clause, l'exécution continue avec l'instruction qui se trouve après
l'instruction "if".

Ici, il y a une ambiguité - examinez le fragment suivant :

        if Expr then if Expr then Instruction1 else Instruction2

A quel test "if" s'applique la clause "else" ?  PCQ, comme plusieurs autres
implémentations, relie la partie "else" à l' "if" le plus proche.


 Instructions While
--------------------

L'instruction "while" est une de celles qui permettent de faire des boucles.
Elle a la forme suivante :

<While Instruction> ::= while <Expr Booléenne> do <Instruction>

Au début de la boucle, on évalue l'expression booléenne. Si le résultat de
l'évaluation est True, la partie instructions est exécutée. Quand cette
partie prend fin, l'expression est évaluée une nouvelle fois et le processus
continue tant que l'expression ne donne pas une évaluation False. Dès que
cela arrive, l'exécution continue avec l'instruction qui se trouve après
l'instruction "while".


 Instructions Repeat
---------------------

L'instruction "Repeat" permet une forme de bouclage légèrement différente.
Elle a la forme suivante :

<Instruction Repeat> ::= repeat <Instructions> until <Expr Booléenne>

<Instructions> ::= <Instruction> | <Instruction> ; <Instructions>

Lorsqu'on rencontre l'instruction "repeat", la partie instructions est
exécutée, puis on évalue l'expression booléenne. Si l'expression donne une
évaluation False, la partie instructions est éxécutée à nouveau. Si
l'expression donneune évaluation True, l'exécution continue avec
l'instruction suivante. Remarquez que les boucles "repeat" s'exécutent
toujours au moins une fois, tandis que les boucles "while" ne s'exécutent
pas du tout. Notez aussi que la partie <Instructions> peut être tout à fait
vide.


 Instructions For
------------------

L'instruction "for" fournit une troisième possibilité de bouclage dans les
cas où l'on connaît exactement le nombre d'itérations que doit faire la
boucle. Elle a la forme suivante :

<Instruction For> ::= for <Référence Variable> :=
                          <Expression> <Sens>
                          <Expression> do <Instruction>
<Sens> ::= to | downto

Notez qu'elle est différente par rapport à celle de la version 1.1 de PCQ.
Quand on rencontre une boucle "for", on évalue la première expression (la
valeur initiale) et cette valeur est stockée dans la référence variable
(qu'on appelle indice). Ensuite l'indice est comparé avec la deuxième
expression (la valeur finale). Si le sens est "to" et que l'indice est égal
ou inférieur à la valeur finale, la partie instructions est exécutée. A la
fin de tout cela, l'indice est incrémenté de un et testé à nouveau avec la
valeur finale. Tout ceci continue tant que l'indice ne sera pas supérieur à
la valeur finale; à cet instant, l'exécution continue avec l'instruction
suivante.

Si le sens est "downto", il se produit la même chose, si l'on excepte que
l'indice est décrémenté à chaque passe et la bouclage continue tant que
l'indice ne sera pas inférieur à la valeur finale.

Notez que la boucle "for" pourrait ne pas s'exécuter du tout si la valeur
initiale était plus grande que la valeur finale (pour les boucles "to" et,
inversement, pour les boucles "downto"). Notez aussi que la valeur finale
est évaluée totalement à chaque fois, pendant la boucle, par conséquent, si
vous avez à faire à une expression complexe, vous pourriez souhaiter de la
sauvegarder dans une variable avant l'instruction "for".

Vous pouvez toujours employer une boucle "while" ou "repeat" au lieu d'une
boucle "for" et, dans les faits, on emploie beaucoup moins la boucle "for".
Niklaus Wirth, le type qui a conçu le Pascal et le Modula-2, a réellement
laissé cette instruction en dehors de son dernier langage (Oberon).

On considère que c'est une erreur de modifier la variable indice à
l'intérieur d'une boucle, mais le Pascal PCQ ne respecte pas cette règle.
Naturellement, ce n'est pas une bonne idée.


 Instructions Case
-------------------

On utilise l'instruction Case pour tester une valeur en opposition à  une
série d'alternatives et pour traiter des instructions en conséquence. Elle a
la forme suivante :

<Instruction case> ::= case <Expression> of <Alternatives> end |
                       case <Expression> of <Alternatives>
                                         else <Instruction> end
    
<Alternatives> ::= <Alternative> | <Alternative> ; <Alternatives>

<Alternative>  ::= <Vals de Case> : <Instruction>

<Valeurs de Case> ::= <Val de Case> | <Val de Case> , <Valeurs de Case>

<Val de Case>  ::= <Expr de Const> | <Expr de Const> .. <Expr de Const>

Lorsqu'on exécute l'instruction "case", on évalue l'expression. Celle-ci est
ensuite comparée avec tous les cas et à tous les niveaux jusqu'à ce qu'elle
concorde avec l'un des "case"; à cet instant, l'instruction associée au
"case" en question est exécutée. Si aucune alternative ne concorde, on
exécute l'instruction "else", s'il en existe une. Si tel n'est pas le cas,
l'exécution se borne à continuer avec l'instruction "case" suivante.

Notez que l'expression n'est évalué qu'une seule fois et que par conséquent
une instruction "case" pourra être plus efficace qu'une suite d'instructions
"if" équivalente. Notez aussi qu'une seule instruction (au maxi) pour chaque
instruction "case" sera exécutée - ce n'est pas comme en C, où l'exécution
échoue tant qu'on ne lui dit pas de s'arrêter.


 Instructions With
-------------------

L'instruction With permet d'indiquer une variable d'enregistrement à qui on
appliquera une instruction. A l'intérieur de l'instruction, on peut abrégér
des références aux champs d'un enregistrement en indiquant seulement le nom
du champ. Ceci vous évite de la frappe et le compilateur génère un code un
peu plus efficace. Cela n'a aucun but fonctionnel. Le format d'une
instruction With est le suivant :

<Instruction With> ::= with <Expressions> do <Instruction>

<Expressions> ::= <Expression> | <Expression> , <Expressions>

Si l'on indique plus d'un enregistrement (en le séparant du précédent par
une virgule), le compilateur le traitera comme si celui-ci était emboîté
dans des instructions; le premier enregistrement aura une portée plus à
l'extérieur, tandis que le dernier aura une portée plus à l'intérieur.

Dans l'instruction, toute référence aux champs sera considérée comme
s'appliquant à l'enregistrement le plus à l'intérieur à qui elle s'applique.
On pourra éviter des ambiguités en se servant de la spécification qui prend
en compte la totalité de l'enregistrement.

Les instructions With sont particulièrement pratiques lorsque la référence
aux enregistrements est longue et compliquée - elles ne seront exécutées
qu'une seule fois, ce qui en augmente l'efficacité. Une autre circonstance
où elles s'avèrent bien pratiques est lors du remplissage des valeurs d'un
enregistrement. Elle n'améliorent pas toujours l'efficacité du programme,
mais elles évitent beaucoup de frappe au clavier.

Si vous êtes en train de programmer avec une instruction with qui se
présente sous la forme  "with p^ do ...", le fait d'altérer la valeur de p
est considéré come une erreur. Par exemple, c'est une erreur de libérer la
mémoire d'un enregistrement dans une instruction "with" qui fait référence à
l'enregistrement. Cette erreur n'est pas détectée par le Pascal PCQ et il
vaut mieux éviter de la faire.


 Instructions Composées
------------------------

L'instruction composée vous permet d'utiliser une suite d'instructions dans
toute situation qui fait appel à une instruction au minimum. Elle a la forme
suivante :

<Instruction Composée> ::= begin <Instructions> end

En réalité, une instruction composée peut être employée n'importe où l'on
autorise une instruction et l'instruction composée en elle-même ne génère
pas de code supplémentaire. En d'autres mots, le fait d'entourer un groupe
d'expressions par "begin" et "end" ne modifiera pas le code produit par le
compilateur - cela clarifie vos intentions.


 Instructions d'Affectation
----------------------------

Les instructions d'affectation sont employées pour fixer la valeur d'une
variable. Elles ont la forme suivante :

<Instruction d'Affectation> ::= <Référence Variable> := <Expression>

Souvenez-vous que le type de la variable doit concorder avec le type de
l'expression et ce de façon identique (pour les règles spécifiques, cf. la
section "Déclarations de Types").


 Appel de Procédures
---------------------

Les appels aux procédures transfèrent l'exécution à une routine déterminée
à l'avance, en lui passant les paramètres nécessaires. Ils ont la forme
suivante :

<Appel de Procédure> ::= <Identificateur> |
                         <Identificateur> ( <Paramètres Réels> )

<Paramètres Réels> ::= <Paramètre Réel> |
                       <Paramètre Réel> ; <Paramètres Réels>

<Paramètre Réel> ::= <Expression>

Les procédures sont différentes des fonctions car celles-ci retournent une
valeur et qu'on ne peut les appeler qu'à partir d'une expression. Les
procédures ne retournent pas de valeur et on ne les appelle qu'à partir
d'une instruction.

Lorsqu'on exécute une instruction de procédure, chaque paramètre réel est
évalué et poussé sur la pile dans un ordre de gauche à droite. Comme le C
emploie un nombre de paramètres variable, il les pousse sur la pile de
droite à gauche. Par conséquent, si vous envisagez d'appeler une routine en
C, il vous faudra retourner l'ordre des paramètres.


 Instructions Return
---------------------

D'ordinaire, l'exécution d'une procédure continue jusqu'à la fin de la
procédure, moment auquel l'exécution revient au programme appelant.
L'instruction "return" vous permet de vous échapper immédiatement de la
procédure en cours. Elle a cette forme très élémentaire :

                 <Instruction Return> ::= return

L'instruction "return" n'est valable qu'à l'intérieur d'une procédure. Elle
n'est pas valide à l'intérieur d'une fonction car celle-ci doit retourner
une valeur - dans une fonction, l'instruction analogue est l'assignation à
l'identificateur de la fonction qui provoque un retour immédiat. En outre,
une instruction "return" ne serait pas valide dans le corps principal du
programme car elle provoquerait la fin du programme. A la place, on devra
mettre fin au programme de façon explicite avec une instruction Exit.


 Instructions Goto
-------------------

L'instruction "goto" transfère immédiatement l'exécution à une étiquette
déterminée. On devra s'en servir avec une extrême vigilance et, si possible,
on devra l'éviter. Voici sa forme :

<Instruction Goto> ::= goto <Identificateur>

Le Pascal standard exige qu'une étiquette "goto" soit constituée d'une suite
de chiffres et le Turbo Pascal étend cette définition pour permettre
l'emploi d'identificateurs comme étiquettes. Le Pascal PCQ franchit l'étape
logique suivante en exigeant que les étiquettes soient des identificateurs
et non des chiffres.

Plusieurs programmeurs vous diront que l'instruction "goto" n'est qu'une
mauvaise habitude de programmation car elle rend difficiles la compréhension
et le débogage d'un programme. Il y a toutefois d'autres problèmes. Par
exemple, si vous faites un "goto" à l'intérieur d'une boucle "for" pour en
sortir, vous semerez le trouble dans la pile du programme (tant que vous
n'aurez pas quitté la routine). Il arrive des choses semblables avec
l'instruction "with". Je ne vous embêterais même pas en vous parlant de la
désorganisation qui s'en suit lorsqu'on saute dans une boucle "for" en
partant de l'extérieur de celle-ci.

Morale de l'histoire : essayez de les éviter.




============================================================================

                              Entrées/Sorties

============================================================================


 E/S du Pascal
---------------

Vous pouvez vous imaginer les routines d'E/S Pascal comme une interface avec
les routines de l'AmigaDOS. Les routines d'E/S du Pascal emploient toutes
l'AmigaDOS pour les opérations de lecture et d'écriture réelles. Ainsi, si
cela vous chante, il vous est possible d'employer un fichier AmigaDOS à la
place des routines du Pascal.

Toutefois, les E/S du Pascal présentent vraiment plusieurs avantages. En
tout premier lieu, tous les fichiers PCQPascal sont tamponnés, c'est-à-dire
que chaque opération de lecture et d'écriture n'entraîne pas nécessairement
un accès à l'AmigaDOS à chaque fois. Ceci accélère un peu les choses.

Un deuxième avantage est constitué par l'emploi des routines Read, ReadLn,
Write et Writeln du Pascal, qui peuvent s'avérer extrêmement pratiques.

Lorsque vous déclarez un fichier dans un programme, soit un "Fichier d'un
Type Quelconque" soit un fichier "Texte", vous vous réservez en réalité un
enregistrement. Celui-ci, si ces champs sont accessibles, ressemblera à :

     FichierPCQ = enregistrement
         Handle      : Un pointeur de fichier AmigaDOS
         Next        : Un pointeur sur le fichier Pascal suivant
         Buffer      : L'adresse du tampon du fichier
         Current     : La position dans le tampon où aura lieu la
                       prochaine lecture ou écriture
         Last        : La dernière position d'une lecture
         Max         : L'adresse de la fin du tampon+1
         RecSize     : La taille des éléments du fichier
         Interactive : Une valeur booléenne - True signifie que
                       le fichier est lié à une fenêtre CLI
         EOF         : Une valeur booléenne
         Access      : Une valeur Short, soit MODE_NEWFILE soit
                       MODE_OLDFILE
     fin;


 Fichiers Typés et Fichiers Texte
----------------------------------

Le Pascal possède deux types de fichiers très différents entre eux. Un
fichier de type normal s'appelle fichier typé et est déclaré avec une
spécification de type qui a la forme suivante :

                  VarFichier : Fichier de TypeElémentaire

Essentiellement, les fichiers typés sont des séquences illimitées d'éléments
avec un seul type d'éléments. On peut employer la commande Write pour écrire
des éléments individuels à la fin du fichier, ainsi que la comande Read pour
introduire l'élément courant et pour déplacer le pointeur de fichier sur
l'élément suivant. Dans chaque fichier typé, on ne peut écrire qu'un seul
type d'éléments.

Les fichiers typés stockent leurs éléments exactement dans le format dans
lequel ceux-ci apparaissent en mémoire, par conséquent, souvent, il n'est
pas possible de les lire. Un fichier composé d'éléments de type caractère
sera lisible, mais un fichier composé d'éléments entiers sera illisible.
Comme les fichiers typés stockent toujours des éléments complets, chacun des
éléments sera nécessairement d'une taille bien déterminée.

En réalité, vous n'aurez besoin de rien d'autre si l'on excepte les fichiers
typés - tout ce que vous pourriez avoir à faire avec des fichiers pourra
être fait avec des fichiers typés. Cependant, par amour de commodité, Pascal
utilise aussi les fichiers de type Texte. Le fichier Text fait partie d'une
catégorie particulière, celle des "File of Char" [Fichiers de Caractères],
mais n'est pas compatible avec cette dernière. Les fichiers texte sont
composés de caractères ASCII morcelés à l'intérieur de lignes de longueur
variable. Chaque ligne se termine par un caractère spécial de retour à la
ligne qui, sur l'Amiga, est le caractère de saut de ligne (valeur ASCII =
 10. Sur les machines MS-DOS, le caractère de retour de ligne est une
séquence composée d'un retour chariot et d'un saut de ligne).

Etant donné que les fichiers Text (comme cette documentation, ainsi que
tous les fichiers source) sont tellement courants, le Pascal possède une
multitude de routines intégrées pour lire et écrire des valeurs dans et à
partir de ces fichiers. La plupart des types standard, par exemple, ont une
routine particulière pour convertir ces fichiers en caractères ASCII et pour
écrire ces caractères dans un fichier. Le compilateur fait appel à ces
routines de manière automatique pour transcrire chaque expression dans une
procédure Write vers un fichier Text. Il existe des routines semblables pour
pouvoir lire ces mêmes types. La description des routines Read et Write
ci-dessus a montré exactement comment s'opère cette conversion.

Il existe même une forme particulière de procédures Read et Write qui permet
de travailler exclusivement avec des fichiers Text - il s'agit des commandes
ReadLn et WriteLn. Elles sont expliquées ci-dessous, mais notez que, les
les fichiers typés n'ayant pas de lignes, on n'utilise ces deux routines que
pour les Fichiers Text.


 Ouverture de Fichiers
-----------------------

Il y a plusieurs routines qui sont étroitement liées permettant l'ouverture
des fichiers en Pascal. Pour ouvrir des fichiers en entrée, c'est-à-dire des
fichiers déjà existant -qui seront ouverts en lecture, on peut employer soit
la fonction ReOpen(), soit la procédure Reset(). Elles sont définies de la
manière suivante :

                 Reset(var VarFichier : File ou Text;
                           NomFichier : String;
                         TailleTampon : Integer);

La procédure "Reset" ouvre un fichier en lecture. Le paramètre VarFichier
indique la variable de fichier Pascal qui devra être associée à ce fichier
en AmigaDOS. Comme celui-ci peut être n'importe quel nom de fichier valide
en AmigaDOS, il pourra en fait faire référence à l'imprimante, à la fenêtre
de la console ou à tout autre chose.

Le paramètre Tailletampon indique la taille du tampon voulu en octets. Quand
PCQ essaiera d'ouvrir le fichier, il tentera de réserver toute la mémoire
dont il a besoin pour le tampon. S'il n'y arrive pas, il met à 1 IOResult 
et échoue. En réalité, le PCQ essaie de réserver un tampon qui soit égal à
un multiple pair de la taille des éléments du fichier, qui ne soit pas plus
grand que TailleTampon, mais qu'il ait au moins la taille d'un élément (pour
les fichiers Text, la taille d'un élément est égale à un seul caractère). Le
paramètre Tailletampon est totalement optionnel - si on ne l'indique pas, le
compilateur utilise 128, la valeur par défaut.

Si vous vous servez d'une vérification des E/S automatique, le programme
s'arrêtera avec une erreur de l'exécutable si le fichier ne peut être
ouvert. Si vous faites une vérification manuelle, le programme se limite à
mettre à 1 IOResult.

La variable VarFichier ne devrait pas faire référence à un fichier déjà
ouvert. On devrait d'abord fermer le fichier ou alors employer une variable
de fichier différente.


                ReOpen(NomFich    : String;
                    var VarFich   : file ou text;
                    TailleTampon  : Integer) : Boolean

ReOpen est la forme fonction de Reset. Celle-ci cherche à ouvrir un fichier
de la même façon que Reset et, si tout se passe bien, il retourne True. S'il
y avait un problème, il retournerait False.

ReOpen ne met jamais à 1 IOResult, ainsi si vous employez une vérification
automatique des E/S, un appel à ReOpen ne fera pas échouer le programme.
Comme avec la procédure Reset, le paramètre TailleTampon est optionnel.


Si vous avez besoin d'ouvrir un fichier en écriture (ce qui efface tout
fichier existant de même nom !), vous pouvez employer la procédure Rewrite
ou la fonction Open(). Elles sont définies de la façon suivante :

                Rewrite(var VarFichier : File or Text;
                            NomFichier : String;
                          Tailletampon : Integer);

Rewrite ouvre un fichier AmigaDOS en écriture, en effaçant tout autre
fichier existant avec le même nom. Les paramètres sont semblables à ceux de
la commande Reset et Tailletampon est encore une fois optionnel.

Rewrite met à 1 IOResult, donc si le programme utilise une vérification
automatique des E/S, il échoue s'il ne peut ouvrir le fichier. Les
programmes qui gèrent leurs propres E/S devront s'assurer de regarder la
valeur de IOResult.

Comme avec toutes les routines d'ouverture de fichiers, on ne doit pas
employer une variable de fichier qui fait référence à un fichier déjà
ouvert.


                Open(NomFich      : String;
                    var VarFich   : file ou text;
                    Tailletampon  : Integer) : Boolean

Open est équivalent à Rewrite, mais sous forme de fonction. Elle cherche à
ouvrir un fichier en écriture et, si tout se passe bien, elle retourne True.
Si elle rencontre un problème, elle retourne False. Souvenez-vous que
l'ouverture d'un fichier en sortie a pour conséquence l'effacement de tout
fichier ayant le même nom.

Open ne met pas à 1 IOResult, par conséquent, les programmes utilisant une
vérification automatique des E/S pourront l'utiliser sans échouer. Le
paramètre TailleTampon, comme dans le reste des routines d'ouverture de
fichiers, est optionnel.


 Ecriture de Fichiers
----------------------

En Pascal la sortie est gérée par les procédures Write et Writeln.
Contrairement à plusieurs procédures Pascal, ces routines acceptent un
nombre de paramètres illimité. Si vous écrivez dans un fichier Text, ces
paramètres peuvent prendre une multitude de types différents. La procédure
Write possède la forme élémentaire suivante :

        Write(var VarFichier : Text ou Fichier Typé, Expressions...)

VarFichier est optionnel. Si on n'en indique pas, on utilisera à sa place la
Sortie du fichier Text standard. Si VarFichier est un fichier typé, chaque
expression devra être du type des éléments. Ceux-ci seront écrits dans le
fichier sans espace entre eux, et formatés seulement comme ils le sont en
mémoire.

Si vous écrivez dans un fichier Text, c'est alors toute une autre histoire.
En premier lieu, chaque expression peut prendre la forme "e:m:n", où e est
l'expression elle-même et m et n sont des entiers de constantes. m indique
la largeur minimale du champ - si l'article qu'on doit écrire prend moins de
m caractères, on remplira le champ avec des espaces. n n'est autorisé que
si e est une expression de type réel et il indique combien de chiffres
devra-t-on écrire à droite du point des décimales. Les valeurs par défaut
pour m et n sont, respectivement, 1 et 2. De manière plus spécifique, ce
qu'on y écrira dépendra du type, en conformité avec ce qui suit :

Integer
Short
Byte     Ces trois types s'écrivent tous sous forme de séquences
         de chiffres ASCII, comme on pouvait s'y attendre. Ils ne sont
         précédés d'aucun espace, mais les types Short et Integer
         peuvent, si nécessaire, commencer par le signe moins. Il n'y
         a pas d'espaces au début.

Real     On écrit toute la partie entière (la partie à gauche du point
         des décimales). Si n est différent de zéro, on écrit un point
         pour les décimales suivi des chiffres indiquant la partie
         fractionnaire. Notez que, pour les nombres réels, m indique
         le nombre de chiffres qu'on devra écrire à gauche du point
         des décimales et non toute la largeur du champ (probablement,
         ceci changera dans la prochaine version).

Char     On écrit un caractère sous forme de caractère unique.
         Inchangé.

Array of Char
         On écrit tout le champ, caractère par caractère, sur toute
         la longueur déclarée,

String   On écrit toute la chaîne de caractères jusqu'au caractère
         final nul, celui-ci non compris.

Boolean  On écrit soit le mot TRUE soit le mot FALSE, sans espaces
         ni au début, ni à la fin.


           WriteLn(var FileVar : Text; Expressions...)

Writeln c'est exactement la même chose que Write, mais, après avoir écrit
chaque expression, conformément aux règles ci-dessus, elle ajoute aussi un
caractère de retour à la ligne. WriteLn ne peut être employée qu'avec les
fichiers Text.


 Lecture de Fichiers
---------------------

En Pascal l'entrée est gérée par la procédure Read. Comme la procédure
Write, Read accepte un nombre de paramètres quelconque et plusieurs types de
paramètres, si vous êtes en train de lire d'après un fichier Text. Son
format est le suivant :

     Read(var VarFich : Text ou Fichier Typé ; Références Variables....)

Le paramètre VarFich est optionnel. S'il est omis, on emploie à sa place
l' "Input" du fichier Text standard.

Si VarFich se réfère à un fichier typé, chaque référence variable sera
remplie avec les éléments de fichier ultérieurs, tant qu'on n'atteigne EOF
ou qu'auparavant ne se produise une erreur. La lecture à partir d'un fichier
Text est une affaire un peu plus souple. Comme avec les instructions Write,
ce qui arrivera dépendra du type qui devra être lu, conformément à ce qui
suit :

Integer
Short
Byte     On saute tout espace blanc, qui est défini comme tout caractère
         dont la valeur ASCII est inférieure ou égale à 32 (valeur du
         caractère espace). Si le premier espace non blanc n'est pas un
         chiffre ou si l'on atteint EOF, on tombe sur une erreur (pour
         plus de renseignement, cf. "Procédures de Sortie"). Si tel
         n'est pas le cas, on lit les chiffres jusqu'au premier caractère
         autre qu'un chiffre. On retourne le nombre qui en résulte et le
         pointeur de fichier reste sur la position de ce "non-chiffre".

Real     D'abord, on lit un entier exactement comme ci-dessus. Si le
         caractère suivant est un point, on lit encore les chiffres
         fractionnaires jusqu'au premier "non-chiffre". Une valeur
         réelle ne nécessite pas une partie fractionnaire et n'a pas
         besoin d'un point pour les décimales.

Char     Lit le caractère simple suivant. Le Pascal Standard transforme
         les caractères de fin de ligne en espaces, mais le Pascal PCQ,
         comme Turbo Pascal, leur permet d'en rechapper en tant que
         sauts de lignes ASCII.

Array of Char
         Lit des caractères dans un tableau tant que celui-ci est plein
         ou qu'il ait atteint une fin de ligne. Si celle-ci est atteinte,
         le reste du tableau est rempli avec des espaces et le pointeur
         de fichier reste pointé sur le caractère de fin de ligne - il
         vous faudra faire appel à Readln pour vous en débarasser.

String   Lit les caractères dans le tampon de String jusqu'à atteindre
         une fin de ligne. A ce moment, la chaîne se termine avec un
         octet zéro et le pointeur de fichier reste pointé sur le
         caractère de fin de ligne. Notez que cette routine ne vérifie
         pas la longueur et que, par conséquent, il faut vous assurer
         que la chaîne forunie soit suffisamment grande dans le fichier
         de lecture.

Boolean  Impossible.


Une suite de références variables dans une procédure Read agit exactement
comme chacune des références dans une procédure Read individuelle. Ainsi :

                     Read(Input, Var1, Var2);

est équivalent à

              Read(Input, Var1); Read(Input, Var2);

qui est aussi équivalent à

                     Read(Var1); Read(Var2);


           ReadLn(var VarFich : Text; Références Variables...)

Readln est exactement comme Read. Après avoir lu toutes les variables
indiquées, cette commande avale les caractères jusqu'à ce qu'elle ne trouve
le prochain fin de ligne, pour l'avaler à son tour. On ne peut utiliser
cette commande qu'avec les fichiers Text.


 Tampons de Fichiers
---------------------

Comme le Pascal Standard, mais différemment de Turbo Pascal, PCQ vous permet
d'accéder directement aux tampons des fichiers. La syntaxe de l'appel est la
suivante :

                         <Appel Variable Fichier> ^
                              ex. VarFichier^

Cette expression possède le même type que les éléments du fichier lui-même
(les fichiers Text possèdent des éléments de type Char). Avec des fichiers
d'entrée, cette syntaxe regarde à l'avance le prochain élément introduit par
la procédure Read(). Si EOF(VarFichier) est True, alors VarFichier^ est non
valide.

Avec les fichiers de sortie, l'appel au tampon du fichier affiche le tampon
de sortie. Il ne s'agit pas de la valeur qui sera écrite par la procédure
Write() - pour plus de renseignements, voyez ci-dessous la description de
Put().

Logiquement, la longueur du tampon du fichier auquel on accède par cette
syntaxe est la longueur d'un de ces éléments, mais le tampon réel en mémoire
peut avoir virtuellement une taille quelconque. Pour plus de détails sur la
manière de régler la taille du tampon, voyez les commandes d'ouverture d'un
fichier.

En réalité, dans PCQ, l'emploi de cette syntaxe est considéré comme une
opération d'E/S, étant donné que cette opération peut mettre à 1 IOResult.
Ceci n'arrive que si le fichier est interactif car on garde pas pleins les
tampons d'un fichier interactif.

Si vous faites usage du tampon de fichier, vous vous servirez probablement
de l'une ou des deux routines suivantes :


               Get(var VarFichier : Text ou Fichier Typé)

Get se limite à déplacer le pointeur de fichier de l'élément courant à
l'élément suivant. Cette action peut entraîner un appel au DOS pour remplir
le tampon à nouveau, mais d'ordinaire ce n'est qu'une façon d'ajuster un
champ de la variable fichier elle-même. Faire appel à cette routine dans un
fichier dont EOF(VarFichier) est True est une erreur.

On pourra s'imaginer chaque lecture dans un fichier typé ayant la forme
"Read(VarFich,Elément)" de la manière suivante :

        Elément := VarFich^; { Pour affecter la valeur courante }
        Get(VarFich);        { Pour faire avancer le pointeur de fichier }


               Put(var VarFichier : Text ou Fichier Typé)

Put déplace le pointeur de fichier après l'élément courant dans un fichier
de sortie, en écrivant le tampon sur la disquette, si nécessaire. Chaque
instruction de la forme "Write(VarFich,Expr)", où VarFich est un fichier
typé, pourrait être implémentée en tant que

        VarFich^ := Expr; { Mettre en place la valeur du tampon }
        Put(VarFich);     { L'affecter au tampon }

Notez que tant qu'on n'a pas fait appel à la procédure Put, une affectation
au tampon du fichier surcharge l'affectation précédente.


 Vérification des E/S
----------------------

Virtuellement, l'Entrée et la Sortie peuvent provoquer un nombre d'erreurs
imprévues supérieur à celui d'une zone de programmation quelconque. Le
Pascal PCQ s'empare des erreurs de deux façons différentes. La première est
la vérification automatique des erreurs d'E/S - PCQ vérifie s'il y a eu une
erreur après chaque opération d'E/S. Si tel est le cas, le programme échoue
avec une erreur de l'exécutable. Croyez-le ou non, il s'agit du comportement
par défaut.

Si vous désactivez la vérification automatique en utilisant la directive
{$I-} du compilateur, vous prenez la responsabilité de la vérification des
erreurs. On désactive la vérification en appelant la fonction IOResult qui
retourne 0 si tut se passe bien ou un nombre quelconque s'il y a eu un
problème. Lors d'un appel à IOResult, vous mettez à zéro la valeur retournée
automatiquement, par conséquent si vous devez vous servir du code d'erreur
plus tard, il vous faudra le recupérer dans une variable.

IOResult est mis à 1 par toutes les routines d'E/S. Aucune de celles-ci ne
marchera, si le résultat fourni par IOResult n'est pas égal à zéro, ainsi
vous devrez vérifier les erreurs autant que possible pour éviter de sauter
des opérations de lecture et d'écriture.

Les valeurs retournées par IOResult sont les mêmes que celles retournées par
les erreurs de l'exécutable - des valeurs possibles sont listées dans la
section "Procédures de Sortie".


 E/S Standard
--------------

L'une des parties plus délicates de la programmation sur l'Amiga est qu'un
programme peut être lancé à partir de deux environnements très différents.
Le CLI invoque un programme d'une manière très semblable à l'MS-DOS - le
programme a des canaux d'entrée et de sortie évidents. D'un autre côté, le
Workbench n'offre rien de pareil. Un programme qui a besoin d'une entrèe et
d'une sortie doit fixer celles-ci de manière explicite.

Tous les programmes PCQ fixent une sorte de canal d'entrée et de sortie
standard auxquels on peut avoir accès par l'Entrée et la Sortie des fichiers
Text. Naturellement, ce que représenteront ces canaux dépendra de
l'environnement d'où on aura lancé les programmes.

Prenons d'abord le cas simple. Si vous lancez un programme à partir du CLI,
l'Entrée et la Sortie se référeront à la fenêtre CLI elle-même. A moins que
vous ne fassiez une indirection, c'est-à-dire que L'Entrée et la Sortie se
réfèrent aux canaux qu'on aura indiqués dans la ligne de commande (pour plus
d'informations, voyez le manuel de l'AmigaDOS). Mais, après tout, il se peut
que ce ne soit pas si simple que nous venons de l'affirmer.

Si vous avez lancé le programme à partir du Workbench, le code de démarrage
passe par plusieurs stades pour fixer l'Entrée et la Sortie. Tout d'abord,
le code regarde la valeur de la constante typée String standard StdInName.
Si cette valeur est égale à Nil, il n'y aura pas d'ouverture de fichier et
un appel à l'Entrée pourra provoquer de graves problèmes. Si la valeur n'est
pas égale à zéro, le code de démarrage cherchera à ouvrir le fichier. S'il
n'y arrive pas, il s'arrêtera avec une erreur de l'exécutable qui porte le
numéro 53. Si tout se passe bien, on fixe l'Entrée.

Ensuite le code de démarrage regarde StdOutName. Si celui-ci est égal à Nil,
on ne fixe pas la Sortie, par conséquent toutes les procédures Write auront
intérêt à utiliser un fichier explicite. Si StdOutName fait référence à
la même chaîne de caractères que StdInName (il ne s'agit pas de deux chaînes
de caractères avec le même contenu - celles-ci en réalité pointent sur la
même zone de mémoire) et si le fichier associé à l'Entrée est interactif
(par exemple, s'il est connecté à la fenêtre de la console), alors la Sortie
est associée au même pointeur de fichier que l'Entrée. Les valeurs par
défaut de StdInName et de StdOutName possèdent cette propriété. Si l'un de
ces deux tests échoue, le code de démarrage essaie d'ouvrir un fichier
conformément à StdOutName et, si cela marche, alors la Sortie est installée
en conséquence. Autrement, le programme se termine avec une erreur de
l'exécutable qui porte le numéro 57. 

Les valeurs par défaut des deux canaux sont définies dans PCQ.lib come suit

        CONST
            StdInName  : String = "CON:0/0/640/200/";
            StdOutName : String = StdInName;

Conformément aux règles indiquées ci-dessus, normalement cela devrait donner
comme résultat l'ouverture d'une fenêtre de console plein écran avec une
entrée en provenance de celle-ci et une sortie allant vers celle-ci.

Remarquez que StdInName et StdOutName sont définies en tant que constantes
typées. Il ne peut pas s'agir de variables car elles ont été ouvertes avant
qu'un programme quel qu'il soit n'ait pu s'exécuter. Si cela vous pose un
problème majeur, vous avez la possibilité de les définir toutes les deux en
tant que Nil, ce qui vous donnera la possibilité d'ouvrir les Entrées et les
Sorties qu'il vous plaira en partant de votre programme. Probablement, vous
devrez réemployer l'Entrée et la Sortie seulement quand vous aurez lancé
votre programme à partir du Workbench (vous pourrez vérifier si vous avez
démarré du Workbench en appelant GetStartupMsg dans "Utils/Parameters.i").

Au cas où vous auriez compilé votre programme en vous servant de l'option
d'initialisation "-s" pour avoir un code de taille réduite, vous n'auriez
plus aucune possibilité : l'Entrée et la Sortie ne seront pas fixées et, en
fait, cette option n'initialise aucune routine d'E/S. Pour plus de détails,
voyez la section "Code d'Initialisation Réduit".




============================================================================

                          Chaînes de Caractères

============================================================================

Les chaînes de caractères en Pascal PCQ sont semblables aux chaînes du C et
ne ressemblent aucunement aux chaînes de Turbo Pascal. Ceci n'est pas trop
bien car les chaînes de Turbo Pascal sont bien plus commodes. Eventuellement
un jour, les chaînes de PCQ seront identiques à celle de Turbo Pascal, mais
pour l'instant nous n'en sommes pas là.

On peut s'imaginer le type chaîne tout simplement sous la forme "^Char". Par
conséquent, toutes les variables de chaînes de caractères occuperont quatre
octets et stockeront l'adresse de la chaîne réelle. Le texte pourra être
d'une longueur quelconque et se terminera par le caractère Chr(0). Une
instruction comme

        StringVar := "Une chaîne"

... stocke concrètement l'adresse de la constante chaîne de caractères dans
une variable chaîne plutôt que de copier la chaîne elle-même dans un espace
déjà existant.

En Pascal, les constantes chaînes d'un texte sont délimitées par des
caractères de guillemets en opposition aux caractères d'apostrophes des
constantes d'un tableau de caractères. Ainsi "Une chaîne" est considérée
comme une constante de type String tandis que 'différente de chaîne' est
considérée comme une constante de type "Array [0..11] of Char".

Les chaînes de caractères sont définies en tant que simples pointeurs, ainsi
l'appel "VarChaine^" est valide et est de type Char. En réalité, il pointe
sur le premier octet du tampon de la chaîne. Mais, contrairement à ce qui se
passe avec les pointeurs normaux, on peut aussi accéder aux caractères
individuels d'une chaîne par une notation indicée. Par exemple, pour prendre
le quatrième caractère d'une chaîne, vous pourriez utiliser "VarChaine[3]".
Souvenez-vous que "VarChaine[0]" est le premier élément de la chaîne.


 Allocation d'Espace pour les Chaînes
--------------------------------------

Comme les vraies variables String ne stockent qu'une seule adresse, il vous
faudra réserver de l'espace pour le texte proprement dit. Le C vous permet
de définir cet espace lorsque vous déclarez le type chaîne, tandis que le
PCQ ne vous en offre pas autant. En Pascal PCQ, il vous faudra réserver de
la mémoire de manière explicite à partir du système ou alors affecter
l'adresse à la variable d'un tampon destiné à la chaîne. Pour ce faire,
on dispose de plusieurs fonctions, définies dans le fichier 'include'
StringLib.i, qui réservent de l'espace pour les chaînes de caractères. Voici
ces fonctions :

               AllocString(Taille : Integer) : String

AllocString retourne simplement une zone de mémoire non initialisée d'une
taille minimale de 16 octets. Cette zone mémoire est considérée comme
mémoire appartenant à PCQ; elle par conséquent rendue au système après
utilisation (pour plus de renseignements, voyez la section "Gestion de la
Mémoire").

                strdup(ChaineIn : String) : String

La fonction strdup (duplication de chaîne) est équivalente à ceci

                temp := AllocString(strlen(ChaineIn);
                strcpy(temp,ChaineIn);
                strdup := temp;

Autrement dit, cette fonction réserve juste assez de mémoire pour pouvoir
contenir la chaîne d'entrée, puis en fait une copie dans le nouveau tampon.
On considère aussi que cette mémoire appartient à PCQ, par conséquent elle
sera rendue au sytème lorsque le programme aura pris fin.

Une autre façon d'installer un tampon de chaîne est celle d'assigner à la
variable chaîne l'adresse d'un tableau déclaré ailleurs. Par exemple

        Var
            Chaîne1 : String;
            Tampon1 : Array [0..127] of Char;
        begin
            Chaîne1 := Adr(Tampon1);

... installe un tampon de 128 caractères pour Chaîne1. Si l'on tentait de
stocker une chaîne de 129 caractères dans le tampon, on pourrait avoir toute
sorte de problèmes : faites donc attention.


 Utilisation des Caractères Escape
-----------------------------------

Naturellement, il existe beaucoup de caractères utiles qu'on ne peut écrire
aisément dans le fichier source d'un programme. Le caractère de fin de ligne
par exemple est toujours considéré comme la fin d'une ligne plutôt que comme
une constante. Si vous avez besoin d'introduire ce type de caractère dans
une constante texte (Char, Array of Char ou String), vous devrez employer la
convention d'échappement du C. Voici les séquences d'échappement qu'accepte
PCQ :

           \n   Line Feed [Saut de Ligne], chr(10)
           \t   Tab [Tabulation], chr(9)
           \0   Null [Nul], chr(0)
           \b   Backspace [Espace Arrière], chr(8)
           \e   ESC [Echappement], chr(27)
           \c   CSI (Introducteur de la Séquence de Commande), chr($9B)
           \a   Attention [Sonnette], chr(7)
           \f   Form Feed [Saut de Page], chr(12)
           \r   Carriage Return [Retour Chariot], chr(13)
           \v   Vertical Tab [Tabulation Verticale], chr(11)

[NdT. Pour mémoire, j'ai laissé aussi la dénomination anglaise].

Tout autre caractère passera inchangé; c'est pour cela que les définitions
suivantes contiennent aussi

           \\   Juste une seule barre oblique inverse
           \'   Une seule marque d'apostrophe, même dans une constante
                délimitée par des apostrophes
           \"   Un guillemet, même dans une constante String

Ainsi une chaîne comme "A\tboy\nand\\his \"dog." deviendra :

        |A      boy
        |and\his "dog

... où la barre verticale | représente la marge gauche.


 StringLib
-----------

StringLib.i est un fichier 'include', présent dans le répertoire Utils, qui
définit un ensemble  de fonctions -dans le style du C-  à utiliser avec les
chaînes de caractères. On donne des explications  sur ces fonctions dans le
fichier  'include'  lui-même.   Les sources  de ces routines  sont dans les
sources  de  la  bibliothèque  d'exécution,   qui sont  disponibles dans la
version enregistrée.





============================================================================

                          Gestion de la Mémoire

============================================================================

Un des problèmes de programmation sur l'Amiga est constitué par le fait que
celui-ci n'offre pas de dépistage des ressources. Dans un programme MS-DOS,
vous avez la possibilité d'ouvrir des fichiers et de réserver de la mémoire
comme un fou. Sur l'Amiga, tous ces fichiers resteront ouverts et la mémoire
restera réservée. Ensuite, on vous attend pour le nettoyage.

Pour vous aider dans cette tâche, le Pascal PCQ utilise un schéma de
réservation de mémoire particulier qui fait appel à la routine AllocRemember
d'Intuition pour garder la trace de toutes vos réservations de mémoire.
Lorsque votre programme prend fin, toute partie de mémoire que vous n'auriez
pas désaffectée sera libérée automatiquement par une procédure de Sortie.

Cette procédure ne marche que pour la mémoire réservée par l'intermédiaire
des routines spéciales de PCQ, soit New, AllocString (Utils/StringLib.i) ou
GetMem (dans Utils/PCQMemory.i). La mémoire réservée à l'aide d'une de ces
routines s'appelle mémoire PCQ, mais, naturellement, celle-ci n'est pas
différente de la mémoire ordinaire du système, si l'on excepte qu'elle lui
sera rendue.

Même si la mémoire est libérée automatiquement, il faudra la désaffecter dès
que vous n'en aurez plus besoin. Il pourrait y avoir d'autres programmes en
train de tourner qui pourraient s'en servir. Si vous décidez de libérér la
mémoire PCQ, pour le faire, il vous faudra faire appel à Dispose, FreeString
ou FreePCQMem. Si vous ne le faisiez pas, la mémoire serait retournée au
système et les routines mémoire de PCQ n'en sauraient rien. Par conséquent,
elles pourraient tenter de la libérer à nouveau à la fin du programme.
Gourou assuré.

On alloue toujours la mémoire PCQ en mettant les drapeaux MEMF_PUBLIC et
MEMF_CLEAR. Ainsi donc, s'il vous faut de la mémoire 'chip', il vous faudra
faire appel à la fonction normale AllocMem d'Exec (dans Exec/Memory.i).


 HeapError [Erreur dans le Tas]
--------------------------------

Ainsi donc, qu'est-ce qu'il arrive lorsque les routines de gestion mémoire
de PCQ n'arrivent pas à désaffecter ces parties de mémoire appelées par un
utilisateur ?  Cela dépendra de la valeur de HeapError, une variable Address
standard. HeapError contient l'adresse d'une fonction dont l'en-tête a la
forme suivante :

           Function HeapFunc(Taille : Integer) : Integer;

Le paramètre Taille est la quantité de mémoire que le distributeur est en
train d'essayer de s'attribuer, tandis que l'entier retourné détermine de
quelle façon le distributeur répondra au problème posé. Si la fonction
retourne 0, le distributeur stoppera le programme avec une erreur de
l'exécutable qui portera le numéro 54. Si la fonction retourne 1, le
distributeur retournera la valeur Nil, par conséquent vous aurez à faire une
vérification de valeur Nil après chaque appel à New, AllocString ou GetMem.
Si la fonction HeapError retourne 2, le distributeur tente une nouvelle
affectation. Ceci vous donne une chance de libérer un peu de mémoire, si
cela est possible. Si l'affectation échoue, la fonction HeapError sera
appelée à nouveau.

Pour installer une fonction comme la fonction HeapError, vous devriez
employer quelque chose qui se présente comme ceci :

                     HeapError := @HeapFunc;

... où HeapFunc est telle qu'elle a été définie ci-dessus.




============================================================================

                          Procédures de Sortie

============================================================================

Les procédures de sortie sont des routines que l'on met en place pour
qu'elles puissent démarrer quand la routine principale a pris fin ou qu'il
se produit une erreur de l'exécutable. On les emploie pour rendre les
ressources au système ou pour sortir avec élégance ou même pour récupérer le
système suite à des erreurs de l'exécutable.

Voici comment elles fonctionnent : quand un programme prend fin, pour une
raison quelle qu'elle soit, PCQ regarde la valeur de ExitProc, une variable
Address standard. Si celle-ci est différente de Nil, PCQ met ExitProc sur
Nil et appelle la procédure qui pointe sur ce dernier. Quand la procédure
retourne, PCQ teste encore une fois ExitProc et continue à appeler les
procédure de sortie tant qu'ExitProc n'est pas égal à Nil. Le code normal
d'initialisation de PCQ installe une procédure de sortie qui libère toute la
mémoire réservée par l'intermédiaire de New ou d'AllocString et qui ferme
tous les fichiers Pascal encore ouverts. Par conséquent, tout programme
normal a au moins une procédure de sortie.

Pour changer une procédure en procédure de sortie, définissez d'abord une
routine sans aucun paramètre. Mettez ensuite la variable ExitProc standard
sur l'adresse de votre routine. Dans la majorité des cas, vous souhaiterez
sauvegarder la valeur précédente de ExitProc pour que, malgré tout, toutes
les autres procédures de sortie fonctionnent. De l'intérieur de la procédure
de sortie elle-même, il vous faudra réinitialiser ExitProc pour que celle-ci
pointe sur la routine précédemment définie.

Il y a deux autres variables supplémentaires associées aux procédures de
sortie qui ne sont valides que lorsque la procédure s'exécute réellement en
tant que procédure de sortie. Elles existent toujours, mais leurs valeurs ne
sont mises en place que lorsque le programme prend fin. Les voici :

ExitCode     ExitCode contient la valeur de toutes les erreurs de
             l'exécutable qui auraient provoqué la fin du programme.
             Il s'agira soit d'une valeur que vous aurez fournie par
             l'intermédiaire de la routine Exit(), soit d'un code 
             d'erreur de l'exécutable.

ExitAddr     ExitAddr est l'adresse où s'est produite l'erreur de
             l'exécutable. Elle n'est valide que si ExitCode n'est
             pas égal à zéro. Elle peut (en théorie) être utilisée
             pour récupérer le système après une erreur de l'exécutable,
             mais il vous faudra être rudement familier avec le vrai
             programme de l'exécutable pour pouvoir vous en servir.
             Le code source d'exécution est fourni avec la version 
             enregistrée de PCQ Pascal.

 Erreurs de l'Exécutable
-------------------------

Il y a plusieurs erreurs qui peuvent être à l'origine de l'arrêt immédiat
d'un programme PCQ. Quand cela se produit, ExitCode est mis à une valeur
spécifique qui sera éventuellement retournée par l'AmigaDOS. A son tour,
l'AmigaDOS devrait normalement l'ignorer, ainsi donc vous ne verrez jamais
l'erreur. Les deux façons que je connaîs pour voir la valeur en retour (si
elle n'est pas égale à 0) sont de lancer le programme dans un 'script' ou de
le lancer en employant la commande Run de l'AmigaDOS. Dans les deux cas, si
le programme a un code de retour qui n'est pas égal à zéro, l'AmigaDOS
affichera "NomDuProgramme failed returncode #".

Voici les erreurs de l'exécutable générées par des programmes PCQ :

            Code       Description
          ----------------------------------------------
             50    No memory for IO buffer (1)
                   Pas assez de mémoire pour le tampon d'E/S
             51    Read past EOF (1)
                   Tentative de lecture après EOF
             52    Input file not open (2)
                   Fichier en entrée n'est pas ouvert
             53    Could not open StdInName (3)
                   Impossible ouvrir StdInName
             54    New() failed (4)
                   New() a échoué
             55    Integer divide by zero
                   Division d'un entier par zéro
             56    Output file not open (2)
                   Fichier en sortie n'est pas ouvert
             57    Could not open StdOutName (3)
                   Impossible ouvrir StdOutName
             58    Found EOF before first digit while
                   reading an integer (1)
                   Trouvé EOF avant le premier chiffre
                   lors de la lecture d'un entier
             59    No digits found in reading an integer (1)
                   Trouvé aucun chiffre lors de la lecture d'un entier
             60    Range error (5)
                   Erreur d'intervalle

Les codes d'erreur AmigaDOS suivants peuvent intervenir après un appel à
Open, ReOpen, Write, Read, etc. :  (1)

            103    Insufficient free store
                   Mémoire libre insuffisante
            202    Object in use
                   Objet en service
            203    Object already exists
                   L'objet existe déjà
            204    Directory not found
                   Répertoire non trouvé
            205    Object not found
                   Objet non trouvé 
            206    Invalid window specification
                   Spécification de fenêtre non valide
            210    Invalid component name
                   Nom du composant non valide
            212    Object wrong type
                   Objet de type erroné
            213    Disk not validated
                   Disquette non validée
            214    Disk write protected
                   Disquette protégée en écriture
            218    Device not mounted
                   Périphérique non installé
            221    Disk full
                   Disquette pleine
            223    File is write protected
                   Fichier protégé en écriture
            224    File is read protected
                   Fichier protégé en lecture
            225    Not a DOS disk
                   Disquette avec un format non DOS
            226    No disk in drive
                   Aucune disquette dans le lecteur

[NdT. Pour mémoire, j'ai laissé aussi la dénomination anglaise].

        (1)  Ces erreurs ne provoquent des erreurs de l'exécutable
             que si l'on a activé la vérification automatique des
             erreurs en E/S (elle l'est par défaut). Si vous avez
             employé la directive {$I-} du compilateur pour indiquer
             que vous allez faire un test explicite de IOResult, le
             programme ne s'arrêtera pas de manière automatique.
        (2)  PCQ n'a pas toujours la possibilité de déterminer si le
             fichier n'est pas ouvert. S'il le peut, il édite cette
             erreur. S'il ne le peut pas, la machine se bloque.
        (3)  Ces erreurs interviennent dans le code d'initialisation
             avant que soient mises en place les procédures de sortie.
        (4)  Cf. section "Gestion de la Mémoire" pour voir comment
             empêcher l'édition d'une erreur de l'exécutable.
        (5)  Cette erreur ne se produit que si vous avez activé le
             contrôle par intervalle avec la directive {$R+} du
             compilateur.




============================================================================

                         Directives de Compilation

============================================================================

Le Pascal PCQ fournit plusieurs options qui ne sont pas utiles dans tous les
programmes. Par exemple, une application importante ne devrait pas prendre
fin avec une erreur de l'exécutable, si elle n'arrive pas à ouvrir un
fichier. Par conséquent, le Pascal PCQ vous permet de déterminer plusieurs
aspects du programme généré à partir d'un code donné.

Vous pourrez commander ces options en faisant paraître les directives du
compilateur. Ces directives sont contenues dans des commentaires et doivent
commencer avec le signe dollar comme premier caractère du commentaire. Suit,
juste après le signe dollar, une lettre qui indique la directive et qui est
suivie à son tour d'un zéro ou de différents caractères donnant plusieurs
autres informations supplémentaires.

Vous pouvez inclure plusieurs directives dans un seul commentaire, en les
séparant avec des virgules. Ainsi, les directives suivantes invalideront la
vérification des E/S, mais valideront la vérification d'intervalle :

                             {$I-,R+}

Voici les directives qui sont acceptées :


             {$A Tout nombre d'une instruction assembleur}

La directive $A vous permet d'insérer des instructions en langage assembleur
à un point donné du code source. Le texte des instructions est transmis
inchangé à l'assembleur, vous devrez donc inclure les commentaires et mettre
des références variables conformément aux règles de l'assembleur.

Comme on peut mettre des commentaires partout où il y a un espace blanc,
d'un point de vue technique, vous avez la possibilité d'insérer des
instructions en assembleur au milieu d'une expression. Toutefois, ceci
pourrait produire des résultats imprévisibles, par conséquent il vaudra
mieux employer le langage assembleur seulement entre les instructions.


                            {$B+} ou {$B-}

La directive $B active et désactive les évaluations court-circuit. Si vous
employez la directive $B+ pour activer les évaluations court-circuit, qui
est celle qui existe actuellement par défaut, PCQ évaluera les expressions
booléennes normalement, mais dès qu'il connaîtra la valeur finale de
l'expression, il en sautera les parties restantes. Ainsi, dans une suite de
clauses "or", dès que l'une de celles-ci donne une évaluation True, le reste
est sauté. Si vous vous servez des évaluations court-circuit, une expression
sera toujours évaluée de gauche à droite. Les court-circuits rendent une
évaluation booléenne un peu plus rapide, tout particulièrement dans les
équations un peu longues.

Si vous désactivez les évaluations court-circuit en employant la directive
$B-, toutes les parties d'une expression booléenne seront évaluées même si
le résultat ne fait pas de doute et l'expression ne sera pas obligatoirement
évaluée de gauche à droite.


                           {$I "nomfich"}

Cette directive insère le fichier "nomfich" dans le flux d'entrée dans la
position courante du fichier. Quand le fichier inséré aura été entièrement
lu, on prendra à nouveau son entrée à partir du fichier original. Après
cette directive, il est interdit d'en employer une autre, mais vous avez la
possibilité d'insérer les commentaires de votre choix après le nom du
fichier.

Pour éviter d'inclure un fichier plus d'une fois, le compilateur garde la
liste de tous les fichiers qui ont été déjà inclus. Si le nom d'un fichier
s'accorde avec le nom d'un fichier qui est déjà sur la liste, il ne sera pas
inclus. Notez qu'on ne compare que le nom du fichier et non celui de tout le
chemin de recherche. Par conséquent, il vous faudra vérifier que tous vos
fichiers 'include' ont des noms uniques.

Presque tous les programmes d'exemple montrent de quelle façon on doit
employer les fichiers 'include'.


                          {$I+} ou {$I-}

Une deuxième forme de la directive $I détermine la réaction des programmes
devant les erreurs d'Entrée/Sortie. Le comportement par défaut, qui
correspond à la directive {$I+}, est d'afficher une erreur de l'exécutable
au cas où l'on détecterait une erreur dans une routine d'E/S. La deuxième
option, qu'on spécifie par la directive {$I-}, indique que le programme
lui-même vérifiera la fonction IOResult après des opérations d'E/S et qu'il
en gérèra les erreurs en conséquence. Pour plus de renseignements, voyez la
section "Entrées/Sorties".


                 {$SN} ou {$SX} ou {$SP} ou {$SD}

L'option $S contrôle le stockage des variables globales, ainsi que celui des
constantes typées. L'option N (qui signifie 'Normal storage' [Stockage
normal]) dit au compilateur qu'il doit -pour toutes les variables globales
ultérieures- réserver de la mémoire dans le segment de données et afficher
aussi une définition externe (XDEF en assembleur) pour l'identificateur afin
que ce dernier puisse être utilisé par les routines externes. Il s'agit d'un
schéma normal de stockage des programmes PCQ.

L'option X (qui signifie 'eXternal storage' [stockage eXterne]) informe le
compilateur que toutes les variables globales ultérieures seront définies à
l'extérieur du programme. Par conséquent, le compilateur ne devra pas
réserver de l'espace pour ces variables, mais tout simplement générer une
référence externe (XREF en assembleur). Il s'agit d'un schéma normal de
stockage des fichiers externes.

L'option P (qui signifie 'Private storage' [Stockage Privé]) informe le
compilateur qu'il doit allouer de l'espace pour les variables globales, mais
qu'il ne doit pas exporter l'identificateur lui-même. Ceci permet que les
fichiers externes aient des variables globales qui n'affectent pas le
programme principal.

L'option D (qui signifie 'Default storage' [Stockage par Défaut)])
réinitialise le stockage à sa valeur initiale. Dans un programme externe,
elle agit comme {$SX} et, dans un programme normal, elle agit comme {$SN}.


                          {$O+} or {$O-}

Ces options sont identiques aux options {$I+} et {$I-}.


                          {$R+} or {$R-}

La directive $R détermine si le compilateur doit vérifier que les valeurs
d'indice se trouvent à l'intérieur de la fourchette indiquée du tableau. Le
comportement par défaut est {$R-}, ce qui veut dire que le compilateur ne
générera pas de code supplémentaire. En indiquant {$R+}, on oblige le
compilateur à éditer une erreur de l'exécutable avec le code d'erreur 60. En
activant cette option, on obtient des programmes d'une taille plus grande et
plus lents, je recommande donc de ne l'utiliser que pendant des essais.




============================================================================

                            Conversion de Types

============================================================================

Si vous employez un langage fortement typé comme le Pascal, il vous faut une
méthode pour vous déplacer dans les règles des types. Le Pascal PCQ emploie
la même méthode que le Turbo Pascal et le Modula-2 pour se déplacer dans les
vérifications de type. Voici le format d'une conversion de type :

          <Type ID> ( <Expression ou Appel de Variable> )

Ceci ressemble à une fonction, mais, en définitive, cela n'en est pas une.
Une conversion de type ne génère jamais aucun code - elle se limite à faire
comprendre le code au compilateur. Naturellement, ceci peut entraîner des
problèmes sérieux. A titre d'exemple, une conversion de type telle que
"Short(VarEnumérée)" causera des problèmes car normalement la taille des
types énumérés est d'un octet. Vous avez informé le compilateur pour qu'il
la considère comme une valeur de deux octets, mais le deuxième octet est
indéfini. A la place, une méthode correcte pour gérer cet appel serait
l'emploi de la fonction Ord() ou tout au moins la conversion de la valeur
en type Byte.

Dans cet exemple, la différence entre Short() et Ord() est que Ord() est une
fonction de transfert de types, tandis que Short() n'est vraiment pas une
fonction. Comme autre exemple, analysez le fragment ci-dessous :

                         Writeln(Integer(2.0));
                         Writeln(Trunc(2.0));

Ces deuux lignes n'écriront pas la même valeur. Trunc(), une autre fonction
de transfert, convertit la valeur réelle 2.0 en la valeur entière 2, avant
de l'écrire. La "fonction" Integer ne fait rien du tout : le programme se
borne à écrire la valeur réelle comme si celle-ci était entière, ce qui est
une façon sûre pour engendrer un nombre grotesque.

En général, la conversion d'une expression en une autre d'une taille
supérieure est une mauvaise idée et la conversion d'une expression simple
(une valeur ordinale, réelle ou pointeur) en une autre de type complexe (un
renvoi à un tableau ou à un enregistrement), ou l'inverse, produit presque
toujours des résultats absurdes.




============================================================================

                       Code d'Initialisation Réduit

============================================================================

Parfois, vous pourriez vouloir créer un programme qui ne soit pas surchargé
comme un programme Pascal ordinaire. Par exemple, si vous n'employez jamais
les fichiers Pascal, il n'y a aucune raison pour conserver tout le code de
Writeln() dans votre programme. Si vous souhaitez réduire le code de
démarrage et réduire au minimum le code que PCQ ajoute à votre programme,
vous avez la possibilité de vous servir de l'option ".s" (Small [Réduit])
dans la ligne de commande. Par exemple, pour compiler Tiny.p avec un code
de démarrage réduit, il vous faudra employer la ligne suivante :

                   Pascal Tiny.p Tiny.asm -s

Cependant, la surcharge dont vous vous débarassez n'est pas énormement
inutile et l'un des problèmes de ne pas l'avoir est que vous n'aurez pas la
possibilité de vous en servir. Autrement dit, si vous vous servez de
l'option "-s", dans la ligne de commande, vous ne pourrez pas utiliser les
routines Pascal d'E/S. D'une manière plus spécifique, voici les procédures
et les fonctions qui seront hors de portée :

                Write, WriteLn, Read, ReadLn, Get,
                Put, Open, ReOpen, Close, IOResult

Le compilateur signalera les appels à tous ces identificateurs à l'exception
de IOResult, mais gardez à l'esprit que le compilateur ne verra jamais ces
appels dans des fichiers compilés séparément (fichiers externes) ou dans des
bibliothèques contenant du code objet. La morale de cette histoire est qu'il
faudra faire très attention lors de l'emploi de cette option, autrement il
vous arrivera de lier ensemble les deux routines de démarrage et, de toute
façon, de bloquer la machine.

Ainsi donc qu'est-ce qu'on omet exactement avec cette option ?  Le code de
démarrage normal fait les choses suivantes :

   1. Gère le message de la LigneDeCommande ou celui du Workbench.
   2. Ouvre Intuition, le DOS et la bibliothèque mathématique en
      virgule flottante [MathFFP].
   3. Prépare l'Entrée et la Sortie en ouvrant une fenêtre, si
      nécessaire.
   4. Initialise la liste de réservation de mémoire, ainsi que
      celle des fichiers ouverts, pour pouvoir les libérer lors de
      la procédure de sortie.
   5. Installe la procédure de sortie qui libérera la mémoire
      et fermera les fichiers.

Comme vous pouvez le voir, il y a plusieurs routines assez importantes :
Open(), Close(), la préparation de l'Entrée et de la Sortie, selon la façon
dont on aura prévu le lancement du programme et le contenu de StdInName et
de StdOutName, la procédure de sortie qui libère tout, etc.. De son côté, le
code d'initialisation réduit fait les choses suivantes :

   1. Gère le message de la LigneDeCommande ou celui du Workbench.
   2. Ouvre Intuition, le DOS et la bibliothèque arithmétique en
      virgule flottante [MathFFP].
   3. Initialise la liste de réservation de mémoire et installe
      une routine simple pour libérer toute la mémoire obtenue par
      New().

Et c'est tout. Conformément à mes résultats préliminaires, le programme
suivant "Program Test; begin end.", après compilation, a normalement une
taille de 2.5 Ko et une taille inférieure à 700 octets, si l'on emploie le
code d'initialisation réduit.




============================================================================

                           Fichiers Externes

============================================================================

En développant le compilateur, je me suis aperçu que tout ce machin dans un
seul fichier source était vraiment trop grand - les fichiers assembleur
intermédiares étaient sans fin et le temps de compilation était ridiculement
excessif. Pour fractionner un peu tout cela, j'ai ajouté une méthode qui
permette de faire une compilation séparée, similaire dans l'esprit aux
unités du Turbo Pascal, mais moins puissante.

Les fichiers externes ont le format suivant :

           <Fichier Externe> ::= External; <Définitions>

En d'autres termes, un fichier externe commence par le mot réservé External,
un point-virgule, puis un nombre quelconque de blocs de définition. Ces
blocs, tels qu'ils ont été définis auparavant, peuvent être des fonctions,
des procédures, des variables, etc..

A chaque fois que vous définissez une procédure ou fonction, le Pascal PCQ
"exporte" l'identificateur pour que d'autres fichiers puissent ensuite s'en
servir. Ces autres fichiers se réfèrent à la routine en incluant dans leur
code une référence externe (cf. "Références Externes", dans la section
"Procédures et Fonctions"). Ainsi, si vous définissez la procédure DoIt dans
votre fichier externe, vous devrez inclure la declaration suivante dans tout
autre fichier où vous emploierez la routine :

                        Procedure DoIt;
                            External;

Cette déclaration dit au compilateur qu'il devra "importer" l'identificateur
d'un autre fichier.

La définiton des variables et des constantes typées à niveau global dans un
fichier externe est un peu plus compliquée. Supposons, par exemple, d'avoir
une variable globale dans le programme principal, mais de vouloir aussi
faire référence à celle-ci dans le fichier externe. Si on la déclare
normalement dans le fichier externe, on peut s'attendre à ce que le Pascal
PCQ réserve deux zones de mémoire pour une seule variable, l'une dans le
programme principal et l'autre dans le fichier externe.

A cause de ce problème, on suppose, par défaut, que les variables et les
constantes typées à niveau global (seulement à ce niveau) n'ont été définies
que dans les fichiers programme normaux. Ainsi, si on définit une variable
globale dans un fichier externe, PCQ supposera que cette variable devra être
importée à partir d'un autre fichier et ne réservera pas d'espace mémoire.
Toutefois, on peut passer outre cette hypothèse en employant la directive
$S du compilateur.

Si vous vous êtes servi de fichiers externes, vous devez vous assurer que
leurs routines sont présentes dans le programme exécutable final. Pour ce
faire, il vous faut inclure le nom du fichier dans la commande de l'éditeur
de liens de la manière suivante :

    Blink Principal.o Externe1.o ... to ProgrammePrinc Library PCQ.lib

En d'autres termes, vous inclurez les fichiers objet externes (la sortie de
l'assembleur) dans la commande de l'éditeur de liens juste après le fichier
principal, mais avant le mot réservé "to". On peut mettre les fichiers objet
dans un ordre quelconque.

Bien que Pascal soit un langage insensible aux majuscules et aux minuscules,
l'assembleur ne l'est pas. Ainsi, quand vous faites des références externes,
vous devez vous assurer que la toute première référence à votre code - une
déclaration de variable ou bien l'en-tête véritable d'une procédure ou d'une
fonction - soit écrite avec le même caractère que celui de la définition
dans le fichier externe. Des utilisations ultérieures peuvent être écrites
en majuscule ou en minuscule - on n'emploie que la première définition.




============================================================================

               Notes Destinées aux Programmeurs en Assembleur

============================================================================

Dans les précédentes versions du copmpilateur, les registres de d2 à d7, a2
et a3 étaient tous disponibles à n'importe quel moment et les registres de
brouillon ['scratch'] étaient disponibles entre les instructions. Ceci n'est
plus vrai : certaines routines devront donc être réécrites.

Maintenat, la version 1.2 de PCQ utilise les registres d'une manière bien
plus efficace, c'est-à-dire qu'on peut mettre en service tous les registres
de données. PCQ alloue les registres à partir de d7 pour conserver les
résultats des sous-expressions, donc la disponibilité des registres dans les
expressions dépendra du code Pascal. Entre les instructions, tous les
registres de données sont encore une fois disponibles.

Les registres d'adresse sont utilisés comme auparavant : a7 est le pointeur
de la pile, a6 est utilisé pour pointer sur la bibliothèque de base et a4
est utilisé pour pointer sur les anciennes structures. Le compilateur peut
se servir de a3 et d'a2 pendant les expressions pour conserver la valeur
d'une adresse intermédiaire.

Les routines système considèrent d0, d1, a0 et a1 comme des registres de
brouillon, mais préservent tous les autres registres.




============================================================================

                                Erreurs

============================================================================

Lorsque le compilateur tombe sur n'importe quelle erreur dans le programme,
il affiche la ligne courante et la précédente en mettant en surbrillance la
zone générale de l'erreur. Sur la ligne suivante, il vous donne le numéro de
la ligne et la procédure ou la fonction courantes qua vous avez définies,
plus un texte de description (optimiste).

Normalement, la première erreur est assez précise. Après celle-ci,
cependant,  le compilateur pourra commencer à vous envoyer toute sorte de
signalations fallacieuses qu'il vaut mieux ignorer. Pour cette raison, le
Pascal PCQ s'arrête automatiquement après quatre erreurs (j'avais l'habitude
d'en afficher cinq, mais, apparemment, la première erreur sortait du cadre
lors du défilement d'un écran normal).

Si on indique l'option "-q" Quiet dans la ligne de commande, le rapport des
erreurs aura un aspect plus normal, c'est-à-dire la forme suivante :

"nom du fichier source" At ##,## : Error Text

Les deux-points, la virgule et le mot "At" sont tous au pied de la lettre.
Le premier ## indique la ligne et le deuxième la colonne. J'ai conçu ce
format pour pouvoir rendre plus facile le développement de routines de
compilation automatisées.




============================================================================

                                Sources

============================================================================

J'ai écrit ce programme comme une expérience d'apprentissage et, au cas où
vous le demanderiez, je suis sûr d'avoir appris beaucoup.   D'où j'ai tiré 
mon  information ?  Regardons d'abord l'information concernant de manière
plus spécifique l'Amiga.

Amiga 1.3 Native Developer's Update. C'est un ensemble de quatre disquettes
distribuées par Commodore (précisément par CATS). Dans ces disquettes, on
trouve les bibliothèques 'include' en assembleur et en C, l'Amiga.lib, ALink
et tout plein d'autres choses. Peut-être encore plus important, on y trouve
les 'Amiga Autodocs', un ensemble de fichiers de documentation expliquant
une par une toutes les fonctions disponibles dans les bibliothèques et dans
les périphériques logiques de l'Amiga. Toutefois, chaque fonction étant
expliquée individuellement, il vous faudra une source de type plus général.
Cependant, ces disquettes sont une affaire. La mise à jour 2.0 devrait enfin
sortir, mais, au moment où j'écris, elle n'est pas encore disponible, par
conséquent envoyez 20 dollars et demandez la version 1.3 à

                     C.A.T.S.
                     1200 Wilson Drive
                     West Chester, PA 19380

Les manuels Kernel Amiga ROM. C'est l'ensemble officiel des livres destinés
à la programmation sur Amiga et, si vous ne les possédez pas, vous avez un
handicap. La dernière édition en ma possession est la version du système
d'exploitation de l'Amiga 1.1 et, par conséquent, je ne sais pas de quelle
manière sont actuellement oraganisés les manuels. Cependant, vous devriez
prendre sans aucun doute celui qui traite d'Intuition et, si vous avez les
moyens, celui qui traite des 'Libraries and Devices'. Ils sont épais et très
chers, mais il est difficile de faire des progrès sans les avoir. Certaines
personnes, naturellement, vous diront qu'ils sont pleins de fautes et
difficiles à lire; personnellement, je les ai trouvés très soignés et très
clairs. Je pense que certains programmeurs se plaisent à rejeter la
responsabilité de leur incapacité à comprendre sur les autres...

Le manuel C d'Anders Bjerin. Je ne l'ai jamais consulté, ainsi je n'ai pas
la moindre idée de ce qu'il contient. Il couvre beaucoup de sujets sur les
bibliothèques Intuition et Graphics et, dans la perspective du C, il ne
devrait pas présenter beaucoup de problèmes de compréhension. Il est présent
sur les disquettes Fish 456 et 457 et, une fois décompacté, il occupe quatre
disquettes pleines. 

Plus en particulier, pour l'information sur les compilateurs, je me suis
référé aux sources suivantes :

PDC, un compilateur C, librement distribuable, supporté par Jeff Lydiatt.
C'est un excellent programme, bien qu'il ait été eclipsé récemment par DICE,
GCC et d'autres compilateurs C vraiment excellents. J'ai appris (et utilisé)
beaucoup sur les structures d'activation, en partant des 'listings' produits
par ce compilateur bien que le code source de PDC reste un mystère.

Le code source de Pascal-S. C'est une petite démonstration d'un compilateur
Pascal p-code produit il y a quelques années dans l'ETH de Zurich, là où
enseigne Wirth. Il peut répondre à beaucoup de questions, mais n'est pas
vraiment un bon exemple de style de programmation.

Le code source de Small-C. Il s'agit d'un autre compilateur C, librement
distribuable, décrit, il y quelques années, dans le "Dr. Dobb's Journal". Il
n'est pas vraiment puissant, mais la simplicité du code source en fait une
référence très pratique. C'est l'un des compilateurs employés pour amorcer
PCQ.

Brinch Hansen sur les Compilateurs Pascal, de Per Brinch Hansen. Ce livre
est l'un de ceux que j'ai utilisés et dont je peux dire le plus de bien dans
la demi-douzaine d'ouvrages que j'ai lus, lorsque j'étais en train d'écrire
ce programme. Principalement, grâce à ce livre, j'ai compris tout ce que
je faisais de travers. Excellent !

Les séries 'Toy Compiler' dans 'Amiga Transactor', tenues par Chris Gray.
Ces séries sont vraiment pleines d'informations et sont tenues par l'auteur
de Draco. Pour vivre, Gray écrit aussi des compilateurs, ainsi il sait
maintenant de quoi il parle. Malheuresement, ces séries sont difficiles à
trouver, car 'Transactor' a cessé de paraître. Toutefois, demandez autour de
vous - cela en vaut la peine.

Compilers : Principles, Techniques and Tools de Aho, Sehti et Ullman. C'est
le gros bouquin, le livre surnommé le bouquin du Dragon, dernier cri sur la
manière d'écrire un compilateur. Si vous souhaitez le consulter, il est
disponible, mais il vaudra mieux que vous possédiez un assez bon bagage
mathématique. Bien que j'ai eu ce livre comme livre de texte lors d'un cours
que je suivais, je n'en ai jamais lu plus de quelques pages.




============================================================================

                      Améliorations Urgentes à Venir

============================================================================

J'ai utilisé la version 1.2 pendant plusieurs mois, avant de la mettre en
circulation, ce qui fait que je suis relativement confiant pour ce qui est
de sa qualité. Malgré tout, il y a eu tellement de changements importants
que je m'attends à avoir des problèmes. Par conséquent, ma priorité, comme
toujours, sera la correction des erreurs.

Suivront les conventions optionnelles des appels en C, l'optimisation du
'peephole' intégré et probablement les réels IEEE en simple précision. Tout
cela est assez facile à faire.

La version 1.3 sera une version axée sur la compatibilité. Elle comprendra
les chaînes de caractères dans le style de Turbo Pascal, les valeurs de
retour des fonctions, les réels en double précision et les types de Turbo
Pascal : Word, LongInt, ShortInt, etc.. Address deviendra Pointer, Integer
deviendra LongInt, Short deviendra Integer, Exit deviendra Halt, etc.. Je
pourrai même implémenter la syntaxe d'Unix.

L'autre partie que je voudrais explorer est celle concernant les débogueurs,
de préférence au niveau des programmes sources. J'ai cherché le code source
d'un programme moniteur, mais je n'en ai pas encore trouvé.




============================================================================

                       Historique des Mises à Jour

============================================================================

Version 1.2b (7 Février 1993)

  o   Correction de la fonction sqr() pour les valeurs autres  que  virgule
      flottante.

Version 1.2b (15 Mars 1992)

  o   Correction de Write() et Read() de valeurs Real, qui, d'une façon  ou
      d'une autre, était une fois de plus en défaut.

Version 1.2b (15 Février 1992)

  o   Correction des routines de DateTools.i.
  o   Correction d'un problème avec les types étendue dont la limite  basse
      est comprise entre 1 et 255.
  o   Les comparaisons de types structurés  ne  marchaient  pas.  Désormais
      elles marchent.
  o   Correction d'un problème avec le code glue  de  GetColorTable  de  la
      iff.library.

Version 1.2b (8 Septembre 1991)

  o   Correction d'un autre problème dans l'indexage de tableau, cette fois
      avec les tableaux multi-dimensionnels.
  o   Correction d'une erreur dans le fichier Exec/ExecBase.i.

Version 1.2b (13 Août 1991)

  o   Correction d'un problème d'indexage de tableau.
  o   Le compilateur accepte désormais à nouveau des  boucles  REPEAT/UNTIL
      vides.
  o   J'ai enlevé une { sans correspondance dans Intuition/IntuitionBase.i.
  o   J'ai modifié Ord() pour promouvoir automatiquement les  valeurs  d'un
      seul octet en type Short.

Version 1.2b (22 juin 1991)

  o   Le compilateur ignorerait les paramètres de fonctions ou de procédures
      qui suivraient les constantes négatives.
  o   Maintenant le compilateur s'assure que chaque élément d'un tableau se
      trouve à une adresse paire, à condition que la taille de cet élément
      soit supérieure à un octet.
  o   Corrigé les problèmes de bouclage avec REPEAT/UNTIL.
  o   La directive $A ne fonctionne pas entre l'en-tête de la routine et la
      zone où se trouve le code.

Version 1.2a (8 juin 1991)

Corrigé plusieurs bogues :
  o   L'opérateur XOR produirait des commandes assembleur non autorisées.
  o   Certaines comparaisons en virgule flottante donneraient des résultats
      faux.
  o   Maintenant, la directive assembleur $A marche dans tout le code, ne
      fonctionne pas dans les procédures et les fonctions.
  o   Le compilateur avait l'habitude d'accepter des références inconnues
      avec les constantes typées (comme opérandes de l'opérateur @).
  o   Les instructions INC et DEC ne gèrent pas correctement les formes
      Inc(var1,var2).

Version 1.2 (18 avril 1991)

    Corrigé strlen et CreateTask() pour qu'elles fonctionnent avec une
mémoire 32 bits.
    Réécrit entièrement la routine d'analyse syntaxique d'une expression et
celle de génération du code. Maintenant, les routines emploient les
registres de manière plus efficace et fournissent une bonne base à
l'optimiseur 'peephole' intégré.
    Ajouté quelques caractéristiques de Turbo Pascal : maintenant, on peut
employer partout les conversions de types, même dans le calcul des adresses.
Ainsi, maintenant, vous avez la possibilité d'écrire quelque chose comme
TypeEnreg(Pointeur^).Champ, ce qui était interdit dans la version 1.1.
    Modifié de manière importante l'instruction FOR pour la rendre plus
efficace et plus proche de Turbo Pascal. Cela tient à deux différences : les
boucles FOR ne s'exécutent plus au minimum une fois (c'est-à-dire que
for i := 1 to 0 do ...  s'exécutera zéro fois) et la clause BY n'existe
plus.
    Ajouté des évaluations court-circuit pour les 'short', des conversions
en virgule flottante automatiques, des fonctions 'Heap', Reset et Rewrite.
    Maintenant, on peut employer des fonctions standard ou des opérateurs
dans les expressions de constantes.
    Modifié les routines Read pour qu'elles soient conformes au Pascal
standard et au Turbo Pascal pour ce qui concerne l'espace blanc qu'on saute
avant de lire des entiers et des réels. On avait l'habitude de s'arrêter aux
EOLN.

Version 1.1d du 6 mai 1990 :

    J'ai commencé à accumuler des petits changements sous le numéro d'une
nouvelle version purement pour des raisons d'esthétique. La première
différence est que, maintenant, le compilateur ne crée qu'une SECTION pour
les données, s'il doit bien sûr en créer une. Cela ressemble à une édition
ilustrant le bon fonctionnement, même si, en réalité, le compilateur ne crée
aucune SECTION, s'il est en train de compiler une unité Externe.
    Lorsque StdOut est un fichier, le compilateur n'écrit plus le numéro des
lignes, ainsi que tout le reste. J'ai fait aussi ce que j'espérais dans la
dernière erreur des routines de lecture des nombres réels.
    Les routines qui comparent le nom des fichiers 'include' à la liste des
fichiers qui ont été déjà inclus accepte les majuscules et les minuscules.
Je n'arrive pas à comprendre pourquoi je ne l'ai pas fait avant.

Version 1.1c du 6 avril 1990 :

    J'aurais dû deviner que le problème de reconnaissance de signe de petits
nombres réels en sortie serait un problème symétrique en entrée. Cela était
un problème et maintenant ça n'en est plus un. J'ai aussi corrigé le
problème qu'on avait avec les constantes réelles. J'ai ajouté aussi les
fonctions exp() et ln() que Martin Combs m'a envoyé récemment. Pour éviter
l'inflation dans le numéro des versions, j'ai changé la date, mais j'ai
gardé la même version.
    Je pensais ajouter l'optimisation du 'peephole'au processus, mais au
lieu de cela d'une manière normale, j'ai joué avec un programme séparé. Pour
simplifier tout cela, j'ai supprimé les branches courtes du code généré.
Quoiqu'il en soit quand cela est nécessaire, l'A68k les rajoute.

Version 1.1c du 3 mars 1990 :

  Les seuls changements apportés au compilateur sont les nouvelles fonctions
standard. Les changements plus significatifs ont  été  opérés  dans la
bibliothèque de l'exécutable.  D'abord, j'ai remplacé les fonctions sin() et
cos(),  en  m'appuyant sur des suggestions de Martin Combs - maintenant, les
résultats  sont  d'une précision d'environ 3 chiffres, et les fonctions sont
légèrement  plus lentes.  Martin a été assez gentil de m'envoyer un ensemble
de  routines  bien  utiles,  qui  comprennent  aussi  les fonctions tan() et
arctan().  J'ai également corrigé la routine qui écrit les nombres réels, de
sorte  que maintenant les valeurs comprises entre -1.0 et 0.0 comprennent le
signe moins.

Version 1.1b du 6 février 1990 :

  Ce programme a plus d'un an.
  J'ai  ajouté  la  fonction  Sqr().  Sqr(n) est la même fonction que n * n,
mais  elle  est  partiellement  plus  rapide et plus compacte.  En outre, le
compilateur  avait  l'habitude  de  générer  beaucoup  d'erreurs  lorsqu'on
oubliait   un   fichier   'include'.   Maintenant,  il  saute  le  reste  du
commentaire, comme il aurait dû le faire auparavant.
  Apparemment, les constantes en virgule flottante n'avaient pas l'habitude
de marcher.   Pourquoi suis-je toujours le dernier à l'apprendre ?  J'ai
ajouté également  les fonctions Sin() et Cos(), qui s'appuient sur un aparté
que j'ai eu lors d'une lecture sur un sujet entièrement différent.
  Plus  tard,  j'ai  ajouté  la  fonction sqrt(), en employant la méthode de
Newton.

Version 1.1a du 20 janvier 1990 :

  J'ai  corrigé une bogue dans la routine WriteArb, bogue qui se manifestait
chaque fois qu'on écrivait dans un 'Fichier QuelqueChose'.
  J'ai  fixé une bogue que j'avais laissée dans la bibliothèque arithmétique
en  virgule  flottante.   Il paraît qu'elle n'a pas été mise à jour lors des
changements  effectués  dans la version 1.1, en sorte que -lors de l'édition
de  liens-  elle  réclamait des objets qui n'étaient plus nulle part.  Etant
donné  que  l'arithmétique  en virgule flottante est maintenant gérée par le
compilateur, je ne m'en étais pas aperçu avant.

Version 1.1 du 1er décembre 1989 :

  Cette  version  a été complètement réécrite et elle présente tellement de
changements pour que je puisse en donner la liste détaillée. Les principaux
changements concernent les instructions with, le nouveau système d'entrées/
sorties, la table des symboles -qui a été entièrement redessinée-, les
procédures emboîtées et plusieurs opérateurs arithmétiques nouveaux. Pour
faciliter la portabilité des programmes -écrits en C et en Turbo Pascal- sur
l'Amiga, j'ai ajouté les constantes typées, l'instruction Goto ainsi qu'une
syntaxe normale pour les tableaux à plusieurs dimensions.

Version 1.0c du 21 mai 1989 :

  J'ai  modifié  un  peu les routines d'entrée, en employant les fichiers du
DOS  plutôt  que  ceux du PCQ.  J'ai tamponné l'entrée et rendu la structure
plus  flexible  pour  pouvoir  imbriquer  les  'include'.   Plutôt  que  de
raccomoder  certaines directives IfNDef, j'ai décidé de sauvegarder la trace
des  noms  des  fichiers  inclus  et  de sauter ceux déjà faits.  Le fait de
tamponner  l'entrée  réduit  le temps de compilation de moitié.  Je n'aurais
jamais  cru  que le fait de mettre des tampons aurait une telle portée et je
suppose que je devrais repenser l'entrée/sortie de PCQ à la lumière de cette
découverte.
  J'ai  ajouté  du code pour tester CTRL-C, par conséquent vous pourrez vous
échapper plus tôt du programme et le faire proprement. Le fichier 'include'
Ports.i présentait quelques erreurs, que j'ai corrigées; j'ai aussi
corrigé  la  routine  qui  ouvre  une console pour les programmes qui en ont
besoin. Elle avait l'habitude de créer des problèmes quand il y avait
plusieurs arguments dans le premier write().
  J'ai  ajouté  la fonction SizeOf(), l'arithmétique en virgule flottante et
les fonctions standard associées à l'arithmétique en virgule flottante.
  Il  y avait aussi plusieurs problèmes mineurs dans les fichiers 'include',
problèmes  que  j'ai découvert lorsque j'ai eu les 'include' 1.3, le premier
ensemble officiel depuis que j'ai eu les 1.0.
  J'ai  desserré la syntaxe de AND, OR ET NOT pour qu'elle accepte n'importe
quel  type  ordinal.  Ceci vous permettra d'utiliser les opérateurs logiques
sur  les  entiers  ou  sur  autre  chose.  J'ai également ajouté la fonction
Bit(),  décrite  ci-dessus.   Tout  ceci  est  provisoire, jusqu'à ce que je
puisse incorporer ces ensembles dans le langage.
  Pour  terminer,  j'ai  ajouté  l'indexage  des  chaînes.  Ce faisant, j'ai
trouvé  une  bogue  dans  la  routine  d'adressage  selector(), je l'ai donc
réécrite  pour  qu'elle  soit  plus  raisonnable.   Je  pense aussi qu'elle
produit  un  code  plus  important, mais je ne me suis pas trop fatigué car,
quoiqu'il en soit, je vais bientôt ajouter les arbres d'expression.

Version 1.0b du 17 avril 1989 :

  J'ai  corrigé  une  bogue  là  où  se  font les comparaisons de structures
complexes.   Il paraît que, à un endroit, on prenait en compte trop d'octets
et que, par conséquent, la comparaison échouait.

Version 1.0a du 8 avril 1989:

  Dans  cette  version, j'ai ajouté les opérations arithmétiques sur 32 bits
et   corrigé  l'instruction  case.   Je  me  suis  occupé  de  cette  partie
arithmétique  seulement  pour  que le source en assembleur soit plus propre,
par  contre,  j'ai entièrement changé l'instruction case.  La version 1.0 du
compilateur   produisait   une  table  où  le  compilateur  allait  chercher
séquentiellement  les  valeurs apropriées et -s'il les trouvait- les mettait
en  parallèle  avec  une  adresse.   Je  croyais  que  tous les compilateurs
fonctionnaient ainsi, mais, lors du débogage d'un programme en Turbo Pascal,
en  travaillant,  je  me  suis  aperçu  que  celui-ci  faisait  un  tas  de
comparaisons,  avant  chaque  instruction case, comme s'il était en train de
faire  une  série d'instructions case optimisées. J'y ai réfléchi et rejeté
cette  idée  comme  étant  trop  simpliste,  mais si ceci est assez bon pour
Turbo, c'est suffisamment bon pour moi.
  La  deuxième chose que j'ai changée -dans cette version-, c'est le code de
démarrage.   Maintenant,  vous  pouvez  lancer  les programmes en Pascal PCQ
à partir  du   Workbench.    C'était   seulement  l'affaire  de  prendre  en
considération  le  message  du  Workbench,  mais  j'en ai profité aussi pour
perdre  mon  temps  avec l'entrée et la sortie standard.  Si vous essayez de
lire ou d'écrire sur l'entrée ou la sortie standard -dans un programme lancé
à partir  du  Workbench-,  le  code  d'exécution ouvrira une fenêtre à votre
place.
  J'ai  aussi  corrigé  une bogue que j'ai découverte : un indice de tableau
qui n'était pas de type numérique voyait son type confondu.  Rien de plus.

Version 1.0 du 1er février 1989.

    Première version.




============================================================================

                Notes Supplémentaires, Copyright et Adresse

============================================================================

Cette documentation, le code source du compilateur, le compilateur lui-même,
le code source de la bibliothèque de l'exécutable et la bibliothèque de
l'exécutable elle-même sont tous (hmmm)

                    Copyright (c) 1989 Patrick Quaid.

J'autorise  la libre distribution  de cette version du package,  du  moment
que  tous les fichiers de l'archive, à l'exception possible de l'assembleur
et du relieur (s'il vous plait, incluez  les  autant  que  possible),  sont
inclus et inchangés. Bien sûr, personne ne peut gagner vraiment de l'argent
en  distribuant  ce  programme.  Il  peut seulement être distribué dans des
collections de disquettes où une somme raisonnable  est  facturée  pour  la
disquette elle-même. La somme raisonnable est ici définie au maximum à  10$
par  disquette,  ou  ce  que  Fred  Fish  facture actuellement (environ six
dollars au moment où j'écris ceci).

  La version 1.2b de PCQ Pascal est "freeware",  ce  qui  signifie  qu'elle
peut  être  librement  distribuée,  et  qu'aucun  droit  n'est  requis. Les
versions futures, y  compris  l'actuelle  1.2d,  sont  maintenant  envoyées
seulement aux utilisateurs enregistrés, et ne peuvent pas être distribuées.
Les  frais  d'inscription  pour  PCQ  Pascal sont de 25$, ce pour quoi vous
obtiendrez ce qui suit:

   o  La dernière  version  du  compilateur,  qui  supporte  désormais  les
      enregistrements  avec  variante, les commentaires délimités par (* et
      *), les mots-clé CHIP et FAST pour  les  variables  globales  et  les
      constantes  typées,  les déclarations de pointeur du Pascal standard,
      un profileur d'exécution, un  support  de  la  mathtrans.library,  et
      beaucoup plus.
   o  PCQ,  un  utilitaire make extrêmement flexible et personnalisable qui
      vous permet de compiler, d'assembler  et  de  relier  des  programmes
      simples et des projets complexes avec une seule commande.
   o  PCQ.lib.DOC,  qui  décrit  chaque  routine  interne  à  PCQ Pascal ou
      définie dans Include:Utils. Bien plus de 100 routines sont  couvertes
      dans  un format similaire à celui des AutoDocs, et compatible avec la
      fonction de référence REF de DME.
   o  Les fichiers include et une bibliothèque d'exécution compatible  avec
      l'AmigaDOS 2.0, dès qu'ils seront disponibles.

  Pour 15$  supplémentaires  (qui,  à  propos,  couvrent  juste  les  frais
d'impression),  je  vous  enverrais  un  manuel de l'utilisateur imprimé et
relié, basé sur Pascal.DOC et un manuel de référence, basé sur PCQ.lib.DOC.
Ils sont complètement reformatés, et ont même des index complets.

  Vous pouvez toujours obtenir la dernière version du compilateur  freeware
auprès  de  moi  en  envoyant  une disquette, une enveloppe et les frais de
port. Cependant il sera seulement mis à jour pour corriger les bogues, donc
de nouvelles versions ne verront pas le jour très fréquemment.

  Toutes questions, commentaires, ou quoi que ce soit peuvent être adressés
à:

      Pat Quaid
      2250 Clarendon Blvd, Apt #1209
      Arlington, VA 22201
      USA

      Téléphone: (703) 524-8945

  Vous avez bien plus de chances de pouvoir me contacter  par  courrier que
par  téléphone, mais cela ne me dérange pas que vous essayiez. Appréciez le
compilateur.

