Introduction
En langage de programmation Pascal, un fichier n'est, en théorie, qu'un autre type de données abstrait. Bien sûr, la plupart des mises en oeuvre Pascal connectent des variables de ce type à des fichiers de données de système d'exploitation réels. Les fichiers du IBM Personal Computer Pascal se connectent aux types de fichiers normaux disponibles dans le système d'exploitation PC DOS (IBM Personal Computer Disk Operating System).
Il s'agit notamment des affichages vidéo, des imprimantes, des périphériques de flux génériques (comme un port RS232) et des fichiers sur disque avec des données au format textuel ou interne accessibles avec plusieurs méthodes différentes. Le IBM Personal Computer Pascal utilise toujours le DOS pour accéder aux fichiers et n'impose pas de mise en forme ou de structure supplémentaire. Les fichiers sont disponibles en deux structures de base et trois modes.
Structures de fichiers
Les structures de fichiers sont BINARY et ASCII. Les fichiers de structure BINARY dans le IBM Personal Computer Pascal (similaires au FILE du Pascal standard d'un certain type), correspondent aux fichiers du système d'exploitation non formatés. Les primitives GET et PUT transfèrent un nombre fixe d'octets par appel égal à la longueur d'un composant du fichier BINARY. Les fichiers de structure ASCII (comme le type de données Pascal standard TEXT) correspondent aux fichiers textuels du système d'exploitation. Le type Pascal TEXT est comme un FILE OF CHAR, mais les groupes de caractères sont organisés en lignes de texte. Les primitives comme GET et PUT fonctionnent toujours sur la base de caractères sur ces fichiers. En Pascal, les fichiers texte sont divisés en lignes avec un marqueur de ligne, conceptuellement un caractère n'étant pas du type CHAR. Bien qu'un fichier texte puisse en théorie contenir n'importe quelle valeur de type CHAR, dans le système d'exploitation PC DOS, l'écriture d'un CHAR(13), soit le caractère de retour chariot, termine la ligne actuelle (l'enregistrement). Cette valeur de caractère est utilisée comme marqueur de ligne dans ce cas, et lorsqu'elle est lue, elle ressemble toujours à un blanc. Pour l'utilisateur, chaque ligne est suivie d'un marqueur de ligne se lisant comme un blanc. De manière similaire, le caractère CHR(26) indique la fin d'un fichier texte. Cette situation signifie que l'écriture de CHR(26) met fin au fichier et qu'une tentative de lecture de CHR(26) est une erreur (lecture après la fin du fichier).
Modes de fichier
Les modes de fichier standard sont TERMINAL (Terminal), SEQUENTIAL (Séquentiel) et DIRECT (Direct) :
- Les fichiers en mode TERMINAL correspondent toujours à un écran et clavier interactif ou à une imprimante.
- Les fichiers en mode SEQUENTIAL correspondent à un fichier de disquette ou à un autre périphérique d'accès séquentiel.
- Le mode DIRECT correspond au fichier de disquette ou à un autre périphérique à accès aléatoire.
Les fichiers Pascal standard peuvent avoir le mode SEQUENTIAL, TERMINAL ou DIRECT. La fonction d'entrée/sortie étendue inclut la possibilité d'accéder au mode d'un fichier. Les fichiers en mode SEQUENTIAL et TERMINAL sont ouverts pour lecture ou écriture au début du fichier, et les enregistrements sont accessibles dans l'ordre jusqu'à la fin du fichier. Les fichiers de structure ASCII en mode SEQUENTIAL et TERMINAL ont des enregistrements de longueur variable (lignes). Tous les fichiers de structure BINARY ont des enregistrements de longueur fixe (lignes ou composantes). La déclaration d'un fichier en Pascal indique la structure mais pas le mode; par exemple, FILE OF STRING(80) indique la structure BINARY et TEXT indique la structure ASCII. L'affectation F.MODE:=SEQUENTIAL définit le mode des fichiers SEQUENTIAL. Le langage de programmation Pascal a deux fichiers prédéclarés, INPUT et OUTPUT. Dans IBM Personal Computer Disk Operating System, ils commencent par être connectés au clavier et à l'affichage de l'utilisateur et ont une structure ASCII et un mode TERMINAL, mais peuvent être réaffectés et/ou recevoir un autre mode. L'entrée en mode TERMINAL fonctionne de différentes manières selon que le fichier a une structure ASCII ou BINARY. Pour la structure ASCII (type TEXT), des lignes entières sont lues en même temps, ce qui permet l'édition habituelle entre les lignes DOS (retour en arrière, curseur avancé, annuler,...) pendant la saisie de la ligne et l'écho des caractères tels qu'ils sont saisis de la manière habituelle. Puisqu'une ligne entière est lue à la fois, le programmeur ne peut pas lire les caractères tels qu'ils sont saisis. Cependant, pour le mode TERMINAL de structure BINARY (généralement de type FILE OF CHAR), le programmeur peut utiliser la procédure GET pour lire des caractères au fur et à mesure de leur saisie; aucune modification ni aucun écho d'interligne n'est effectué. Cette méthode permet d'effectuer l'édition d'écran, la sélection de menu et d'autres programmes interactifs sur une touche plutôt que sur une ligne. La procédure READ ne peut pas être utilisée pour accéder à cette fonction. Dans ce mode TERMINAL ou BINARY, deux caractères spéciaux existent pour faciliter cette opération. La valeur de CHR(0) comme premier octet signifie qu'aucune donnée n'est présente. Cette valeur ne peut pas être lue. La valeur CHR(255) ne peut pas être écrite dans un fichier TERMINAL BINARY car elle signifie «lecture un caractère» dans DOS. Par exemple :
- Program FileSamples(INPUT,OUTPUT);
-
- Var
- F,G:File of CHAR;
-
- Function INKEY:CHAR;Begin
- Repeat GET(F) Until F^<>CHR(0);
- INKEY:=F^;
- End;
-
- Var
- C:CHAR;
-
- BEGIN
- WRITELN('Terminal binaire(echo)');
- ASSIGN(F,'USER');
- RESET(F);
- ASSIGN(G,'USER');
- REWRITE(G);
- Repeat
- C:=INKEY;
- WRITE(G,C);
- Until C='.';
- END.
Ce programme d'exemple lit et fait écho des caractères jusqu'à un caractère «.» soit rencontré. La fonction INKEY attend en boucle jusqu'à ce qu'un caractère soit disponible. Des caractères spéciaux sont également lus, comme Ctrl+C, Esc, BackSpace,...
Primitives de système de fichiers
Les descriptions des procédures READ et WRITE sont définies en termes d'accès primitif aux variables GET, PUT et du tampon. Par convention, dans toutes les descriptions, F est un paramètre de fichier (les fichiers sont toujours des paramètres de référence) et F^ est la variable tampon.
Accès à la variable tampon
Un mécanisme interne (généralement transparent pour le programmeur) est utilisé pour gérer de manière naturelle l'entrée de terminal interactive. Le «Lazy Evaluation» s'applique à tous les fichiers de structure ASCII et est nécessaire pour l'entrée de terminal naturel. Dans ce cas, le compilateur génère un appel d'exécution exécuté avant toute utilisation de la variable tampon (affectation à celui-ci, une utilisation dans une expression, une vérification de EOF ou EOLN,...).
Lazy Evaluation
L'évaluation Lazy Evaluation se produit uniquement lors de la lecture à partir d'un fichier texte. La variable tampon du fichier a une valeur d'état spéciale pouvant être pleine ou vide. Deux règles s'appliquent à tout fichier texte F :
- Lorsque la variable tampon de F est accessible, si son état est vide, la composante de fichier suivant est physiquement entré; après un accès, l'état est toujours complet.
- Lorsque la procédure GET(F) est appelée, si son état est vide, la composante de fichier suivant est physiquement entré; après un appel à GET, l'état est toujours vide.
Cette situation reporte efficacement l'entrée physique jusqu'à ce qu'elle soit réellement nécessaire à un accès à une variable tampon (y compris les fonctions EOLN et EOF). La procédure RESET définit d'abord l'état complet et appelle GET le définissant simplement vide sans faire une entrée physique. L'évaluation Lazy Evaluation est autorisée dans la norme ISO.
{RESET(INPUT); Fait automatiquement}
WRITE(OUTPUT, "Entrer le nombre :");
READLN(INPUT,FOO);
La procédure RESET effectue un GET, définissant simplement l'état de la variable de tampon sur vide. La première action physique à l'écran/au clavier est la sortie rapide du WRITE. La procédure READLN effectue une série d'opérations «temp:= INPUT ^;GET(INPUT);» dans chacune de ces entrées physiques se produit lorsque INPUT^ est récupéré, et le GET redéfinit simplement l'état sur vide. La procédure READLN se termine par la séquence :
WHILE NOT EOLN DO GET; GET;
Cette situation a pour effet de sauter les caractères de fin et le marqueur de ligne (c'est-à-dire le retour chariot). La fonction EOLN appelle l'entrée physique; lorsque le retour chariot est entré, l'état EOLN est défini. À la fois la procédure GET dans la boucle WHILE et le GET de fin vient de remettre l'état à vide. La dernière entrée physique dans la séquence ci-dessus est la lecture du retour chariot. La procédure READ du Standard Pascal est toujours une composante mettant de l'avant; il appelle GET après avoir défini la variable cible à la valeur de la variable tampon. La motivation pour cela est de définir la valeur EOF avant la lecture pour éviter de lire la fin du fichier. Dans l'environnement de fichiers séquentiels de traitement par lots d'origine de Pascal, cette méthode est acceptable. Si RESET et READ étaient utilisés sans évaluation Lazy Evaluation, l'utilisateur devrait taper le premier caractère de FOO pour satisfaire le GET dans RESET, puis voir l'invite et taper le reste de FOO, avec un retour de chariot et le premier caractère de la réponse suivante. Le IBM Personal Computer Pascal génère un appel système d'entrée/sortie lors de l'accès à la variable tampon. Toutefois, si la variable tampon est un paramètre de référence réel, la procédure ou la fonction utilisant ce paramètre peut effectuer des entrées/sortie dans le même fichier et ces appels spéciaux ne peuvent pas être exécutés. Passer une variable tampon en tant que paramètre de référence est une erreur (bien que seul un avertissement soit donné), et l'effet de faire GET ou PUT sur un fichier dans une procédure ou une fonction accédant indirectement à la variable tampon via un paramètre de référence n'est pas défini. L'attribution de l'adresse d'une variable tampon à une variable de type d'adresse présente à peu près la même insécurité.