ENTREES-SORTIES
ET ENVIRONNEMENT MSDOS

A. INTRODUCTION

Turbo-Forth pour IBM PC et compatibles a besoin pour communiquer avec les organes physiques de cet ordinateur de faire très souvent appel aux fonctions de son système d'exploitation MS-DOS. Cette partie du langage, bien évidemment très dépendante du système, utilise largement un grand nombre d'opérations élémentaires spécifiques à la machine.

Toutes ces opérations élémentaires sont accessibles au moyen d'interruptions logicielles, sortes de routines en code exécutables depuis n'importe quel programme en mémoire. On distingue classiquement:

les fonctions primitives du BIOS (Basic Input Output System) résident en mémoire morte, placées par le constructeur en fonction de la configuration matérielle, des fonctions MS-DOS formant une couche supérieure plus générale et standardisée mais nécessitant au préalable le chargement en mémoire vive du système d'exploitation.

Schématiquement, Turbo-Forth fait appel au système d'exploitation MS-DOS pour cinq grandes classes d'actions.


1. La gestion des périphériques.

Elle s'effectue préférentiellement par le biais du gestionnaire MS-DOS dans un souci de compatibilité. Le BIOS n'est qu'exceptionnellement utilisé.

Cette partie du Forth se charge notamment des entrées au clavier, des sorties vers l'écran, et de toutes les entrées-sorties vers les périphériques (imprimante, sortie auxiliaire etc...).

Pour gérer ses périphériques, MS-DOS suppose l'installation au démarrage d'un certains nombre de "drivers" qui pilotent les opérations d'entrées-sorties pour chacun d'entre eux. Outre les drivers standards toujours installés, Turbo-Forth suppose que soit installé le driver ANSI ce qui lui permet notamment de modifier les attributs d'affichage à l'écran. Votre fichier CONFIG.SYS lu à l'allumage du système doit donc comporter la ligne DEVICE = ANSI.SYS pour exploiter ces possibilités.


2. La gestion de la mémoire de masse.

La mémoire externe de l'ordinateur ou mémoire de masse est un ensemble complexe possédant une double organisation: une organisation physique sous forme d'un support -le disque- divisé en pistes, secteurs et groupes de secteurs (clusters) et une organisation logique en fichiers regroupés dans des répertoires et des sous-répertoires. L'accès aux fichiers depuis Forth passe par un jeu complet de primitives d'exploitation du MS-DOS.

Sous le seul angle de vue Disk Operating System, MS-DOS possède une gestion hybride. Une première architecture, directement héritière du système CP/M 80, exploite les fichiers au travers de zones tampons de contrôle (FCB ou File Control Buffer) maintenues en mémoire. Les entrées-sorties n'y sont pas communes avec celles des périphériques et ne peuvent être redirigées. Ce type de gestion des fichiers persiste dans les versions ultérieures à la V1.0 de MS-DOS mais à partir de la V2.0 est apparue une deuxième architecture, de type UNIX, pour laquelle périphériques et fichiers ont les mêmes opérations d'entrées-sorties. Chaque destinataire de ces opérations est défini par un numéro propre, que l'on appelle généralement ticket en français ou handle en anglais. Turbo-Forth utilise la gestion par tickets et la notion de HANDLE prend ainsi une grande importance en Forth.


3. La mémoire virtuelle Forth.

La première utilisation de la mémoire de masse par Forth consiste à gérer sa mémoire virtuelle c'est-à-dire cet espace mémoire où sont stockés les programmes que compile le langage. Virtuelle car cet espace très vaste, apparemment totalement accessible au programme, n'occupe en fait qu'une petite partie de la mémoire centrale: les tampons. Par l'intermédiaire de ceux-ci, les échanges avec la mémoire de masse s'opèrent de façon transparente.

Turbo-Forth a choisi de gérer des fichiers textes séquentiels au format standard ASCII plutôt que des fichiers blocs en accès direct comme ses prédécesseurs Forth. Ce choix s'imposait dans une politique générale d'ouverture sur l'environnement MS-DOS usuel. Les tampons Forth sont alors limités à des tampons de lignes.


4. L'allocation mémoire.

Avec l'apparition des microprocesseurs 16 bits permettant l'adressage d'une vaste mémoire centrale, les nouveaux systèmes d'exploitation permettent la cohabitation de plusieurs programmes, certains d'entre eux pouvant rester résidents. MS-DOS dispose dans ce but d'un système d'allocation de la mémoire centrale auquel Forth accède lui-même. Cette mémoire centrale est organisée par le microprocesseur 8086 en segments de 64 kilo-octets disposés en paragraphes de 16 octets. Turbo-Forth peut être confiné dans un seul segment. Ses opérateurs extra-segment lui donnent par ailleurs accès à toute la mémoire adressable.


5. L'intégration

Turbo-Forth introduit le concept fondamental d'intégration. On entend par là la possibilité pour un logiciel de lancer l'exécution d'un programme ou d'une commande externe sans quitter ce logiciel qui reste présent en mémoire centrale et auquel le système retourne dès la fin de la procédure externe qu'il a lui-même lancée. La première application de l'intégrateur Turbo-Forth est l'utilisation d'un éditeur de texte quelconque laissé au libre choix de l'utilisateur.


B. GESTION DES PÉRIPHÉRIQUES.

1. Primitives d'entrées-sorties de périphériques.

(IN) fun --- c  

Lecture d'un caractère depuis un périphérique d'entrée MS-DOS. Le code de fonction en appel se réfère aux interruptions MS-DOS et peut prendre en pratique les valeurs suivantes:

fun: caractère lu:
1 STDIN (le clavier) avec écho sur STDOUT (l'écran), test d'un Break et traduction éventuelle des codes étendus (Ctrl,Alt,Esc etc.)
3 AUX (interface série) avec écho sur STDOUT
7 Comme la fonction 1 sans écho ni test Break ni traduction
8 Comme la fonction 1 sans écho
11 Test tampon STDIN c = 0 si le tampon est vide

STDIN, STDOUT, AUX sont des dénominations MS-DOS de tickets de périphériques qui peuvent faire l'objet de redirections: il ne faut pas y voir des entités FORTH.


(OUT) c fun ---  

Écriture d'un caractère sur un périphérique de sortie MS-DOS. Le code de fonction en appel se réfère aux interruptions MS-DOS et peut prendre en pratique les valeurs suivantes:

fun: caractère écrit:
2 STDOUT c'est-à-dire le plus souvent l'écran
4 AUX, la sortie série active
5 STDPRN, l'imprimante
6 l'écran si c <> 255
9 STDOUT mais c doit être l'adresse d'une chaîne terminée par le caractère $ (le Forth n'utilise pas ce type de chaînes)

STDOUT, AUX, STDPRN sont des dénominations MS-DOS de tickets de périphériques qui peuvent faire l'objet de redirections: il ne faut pas y voir des entités FORTH.


(CONS) c ---  

Primitive d'écriture d'un caractère sur l'écran. Équivaut à 6 (OUT)


(CONSOLE) c ---  

Affiche le caractère c sur le terminal. Le mot autorise la gestion multitâche et compte le nombre de caractères émis dans la variable #OUT . Il peut donc servir de vecteur pour EMIT si on renonce à utiliser une sortie imprimante:

' (CONSOLE) IS EMIT  

(PRINT) c ---  

Affiche un caractère c sur l'imprimante seulement. Ce mot peut être utilisé par le mot d'exécution vectorisée EMIT.

ASCII A (PRINT)

(EMIT) c ---  

Affiche le caractère c sur le terminal avec éventuel écho sur l'imprimante. Ce mot est le vecteur par défaut du mot d'exécution vectorisée EMIT. Si la variable booléenne PRINTING contient une valeur non nulle le caractère c est envoyé sur le terminal et sur l'imprimante, sinon il n'est affiché qu'à l'écran. Le contenu de la variable #OUT est incrémenté de une unité dans les deux cas.

PRINTING ON ASCII A (EMIT)
PRINTING OFF ASCII B (EMIT) 

(KEY) --- c  

Attend qu'une touche du clavier soit activée et dépose le code ASCII de celle-ci sur la pile de données. A l'initialisation, ce mot est utilisé par le mot d'exécution vectorisée KEY.

(KEY) .     et appui sur la touche 'A' affiche 65
(KEY) (KEY) . . et appui sur la touche 'F1' affiche 59 0

(KEY?) --- f  

Renvoie un flag booléen vrai si l'utilisateur active une touche du clavier, sinon renvoie un flag booléen faux. Ce mot est utilisé par le mot d'exécution vectorisée KEY?.


PRINTING --- adr  

Variable booléenne dont le contenu est vrai si (EMIT)[par conséquent en général EMIT] doit envoyer un caractère en écho sur l'imprimante.

PRINTING ON   active l'imprimante
PRINTING OFF   désactive l'imprimante

PR-STAT --- f  

Mot de contrôle de l'imprimante que Turbo-Forth n'utilise pas en temps ordinaire. Délivre un flag booléen toujours 'vrai' à l'initialisation. Sans être un mot vectorisé, peut être facilement redéfini par l'usager selon l'équipement particulièrement dans un environnement multitâche:

: PRET? CR ." L'imprimante est-elle connectée et allumée ?"
 KEY UPC ASCII O = ;
' PRET? IS PR-STAT

Avec un BIOS compatible IBM et une imprimante parallèle, on peut tester l'état de l'imprimante n°0 avec le mot suivant:

DECIMAL CODE (PR-STAT)
2 # AH MOV 0 # DX MOV
23 INT 144 # AH XOR 0=
IF -1 # AX MOV ELSE 0 # AX MOV
THEN 1PUSH END-CODE '
(PR-STAT) IS PR-STAT

Dans ce cas PR-STAT ne délivre un flag vrai que si l'imprimante est connectée et prête à imprimer.


2. Lecture du clavier.

KEY --- c F83

Mot d'exécution vectorisée. Attend qu'une touche du clavier soit activée, puis délivre le code ASCII de cette touche. Ce mot exécute par défaut (KEY) . La revectorisation de cette fonction permet de modifier profondément l'accès au système, voire de le commander depuis un périphérique différent du clavier (modem ou RS232 pour exemple). Exemple:

: DECODE-CLAVIER ( ---)
 BEGIN CR ." Appuyez sur une touche du clavier (ESC pour finir) "
 KEY CR ." Vous venez d'appuyer sur la touche de code "
 DUP . 27 = UNTIL ;

Notez à l'exécution de DECODE-CLAVIER les codes retournés par certaines touches spéciales (fonctions, contrôles, touches alternes): il faudra parfois exécuter deux KEY pour accéder à ces touches.


KEY? --- f  

Mot d'exécution vectorisée. Délivre un flag booléen vrai si une touche a été activée au moment de l'exécution de ce mot. KEY? exécute par défaut (KEY?).

: ARRETEZ-MOI ( -- )
 BEGIN CR ." frappez une touche..." KEY?
 UNTIL KEY DROP ;

STOP? --- f  

Ce mot se met en attente d'une touche dès qu'une première touche est pressée puis délivre un booléen vrai s'il s'agit de la touche de retour-chariot. STOP? est utilisé pour suspendre momentanément ou sortir d'un processus répétitif:

: JE-COMPTE ( -- )
 0 BEGIN CR DUP . 1+ STOP?
 UNTIL DROP ;

3. Émission des caractères.

EMIT c ---  

Mot d'exécution vectorisé. Affiche le caractère de code ASCII c sur le périphérique sélectionné. Le mot EMIT peut être vectorisé par l'un des mots suivants:
(CONSOLE) Affichage sur le moniteur
(PRINT) Affichage sur l'imprimante
(EMIT) Affichage sur le moniteur et l'imprimante si PRINTING est vrai, sinon n'affiche que sur le moniteur.

Selon le matériel utilisé, le code ASCII du caractère c peut être compris dans l'intervalle 0<=c<127 ou 0<=c<255. L'interprétation des codes compris entre 0 et 31 dépend du matériel utilisé, mais en règle générale, ce sont les codes ASCII standards qui sont exécutés. Attention, si votre système dispose d'options de sélection de mode d'affichage ou de couleurs par l'intermédiaire du code ASCII ESC (27 en décimal), les commandes resteront spécifiques à votre système.

Le mot EMIT peut aussi être revectorisé sur un mot défini par l'utilisateur. Exemple:

: UP-EMIT ( c ---)
 UPC (EMIT) ;  \ transformation majuscule
' UP-EMIT IS EMIT

A partir de ce moment, TURBO-Forth refuse d'afficher les caractères minuscules. En fait, UP-EMIT convertit tout caractère minuscule en caractère majuscule


BACKSPACES n ---  

Envoie n fois le code ASCII 8 de recul d'une colonne sans effacement sur le terminal de sortie. Attention, seul le code 8 est envoyé, ce qui peut poser des problèmes sur certaines imprimantes.


BEEP ---  

Provoque l'émission d'un bip sonore sur la majorité des terminaux et imprimantes.


CR ---  

Mot d'exécution vectorisée. Exécute par défaut le mot CRLF. Exécute un retour chariot et le passage à la ligne suivante du curseur sur la console ou l'imprimante. Le contenu du compteur de caractères #OUT est remis à zéro et le contenu du compteur de lignes #LINES est incrémenté d'une unité.


CRLF ---  

Exécute un retour chariot avec saut de ligne sur le terminal de sortie. Ce mot est exécuté par défaut par le mot CR. Il émet les codes ASCII 13 et 10. En impression, certaines imprimantes exécutent ces deux fonctions à la seule réception du code ASCII 13, ce qui provoque une impression en double interligne. Pour éviter ceci, il faut revectoriser CR comme suit:

: (CR) 13 EMIT ;
: PRINTER
 ['] (PRINT) IS EMIT ['] (CR) IS CR ;
: CONSOLE ['] (EMIT) IS EMIT ['] CRLF IS CR ;

Et à partir de maintenant, tapez simplement PRINTER pour déclencher une séance d'impression. Tapez ensuite CONSOLE pour ramener l'affichage vers l'écran exclusivement. Si vous désirez une impression simultanée sur l'imprimante et l'écran, il faudra remplacer (PRINT) par (PEMIT) dans la définition de PRINTER.


REPLICATE n car ---  

Reproduit n fois le caractère de code ASCII car. Le mot SPACES utilise REPLICATE dans sa définition. Pour rappel, le standard n'interdit pas de définir un mot standard à l'aide de mots non standards, pourvu que le fonctionnement de ce mot reste standard. Exemple d'utilisation de REPLICATE:

: LIGNE 80 ASCII - REPLICATE ;

SPACE --- F83

Envoie un caractère 'espace' vers le terminal (console, imprimante ou les deux) déterminé par EMIT.

ASCII A EMIT ASCII B EMIT     affiche AB
ASCII A EMIT SPACE ASCII B EMIT  affiche A B

SPACES n --- F83

Envoie n caractères 'espace' vers le terminal.

ASCII A EMIT 3 SPACES ASCII B EMIT  affiche A  B

TYPE adr long --- F83

Envoie vers le terminal une chaîne explicite de caractères débutant à l'adresse adr et longue de long octets:

: BALBUTIEMENT ( -- )
 " Ceci est un test " ( adr n -- )
 0 DO CR DUP I TYPE LOOP DROP ;

A l'exécution ce petit exemple va afficher des chaînes de plus en plus longues:

C
Ce
Cec
Ceci
...etc.

Comme pour tous les mots envoyant un ou plusieurs caractères sur le terminal, c'est le mot d'exécution vectorisée EMIT qui détermine sur quel(s) périphérique(s) de sortie sont envoyés les caractères:

' (PRINT)  IS  EMIT  BALBUTIEMENT
' (EMIT)  IS  EMIT  BALBUTIEMENT

>TYPE adr long ---  

Version sécurisée multi-tâche de TYPE : n'affiche une chaîne qu'après l'avoir déplacée dans la zone mémoire temporaire PAD .


LTYPE seg adr long ---  

Version multisegment de TYPE : l'adresse de la chaîne est exprimée sur 32 bits en segment et adresse offset. (seg adr)


4. Fonctions de mise en page.

#OUT --- adr  

Variable gardant le nombre de caractères déjà envoyés sur une ligne: #OUT est remis à zéro à chaque retour à la ligne ou effacement de page vidéo provoqué par DARK.


#LINE --- adr  

Variable gardant le nombre de lignes déjà envoyées: incrémentée à chaque retour à la ligne, elle est remise à zéro par DARK.


LMARGIN --- adr  

Variable donnant le nombre d'espaces jusqu'à la marge de gauche. Sa valeur initiale est nulle. Le mot WORDS est un exemple de mise en page:

10 LMARGIN ! WORDS

RMARGIN --- adr  

Variable donnant le nombre de colonnes jusqu'à la marge de droite. Sa valeur initiale est de 70. Le mot WORDS est un exemple de mise en page:

0 RMARGIN ! WORDS

?LINE n ---  

Réalise un passage à la ligne sur la marge gauche s'il reste moins de n colonnes jusqu'à la marge de droite. Permet de "wrapper" une chaîne qui serait coupée en fin de ligne:

: NE-ME-COUPEZ-PAS ( -- )10 0 DO " ne-me-coupez-pas "
 DUP ?LINE TYPE LOOP ;

?CR ---  

Réalise un passage à la ligne sur la marge gauche si la marge de droite est dépassée. Est utilisé par WORDS .


?TAB len ---  

Réalise une tabulation à espacement régulier: un nombre suffisant d'espaces est émis pour que l'affichage (ou l'impression) reprenne sur une colonne multiple de len. Est utilisé notamment par WORDS .

: JOLIE-TABLE ( -- )
 CR 100 0 DO ?CR 8 ?TAB I . LOOP ;

5. Gestions spécifiques de l'écran.

(AT) col lig --- col lig  

Primitive de AT positionnant le curseur sur une ligne et une colonne de l'écran vidéo. Utilise une interruption compatible BIOS (10 hexa). Colonne et ligne sont laissés sur la pile.


AT col lig ---  

Positionne le curseur clignotant sur une ligne donnée (de 0 à 24 sur un écran usuel) et une colonne donnée (de 0 à 79 généralement). Les variables #OUT et #LINE prennent les valeurs col et lig.

: ESCALIER ( -- ) DARK 20 0 DO I I AT 
 ." Écriture en escalier" LOOP ;

(CURSOR) --- col lig  

Donne la position courante du curseur clignotant en colonne (de 0 à 79 généralement) et numéro de ligne (de 0 à 24 sur un écran usuel). Fait appel à une interruption compatible (10 hexa) BIOS.

: PETIT-COMPTEUR (CURSOR) 1000 0
 DO 2DUP AT I . LOOP 2DROP ;

(FRAME) frame1 frame2 ---  

Fixe la taille du curseur clignotant: frame1 est la première ligne- pixel, frame2 la dernière ligne-pixel du pavé clignotant. Selon les cartes vidéo ces paramètres pourront varier de 0 à 7 (carte couleur) ou de 0 à 13 (carte monochrome) le plus souvent. Si frame2 est inférieur à frame1, le curseur disparaît. Fait appel à une interruption compatible (10 hexa) BIOS.

0 7 ( ou 0 13 ) (FRAME) : gros pavé curseur 
0 0 (FRAME) : curseur fin "en haut" 
7 7 (FRAME) : curseur fin "en bas" ou "au milieu"

GRMODE --- adr  

Variable conservant le mode vidéo d'affichage graphique. Consultez votre documentation technique pour savoir quels sont les modes supportés par votre équipement. La valeur initiale de GRMODE est 2 ce qui correspond à l'affichage texte monochrome en 80*25 caractères.


(MODE) ---  

Primitive de MODE : fixe le mode d'affichage vidéo graphique tel qu'il est défini dans la variable GRMODE. Fait appel à une interruption compatible (10 hexa) BIOS.


MODE n ---  

Change le mode d'affichage vidéo graphique. La valeur n (comprise entre 0 et 7 le plus souvent) est conservée dans la variable GRMODE. Consultez votre documentation technique pour connaître les modes supportés par votre équipement.


DARK ---  

Efface l'écran vidéo en réinitialisant le mode d'affichage vidéo. Remet à zéro les variables #OUT et #LINE de mise en page. Bien qu'il ne s'agisse pas d'un mot vectorisé, DARK est accessible à une redéfinition selon le terminal utilisé. Exemple: pour un terminal de type imprimante, l'action de DARK serait de réaliser un saut de page:

: FORM-FEED 12 (PRINT)
 \ 12 code saut de page le plus fréquent ;
' FORM-FEED IS DARK 
L'option DARK quand PRINTING est ON provoque un saut de page
' (MODE) IS DARK
\ pour rétablir l'action usuelle de DARK sur l'écran

Dans TURBO-Forth, le mot DARK a été pseudo-vectorisé. A la méta- compilation, le premier mot de sa définition a été NOOP, c'est à dire 'ne rien faire'. Mais le principe de revectorisation exécuté par IS a substitué le mot (MODE) à NOOP en début de définition.


6. Attributs d'affichage vidéo.

ATTRIBUTS --- adr  

Variable délivrant un flag booléen autorisant ou non l'envoi d'une séquence ESCape à l'affichage par les mots utilisant (ATTRIB). Les séquences ESC sont normalement gérées par le fichier système driver ANSI.SYS. Si celui-ci n'a pas été appelé à l'initialisation du système, les attributs risquent de ne pas être gérés correctement. Dans ce cas, on neutralise les effets indésirables en tapant:

ATTRIBUTS OFF

A partir de maintenant, les mots BOLD, UNDERL, BLINK et INVERS deviennent inopérants. Pour bénéficier des attributs d'affichage par séquences ESC, il faut que votre fichier CONFIG.SYS (le créer au besoin) contienne la ligne texte suivante:

DEVICE = ANSI.SYS

et que le fichier ANSI.SYS soit présent dans le répertoire actif lors du Boot du système. Turbo-Forth suppose à son lancement que c'est bien le cas et c'est donc l'option ATTRIBUTS ON qui est active: vous le remarquez par l'affichage gras (bold) du message 'OK'.


(ATTRIB) n ---  

Envoie l'attribut numéro n. Cette valeur vient s'intégrer dans une séquence ESC et modifie les attributs d'affichage en mode texte (surintensité, inversion, clignotement, etc...). Pour les possesseurs d'une carte couleur, ce mot permet d'ajouter d'autres commandes d'attributs en plus des mots BLINK BOLD INVERS UNDERL déjà définis:

: RED 31 (ATTRIB) ;  \ affichage en caractères rouges
: -BLUE 44 (ATTRIB) ;  \ affichage sur fond bleu

Consultez votre documentation technique sur les codes de contrôle ANSI de votre terminal: 30 à 37 pour les couleurs de l'avant-plan et 40 à 47 pour les couleurs du fond sont des valeurs habituelles. Certaines séquences risquent de ne pas fonctionner correctement sur tous les systèmes, notamment si vous êtes en mode CGA, EGA ou HERCULES.


BLINK ---  

Envoie une séquence d'attributs. Provoque le clignotement de tout caractère émis par la suite sur le moniteur si ATTRIBUTS est ON.


BOLD ---  

Envoie une séquence d'attributs. Provoque la surintensité de tout caractère émis par la suite sur le moniteur si ATTRIBUTS est ON.


INVERS ---  

Envoie une séquence d'attributs. Provoque l'inversion vidéo de tout caractère émis par la suite sur le moniteur si ATTRIBUTS est ON.


UNDERL ---  

Envoie une séquence d'attributs. Provoque le soulignement de tout caractère émis par la suite sur le moniteur si ATTRIBUTS est ON.


ATTOFF ---  

Envoie une séquence d'attributs. Provoque le retour en affichage normal et annule donc les attributs d'affichage précédemment demandés par BOLD, UNDERL, BLINK ou INVERS si ATTRIBUTS est ON.

20 STRING TEST$
" Test des attributs vidéo" TEST$ $!
: VARIATIONS ( -- )
 CR BOLD  TEST$ TYPE ( en gras )
 ATTOFF
 CR UNDERL TEST$ TYPE ( souligné )
 CR BOLD  TEST$ TYPE ( gras et souligné )
 ATTOFF CR TEST$ TYPE ( normal ) ;
ATTRIBUTS OFF VARIATIONS
ATTRIBUTS ON VARIATIONS

C. LA GESTION DE LA MÉMOIRE DE MASSE.

1. Les noms de fichiers.

PATHWAY chemin\nom --- adr0  

Interprète dans le flot d'entrée un chemin d'accès à un fichier. Délivre pour MS-DOS une adresse ascii0. La chaîne à interpréter doit être d'un seul tenant sans espace et peut comporter toutes les composantes d'un nom de fichier: lettre d'un lecteur suivi de ':', succession de répertoires et sous-répertoires séparés par '\', nom du fichier (8 caractères maximum), extension du nom ( '.' et 3 caractères maximum). MS-DOS accepte des chemins-noms de fichiers pouvant totaliser 64 caractères. Exemples:

PROG PROGRAMM.$$$ C:FORTH\GRAPHICS\DESSINS\SCHEMAS\MOTIFS\LUTIN.PIC 

Note: Une chaîne ascii0 est une formulation de chaîne de caractères que TURBO-FORTH n'a pas l'habitude d'utiliser pour son compte. Elle est définie par une adresse de début et se termine obligatoirement par le caractère nul (octet zéro). Ce type d'expression d'une chaîne est en général moins pratique que les chaînes explicites (adresse,longueur) ou les chaînes implicites (adresse avec la longueur codée sur le premier ou les deux premiers octets) car il n'est pas possible d'en connaître la longueur sans l'explorer caractère par caractère. Il en est de même pour un autre type de chaîne parfois utilisées par MS-DOS, les chaînes ascii$ où c'est le caractère '$' qui signale la fin de la chaîne avec comme contrainte supplémentaire l'interdiction d'utiliser ce caractère à l'intérieur d'une chaîne.


EXT$ --- adr long  

Variable chaîne (voir le mot STRING) donnant une extension par défaut pour des noms de fichiers. Sa longueur maximale est de 4 caractères compte tenu du point '.' qui reconnaît le début d'une extension de nom.

EXT$ TYPE affiche '.FTH'

.FTH est l'extension habituelle des fichiers exploités par Turbo- Forth.


FILENAME <chemin\nom[.ext]>--- adr0  

Interprète dans le flot d'entrée un chemin d'accès à un fichier. Délivre pour MS-DOS une adresse ascii0. Ce mot réalise la même fonction que le mot PATHWAY à la différence qu'il incorpore dans la chaîne l'extension par défaut EXT$ si aucune extension n'est précisée. Pour accéder à un fichier sans aucune extension par FILENAME, il suffit de faire suivre le nom par un point seul. Exemples:

PROG   est interprété PROG.FTH 
PROG.BAS        PROG.BAS 
PROG.          PROG

2. Fonctions primitives DOS.

?DOS-ERR err ---  

Traite le code erreur en retour d'un appel à une fonction MS-DOS. Ce code est égal à zéro si l'opération s'est déroulée correctement sans erreur. Dans le cas contraire MS-DOS fournit un code compris entre 1 et 18 (variable selon les versions) dont la signification est commune aux diverses fonctions appelées. Ainsi le code 2 signifie 'fichier non trouvé'.

?DOS-ERR affiche le dernier mot interprété suivi d'un message explicatif de l'erreur et provoque l'arrêt du traitement (voir ABORT) si le code err est non nul.

Toute erreur provoquant un ABORT du traitement en cours a pour effet de fermer tous les fichiers ouverts par Turbo-Forth.

?DOS-ERR doit suivre la plupart des primitives DOS quand elles délivrent un code err sur la pile.


(OPEN) adr0 access --- hndl err  

Ouvre un fichier existant et en autorise donc l'accès. Adr0 est une adresse de chaîne ascii0 (voir ci dessus PATHWAY ou FILENAME) qui peut contenir un chemin de répertoire. Access est un code d'accès MS-DOS qui doit prendre l'une des valeurs suivantes:

access=0 : accès au fichier en lecture seule 
access=1 : accès au fichier en écriture seule 
access=2 : accès au fichier en lecture ou écriture

En retour hndl est le ticket (handle) d'accès au fichier et err le code de retour d'appel MS-DOS.

Le ticket est un numéro d'ordre qui représente un canal d'entrée- sortie pour MS-DOS. Les tickets sont attribués dans un ordre croissant dans la limite des fichiers ouvrables par le DOS. Le premier ticket attribué à un fichier est 5 car les tickets 0 à 4 sont toujours déjà attribués:

hndl=0 : périphérique standard d'entrée (le clavier en principe) 
hndl=1 : périphérique standard de sortie (l'écran en principe) 
hndl=2 : sortie des erreurs (l'écran ; non utilisé par Forth)
hndl=3 : périphérique auxiliaire (port série en général) 
hndl=4 : imprimante 
hndl=5 : premier fichier ouvert

... Par défaut MS-DOS fixe à 8 le dernier ticket attribuable mais cette valeur peut être modifiée par la commande FILES=xx dans le fichier CONFIG.SYS au lancement du système.

Le code de retour err sera non nul si le fichier n'est pas trouvé, si la chaîne du nom est incorrecte, s'il n'y a plus de ticket disponible ou si l'accès est refusé. Cette dernière erreur survient quand le code d'accès d'ouverture n'est pas compatible avec l'attribut du fichier comme par exemple vouloir ouvrir en lecture- écriture un fichier d'attribut lecture-seule.

Si l'ouverture est réalisée (err=0), le pointeur de fichier MS-DOS pointe sur le premier octet du fichier.

: OUVRE ( <fichier> -- )
 CR FILENAME 0 (OPEN) ?DOS-ERR 
 HERE COUNT TYPE ." ouvert avec le ticket " . ;
 OUVRE TURBO.COM
 TURBO.COM ouvert avec le ticket 5
 OUVRE ALEPH ALEPH.FTH ouvert avec le ticket 6
 OUVRE MACHIN MACHIN.FTH fichier non trouvé
 OUVRE CLOCK CLOCK.FTH ouvert avec le ticket 5
 ... 

(CLOSE) n ---  

Ferme le fichier ouvert au ticket n. Le ticket n est libéré. Ce mot ne laisse pas de code err en retour et n'a donc pas à être suivi de ?DOS-ERR.


(CREATE) adr0 att --- hndl err  

Crée un nouveau fichier et l'ouvre en lecture-écriture. Adr0 est une adresse de chaîne ascii0 (voir ci dessus PATHWAY ou FILENAME) qui peut contenir un chemin de répertoire. Att est l'attribut que MS-DOS doit assigner au nouveau fichier. Il s'agit d'un octet dont les bits 0 à 5 ont chacun une signification:

bit 0 à 1 : fichier en lecture seule (protégé contre l'écriture ou l'effacement)
bit 1 à 1 : fichier caché (non affiché par DIR)
bit 2 à 1 : fichier système (recopié par SYS)
bit 3 à 1 : pseudo-fichier nom du volume
bit 4 à 1 : pseudo-fichier nom d'un répertoire 
bit 5 à 1 : fichier modifié (bit d'archivage)
      (utilisé par la commande externe BACKUP)

Lors de la création d'un fichier par (CREATE) c'est généralement l'attribut zéro (tous bits à zéro) qui doit être utilisé. En retour hndl est le ticket (handle) d'accès au fichier ainsi créé et err le code de retour d'appel MS-DOS: voir (OPEN).

Si le fichier à créer existe déjà dans le même répertoire, il est recréé sans code d'erreur et son ancien contenu est entièrement vidé (sauf s'il est protégé). Le pointeur de fichier est placé en début de fichier (ou en fin puisqu'il s'agit toujours d'un fichier vide)

: CREER-FICHIER-VIDE (<fichier> -- )
 FILENAME 0 (CREATE) ?DOS-ERR (CLOSE) ;
CREER-FICHIER-VIDE INUTILE 
DIR 

affiche l'existence d'un fichier INUTILE.FTH 0


(SEEK) ddép hndl sens --- dpos err  

Déplace le pointeur de fichier dans un fichier déjà ouvert pour des opérations de lecture ou d'écriture en accès direct. Comme un fichier peut avoir plus de 64 kilo-octets, ce mot utilise des arguments entiers 32 bits (deux cellules sur la pile):

Ddép est le nombre 32-bits d'octets de déplacement du pointeur de fichier.
Hndl est le ticket du fichier concerné.
Sens détermine le sens du déplacement:
   sens=0 : déplacement depuis le début du fichier
   sens=1 : déplacement depuis la position actuelle du pointeur
   sens=2 : déplacement depuis la fin du fichier

Au retour dpos donne sur 32 bits la nouvelle position du curseur et err est le code de retour MS-DOS.

L'argument de retour dpos peut être exploité pour connaître la taille d'un fichier:

: FILESIZE ( <filename>-- dlen )
 FILENAME 0 (OPEN) ?DOS-ERR
 DUP 0 0 ROT 2 (SEEK) ?DOS-ERR ROT (CLOSE) ;

FILESIZE TURBO.COM D.

affiche la taille du fichier TURBO.COM


(GET) seg adr len hndl --- len' err  

Primitive de lecture séquentielle dans un fichier: charge dans un tampon intra ou extra-segment len octets depuis le fichier (ou le périphérique) ouvert au ticket hndl.

Le tampon de lecture est donné par son adresse étendue seg (segment) et adr (offset adresse). Si le tampon de lecture est dans le segment Forth, on utilisera le mot DSEGMENT comme premier argument. Au retour, len' donne le nombre d'octets effectivement lus et err est le code de retour d'appel MS-DOS. Len' peut être inférieur à len si la fin du fichier a été atteinte sans que le code err soit celui d'une erreur.

La lecture s'effectue à la position courante du pointeur de fichier; celui-ci est déplacé en avant de len' octets pour poursuivre une lecture séquentielle.

: LIT-DEBUT ( <fichier> -- )
 FILENAME 0 (OPEN) ?DOS-ERR >R
 DSEGMENT PAD 10 R@ (GET) ?DOS-ERR
 PAD SWAP TYPE R> (CLOSE) ;

LIT-DEBUT ESSAI

affiche les 10 premiers caractères de ESSAI.FTH


(PUT) seg adr len hndl --- len' err  

Primitive d'écriture séquentielle dans un fichier: sauve len octets depuis un tampon intra ou extra-segment dans le fichier (ou le périphérique) ouvert au ticket hndl.

Le tampon d'écriture est donné par son adresse étendue seg (segment) et adr (offset adresse). Si le tampon est dans le segment Forth, on utilisera le mot DSEGMENT comme premier argument.

Au retour, len' donne le nombre d'octets effectivement écrits et err est le code de retour d'appel MS-DOS. Len' peut être inférieur à len si le support n'a plus de place pour allonger le fichier sans que le code err soit celui d'une erreur.

L'écriture s'effectue à la position courante du pointeur de fichier; celui-ci est déplacé en avant de len' octets pour poursuivre une écriture séquentielle.

: ECRIT-DEBUT ( <fichier> string -- )
 FILENAME 1 (OPEN) ?DOS-ERR >R
 DSEGMENT -ROT R@ (PUT) ?DOS-ERR DROP
 R> (CLOSE) ;

" \ essai de (put)" ECRIT-DEBUT ESSAI 

inscrit \ essai de (put)' en tête du fichier ESSAI.FTH (à tester sur un fichier sans importance bien entendu)


DMA --- adr  

Donne l'adresse de la DMA (direct memory address) aussi appelée DTA (Disk transfer area) qui est la zone de la mémoire RAM dont MS-DOS se sert pour les transferts d'enregistrements sur disque quand les accès sont de type FCB (File control block) ou pour placer des informations sur les fichiers. La DTA n'est pas utilisée pour la gestion par tickets (handles).

Lors du lancement d'un programme, MS-DOS fixe par défaut sa DTA à l'adresse 128 dans le préfixe du segment de programme (PSP) avec une taille utilisable qui ne peut dépasser 128 octets sous peine d'écraser le début du programme lui-même.

 
SET-DMA adr ---  

Change l'adresse de la DMA (voir ci dessus) avec l'adresse adr. Utilisable notamment si la DMA doit avoir plus de 128 octets. Il ne peut y avoir qu'une DMA active. Le mot est de peu d'intérêt dans une gestion par tickets (handles).

 
(SEARCH0) adr0 att --- fl  

Recherche un fichier dans un répertoire: délivre un flag vrai si le fichier est trouvé et charge en DMA des informations à son sujet.

Adr0 est une adresse de chaîne ascii0 (voir PATHWAY ou FILENAME) qui peut contenir un chemin de répertoire si la recherche doit s'effectuer en dehors du répertoire courant. Cette chaîne peut contenir des caractères jokers comme '*' ou '?'. Dans ce cas seul le premier fichier trouvé correspondant au masque demandé est pris en compte. Il faut utiliser (SEARCH) pour accéder aux suivants.

Att permet d'étendre la recherche selon les attributs de fichier. Voir au mot (CREATE) la codification de l'attribut d'un fichier. Si Att=0 la recherche ne porte que sur les fichiers normaux. Quand un bit de Att est mis à un la recherche comporte en plus les fichiers désignés par ce bit d'attribut. Exemple: si Att=18 (2:bit caché + 16:bit répertoire), la recherche portera aussi bien sur les fichiers usuels que sur les fichiers cachés ou les pseudo-fichiers noms de répertoires.

Si un fichier spécifié a pu être trouvé, MS-DOS charge dans la DMA 43 octets qui fournissent des informations sur ce fichier:

octets 0-20 : réservés à MS-DOS pour la recherche
octet 21 : attribut du fichier
octets 22-23 : heure de la dernière écriture
octets 24-25 : date de la dernière écriture
octets 26-29 : taille du fichier (26-27:partie basse,28- 29:partie haute)
octets 30-42 : nom complet du fichier sous forme de chaîne ascii0

Le fichier trouvé n'est pas ouvert.

 
(SEARCH) --- fl  

Recherche un autre fichier dans un répertoire après une première recherche par (SEARCH0) ou après une précédente reprise de recherche par (SEARCH): dépose un flag vrai si un autre fichier spécifié a pu être trouvé et charge en DMA des informations à son sujet.

Il n'est pas besoin de répéter les arguments de la recherche par (SEARCH0) qui doit toujours précéder un ou plusieurs (SEARCH). Il faut juste veiller à ce que la DMA n'ait pas été modifiée entre (SEARCH0) et (SEARCH) car elle contient les informations pour que MS-DOS poursuive la recherche.

: COMBIEN-DE-FICHIERS ( <masque> -- ) 
 0 PATHWAY 0 (SEARCH0)
 IF BEGIN 1+ (SEARCH) NOT UNTIL THEN . ;

COMBIEN-DE-FICHIERS B:\FORTH\*.FTH

affiche le nombre de fichiers répondant au masque '*.FTH' dans le répertoire FORTH de B:

 
BDOS adr fun --- err  

Primitive d'appel de certaines fonctions MS-DOS (adr désigne généralement une adresse, fun est un numéro de fonction pour l'interruption 21H, err est le code de retour MS-DOS signalant une éventuelle erreur).

MS-DOS n'ayant pas un accès normalisé aux sous-fonctions de l'interruption 21H, ce mot n'est guère utilisable en dehors des fonctions qu'il sert à définir: SELECT (fun=14), SET-DMA (fun=26), MKDIR (fun=57), RMDIR (fun=58), CHDIR (fun=59) ou DEL (fun=65).

Voici à titre d'exemple un mot qui permet d'effacer dans le répertoire courant un groupe de fichiers (ce que n'autorise pas DEL) avec sélection au clavier des fichiers à effacer:

: ERA ( <masque> -- )
 0 PATHWAY 0 (SEARCH0)
 IF
  BEGIN
   CR .NAME ." Effacer ? O/N "
   KEY UPC DUP EMIT
   ASCII O =
   IF DMA 30 + 65 BDOS ?DOS-ERR 1+ THEN
   (SEARCH) NOT
  UNTIL
 THEN CR . ." fichiers effacés" ;

ERA *.* 

Affiche successivement tous les fichiers qu'il propose d'effacer puis affiche le nombre total de fichiers effacés.


DRV --- n  

Délivre le numéro du lecteur (drive) courant. Le code empilé n=0 pour désigner le lecteur A: , n=1 pour le lecteur B: etc...

 
SELECT n ---  

Sélectionne un numéro de lecteur (drive) courant: n=0 pour sélectionner le lecteur A: , n=1 pour le lecteur B: etc...

 
(FREE) n --- b/sec #clusters sec/cluster  

Primitive pour le calcul de la capacité restant libre sur un lecteur. Le code n=0 désigne le lecteur courant, n=1 le lecteur A: , n=2 le lecteur B: etc... Attention donc: MS-DOS n'utilise pas ici le même codage que pour les fonctions DRV et SELECT. En retour sont empilés trois valeurs 16 bits:

b/sec    est lenombre d'octets par secteur sur le disque.
#clusters  est le nombre de clusters (groupe de secteurs) restant libres.
sec/cluster est le nombre de secteurs par cluster ou -1 si n est invalide. 

L'espace mémoire disponible sur le support se calcule en multipliant (en double précision) les trois valeurs si le lecteur est valide: voir FREE.

 
(REN) adr01 adr02 --- err  

Primitive pour renommer un fichier ou le transférer dans un autre répertoire du même lecteur:

Adr01 est l'adresse d'une chaîne ascii0 (voir PATHWAY pour l'explication de ce type de chaîne) désignant l'ancien nom d'un fichier, comportant éventuellement un chemin d'accès.
Adr02 est l'adresse d'une chaîne ascii0 désignant le nouveau nom ou le nouveau chemin\nom pour ce fichier.

Les chaînes adr01 et adr02 ne peuvent contenir de caractères jokers '*' ou '?'ni désigner des noms de sous-répertoire ou de volume. Le code err est celui de retour d'appel MS-DOS signalant une éventuelle erreur.

3. La gestion des répertoires de fichiers.

A:--- Rend le lecteur de disque A: courant.
B: --- Rend le lecteur de disque B: courant s'il existe.
C: --- Rend le lecteur de disque C: courant s'il existe. C: est en général la dénomination du disque dur.
D: --- Rend le lecteur de disque D: courant s'il existe. D: est souvent la dénomination d'un disque virtuel en mémoire vive.
E: --- Rend le lecteur de disque E: courant s'il existe. E: peut être la dénomination d'un disque virtuel en mémoire vive.

CHDIR ---  

Change le répertoire courant avec le mot (au sens Forth) qui suit. Emet l'erreur 'chemin incorrect' si le répertoire n'existe pas ou n'est pas accessible. CHDIR C:\FORTH\IA\EXPERT CHDIR \ (pour retourner dans un répertoire racine) La commande CHDIR peut être obtenue en interprétation en frappant la touche de fonction F6.

 
MKDIR <répertoire>---  

Crée un nouveau sous-répertoire avec le 'mot' qui suit. Ce mot peut comporter un nom de lecteur et un chemin si le nouveau sous- répertoire est à créer en dehors du répertoire courant. MKDIR POUBELLE

 
RMDIR <répertoire> ---  

Supprime un sous répertoire désigné par le 'mot' qui suit. Ce mot peut comporter un nom de lecteur et un chemin si le sous-répertoire n'appartient pas au répertoire courant. RMDIR POUBELLE Cette commande est refusée par MS-DOS si le sous-répertoire n'est pas vide de fichiers.

 
DEL <chemin\fichier.ext>---  

Efface le fichier désigné par le 'mot' qui suit. Ce mot peut comporter un nom de lecteur et un chemin si le fichier n'est pas dans le répertoire courant. Un seul fichier peut être effacé: les caractères jokers '*' ou '?' ne sont pas acceptés. L'extension du nom de fichier doit être précisée car elle n'est pas interprétée par défaut. DEL C:\FORTH\INUTILE.FTH

REN ---  

Renomme un fichier nom1 (ancien nom) en nom2 (nouveau nom). REN interprète les deux 'mots' qui le suivent dans le flot d'entrée. Ces mots peuvent comporter un nom de lecteur et un chemin d'accès jusqu'au fichier. Il est possible d'utiliser REN pour transférer un fichier d'un répertoire dans un autre à condition qu'il s'agisse du même lecteur. Les extensions des noms de fichiers peuvent être omises dans le cas de l'extension par défaut (voir EXT$).

REN TRUC MACHIN      renomme TRUC.FTH en MACHIN.FTH
REN C:\DOS\COMMAND.COM C:\FORTH\COMMAND.COM
transfère COMMAND.COM dans le sous-répertoire FORTH 
 

FREE --- d  

Délivre le nombre d'octets restant libres sur le lecteur courant. Ce nombre est codé sur 32 bits (entier double précision). FREE D.

 
.NAME ---  

Primitive de DIR affichant le nom d'un fichier et sa taille en octets. L'information est lue dans la DMA après une recherche de fichiers par (SEARCH0) ou (SEARCH) (voir ces mots).

 
(DIR) adr long ---  

Primitive de DIR affichant la liste des fichiers d'un répertoire selon le masque donné par une chaîne explicite débutant en adr et longue de long octets. Cette chaîne peut comporter un nom de lecteur, un chemin de répertoire, des caractères jokers '*' ou '?'.

" A:\FORTH\*.FTH" (DIR)
: CAT " *.FTH" (DIR) ;
CAT 

affiche un directory des fichiers .FTH du répertoire courant.


DIR [<chemin\masque>] ---  

Commande d'affichage du directory (liste des fichiers) d'un répertoire. DIR interprète dans le flot d'entrée le mot qui le suit comme chemin d'accès et masque. Ce mot est facultatif (frapper DIR puis touche ): tous les fichiers du répertoire courant sont affichés (équivaut à 'DIR *.* ').

DIR
DIR B:*.*
DIR C:\FORTH\ESSAI?.F* 

La commande DIR seule peut être obtenue en interprétation en frappant la touche de fonction F5.

 

D. LA MEMOIRE VIRTUELLE DE TURBO-FORTH.

1. Tickets de fichiers ouverts par Turbo-Forth.

FILES --- 8  

Constante donnant le nombre maximal de tickets pouvant être ouverts simultanément par Turbo-Forth. La valeur 8 correspond à la valeur par défaut de MS-DOS et permet d'ouvrir 4 fichiers (tickets 5 à 8, les tickets 0 à 4 étant réservés aux périphériques standards).

Ce nombre peut se révéler insuffisant d'autant que 8 est le nombre total de tickets ouverts y compris quand plusieurs programmes différents sont susceptibles d'ouvrir des fichiers (voir les commandes d'intégration).

Pour modifier le nombre de tickets utilisables, il faut d'abord changer la variable MS-DOS FILES (c'est le même nom) dans le fichier CONFIG.SYS en y plaçant une ligne 'FILES=xx' avec xx compris entre 8 et 255. La variable FILES peut atteindre 255 globalement, mais il faut savoir qu'un programme ne peut utiliser plus de 20 tickets (soit 14 fichiers) à lui tout seul.

Si FILES de MS-DOS permet plus de 8 tickets, FILES de Turbo-Forth peut être modifié jusqu'à 20 en le traitant comme une pseudo- constante:

14 IS FILES 

autorise 14 tickets (soit 10 fichiers).


#FILES --- n  

Délivre le nombre de tickets actuellement utilisés par Turbo-Forth. Ce nombre est au plus égal à la constante FILES.

 
?OPEN ---  

Assure que Turbo-Forth peut utiliser un nouveau ticket pour ouvrir un fichier. Un message d'erreur 'Trop de fichiers ouverts pour TURBO-Forth' est émis si le programme ne peut ouvrir un nouveau fichier. Ce type d'erreur survient le plus souvent quand trop de commandes INCLUDE (voir ce mot) sont imbriquées les unes dans les autres.

Voir le mot FILES pour savoir comment étendre la multi-ouverture de fichiers aussi bien au niveau de MS-DOS qu'au niveau de Turbo- Forth.

 
HANDLE --- adr  

Variable USER contenant le ticket (handle) courant. Le ticket courant désigne le périphérique d'où sont lues toutes les commandes au langage (flot d'entrée de l'interpréteur: voir le mot SOURCE):

HANDLE ?

affiche 0 si cette commande est entrée au clavier affiche 5 (ou plus) si elle est contenue dans un fichier interprété.

Toutefois Turbo-Forth utilise aussi HANDLE pour désigner un flot d'entrée dans une chaîne interprétée (voir $EXECUTE). Dans ce cas la valeur contenue dans HANDLE est négative ce qui n'a plus de sens en terme de "ticket" MS-DOS mais reste le témoin du niveau d'imbrication de l'interpréteur:

: NIVEAU1 " HANDLE ?" $EXECUTE ;
: NIVEAU2 " NIVEAU1" $EXECUTE ;
NIVEAU1   affiche -1
NIVEAU2   affiche -2 

HANDLE ne peut pas être modifié directement par l'utilisateur: vouloir écrire 5 HANDLE ! provoquera une erreur même si un fichier est ouvert au ticket 5. Voir plus loin au mot GETLINE un exemple qui montre comment doit être utilisé HANDLE.

 
OPEN <fichier[.ext]>--- hndl  

Ouvre un fichier en lecture et initialise un tampon de ligne. Le nom du fichier est interprété dans le flot d'entrée avec le mot qui suit: ce nom peut comporter l'indication d'un lecteur et d'un chemin de répertoire; l'extension du nom est facultative s'il s'agit de l'extension par défaut.

Le ticket courant n'est pas modifié: OPEN laisse sur la pile le ticket du fichier ouvert par MS-DOS. Voir plus loin au mot GETLINE un exemple d'utilisation de OPEN.

 
CLOSE ---  

Ferme le fichier ouvert au ticket courant (voir HANDLE). Ce mot ne doit pas être utilisé sans être immédiatement suivi d'une réaffectation de HANDLE. Voir plus loin au mot GETLINE un exemple d'utilisation de CLOSE.

 
ALLCLOSE ---  

Ferme tous les fichiers ouverts par TURBO-FORTH. Ce mot peut éventuellement être exécuté seul mais uniquement au clavier (quand HANDLE contient le ticket zéro).

Il importe de savoir que toute erreur d'interprétation même sans rapport avec la gestion de fichiers provoque ALLCLOSE ; c'est le cas des mots (?ERROR) ?ERROR ?DOS-ERR ABORT" .


2. Les tampons de lignes.

LBUF --- 322  

Constante codée donnant la longueur d'un tampon de fichier. Turbo-Forth gère un ensemble de textes divers qui forme sa mémoire virtuelle de programmes tantôt interprétés tantôt compilés. Cette mémoire virtuelle n'est plus organisée en blocs sur le support disque comme dans les anciennes versions du langage mais en fichiers ASCII standards dont nous avons vu qu'ils bénéficient de toutes les fonctionnalités d'un système d'exploitation structuré.

Turbo-Forth lit ses fichiers séquentiellement ligne par ligne et affecte donc pour chaque fichier ouvert un tampon de ligne situé au sommet de sa mémoire segment (juste en deçà des piles). Chaque tampon contient l'espace suffisant pour charger une ligne plus un certain nombre d'informations indispensables, le tout occupant 322 octets. Voici la répartition de ces 322 octets:

Cette organisation amène à poser deux questions:

  1. Les lignes des fichiers FORTH peuvent-elles comporter plus de 255 caractères (retour chariot compris)? Réponse: NON. Turbo-Forth refuse d'interpréter de très longues lignes. Ceci ne représente pas une réelle limitation dans la mesure où interpréteur et compilateur sont multilignes (tous les mots peuvent être présentés sur une nouvelle ligne). Seules les chaînes en tant que telles ( "Ô temps! suspends ton vol; et vous, heures propices suspendez votre cours!") doivent être placées sur une seule ligne mais elles aussi sont limitées à 255 caractères d'un seul tenant. Par ailleurs les lignes courtes facilitent la lecture des programmes.
  2. Les fichiers FORTH peuvent-ils comporter plus de 32767 ou même plus de 65535 lignes? Réponse: OUI. Le nombre 16 bits indiquant le numéro de la ligne en cours dans le tampon n'est là que pour signaler à l'utilisateur sur quelle ligne le système a détecté une éventuelle erreur. Si une erreur survient au delà de la 32767 ieme ligne, le message signalera un nombre négatif encore valide pour l'édition; au delà de 65535 lignes la localisation de l'erreur sera impropre mais facilement retrouvée. Il reste cependant toujours conseillé de privilégier l'usage de petits fichiers organisés en modules même (et surtout) pour les très gros programmes: chaînages et inclusions facilitent la conception et la mise au point.

 
C/PATH --- 64  

Constante codée donnant la longueur maximale du nom d'un fichier tel qu'il est conservé dans le tampon. Cette valeur de 64 caractères est celle qu'autorise MS-DOS. Rappelons qu'un fichier peut être désigné par une chaîne relativement longue comportant un nom de lecteur et un chemin d'accès dans les répertoires et sous- répertoires. Exemple:

'C:\FORTH\MATH\CALCUL\SQR.FTH' 

 
BUFFER --- adr  

Délivre l'adresse du tampon du fichier courant. Cette adresse pointe directement sur la chaîne implicite de la dernière ligne chargée. Voir au mot LBUF l'organisation d'un tampon.

 
.LINE ---  

Affiche la ligne contenue dans le tampon du fichier courant. Ce mot est exécuté à chaque GETLINE si la variable ECHO est ON. Voir plus loin au mot GETLINE un exemple d'utilisation de .LINE.

 
LINE# --- adr  

Délivre une adresse dans le tampon courant contenant sur 16 bits le numéro de la dernière ligne chargée. Voir au mot LBUF l'organisation d'un tampon.

 
PATHNAME --- adr  

Délivre une adresse dans le tampon courant contenant le chemin\nom du fichier en cours de lecture. Voir au mot LBUF l'organisation d'un tampon. A cette adresse débute une chaîne explicite fixe de 64 caractères; le nom complet du fichier est éventuellement complété à droite par des espaces.

 
PATHNAME! adr long ---  

Enregistre le chemin\nom (PATHNAME) d'un fichier dans la zone tampon réservée à ce fichier. Ce mot est exécuté par OPEN. Il n'y a pas lieu de l'utiliser en pratique.

Note sur les tampons de lignes: nous avons vu que les tampons étaient alloués ticket par ticket dans la mémoire haute du segment de programme (voir la carte mémoire de Turbo-Forth en annexe) et ceci de façon descendante, le tampon du ticket n+1 étant situé sous le tampon du ticket n . Il peut être utile de savoir que tous les tickets y compris les numéros 0 à 4 réservés aux périphériques disposent d'un tampon de ligne Forth. Ils ne sont guère utilisés en pratique. Leur existence se justifie par les possibilités de redirections des entrées-sorties par MS-DOS qui peuvent également être exploitées par Turbo-Forth comme dans le module PIP.FTH . Ces tampons additionnels sont également à la disposition de l'utilisateur.


3. Lecture des lignes d'un fichier.

EOF? --- adr  

Variable booléenne dont le contenu est vrai s'il n'y a plus de ligne à lire dans le fichier courant.

 
EOF ---  

Force la variable EOF? à la valeur 'vrai' ce qui provoque une fin de fichier artificielle pour l'interpréteur.

EOF est utile pour placer un texte de commentaires à la fin d'un fichier source: toutes les lignes placées après celle contenant EOF ne seront pas interprétées et le fichier sera refermé par le système dès qu'il aura fini d'interpréter la ligne contenant EOF.

Ce mot permet également de vous faciliter la mise au point de programmes délicats. Pour exemple, si la compilation d'un programme source plante votre système et que vous soyez obligé de couper l'alimentation ou de relancer le DOS pour avoir à nouvau la main, éditez le programme incriminé et placez EOF à l'endroit supposé de l'erreur. Ensuite, compilez à nouveau votre programme. Si la compilation réussit jusqu'à EOF, c'est que l'erreur est plus loin. Si la compilation plante à nouveau le système, rééditez le fichier source et déplacez votre EOF vers le début du fichier. Après plusieurs essais, vous aurez localisé l'erreur.

 
GET --- c  

Lit un seul caractère dans le fichier courant. Equivaut à KEY si HANDLE (ticket courant) est nul c'est-à-dire quand l'interpréteur est justement branché sur le clavier. GET n'est pas utilisé par le système lui-même; son emploi permet la lecture séquentielle octet par octet de fichiers divers en utilisant l'organisation des tampons Forth.

 
(GETLINE) adr hndl --- f  

Primitive de GETLINE : lit une ligne de texte dans le fichier ouvert au ticket hndl. La ligne est placée dans un tampon à l'adresse adr sous forme de chaîne implicite, le premier octet étant affecté à la longueur effective de la ligne chargée. Le flag de retour est positionné à vrai si la lecture atteint la fin du fichier, si survient une erreur de lecture ou encore si le code de retour- chariot n'est pas rencontré une fois lue la limite des 255 caractères. Tous les caractères de contrôle lus sont remplacés par des espaces dans le tampon.

 
GETLINE ---  

Lit une ligne de texte dans le fichier courant. La ligne est placée dans le tampon de ligne du fichier courant et éventuellement affichée si la variable ECHO est ON. Le compteur de ligne du tampon est incrémenté et la variable EOF? mise ON si la fin du fichier est atteinte.

GETLINE réalise chaque opération élémentaire de lecture d'un fichier lors de son interprétation par INCLUDE.

Voici un exemple relativement simple de l'utilisation conjointe des mots OPEN HANDLE GETLINE .LINE et CLOSE pour définir un mot VIEW listant un fichier à partir de la rencontre d'un mot quelconque. La syntaxe en est:

VIEW <fichier> <mot> 

et comme la première occurence d'un mot Forth dans un fichier est généralement sa définition (hors commentaires), on utilisera VIEW pour retrouver le source d'un mot puis voir son utilisation dans le reste du fichier. La commande VIEW <fichier> seule est équivalente à LIST <fichier>:

: VIEW ( <fichier[.ext]><mot> -- )
 ECHO @ \ conserve l'état courant de ECHO
 HANDLE @ \ conserve le HANDLE courant
 ECHO OFF \ pas d' ECHO pour commencer
 OPEN \ ouvre le fichier
 BL WORD DROP \ isole le mot à chercher du flot actuel
 HANDLE ! \ attribue le ticket courant au fichier
 BEGIN \ commence à lire le fichier:
  GETLINE \ prend une ligne
  ECHO @ 0= \ ECHO est encore OFF ?
  IF HERE COUNT \ si oui: chaîne du mot à chercher
   BUFFER COUNT \ chaîne chargéedans le tampon 
   SEARCH \ recherche le mot dans le tampon
   NIP \ la positiondu mot est inutile 
   IF .LINE \ si trouvé: affiche la ligne 
    ECHO ON \ et oncontinue en ECHO ON
   THEN \ si pas trouvé: on continue comme ça
  THEN \ si non: on continue sans chercher le mot
  EOF? @ STOP? OR \ jusqu'à fin de fichier ou stop au clavier
 UNTIL \ c'est fini:
 CLOSE \ on ferme le fichier
 HANDLE ! \ on rétablit le HANDLE ECHO ! ; \ on rétablit ECHO 

Notez dans cette définition de VIEW la façon habituelle de gérer HANDLE: il faut d'abord en conserver la valeur courante, ici sur la pile, avant de le diriger sur le fichier ouvert par OPEN et ne pas oublier de le restituer après la fermeture de ce fichier. On aura pris garde à diriger HANDLE qu'après l'utilisation du flot d'interprétation en cours: ici la séquence BL WORD qui interprète encore un mot après le nom du fichier doit précéder la séquence HANDLE ! sinon ce mot serait pris dans le tampon nouvellement ouvert...

 
INCLUDE <fichier[.ext]>--- imm.  

Interprète un fichier source. Le mot qui suit INCLUDE est interprété comme un nom de fichier: celui-ci peut contenir le nom d'un lecteur et un chemin d'accès de répertoire; l'extension du nom de fichier est facultative quand il s'agit de l'extension par défaut (voir EXT$). Le fichier ainsi défini est ouvert puis immédiatement interprété ligne par ligne: les instructions sont exécutées et les nouvelles définitions compilées selon le concept habituel au langage de la dualité interprétation-compilation. En fin de fichier -qu'elle soit naturelle ou provoquée par le mot EOF- le fichier interprété est fermé et l'interpréteur rendu à la source appelante. Le texte interprété par INCLUDE est affiché ligne par ligne pour un traçage visuel de contrôle si la variable ECHO est ON. Si une erreur survient dans le texte, celle-ci est localisée dans le fichier, l'appel à un éditeur externe est préparé pour une correction immédiate au site de l'erreur, l'ensemble du processus d'interprétation est arrêt, et tous les fichiers refermés.

INCLUDE B:\FORTH\CALCUL\COMPLEX.FTH
INCLUDE TIMER 

Ce mot est le plus important du concept de mémoire virtuelle interprétée tel qu'il est conçu dans Turbo-Forth. Par rapport au concept de blocs qui utilisait une syntaxe de type n°-de-bloc LOAD (éventuellement à l'intérieur d'un seul fichier global ouvert par un mot OPEN) INCLUDE apporte au principe de la gestion des programmes sources deux innovations fondamentales au langage Forth:

La propriété fondamentale de INCLUDE est en effet la ré-entrance: un fichier interprété par INCLUDE peut lui-même comporter une ou plusieurs commandes INCLUDE d'interprétation d'autres fichiers. L'interpréteur est alors dérouté dans un autre fichier avant de revenir automatiquement dans le fichier appelant immédiatement après la commande INCLUDE , ceci sans autre commande de retour que la fin de fichier ou l'exécution de EOF.

INCLUDE MAIN
fichier main.fth  : [prog] ( séquence de programme)
           INCLUDE MODUL1
           [fin_prog]

fichier modul1.fth : [sub1]
           INCLUDE MODUL2
           [fin_sub1]

fichier modul2.fth : [sub2]

La commande INCLUDE MAIN va interpréter (et/ou compiler) les séquences de programmes: [prog] [sub1] [sub2] [fin_sub1] [fin_prog] dans cet ordre avant de rendre la main à l'utilisateur.

La ré-entrance de INCLUDE admet deux limites dans l'imbrication des programmes les uns dans les autres qu'il convient parfois de se rappeler:

  1. Une limite liée à la pile de retour: chaque appel de INCLUDE empile deux cellules 16 bits sur la pile de retour (ce sont les valeurs courantes de HANDLE et >IN qui pointent sur la source appelante) pour permettre un retour exact de l'interpréteur après le INCLUDE. Pour une pile de retour théorique de 256 octets, on calcule ainsi un maximum de 64 niveaux d'imbrication de fichiers ce qui est largement supérieur aux capacités intellectuelles d'un programmeur et hors de proportion avec l'usage (excepté peut-être le cas très particulier et complexe d'un appel récursif d'un même fichier).
  2. Une limite plus sérieuse toutefois qui est celle du nombre de fichiers pouvant être ouverts simultanément. Cette limite est propre à la fois à MS-DOS et à Turbo-Forth: elle est très basse par défaut puisqu'une variable FILES à 8 n'autorise l'ouverture que de 4 fichiers soit 4 niveaux d'imbrication pour INCLUDE. Voir le mot FILES au début de ce chapitre pour apprendre comment étendre le nombre de fichiers utilisables. Ceci dit le programmeur Forth apprendra qu'il est bien rare d'atteindre le niveau 4 d'imbrication...

Nous venons de parler des limites d'imbrication des INCLUDE. Il n'est peut-être pas inutile de préciser qu'il ne faut pas y voir une limite aux appels successifs du mot INCLUDE. Imaginons en effet un fichier PROG.FTH contenant un grand nombre d'appels du type:

INCLUDE SUB1
INCLUDE SUB2
...
INCLUDE SUBx 

Si nous supposons que les fichiers SUBx.FTH ne réalisent pas eux- mêmes d'opérations INCLUDE, il faut comprendre que la commande INCLUDE PROG n'utilisera jamais l'ouverture que de deux fichiers simultanément et n'a guère besoin que de 4 octets sur la pile de retour: chaque ticket ouvert pour un fichier SUBx sera refermé avant d'être réutilisé pour le suivant. L'imbrication n'est qu'un aspect particulier de la ré-entrance. Le mot INCLUDE peut être obtenu au clavier en frappant la touche de fonction F3.


LIST <fichier[.ext]>---  

Liste un fichier texte ASCII sur le ou les périphériques de sortie (écran et/ou imprimante selon le vecteur EMIT). Cette commande est utilisée pour connaître ou vérifier le contenu d'un fichier que ce soit un fichier source Forth ou tout autre fichier texte.

Le mot qui suit LIST est interprété comme un nom de fichier: il peut comporter un nom de lecteur et un chemin d'accès de répertoire; l'extension du nom de fichier est facultative s'il s'agit de l'extension par défaut. Le listage est suspendu par l'appui d'une touche puis repris par une autre frappe ou interrompu par la touche retour (contient le mot STOP?).

LIST A:AUTOEXEC.BAT
LIST C:\FORTH\LISEZ.MOI
LIST CLOCK  (pour CLOCK.FTH) 
 

E. ALLOCATION MEMOIRE.

1. Segments et paragraphes utilisés par Turbo-Forth.

DSEGMENT --- u  

Délivre sur 16 bits l'adresse segment de Turbo-Forth. Cette adresse est la valeur courante du registre de segment DS (Data-Segment) du micro-processeur.

Les microprocesseurs de la famille 8086 peuvent en effet adresser un méga-octet de mémoire. Toute adresse physique est définie par une adresse 16 bits de segment et une adresse 16 bits d'offset dans ce segment. Un segment débute toujours à une adresse multiple de 16 (on parle de paragraphe pour un bloc de 16 octets) et permet d'adresser une zone d'au plus 64 kilo-octets (correspondant à l'adressage 16 bits d'un offset). On notera qu'une même adresse physique peut être exprimée sous plusieurs couples segment-offset équivalents dans la mesure où les segments de 64K se chevauchent tous les 16 octets.

Pour simplifier l'adressage, le microprocesseur manipule des adresses 16 bits d'offsets en prenant pour base de segments les valeurs inscrites dans quatre registres de segments:

Lorsque Turbo-Forth est lancé par le système, son code est chargé dans le premier segment libre. Celui-ci varie selon les programmes déjà chargés, les drivers installés, les allocations résidentes (un disque virtuel ou un programme résident par exemple) qui occupent la mémoire basse du système. C'est ce segment que donne DSEGMENT car pour Turbo-Forth les registres CS DS et SS doivent être tenues aux mêmes valeurs (l'usage du segment ES est libre).

Toute la mémoire disponible à partir de DSEGMENT est allouée à Turbo-Forth lors de son lancement par MS-DOS. En fait, le programme n'a besoin que des 64K octets de DSEGMENT pour son propre usage: le dictionnaire, les piles, les tampons sont tous contenus dans ces 64K (voir la carte mémoire en annexe). Ceci n'empêche pas Turbo- Forth d'avoir accès à toute la mémoire par l'usage d'opérateurs extra-segments (voir des mots tels que L@ L! LCMOVE etc où le préfixe 'L' rappelle un adressage 'Long' 32 bits segment+offset).

Dans DSEGMENT les 256 premiers octets sont construits par MS-DOS: ils constituent le PSP (Préfixe du Segment de Programme) qui contient des informations pour le système. Après le PSP est chargé le code contenu dans le fichier TURBO.COM constituant le programme proprement dit (le dictionnaire). Ils peut être utile de connaître ce que contient le PSP dont toutes les adresses, par définition intra-segment, sont aisément accessibles par le langage:
Offset dans PSP
Contenu
00-01
instruction INT 20h de retour à l'appelant (COMMAND.COM en général)
02-03
dernière adresse segment allouable
06-07
nombre d'octets valides dans le segment
10-13
adresse offset-segment de retour à l'appelant
14-17
adresse offset-segment de branchement Break
18-21
adresse offset-segment d'erreur fatale (saut à l'habituel "Abort,Retry,Ignore")
24-43
Table des 20 tickets (handles) utilisables
44-45
Adresse segment environnement (zone contenant les variables de MS-DOS)
80-81
Instruction INT 21h d'appel de fonctions
92-107
premier bloc de contrôle fichier (FCB)
108-123
deuxième FCB (Turbo-Forth préfère utiliser les tickets)
128-255
chaîne implicite passée en paramètres d'appel et zone DMA (voir ce mot) par défaut. (les autres adresses du PSP sont réservées à MS-DOS)

Ainsi:

2 @ ( dernier segment ) DSEGMENT ( premier segment ) - U.

affiche en paragraphes de 16 octets la mémoire disponible pour Turbo-Forth.

 
SEGMENT> --- adr  

Variable destinée à contenir une adresse d'extra-segment. Sa valeur est initialisée à DSEGMENT. Est utilisée par les utilitaires LDUMP et DUMP de vidage mémoire.

 
BYE [o] ---  

Quitte Turbo-Forth en exécutant un retour au programme appelant: c'est le processeur de commandes COMMAND.COM le plus souvent avec soit affichage du 'prompt' (type 'A:\>') ou poursuite de l'interprétation d'un fichier BATch de commandes.

Toute la mémoire allouée à Turbo-Forth est restituée au système: il s'agit d'un retour simple par opposition à un retour laissant tout ou partie du programme résident (voir programmation avancée). Les tampons sont vidés et les fichiers laissés ouverts refermés.

BYE admet sur la pile un paramètre facultatif: il s'agit d'un octet servant de code de retour transmis au programme appelant. Pour COMMAND.COM cet octet est récupéré dans ERRORLEVEL qui peut être testé dans un fichier batch. Exemple:

: MENU ( ---)
 CR ." 1..EXECUTION WORDSTAR"
 CR ." 2..EXECUTION MULTIPLAN"
 CR ." 3..EXECUTION TURBO-FORTH"
 CR CR ." Votre choix:"
  BEGIN 
   ASCII 1 = IF 1 BYE THEN 
   ASCII 2 = IF 2 BYE THEN
   ASCII 3 = IF 3 BYE THEN
  AGAIN ;

Ensuite, après compilation, taper ' MENU IS BOOT SAVE-SYSTEM MENU et complétez le fichier AUTOEXEC.BAT de votre DOS avec le court programme suivant, valable pour un système équipé d'un disque dur:

...partie initialisation de AUTOEXEC.BAT...
:debut
MENU 
IF ERRORLEVEL=3 GOTO choix3 
IF ERRORLEVEL=2 GOTO choix2
IF ERRORLEVEL=1 GOTO choix1 
:choix1 
C:\WS\WS2000 
GOTO debut
:choix2
C:\MP\MP3
GOTO debut
:choix3
C:\TF83\TURBO.COM
GOTO debut 

Et maintenant, au démarrage de votre DOS, un petit menu permettra d'accéder directement aux différents programmes utilitaires de votre système.


BYE? ---  

Quitte Turbo-Forth (voir BYE) après avoir demandé à l'utilisateur confirmation par l'appui d'une touche. BYE? est obtenu en exécution directe par l'appui de la touche de fonction F8.

HEIGHT --- 4096

Constante délivrant une taille en paragraphes (blocs de 16 bits) que le système doit allouer à Turbo-Forth. La valeur 4096 paragraphes équivaut à 64K octets qui est la taille minimale que peut s'allouer Turbo-Forth puisque toutes ses composantes (dictionnaire,piles,tampons) sont dans le même segment DSEGMENT.

HEIGHT précède ALLOC (voir ce mot) chaque fois que Turbo-Forth a besoin de réduire sa propre allocation (toujours maximale au lancement) pour d'autres programmes: voir les commandes d'intégration.

Si une application nécessite à la fois un espace extra-segment de travail et la possibilité de libérer de la place pour d'autres programmes, on modifiera HEIGHT comme une pseudo-constante. Pour réserver 128K à Turbo-Forth dont 64K extra-segments on écrira par exemple:

HEIGHT 2* IS HEIGHT 
ALLOC n --- seg  

Modifie la taille mémoire allouée à Turbo-Forth: n est le nombre de paragraphes (blocs de 16 octets) qui doivent être alloués; ce nombre ne doit pas être inférieur à 4096 (valeur courante de HEIGHT pour 64K octets alloués).

Au retour, ALLOC laisse sur la pile l'adresse segment du dernier bloc alloué (c'est normalement DSEGMENT) pour permettre éventuellement de calculer la mémoire restant libre (en cas d'impossibilité d'allocation par MS-DOS la valeur empilée est celle d'un code d'erreur d'un octet égal à 7, 8, ou 9).


2. Sauvegardes de zones mémoire sur disque.

LSAVE <fichier[.ext]>seg adr1 adr2 ---  

Sauve dans un fichier une zone mémoire extra-segment. Le nom du fichier est interprété avec le mot qui suit LSAVE: il peut comporter un nom de lecteur et un chemin d'accès de répertoire; l'extension du nom est facultative avec l'extension '.COM' prise par défaut. La zone mémoire à sauvegarder est comprise entre les adresses offset adr1 et adr2 dans le segment seg. Ce mot permet donc de sauvegarder un fichier binaire d'au plus 64K octets.

Avant de réaliser la sauvegarde LSAVE teste l'espace mémoire restant libre sur le lecteur destination et émet un message d'erreur sans faire de sauvegarde si la totalité de la zone ne peut y être logée.


SAVE <fichier[.ext]>adr1 adr2 ---  

Sauve dans un fichier une zone mémoire intra-segment. Le nom du fichier est interprété avec le mot qui suit SAVE: il peut comporter un nom de lecteur et un chemin d'accès de répertoire; l'extension du nom est facultative avec l'extension '.COM' prise par défaut. La zone mémoire à sauvegarder est comprise entre les adresses adr1 et adr2.

Avant de réaliser la sauvegarde SAVE teste l'espace mémoire restant libre sur le lecteur destination et émet un message d'erreur sans faire de sauvegarde si la totalité de la zone ne peut y être logée.

 
SAVE-SYSTEM <fichier[.COM]>--- F83

Sauve dans un fichier le dictionnaire Turbo-Forth actuel. Le nom du fichier est interprété avec le mot qui suit SAVE-SYSTEM: il peut comporter un nom de lecteur et un chemin d'accès de répertoire; l'extension du nom est facultative avec l'extension '.COM' prise par défaut.

Avant de réaliser la sauvegarde SAVE-SYSTEM teste l'espace mémoire restant libre sur le lecteur destination et émet un message d'erreur sans faire de sauvegarde si la totalité du dictionnaire ne peut y être logé.

La zone sauvegardée va de l'adresse 256 (début du programme après le PSP) jusqu'à l'adresse pointée par HERE (voir ce mot). Est ainsi placée dans un nouveau fichier une nouvelle version de Turbo-Forth:

INCLUDE FLOAT
SAVE-SYSTEM TFF 

TFF.COM est ici une nouvelle version de Turbo-Forth contenant les fonctions précompilées de calcul en virgule flottante. Ainsi l'utilisateur peut-il utiliser un langage Forth adapté à ses besoins sans avoir à compiler au préalable ses bibliothèques de programmes.

SAVE-SYSTEM sauvegarde toutes les variables en l'état, les mots éventuellement en cours de traçage (fonction DEBUG) et les vocabulaires sélectionnés. Exemple:

 TURBO HEX SAVE-SYSTEM TURBO.COM BYE

Charge TURBO-Forth, sélectionne la base numérique hexadécimale, sauvegarde TURBO en l'état et retourne sous MSDOS. Au prochain chargement de TURBO, vous serez d'office en base numérique hexadécimale. Cette faculté du langage à s'étendre lui-même fait partie de la philosophie fondamentale du Forth, au risque de rendre difficile la définition d'un standard.

SAVE-SYSTEM permet aussi de créer des modules d'applications compilées sous forme de fichiers .COM exécutables: une application est compilée dans le dictionnaire, l'exécution du programme est vectorisée sur la procédure de démarrage et l'ensemble sauvé dans un fichier de commande "fermé". Supposons que vous ayez écrit un superbe programme FLIGHT de simulateur de vol. Le simulateur est lancé par un mot SIMULATOR qui gère toutes les phases du jeu:

: SIMULATOR
 INITIALISE-PLAN-DE-VOL
 BEGIN PLANTE-LE-DECOR 
  ATTEND-UNE-COMMANDE
  DEPLACE-LE-ZINC
  ARRGH-CRASH?
 UNTIL BYE ;
(Un jeu diabolique qui ne s'arrête que lorsqu'on est mort !) 

Nous écrirons alors les quelques lignes suivantes:

INCLUDE FLIGHT.FTH 
' SIMULATOR IS BOOT 
SAVE-SYSTEM FLIGHT.COM 

Vous venez de créer un programme FLIGHT.COM de simulation de vol qui fera les délices du service marketing...

Notez comment, avant SAVE-SYSTEM, on a "fermé" l'application FLIGHT entre la revectorisation de BOOT (voir ce mot) et le BYE (voir ce mot) qui termine la définition de SIMULATOR.

Certaines techniques avancées permettent de compiler des applications très compactes, faisant abstraction des en-têtes des mots Forth et des bibliothèques inutilisées du langage.

SAVE-SYSTEM est obtenu en exécution au clavier par la touche F4.


F. COMMANDES D'INTEGRATION.

1. Principes et primitives d'intégration MS-DOS.

 
(PROGRAM) adr0 adr_params mode --- fl  

Primitive de chargement et d'exécution d'un autre programme. Cette fonction MS-DOS (notée souvent EXEC dans les manuels) est très puissante car elle permet à un programme "père" de commander l'exécution d'un programme "fils" quelconque avec retour au programme père dès la fin d'exécution du programme fils. On dit du programme père qu'il possède des fonctions d'intégration: il est capable de se comporter lui-même comme un système d'exploitation.

Cette primitive réclame trois arguments sur la pile:

Une table de paramètres doit être préalablement constituée à l'adresse passée en second argument. Elle présente un format de 14 octets pour le mode 0 qui doit respecter la signification suivante:
octets 0-1 adresse segment de l'environnement (variables MS-DOS). La valeur 0 attribue au programme fils le même bloc environnement que celui du programme père.
octets 2-3 adresse offset d'une chaîne implicite (1er octet pour sa longueur) passée comme ligne de commande au programme fils.
octets 4-5 adresse segment de la chaîne de commande.
octets 6-7 adresse offset du premier FCB (File Control Block)
octets 8-9 adresse segment du premier FCB
octets 10-11 adresse offset du second FCB
octets 12-13 adresse segment du second FCB

Pour le mode 3 (overlay), la table de paramètres est limitée à 4 octets:
octets 0-1 adresse segment de chargement de l'overlay
octets 2-3 facteur de relocation à savoir toujours 0 pour un fichier .COM ou l'adresse segment de départ d'un fichier .EXE qui doit être ajoutée aux adresses relogeables.

Pour le mode 0, il importe de préciser que le programme fils dispose toujours des tickets (voir HANDLE) du programme père. Ceci est particulièrement important quand le programme père a procédé à des redirections d'entrées-sorties.

Au retour de (PROGRAM) qui est aussi le retour du programme exécuté en mode 0, la pile contient le code de retour d'une éventuelle erreur MS-DOS. Ce flag peut être testé par ?DOS-ERR (voir ce mot).

(PROGRAM) ne peut être utilisé par un programme père .COM comme Turbo-Forth qui prend par défaut toute la mémoire disponible qu'après un ordre ALLOC (voir ce mot) libérant un espace suffisant pour le programme fils sous peine d'une erreur 'mémoire insuffisante'. Cet espace sera restitué en sortie du programme fils: l'allocation mémoire HEIGHT ALLOC peut être limitée à la première utilisation de (PROGRAM).

 
PARAM --- adr  

Adresse d'une table de paramètres de 14 octets pour l'exécution d'une commande d'intégration: voir sa signification au mot (PROGRAM). Cette table est initialisée avant chaque lancement par PROGRAM. Elle est réutilisable et peut être limitée aux 4 premiers octets pour un chargement d'overlay.

 
COMMAND$ --- adr long  

Variable-chaîne (voir le mot STRING) d'une longueur maximale de 32 octets destinée à contenir temporairement une chaîne de commande passée à un programme externe par l'intégrateur.

Rappelons que cette chaîne est celle que vous avez l'habitude de placer après un nom de fichier pour indiquer au programme ce qu'il doit faire dès son lancement. Sa syntaxe varie d'un programme à l'autre et peut contenir des séparateurs divers (espace,virgule,caractère '/' etc):
Programme
Chaîne de commande
PRINT
B:\TEST.FTH /P
EDIT
A:AUTOEXEC.BAT 100 0
TURBO
2 2 + . BYE

 
PARAM! ---  

Primitive du mot PROGRAM: initialise la table PARAM d'intégration avec l'environnement de Turbo-Forth, charge dans la zone PAD le contenu de la variable chaîne COMMAND$, place dans PARAM+2 l'adresse PAD comme étant la ligne de commande à passer au programme fils, initialise des FCB par défaut et vide la variable chaîne COMMAND$ pour qu'une prochaine commande PROGRAM n'ait par défaut aucune chaîne de commande.


2. Commandes utilisateur d'intégration.

 
PASS adr long ---  

Enregistre dans la variable chaîne COMMAND$ une chaîne de commande d'au plus 32 caractères qui doit être passée au programme fils lors de la prochaine commande PROGRAM.

Ce passage d'une ligne de commande est facultative avant PROGRAM. Par défaut PROGRAM lance un programme sans ligne de commande. Si un programme doit être lancé plusieurs fois, il convient de répéter la séquence PASS.

 " B:TEST.FTH /P" PASS PROGRAM A:PRINT.EXE 

ajoute B:TEST.FTH dans la file d'attente d'impression "spoolée".

PROGRAM ---  

Intègre l'exécution d'un programme externe. Le mot qui suit PROGRAM est interprété comme un nom de fichier; il peut comporter un nom de lecteur ou un chemin d'accès de répertoire, mais pas de caractère joker; l'extension du nom doit être précisée comme .COM ou .EXE.

Le programme est exécuté immédiatement avec éventuellement le passage d'une chaîne de commande si une instruction PASS a précédé PROGRAM. Le retour d'exécution du programme fils s'effectue dans Turbo-Forth juste après la commande PROGRAM <fichier>.

Le mot PROGRAM se charge de libérer le maximum de mémoire pour charger le programme fils (voir HEIGHT et ALLOC) et veille à tester l'occurence d'une erreur dans la demande de procédure d'intégration.

Le concept d'intégration qu'introduit PROGRAM ouvre des horizons nouveaux au langage Forth: le langage n'est plus un simple interpréteur ou un compilateur fermé sur lui-même mais un gestionnaire qui intègre tout le monde logiciel extérieur. Il est difficile de donner ici un aperçu de l'étendue du concept d'intégration.

Prenons l'exemple imaginaire d'un tableur - appelons-le MP.EXE -, d'un programme Forth capable de traiter les données d'un fichier *.MP pour établir des histogrammes quadri-dimensionnels (?) dans un fichier image H4D.PIC et d'un logiciel HSPLOT.COM seul capable d'imprimer un dessin sur une table traçante HISPANO-SUIZA V12 ...Turbo-Forth ne va avoir aucune peine à construire une application très personnalisée "intégrant" aussi bien le tableur mondialement utilisé que le plus exotique des traceurs graphiques:

PROGRAM C:\MP\MP.EXE
" B:H4D.PIC /H /T=2000"
PASS PROGRAM A:HSPLOT.COM 

PROGRAM, nous l'avons vu est une commande (mode exécution) qui interprète un nom de fichier. Il est aisé en Turbo-Forth de compiler une commande interprétée: si notre application doit intégrer le tableur MP.EXE à l'intérieur de définitions compilées, nous définirons un mot MP compilable qui intégrera le tableur:

 : MP ( -- ) " PROGRAM C:\MP\MP.EXE" $EXECUTE ;

Une séquence " commande-chaîne" PASS peut être aussi compilée avant la séquence " PROGRAM XXX" $EXECUTE si le programme doit être lancé avec une chaîne de commande.

: FORMAT ( <lecteur:> -- )
BL WORD COUNT PASS
" PROGRAM C:\DOS\FORMAT.EXE" $EXECUTE ;

FORMAT A:/S formate et initialise une disquette dans A:

Une utilisation particulière de PROGRAM consiste à intégrer un second (et de là un troisième etc...) module TURBO-FORTH piloté par le premier ou dédié à une tâche spéciale:

" INCLUDE ESSAI" PASS PROGRAM TURBO

Le programme ESSAI.FTH est testé dans un deuxième Turbo-Forth puis on retournera dans le premier Turbo-Forth non modifié par une commande BYE.

Enfin l'intégrateur PROGRAM est utilisé pour lancer un éditeur externe de fichiers textes laissé au libre choix de l'utilisateur. Ainsi, TURBO-Forth s'affranchit d'un environnement tendant à évoluer vers la performance.

SHELL adr long ---  

Intègre une commande du processeur de commandes MS-DOS COMMAND.COM. La chaîne explicite (adr,long) placée sur la pile est une ligne de commande (30 caractères compte tenu du /C inséré en tête par SHELL) exprimant une commande MS-DOS: commande interne (comme DIR,COPY etc), commande externe (comme PRINT,DISKCOPY etc), lancement d'un programme .EXE ou .COM, lancement d'un fichier lot de commandes .BAT...

Le fichier COMMAND.COM est chargé et lancé avec l'exécution de cette commande. Le retour est immédiat dans Turbo-Forth après l'exécution de la commande. Dans certains cas, le retour au Forth depuis MS-DOS se fera avec la commande EXIT.

Le fichier COMMAND.COM est chargé depuis le répertoire courant: il convient de s'assurer de sa présence ou modifier le chemin du répertoire courant avec la commande CHDIR. L'espace occupé par COMMAND.COM et les programmes qu'il peut lui-même intégrer est restitué au retour de SHELL.

" DIR | SORT > CATALOG " SHELL
crée un fichier texte CATALOG. contenant le directory trié.

" COPY B:TEST.FTH A:" SHELL
copie le fichier TEST.FTH de B: en A:

" MENU" SHELL

lance le programme MENU.EXE ou MENU.COM ou encore la procédure MENU.BAT

Une commande SHELL peut être compilée telle quelle:

: TIME ( -- ) CR " TIME" SHELL ;

TIME affiche l'heure et propose sa modification.

Nous vous renvoyons à votre manuel pratique MS-DOS pour connaître toutes les commandes auxquelles SHELL donne accès; certaines sont fort méconnues des utilisateurs même chevronnés! Pour ce qui est du lancement de programmes externes, il est plus économique en mémoire et en temps de chargement d'utiliser PROGRAM qui se passe du chargement intermédiaire de COMMAND.COM.


3. Lancement d'un éditeur externe.

EDIT$ --- adr long  

Variable chaîne (voir le mot STRING) d'une longueur maximale de 12 caractères destinée à conserver le nom du fichier de l'éditeur externe. Cette variable chaîne est initialement vide: dans ce cas EDIT lance par défaut le fichier EDIT.COM du répertoire courant. Une façon d'utiliser un éditeur quelconque consiste à le renommer EDIT.COM (à condition qu'il s'agisse d'un fichier .COM).


PROGRAM$ --- adr long  

Variable chaîne (voir le mot STRING) d'une longueur maximale de 32 utilisée par EDIT pour lancer l'éditeur externe.


IN-FILE --- adr long  

Variable chaîne (voir le mot STRING) d'une longueur maximale de 20 caractères destinée à conserver le nom d'un fichier source dans lequel est survenu une erreur d'interprétation.


IN-LINE --- adr  

Variable pointant le numéro de la ligne d'un fichier source dans laquelle est survenu une erreur d'interprétation.


IN-CHAR --- adr  

Variable pointant la position atteinte par l'interpréteur dans une ligne d'un fichier source victime d'une erreur d'interprétation.


EDIT ---  

Commande de lancement de l'éditeur externe. Pour l'histoire, les concepteurs de TURBO-Forth ont d'abord été partagés entre la création d'un éditeur de programme intégré à FORTH et un éditeur externe. La première solution nécessitait la création d'un éditeur écrit en FORTH, donc de passer un certain temps à concevoir et écrire cet éditeur. Finalement, c'est l'option éditeur externe qui l'emporta. Outre le gain de place mémoire, il offrait l'avantage d'être déjà écrit (en TURBO-Pascal pour les curieux), donc de faire gagner du temps aux concepteurs. Mais également, le choix d'un éditeur externe ne contraint pas l'utilisateur à apprendre de nouvelles commandes d'édition s'il est habitué à travailler avec un autre produit. Il suffit de changer le contenu de la variable alphanumérique EDIT$ avec le nom du nouvel éditeur s'il ne s'appelle pas EDIT.COM.

L'intégration d'un programme externe d'édition de fichiers textes au format standard permet au programmeur Turbo-Forth d'écrire ses programmes sources et de les modifier selon ses habitudes. Il existe en effet de très nombreux programmes d'édition depuis le rustique EDLIN de MS-DOS jusqu'aux traitements de textes les plus sophistiqués qui la plupart admettent l'édition (ou la conversion) de fichiers textes ASCII.

EDIT répond à deux procédures de lancement d'un éditeur selon les circonstances de son emploi:

Pour bénéficier pleinement de la faculté de reprendre un fichier source au site-même d'une erreur, il est supposé que l'éditeur externe accepte une ligne de commande à trois paramètres séparés par des espaces de la forme:

EDIT <nom-du-fichier> <ligne> <colonne>

Où <nom-du-fichier> est le chemin\nom d'un fichier à éditer et <ligne> <colonne> la position du curseur dans le texte à fixer dès le lancement.

Si votre éditeur n'accepte pas plus d'un paramètre (celui du fichier à éditer), il faudra retrouver l'erreur en vous aidant du message de localisation délivré par l'interpréteur. Si votre éditeur accepte de se positionner au lancement sur une ligne, ou mieux sur une ligne et une colonne, selon une syntaxe différenteé il est préférable de redéfinir le mot EDIT de façon appropriée en construisant dans la variable chaîne COMMAND$ la chaîne de paramètres pour votre éditeur (après une erreur le mot (WHERE) charge dans COMMAND$ le nom du fichier incriminé):

: EDIT ( -- )
DECIMAL COMMAND$ NIP
IF " /L="        COMMAND$ APPEND$
  IN-LINE @ (.)  COMMAND$ APPEND$
  " /C="         COMMAND$ APPEND$
  IN-CHAR @ (.)  COMMAND$ APPEND$
ELSE CR ." Fichier à éditer:"
  COMMAND$ INPUT$
THEN " PROGRAM EDT.EXE" $EXECUTE ;

EDIT est ici redéfini pour un éditeur externe EDT.EXE acceptant une syntaxe de lancement: EDT [fichier][/L=xxx][/C=yyy] avec xxx et yyy pour la ligne et la colonne du curseur où débuter l'édition.

La commande EDIT (même redéfinie) est obtenue au clavier par la touche F2.


NEW-EDITOR ---  

Change l'éditeur externe chargé par EDIT. Ce mot demande à l'utilisateur le nom du fichier (préciser l'extension .COM ou .EXE) qui doit être intégré comme éditeur. Ce nom de fichier est conservé dans la variable chaîne EDIT$. Il n'y a pas lieu de modifier EDIT si cet éditeur accepte une syntaxe <fichier-à-éditer><ligne> <colonne>. NEW-EDITOR est obtenu au clavier par la touche Shift-F6.

 

 

-- hautdepage -- page d'accueil --