PROGRAM station; (*_________________________________________________________*) (* loglan station h+ *) (* hgen station *) (* egahint /m50000 station *) (*---------------------------------------------------------*) (*----------------------------------------------------------*) (* CALSSE DEFINISSANT LES PROCEDURES DE GRAPHISME UTILISEES *) (*----------------------------------------------------------*) UNIT graph : IIUWGRAPH CLASS; CONST MAXx = 635, MAXy = 348, LETDIMY = 08, (* Hauteur lettre *) LETDIMX = 8, (* Largeur lettre *) Fgauche = -75, (* Fleche gauche *) Fdroite = -77, (* Fleche droite *) ESC = 27, (* Touche escape *) RETOUR = 13, (* Touche return *) BKSPACE = 8, (* Touche Backspace *) MOINS = 45; (* Touche signe moins *) (*---------------------------------------------------*) (* PROCEDURE permettant d'utiliser le mode GRAPHIQUE *) (*---------------------------------------------------*) UNIT initgraph : PROCEDURE; BEGIN CALL GRON(1); END initgraph; (*---------------------------------------------------*) (* PROCEDURE permettant de fermer le mode GRAPHIQUE *) (*---------------------------------------------------*) UNIT closegraph : PROCEDURE; BEGIN CALL GROFF; END closegraph; (*-----------------------------------------------------------------*) (* AFFICHAGE en (x,y) d'un RECTANGLE de longueur l et de hauteur h *) (*-----------------------------------------------------------------*) UNIT rectangle : PROCEDURE(x,y,l,h : INTEGER); BEGIN CALL MOVE (x,y); CALL DRAW (x+l,y); CALL DRAW(x+l,y+h); CALL DRAW(x,y+h); CALL DRAW(x,y); END rectangle; (*--------------------------------------------------------------------*) (* ECRITURE d'une CHAINE de caracteres sur l'ecran graphique en (x,y) *) (*--------------------------------------------------------------------*) UNIT ecrit_text : PROCEDURE(x,y : INTEGER;str : string); VAR ch : ARRAYOF CHARACTER, lg,i : INTEGER; BEGIN call color(14); CALL move (x,y); ch := UNPACK(str); lg := UPPER(ch) - LOWER(ch) + 1; FOR i := 1 TO lg DO CALL HASCII(0); CALL HASCII(ORD(ch(i))); OD; call color(15); END; (*---------------------------------*) (* LECTURE d'une touche au clavier *) (*---------------------------------*) UNIT inchar : FUNCTION : INTEGER; VAR i : INTEGER; BEGIN DO i := INKEY; IF i =/= 0 THEN EXIT; FI; OD; result := i; END inchar; (*-------------------------------------------------------------------*) (* LECTURE d'un ENTIER au clavier et AFFICHAGE sur l'ecran graphique *) (*-------------------------------------------------------------------*) UNIT lire_entier: FUNCTION(x,y:INTEGER;OUTPUT valeur :INTEGER): BOOLEAN; VAR nbchiffre,key,i,cas : INTEGER, negatif : BOOLEAN; BEGIN CALL MOVE(x,y); FOR i := 1 TO 6 DO CALL HASCII(0); CALL MOVE(INXPOS+8,INYPOS); OD; CALL MOVE(x,y); DO DO (* Lecture de la touche *) key := inchar; cas := key; IF (key >= 48 AND key <= 57) THEN cas := 1; EXIT; FI; IF (key = RETOUR) OR (key = ESC) OR (key = MOINS) OR (key = BKSPACE) THEN EXIT; FI; OD; CASE cas WHEN 1 : (* Saisie d'un chiffre *) IF (nbchiffre < 5 ) THEN valeur := valeur*10 + key - 48; IF x = INXPOS THEN negatif := FALSE; FI; CALL HASCII(0); CALL HASCII(key); nbchiffre := nbchiffre + 1; ELSE valeur :=(valeur DIV 10)*10 + key - 48; CALL MOVE(inxpos-8,y); CALL HASCII(0); CALL HASCII(key); FI; WHEN MOINS : (* Saisie du signe moins *) IF x = INXPOS THEN negatif := TRUE; CALL HASCII(0); CALL HASCII(MOINS); FI; WHEN RETOUR : (* Validation du chiffre eventuellement entre *) IF negatif THEN valeur := 0 - valeur; FI; IF nbchiffre > 0 THEN result := true; FI; RETURN; WHEN ESC : (* Abandon de la saisie *) RETURN; WHEN BKSPACE : (* Saisie de la touche Backspace *) IF nbchiffre > 0 THEN valeur := valeur DIV 10; CALL MOVE(INXPOS-8,y); CALL HASCII(0); nbchiffre := nbchiffre -1 ELSE IF negatif THEN negatif := FALSE; CALL MOVE(inxpos-8,y); CALL HASCII(0); FI; FI; ESAC; OD; END lire_entier; (*---------------------------------------------------------------------*) (* ECRITURE d'un ENTIER sur l'‚cran graphique au coordonn‚es courantes *) (*---------------------------------------------------------------------*) UNIT ecrit_entier : PROCEDURE (x : INTEGER); VAR val,i : INTEGER, strx : ARRAYOF CHARACTER; BEGIN ARRAY strx DIM(1:7); i := 7; val := ABS(x); DO strx(i) := chr(48+(val MOD 10)); val := val DIV 10; IF (val = 0) THEN EXIT; FI; i := i - 1; OD; IF x < 0 THEN i := i - 1; strx(i) := chr(MOINS); FI; WHILE i <= 7 DO CALL HASCII(0); CALL HASCII(ORD(strx(i))); i := i + 1; OD; END ecrit_entier; (*-------------------------------------------------------*) (* PROCEDURE d'ECRITURE de l'HEURE sur l'‚cran graphique *) (*-------------------------------------------------------*) UNIT ecrit_heure : PROCEDURE(posx,posy : INTEGER,time : REAL); VAR h,m,s : INTEGER; BEGIN h := ENTIER(time / 3600.0); m := ENTIER(time - ENTIER(time/3600)*3600) DIV 60; s := ENTIER(time - ENTIER(time/3600)*3600) MOD 60; IF ( h < 10) THEN CALL ecrit_text(posx,posy,"0"); ELSE CALL MOVE(posx,posy); FI; CALL ecrit_entier(h); CALL ecrit_text(INXPOS,INYPOS,":"); IF ( m < 10) THEN CALL ecrit_text(INXPOS,INYPOS,"0"); FI; CALL ecrit_entier(m); CALL ecrit_text(INXPOS,INYPOS,":"); IF ( s < 10) THEN CALL ecrit_text(INXPOS,INYPOS,"0"); FI; CALL ecrit_entier(s); END ecrit_heure; END graph; (*----------------------------------------------------------*) (* IMPLEMENTATION d'une QUEUE DE PRIORITE sous forme de TAS *) (*----------------------------------------------------------*) UNIT priorityqueue : graph CLASS; (*----------------------------*) (* CLASSE repr‚sentant le TAS *) (*----------------------------*) UNIT queuehead: CLASS; VAR last,root:node; (*---------------------------------------------*) (* FONCTION renvoyant l'ELEMENT MINIMUM du TAS *) (*---------------------------------------------*) UNIT min: FUNCTION: elem; BEGIN IF root=/= NONE THEN RESULT:=root.el FI; END MIN; (*------------------------------------*) (* INSERTION d'un element dans le TAS *) (*------------------------------------*) UNIT insert: PROCEDURE(r:elem); VAR x,z:node; BEGIN x:= r.lab; IF last=NONE THEN root:=x; root.left,root.right,last:=root ELSE IF last.ns=0 THEN last.ns:=1; z:=last.left; last.left:=x; x.up:=last; x.left:=z; z.right:=x; ELSE last.ns:=2; z:=last.right; last.right:=x; x.right:=z; x.up:=last; z.left:=x; last.left.right:=x; x.left:=last.left; last:=z; FI; FI; CALL correct(R,FALSE) END insert; (*---------------------------------*) (* SUPPRESSION d'un ELEMENT du TAS *) (*---------------------------------*) UNIT delete: PROCEDURE(r: elem); VAR x,Y,z:node; BEGIN x:=r.lab; z:=last.left; IF last.ns =0 THEN Y:= z.up; if y<>none then (*!!!!!!!!dopisalam !!!!!*) Y.right:= last else root :=none fi; last.left:=Y; last:=Y; ELSE Y:= z.left; Y.right:= last; last.left:= Y; FI; z.el.lab:=x; x.el:= z.el; last.ns:= last.ns-1; r.lab:=z; z.el:=R; IF x.less(x.up) THEN CALL correct(x.el,FALSE) ELSE CALL correct(x.el,TRUE) FI; END delete; (*------------------------------------------------------------------------*) (* CORRECTION-REEQUILIBRAGE du TAS aprŠs une insertion ou une suppression *) (*------------------------------------------------------------------------*) UNIT correct: PROCEDURE(r:elem,down:BOOLEAN); VAR x,z:node, t:elem, fin,log:BOOLEAN; BEGIN z:=r.lab; IF down THEN WHILE NOT fin DO IF z.ns =0 THEN fin:=TRUE; ELSE IF z.ns=1 THEN x:=z.left; ELSE IF z.left.less(z.right) THEN x:=z.left; ELSE x:=z.right; FI; FI; IF z.less(x) THEN fin:=TRUE; ELSE t:=x.el; x.el:=z.el; z.el:=t; z.el.lab:=z; x.el.lab:=x FI; FI; z:=x; OD; ELSE x:=z.up; (* !!!!!!!!!!refference to none **********) IF x=NONE THEN log:=TRUE; ELSE log:=x.less(z); FI; WHILE NOT log DO t:=z.el; z.el:=x.el; x.el:=t; x.el.lab:=x; z.el.lab:=z; z:=x; x:=z.up; IF x=NONE THEN log:=TRUE ELSE log:=x.less(z); FI; OD; FI; END correct; END queuehead; (*-----------------------------------*) (* NOEUD du TAS contenant un element *) (*-----------------------------------*) UNIT node: CLASS (el:elem); VAR left,right,up: node, ns:INTEGER; (*-----------------------------------*) (* COMPARAISON de deux NOEUDS du TAS *) (*-----------------------------------*) UNIT less: FUNCTION(x:node): BOOLEAN; BEGIN IF x= NONE THEN RESULT:=FALSE ELSE RESULT:=el.less(x.el) FI; END less; END node; (*-----------------------------------*) (* TYPE generique des element du TAS *) (*-----------------------------------*) UNIT elem: CLASS(prior:REAL); VAR lab: node; (*----------------------------------------------------*) (* FONCTION generique de comparaison de deux elements *) (*----------------------------------------------------*) UNIT VIRTUAL less: FUNCTION(x:elem):BOOLEAN; BEGIN IF x=NONE THEN RESULT:= FALSE ELSE RESULT:= prior< x.prior FI; END less; BEGIN lab:= NEW node(THIS elem); END elem; END priorityqueue; (*----------------------------------------------------------------------------*) (*--------------------------------*) (* MODULE GENERIQUE de SIMULATION *) (*--------------------------------*) UNIT simulation: priorityqueue CLASS; VAR curr: simprocess, (* Processus actif *) pq:queuehead, (* L'axe des temps *) mainpr: mainprogram; UNIT simprocess: COROUTINE; VAR event, eventaux: eventnotice, finish: BOOLEAN; (*---------------------------------------------------------*) (* FONCTION permettant de savoir si le processus est actif *) (*---------------------------------------------------------*) UNIT IDLE: FUNCTION: BOOLEAN; BEGIN RESULT:= EVENT= NONE; END IDLE; (*-----------------------------------------------------------*) (* FONCTION permettant de savoir si le processus est termin‚ *) (*-----------------------------------------------------------*) UNIT TERMINATED: FUNCTION :BOOLEAN; BEGIN RESULT:= finish; END TERMINATED; UNIT evtime: FUNCTION: REAL; BEGIN IF IDLE THEN CALL ERROR1; FI; RESULT := event.eventtime; END evtime; UNIT ERROR1:PROCEDURE; BEGIN ATTACH(main); WRITELN(" Erreur tentative d'acces a un processus endormi"); END ERROR1; UNIT ERROR2:PROCEDURE; BEGIN ATTACH(main); WRITELN(" Erreur : tentative d'acces a un processus deja termine"); END ERROR2; BEGIN RETURN; INNER; finish:=TRUE; CALL passivate; CALL ERROR2; END simprocess; (*-------------------------------------------------*) (* PLACEMENT du processus actif sur l'axe du temps *) (*-------------------------------------------------*) UNIT eventnotice: elem CLASS; VAR eventtime: REAL, proc: simprocess; UNIT VIRTUAL less: FUNCTION(x: eventnotice):BOOLEAN; BEGIN IF x=NONE THEN RESULT:= FALSE; ELSE RESULT:= eventtime< x.eventtime OR (eventtime=x.eventtime AND prior< x.prior); FI; END less; END eventnotice; UNIT mainprogram: simprocess CLASS; BEGIN DO ATTACH(main); OD; END mainprogram; (*-----------------------------------------------------------*) (* FONCTION permettant de savoir quel est le processus actif *) (*-----------------------------------------------------------*) UNIT time:FUNCTION:REAL; BEGIN RESULT:=current.evtime; END time; (*--------------------------------------------------------------------*) (* FONCTION retournant le premier processus place sur l'axe des temps *) (*--------------------------------------------------------------------*) UNIT current: FUNCTION: simprocess; BEGIN RESULT:=curr; END current; (*-----------------------------------------------------------*) (* PROCEDURE permettant d'activer le processus p … l'heure t *) (*-----------------------------------------------------------*) UNIT schedule: PROCEDURE(p:simprocess,t:REAL); BEGIN IF t