IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ PascalConsultez toutes les FAQ

Nombre d'auteurs : 10, nombre de questions : 402, dernière mise à jour : 7 janvier 2018  Ajouter une question

 

Bienvenue dans la F.A.Q. Pascal !

Celle-ci rassemble les réponses aux questions les plus fréquemment posées sur le langage Pascal et tous ses outils de programmation. Si elle n'a pas pour vocation de répondre à toutes les interrogations possibles, elle reste une bonne base de connaissances sur le Pascal, et ne demande qu'à être enrichie par vos expériences personnelles.

Nous vous invitons à proposer vos propres questions/réponses directement dans la FAQ ou, si vous souhaitez apporter une modification à une question/réponse existante, à la poster dans le fil de discussion renseigné ci-dessous.

Nous vous souhaitons une bonne lecture !

L'équipe Pascal.

SommaireLes différents compilateursTurbo PascalProgrammation avancée en Turbo Pascal (13)
précédent sommaire suivant
 

Le gestionnaire de mémoire standard de Turbo Pascal ne peut accéder qu'à la mémoire conventionnelle, autrement dit aux 640 ko de mémoire basse. Or, de nos jours, les PC dépassent allègrement 1 Gb de mémoire vive. Comment dépasser la limite des 640 ko ?
La mémoire située au-delà de la mémoire conventionnelle est appelée mémoire haute ou mémoire étendue. Il existe deux protocoles sous Dos pour y accéder :

  • EMS (Expanded Memory Specification), qui fonctionne avec un système de pages mémoire de 16 ko, plutôt utilisée sur les ordinateurs 286 et tombée en désuétude depuis ;
  • XMS (eXtended Memory Specification), apparue avec les 386. On préférera cette dernière, qui permet d'accéder jusqu'à 64 Mo de mémoire.

Si ce n'est pas toute la mémoire dont vous disposez, c'est déjà une quantité plus que satisfaisante pour les besoins les plus courants.

Si vous désirez utiliser la mémoire XMS, il vous faudra créer vous-même l'interface entre celle-ci et votre programme, Turbo Pascal n'offrant rien de tel.

Vous pouvez aussi vous servir des unités ci-dessous.

Mis à jour le 7 mars 2004 Eric Sigoillot

Par défaut, un programme Turbo Pascal s'attribue toute la mémoire conventionnelle disponible (les 640 premiers kb). Si l'on désire laisser de la place pour d'autres programmes (typiquement lorsque l'on veut exécuter un programme externe), il est possible de jouer avec la directive de compilation {$M TaillePile,TasMini,TasMaxi} (en l'occurrence, la valeur de TasMaxi). Cette méthode, bien que préconisée par Borland, manque singulièrement de flexibilité, car la taille maximale du tas est fixée une fois pour toutes au moment de la compilation. Or, il est possible de réduire la taille du tas en cours d'exécution du programme.

Les deux procédures suivantes (HeapShrink et HeapExpand) sont toutefois à utiliser sous votre propre responsabilité. Celles-ci consistent à réduire la taille du tas au minimum possible (sans perdre vos variables allouées dynamiquement) avant l'exécution du programme externe (HeapShrink), puis à lui rendre sa taille originale au retour du programme externe (HeapExpand) :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  
Program Exemple; 
{$M 16384,0,655360}  { On peut allouer toute la mémoire au démarrage } 
... 
Procedure HeapShrink; { Réduit le tas au maximum } 
Var 
  RegBx : Word; 
Begin 
  RegBx := MemW[Seg(HeapPtr):Ofs(HeapPtr) + 2] - PrefixSeg; 
  asm 
    mov bx, RegBx 
    mov es, PrefixSeg 
    mov ah, 4Ah 
    int 21h 
  end; 
End; 
  
Procedure HeapExpand; { Redonne au tas sa taille originale } 
Var 
  RegBx : Word; 
Begin 
  RegBx := MemW[Seg(HeapEnd):Ofs(HeapEnd) + 2] - PrefixSeg; 
  asm 
    mov bx, RegBx 
    mov es, PrefixSeg 
    mov ah, 4Ah 
    int 21h 
  end; 
End; 
... 
Begin 
  ... 
  HeapShrink; 
  SwapVectors; 
  Exec('COMMAND.COM',''); 
  SwapVectors; 
  HeapExpand; 
  if DosError <> 0 then ... 
  ... 
End.

Mis à jour le 7 mars 2004 Eric Sigoillot

Pour tester si un disque existe, et donc s'il est accessible, on peut tenter de basculer sur ce disque et ensuite vérifier que tout s'est bien passé. Pour ce faire, on utilise les fonctions 0Eh et 19h de l'interruption 21h.

Le code suivant se sépare en plusieurs parties. Tout d'abord, on récupère le lecteur en cours, puis on tente de basculer sur le lecteur désiré et on compare avec la nouvelle valeur du lecteur en cours. Si cette nouvelle valeur diffère du lecteur désiré, alors c'est que ce lecteur n'existe pas et/ou n'est pas accessible. Enfin, on rétablit le lecteur d'origine.

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  
Uses 
  Dos; 
  
Function DriveExists (const Drive : Char) : Boolean; 
Var 
  Regs : Registers; 
  CurrentDrive, NewDrive : Byte; 
Begin 
  DriveExists := False; 
  { Test de validité } 
  if not (Upcase(Drive) in ['A'..'Z']) then Exit; 
  
  { On récupère le lecteur actuel } 
  Regs.ah := $19; 
  MsDos(Regs); 
  CurrentDrive := Regs.al; 
  
  { On bascule sur le nouveau lecteur } 
  NewDrive := Ord(UpCase(Drive)) - Ord('A'); 
  Regs.ah := $0E; 
  Regs.dl := NewDrive; 
  MsDos(Regs); 
  
  { On vérifie que tout s'est bien déroulé } 
  Regs.ah := $19; 
  MsDos(Regs); 
  DriveExists := (Regs.al = NewDrive); 
  
  { On réactive le lecteur précédent } 
  Regs.ah := $0E; 
  Regs.dl := CurrentDrive; 
  MsDos(Regs); 
End;

Mis à jour le 5 juin 2004 Eric Sigoillot

Les touches de contrôle : Ctrl, Alt, AltGr ou Maj, possèdent une place à part sur notre clavier. Leur manière de détection – mis à part au niveau de l'interruption clavier – est totalement différente de celle des autres touches.
On peut compter également dans les rangs des touches de contrôle les touches à bascule : Verr Num, Verr Maj, Inser ou Arrêt Défil.

Pour savoir si une de ces touches est actuellement pressée (active) ou relâchée (inactive), il faut regarder la valeur du Word à l'adresse mémoire $0040:$0017. Chaque bit de ce mot est attribué à une touche. Si elle est pressée (ou active), le bit est à 1, sinon, il est à 0. Il est à noter que, si les touches de contrôle sont en double (une gauche et une droite), alors elles sont gérées séparément. Le tableau suivant les décrit :

Touche Bit(s) Masque
Ctrl gauche 2 et 8 $0104
Ctrl droite 2 $0004
Maj gauche 1 $0002
Maj droite 0 $0001
Alt 3 et 9 $0208
Alt Gr 3 $0008
Verr Num 5 $20
Verr Maj 6 $40
Inser 7 $80
Arrêt Défil 4 $10
Pour connaître l'état du Word en $0040:$0017, on peut au choix utiliser le tableau MemW, ou bien, de manière plus pratique, se servir d'une variable Word déclarée en absolute, comme dans l'exemple ci-dessous.

Les touches à bascule n'utilisent que le Byte à l'adresse $0040:$0017.

L'exemple suivant se charge de vérifier la combinaison de touches AltGr + E. Si ces deux touches sont pressées, alors le mot « Euro » est affiché à l'écran. Attention ! La combinaison Alt+E correspond à une touche étendue. Mais tel quel, avec seulement ReadKey, il est impossible de savoir s'il s'agit juste de Alt ou bien AltGr. C'est ici qu'intervient notre code. On va distinguer Alt et AltGr. Si AltGr est pressé, alors seul le bit 3 est actif. Sinon, il y a aussi le bit 9. On va donc vérifier que le bit 3 est actif, mais pas le 9... Pour ce faire, on applique le masque isolant les bits 3 et 9, et on regarde si le bit 9 est bien éteint, alors que le 3 ne l'est pas.

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  
Program TestEuro; 
Uses 
  Crt; 
  
Var 
  KbdState : Word absolute $0040:$0017;    { Déclare une variable Word à l'adresse $0040:$0017 } 
  Ch : Char; 
  
Begin 
  repeat 
    Ch := ReadKey; 
    if Ch = #0 then    { Alt+E renvoie la combinaison #0, #18 } 
    begin 
      if (ReadKey = #18) and (KbdState and $0208 = $0008) then   { Masques associés à Alt et AltGr } 
        WriteLn('Euro'); 
    end; 
  until Ch = #27;    { On quitte avec Echap } 
End.
Remarque : il est possible de modifier l'état d'une touche à bascule en modifiant directement en mémoire le bit souhaité. Attention toutefois, non seulement il ne faut modifier que le Byte à cette adresse, mais en plus, la modification du bit n'entraîne pas un changement de couleur des LED du clavier ! Pour modifier aussi leur couleur en conséquence, il faudra utiliser le port $60 et lui envoyer la valeur $ED. Par exemple, pour activer l'état Num Lock, on écrira :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  
Var 
  KbdSwitch : Byte absolute $0040:$0017; 
  OldSwitch : Word; 
  
Begin 
  (* Active Ver Num *) 
  OldSwitch := KbdSwitch; 
  KbdSwitch := OldSwitch and (not $20) or $20;   { On ne modifie que Verr Num, pas les autres bits } 
  { On modifie les LED du clavier en fonction des bits } 
  Port[$60] := $ED; 
  Port[$60] := (KbdSwitch shr 4) and 7; 
  
  (* Désactive Verr Num *) 
  OldSwitch := KbdSwitch; 
  KbdSwitch := OldSwitch and (not $20);   { On conserve les autres bits, sauf Verr Num } 
  { On modifie les LED du clavier en fonction des bits } 
  Port[$60] := $ED; 
  Port[$60] := (KbdSwitch shr 4) and 7; 
End;

Mis à jour le 30 mars 2004 Eric Sigoillot

Turbo Pascal ne sait malheureusement pas détecter les touches F11 et F12. Il faut l'aider un peu... Pour cela, il faut se servir de la fonction 10h de l'interruption 16h :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  
Uses 
  Dos; 
  
Function ReadExtKey : Word; 
Var 
  Regs      : Registers; 
  KbdStatus : Byte absolute $0040:$0096; 
Begin 
  ReadExtKey := 0; 
  if KbdStatus and 16 = 0 then Exit; 
  Regs.ah := $10; 
  Intr($16, Regs); 
  ReadExtKey := Regs.ax 
End; 
  
Var 
  Key : Word; 
Begin 
  ... 
  Key := ReadExtKey; 
  if Key = $8500 then { F11 appuyée } 
  else if Key = $8600 then { F12 appuyée }; 
  ... 
End.

Mis à jour le 5 juin 2004 Eric Sigoillot

Chaque programme EXE conçu avec Turbo Pascal est composé de plusieurs segments : des segments de code, un segment de données et un segment de pile. De plus, Turbo Pascal place toujours chaque module (programme principal ou unité) dans un segment distinct. Bien entendu, il y a communication entre chacun des segments de code, notamment pour appeler des procédures et fonctions.
C'est ici qu'intervient la notion d'appel « far » et d'appel « near ». En effet, sitôt que l'on entre dans une procédure, il faut aussi penser à en sortir. Par conséquent, on sauve sur la pile la position actuelle avant d'appeler la procédure. Si on reste dans le même segment, seul l'offset est à empiler. On parle alors d'appel « near » (proche). Si par contre, on change de segment, alors il faut penser également à empiler le segment dans lequel on se trouve, et on parle d'appel « far » (lointain).

De fait, comme une unité se situera toujours dans un segment différent du programme principal ou d'une autre unité, toutes ses procédures et fonctions déclarées dans la partie interface seront déclarées comme « far ». De même, comme une procédure ou une fonction déclarée dans le programme principal n'est accessible que dans ce même programme principal, elle sera toujours déclarée comme « near ».

Un problème se pose donc quand une procédure est déclarée dans le programme principal et qu'elle est destinée à être utilisée en dehors de celui-ci. C'est notamment le cas des gestionnaires d'interruption. Dans ce cas, il faut forcer Turbo Pascal à adopter un mode d'appel « far ».
Pour ce faire, deux solutions s'offrent à nous. Soit on ajoute la directive « far » à l'en-tête de la procédure, soit on la place entre les directives de compilation {$F+}...{$F-} :

Code delphi : Sélectionner tout
1
2
3
4
5
  
Procedure AppelFar; far; 
Begin 
  ... 
End;


Code delphi : Sélectionner tout
1
2
3
4
5
6
7
  
{$F+} 
Procedure AppelFar; 
Begin 
  ... 
End; 
{$F-}

Mis à jour le 7 mars 2004 Eric Sigoillot

Il peut être utile d'écrire sa propre routine d'interruption pour remplacer une routine du BIOS ou du DOS.
Il s'agit en fait d'une procédure classique affublée de la directive interrupt. Important : cette procédure doit être déclarée comme FAR, à l'aide de la directive de compilation {$F+}.

Pour que votre routine personnelle remplace une des routines du BIOS ou du DOS, il faut aller déposer son adresse dans le vecteur d'interruptions, en prenant soin de sauvegarder l'adresse qui s'y trouvait. Les procédures GetIntVec et SetIntVec, de l'unité Dos, permettent respectivement de lire et d'écrire dans le vecteur d'interruptions.

Important : avant la terminaison de votre programme, il faut impérativement restaurer le vecteur d'interruptions dans son état initial, sous peine de risquer de planter la machine (ou la machine DOS virtuelle).

Prenons un exemple : la désactivation du Ctrl+C et du Ctrl-Break. Pour cela, il suffit de remplacer l'adresse des entrées 23h et 1Bh dans le vecteur d'interruptions par l'adresse d'une routine personnelle qui ne fait rien :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  
Uses 
  Dos; 
  
Var 
  { Pour sauver les anciens vecteurs d'interruption } 
  OldInt1B, OldInt23 : Pointer; 
  
{ L'interruption nulle qui va remplacer les vecteurs actuels } 
{$F+} 
Procedure NullInt (Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP: Word); interrupt; 
Begin 
End; 
{$F-} 
  
Begin 
  { On sauve les anciens vecteurs } 
  GetIntVec($1B,OldInt1B); 
  GetIntVec($23,OldInt23); 
  { On installe la procédure nulle } 
  SetIntVec($1B,@NullInt); 
  SetIntVec($23,@NullInt); 
  ... 
  { Ici, Ctrl+Break est désactivé } 
  ... 
  { On rétablit les anciens vecteurs } 
  SetIntVec($1B,OldInt1B); 
  SetIntVec($23,OldInt23); 
end.

Mis à jour le 10 mai 2005 Alcatîz Eric Sigoillot

Turbo Pascal ayant été conçu dans les années 80, il ne sait pas explicitement utiliser les instructions 32 bits des processeurs 386 et supérieurs.

Pour bien comprendre le principe qui suit, il faut descendre jusqu'au code machine.
Considérons les deux instructions suivantes :

Code : Sélectionner tout
1
2
 
mov ax, cx
et

Code : Sélectionner tout
1
2
 
mov eax, ecx
Elles donnent respectivement en code machine :

Code : Sélectionner tout
1
2
 
89h C8h
et

Code : Sélectionner tout
1
2
 
66h 89h C8h
On remarque que seul le préfixe 66h est ajouté au code 16 bits pour donner le code 32 bits. Ce principe est valable pour toutes les instructions 32 bits ayant un équivalent 16 bits.

Ainsi, pour coder mov eax, ecx, on écrira :

Code delphi : Sélectionner tout
1
2
3
4
  
asm 
  db 66h; mov ax, cx 
end;
Seule précaution à prendre : lors de l'utilisation de constantes. En effet, il faut bien prendre garde à indiquer une constante sur 32 bits, et non sur 16 bits comme Turbo Pascal le fait par défaut.
De fait, pour coder mov eax, 0, on écrira :

Code delphi : Sélectionner tout
1
2
3
4
  
asm 
  db 66h; mov ax, 0; dw 0000h 
end;
Le dw 0000h correspondant au mot de poids fort de la constante.

Mis à jour le 7 mars 2004 Eric Sigoillot

Pour accéder à un paramètre par adresse (transmis avec var), vous devrez toujours utiliser un pointeur, en général ES:DI ou bien DS:SI :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
  
Procedure ParamAdresse (var P : Integer); assembler; 
asm 
  ... 
  les di,P 
  ... 
end;

Mis à jour le 7 mars 2004 Eric Sigoillot

Si votre fonction n'utilise qu'un bloc en assembleur, alors vous pouvez vous servir de la variable locale déclarée implicitement @Result :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
  
Function Test : Integer; 
Begin 
  ... 
  asm 
    ... 
    mov  @Result, ax 
    ... 
  end; 
  ... 
End;
Si, par contre, toute votre fonction est en assembleur, alors il y a plusieurs cas de figure :

Type du résultat Méthode de renvoi
Type scalaire 8 bits (entier, caractère, booléen, énuméré) Registre AL
Type scalaire 16 bits (Integer, Word) Registre AX
Type scalaire 32 bits (LongInt, pointeur) Registres DX:AX
String @Result (cas particulier)
Real Registres DX:BX:AX
Autres types de réels (Single, Double...) Registre ST(0) (premier registre FPU)

Mis à jour le 7 mars 2004 Eric Sigoillot

Il est possible d'écrire des routines en Assembleur, de les compiler sous forme de fichier objet (.OBJ) et de les lier à un programme Turbo Pascal. Toutefois, il faut respecter plusieurs règles :

  • le module objet doit être au format .OBJ 16 bits ;
  • les procédures et fonctions doivent se trouver dans un segment appelé CODE ou CSeg ;
  • pour pouvoir être utilisées dans le programme Pascal, ces procédures et fonctions doivent être déclarées PUBLIC ;
  • les éventuelles variables doivent se trouver dans un segment appelé DATA ou DSeg ;
  • pour utiliser des variables, procédures ou fonctions du programme Pascal, il faut les référencer par la directive EXTRN.

Voici un exemple de source Assembleur (TCURSOR.ASM, compilé dans le fichier objet TCURSOR.OBJ) :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
DATA      SEGMENT   WORD   PUBLIC 
 
          EXTRN     Textx : word 
          EXTRN     Texty : word 
          EXTRN     Textpage : word 
 
DATA      ENDS 
 
CODE      SEGMENT   WORD   PUBLIC 
 
          ASSUME    CS:CODE,DS:DATA 
          PUBLIC    TCURSOR 
 
COMMENT ! Déplacement du curseur vers les coordonnées (textx,texty) ! 
 
TCURSOR   PROC      FAR 
          push      ax 
          push      bx 
          push      dx 
          pushf 
          mov       bx,Textpage 
          mov       bh,bl               ; BH = page active 
          mov       dx,Textx            ; DL = colonne 
          mov       ax,Texty 
          mov       dh,al               ; DH = ligne 
          mov       ah,2                ; Déplacement du curseur 
          int       10h                 ; Services vidéo du BIOS 
          popf 
          pop       dx 
          pop       bx 
          pop       ax 
          ret 
TCURSOR   ENDP 
 
CODE      ENDS 
 
          END
La procédure TCURSOR peut être utilisée dans le programme Pascal si elle est déclarée external. La directive $L informe l'éditeur de liens qu'il doit lier le fichier TCURSOR.OBJ à l'exécutable :

Code delphi : Sélectionner tout
1
2
3
  
{$L TCURSOR} 
Procedure TCURSOR; external;

Mis à jour le 20 février 2007 Alcatîz

La réponse est non : même si, dans votre module objet (.OBJ), vous définissez une variable dans le segment DATA (ou DSeg), même si cette variable est finalement stockée avec les variables globales du programme, elle ne peut être utilisée ailleurs que dans les routines du module objet. La solution est de déclarer cette variable dans le programme Pascal et, dans le module objet, de la déclarer dans le segment DATA avec la directive EXTRN.

Mis à jour le 24 février 2007 Alcatîz

Il est impossible d'intégrer directement du code en C dans un programme Pascal. Toutefois, il est possible de « ruser ». Pour ce faire, il faut créer en aval un module en C et le compiler sous forme de fichier objet compatible Intel *.OBJ.
Certaines règles doivent cependant s'appliquer – et il est impossible d'y déroger :

  • le module en C doit être compilé sous un modèle de mémoire small ;
  • le module C doit être compilé avec un compilateur 16 bits si le compilateur Pascal est un compilateur 16 bits et 32 bits si le compilateur Pascal est 32 bits ;
  • toutes les données (variables, constantes, types, classes...) du module C seront inaccessibles dans le code Pascal, mais, par contre, les variables du module Pascal seront accessibles depuis le module C. Par conséquent, toute donnée devant être partagée devra être déclarée dans le module Pascal ;
  • il faut déclarer toutes les routines destinées à être partagées en mode d'appel far ;
  • il est a priori impossible d'utiliser des routines de la runtime library (RTL) C/C++ à cause de conflit de noms.

Une fois toutes ces remarques prises en considération, il suffit de créer un module en C, en déclarant en tant que extern tous les éléments se situant dans le module Pascal, en prenant garde à la casse (majuscules et minuscules). Il faut ensuite le compiler sous forme de fichier objet.
Dans le module Pascal, il suffit de déclarer toutes les procédures et variables nécessaires puis d'intégrer au code le fichier objet grâce à la directive de compilation {$L MODULE_C.OBJ}MODULE_C correspond au nom de votre module C.

L'exemple suivant illustre l'intégration d'un module C dans un programme en Pascal.

Code C : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  
/* Module MODC.C */ 
  
typedef unsigned int word; 
  
extern void Clear(word Color); /* Procédure du module Pascal */ 
extern word Color;    /* Variable déclarée dans le module Pascal */ 
  
void CallClear() 
{ 
  /* Modifie une variable Pascal */ 
  if (Color == 15) Color = 1; 
  else Color++; 
  /* Appelle une procédure Pascal */ 
  Clear(Color); 
}
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  
Program IntegrationC; 
  
Cses 
  Crt; 
  
{ Variable partagée } 
Var 
  Color : Word; 
  
{ Procédure partagée } 
Procedure Clear (Color : Word); 
Begin 
  TextBackground(Color); 
  ClrScr; 
End; 
  
{ Intégration de la procédure en C } 
Procedure CallClear; external; 
{$L MODC.OBJ} 
  
Begin 
  Color := 1; 
  CallClear; 
  ReadLn; 
End.

Mis à jour le 5 juin 2004 Eric Sigoillot

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.