home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 25
/
CD_ASCQ_25_1095.iso
/
dos
/
prg
/
emsutil
/
ems.txt
< prev
next >
Wrap
Text File
|
1995-08-29
|
30KB
|
809 lines
█▀▀▀▀ █▀▄ ▄▀█ ▄▀▀▀▀ █ █ ▀▀█▀▀ █ █ █ ▀▀█▀▀ █ █▀▀▀▀ ▄▀▀▀▀
█▄▄▄ █ ▀ █ ▀▄▄▄ █ █ █ █ █ █ █ █ █▄▄▄ ▀▄▄▄
█ █ █ █ █ █ █ █ █ █ █ █ █ █
▀▀▀▀▀ ▀ ▀ ▀▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀▀▀ ▀ ▀ ▀ ▀▀▀▀▀ ▀▀▀▀
──────────────────────────────────────────────────────────────────────────
──────────────────────────────────────────────────────────────────────
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█
█▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓█
█▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓█
█▓▒░ ░▒▓█
█▓▒░ EMS UTILITIES V1.00 ░▒▓█
█▓▒░ ░▒▓█
█▓▒░ Aupetit Sébastien - Septembre 1995(c) ░▒▓█
█▓▒░ ░▒▓█
█▓▒░ Version Shareware : enregistrez-vous ! ░▒▓█
█▓▒░ ────────────────────────────────────── ░▒▓█
█▓▒░ ░▒▓█
█▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓█
█▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓█
█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
Chapitre 1 : Qu'est-ce que EMS UTILITIES ?
Chapitre 2 : A savoir.
Chapitre 3 : Quelques notions sur l'EMS pour comprendre la nécessité de EMS
UTILITIES.
Chapitre 4 : Description des unités.
Chapitre 5 : Précautions et conseils lors de la programmation.
Chapitre 6 : Enregistrez-vous !
┌──────────────────────────────────────┐
│ CHAPITRE 1 : Qu'est-ce EMS UTILITIES │
└──────────────────────────────────────┘
EMS UTILITIES est un coffret regroupant des fonctions pour gérer l'EMS
(Expanded Memory Specification ) dans vos programmes de façon similaire aux
instructions Turbo Pascal.
Aux instructions Turbo Pascal : GetMem, FreeMem correspondent les instructions
EMS UTILITIES Ems_GetMem, Ems_FreeMem.
Toutefois leurs utilisations doivent être combinées à Ems_Acces pour accèder à
une zone mémoire. ( voir plus loin )
L'un des avantages de EMS UTILITIES est que ses procédures et fonctions
peuvent être exploitées même sans pilote EMS et carte EMS. EMS UTILITIES a la
possibilité de pouvoir simuler de la mémoire EMS sur disque sans que le
programme n'en voit la différence. Ainsi un programme exploitant la mémoire
EMS pourra être utilisé même sur un système n'ayant pas de mémoire EMS.
┌────────────────────────┐
│ CHAPITRE 2 : A savoir. │
└────────────────────────┘
Ce coffret n'est pas gratuit. Pour toutes utilisations au delà d'un délai de
30 jours suivant la première utilisation, vous avez l'obligation morale de
vous enregistrez. Pour cela veuillez vous référer au chapitre : Enregistrez
- vous !
Il est aussi à noter que je décline toutes responsabilités quant aux domages
que pouraient provoquer EMS UTILITIES.
Je vous serais gré de m'envoyer un courrier si un bogue se révèlait dans
l'utilisation de ce coffret. Pour cela, écrivez sur un papier la cause et la
ligne de l'unité EMS UTILITIES où le bogue est apparu. Essayez d'expliquer le
plus clairement possible ce qui a provoque l'erreur.
┌─────────────────────────────────────────────────────────────────────────┐
│ Chapitre 3 : Quelques notions sur l'EMS pour comprendre la nécessité de │
│ EMS UTILITIES │
└─────────────────────────────────────────────────────────────────────────┘
Avant d'aborder la description des unités de EMS UTILITIES, il vous faut
connaître certaines bases sur la programmation de l'EMS.
En mode réel, un ordinateur ne peut adresser la mémoire que sur 1Mo de large.
Cela parait suffisant, il faut savoir que l'espace effectivement libre pour un
programme n'est que de 640 ko. Ces 640ko sont encore réduit par DOS et les
drivers pour obtenir en moyenne 512 ko. De plus, la taille du code d'un
programme en mémoire est généralement de 200 à 400 ko, l'espace libre reste
souvant limitant pour un programme. Une solution serait de pouvoir accéder à
plus de mémoire or l'architecture du microprocesseur ne le permet pas.
L'EMS offre à cette limite une solution qui consiste à adresser une autre
mémoire à travers une "fenêtre accéssible". Le programme accède à la portion
de mémoire EMS ( Fenêtre EMS ) à travers une zone mémoire adressable nommer
Page Frame ( Fenêtre accéssible ).
Le shéma suivant vous aidera à comprendre :
Mémoire adressable Mémoire EMS adressable à
travers le Page Frame
^
│ ┌──────────────────────┐ 1 Mo ┌──────────────────────┐
│ │ │ │ │
A ├──────────────────────┤───────┐ │ │
d │ "Fenêtre accéssible" │ └───────├──────────────────────┤
r ├──────────────────────┤───────┐ │ "Fenêtre EMS" │
e │ │ └───────├──────────────────────┤
s │ │ │ │
s │ │ │ │
e │ │ │ Mémoire EMS │
s ├──────────────────────┤ 640 ko │ │
│ │ │ │
c │ │ │ │
r │ │ │ │
o │ │ │ │
i │ │ │ │
s │ │ │ │
s │ │ │ │
a │ │ │ │
t │ │ │ │
e │ │ │ │
s │ │ │ │
│ │ │ │ │
│ └──────────────────────┘ 0 ko └──────────────────────┘
Généralement l'adresse du Page Frame est logée au dessus des premiers 640 ko
pour laisser un maximum d'espace libre aux programmes.
Tout accès dans la zone de la fenêtre s'effectue en fait dans la mémoire EMS.
Ce mode d'exploitation pose plusieurs problèmes :
- Le programme doit se charger de modifier la fenêtre pour accèder à la
zone voulue en mémoire EMS car on ne peut accèder à toute la mémoire EMS en
même temps.
- Ni DOS ni Turbo Pascal se charge de l'allocation et de la répartition
de le mémoire libre et de sa gestion dans l' EMS.
EMS UTILITIES offre une solution à ces différents problèmes.
De plus, EMS UTILITIES prévoit le cas où la mémoire EMS n'est pas présente. Ce
coffret permet en effet le cas échéant de simuler de la mémoire EMS ainsi
votre programme n'a pas à prévoir deux gestions de mémoire, tout est
fait de façon transparante.
┌───────────────────────────────────────┐
│ CHAPITRE 4 : Description des unités. │
└───────────────────────────────────────┘
**** SOMMAIRE ****
L'unité Ems_Var.
Les unités EmsDisk et EmsEms.
L'unité Ems.
L'unité EmsLib.
L'unité EmsStr.
NB : Un handle EMS est un handle fourni par l'EMM ( Expanded Memory Manager).
Il est a diférencier des handles EMS UTILITIES qui sont en fait un index dans
un tableau de Handle EMS.
┌──────────────────┐
│ L'unité Ems_Var │
└──────────────────┘
Cette unités regroupe un ensemble de variables et de constantes utilisées par
plusieurs unités de EMS UTILITIES.
I) La gestion des erreurs
─────────────────────────
Cette unité contient la variable EmsErrorProc destinée a recevoir un pointeur
sur une routine d'erreur EMS.
La variable EmsErrorProc est déclarée de la façon suivante :
Const EmsErrorProc : TEmsErrorProc = Ems_DefaultErrorproc;
│ │
┌───────────────┘ └──────────────┐
│ │
Type TEmsErrorProc = Procedure; Ems_DefaultErrorProc est la routine de
traitement d'erreur EMS par défaut.
Vous pouvez définir votre propre routine de traitement des erreurs en
définissant une procédure à accès Far.
Cette routine pourra choisir d'ignorer certaines erreurs et d'autres non. La
routine par défaut déclenche une sortie immédiate du programme.
Toute routine de gestion des erreurs EMS doit consulter la variable
EmsErrorCode ( de type WORD ).
A cette fin, l'unité Ems_Var définie une série de constantes dont voici la
description :
EmsError_Ok = $00;
{ Aucune erreur }
EmsError_NotInitialized = $01;
{ Les fonctions de l'EMS n'ont pas été initialisées }
EmsError_NotEnoughMemory = $02;
{ Mémoire disponible insuffisante }
EmsError_CreateFile = $03;
{ Création du fichier d'échange impossible }
EmsError_CloseFile = $04;
{ Erreur lors de la fermeture du fichier d'échange EMS }
EmsError_EraseFile = $05;
{ Erreur lors de l'éffacement du fichier d'échange EMS }
EmsError_Release = $06;
{ Erreur lors de la libération d'une page }
EmsError_AllocTooLargeBlock = $07;
{ Tentative d'allocation d'un bloc de plus de }
{ MaxPageBlockSize + SizeOf(TEmsFreeRec) octets, voir plus loin }
EmsError_InternError = $80;
{ Erreur interne, Peut-être EMM détruit }
EmsError_ElectronicError = $81;
{ Défaut de fonctionnement de l'électronique EMS }
EmsError_OccupiedEMM = $82;
{ EMM occupé }
EmsError_BadHandle = $83;
{ Handle incorrect, cette erreur peut se produire si un pointeur non EMS
est transmit aux fonctions de EMS UTILITIES }
EmsError_BadFunction = $84;
{ Fonction appelée non reconnue }
EmsError_NoMoreHandleFree = $85;
{ Il n'y a plus de handles disponibles, cette erreur peut se produire dans
le cas où beaucoup trop de Handle ont été alloués }
EmsError_SaveRestoreMap = $86;
{ Erreur lors de la sauvegarde ou du renvoi de la concordance entre }
{ pages logiques et physiques }
EmsError_NotEnoughPhysicalPage = $87;
{ Le nb de pages physiques demandé est supérieur au nombre de pages }
{ disponibles }
EmsError_NotEnoughLogicPage = $88;
{ Le nb de pages logiques demandées est supérieur au nb actuellement }
{ disponible }
EmsError_TryToAllocZeroPage = $89;
{ Tentative d'allouer 0 Page }
EmsError_InvalidLogicPage = $8A;
{ Numéro de page logique non valable }
EmsError_InvalidPhysicalPage = $8B;
{ Numéro de page physique non valable }
NB : Si la routine des gestions des erreurs décide d'ignorer une erreur, elle
doit mettre la variable EmsErrorCode à EmsError_Ok.
NB : La routine d'erreur quitte le programme avec un code de sortie de $FFFF.
II) La gestion des procédures à appeler.
────────────────────────────────────────
Cette unité contient une variable nommée EmsProc servant à indiquer quelle
gestion EMS UTILITIES est en cours. ( EMS ou émulation )
Les valeurs valides pour cette variable sont :
Ems_EmsProc = 0; { Utilisation de l'EMM et de l'EMS }
Ems_DiskProc = 1; { Utilisation d'un fichier d'échange }
Par défaut cette variable est préfixée à Ems_EmsProc.
Avant l'appel de la procédure d'initialisation des fonctions d'EMS UTILITIES,
il est possible de modifier cette variable pour modifier le comportement de
ces fonctions. Cette variable ne doit JAMAIS être modifiée par la suite si
l'initialisation a réusie.
III) La taille maximale du bloc allouable
─────────────────────────────────────────
La taille maximale du bloc allouable par les fonctions d'EMS UTILITIES est
contenue dans la variable MaxPageBlockSize. Cette variable est modifiée par
les procédures d'initialisation. Cette variable ne doit JAMAIS être modifiée.
IV) Le segment du Page Frame
────────────────────────────
Le segment du Page Frame EMS est inscrit dans la variable Ems_FrameSeg. Cette
variable ne doit JAMAIS être modifiée.
V) Le nombre d'handle déjà alloué.
──────────────────────────────────
Le nombre de handle EMS dejà alloué est contenu dans la variable EmsHeapEnd.
Comme la taille d'un handle de EMS UTILITIES est préfixée à 64ko, pour obtenir
la taille de mémoire EMS utilisée par le programme il suffit de multiplier
cette variable par 64ko. Cette variable ne doit JAMAIS être modifiée.
VI) L'état des fonctions de EMS UTILITIES.
──────────────────────────────────────────
La variable EmsStatus de type BOOLEAN permet d'indiquer aux fonctions de EMS
UTILITIES si l'initialisation s'est déroulée ( correctement ).
VII) Le handle actuellement chargé en mémoire.
──────────────────────────────────────────────
La variable ActualEmsHandle indique quel est le handle EMS actuellement chargé
en mémoire.
VIII) La taille maximale de mémoire EMS utilisable par un programme.
────────────────────────────────────────────────────────────────────
Un programme peut par l'utilisation de EMS UTILITIES allouer au maximum de 16
Mo de mémoire EMS. Ce chiffre est réduit par la gestion à l'intérieur de
chaque handle mais ceci reste malgré tout négligeable.
IX) La taille maximale que pourrait avoir un bloc de mémoire EMS.
─────────────────────────────────────────────────────────────────
La taille de ce bloc est définie par le type TEmsMaxSize déclaré de la façon
suivante :
Const EmsMaxSize = 65536 - 4;
Type TEmsMaxSize = 0..EmsMaxSize;
┌───────────────────────────────┐
│ Les unités EmsDisk et EmsEms │
└───────────────────────────────┘
Ces deux unités étant utilisées en interne par EMS UTIlITIES nous n'en feront
qu'une brève description.
Ces deux unités sont rigoureusement symétriques et utilisent la même syntaxe
: toutes les fonctions de ces unités commencent par leurs noms.
L'unité EmsDisk est une interface pour l'émulation de mémoire EMS et EmsEms
fait la même chose mais avec l'EMM ( Expanded Memory Manager ) et l'EMS.
Cotation : XXXX représente le nom de l'unité.
Function XXXX_Init : Boolean; procède à l'initialisation des fonctions de
l'unité, elle retourne True si l'initialisation a réussie.
On peut notemment utiliser la fonction EmsEms_init pour savoir si une mémoire
EMS est présente mais il est plus judicieux d'utiliser la procédure
d'initialisation générale de l'unité Ems.
Function XXXX_Done : Boolean; effectue la tâche inverse de la précédente.
Function XXXX_GetFrameSeg( var FrameSeg : Word ) : Boolean; retourne dans
FrameSeg le segment du Page Frame et retourne True si l'opération a réussie.
Function XXXX_GetHandleFree( var MaxHandle : Word ) : Boolean; retourne dans
MaxHandle le nombre de handle encore allouable, elle retourne aussi True s'il
reste au moins un handle de libre et si tout c'est déroulé normalement sans
erreur.
Function XXXX_AllocHandle( var Handle : Word ) : Boolean; alloue un handle EMS
de 64ko et retourne True si réussie.
Function XXXX_ReleaseHandle( var Handle : Word ) : Boolean; libère un handle
EMS et retourne True si pas d'erreur.
Functions XXXX_Maphandle( Handle : Word ) : Boolean; charge un handle EMS en
mémoire ( fixe la mapping ) et retourne True si réusi.
┌──────────────────┐
│ L'unité EmsUtil. │
└──────────────────┘
Pour réduire la complexité de la gestion utilisée par EMS UTILITIES, j'ai
décidé de me servir d'une unité spécialement destinée à se charger de
l'orientation des commandes soit vers l'unité EmsEms ou l'unité EmsDisk.
Cette unité adopte donc les même fonctions que les unités précédentes :
Function _Ems_Init : boolean;
Function _Ems_GetFrameSeg( var FrameSeg : Word ) : Boolean;
Function _Ems_GethandleFree( var MaxHandle : Word ) : Boolean;
Function _Ems_AllocHandle( var Handle : Word ) : Boolean;
Function _Ems_ReleaseHandle( var handle : Word ) : Boolean;
Function _Ems_MapHandle( Handle : Word ) : Boolean;
Function _Ems_Done : Boolean;
╔══════════════╗
║ L'unité Ems. ║
╚══════════════╝
L'unité Ems incarne en fait toute la gestion de EMS UTILITIES.
En premier lieu, il faut savoir que ces fonctions utilisent des pointeur EMS.
I) Qu'est-ce q'un pointeur EMS ?
────────────────────────────────
Un pointeur EMS a la particularité d'avoir la même taille que le type POINTER
mais il présente une structure. Il est déclaré de la façon suivante :
Type TEmsPointer = Record
Handle : Word; ───────> Handle est index dans une table d'Handle
EMS
Ptr : Word; ──────────> Ptr est une adresse d'offset dans le Handle
EMS UTILITIES
End;
Comme un pointeur EMS a la taille d'un POINTER, nous pouvons donc la
transtyper. ( Role de l'unité EmsLib );
II) Description des fonctions et de leurs utilisations.
───────────────────────────────────────────────────────
1) L'initialisation
───────────────────
Avant de pouvoir utiliser les fonctions de EMS UTILITIES, il faut procéder à
leur initialisation, on peut procèder de la façon suivante :
begin
If _EmsInit then
Begin
....
Corps du programme
....
End
Else
Begin
....
Message d'erreur
....
End;
End.
Si l'on procède à l'initialisation comme si dessus, EMS UTILITIES utilisera
les fonctions de l'EMM et de l'EMS. Or s'il n'y a pas de pilote EMS en
mémoire, un message d'erreur apparaîtra.
Une solution consiste a modifier la variable EmsProc en la méttant à
Ems_DiskProc. Mais là aussi ce n'est pas une solution, car si un pilote EMS
est présent, on ne l'utilisera pas. La solution consiste à appeler chaque
initialisation tour à tour de la façon suivante :
Begin
If Not(_EmsInit) then { Initialisation par defaut recherche de l'EMM }
{et de l'EMS }
Begin { non pas d'EMS et d'EMM }
{ on procède à l'initialisation de l'émulation }
EmsProc := Ems_DiskProc;
If Not(_EmsInit) then { Initialisation de l'émulation }
Begin { émulation impossible }
message d'erreur
End;
End;
...
Corps du programme
...
End.
Dès lors que la procédure d'initialisation a réussie, une procédure de sortie
critique est installée pour être sûr que toute la mémoire EMS alloué par le
programme soit effectivement libérée.
Pendant l'initialisation des fonctions de EMS UTILITIES, un bloc de mémoire de
1 ko, pour mémoriser la liste des Handles EMS alloués, est allouée dans le
tas. Veiller donc à laisser de l'espace mémoire pour la table des Handles EMS.
Au cours de l'initialisation des fonctions d'émulation, un bloc de 65528
octets ( plus grand bloc allouable avec GetMem ) est alloué dans le tas. Là
aussi dans la cas où l'espace mémoire serait insuffisant, EmsErrorCode
contiendrait la valeur EmsError_NotEnoughMemory et le programme se
terminerait.
2) Allouer de la mémoire
────────────────────────
On alloue de la mémoire EMS avec _EmsGetMem.
Function _EmsGetMem( var EmsPointer : TEmsPointer; Size : TEmsMaxSize ) :
Boolean;
Cette fonction retourne True si l'allocation a réussie.
EmsPointer pointe sur la zone allouée.
Size est la taille du bloc à allouer
NB : Size ne doit pas dépasser la taille de MaxPageBlockSize - 4 octets.
3) Libérer un bloc de mémoire EMS.
──────────────────────────────────
On libère un bloc de mémoire EMS avec _EmsFreeMem.
Function _EmsFreeMem( var EmsPointer : TEmsPointer; Size : TEmsMaxSize ) :
Boolean;
Cette fonction attend dans EmsPointer un pointer EMS alloué précédemment avec
_EmsGetMem, ainsi que la taille à libérer.
NB : LA TAILLE ALLOUEE DOIT ETRE IDENTIQUE A LA TAILLE LIBEREE.
4) Accèder à un bloc de mémoire EMS.
────────────────────────────────────
On accède à un bloc de mémoire EMS avec _EmsAcces.
Function _EmsAcces( EmsPointer : TEmsPointer ) : Pointer;
Cette fonction attend un pointer EMS préalablement allouée avec _EmsGetMem.
Elle amène la handle en mémoire s'il n'y est pas et retourne un pointeur sur
la zone.
REMARQUE : le segment du pointer est Ems_FrameSeg.
ATTENTION : Tout autre accès à la mémoire EMS, peut modifier le Handle
actuellement en mémoire. Le pointeur qui a été retourné devient donc invalide
car il pointe sur une zone erronée. ( voir la rubrique conseil lors de la
programmation )
5) Verifier la validitée d'un pointer EMS.
──────────────────────────────────────────
Il est possible de savoir si un pointeur EMS pointe effectivement sur une zone
en mémoire EMS grâce à la fonction _EmsAssigned dont l'emploi est identique à
l'instruction Turbo Pascal : Assigned.
Function _EmsAssigned( EmsPointer : TEmsPointer ) : Boolean;
Cette fonction attend dans EmsPointer un pointeur EMS et retourne True s'il
pointe sur une zone EMS.
┌──────────────────┐
│ L'unité EmsLib. │
└──────────────────┘
Cette unité permet d'utiliser les fonctions de EMS UTILITIES avec des
pointeurs.
Pour assurer la compatibilité entre les pointeurs EMS et les POINTERs, on
utilise un type de transtypage :
Type TPtrEms = Record
Case Boolean Of
True : ( EmsPtr : TEmsPointer );
False : ( Ptr : Pointer );
End;
Cette unité redéfinie cinq fonctions et procédures :
- L'initialisation :
Function Ems_Init : Boolean; identique à _EmsInit;
- Allouer de la mémoire EMS :
Function Ems_GetMem( Size : Word ) : Pointer; identique à _EmsGetMem
mais le résultat est
retourné par la
fonction.
- Libérer de la mémoire EMS :
Procedure Ems_FreeMem( var P : Pointer; Size : Word ); identique à
_EmsFreeMem mais
P a été retourné
par Ems_GetMem.
- Vérifier la validitée d'un pointeur sur de la mémoire EMS :
Function Ems_Assigned( P : Pointer ) : Boolean; identique a
_EmsAssigned
- Accèder à un bloc de mémoire EMS :
Function Ems_Acces( P : Pointer ) : Pointer; identique à _EmsAcces
┌──────────────────┐
│ L'unité EmsStr. │
└──────────────────┘
L'unité EmsStr est destinée plus particulièrement à être utilisée avec Turbo
Vision en remplacement des fonctions NewStr et DisposeStr.
- Allocation dynamique d'une chaine de caractères :
Function Ems_NewStr( S : String ) : Pointer;
- Libération d'une chaine de caractères allouée avec Ems_NewStr :
Procedure Ems_DisposeStr( Var P : Pointer );
- Accèder à la chaine :
Function Ems_AccesStr( P : Pointer ) : PString;
Voir le manuel de Turbo Vision.
┌────────────────────────────────────────────────────────────────┐
│ Chapitre 5 : Précautions et conseils lors de la programmation. │
└────────────────────────────────────────────────────────────────┘
Vue que l'on ne peut accèder à toute la mémoire EMS en même temps, certains
problèmes se posent lors de la création de listes chainées d'enregistrement.
Soit A un bloc de mémoire EMS. Ce bloc de mémoire étant structuré et Ptr étant
un pointeur sur le prochain bloc de mémoire EMS.
Si l'on alloue un bloc B, dont l'adresse est mise dans Ptr (A). il se peut que
l'allocation du bloc B ait modifié le Handle actuellement en mémoire, alors
l'adresse du Bloc A serait erronée en mémoire.
Par exemple : ( fichier LoadFile.PAS )
Type PLignePtr = ^TLignePtr;
TLignePtr = Record
Ligne : Pointer; ──────> mémorise un pointeur sur la chaine
dynamique
Next : Pointer; ───────> mémorise l'adresse du prochain TLignePtr
End;
Si l'on utilise cette méthode, alors les résultats sont inattendus :
Procedure LoadFile;
Var P : Pointer;
Ligne : String;
Begin
P := Ems_GetMem(SizeOf(TLignePtr));
RootLigne := P;
While Not(Eof(FichierText)) do
Begin
ReadLn(FichierText, Ligne);
PLignePtr(Ems_Acces(P))^.Ligne := Ems_NewStr(Ligne);
PLignePtr(Ems_Acces(P))^.Next := Ems_GetMem(SizeOf(TLignePtr));
P := PLignePtr(Ems_Acces(P))^.Next;
End;
End;
En effet Turbo Pascal commencera par évaluer PlignePtr(Ems_Acces(P)) ce qui
pourra charger le Handle 1 et Ems_NewStr(ligne) n'alloue pas la chaine dans
le Handle 1, Turbo Pascal se servira de l'adresse retournée par la fonction,
celle-ci n'étant plus valide car le Handle en mémoire n'est plus le même. Au
pire cela ne peut rien faire, mais cela peut aussi détruire des données et
provoquer un plantage.
Pour éviter tous ces désagréments, il convient de réserver une variable
TLignePtr dans la pile par Var, d'allouer la chaine et le bloc suivant par
rapport à cette variable puis d'accèder à la véritable variable en EMS et de
recopier la variable de la pile.
Procedure LoadFile;
Var P : Pointer;
Structure : TLignePtr;
Ligne : String;
Begin
P := Ems_GetMem(SizeOf(TLignePtr));
RootLigne := P;
While Not(Eof(FichierText)) do
Begin
ReadLn(FichierText, Ligne);
Structure.Ligne := Ems_NewStr(Ligne);
Structure.Next := Ems_GetMem(SizeOf(TLignePtr));
PLignePtr(Ems_Acces(P))^ := Structure;
P := Structure.Next;
Strcuture.Next := nil;
End;
End;
En règle générale, ne combinez JAMAIS deux instructions se référant à l'EMS
sur des cotés opposés de la même ligne ( de part et d'autre du := ).
L'instruction suivante est valide : ( voir LoadFile.PAS )
PStr := Ems_AccesStr(PLignePtr(Ems_Acces(P))^.Ligne);
car Turbo Pascal va dabord evaluer PLignePtr(Ems_Acces(P))^.Ligne et seulement
après Ems_AccesStr(...); comme Ligne est un POINTER, il est transmit à
Ems_AccesStr par la pile. Je vous conseille d'éviter cette méthode qui peut
provoquer beaucoup de bogue qui seront très dûr à résoudre.
┌─────────────────────────────────┐
│ Chapitre 6 : Enregistrez-vous ! │
└─────────────────────────────────┘
EMS UTILITIES a nécessité de nombreuses heures de travail. Seulement si vous
vous enregistrez, je pourais continuer de mettre à jour EMS UTILITIES. Vue
les services rendus aux programmeurs par EMS UTILITIES, la modique somme de
150 FF n'est seulement qu'une formalité pour pouvoir disposer de EMS
UTILITIES sans royalities dans vos programme.
Comment faire pour s'enregistrer ?
──────────────────────────────────
Il vous suffit d'envoyer une disquette vierge au format 3'1/2 720ko ou 1.44Mo
à l'adresse suivante :
┌─────────────────────────────────────┐
│ Aupetit Sébastien │
│ 58 Rue du Préfet Dalphonse - Notz │
│ 36000 Châteauroux - France │
└─────────────────────────────────────┘
accompagner de votre chèque de 150 FF à l'ordre de Sébastien Aupetit et d'une
enveloppe affranchie au tarif lettre portant votre nom et votre adresse
complète.
ATTENTION : Seul des Francs Français sont acceptés.
Dans un délai raisonnable, vous recevrez une version de EMS UTILITIES V1.00
n'affichant pas de message de copyright.
Vous serez informer de toute nouvelle version de EMS UTILITIES.
Merci ! J'espère que EMS UTILITIES vous a plu
et que cette documentation est assez complète.
Sébastien Aupetit