Autres articles / Other articles

Evolution des structures depuis la version 7.0.7.21

publication: 9 décembre 2024 / mis à jour 9 décembre 2024

Read this page in english

 


Dans le précédent chapitre, on a abordé le problème de la taille des champs dans une structure. Il était recommandé de définir des mots spécifiques pour lire ou écrire dans ces champs.

Dans la version eForth Windows 7.0.7.21 les @field et !field apparaissent dans le vocabulaire structures. Ces mots apportent une solution élégante pour lire ou écrire des données depuis des accesseurs.

Les types de champs dans les structures

Il y a quatre types de champs connus: i8, i16, i32 et i64, gérant respectivement des champs de 8, 16, 32 et 64 bits. Ces quatre types sont complétés par trois nouveaux types:

Il n'y a pas de mot u64.

Cette panoplie de champs est complétée du mot sc@ qui exécute une récupération d'octet signé dans le contenu d'un champ huit bits.

structures 
struct 8BXY 
    i8 field ->8bx 
    i8 field ->8by 
     
create XY-offset 
    -3 c, 
    12 c, 
     
XY-offset ->8bx sc@ .   \ display -3 
XY-offset ->8by sc@ .   \ display 12 

Le typage des données 8, 16, 32 ou 64 bits, signés ou non signés, rajoute de la complexité dans le choix adaptés des mots effectuant une lecture ou écriture dans les champs d'une structure.

Accès simplifié aux données d'un champ de structure

Heureusement, les deux nouveaux mots @field et !field apportent uen solution qui simplifie l'accès au contenu des champs en s'adaptant automatiquement à la taille et au type des champs définis:

XY-offset @field ->8bx . 
XY-offset @field ->8by . 

Les mots @field et !field doivent être suivis de l'accesseur correspondant.

Utilisons @field dans une définition:

: getXY ( -- x y ) 
    XY-offset @field ->8bx 
    XY-offset @field ->8by 
  ; 
getXY   \ leave -3 12 on stack 

Si on décompile notre mot getXY, on retrouve le mot sc@ au lieu de @field:

see getXY  \ display: 
: getXY 
    XY-offset ->8bx sc@ XY-offset ->8by sc@ 
; 

Les mots @field et !field sont donc particulièrement utiles pour gérer les accès à des champs de taille hétérogène dans des structures. La modification du type dans une structure ne nécessite pas la modification des définitions qui utilisent @field ou !field.

Les alias de type de données

Partons d'une structure écrite en langage C:

typedef struct _DCB {
  DWORD DCBlength;
  DWORD BaudRate;
  DWORD fBinary : 1;
  DWORD fParity : 1;
  DWORD fOutxCtsFlow : 1;
  DWORD fOutxDsrFlow : 1;
  DWORD fDtrControl : 2;
  DWORD fDsrSensitivity : 1;
  DWORD fTXContinueOnXoff : 1;
  DWORD fOutX : 1;
  DWORD fInX : 1;
  DWORD fErrorChar : 1;
  DWORD fNull : 1;
  DWORD fRtsControl : 2;
  DWORD fAbortOnError : 1;
  DWORD fDummy2 : 17;
  WORD  wReserved;
  WORD  XonLim;
  WORD  XoffLim;
  BYTE  ByteSize;
  BYTE  Parity;
  BYTE  StopBits;
  char  XonChar;
  char  XoffChar;
  char  ErrorChar;
  char  EofChar;
  char  EvtChar;
  WORD  wReserved1;
} DCB, *LPDCB;

Pour utiliser cette même structure avec eForth Windows, il est nécessaire de traduire la taille de chaque type de donnée (DWORD, WORD, BYTE...) en son type de données i8 i16 i32. C'est long, fastidieux, et sujet à erreurs.

La solution est de définir des alias:

( Windows handles bottom out as void pointers. ) 
: HANDLE    ptr ; 
: DWORD     u32 ; 
: WINLONG   i32 ; 
: UINT      u32 ; 
: WPARAM    ptr ; 
: LPARAM    ptr ; 
: WINBOOL   i32 ; 
: WINWORD   u16 ;    
: WORD      u16 ; 
: BYTE      u8  ; 
\ char  use u8 or BYTE 

Il n'y a que pour le type char pour lequel on ne définit pas d'alias, car il y a risque de colision avec le mot char du vocabulaire FORTH. Voici comment on peut réécrire en Forth la structure DCB si on utilise ces alias:

structures 
struct DCB 
  DWORD field ->DCBlength 
  DWORD field ->BaudRate 
  DWORD field ->fBinary 
  DWORD field ->fParity 
  DWORD field ->fOutxCtsFlow 
  DWORD field ->fOutxDsrFlow 
  DWORD field ->fDtrControl 
  DWORD field ->fDsrSensitivity 
  DWORD field ->fTXContinueOnXoff 
  DWORD field ->fOutX 
  DWORD field ->fInX 
  DWORD field ->fErrorChar 
  DWORD field ->fNull 
  DWORD field ->fRtsControl 
  DWORD field ->fAbortOnError 
  DWORD field ->fDummy2 
  WORD  field ->wReserved 
  WORD  field ->XonLim 
  WORD  field ->XoffLim 
  BYTE  field ->ByteSize 
  BYTE  field ->Parity 
  BYTE  field ->StopBits 
  BYTE  field ->XonChar 
  BYTE  field ->XoffChar 
  BYTE  field ->ErrorChar 
  BYTE  field ->EofChar 
  BYTE  field ->EvtChar 
  WORD  field ->wReserved1 

Dans la version de DCB en langage C, nous avons un certain nombre de champs avec des valeurs par défaut. Voici comment initialiser une structure DCB en Forth avec !field:

: DCB.init  ( DCBaddr -- ) 
    >r 
    1   r@ !field ->fBinary 
    1   r@ !field ->fParity  
    1   r@ !field ->fOutxCtsFlow 
    1   r@ !field ->fOutxDsrFlow 
    2   r@ !field ->fDtrControl 
    1   r@ !field ->fDsrSensitivity 
    1   r@ !field ->fTXContinueOnXoff 
    1   r@ !field ->fOutX 
    1   r@ !field ->fInX 
    1   r@ !field ->fErrorChar 
    1   r@ !field ->fNull 
    2   r@ !field ->fRtsControl 
    1   r@ !field ->fAbortOnError 
    17  r> !field ->fDummy2 
  ; 
create COM5-DCB 
    DCB allot 
    COM5-DCB DCB.init 

En résumé, avec cette évolution, la gestion des champs dans les structures devient infiniment plus simple et beaucoup plus souple. Cette évolution reste compatible avec les codes sources Forth plus anciens exploitant les structures sans nécessiter la réécriture de ces fichiers source.


Legal: site web personnel sans commerce / personal site without seling