1 PROGRAM BIBLIOTHEQUE;
\r
3 SIGNAL Del_Rec_Inexistant, Key_AlReady_In_Index,
\r
4 TreeHeight_Overflow, Signal11, Signal12, Signal14;
\r
6 (*-------------------------------------------------*)
\r
7 (* MODULE de GESTION des FICHIERS de l'application *)
\r
8 (*-------------------------------------------------*)
\r
9 UNIT FileSystem: CLASS;
\r
11 (*-----------------------------------------------------------*)
\r
12 (* CLASSE representant la FILE des FICHIERS de l'application *)
\r
13 (*-----------------------------------------------------------*)
\r
15 VAR Name: ARRAYOF CHAR,
\r
23 VAR System: RFile; (* FICHIER manipule lors des differentes operations *)
\r
25 (*-----------------------------------------------------------*)
\r
26 (* RECHERCHE d'un FICHIER dans les FICHIERS de l'APPLICATION *)
\r
27 (*-----------------------------------------------------------*)
\r
28 UNIT FindInSystem : FUNCTION(Name:ARRAYOF CHAR): RFile;
\r
30 (*-------------------------------------------*)
\r
31 (* COMPARAISON de deux CHAINES de caracteres *)
\r
32 (*-------------------------------------------*)
\r
33 UNIT EqualString: FUNCTION(chaine1, chaine2: ARRAYOF CHAR):BOOLEAN;
\r
34 VAR i1, i2, len, i: INTEGER;
\r
36 IF (chaine1 = NONE) OR (chaine2 = NONE)
\r
37 THEN writeln("Un parametre est egal a NONE dans EqualString");
\r
38 CALL ENDRUN (* ARRET du programme *)
\r
40 i1 := LOWER(chaine1); i2 := LOWER(chaine2);
\r
41 len := UPPER(chaine1) - i1 + 1;
\r
42 IF len =/= UPPER(chaine2) - i2 + 1
\r
43 THEN RETURN (* Chaines de longueurs differentes *)
\r
47 IF chaine1(i1) =/= chaine2(i2)
\r
48 THEN RETURN (* Chaines differentes *)
\r
50 i1 := i1 + 1; i2 := i2 + 1
\r
52 (* Si on arrive la les chaines sont egales *)
\r
59 System.Name := Name;
\r
61 WHILE NOT EqualString(Name,df.Name)
\r
71 (*-------------------------------------------*)
\r
72 (* AJOUT d'un Fichier a la FILE des FICHIERS *)
\r
73 (*-------------------------------------------*)
\r
74 UNIT AddToSystem: FUNCTION(Name: ARRAYOF CHAR): RFile;
\r
76 RESULT := NEW RFile;
\r
77 RESULT.Name := Name;
\r
78 RESULT.Next := System.Next;
\r
79 RESULT.Prev := System;
\r
80 System.Next.Prev := RESULT;
\r
81 System.Next := RESULT;
\r
84 (*----------------------------------------------*)
\r
85 (* SUPPRIMER un FICHIER de la FILE des FICHIERS *)
\r
86 (*----------------------------------------------*)
\r
87 UNIT DeleteFromSystem: PROCEDURE(df:RFile);
\r
92 df.Next.Prev := df.Prev;
\r
93 df.Prev.Next := df.Next
\r
94 END DeleteFromSystem;
\r
96 (*-------------------------------------------------------------------------*)
\r
97 (* CALCUL de la LONGUEUR d'un Fichier exprime en nombres d'enregistrements *)
\r
98 (*-------------------------------------------------------------------------*)
\r
99 UNIT FindFileLength: FUNCTION(df :file, RecLen :INTEGER) :INTEGER;
\r
100 VAR record: ARRAYOF INTEGER, i:INTEGER;
\r
103 THEN writeln("ERREUR FindFileLength : Fichier inexistant");
\r
108 ARRAY record DIM (1:RecLen);
\r
109 i := RecLen*INTSIZE;
\r
111 GETREC(df,record,i);
\r
112 IF i =/= RecLen*INTSIZE
\r
115 RESULT := RESULT + 1;
\r
117 END FindFileLength;
\r
120 (*-----------------------------------------------------------------------*)
\r
121 (* CREATION d'un nouveau FICHIER et insertion de ce Fichier dans la FILE *)
\r
122 (* le Fichier est ouvert est sa longueur est egal a 1 *)
\r
123 (*-----------------------------------------------------------------------*)
\r
124 UNIT MakeFile: FUNCTION(Name: ARRAYOF CHAR, RecLen: INTEGER): RFile;
\r
126 IF FindInSystem(Name) =/= NONE
\r
127 THEN writeln("ERREUR MakeFile : Fichier existant");
\r
130 THEN writeln("ERREUR MakeFile : Longueur de Fichier doit etre positive");
\r
132 RESULT := AddToSystem(Name);
\r
133 RESULT.Opened := TRUE;
\r
134 RESULT.RecLen := RecLen;
\r
135 RESULT.Position := 1;
\r
136 RESULT.Length := 1;
\r
137 OPEN(RESULT.Fichier, direct, Name);
\r
138 CALL REWRITE(RESULT.Fichier);
\r
141 (*------------------------------------------------------------------*)
\r
142 (* OUVRIR un Fichier deja present dans la FILE des FICHIERS *)
\r
143 (* ou AJOUT de ce FICHIER a la FILE si il n'y est pas. *)
\r
144 (*------------------------------------------------------------------*)
\r
145 UNIT OpenFile: FUNCTION(Name: ARRAYOF CHAR, RecLen: INTEGER): RFile;
\r
148 THEN writeln("ERREUR OpenFile : La longueur d'enregistrement doit etre
\r
151 RESULT := FindInSystem(Name);
\r
153 THEN RESULT := AddToSystem(Name)
\r
155 RESULT.Opened := TRUE;
\r
156 RESULT.RecLen := RecLen;
\r
157 RESULT.Position := 1;
\r
158 OPEN(RESULT.Fichier,direct,Name);
\r
159 RESULT.Length := FindFileLength(RESULT.Fichier,RecLen);
\r
160 IF RESULT.Length = 1
\r
161 THEN CALL REWRITE(RESULT.Fichier) (* Le FICHIER est VIDE *)
\r
162 ELSE CALL RESET(RESULT.Fichier) FI; (* Le FICHIER n'est pas VIDE *)
\r
165 (*--------------------------------------------*)
\r
166 (* FERMETURE d'un fichier ouvert par OpenFile *)
\r
167 (*--------------------------------------------*)
\r
168 UNIT CloseFile: PROCEDURE (df :RFile);
\r
171 THEN writeln("ERREUR CloseFile : Fichier inexistant");
\r
174 THEN writeln("ERREUR CloseFile : Fermeture d'un fichier pas ouvert");
\r
176 df. Opened := FALSE;
\r
180 (*-------------------------------*)
\r
181 (* TEST si un FICHIER est OUVERT *)
\r
182 (*-------------------------------*)
\r
183 UNIT IsOpen: FUNCTION(df :RFile) :BOOLEAN;
\r
186 THEN writeln("ERREUR IsOpen : Fichier inexistant");
\r
188 RESULT := df.Opened
\r
191 (*----------------------------------------------------*)
\r
192 (* MISE a 1 de la POSITION de LECTURE dans le FICHIER *)
\r
193 (*----------------------------------------------------*)
\r
194 UNIT Frewind: PROCEDURE(df :RFile);
\r
197 THEN writeln("Frewind : Fichier inexistant");
\r
200 THEN writeln("Frewind : Fichier pas ouvert");
\r
203 CALL RESET(df.Fichier)
\r
206 (*----------------------------------*)
\r
207 (* TEST si on est en fin de FICHIER *)
\r
208 (*----------------------------------*)
\r
209 UNIT Feof: FUNCTION(df: RFile): BOOLEAN;
\r
212 THEN writeln("Feof : Fichier inexistant");
\r
215 THEN writeln("Feof : Fichier pas ouvert");
\r
217 RESULT := ( df.Position >= df.Length )
\r
220 (*----------------------------------------------*)
\r
221 (* ECRITURE d'un enregistrement dans le fichier *)
\r
222 (*----------------------------------------------*)
\r
223 UNIT Fput: PROCEDURE(df :RFile, Record :ARRAYOF INTEGER);
\r
224 VAR nbint, i : INTEGER;
\r
227 THEN writeln("ERREUR Fput : Fichier inexistant");
\r
228 CALL ENDRUN; (* FIN du PROGRAMME *)
\r
231 THEN writeln("ERREUR Fput : Fichier pas ouvert"); FI;
\r
232 IF df.Position > df.Length
\r
233 THEN writeln("ERREUR Fput : Tentative d'acces apres la fin de fichier");
\r
236 THEN writeln("ERREUR Fput : Enregistrement inexistant");
\r
238 nbint := UPPER(Record) - LOWER(Record) + 1;
\r
239 IF nbint =/= df.RecLen
\r
240 THEN writeln("ERREUR Fput : Taille enregistrement incorrect") FI;
\r
241 i := nbint * intsize;
\r
242 PUTREC(df.Fichier, Record, i);
\r
243 IF i =/= nbint * intsize
\r
244 THEN writeln("ERREUR Fput : ERREUR durant l'ecriture") FI;
\r
245 (* MODIFICATION de la POSITION de LECTURE du FICHIER et de la LONGUEUR
\r
246 eventuellement du FICHIER *)
\r
247 df.Position := df.Position + 1;
\r
248 IF df.Position > df.Length
\r
249 THEN df.Length := df.Position
\r
253 (*---------------------------------------------*)
\r
254 (* LECTURE d'un ENREGISTREMENT dans le FICHIER *)
\r
255 (*---------------------------------------------*)
\r
256 UNIT Fget: FUNCTION(df :RFile): ARRAYOF INTEGER;
\r
257 VAR Record: ARRAYOF INTEGER,
\r
258 nbint, i : INTEGER;
\r
261 THEN writeln("ERREUR Fget : Fichier inexistant"); FI;
\r
263 THEN writeln("ERREUR Fget : Fichier pas ouvert"); FI;
\r
264 IF df.Position >= df.Length
\r
265 THEN writeln("ERREUR Fget : Tentative lecture apres la fin de fichier");
\r
267 nbint := df.RecLen;
\r
268 ARRAY Record dim (1:nbint);
\r
269 i := nbint * intsize;
\r
270 GETREC(df.Fichier, Record, i);
\r
271 IF i =/= nbint * intsize
\r
272 THEN writeln("ERREUR Fget : Erreur durant la lecture");
\r
274 df.Position := df.Position + 1;
\r
278 (*------------------------------------------------------------------------*)
\r
279 (* DEPLACEMENT dans le fichier a la Position du NUMRECieme ENREGISTREMENT *)
\r
280 (*------------------------------------------------------------------------*)
\r
281 UNIT Fseek: PROCEDURE(df :RFile, numrec :INTEGER);
\r
282 VAR offset: INTEGER;
\r
285 THEN writeln("ERREUR Fseek : Fichier inexistant");
\r
288 THEN writeln("ERREUR Fseek : Fichier non ouvert");
\r
291 THEN writeln("ERREUR Fseek : Numero de record doit etre positif");
\r
293 IF numrec > df.Length
\r
294 THEN writeln("ERREUR Fseek : Tentative d'acces apres la fin de fichier");
\r
296 df.Position := numrec;
\r
297 offset := (numrec - 1) * df.RecLen * intsize;
\r
298 CALL seek(df.Fichier, offset, 0)
\r
301 (*-------------------------------------------------------*)
\r
302 (* INDIQUE la POSITION COURANTE dans le FICHIER specifie *)
\r
303 (*-------------------------------------------------------*)
\r
304 UNIT Position: FUNCTION(df :RFile) :INTEGER;
\r
307 THEN writeln("ERREUR Position : Fichier inexistant") FI;
\r
309 THEN writeln("ERREUR Position : Fichier pas ouvert") FI;
\r
310 RESULT := df.Position
\r
313 (*-----------------------------------------*)
\r
314 (* INDIQUE la LONGUEUR du FICHIER specifie *)
\r
315 (*-----------------------------------------*)
\r
316 UNIT FileLen: FUNCTION(df :RFile) :INTEGER;
\r
319 THEN writeln("ERREUR FileLen : Fichier inexistant") FI;
\r
321 THEN writeln("ERREUR FileLen : Fichier pas ouvert") FI;
\r
322 RESULT := df.Length
\r
325 BEGIN (* FileSystem *)
\r
326 System := NEW RFile;
\r
327 System.Next, System.Prev := System;
\r
333 (*------------------------------------------------------*)
\r
334 (* MODULE contenant la declaration d'une BASE de DONNEE *)
\r
335 (* c.a.d. : RELATION, FICHIER DONNEES, FICHIER INDEX *)
\r
336 (*------------------------------------------------------*)
\r
337 UNIT HandlerOfRelations:FileSystem CLASS(PageSize, TreeHeight,
\r
338 HalfPageSize : INTEGER);
\r
340 (*-----------------------------------------------------*)
\r
341 (* MODULE GENERIQUE d'un FICHIER de DONNEES de la BASE *)
\r
342 (*-----------------------------------------------------*)
\r
343 UNIT DataFile :CLASS;
\r
344 VAR df :RFile; (* DESCRIPTEUR du FICHIER *)
\r
345 VAR FreePlace:INTEGER; (* POSITION du dernier EMPLACEMENT LIBRE *)
\r
347 (*-----------------------------------------------------------*)
\r
348 (* DEPLACEMENT de la POSITION de LECTURE du fichier au DEBUT *)
\r
349 (*-----------------------------------------------------------*)
\r
350 UNIT Reset:PROCEDURE;
\r
351 BEGIN CALL Fseek(df,1) END Reset;
\r
353 (*-------------------------------------------------*)
\r
354 (* AJOUT au fichier de DONNEES d'un enregistrement *)
\r
355 (*-------------------------------------------------*)
\r
356 UNIT AddRec : PROCEDURE(Rec :ARRAYOF INTEGER;OUTPUT DataRef :INTEGER);
\r
357 VAR AuxRec: ARRAYOF INTEGER; (* Tableau auxiliaire pour lire la Position
\r
358 du nouvel emplacement libre *)
\r
361 THEN (* AJOUT en FIN de fFICHIER *)
\r
362 DataRef:=FileLen(df);
\r
363 ELSE (* AJOUT a l'EMPLACEMENT LIBRE *)
\r
364 DataRef:=FreePlace;
\r
365 CALL Fseek(df,DataRef);
\r
366 ARRAY AuxRec dim(LOWER(Rec):UPPER(Rec));
\r
368 FreePlace:=AuxRec(1); (* NOUVEL EMPLACEMENT LIBRE *)
\r
370 (* ECRITURE de l'enregistrement *)
\r
371 CALL Fseek(df,DataRef);
\r
375 (*-------------------------------------------------------*)
\r
376 (* SUPPRESSION du fichier de DONNEES d'un enregistrement *)
\r
377 (*-------------------------------------------------------*)
\r
378 UNIT DelRec: PROCEDURE(DataRef :INTEGER);
\r
379 VAR AuxRec: ARRAYOF INTEGER;
\r
381 CALL Fseek(df,DataRef);
\r
382 ARRAY AuxRec dim (1:df.RecLen);
\r
383 AuxRec(1):=FreePlace;
\r
384 CALL Fput(df,AuxRec);
\r
385 FreePlace:=DataRef (* NOUVEL EMPLACEMENT LIBRE *)
\r
388 (*--------------------------------------------------------------*)
\r
389 (* RECHERCHE d'un ENREGISTREMENT dans le FICHIER de DONNEES *)
\r
390 (* renvoie sa Position dans le fichier ou -1 si il n'y est pas. *)
\r
391 (*--------------------------------------------------------------*)
\r
392 UNIT FindRec:PROCEDURE(Rec :ARRAYOF INTEGER;OUTPUT DataRef :INTEGER);
\r
393 VAR AuxRec: ARRAYOF INTEGER,
\r
397 ARRAY AuxRec DIM(LOWER(Rec):UPPER(Rec));
\r
399 WHILE (NOT Feof(df) AND NOT trouve)
\r
401 DataRef := Position(df);
\r
403 FOR i:=LOWER(AuxRec) TO UPPER(AuxRec)
\r
405 trouve := (AuxRec(i)=Rec(i));
\r
410 IF (trouve AND FreePlace <> 0)
\r
411 THEN (* RECHERCHE SI ce n'est pas un enregistrement EFFACE
\r
412 qui correspond au tuple *)
\r
414 WHILE NOT Place=0 (* POUR CHAQUE emplacement LIBRE *)
\r
417 THEN trouve := FALSE;
\r
419 ELSE CALL Fseek(df,Place);
\r
424 (* REPOSITIONNEMENT TETE de LECTURE *)
\r
425 CALL Fseek(df,DataRef+df.RecLen)
\r
429 THEN (* L'ENREGISTREMENT n'est pas dans le FICHIER *)
\r
435 FreePlace:=0 (* AUCUN EMPLACEMENT LIBRE a la creation *)
\r
438 (*-------------------------------------------------------*)
\r
439 (* MODULE GENERIQUE d'une relation de la BASE DE DONNEES *)
\r
440 (*-------------------------------------------------------*)
\r
441 UNIT Relation : DataFile CLASS ;
\r
442 VAR Indexs :ARRAYOF IndexFile; (* Tableau des INDEXs lies au fichier de
\r
444 (*---------------------------------*)
\r
445 (* CLASSE generique d'une RELATION *)
\r
446 (*---------------------------------*)
\r
447 UNIT Tuple : CLASS;
\r
450 (*-------------------------------------------------------*)
\r
451 (* FONCTION GENERIQUE de conversion d'une relation en *)
\r
452 (* TABLEAU d'ENTIERS pour la sauvegarde dans un fichier. *)
\r
453 (*-------------------------------------------------------*)
\r
454 UNIT VIRTUAL TupleToArray:FUNCTION(T: Tuple):ARRAYOF INTEGER;
\r
458 (*---------------------------------------------------------*)
\r
459 (* FONCTION GENERIQUE de conversion d'un tableau d'entiers *)
\r
460 (* en objet de type TUPLE. *)
\r
461 (*---------------------------------------------------------*)
\r
462 UNIT VIRTUAL ArrayToTuple : FUNCTION(A :ARRAYOF INTEGER):Tuple;
\r
465 (*--------------------------------------------*)
\r
466 (* INSERTION d'un TUPLE au FICHIER de DONNEES *)
\r
467 (*--------------------------------------------*)
\r
468 UNIT InsertTuple :PROCEDURE(T: Tuple);
\r
469 VAR AuxRec : ARRAYOF INTEGER,
\r
472 AuxRec := TupleToArray(T);
\r
473 (* AJOUT au FICHIER de DONNEES *)
\r
474 CALL AddRec(AuxRec,DataRef);
\r
476 THEN (* Pour chaque INDEX lie a la RELATION *)
\r
478 FOR i:=1 TO UPPER(Indexs)
\r
481 THEN (* AJOUT d'une NOUVELLE CLE *)
\r
482 CALL Indexs(i).AddKey(Indexs(i).KeyOf(T),DataRef)
\r
488 (*----------------------------------------------*)
\r
489 (* SUPPRESSION d'un TUPLE du FICHIER de DONNEES *)
\r
490 (*----------------------------------------------*)
\r
491 UNIT DeleteTuple :PROCEDURE(T: Tuple);
\r
492 VAR AuxRec :ARRAYOF INTEGER,
\r
493 i,DataRef :INTEGER;
\r
495 (* RECHERCHE de la POSITION du tuple dans la BASE a partir *)
\r
496 (* de l'INDEX PRIMAIRE Indexs(1). *)
\r
497 DataRef := Indexs(1).FindKey(Indexs(1).KeyOf(T));
\r
498 CALL Indexs(1).DelKey(Indexs(1).KeyOf(T),DataRef);
\r
499 (* LECTURE du TUPLE dans la BASE *)
\r
500 CALL Fseek(df,DataRef);
\r
501 AuxRec := Fget(df);
\r
502 (* SUPRESSION du tuple de la BASE *)
\r
503 CALL DelRec(DataRef);
\r
504 (* SUPPRESSION des differentes CLES dans les autres indexs *)
\r
505 FOR i:=UPPER(Indexs) DOWNTO 2
\r
507 CALL Indexs(i).DelKey(Indexs(i).KeyOf(T),DataRef)
\r
511 (*---------------------------------*)
\r
512 (* RECHERCHE d'un TUPLE de la BASE *)
\r
513 (*---------------------------------*)
\r
514 UNIT FindTuple :PROCEDURE(T: Tuple;OUTPUT Position : INTEGER);
\r
515 VAR AuxRec :ARRAYOF INTEGER,
\r
516 i,DataRef :INTEGER;
\r
518 AuxRec := TupleToArray(T);
\r
519 CALL FindRec(AuxRec,DataRef);
\r
520 Position := DataRef;
\r
523 (*-------------------------------------------------------------*)
\r
524 (* MODULE GENERIQUE d'un FICHIER d'INDEX de la BASE de DONNEES *)
\r
525 (* implemente sous forme de B ARBRE. *)
\r
526 (*-------------------------------------------------------------*)
\r
527 UNIT IndexFile:DataFile COROUTINE;
\r
529 (*---------------------------------------------------------------*)
\r
530 (* PAGE contenu dans le B ARBRE est qui est le type des ELEMENTS *)
\r
531 (* SAUVEGARDES sur le FICHIER. *)
\r
532 (*---------------------------------------------------------------*)
\r
534 VAR ItemsOnPage, (* NOMBRES de PAGES FILLES *)
\r
535 LessPageRef :INTEGER, (* POSITION dans le FICHIER de la PAGE des
\r
536 cles INFERIEURES a la PREMIERE cle de
\r
538 ItemsArray :ARRAYOF Item; (* TABLEAU des cles contenues dans cette
\r
541 ARRAY ItemsArray dim (1:PageSize)
\r
545 (*-------------------------------------------------------------*)
\r
546 (* FONCTION de CONVERSION d'un enregistrement du FICHIER INDEX *)
\r
547 (* en page du B-arbre correspondant. *)
\r
548 (*-------------------------------------------------------------*)
\r
549 UNIT RecToPage:FUNCTION(A :ARRAYOF INTEGER) :Page;
\r
555 P.ItemsOnPage,j := A(1);
\r
556 P.LessPageRef := A(2);
\r
557 ARRAY P.ItemsArray dim (1:PageSize);
\r
561 It.ky := RecToKey(A, 3+(i-1)*(KeySize+2) ) ;
\r
562 It.PageRef := A(i*(KeySize+2)+1);
\r
563 It.DataRef := A(i*(KeySize+2)+2);
\r
564 P.ItemsArray(i) := It;
\r
569 (*----------------------------------------------------------------*)
\r
570 (* FONCTION de CONVERSION d'une PAGE du B-ARBRE en enregistrement *)
\r
571 (* du FICHIER INDEX correspondant. *)
\r
572 (*----------------------------------------------------------------*)
\r
573 UNIT PageToRec : FUNCTION (P: Page): ARRAYOF INTEGER;
\r
574 VAR AuxRec : ARRAYOF INTEGER,
\r
578 ARRAY AuxRec dim(1:(PageSize*(KeySize+2)+2));
\r
579 AuxRec(1) := P.ItemsOnPage;
\r
580 AuxRec(2) := P.LessPageRef;
\r
581 FOR i := 1 TO P.ItemsOnPage
\r
583 It:=P.ItemsArray(i);
\r
584 CALL KeyToRec(It.ky,AuxRec, 3+(i-1)*(KeySize+2) );
\r
585 AuxRec(i*(KeySize+2)+1) := It.PageRef;
\r
586 AuxRec(i*(KeySize+2)+2) := It.DataRef;
\r
591 UNIT Item : CLASS ;
\r
592 VAR ky: key, (* CLE du tuple concerne *)
\r
593 PageRef, (* POSITION dans le FICHIER INDEX de la PAGE RACINE
\r
594 contenant les CLES SUPERIEURES a ce tuple ci *)
\r
595 DataRef :INTEGER; (* POSITION dans le FICHIER de DONNEES du tuple
\r
599 (*------------------------------------------------------------------*)
\r
600 (* MODULE GENERIQUE de CLE de TUPLE defini ulterieurement dans les *)
\r
601 (* classes heritantes. *)
\r
602 (*------------------------------------------------------------------*)
\r
606 VAR KeySize : INTEGER; (* Taille de la cle de Items *)
\r
608 (*--------------------------------------*)
\r
609 (* FONCTION GENERIQUE renvoyant pour un *)
\r
610 (* tuple donne la cle correspondante. *)
\r
611 (*--------------------------------------*)
\r
612 UNIT VIRTUAL KeyOf:FUNCTION(t :Tuple) :key; END KeyOf;
\r
614 (*------------------------------------------------------*)
\r
615 (* TEST de COMPARAISON GENERIQUE de deux cles de tuples *)
\r
616 (*------------------------------------------------------*)
\r
617 UNIT VIRTUAL Leq:FUNCTION(key1, key2 :key) :Boolean; END Leq;
\r
619 (*------------------------------------------------------------*)
\r
620 (* FONCTION GENERIQUE de TRANSFORMATION d'une serie d'entiers *)
\r
621 (* en la CLE correspondante. *)
\r
622 (*------------------------------------------------------------*)
\r
623 UNIT VIRTUAL RecToKey : FUNCTION(A :ARRAYOF INTEGER, j :INTEGER) :Key;
\r
624 BEGIN END RecToKey;
\r
626 (*---------------------------------------------------------*)
\r
627 (* FONCTION GENERIQUE de TRANSFORMATION d'une CLE de tuple *)
\r
628 (* en une serie d'entiers. *)
\r
629 (*---------------------------------------------------------*)
\r
630 UNIT VIRTUAL KeyToRec:PROCEDURE(ky :Key, A :ARRAYOF INTEGER, j :INTEGER);
\r
631 BEGIN END KeyToRec;
\r
633 UNIT SearchStep: CLASS;
\r
634 VAR PageRef,RefOnPage : INTEGER,
\r
638 VAR StackOfPages: ARRAYOF Page, (* Pile de Pages *)
\r
639 Finger: INTEGER, (* Indice *)
\r
640 Path: ARRAYOF SearchStep,
\r
641 AuxRec : ARRAYOF INTEGER,
\r
645 (*------------------------------------------------------------------*)
\r
646 (* INSERTION de la cle ky au FICHIER d'INDEX, DataRef correspondant *)
\r
647 (* a la Position du tuple dans le fichier de donnees. *)
\r
648 (*------------------------------------------------------------------*)
\r
649 UNIT AddKey:PROCEDURE(INPUT ky:key,DataRef:INTEGER);
\r
653 AddItem, AuxItem, itm2 : Item,
\r
654 IncreaseHeight : BOOLEAN,
\r
656 AuxRec : ARRAYOF INTEGER;
\r
658 UNIT Search : PROCEDURE (INPUT itm1 : Item, PageRef:INTEGER;
\r
659 OUTPUT include : BOOLEAN, itm2 :Item);
\r
666 UNIT Insert : PROCEDURE;
\r
667 VAR OldPage, RightPage : Page,
\r
668 AuxRec : ARRAYOF INTEGER,
\r
669 AuxItmArr, AuxItmArr2 : ARRAYOF Item,
\r
670 RightPageRef, i : INTEGER;
\r
672 OldPage := StackOfPages(Finger);
\r
673 IF OldPage.ItemsOnPage < PageSize
\r
674 THEN CALL UpdatePage (item2, ItemRef, OldPage);
\r
675 Path(Finger).RefOnPage := ItemRef + 1;
\r
677 ELSE include := TRUE;
\r
678 OldPage.ItemsOnPage := HalfPageSize;
\r
679 Path(Finger).updated := TRUE;
\r
680 RightPage := NEW Page;
\r
681 RightPage.ItemsOnPage := HalfPageSize;
\r
682 ARRAY RightPage.ItemsArray dim (1:PageSize);
\r
683 AuxItmArr := OldPage.ItemsArray;
\r
684 AuxItmArr2 := RightPage.ItemsArray;
\r
685 IF ItemRef = HalfPageSize
\r
686 THEN FOR i := 1 to HalfPageSize
\r
688 AuxItmArr2(i):=AuxItmArr(i+HalfPageSize)
\r
691 ELSE IF ItemRef < HalfPageSize
\r
692 THEN FOR i := 1 TO HalfPageSize
\r
694 AuxItmArr2(i) := AuxItmArr(i+HalfPageSize)
\r
696 itm2 := AuxItmArr(HalfPageSize);
\r
697 FOR i := HalfPageSize-1 DOWNTO ItemRef+1
\r
699 AuxItmArr(i+1) := AuxItmArr(i)
\r
701 AuxItmArr(ItemRef+1) := item2;
\r
702 ELSE itm2 := AuxItmArr(HalfPageSize+1);
\r
703 FOR i := HalfPageSize+2 TO ItemRef
\r
705 AuxItmArr2(i-HalfPageSize-1) :=
\r
708 AuxItmArr2(ItemRef-HalfPageSize) := item2;
\r
709 FOR i := ItemRef+1 TO PageSize
\r
711 AuxItmArr2(i-HalfPageSize) := AuxItmArr(i)
\r
715 (* StackOfPages(finger) := OldPage; *)
\r
716 CALL Fseek(df,Path(Finger).PageRef);
\r
717 CALL Fput(df,PageToRec(StackOfPages(Finger)));
\r
718 RightPage.LessPageRef := itm2.PageRef;
\r
719 AuxRec :=PageToRec(RightPage);
\r
720 CALL AddRec(AuxRec,RightPageRef);
\r
721 itm2.PageRef :=RightPageRef;
\r
727 THEN include := TRUE;
\r
729 itm2.PageRef := -1;
\r
730 ELSE Finger, depth := Finger+1;
\r
731 CALL GetPage (PageRef);
\r
732 AuxPage := StackOfPages (Finger);
\r
733 CALL SearchPage (AuxPage, itm1, NextPageRef, ItemRef);
\r
734 CALL Search(itm1, NextPageRef, include, item2);
\r
738 Finger := Finger -1;
\r
743 Path(1).updated := TRUE;
\r
744 AuxItem := NEW Item;
\r
746 AuxItem.DataRef := DataRef;
\r
747 AuxItem.PageRef := -1;
\r
749 CALL Search(AuxItem, Path(1).PageRef,
\r
750 IncreaseHeight, AddItem);
\r
752 THEN NewRoot := NEW Page;
\r
753 NewRoot.ItemsOnPage := 1;
\r
754 NewRoot.LessPageRef := Path(1).PageRef;
\r
755 ARRAY NewRoot.ItemsArray dim (1:PageSize);
\r
756 NewRoot.ItemsArray(1) := AddItem;
\r
757 IF depth+1 > TreeHeight
\r
758 THEN RAISE TreeHeight_Overflow
\r
760 FOR i := 1 TO depth
\r
762 StackOfPages(i+1) := StackOfPages(i);
\r
763 Path(i+1) := Path(i);
\r
765 StackOfPages(1) := NewRoot;
\r
766 Path(1) := NEW SearchStep;
\r
767 Path(1).RefOnPage := 1;
\r
768 Path(1).updated := TRUE;
\r
769 AuxRec :=PageToRec(NewRoot);
\r
770 CALL AddRec(AuxRec, PageRef);
\r
771 Path(1).PageRef := PageRef;
\r
773 ELSE Finger := depth
\r
774 FI (* IncreaseHeight *);
\r
777 (*-------------------------------------------------------------------*)
\r
778 (* RECHERCHE de la cle Ky IMMEDIATEMENT INFERIEURE a la CLE indique *)
\r
779 (* par Path, DataRef correspond a la POSITION du TUPLE associe a la *)
\r
780 (* CLE dans le fichier de donnees. *)
\r
781 (*-------------------------------------------------------------------*)
\r
782 UNIT PrevKey : PROCEDURE (OUTPUT ky:key, DataRef:INTEGER);
\r
783 VAR AuxPage : Page, AuxRec : ARRAYOF INTEGER,
\r
784 PageRef, NextPageRef, RefOnPage : INTEGER;
\r
786 RefOnPage := Path(Finger).RefOnPage;
\r
787 PageRef:=Path(Finger).PageRef;
\r
788 AuxPage:=StackOfPages(Finger);
\r
789 IF AuxPage.LessPageRef = -1
\r
790 THEN IF RefOnPage <> 1
\r
791 THEN RefOnPage := RefOnPage -1;
\r
792 Path(Finger).RefOnPage := RefOnPage
\r
794 THEN ky:=AuxPage.ItemsArray(RefOnPage).ky;
\r
795 DataRef:=AuxPage.ItemsArray(RefOnPage).DataRef;
\r
798 ELSE RefOnPage := 0;
\r
799 WHILE Finger <> 1 AND RefOnPage = 0
\r
801 Finger := Finger-1;
\r
802 Auxpage := StackOfPages(Finger);
\r
803 RefOnPage := Path(Finger).RefOnPage
\r
805 IF Finger = 1 AND RefOnPage = 0
\r
806 THEN ky:=AuxPage.ItemsArray(1).ky;
\r
807 DataRef:=AuxPage.ItemsArray(1).DataRef;
\r
812 FI (* RefOnPage <> 1 *);
\r
813 ELSE IF RefOnPage = 1
\r
814 THEN NextPageRef := AuxPage.LessPageRef;
\r
815 Path(Finger).RefOnPage := 0
\r
816 ELSE RefOnPage := RefOnPage -1;
\r
817 NextPageRef := AuxPage.ItemsArray(RefOnPage).PageRef;
\r
818 Path(Finger).RefOnPage := RefOnPage
\r
820 WHILE NextPageRef <> -1
\r
822 Finger := Finger +1;
\r
823 PageRef := NextPageRef;
\r
824 CALL GetPage(PageRef);
\r
825 AuxPage := StackOfPages(Finger);
\r
826 RefOnPage, Path(Finger).RefOnPage := Auxpage.ItemsOnPage;
\r
827 NextPageRef := AuxPage.ItemsArray(RefOnPage).PageRef
\r
830 ky:=AuxPage.ItemsArray(RefOnPage).ky;
\r
831 DataRef:=AuxPage.ItemsArray(RefOnPage).DataRef
\r
833 (*-----------------------------------------------------*)
\r
834 (* RECHERCHE de la CLE la plus petite du fichier INDEX *)
\r
835 (*-----------------------------------------------------*)
\r
836 UNIT MinKey : PROCEDURE (OUTPUT k:Key, DataRef : INTEGER);
\r
837 VAR PageRef : INTEGER, AuxPage : Page, AuxItem : Item;
\r
841 AuxPage := StackOfPages(Finger);
\r
842 PageRef := AuxPage.LessPageRef;
\r
843 Path(Finger).RefOnPage := 0;
\r
844 IF PageRef = -1 THEN EXIT FI;
\r
845 Finger := Finger +1;
\r
846 CALL GetPage(PageRef);
\r
848 AuxItem := AuxPage.ItemsArray(1);
\r
850 DataRef := AuxItem.DataRef;
\r
851 Path(Finger).RefOnPage := 1
\r
854 UNIT MaxKey : PROCEDURE( OUTPUT k:Key, DataRef: INTEGER);
\r
855 VAR PageRef, n : INTEGER,
\r
860 AuxPage := StackOfPages(Finger);
\r
861 Path(Finger).RefOnPage, n := AuxPage.ItemsOnPage;
\r
862 PageRef := AuxPage.ItemsArray(n).PageRef;
\r
863 IF PageRef = -1 THEN EXIT FI;
\r
864 Finger := Finger+1;
\r
865 CALL GetPage(PageRef)
\r
867 k := AuxPage.ItemsArray(n).Ky;
\r
868 DataRef := AuxPage.ItemsArray(n).DataRef
\r
871 (*-------------------------------------------------------------------*)
\r
872 (* RECHERCHE de la cle Ky IMMEDIATEMENT SUPERIEURE a la cle indique *)
\r
873 (* par Path, DataRef correspond a la Position du tuple associe a la *)
\r
874 (* cle dans le fichier de donnees. *)
\r
875 (*-------------------------------------------------------------------*)
\r
876 UNIT NextKey: PROCEDURE (OUTPUT ky:key,DataRef:INTEGER);
\r
877 VAR AuxPage : Page,
\r
879 PageRef,NextPageRef,
\r
880 RefOnPage : INTEGER;
\r
882 RefOnPage := Path(Finger).RefOnPage;
\r
883 PageRef := Path(Finger).PageRef;
\r
884 AuxPage:=StackOfPages(Finger);
\r
885 IF AuxPage.LessPageRef = -1
\r
886 THEN WHILE Finger <> 1 AND RefOnPage = AuxPage.ItemsOnPage
\r
888 Finger := Finger - 1;
\r
889 AuxPage := StackOfPages(Finger);
\r
890 RefOnPage := Path(Finger).refOnPage
\r
892 IF RefOnPage = AuxPage.ItemsOnPage
\r
893 THEN AuxItem := AuxPage.ItemsArray(RefOnPage);
\r
894 DataRef := AuxItem.DataRef;
\r
898 ELSE RefOnPage := RefOnPage+1;
\r
899 Path(Finger).RefOnPage := RefOnPage
\r
901 ELSE NextPageRef := AuxPage.ItemsArray(RefOnPage).PageRef;
\r
902 WHILE NextPageRef <> -1
\r
904 Finger := Finger+1;
\r
905 PageRef := NextPageRef;
\r
906 CALL GetPage(PageRef);
\r
907 AuxPage := StackOfPages(Finger);
\r
908 Path(Finger).refOnPage := 0;
\r
909 NextPageRef := AuxPage.LesspageRef
\r
912 Path(Finger).RefOnPage := 1
\r
914 AuxItem := AuxPage.ItemsArray(RefOnPage);
\r
915 DataRef := AuxItem.DataRef;
\r
919 (*--------------------------------------------------------------------*)
\r
920 (* SUPPRESSION de la cle ky au FICHIER d'INDEX, DataRef correspondant *)
\r
921 (* a la Position du tuple dans le fichier de donnees. *)
\r
922 (*--------------------------------------------------------------------*)
\r
923 UNIT DelKey : PROCEDURE (INPUT ky:key,DataRef:INTEGER);
\r
924 VAR DataRef1: INTEGER,
\r
928 UNIT remove : PROCEDURE(OUTPUT underflw:BOOLEAN);
\r
929 VAR AuxPage,AuxPage1 :Page,
\r
930 i,ItemsOnPage,RefOnPage,NextPageRef :INTEGER;
\r
932 AuxPage:=StackOfPages(Finger);
\r
934 Path(Finger).updated:=TRUE;
\r
935 RefOnPage := Path(Finger).RefOnPage;
\r
937 IF AuxPage.LessPageRef <> -1
\r
938 THEN NextPageRef :=
\r
939 AuxPage.ItemsArray(RefOnPage).PageRef;
\r
940 WHILE NextPageRef <> -1
\r
942 Finger := Finger+1;
\r
943 CALL GetPage(NextPageRef);
\r
944 AuxPage1 := StackOfPages(Finger);
\r
945 Path(Finger).RefOnPage := 0;
\r
946 NextPageRef := AuxPage1.LessPageRef
\r
948 Path(Finger).updated:=TRUE;
\r
949 Path(Finger).RefOnPage := 1;
\r
950 AuxPage.ItemsArray(RefOnPage).ky := AuxPage1.ItemsArray(1).ky;
\r
951 AuxPage.ItemsArray(RefOnPage).DataRef:=
\r
952 AuxPage1.ItemsArray(1).DataRef;
\r
953 StackOfPages(i):=AuxPage;
\r
954 AuxPage:= AuxPage1;
\r
957 ItemsOnPage:= AuxPage.ItemsOnPage -1;
\r
958 FOR i:=RefOnPage TO ItemsOnPage
\r
960 AuxPage.ItemsArray(i):=AuxPage.ItemsArray(i+1)
\r
962 AuxPage.ItemsOnPage:= ItemsOnPage;
\r
963 StackOfPages(Finger):=AuxPage;
\r
964 IF ItemsOnPage<HalfPageSize
\r
965 THEN underflw:=TRUE
\r
969 UNIT underflow: PROCEDURE(inout underflw:BOOLEAN);
\r
971 AuxPage,AuxPage1, AuxPage2:Page,
\r
972 i,k,n,pb,lb,PageRef,RefOnPage: INTEGER,
\r
973 AuxRec: ARRAYOF INTEGER;
\r
975 writeln("underflow",Finger);
\r
978 THEN AuxPage:=StackOfPages(Finger);
\r
979 Path(Finger).updated:=TRUE ;
\r
980 Path(Finger-1).updated:=TRUE ;
\r
981 AuxPage1:=StackOfPages(Finger-1);
\r
982 RefOnPage:=Path(Finger-1).RefOnPage;
\r
983 IF RefOnPage< AuxPage1.ItemsOnPage
\r
984 THEN k:=RefOnPage+1;
\r
985 Itm:=AuxPage1.ItemsArray(k);
\r
986 PageRef:=Itm.PageRef;
\r
987 CALL Fseek(df,PageRef);
\r
989 AuxPage2:=RecToPage(AuxRec);
\r
990 Itm.PageRef:=AuxPage2.LessPageRef;
\r
991 AuxPage.ItemsArray(AuxPage.ItemsOnPage+1):=Itm;
\r
992 n:=AuxPage2.ItemsOnPage-HalfPageSize;
\r
994 THEN n:=entier((n-1)/2);
\r
995 Itm:=AuxPage2.ItemsArray(n+1);
\r
996 Itm.PageRef:=PageRef;
\r
997 AuxPage1.ItemsArray(k):=Itm;
\r
1000 AuxPage.ItemsArray(HalfPageSize+i):=
\r
1001 AuxPage2.ItemsArray(i)
\r
1003 AuxPage.ItemsOnPage:=HalfPageSize+n;
\r
1004 StackOfPages(Finger):=AuxPage;
\r
1005 StackOfPages(Finger-1):=AuxPage1;
\r
1006 k:=AuxPage2.ItemsOnPage-(n+1);
\r
1009 AuxPage2.ItemsArray(i):=
\r
1010 AuxPage2.ItemsArray(n+1+i)
\r
1012 AuxPage2.ItemsOnPage:=k;
\r
1013 AuxRec:=PageToRec(AuxPage2);
\r
1014 CALL Fseek(df,PageRef);
\r
1015 CALL Fput(df,AuxRec);
\r
1016 ELSE (*AuxPage2.ItemsOnPage=HalfPageSize tzn. n=0*)
\r
1017 FOR i:=1 TO HalfPageSize
\r
1019 AuxPage.ItemsArray(HalfPageSize+i):=
\r
1020 AuxPage2.ItemsArray(i)
\r
1022 AuxPage.ItemsOnPage:=PageSize;
\r
1023 FOR i:=RefOnPage+2 TO AuxPage1.ItemsOnPage
\r
1025 AuxPage1.ItemsArray(i-1):=
\r
1026 AuxPage1.ItemsArray(i)
\r
1028 AuxPage1.ItemsOnPage:=AuxPage1.ItemsOnPage-1;
\r
1029 StackOfPages(Finger-1):=AuxPage1;
\r
1030 StackOfPages(Finger):=AuxPage;
\r
1031 CALL DelRec(PageRef);
\r
1032 IF AuxPage1.ItemsOnPage<HalfPageSize
\r
1033 THEN Finger:=Finger-1;
\r
1037 ELSE IF RefOnPage>1
\r
1038 THEN Itm:=AuxPage1.ItemsArray(RefOnPage-1);
\r
1039 PageRef:=Itm.PageRef;
\r
1040 ELSE PageRef:=AuxPage1.LessPageRef;
\r
1042 CALL Fseek(df,PageRef);
\r
1044 AuxPage2:=RecToPage(AuxRec);
\r
1045 Itm:=AuxPage1.ItemsArray(RefOnPage);
\r
1046 Itm.PageRef:=AuxPage.LessPageRef;
\r
1047 n:=AuxPage2.ItemsOnPage-HalfPageSize;
\r
1049 THEN n:=entier((n-1)/2);
\r
1050 k:=AuxPage.ItemsOnPage;
\r
1053 AuxPage.ItemsArray(k+n+2-i):=
\r
1054 AuxPage.ItemsArray(k+1-i)
\r
1056 AuxPage.ItemsArray(n+1):=Itm;
\r
1057 AuxPage.ItemsOnPage:=k+n+1;
\r
1058 Itm:=AuxPage2.ItemsArray(HalfPageSize+n+1);
\r
1059 Itm.PageRef:=PageRef;
\r
1060 AuxPage1.ItemsArray(RefOnPage):=Itm;
\r
1063 AuxPage.ItemsArray(i):=
\r
1064 AuxPage2.ItemsArray(HalfPageSize+1+i+n)
\r
1066 AuxPage.ItemsOnPage:=HalfPageSize+n;
\r
1067 AuxPage2.ItemsOnPage:= HalfPageSize+n;
\r
1068 StackOfPages(Finger-1):=AuxPage1;
\r
1069 StackOfPages(Finger):=AuxPage;
\r
1070 AuxRec:=PageToRec(AuxPage2);
\r
1071 CALL Fseek(df,PageRef);
\r
1072 CALL Fput(df,AuxRec);
\r
1073 ELSE AuxPage2.ItemsArray(HalfPageSize+1):=Itm;
\r
1074 FOR i:=1 TO HalfPageSize-1
\r
1075 DO AuxPage2.ItemsArray(HalfPageSize+1+i):=
\r
1076 AuxPage.ItemsArray(i)
\r
1078 AuxPage1.ItemsOnPage:=AuxPage1.ItemsOnPage-1;
\r
1079 AuxPage2.ItemsOnPage:=PageSize;
\r
1080 StackOfPages(Finger-1):=AuxPage1;
\r
1081 StackOfPages(Finger):=AuxPage2;
\r
1082 Path(Finger-1).RefOnPage:=RefOnPage-1;
\r
1083 CALL DelRec(Path(Finger).PageRef);
\r
1084 Path(Finger).PageRef:=PageRef;
\r
1085 IF AuxPage1.ItemsOnPage<HalfPageSize
\r
1086 THEN Finger:=Finger-1;
\r
1091 ELSE AuxPage:=StackOfPages(1);
\r
1092 IF AuxPage.ItemsOnPage=0
\r
1093 THEN CALL DelRec(Path(1).PageRef);
\r
1094 IF AuxPage.LessPageRef<>-1
\r
1096 WHILE Path(i)<>NONE
\r
1098 Path(i-1):=Path(i);
\r
1099 StackOfPages(i-1):=StackOfPages(i);
\r
1102 ELSE writeln("erreur1");
\r
1110 DataRef1:=FindKey(k);
\r
1112 IF k=ky AND DataRef=DataRef1
\r
1113 THEN CALL remove(underflw);
\r
1116 CALL underflow(underflw)
\r
1119 ELSE IF k<>ky or DataRef1= -1
\r
1120 THEN writeln("erreur2")
\r
1121 ELSE CALL NextKey(k,DataRef1)
\r
1128 UNIT FindKey:FUNCTION (k : key): INTEGER;
\r
1132 Itms : ARRAYOF Item,
\r
1136 PageRef := Path(Finger).PageRef;
\r
1138 CALL GetPage( PageRef );
\r
1139 AuxPage := StackOfPages(Finger);
\r
1140 Itms := AuxPage.ItemsArray;
\r
1141 FOR i := AuxPage.ItemsOnPage DOWNTO 1
\r
1145 THEN Path(Finger).RefOnPage := i;
\r
1147 THEN RESULT := Itms(i).DataRef;
\r
1150 PageRef := Itms(i).PageRef;
\r
1153 THEN PageRef := AuxPage.LessPageRef;
\r
1154 Path(Finger).RefOnPage := 0;
\r
1159 THEN IF Path(Finger).RefOnPage = 0
\r
1160 THEN Path(Finger).RefOnPage :=1
\r
1164 ELSE Finger := Finger+1
\r
1169 UNIT SearchKey: PROCEDURE(INPUT k:key;OUTPUT DataRef : INTEGER);
\r
1171 DataRef := FindKey(k);
\r
1173 THEN CALL NextKey(k,DataRef)
\r
1177 UNIT GetPage : PROCEDURE(PageRef : INTEGER);
\r
1178 VAR AuxRec : ARRAYOF INTEGER;
\r
1180 IF Path(Finger) = NONE
\r
1181 THEN Path(Finger) := NEW SearchStep;
\r
1182 Path(Finger).Updated := FALSE;
\r
1183 Path(Finger).PageRef := PageRef-1;
\r
1185 IF Path(Finger).Updated
\r
1186 THEN AuxRec := PageToRec(StackOfPages(Finger));
\r
1187 CALL Fseek(df, Path(Finger).PageRef);
\r
1188 CALL Fput(df,AuxRec);
\r
1190 CALL Fseek(df, PageRef);
\r
1191 AuxRec := Fget(df);
\r
1192 StackOfPages(Finger) := RecToPage(AuxRec);
\r
1193 Path(Finger) := NEW SearchStep;
\r
1194 Path(Finger).PageRef := PageRef;
\r
1195 Path(Finger).updated := FALSE;
\r
1198 UNIT UpdatePage : PROCEDURE (INPUT AuxItem : Item, ItemRef : INTEGER,
\r
1200 VAR AuxItmArr : ARRAYOF Item,
\r
1203 AuxPage.ItemsOnPage, n := AuxPage.ItemsOnPage +1;
\r
1204 FOR i := n DOWNTO ItemRef +2
\r
1206 AuxItmArr := AuxPage.ItemsArray;
\r
1207 AuxItmArr(i) := AuxItmArr(i-1)
\r
1209 AuxPage.ItemsArray(ItemRef+1) := AuxItem;
\r
1210 Path(Finger).Updated := TRUE;
\r
1213 UNIT order : FUNCTION (i1, i2 : Item) : BOOLEAN;
\r
1220 THEN IF Leq(k1, k2)
\r
1221 THEN n := i1.DataRef - i2.DataRef;
\r
1223 THEN RAISE Signal14
\r
1226 ELSE RESULT := FALSE
\r
1228 ELSE IF NOT Leq(k1, k2)
\r
1230 ELSE RESULT := TRUE
\r
1235 UNIT SearchPage : PROCEDURE (INPUT P :Page, it :Item;
\r
1236 OUTPUT NextPageRef, ItemRef :INTEGER);
\r
1237 VAR Itms : ARRAYOF Item,
\r
1240 Itms :=P.ItemsArray;
\r
1241 FOR ItemRef := P.ItemsOnPage DOWNTO 1
\r
1243 it1 := Itms(ItemRef);
\r
1245 THEN NextPageRef := it1.PageRef;
\r
1250 NextPageRef := P.LessPageRef;
\r
1253 BEGIN (*IndexFile*)
\r
1255 ARRAY StackOfPages dim(1:TreeHeight);
\r
1256 ARRAY Path dim (1:TreeHeight);
\r
1257 StackOfPages(1) := NEW Page;
\r
1258 StackOfPages(1).ItemsOnPage := 0;
\r
1259 StackOfPages(1).LessPageRef := -1;
\r
1260 ARRAY StackOfPages(1).ItemsArray dim (1: PageSize);
\r
1261 Path(1):= NEW SearchStep;
\r
1262 Path(1).PageRef := 1;
\r
1263 Path(1).RefOnPage := 0;
\r
1266 END HandlerOfRelations;
\r
1270 PREF HandlerOfRelations(4,8,2) BLOCK
\r
1272 CONST (* couleur: la definition de ces couleurs varie avec le mode
\82cran *)
\r
1273 (* il est possible celles ci ne corespondent pas
\85 leurs d
\82finition *)
\r
1274 Noir = 0, Rouge = 1, Vert = 2, Jaune = 3, Bleu = 4, Magenta = 5,
\r
1275 Cyan = 6, Blanc = 7,
\r
1276 (* attribut carateres *)
\r
1277 Normal = 0, Gras = 1, Clignotant = 5, Inverse = 7, Cache = 8,
\r
1278 (* code retour clavier *)
\r
1279 Fgauche = -75, Fdroite = -77,Fhaut = -72, Fbas = -80,
\r
1280 ESC = 27, RETOUR = 13, BKSPACE = 8;
\r
1282 (* definition des procedures
\82cran et clavier *)
\r
1284 (*detection d'une touche *)
\r
1285 UNIT inchar : IIuwgraph FUNCTION : INTEGER;
\r
1288 DO RESULT := inkey; IF RESULT =/= 0 THEN EXIT FI OD;
\r
1291 (*efface l'
\82cran et place le curseur en position (1,1) *)
\r
1292 UNIT cls : PROCEDURE;
\r
1294 write( CHR(27),"[2J");
\r
1298 (* positionne le curseur en colonne x et ligne y *)
\r
1299 UNIT GotoXY : PROCEDURE(x, y: INTEGER);
\r
1300 VAR a,b,c,d : CHAR, i,j : INTEGER;
\r
1302 i := y DIV 10; j := y MOD 10; a := CHR(48+i); b := CHR(48+j);
\r
1303 i := x DIV 10; j := x mod 10; c := CHR(48+i); d := CHR(48+j);
\r
1304 write(CHR(27),"[",a,b,";",c,d,"H")
\r
1307 (* definition des couleurs du caracteres et du fon *)
\r
1308 UNIT SetColor : PROCEDURE(font,back : INTEGER);
\r
1310 write(CHR(27),"[","3",CHR(48+font),";4",CHR(48+back),"m");
\r
1313 UNIT Text_attr : PROCEDURE(Plus, Attr : INTEGER);
\r
1315 IF (Plus = 0) THEN write(CHR(27),"[0m") FI;
\r
1316 write(CHR(27),"[",CHR(48+Attr),"m");
\r
1322 (* classe de base d'affichage d'une fiche
\85 l'
\82cran *)
\r
1324 UNIT Base_Fiche : CLASS;
\r
1325 VAR Titre :STRING;
\r
1327 UNIT VIRTUAL Touche_Aff : PROCEDURE;
\r
1331 UNIT Affiche : PROCEDURE; (* procedure d'affichage de la base graphique *)
\r
1332 (* permetant la saisie comme la consultation *)
\r
1334 CALL setcolor(cyan,bleu);
\r
1335 CALL GotoXY(10,5);
\r
1336 (* taille du titre: 20 caracteres *)
\r
1337 write(" ",titre," ");
\r
1338 CALL GotoXY(10,6);
\r
1340 CALL setcolor(vert,bleu);
\r
1341 CALL GotoXY(10,7);
\r
1342 write(" Auteur : ");
\r
1343 CALL GotoXY(10,8);
\r
1344 write(" Titre : ");
\r
1345 CALL GotoXY(10,9);
\r
1346 write(" Editeur: ");
\r
1347 CALL GotoXY(10,10);
\r
1348 write(" Annee : ");
\r
1349 CALL GotoXY(10,11);
\r
1350 write(" Sujet : ");
\r
1351 CALL GotoXY(10,12);
\r
1352 write(" NøInv : ");
\r
1353 CALL GotoXY(10,13);
\r
1355 CALL GotoXY(10,14);
\r
1356 CALL setcolor(rouge,bleu);
\r
1358 CALL GotoXY(10,15);
\r
1366 UNIT Fiche_Cons : Base_Fiche CLASS;
\r
1368 UNIT VIRTUAL Touche_Aff : PROCEDURE;
\r
1369 BEGIN END Touche_Aff;
\r
1371 UNIT Put_Champs :PROCEDURE;
\r
1373 IF (L.INV.Ak = NONE)
\r
1376 CALL Put_Chaine(20,7,L.INV.AutLeng,L.INV.Ak.Author);
\r
1377 CALL Put_Chaine(20,8,L.INV.TitLeng,L.INV.Ak.Title);
\r
1378 CALL Put_Chaine(20,9,L.INV.PubLeng,L.INV.Ak.Publisher);
\r
1379 CALL Put_Entier(20,10,4,L.INV.Ak.Year);
\r
1380 CALL Put_Chaine(20,11,L.INV.SubjLeng,L.INV.Ak.Subject);
\r
1381 CALL Put_Entier(20,12,5,L.INV.Ak.NoInv);
\r
1385 Titre := " CONSULTATION LIVRE ";
\r
1390 UNIT Fiche_Saisie : Base_Fiche CLASS;
\r
1392 UNIT VIRTUAL Touche_Aff : PROCEDURE;
\r
1394 write(" [
\11ÄÙ]: Validation. [Esc]: Abandon de la saisie. ");
\r
1397 UNIT Read_Champs :FUNCTION : BOOLEAN;
\r
1398 VAR Code_Saisie : INTEGER;
\r
1401 CALL say("Entrer le Nom de l'Auteur");
\r
1403 Code_Saisie := Read_Chaine(20,7,L.INV.AutLeng,L.INV.Ak.Author);
\r
1404 IF Code_Saisie = 1
\r
1406 ELSE IF Code_Saisie = 2
\r
1408 "Saisie Obligatoire du nom de l'auteur");
\r
1409 write(CHR(7),CHR(7));
\r
1414 CALL say("Entrer le Titre du livre");
\r
1416 Code_Saisie := Read_Chaine(20,8,L.INV.TitLeng,L.INV.Ak.Title);
\r
1417 IF Code_Saisie = 1
\r
1419 ELSE IF Code_Saisie = 2
\r
1421 "Saisie Obligatoire du titre de l'oeuvre");
\r
1422 write(CHR(7),CHR(7));
\r
1427 CALL say("Entrer le Nom de l'Editeur");
\r
1429 Code_Saisie := Read_Chaine(20,9,L.INV.PubLeng,L.INV.Ak.Publisher);
\r
1430 IF Code_Saisie = 1
\r
1432 ELSE IF Code_Saisie = 2
\r
1434 "Saisie Obligatoire du Nom de l'Editeur !");
\r
1435 write(CHR(7),CHR(7));
\r
1440 CALL say("Entrer l'Annee de Parution de l'Oeuvre");
\r
1442 Code_Saisie := Read_Entier(20,10,4);
\r
1443 IF Code_saisie = -1
\r
1445 ELSE IF Code_Saisie = -2
\r
1447 "Saisie Obligatoire de l'annee de parution !");
\r
1448 write(CHR(7),CHR(7));
\r
1449 ELSE L.INV.Ak.Year := Code_Saisie;
\r
1454 CALL say("Entrer le Theme de l'Oeuvre");
\r
1456 Code_Saisie := Read_Chaine(20,11,L.INV.SubjLeng,L.INV.Ak.Subject);
\r
1457 IF Code_saisie = 1
\r
1459 ELSE IF Code_Saisie = 2
\r
1461 "Saisie Obligatoire du Theme de l'oeuvre !");
\r
1462 write(CHR(7),CHR(7));
\r
1467 CALL say("Entrer le Numero d'inventaire du livre");
\r
1469 Code_Saisie := Read_Entier(20,12,5);
\r
1470 IF Code_saisie = -1
\r
1472 ELSE IF Code_Saisie = -2
\r
1474 "Saisie Obligatoire du Nø Inventaire !");
\r
1475 write(CHR(7),CHR(7));
\r
1476 ELSE L.INV.Ak.NoInv := Code_Saisie;
\r
1483 IF Code_Saisie = 0 THEN RESULT := TRUE FI;
\r
1487 Titre := " FICHE SAISIE LIVRE ";
\r
1489 ok := Read_Champs;
\r
1492 UNIT Read_Entier : FUNCTION(x,y,longueur : INTEGER) : INTEGER;
\r
1493 VAR val : INTEGER;
\r
1495 CALL Text_Attr(0,Gras);
\r
1497 FOR i := 1 TO longueur
\r
1502 CALL Text_Attr(0,Inverse);
\r
1506 CALL GotoXY(x+i,y);
\r
1508 WHEN ESC : RESULT := -1;
\r
1510 WHEN RETOUR : IF i = 0
\r
1511 THEN RESULT := -2;
\r
1515 FGauche : IF (i = 0)
\r
1516 THEN write(CHR(7))
\r
1518 CALL Text_Attr(0,Gras);
\r
1519 CALL GotoXY(x+i,y);
\r
1521 CALL Text_Attr(0,Inverse);
\r
1522 RESULT := ENTIER(RESULT / 10)
\r
1524 OTHERWISE IF (i = longueur)
\r
1525 THEN write(CHR(7))
\r
1526 ELSE IF (val > 47 AND val < 58)
\r
1527 THEN write(CHR(val));
\r
1529 RESULT := RESULT* 10 + (val - 48);
\r
1530 ELSE write(CHR(7));
\r
1537 UNIT Put_Entier : PROCEDURE(x,y,longueur : INTEGER;val : INTEGER);
\r
1540 CALL Text_Attr(0,Gras); CALL GotoXY(x,y);
\r
1541 FOR i := 1 TO longueur DO write("Û") OD;
\r
1542 longueur := longueur - 1;
\r
1543 CALL GotoXY(x+longueur,y);
\r
1544 CALL Text_Attr(0,Inverse);
\r
1546 c := CHR(48+(val MOD 10));
\r
1548 longueur := longueur - 1;
\r
1549 CALL GotoXY(x+longueur,y);
\r
1550 val := val DIV 10;
\r
1551 IF val = 0 THEN EXIT FI;
\r
1555 UNIT Read_Chaine : FUNCTION(x,y,longueur :INTEGER;
\r
1556 OUTPUT ch : ARRAYOF CHAR) : INTEGER;
\r
1559 ARRAY ch DIM (1:longueur);
\r
1560 CALL Text_Attr(0,Gras);
\r
1562 FOR i := 1 TO longueur DO
\r
1566 CALL Text_Attr(0,Inverse);
\r
1570 CALL GotoXY(x+i,y);
\r
1572 WHEN ESC : RESULT := 1;
\r
1574 WHEN RETOUR : IF i = 0
\r
1579 FGauche : IF (i = 0)
\r
1580 THEN write(CHR(7))
\r
1582 CALL Text_Attr(0,Gras);
\r
1583 CALL GotoXY(x+i,y);
\r
1585 CALL Text_Attr(0,Inverse)
\r
1587 WHEN Fdroite : IF (i = longueur - 1)
\r
1588 THEN write(CHR(7))
\r
1589 ELSE write(CHR(32));
\r
1593 OTHERWISE IF (i = longueur)
\r
1594 THEN write(CHR(7));
\r
1595 ELSE IF (val >=32 AND val <=125)
\r
1596 THEN write(CHR(val));
\r
1599 ELSE write(CHR(7))
\r
1606 UNIT Put_chaine : PROCEDURE(x,y,Longueur : INTEGER;ch : ARRAYOF CHAR);
\r
1608 CALL Text_Attr(0,Gras); CALL GotoXY(x,y);
\r
1609 FOR i := 1 TO longueur - 1 DO write("Û") OD;
\r
1611 CALL Text_Attr(0,Inverse);
\r
1614 IF (i > UPPER(ch)) ORIF (ORD(ch(i)) = RETOUR) ORIF (i > Longueur - 1)
\r
1622 UNIT say : PROCEDURE(phrase : string);
\r
1624 CALL SetColor(noir,cyan);
\r
1625 CALL GotoXY(1,25);
\r
1628 CALL GotoXY(2,25);
\r
1630 CALL Text_Attr(0,normal);
\r
1636 INFO : ARRAYOF INTEGER,
\r
1642 DataRef : INTEGER;
\r
1644 UNIT Library: CLASS;
\r
1646 VAR New_Base : BOOLEAN,
\r
1649 UNIT Inventory : Relation CLASS;
\r
1650 VAR AutLeng, TitLeng, Publeng, SubjLeng : INTEGER;
\r
1654 UNIT Fiche : Tuple CLASS;
\r
1658 Subject : ARRAYOF CHAR,
\r
1662 ARRAY Author dim(1:AutLeng);
\r
1663 Author(1) := CHR(13);
\r
1664 ARRAY Title dim (1:TitLeng);
\r
1665 Title(1) := CHR(13);
\r
1666 ARRAY Publisher dim (1:Publeng);
\r
1667 Publisher(1) := CHR(13);
\r
1668 ARRAY Subject dim (1:SubjLeng);
\r
1669 Subject(1) := CHR(13);
\r
1672 UNIT VIRTUAL TupleToArray : FUNCTION(F : Fiche):ARRAYOF INTEGER;
\r
1673 VAR AuxRec :ARRAYOF INTEGER,
\r
1676 ARRAY AuxRec DIM (1:137);
\r
1677 FOR i := 1 TO AutLeng
\r
1681 IF ORD(F.Author(i)) = 13
\r
1686 FOR i := 1 TO TitLeng
\r
1688 AuxRec(cpt+i) := ORD(F.Title(i));
\r
1689 IF ORD(F.Title(i)) = 13
\r
1693 cpt := cpt + TitLeng;
\r
1694 FOR i := 1 TO Publeng
\r
1696 AuxRec(cpt+i) := ORD(F.Publisher(i));
\r
1697 IF ORD(F.Publisher(i)) = 13
\r
1701 cpt := cpt + Publeng;
\r
1702 FOR i := 1 TO SubjLeng
\r
1704 AuxRec(cpt+i) := ORD(F.Subject(i));
\r
1705 IF ORD(F.Subject(i)) = 13
\r
1709 cpt := cpt + SubjLeng;
\r
1710 AuxRec(cpt+1) := F.Year;
\r
1711 AuxRec(cpt+2) := F.NoInv;
\r
1715 UNIT VIRTUAL ArrayToTuple : FUNCTION (A :ARRAYOF INTEGER) :Fiche;
\r
1720 FOR i := 1 TO AutLeng
\r
1722 f.Author(i) := CHR(A(i));
\r
1728 FOR i := 1 TO TitLeng
\r
1730 f.Title(i) := CHR(A(cpt+i));
\r
1731 IF ORD(f.Title(i)) = 13
\r
1735 cpt := cpt + TitLeng;
\r
1736 FOR i := 1 TO Publeng
\r
1738 f.Publisher(i) := CHR(A(cpt+i));
\r
1739 IF ORD(f.Publisher(i)) = 13
\r
1743 cpt := cpt + Publeng;
\r
1744 FOR i := 1 TO SubjLeng
\r
1746 f.Subject(i) := CHR(A(cpt+i));
\r
1747 IF ORD(f.Subject(i)) = 13
\r
1751 cpt := cpt + SubjLeng;
\r
1752 f.Year := A(cpt+1);
\r
1753 f.NoInv := A(cpt+2);
\r
1757 UNIT NoInvCatalogue : IndexFile COROUTINE;
\r
1759 UNIT cleNo :Key CLASS;
\r
1760 VAR NoInv : INTEGER;
\r
1763 UNIT VIRTUAL KeyOf:FUNCTION (f :Fiche) :cleNo;
\r
1765 RESULT := NEW cleNo;
\r
1766 RESULT.NoInv := f.NoInv;
\r
1769 UNIT VIRTUAL Leq : FUNCTION (k1,k2 : cleNo) : BOOLEAN;
\r
1772 IF (k1.NoInv > k2.NoInv)
\r
1773 THEN RESULT := FALSE
\r
1777 UNIT VIRTUAL KeyToRec :PROCEDURE(ky:cleNo, A :ARRAYOF INTEGER;
\r
1783 UNIT VIRTUAL RecToKey : FUNCTION(A: ARRAYOF INTEGER,j:INTEGER): cleNo;
\r
1785 RESULT := NEW cleNo;
\r
1786 RESULT.NoInv := A(j);
\r
1789 VAR Akey_NoInv : cleNo;
\r
1791 BEGIN (* NoInvCatalogue *)
\r
1792 (* OUVERTURE du FICHIER INDEX *)
\r
1794 Akey_NoInv := NEW cleNo;
\r
1796 THEN df := MakeFile(UNPACK("NoInv.idx"),2+(PageSize*(KeySize+2)));
\r
1797 ELSE df := OpenFile(UNPACK("NoInv.idx"),2+(PageSize*(KeySize+2)));
\r
1798 Path(1).PageRef := INFO(1);
\r
1799 Path(1).RefOnPage := 1;
\r
1800 CALL Fseek(df,Path(1).PageRef);
\r
1801 AuxRec := Fget(df);
\r
1802 StackOfPages(1) := RecToPage(AuxRec);
\r
1806 (* FERMETURE DU FICHIER INDEX *)
\r
1807 FOR i := 1 TO TreeHeight
\r
1809 IF Path(i) = NONE THEN EXIT FI;
\r
1810 IF Path(i).updated
\r
1811 THEN CALL Fseek(df,Path(i).PageRef);
\r
1812 CALL Fput(df,PageToRec(StackOfPages(i)));
\r
1813 Path(i).updated := FALSE
\r
1816 INFO(1) := Path(1).PageRef;
\r
1817 CALL CloseFile(df)
\r
1818 END NoInvCatalogue;
\r
1820 UNIT AuthorsCatalogue : IndexFile COROUTINE;
\r
1822 UNIT cleA :Key CLASS;
\r
1823 VAR Author :ARRAYOF CHAR,
\r
1826 ARRAY Author dim (1:AutLeng);
\r
1829 UNIT VIRTUAL KeyOf:FUNCTION (f :Fiche) :cleA;
\r
1831 RESULT := NEW cleA;
\r
1832 RESULT.Author := COPY(f.Author);
\r
1833 RESULT.NoInv := f.NoInv;
\r
1836 UNIT VIRTUAL Leq : FUNCTION (k1,k2 : cleA) : BOOLEAN;
\r
1840 FOR i := 1 to AutLeng
\r
1842 IF ORD(k1.Author(i)) =13
\r
1844 ELSE IF ORD(k2.Author(i)) = 13
\r
1845 THEN RESULT := FALSE;
\r
1849 IF ORD(k1.Author(i)) =/= ORD(k2.Author(i))
\r
1850 THEN IF ORD(k1.Author(i)) > ORD(k2.Author(i))
\r
1851 THEN RESULT := FALSE
\r
1856 IF (k1.NoInv > k2.NoInv)
\r
1857 THEN RESULT := FALSE
\r
1861 UNIT VIRTUAL KeyToRec :PROCEDURE(ky:cleA, A :ARRAYOF INTEGER;
\r
1865 FOR i := 1 TO AutLeng
\r
1867 A(j+i-1) := ORD(ky.Author(i))
\r
1869 A(j+AutLeng) := ky.NoInv
\r
1872 UNIT VIRTUAL RecToKey : FUNCTION(A: ARRAYOF INTEGER,j:INTEGER): cleA;
\r
1874 RESULT := NEW cleA;
\r
1875 FOR i := 1 TO AutLeng
\r
1877 RESULT.Author(i) := CHR(A(j+i-1))
\r
1879 RESULT.NoInv := A(j+AutLeng);
\r
1882 VAR Akey_Author : cleA;
\r
1884 BEGIN (* AuthorsCatalogue *)
\r
1885 (* OUVERTURE du FICHIER INDEX *)
\r
1886 KeySize := AutLeng + 1;
\r
1887 Akey_Author := NEW cleA;
\r
1889 THEN df := MakeFile(unpack("Authors.idx"),2+(PageSize*(KeySize+2)));
\r
1890 ELSE df := OpenFile(unpack("Authors.idx"),2+(PageSize*(KeySize+2)));
\r
1891 Path(1).PageRef := INFO(2);
\r
1892 Path(1).RefOnPage := 1;
\r
1893 CALL Fseek(df,Path(1).PageRef);
\r
1894 AuxRec := Fget(df);
\r
1895 StackOfPages(1) := RecToPage(AuxRec);
\r
1899 (* FERMETURE DU FICHIER INDEX *)
\r
1900 FOR i := 1 TO TreeHeight
\r
1902 IF Path(i) = NONE THEN EXIT FI;
\r
1903 IF Path(i).updated
\r
1904 THEN CALL Fseek(df,Path(i).PageRef);
\r
1905 CALL Fput(df,PageToRec(StackOfPages(i)));
\r
1906 Path(i).updated := FALSE
\r
1909 INFO(2) := Path(1).PageRef;
\r
1910 CALL CloseFile(df)
\r
1911 END AuthorsCatalogue;
\r
1913 VAR CA :AuthorsCatalogue,
\r
1914 CInv : NoInvCatalogue,
\r
1915 NBindexs : INTEGER,
\r
1918 BEGIN (* Inventory *)
\r
1920 THEN df := MakeFile(UNPACK("LIBRARY.DAT"),137)
\r
1921 ELSE df := OpenFile(UNPACK("LIBRARY.DAT"),137)
\r
1924 ARRAY Indexs DIM (1:NBindexs);
\r
1925 AutLeng := 25; TitLeng := 50; Publeng := 40; SubjLeng := 20;
\r
1927 Indexs(1),CInv := NEW NoInvCatalogue;
\r
1928 Indexs(2),CA := NEW AuthorsCatalogue;
\r
1931 UNIT OpenLIB : PROCEDURE;
\r
1933 infofile := OpenFile(UNPACK("library.bas"),3);
\r
1934 INFO := Fget(InfoFile);
\r
1935 INV := NEW Inventory;
\r
1936 INV.FreePlace := INFO(3);
\r
1939 UNIT MakeLIB : PROCEDURE;
\r
1941 infofile := MakeFile(UNPACK("library.bas"),3);
\r
1942 INV := NEW Inventory;
\r
1945 UNIT CloseLIB : PROCEDURE;
\r
1949 CALL Text_Attr(0,Gras);
\r
1950 writeln("> FIN DU PROGRAMME BIBLIOTHEQUE.");
\r
1951 CALL CloseFile(INV.df);
\r
1952 FOR i := 1 TO INV.NBindexs DO
\r
1953 ATTACH(INV.Indexs(i))
\r
1955 INFO(3) := INV.FreePlace;
\r
1956 CALL Frewind(InfoFile);
\r
1957 CALL Fput(InfoFile,INFO);
\r
1958 CALL CloseFile(InfoFile);
\r
1962 BEGIN (* Library *)
\r
1963 ARRAY INFO dim (1:3);
\r
1965 CALL setcolor(noir,vert);
\r
1967 write("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ");
\r
1969 write("º ABDILLAHI Ibrahim º ");
\r
1971 write("º AMBAUD Richard º ");
\r
1973 write("º AMIGO Patrick º ");
\r
1975 write("º BRIGIDO Angel º ");
\r
1977 write("º COSTES Francois º ");
\r
1979 write("º COUDERC Christophe º ");
\r
1981 write("º CUESTA Mireille º ");
\r
1983 write("º IBARBIDE Sandrine º ");
\r
1984 CALL GotoXY(2,10);
\r
1985 write("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ");
\r
1986 CALL setcolor(blanc,rouge);
\r
1987 CALL GotoXY(35,12);
\r
1988 write(" GESTION ");
\r
1989 CALL GotoXY(36,13);
\r
1991 CALL GotoXY(33,14);
\r
1992 write(" BIBLIOTHEQUE ");
\r
1993 CALL setcolor(magenta,bleu);
\r
1994 CALL GotoXY(8,23);
\r
1995 write("ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿");
\r
1996 CALL GotoXY(8,24);
\r
1997 write("³ Voulez-vous utilisez une nouvelle base de donn
\82es (O/N) ? : ³");
\r
1998 CALL GotoXY(8,25);
\r
1999 write("ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
\r
2000 CALL GotoXY(70,24);
\r
2001 CALL setcolor(blanc,noir);
\r
2005 WHEN ESC : CALL cls;
\r
2007 writeln("Sortie [ESCAPE], retour au systeme.");
\r
2010 111,121 : (* OUI *)
\r
2015 WHEN 78,110 : (* NON *)
\r
2017 New_Base := FALSE;
\r
2020 OTHERWISE write(CHR(7));
\r
2023 CALL GotoXY(1,25);
\r
2031 UNIT CoMenu : COROUTINE;
\r
2032 CONST nbchoix = 4;
\r
2033 VAR tchoix : ARRAYOF string,
\r
2034 choix,i : INTEGER;
\r
2036 UNIT mov_choix: PROCEDURE(No: INTEGER);
\r
2038 CALL setcolor(blanc,noir);
\r
2039 CALL affchoix(34,choix+5,tchoix(choix));
\r
2040 choix := choix+No;
\r
2041 IF (choix > nbchoix)
\r
2043 ELSE IF (choix = 0)
\r
2044 THEN choix := nbchoix;
\r
2047 CALL text_attr(1,inverse);
\r
2048 CALL affchoix(34,choix+5,tchoix(choix));
\r
2051 "Ajouter des livres
\85 la librairie.");
\r
2053 "Suprimer des livres de la librairie.");
\r
2055 "Rechercher un livre
\85 partir des catalogues (auteurs/sujets).");
\r
2061 UNIT affchoix : PROCEDURE(x,y : INTEGER;ch : string);
\r
2069 BEGIN (* CoMenu *)
\r
2070 ARRAY tchoix DIM (1:nbchoix);
\r
2071 tchoix(1) := "AJOUTER ";
\r
2072 tchoix(2) := "SUPPRIMER ";
\r
2073 tchoix(3) := "RECHERCHER";
\r
2074 tchoix(4) := "QUITTER ";
\r
2079 CALL setcolor(jaune,noir);
\r
2081 writeln(" ÚÄÄÄÄMenuÄÄÄÄ¿");
\r
2086 writeln(" ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ");
\r
2088 CALL setcolor(blanc,noir);
\r
2089 FOR i := 1 TO nbchoix
\r
2091 CALL affchoix(34,i+5,tchoix(i));
\r
2093 CALL mov_choix(0);
\r
2097 WHEN Fhaut : CALL mov_choix(-1);
\r
2098 WHEN Fbas : CALL mov_choix(1);
\r
2099 WHEN ESC : CALL mov_choix(4-choix);
\r
2102 WHEN RETOUR : DETACH;
\r
2111 WHEN Del_Rec_Inexistant:
\r
2121 (*******************************************************************)
\r
2122 (******************** programme principal **************************)
\r
2123 (*******************************************************************)
\r
2126 CALL Text_Attr(0,Normal);
\r
2129 Menu := NEW CoMenu;
\r
2133 WHEN 1: (* INSERTION de TUPLES dans la BASE *)
\r
2136 f := NEW Fiche_Saisie;
\r
2138 THEN CALL L.INV.InsertTuple(L.INV.Ak);
\r
2140 "INSERTION REALISEE, Taper une touche pour continuer");
\r
2147 WHEN 2: (* DESTRUCTION de TUPLES de la BASE *)
\r
2150 "No inventaire du livre a supprimer ?: [ESC] = Abandon");
\r
2151 L.INV.Ak.NoInv := Read_Entier(40,25,5);
\r
2152 IF (L.INV.Ak.NoInv =/= -1) AND (L.INV.Ak.NoInv =/= -2)
\r
2153 THEN L.INV.CInv.AKey_NoInv := L.INV.CInv.KeyOf(L.INV.Ak);
\r
2154 DataRef := L.INV.CInv.FindKey(L.INV.CInv.AKey_NoInv);
\r
2156 THEN write(chr(7));
\r
2158 "SUPPRESSION DE LIVRE INEXISTANT !!!. taper une touche");
\r
2160 ELSE writeln("DATAREF = ",dataref);
\r
2161 CALL L.INV.DeleteTuple(L.INV.Ak);
\r
2163 "SUPPRESSION REALISEE !!!. taper une touche");
\r
2170 WHEN 3: (* RECHERCHE de TUPLES dans la BASE *)
\r
2172 WHEN 4: (* CONFIRMATION DE LA SORTIE *)
\r
2173 CALL setcolor(blanc,noir);
\r
2176 CALL setcolor(blanc,rouge);
\r
2177 CALL Gotoxy(13,10);
\r
2178 write(" CONFIRMER LA SORTIE DU PROGRAMME ");
\r
2179 CALL Gotoxy(13,11);
\r
2181 CALL Gotoxy(13,12);
\r
2182 write(" SORTIR ( O / N ) ? ");
\r
2183 CALL setcolor(blanc,noir);
\r
2187 WHEN 79,111 : (* OUI = "O" ou "o" *)
\r
2189 WHEN 78,110 : (* NON = "N" ou "n" *)
\r
2190 CALL GotoXY(59,12);
\r
2193 OTHERWISE write(CHR(7));
\r
2198 CALL Menu.mov_choix(0);
\r
2204 (****************************************************************************)
\r