Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-05 - 43,50337/21/gpssst.ibm
There is 1 other file named gpssst.ibm in the archive. Click here to see a list.
ZQ
//JBGPSSS JOB (XAO875,JB142M332,1,3),'J BOSE',
//            MSGLEVEL=(2,1) ,CLASS=S,TIME=(0,15)
/*SD                            L#GGS I PROJEKT 13-FACKET
//SIMULA EXEC SIMCLG,REGION=208K
//SIM.SYSIN DD *
%NORESWD
COMMENT (/E/L);
SIMULATION  CLASS  GPSSST(MAX_QUEUES,MAX_STATIONS,MAX_STORAGES,
UNIT,SECDEC);
CHARACTER UNIT;
INTEGER MAX_QUEUES,MAX_STATIONS,MAX_STORAGES,SECDEC;
COMMENT  NOT HIDDEN PROTECTED OBJECT_TRACE_ON,NOREPORT,
TRANSID,SET_STORAGE,RESTART,GPSSS_TIME,CONTENTS_STATION,
STATION,BOX,FILE,SECDEC,UNIT,STANDARD_REPORT,U,TRANSACTION,WAIT_UNTIL,
TIME_SPENT_ONLY,SKIP,TRACE_ON,BEGIN_TIME,HOLD_UNTIL_READY,TRACE_OBJECT,
CONTENTS_STORAGE,CONTENTS_QUEUE,WAITING_STATION,WAITING_STORAGE,
OUTTIME,TRANS_NAME,QUEUE_NAME,STATION_NAME,STORAGE_NAME,WAITING_QUEUE,
BBEGIN_TIME;
COMMENT  NOT HIDDEN PROCESS,CURRENT,TIME,HOLD,PASSIVATE,WAIT,
CANCEL,ACCUM,MAIN,LINKAGE,LINK,HEAD;
BEGIN
    COMMENT  **************************************************
    MONTREAL  GPSSS PACKAGE + VERSION 4.1 +
    WRITTEN - FEBRUARY 1972
    UPDATED - SEPTEMBER 1974
    AUTHOR  - JEAN G. VAUCHER
    PROFESSEUR AGREGE
    DEPARTEMENT D INFORMATIQUE
    UNIVERSITE DE MONTREAL
    C.P. 6128 , MONTREAL 101
    CANADA
    CONVERTED TO DECSYSTEM 10 - JUNE 1976
    BY H-JOACHIM BOSE
    **********************************************************;
    REF (FACILITY)  ARRAY  STATION (1:MAX_STATIONS  );
    REF (STORAGE )  ARRAY  BOX     (1:MAX_STORAGES);
    REF (Q       )  ARRAY  FILE    (1:MAX_QUEUES)  ;
    TEXT ARRAY QUEUE_NNAME(1:MAX_QUEUES);
    TEXT ARRAY STATION_NNAME(1:MAX_STATIONS);
    TEXT ARRAY STORAGE_NNAME(1:MAX_STORAGES);
    TEXT TRANS_NNAME,FIELD;
    REAL BBEGIN_TIME ;
    INTEGER MAXLENGTH,LLENGTH;
    BOOLEAN TRACE_ON,OBJECT_TRACE_ON,NOREPORT,TIME_SPENT_ONLY;
    REF(HEAD)FINISHED_OBJECTS;
    COMMENT  **********************************************************
    OCCURRENCE_STAT. DEFINITION. LINK TO OCCURENCES,ATTRIBUT TO TRANS.
    ******************************************************************;
    LINK CLASS
    OCCURRENCE_STATISTICS(OCCURRENCE_NUMBER,RESOURCE_NUMBER,
    OCCURRENCE_TIME);
    INTEGER OCCURRENCE_NUMBER,RESOURCE_NUMBER;
    REAL OCCURRENCE_TIME;      ;
    INTEGER  TRANSID  ;
    INTEGER  NSTAT, NSTOR, NQUE, PASSE ;
    BOOLEAN OUTOFORDER  ;
    COMMENT  *******************************************************
    QUEUE_NAME DEFINITION
    ***************************************************************;
    PROCEDURE QUEUE_NAME(I,NEW_NAME);
    VALUE NEW_NAME;
    INTEGER I;
    TEXT NEW_NAME;
    BEGIN
        CHECK_LIMITS(I,1); IF OUTOFORDER THEN GOTO OUT;
        IF NEW_NAME.LENGTH>MAXLENGTH THEN MAXLENGTH:=NEW_NAME.LENGTH;
        QUEUE_NNAME(I):-NEW_NAME;
        OUT:  OUTOFORDER := FALSE
    END;
    COMMENT  *******************************************************
    STATION_NAME DEFINITION
    ***************************************************************;
    PROCEDURE STATION_NAME(I,NEW_NAME);
    VALUE NEW_NAME;
    INTEGER I;
    TEXT NEW_NAME;
    BEGIN
        CHECK_LIMITS(I,2);  IF OUTOFORDER THEN GOTO OUT;
        IF NEW_NAME.LENGTH>MAXLENGTH THEN MAXLENGTH:=NEW_NAME.LENGTH;
        STATION_NNAME(I):-NEW_NAME;
        OUT:  OUTOFORDER := FALSE
    END;
    COMMENT  *******************************************************
    STORAGE_NAME DEFINITION
    ***************************************************************;
    PROCEDURE STORAGE_NAME(I,NEW_NAME);
    VALUE NEW_NAME;
    INTEGER I;
    TEXT NEW_NAME;
    BEGIN
        CHECK_LIMITS(I,3); IF OUTOFORDER THEN GOTO OUT ;
        IF NEW_NAME.LENGTH>MAXLENGTH THEN MAXLENGTH:=NEW_NAME.LENGTH;
        STORAGE_NNAME(I):-NEW_NAME;
        OUT:  OUTOFORDER := FALSE
    END;
    COMMENT  ***************************************
    OUTOFORDER DEFINITION
    ***********************************************;
    BOOLEAN PROCEDURE CHECK_LIMITS(NR,FAC);
    INTEGER NR,FAC;
    BEGIN
        SWITCH MSG:=Q,STA,STO;
        GOTO MSG(FAC);
        Q:  IF NR<1 OR NR>MAX_QUEUES THEN BEGIN
            ERREUR(10);
        OUTOFORDER :=TRUE;END; GOTO OUT;
        STA:IF NR<1 OR NR>MAX_STATIONS  THEN BEGIN
            ERREUR(11);
        OUTOFORDER :=TRUE;END; GOTO OUT;
        STO:IF NR<1 OR NR>MAX_STORAGES THEN BEGIN
            ERREUR(12);
        OUTOFORDER :=TRUE; END;
        OUT: ERLOC:=NR;
    END OF OUTOFORDER  ;
    INTEGER TLENGTH;
    COMMENT  ***************************************************
    TRANS_NAME DEFINITION
    ***********************************************************;
    PROCEDURE TRANS_NAME(TRNAME);
    VALUE TRNAME;
    TEXT TRNAME;
    BEGIN
        TRANS_NNAME:- TRNAME;
        TLENGTH:=TRNAME.LENGTH;
    END OF TRANS_NAME ;
    COMMENT  **************************************************
    BEGIN_TIME DEFINITION
    **********************************************************;
    REAL PROCEDURE BEGIN_TIME(TIME);
    REAL TIME;
    BEGIN
    BBEGIN_TIME:=60*ENTIER(TIME)+100*(
    TIME-ENTIER(TIME));
    BEGIN_TIME:=BBEGIN_TIME ;
    END ;
    COMMENT  **************************************************
    TRACE_OBJECT DEFINITION
    **********************************************************;
    PROCEDURE TRACE_OBJECTS;
    IF OBJECT_TRACE_ON THEN BEGIN
        INTEGER TT;
        BOOLEAN NOTFIRST;
        FIELD:-IMAGE.SUB(MAXLENGTH+18,LLENGTH);
        IF  NOT FINISHED_OBJECT.EMPTY THEN BEGIN
            IF LINE>4 THEN SKIP(100);
            OUTTEXT("  THE TRANSACTIONS LEAVING THE SYSTEM ARE");
            SKIP(0);
            OUTTEXT("  =======================================");
            TRACE_QUEUE(FINISHED_OBJECTS);
        END;
        FOR TT:=1 STEP 1 UNTIL MAX_STORAGES DO
        IF BOX(TT)=/=NONE THEN BEGIN
            IF  NOT BOX(TT).INQ.EMPTY THEN BEGIN
                IF  NOT NOTFIRST THEN BEGIN
                    HEADER(1);
                    NOTFIRST:=TRUE;
                END;
                OUTTEXT("          /");
                FACILITY_NAME_OUT(3,TT);
                OUTTEXT("/");
                TRACE_QUEUE(BOX(TT).INQ);
            END;
        END;
        NOTFIRST:=FALSE;
        FOR TT:=1 STEP 1 UNTIL MAX_STATIONS DO
        IF STATION(TT)=/= NONE THEN BEGIN
            IF  NOT STATION(TT).INQ.EMPTY THEN BEGIN
                IF  NOT NOTFIRST THEN BEGIN
                    HEADER(2);
                    NOTFIRST:=TRUE;
                END;
                OUTTEXT("          /");
                FACILITY_NAME_OUT(2,TT);
                OUTTEXT("/");
                TRACE_QUEUE(STATION(TT).INQ);
            END;
        END;
        IF  NOT WAITQ.EMPTY THEN BEGIN
            IF LINE > 4 THEN SKIP(100) ELSE SKIP(4);
            OUTTEXT("THE TRANSACTIONS STUCKED IN WAITQUEUE ARE");
            SKIP(0);
            OUTTEXT("=========================================");
            SKIP(0);
            OUTTEXT("( PASSIVATED IN THE PROCEDURE WAIT_UNTIL )");
            SKIP(1);
            TRACE_QUEUE(WAITQ);
        END;
    END ELSE BEGIN
        SKIP(0);OUTTEXT(
        "YOU HAVE TO SET OBJECT_TRACE_ON := TRUE ");
        SKIP(0);OUTTEXT(" IF YOU WANT TO USE TRACE_OBJECTS ");
        SKIP(10);
    END   OF  TRACE_OBJECT  ;
    COMMENT  *******************************************
    TRACE_QUEUE DEFINITION
    ***************************************************;
    PROCEDURE TRACE_QUEUE (Q_REF);
    REF(HEAD) Q_REF;
    BEGIN
        REF(TRANSACTION) CURRENT_TRANSACTION;
        REF(OCCURRENCE_STATISTICS) CURRENT_OCCURRENCE;
        INTEGER TT;
        CURRENT_TRANSACTION:-Q_REF.FIRST;
        WHILE CURRENT_TRANSACTION=/=NONE DO
        INSPECT CURRENT_TRANSACTION DO BEGIN
            IF   NOT  TIME_SPENT_ONLY THEN BEGIN
                IF LINE+1.5*OCCURRENCES.CARDINAL+10>54 THEN
                SKIP(100) ELSE SKIP(2);
            END ELSE IF LINE + OCCURRENCES.CARDINAL/2
            + 4 > 54 THEN SKIP(100)  ELSE SKIP(2);
            SETPOS(8);
            TRANS_NAME_OUT(ID);
            SKIP(0);
            SETPOS(8);
            IF TRANS_NNAME==NOTEXT THEN
            OUTTEXT("----------") ELSE
            BEGIN
                FOR TT:=1 STEP 1 UNTIL TLENGTH DO
                OUTTEXT("-");
                OUTTEXT("----");
            END;
            SKIP(2);
            IF  NOT  TIME_SPENT_ONLY THEN PRINT_OUT(OCCURRENCES);
            SKIP(1);
            COMPARE(CURRENT_TRANSACTION);
            CURRENT_TRANSACTION:-SUC;
        END  INSPECT TRANSACTION  ;
    END  OF  PROC. TRACE_QUEUE  ;
    COMMENT  ****************************************************
    HEADER DEFINITION
    ************************************************************;
    PROCEDURE HEADER(NR);
    INTEGER NR;
    BEGIN SKIP(100);
        OUTTEXT("THE TRANSACTIONS WAITING TO ENTER ");
        IF NR=1 THEN OUTTEXT("STORAGE ") ELSE
        OUTTEXT("STATION "); OUTTEXT("ARE :");
        SKIP(0);
        OUTTEXT("===============================================");
        SKIP(1);
    END;
    COMMENT  **************************************************
    PRINT_OUT DEFINITION
    **********************************************************;
    PROCEDURE PRINT_OUT (TRANSOCCURRENCE);
    REF(HEAD) TRANSOCCURRENCE ;
    BEGIN
        REF(OCCURRENCE_STATISTICS) Z ;
        Z:- TRANSOCCURRENCE.FIRST;
        WHILE Z =/= NONE DO
        INSPECT Z DO BEGIN
            IF OCCURRENCE_NUMBER>0 THEN
            OUTTEXT("ENTERED ") ELSE
            OUTTEXT("LEAVED  ");
            FACILITY_NAME_OUT(ABS(OCCURRENCE_NUMBER),RESOURCE_NUMBER);
            SETPOS(11+MAXLENGTH);
            OUTTEXT("AT TIME ");
            PUTTIME(OCCURRENCE_TIME+BBEGIN_TIME);
            SKIP(0);
            Z:-Z.SUC;
        END;
    END PROC. PRINT_OUT;
    COMMENT  *****************************************************
    COMPARE DEFINITION
    *************************************************************;
    PROCEDURE COMPARE(TRANSOCCURRENCE);
    REF(TRANSACTION) TRANSOCCURRENCE;
    INSPECT TRANSOCCURRENCE DO BEGIN
        REF(OCCURRENCE_STATISTICS)X,Y;
        X:-OCCURRENCES.FIRST;
        WHILE X=/= NONE DO BEGIN
            Y:-X.SUC;
            WHILE Y=/= NONE DO BEGIN
                IF X.RESOURCE_NUMBER=
                Y.RESOURCE_NUMBER AND
                X.OCCURRENCE_NUMBER=
                -(Y.OCCURRENCE_NUMBER) THEN BEGIN
                    WTIME_SPENT_OUT(X,Y);
                    Y.OUT;
                    GOTO NEXT_X;
                END;
                Y:-Y.SUC;
            END;
            NEXT_X:
            X:-X.SUC;
        END;
    END  COMPARE  ;
    COMMENT  *********************************************
    WTIME_SPENT_OUT DEFINITION
    *****************************************************;
    PROCEDURE WTIME_SPENT_OUT(OCCUR1,OCCUR2);
    REF(OCCURRENCE_STATISTICS) OCCUR1,OCCUR2;
    BEGIN
        OUTTEXT("TIME SPENT IN ");
        INSPECT OCCUR1 DO
        FACILITY_NAME_OUT(OCCURRENCE_NUMBER,RESOURCE_NUMBER);
        SETPOS(17+MAXLENGTH);
        OUTTEXT(":");
        PUTTIME(OCCUR2.OCCURRENCE_TIME-
        OCCUR1.OCCURRENCE_TIME);
        SKIP(0);
    END WTIME_SPENT_OUT;
    COMMENT  ***********************************************
    TRANS_NAME_OUT DEFINITION
    *******************************************************;
    PROCEDURE TRANS_NAME_OUT(NR);
    INTEGER NR;
    BEGIN
        IF TRANS_NNAME==NOTEXT THEN OUTTEXT("OBJECT") ELSE
        OUTTEXT(TRANS_NNAME);
        OUTINT(NR,4);
        SETPOS(POS+2);
    END OF TRANS_NNAME ;
    COMMENT  *********************************************
    FACILITY_NAME_OUT DEFINITION
    *****************************************************;
    PROCEDURE FACILITY_NAME_OUT(NUMBER,RESOURCE);
    INTEGER NUMBER,RESOURCE;
    BEGIN
        SWITCH MSG:=Q,STA,STO;
        GOTO MSG(ABS(NUMBER));
        Q:
        IF QUEUE_NNAME(RESOURCE)==NOTEXT THEN BEGIN
            OUTTEXT(" QUEUE  ");
            OUTINT(RESOURCE,4);
        END ELSE
        OUTTEXT(QUEUE_NNAME(RESOURCE));
        GOTO OUT;
        STA:
        IF STATION_NNAME(RESOURCE)==NOTEXT THEN BEGIN
            OUTTEXT(" STATION");
            OUTINT(RESOURCE,4);
        END ELSE
        OUTTEXT( STATION_NNAME(RESOURCE));
        GOTO OUT;
        STO:
        IF  STORAGE_NNAME(RESOURCE)==NOTEXT THEN BEGIN
            OUTTEXT(" STORAGE");
            OUTINT(RESOURCE,4);
        END ELSE
        OUTTEXT(STORAGE_NNAME(RESOURCE));
        OUT:
    END OF FAC_NAME_OUT;
    COMMENT  ***********************************************
    PUTTIME DEFINITION
    *******************************************************;
    TEXT PROCEDURE PUTTIME(TIME);
    REAL TIME;
    IF FIELD.LENGTH >=
    (IF SECDEC < 0 THEN 12 ELSE IF SECDEC = 0 THEN 15 ELSE SECDEC+16)
    THEN
    BEGIN   INTEGER DAYS,HOURS,M,POWERSEC;   REAL SECONDS;

        PROCEDURE FIXEDIT(X,W);   REAL X;   INTEGER W;
        BEGIN
            FIELD.SUB(FIELD.POS,W).PUTFIX(
            X,IF SECDEC>=0 THEN SECDEC ELSE 0);
            FIELD.SETPOS(FIELD.POS+W);
        END OF FIXEDIT;

        PROCEDURE INTEDIT(I,W);   INTEGER I,W;
        BEGIN
            FIELD.SUB(FIELD.POS,W).PUTINT(I);
            IF FIELD.GETCHAR = ' ' THEN
            BEGIN   FIELD.SETPOS(FIELD.POS-1);
                FIELD.PUTCHAR('0');
            END;
            FIELD.SETPOS(FIELD.POS-1+W);
        END OF INTEDIT;

        BOOLEAN PROCEDURE ADJUSTED;
        BEGIN
            IF M = 60 THEN
            BEGIN   ADJUSTED:= TRUE;
                HOURS:= HOURS + 1;   M:= 0;
                IF HOURS = 24 THEN
                BEGIN   DAYS:= DAYS + 1;   HOURS:= 0   END
     END;
            FIELD.SUB(2,6):= "   D  ";
            FIELD.SETPOS(5);
            IF DAYS < 1 THEN
            FIELD.PUTCHAR(' ') ELSE
            IF DAYS < 10 THEN
            BEGIN
                FIELD.SETPOS(4);
                FIELD.PUTCHAR(CHAR(DAYS+RANK('0')));
            END ELSE
            IF DAYS < 100 THEN
            BEGIN   FIELD.SETPOS(3);   INTEDIT(DAYS,2)   END ELSE
            IF DAYS < 1000 THEN
            BEGIN   FIELD.SETPOS(2);   INTEDIT(DAYS,3) END ELSE
            FIELD.SUB(2,3):= "***";
            FIELD.SETPOS(8);
            INTEDIT(HOURS,2);   FIELD.PUTCHAR(':');
        END OF ADJUST;

        POWERSEC:= 1;
        FOR M:= 1 STEP 1 UNTIL SECDEC DO POWERSEC:= POWERSEC*10;
        IF UNIT = 'D' OR UNIT = 'D'  THEN TIME:= 1440*TIME ELSE
        IF UNIT = 'H' OR UNIT = 'H' THEN TIME:= 60*TIME ELSE
        IF UNIT = 'S' OR UNIT = 'S' THEN TIME:= TIME/60;

        FIELD.SETPOS(1);
        FIELD.PUTCHAR(IF TIME < 0 THEN '-' ELSE ' ');
        TIME:= ABS(TIME);
        IF TIME > 2 147 483 647 THEN GO TO ERROR;
        M:= ENTIER(TIME);
        SECONDS:= 60*(TIME - M);
        HOURS:= M//60;
        M:= MOD(M,60);
        DAYS:= HOURS//24;
        HOURS:= MOD(HOURS,24);
        IF SECDEC >= 0 THEN
        BEGIN
            IF ENTIER(SECONDS*POWERSEC+0.5) = 60*POWERSEC THEN
            BEGIN   M:= M + 1;   SECONDS:= 0   END;
            ADJUSTED;
            INTEDIT(M,2);   FIELD.PUTCHAR('.');
            IF SECONDS < 9.5 THEN
            BEGIN   FIELD.PUTCHAR('0');
                FIXEDIT(SECONDS,IF SECDEC = 0 THEN 1 ELSE SECDEC+2)
            END ELSE
            FIXEDIT(SECONDS,IF SECDEC = 0 THEN 2 ELSE SECDEC+3);
        END ELSE
        BEGIN   TIME:= M + SECONDS/60;
            M:= TIME;
            IF ADJUSTED THEN TIME:= 0;
            IF TIME < 9.5 THEN   FIELD.PUTCHAR('0');
            FIXEDIT(TIME,IF TIME < 9.5 THEN 1 ELSE 2)
        END;
        FIELD.SETPOS(1);   PUTTIME:- FIELD
    END OF PUTTIME OK ELSE
    ERROR:
    BEGIN   FIELD.SETPOS(1);
        WHILE FIELD.MORE DO FIELD.PUTCHAR('*');
        FIELD.SETPOS(1);
        PUTTIME:- FIELD ;
    END OF PUTTIME ERROR;
    PROCEDURE OUTTIME(U_TIME); REAL U_TIME ;
    BEGIN
    TEXT SAVEFIELD;
    SAVEFIELD:- FIELD ;
    IF POS + LLENGTH > LENGTH + 1 THEN OUTIMAGE ;
    FIELD:- IMAGE.SUB(POS,LLENGTH);
    PUTTIME(U_TIME);
    SETPOS(POS + LLENGTH);
    FIELD :- SAVEFIELD ;
    END OF OUTTIME ;
    COMMENT  **************************************************
    HOLD_UNTIL_READY DEFINITION
    **********************************************************;
    PROCEDURE HOLD_UNTIL_READY;
    BEGIN
        IF CURRENT.NEXTEV==NONE THEN
        BEGIN
            OUTTEXT("THE SIMULATION WAS ALREADY FINISHED.");
            SKIP(0);
            OUTTEXT("DO NOT MAKE ""HOLD"" IN THE MAIN PROGRAM,");
            SKIP(0);
            OUTTEXT("BEFORE HOLD_UNTIL_READY");
            SKIP(0);
        END ELSE PASSIVATE;
    END;
    COMMENT  **************************************************
    FACILITY DEFINITION
    **********************************************************;
    CLASS  FACILITY;
    BEGIN
        REF (HEAD) INQ;
        REF (TRANSACTION) OCCUPIER;
        INTEGER  ENTRIES ;
        REAL  TLAST, BUSY_TIME ;
        BOOLEAN   PROCEDURE  BUSY;
        BUSY := OCCUPIER =/=  NONE ;
        INQ :-  NEW  HEAD ;
        TLAST := TIME_ORIGIN ;
    END  FACILITY DEFINITION;
    COMMENT  **************************************************
    STORAGE DEFINITION
    **********************************************************;
    CLASS  STORAGE (CAPACITY);
    INTEGER  CAPACITY;
    BEGIN
        REF (HEAD) INQ;
        INTEGER MAX,ENTRIES,UNIT_ENTRIES; REAL CONTENTS;
        REAL  TLAST, INTGRL;
        COMMENT  ********************************************
        CHECK_INQ DEFINITION
        ****************************************************;
        PROCEDURE  CHECK_INQ;
        BEGIN
            REF (TRANSACTION) CLIENT, NEXT_CLIENT;
            CLIENT :- INQ.FIRST;
            LOOP:
            IF  CLIENT ==  NONE   OR  CONTENTS=  CAPACITY
            THEN  GOTO  FIN;
            NEXT_CLIENT :- CLIENT.SUC ;
            ACTIVATE  CLIENT ;
            CLIENT :- NEXT_CLIENT;
            GOTO  LOOP;
            FIN:
        END  OF CHECK_INQ ;
        INQ :-  NEW  HEAD ;
        TLAST := TIME_ORIGIN ;
    END  STORAGE DEFINITION ;
    COMMENT  ************
    STORAGE CREATION
    ********************;
    PROCEDURE  SET_STORAGE (N,CAPACITY);
    INTEGER  N, CAPACITY;
    BEGIN
        NSTOR := NSTOR + 1 ;
        BOX (N) :-  NEW  STORAGE (CAPACITY);
    END ;
    COMMENT  **************************************************
    QUEUE DEFINITION
    **********************************************************;
    CLASS   Q ;
    BEGIN
        INTEGER  ENTRIES, MAX ;
        REAL  INTGRL, TLAST, CONTENTS;
        TLAST := TIME_ORIGIN ;
    END ;
    BOOLEAN INIT;
    COMMENT  **************************************************
    TRANSACTION DEFINITION
    **********************************************************;
    PROCESS  CLASS  TRANSACTION ;
    COMMENT  NOT HIDDEN PROTECTED ENTER_QUEUE,LEAVE_QUEUE,ENTER_STATION,
    LEAVE_STATION,ENTER_STORAGE,LEAVE_STORAGE,ID,TIME_MARK,
    OCCURRENCES,PRIORITY,PRIORITY_INTO;
    COMMENT  NOT HIDDEN IDLE,NEXTEV,OUT,FOLLOW,PRECEDE,INTO,SUC,PRED;
    BEGIN
        REAL  TIME_MARK, PRIORITY;
        INTEGER  ID ;
        REF(HEAD) OCCURRENCES;
        COMMENT  ***************************************************
 TRACE DEFINITION
 ***********************************************************;
        PROCEDURE TRACE(N);
        INTEGER N;
        BEGIN
            IF  NOT INIT THEN BEGIN
                IF LINE>1 THEN  SKIP(100) ELSE SKIP(1);
                INIT:=TRUE;
            END;
            FIELD:-IMAGE.SUB(POSITION,LLENGTH);
            TRANS_NAME_OUT(ID);
            IF MR<0 THEN OUTTEXT(" LEAVING   ") ELSE
            OUTTEXT(" ENTERING  ");
            FACILITY_NAME_OUT(MR,N);
            SETPOS(MAXLENGTH+15+
            (IF TRANS_NNAME==NOTEXT THEN 11 ELSE TLENGTH+5));
            OUTTEXT("AT TIME ");
            PUTTIME(GPSSS_TIME+BBEGIN_TIME);
            IF MOD(LINE,5)=0 THEN SKIP(1) ELSE  SKIP(0);
            IF LINE>58 THEN SKIP(100);
        END TRACE ;
        COMMENT  ***************
 FINAL_WAIT DEFINITION
 ***********************;
        PROCEDURE FINAL_WAIT(Q_REF);
        REF(HEAD)Q_REF;
        BEGIN
            REF(TRANSACTION)CURRENT_TRANSACTION;
            CURRENT_TRANSACTION:-Q_REF.LAST;
            WHILE CURRENT_TRANSACTION =/=NONE DO
            BEGIN
                IF ID>CURRENT_TRANSACTION.ID THEN
                BEGIN
                    FOLLOW(CURRENT_TRANSACTION);
                    GOTO OUT;
                END;
                CURRENT_TRANSACTION:-CURRENT_TRANSACTION.PRED;
            END;
            FOLLOW(Q_REF);
            OUT:
        END   FINAL_WAIT   ;
        COMMENT  ************
 ENTER_STATION
 ********************;
        PROCEDURE  ENTER_STATION (N);
        INTEGER  N ;
        BEGIN
            CHECK_LIMITS(N,2);
            IF OUTOFORDER THEN GOTO UT;
            START:
            INSPECT  STATION(N)  DO
            BEGIN
                IF  OCCUPIER ==  THIS  TRANSACTION  THEN
                BEGIN
                    ERLOC := N ;
                    ERREUR(6);
                    GOTO  EXIT;
                END ;
                IF  BUSY  THEN   BEGIN
                    PRIORITY_INTO(INQ);
                    IF NEXTEV==NONE THEN ACTIVATE MAIN DELAY 0 ;
                    PASSIVATE;
                    OUT;
                END   ELSE  TLAST := TIME;
                ENTRIES := ENTRIES+1;
                OCCUPIER :-  THIS  TRANSACTION;
                MR:=2;
                IF TRACE_ON THEN TRACE(N);
                IF OBJECT_TRACE_ON THEN
                NEW OCCURRENCE_STATISTICS(2,N,GPSSS_TIME
                ).INTO(OCCURRENCES);
                EXIT:

            END
     OTHERWISE   BEGIN
                STATION (N) :-  NEW  FACILITY;
                NSTAT := NSTAT+1;
                GOTO  START;
            END ;
            UT:OUTOFORDER :=FALSE;
        END  ENTER_STATION ;
        COMMENT  ************
 LEAVE_STATION
 ********************;
        PROCEDURE  LEAVE_STATION (N) ;
        INTEGER  N ;
        BEGIN
            CHECK_LIMITS(N,2);
            IF OUTOFORDER THEN GOTO UT;
            INSPECT  STATION (N)  WHEN  FACILITY  DO
            BEGIN
                IF  OCCUPIER =/=  THIS  TRANSACTION  THEN
                BEGIN
                    ERLOC := N ;
                    ERREUR (3);
                    GOTO  EXIT ;
                END ;
                IF  INQ.EMPTY  THEN   BEGIN
                    OCCUPIER :-  NONE ;
                    BUSY_TIME:=BUSY_TIME + TIME - TLAST;
                END
  ELSE   BEGIN
                    OCCUPIER :- INQ.FIRST;
                    ACTIVATE  INQ.FIRST  DELAY  0 ;
                END ;
                MR:=-2;
                IF TRACE_ON THEN TRACE(N);
                IF OBJECT_TRACE_ON THEN
                NEW OCCURRENCE_STATISTICS(
                -2,N,GPSSS_TIME).
                INTO(OCCURRENCES);
                EXIT:
            END   OTHERWISE   BEGIN
                ERLOC := N ;
                ERREUR(3) ;
            END  ;
            UT:OUTOFORDER :=FALSE;
        END  LEAVE_STATION ;
        COMMENT  ************
 ENTER_STORAGE
 ********************;
        PROCEDURE  ENTER_STORAGE (N, UNITS_REQUIRED) ;
        INTEGER  N, UNITS_REQUIRED ;
        BEGIN
            CHECK_LIMITS(N,3);
            IF OUTOFORDER THEN GOTO UT;
            IF  BOX (N) ==  NONE   THEN  SET_STORAGE(N,1000000) ;
            INSPECT  BOX (N)  WHEN  STORAGE  DO
            BEGIN
                IF  UNITS_REQUIRED>CAPACITY  THEN
                BEGIN
                    ERLOC := N ;
                    ERREUR (4);
                    GOTO  ERROR_EXIT ;
                END ;
                PRIORITY_INTO (INQ);
                TEST:
                IF  UNITS_REQUIRED <= CAPACITY-CONTENTS THEN  GOTO EXIT;
                IF NEXTEV==NONE THEN ACTIVATE MAIN DELAY 0 ;
                PASSIVATE;
                GOTO  TEST;
                EXIT:
                MR:=3;
                IF TRACE_ON THEN TRACE(N);
                IF OBJECT_TRACE_ON THEN
                NEW OCCURRENCE_STATISTICS(
                3,N,GPSSS_TIME).
                INTO(OCCURRENCES);
                OUT;
                ENTRIES:=ENTRIES+1;
                UNIT_ENTRIES:=UNIT_ENTRIES+UNITS_REQUIRED;
                ACCUM(INTGRL,TLAST,CONTENTS,UNITS_REQUIRED);
                IF  CONTENTS>  MAX  THEN  MAX := CONTENTS;
                HOLD (0);
            END  INSPECT ;
            ERROR_EXIT:
            UT:   OUTOFORDER :=FALSE;
        END  ENTER_STORAGE;
        COMMENT  ************
 LEAVE_STORAGE
 ********************;
        PROCEDURE  LEAVE_STORAGE (N,UNITS_RELEASED);
        INTEGER  N,UNITS_RELEASED;
        BEGIN
            CHECK_LIMITS(N,3);
            IF OUTOFORDER THEN GOTO UT;
            INSPECT  BOX (N)  WHEN  STORAGE  DO
            BEGIN
                ACCUM(INTGRL,TLAST,CONTENTS,-(UNITS_RELEASED))  ;
                IF  CONTENTS<  0  THEN   BEGIN
                    ERLOC:=N;
                    ERREUR (5);
                    CONTENTS:=  0;
                END   ELSE BEGIN
                    CHECK_INQ;
                    MR:=-3;
                    IF TRACE_ON THEN TRACE(N);
                    IF OBJECT_TRACE_ON THEN
                    NEW OCCURRENCE_STATISTICS(
                    -3,N,GPSSS_TIME).
                    INTO(OCCURRENCES);
                END;
            END
     OTHERWISE  SET_STORAGE (N,1000000) ;
            UT:OUTOFORDER :=FALSE;
        END;
        COMMENT  ************
 ENTER_QUEUE
 ********************;
        PROCEDURE  ENTER_QUEUE (N);
        INTEGER  N ;
        BEGIN
            CHECK_LIMITS(N,1);
            IF OUTOFORDER THEN GOTO UT;
            IF  FILE (N) ==  NONE   THEN   BEGIN
                FILE (N) :-  NEW  Q;
                NQUE := NQUE + 1;
            END ;
            INSPECT  FILE (N)  DO
            BEGIN
                ENTRIES := ENTRIES +1;
                ACCUM (INTGRL,TLAST,CONTENTS,1);
                IF  CONTENTS>MAX  THEN  MAX := CONTENTS;
                MR:=1;
                IF TRACE_ON THEN TRACE(N);
                IF OBJECT_TRACE_ON THEN
                NEW OCCURRENCE_STATISTICS(
                1,N,GPSSS_TIME).
                INTO(OCCURRENCES);
            END  ;
            UT:OUTOFORDER :=FALSE;
        END  ENTER_QUEUE;
        COMMENT  ************
 LEAVE_QUEUE
 ********************;
        PROCEDURE  LEAVE_QUEUE (N) ;
        INTEGER  N;
        BEGIN
            CHECK_LIMITS(N,1);
            IF OUTOFORDER THEN GOTO UT;
            INSPECT  FILE (N)  DO
            IF  CONTENTS=  0  THEN   BEGIN
                ERLOC:= N ;
            ERREUR(7) ;  END
     ELSE BEGIN
                ACCUM (INTGRL,TLAST,CONTENTS,-1);
                MR:=-1;
                IF TRACE_ON THEN TRACE(N);
                IF OBJECT_TRACE_ON THEN
                NEW OCCURRENCE_STATISTICS(
                -1,N,GPSSS_TIME).
                INTO(OCCURRENCES);
            END
     OTHERWISE   BEGIN
                ERLOC := N ;
                ERREUR(8);
                FILE (N) :-  NEW  Q ;
                NQUE := NQUE +1 ;
            END ;
            UT:OUTOFORDER :=FALSE;
        END;
        COMMENT  ************
 PRIORITY_INTO
 ********************;
        PROCEDURE  PRIORITY_INTO (QUEUE) ;
        REF (HEAD) QUEUE;
        BEGIN
            REF (TRANSACTION) PT ;
            REF (PROCESS) P ;
            IF  QUEUE.EMPTY  THEN  INTO(QUEUE)
            ELSE   BEGIN
                COMMENT   SKIP NON TRANSACTION OBJECTS ;
                P:-QUEUE.LAST ;
                L:  IF  P  IN  TRANSACTION  OR  P== NONE   THEN   BEGIN
                    PT:-P;
                    GOTO  LOOP;
                END ;
                P:-P.PRED ;
                GOTO  L;
                PREDEC:   PT :- PT.PRED ;
                LOOP:      IF  PT== NONE   THEN  PRECEDE(QUEUE.FIRST)
                ELSE   IF  PRIORITY<PT.PRIORITY  THEN  GOTO  PREDEC
                ELSE   IF  PRIORITY=PT.PRIORITY  AND PRIORITY<0
                THEN   GOTO  PREDEC
                ELSE  FOLLOW (PT);
            END ;
        END  PROCEDURE PRIORITY_INTO ;
        INTEGER MR;
        TIME_MARK := GPSSS_TIME ;
        TRANSID  := TRANSID  + 1 ;
        ID := TRANSID  ;
        IF OBJECT_TRACE_ON THEN OCCURRENCES:-NEW HEAD;
        INNER;
        IF OBJECT_TRACE_ON THEN FINAL_WAIT (FINISHED_OBJECTS);
        IF NEXTEV==NONE THEN ACTIVATE MAIN DELAY 0;
    END  CLASS TRANSACTION ;
    COMMENT  *******************************
    WAIT_UNTIL PARAPHENALIA
    ***************************************;
    REF (HEAD) WAITQ ;
    REF (WAIT_MONITOR) WAIT_MONITEUR ;
    BOOLEAN  WAIT_ACTION ;
    PROCEDURE  WAIT_UNTIL (B);  NAME  B;  BOOLEAN  B ;
    INSPECT  CURRENT  DO   BEGIN
        IF  B  THEN   GOTO  EXIT ;
        IF  CURRENT  IN  TRANSACTION  THEN
        CURRENT  QUA  TRANSACTION.PRIORITY_INTO(WAITQ)
        ELSE  INTO(WAITQ);
        IF  WAIT_MONITEUR.IDLE  THEN
        ACTIVATE  WAIT_MONITEUR  AFTER  NEXTEV ;
        LOOP:
        PASSIVATE;
        IF  NOT B THEN  GOTO  LOOP ;
        OUT ;
        WAIT_ACTION :=  TRUE  ;
        EXIT:
    END  WAIT_UNTIL ;
    PROCESS  CLASS  WAIT_MONITOR ;
    BEGIN
        REF (PROCESS) PT ;
        START:
        IF  WAITQ.EMPTY  THEN  PASSIVATE ;
        WAIT_ACTION :=  FALSE  ;
        PT :- WAITQ.FIRST ;
        LOOP:
        IF  PT ==  NONE   THEN   GOTO  WAIT ;
        ACTIVATE  PT ;
        IF  WAIT_ACTION  THEN   GOTO  START ;
        PT :- PT.SUC ;
        GOTO  LOOP ;
        WAIT:
        REACTIVATE  CURRENT  AFTER  NEXTEV ;
        GOTO  START ;
    END  WAIT_MONITOR ;
    COMMENT
    ******************************
    PROCEDURES UTILITAIRES
    ******************************;
    PROCEDURE  SKIP (N) ;
    INTEGER  N;
    BEGIN
        OUTIMAGE;
        IF  N>0  THEN   BEGIN
            IF  LINE+N > 60  THEN  EJECT(2)
            ELSE  EJECT (LINE+N);
        END ;
    END  PROC SKIP;
    REAL   PROCEDURE  GPSSS_TIME ;
    GPSSS_TIME := TIME- SIMULATION_START_TIME ;
    PROCEDURE  CLEAR_SQS ;
    L1:  IF  CURRENT.NEXTEV =/=  NONE   THEN
    BEGIN
        CANCEL (CURRENT.NEXTEV) ;
        GOTO  L1 ;
    END  ;
    PROCEDURE  RESTART ;
    BEGIN
        INTEGER  I ;
        IF  CURRENT =/= MAIN  THEN   BEGIN
        ERREUR(9) ;  GOTO  OUT ;  END  ;
        ERROR_REPORT ;
        IF  NOT NOREPORT THEN STANDARD_REPORT ;
        PASSE := PASSE + 1 ;
        COMMENT   CANCEL ALL RESOURCES ;

        FOR  I := 1  STEP  1  UNTIL  MAX_STATIONS  DO
        STATION (I) :-  NONE  ;
        FOR I := 1  STEP  1  UNTIL  MAX_STORAGES  DO
        BOX     (I) :-  NONE  ;
        FOR  I := 1  STEP  1  UNTIL  MAX_QUEUES  DO
        FILE    (I) :-  NONE  ;
        COMMENT   CANCEL ALL EVENTS ;
        CLEAR_SQS ;
        INIT:=FALSE;
        SIMULATION_START_TIME := TIME ;
        NSTAT := NSTOR := NQUE := 0 ;
        TRANSID  := 0 ;
        U := 987654321 ;
        FINISHED_OBJECTS :- NEW HEAD ;
        OUT:
    END  ;
    COMMENT  *****************************************
    ENQUIRY PROCEDURES
    *************************************************;
    INTEGER   PROCEDURE  CONTENTS_STATION(N) ;
    INTEGER  N ;
    BEGIN CHECK_LIMITS(N,2);
        IF OUTOFORDER THEN GOTO UT;
        INSPECT  STATION(N)  DO
        IF  BUSY  THEN  CONTENTS_STATION := 1 ;
        UT:
    END;
    INTEGER   PROCEDURE  CONTENTS_STORAGE (N) ;
    INTEGER  N ;
    BEGIN CHECK_LIMITS(N,2);
        IF OUTOFORDER THEN GOTO UT;
        INSPECT  BOX (N)  DO
        CONTENTS_STORAGE := CONTENTS;
        UT:
    END;
    INTEGER   PROCEDURE  CONTENTS_QUEUE (N) ;
    INTEGER  N ;
    BEGIN CHECK_LIMITS(N,2);
        IF OUTOFORDER THEN GOTO UT;
        INSPECT  FILE (N)  DO
        CONTENTS_QUEUE := CONTENTS  ;
        UT:
    END;
    INTEGER   PROCEDURE  WAITING_STATION (N) ;
    INTEGER  N ;
    BEGIN CHECK_LIMITS(N,2);
        IF OUTOFORDER THEN GOTO UT;
        INSPECT  STATION (N)  DO
        WAITING_STATION := INQ.CARDINAL ;
        UT:
    END;
    INTEGER   PROCEDURE  WAITING_STORAGE (N) ;
    INTEGER  N ;
    BEGIN CHECK_LIMITS(N,2);
        IF OUTOFORDER THEN GOTO UT;
        INSPECT  BOX (N)  DO
        WAITING_STORAGE := INQ.CARDINAL ;
        UT:
    END;
    INTEGER   PROCEDURE  WAITING_QUEUE (N) ;
    INTEGER  N ;
    BEGIN CHECK_LIMITS(N,2);
        IF OUTOFORDER THEN GOTO UT;
        WAITING_QUEUE := 0 ;
        UT:
    END;
    COMMENT  **************************************************
    REPORT  GENERATOR
    **********************************************************;
    PROCEDURE  STANDARD_REPORT ;
    BEGIN
        INTEGER  I;
        BOOLEAN  SBUS;
        REAL  DTIME;
        DTIME := TIME-TIME_ORIGIN;
        SKIP(100);
        OUTTEXT("***************************");
        OUTTEXT("    -VERSION 4.1-")  ; OUTIMAGE ;
        OUTTEXT("***   MONTREAL  GPSSS   ***");  SKIP(0) ;
        OUTTEXT("***  SIMULATION REPORT  ***");
        SKIP(0); OUTTEXT("***************************");
        SKIP(2);
        OUTTEXT("PASSE  =")  ;
        OUTINT(PASSE,3) ;
        SKIP(1) ;
        OUTTEXT("START  TIME=");
        FIELD:-IMAGE.SUB(13,LLENGTH);
        PUTTIME(TIME_ORIGIN-SIMULATION_START_TIME
        +BBEGIN_TIME ) ;
        SKIP(0);
        OUTTEXT("END    TIME=");
        PUTTIME(GPSSS_TIME + BBEGIN_TIME);
        IF  DTIME=0  THEN   BEGIN
            SKIP(2);
            OUTTEXT("ELAPSED  TIME = 0 - REPORT SKIPPED")  ;
            GOTO  EXIT ;
        END ;
        SKIP(2);
        IF  NSTAT=0  THEN   BEGIN
            OUTTEXT("* NO STATIONS *");
            GOTO  L1;
        END ;
        OUTTEXT("* STATIONS *");
        SKIP(0); OUTTEXT("************");
        SKIP(1);
        SETPOS(15);
        OUTTEXT("AVERAGE");
        SETPOS(38);
        OUTTEXT("AVERAGE");
        SKIP(0);
        OUTTEXT
        ("   STATION   UTILISATION  ENTRIES   TRANSIT TIME   STATUS");
        SKIP(1);
        FIELD:-IMAGE.SUB(32,LLENGTH);
        FOR  I:=1  STEP  1  UNTIL  MAX_STATIONS  DO
        INSPECT  STATION(I)  DO
        BEGIN
            SBUS := BUSY ;
            IF  SBUS  THEN  BUSY_TIME:=BUSY_TIME+TIME-TLAST;
            OUTINT(I,7);
            OUTFIX(BUSY_TIME/DTIME,2,13);
            OUTINT(ENTRIES,10);
            PUTTIME(BUSY_TIME/ENTRIES);
            SETPOS(52);
            IF  SBUS  THEN  OUTTEXT("BUSY")
            ELSE  OUTTEXT("FREE");
            COMMENT   RE-INITIALISATION DES STATISTIQUES ;
            IF  SBUS  THEN  ENTRIES :=1  ELSE  ENTRIES :=0 ;
            BUSY_TIME := 0;
            TLAST := TIME;
            SKIP(0);
        END ;
        L1:
        SKIP(2);
        IF  NSTOR=0  THEN   BEGIN
            OUTTEXT("* NO STORAGES *");
            GOTO  L2;
        END ;
        OUTTEXT("* STORAGES *");
        SKIP(0); OUTTEXT("************");
        SKIP(1);
        SETPOS(23);  OUTTEXT("AVG.");
        SETPOS(32);  OUTTEXT("AVG.");
        SETPOS(51);  OUTTEXT("THRU  TIME");
        SETPOS(67);  OUTTEXT("CONTENTS");
        SKIP(0);
        OUTTEXT
        ("STORAGE   CAPACITY  CONTENTS   UTIL.  ENTRIES  ");
        OUTTEXT
        ("     / UNIT        MAX    NOW");
        SKIP(1);
        FIELD:-IMAGE.SUB(46,LLENGTH);
        FOR I:=1 STEP 1 UNTIL MAX_STORAGES DO
        INSPECT  BOX(I)  DO
        BEGIN
            ACCUM(INTGRL,TLAST,CONTENTS,0);
            OUTINT(I,5)  ;
            OUTINT(CAPACITY,10) ;
            OUTFIX(INTGRL/DTIME,2,12) ;
            IF  CAPACITY=0  THEN  SETPOS(38)  ELSE
            OUTFIX(INTGRL/(DTIME*CAPACITY),4,8);
            OUTINT(ENTRIES,8);
            IF  UNIT_ENTRIES=0  THEN  SETPOS(61)  ELSE
            PUTTIME (INTGRL/UNIT_ENTRIES);
            SETPOS(63);
            OUTINT(MAX,7);
            OUTINT(CONTENTS,7);
            SKIP(0);
            COMMENT   RE-INITIALISATION DES STATISTIQUES ;
            ENTRIES := 0;
            UNIT_ENTRIES := CONTENTS;
            INTGRL := 0 ;
            TLAST := TIME;
            MAX := CONTENTS;
        END ;
        L2:
        SKIP(2);
        IF  NQUE=0  THEN   BEGIN
            OUTTEXT("* NO QUEUES *");
            GOTO  EXIT;
        END ;
        OUTTEXT("* QUEUES *")  ;
        SKIP(0); OUTTEXT("**********")   ;
        SKIP(1);
        SETPOS(19); OUTTEXT(
        "MAX.     CURRENT     AVG.         AVG.")  ;
        SKIP(0); OUTTEXT(
        "QUEUE   ENTRIES  CONTENTS  CONTENTS  CONTENTS     TIME/TRANS");
        SKIP(1);
        FIELD:-IMAGE.SUB(46,LLENGTH);
        FOR  I := 1  STEP  1  UNTIL  MAX_QUEUES  DO
        INSPECT  FILE (I)  DO
        BEGIN
            ACCUM(INTGRL,TLAST,CONTENTS,0);
            OUTINT(I,4)  ;
            OUTINT(ENTRIES,8);
            OUTINT(MAX,10);
            OUTINT(CONTENTS,10);
            OUTFIX(INTGRL/DTIME,2,11);
            IF  ENTRIES=0  THEN   GOTO  OVER;
            PUTTIME(INTGRL/ENTRIES);
            OVER:
            INTGRL := 0;
            MAX := ENTRIES := CONTENTS;
            SKIP(0) ;
        END ;
        EXIT:
        TIME_ORIGIN := TIME;
    END  PROC STANDARD_REPORT ;
    COMMENT   ******************************
    ERROR   PACKAGE
    ***************************************;
    INTEGER  ERNUM,ERLOC ;
    INTEGER   ARRAY  ERTYPE(1:15),ERRES  (1:15),    ERTRAN (1:15)  ;
    REAL   ARRAY  ERTIME (1:15)  ;
    PROCEDURE  ERREUR (N) ;
    INTEGER  N ;
    BEGIN
        ERNUM := ERNUM + 1 ;
        ERTIME (ERNUM) := GPSSS_TIME ;
        IF  N<2  OR  N>12  THEN
        ERTYPE(ERNUM) := 1
        ELSE   BEGIN
            ERTYPE(ERNUM) := N ;
            ERRES (ERNUM) := ERLOC ;
            INSPECT  CURRENT  WHEN  TRANSACTION  DO
            ERTRAN (ERNUM) := ID
            OTHERWISE
            ERTRAN (ERNUM) := 0 ;
        END  ;
        IF  ERNUM = 14  THEN   BEGIN
            ERREUR(2) ;
            CLEAR_SQS ;
            ERROR_REPORT ;
            IF  CURRENT =/= MAIN  THEN   BEGIN

                ACTIVATE  MAIN  DELAY  0 ;
                PASSIVATE;
            END  ;
        END  ;
        ERLOC := 0 ;
    END  ;
    PROCEDURE  ERROR_REPORT ;
    BEGIN
        INTEGER  I ;
        PROCEDURE  PHRASE1 (N) ;  INTEGER  N;
        BEGIN
            IF  N=1  THEN  OUTTEXT("IN  STATION")   ELSE
            IF  N=2  THEN  OUTTEXT("IN  STORAGE")   ELSE
            IF  N=3  THEN  OUTTEXT("IN  QUEUE"   )  ELSE
            OUTTEXT("IN  XXX"     ) ;
            OUTINT(ERRES(I),3) ;
            OUTIMAGE ;
        END  ;
        PROCEDURE  PHRASE2 ;
        BEGIN
            OUTTEXT("               TRANSACTION")  ;
            OUTINT(ERTRAN(I),4) ;
        END  ;
        IF  ERNUM=0  THEN   GOTO  EXIT ;
        SKIP(100) ;
        OUTTEXT("GPSSS  ERROR REPORT   - AT TIME=")  ;
        FIELD:-IMAGE.SUB(34,LLENGTH);
        PUTTIME(GPSSS_TIME);
        OUTIMAGE ;
        OUTTEXT("******************")   ; SKIP(1) ;
        OUTTEXT("PASSE  =")  ;
        OUTINT(PASSE,3) ;
        SKIP(1) ;
        OUTTEXT("**  TIME **")  ; OUTIMAGE ;
        FIELD:-IMAGE.SUB(1,LLENGTH);
        FOR  I:=1  STEP  1  UNTIL  ERNUM  DO
        BEGIN
            SWITCH MSG:= L1,L2,L3,L4,L5,L6,L7,L8,L9,L10,L11,L12;
            OUTIMAGE ;
            PUTTIME(ERTIME(I));
            SETPOS(LLENGTH);
            OUTTEXT("   - ")  ;
            GOTO MSG(ERTYPE(I));
            L1:OUTTEXT("SYSTEM   ERROR")  ;
            GOTO  OUT ;
            L2:OUTTEXT("TOO   MANY ERRORS - SIMULATION TERMINATED");
            GOTO  OUT ;
            L3:PHRASE1  (1) ; PHRASE2 ;
            OUTTEXT("  TRIES TO LEAVE BEFORE ENTERING")  ;
            GOTO  OUT ;
            L4:PHRASE1  (2) ; PHRASE2 ;
            OUTTEXT("  REQUIRES MORE THAN MAX CAPACITY")  ;
            GOTO  OUT ;
            L5:PHRASE1  (2) ; PHRASE2 ;
            OUTTEXT("  CAUSES OVERFLOW WHEN LEAVING")  ;

            GOTO  OUT ;
            L6:PHRASE1  (1) ; PHRASE2 ;
            OUTTEXT("  TRIES TO RE-ENTER")  ;
            GOTO  OUT ;
            L7:PHRASE1  (3) ; PHRASE2 ;
            OUTTEXT("  TRIES TO LEAVE EMPTY QUEUE")  ;
            GOTO  OUT ;
            L8:PHRASE1  (3) ; PHRASE2 ;
            OUTTEXT("  TRIES TO LEAVE NON-EXISTENT QUEUE")  ;
            GOTO  OUT ;
            L9:OUTTEXT("RESTART   USED OUTSIDE MAIN PROGRAM");
            OUTTEXT("  - NO ACTION")  ;
            GOTO  OUT ;
            L10:PHRASE1 (1);GOTO L13;
            L11:PHRASE1 (2);GOTO L13;
            L12:PHRASE1 (3);GOTO L13;
            L13:OUTTEXT("  =  NON-EXISTENT RESOURCE ");
            OUT:
            OUTIMAGE ;
        END  ;
        ERNUM := 0 ;
        EXIT:
    END  ;
    COMMENT  *********************
    POSITION  DEFINITION
    *****************************;
    INTEGER PROCEDURE POSITION ;
    IF
    (IF TLENGTH = 0 THEN 10 ELSE  TLENGTH + 4 )
    + 24 + MAXLENGTH > 79 - TLENGTH
    THEN BEGIN
        POSITION:=  45 ;
        MAXLENGTH:= 11 ;
        TLENGTH:=0;
        CLEAR_NAMES;
        SKIP(0);
        OUTTEXT("  YOU HAVE TO MANY CHARACTERS IN YOUR NAME(S) ");
        SKIP(1);
    END ELSE POSITION:=
    (IF TLENGTH = 0 THEN 10 ELSE  TLENGTH + 4 )
    + 24 + MAXLENGTH ;
    COMMENT  ******************
    CLEAR_NAMES  DEFINITION
    **************************;
    PROCEDURE CLEAR_NAMES;
    BEGIN  INTEGER J;
        FOR J:=1 STEP 1 UNTIL MAX_QUEUES DO
        QUEUE_NNAME(J):-NOTEXT;
        FOR J:=1 STEP 1 UNTIL MAX_STATIONS DO
        STATION_NNAME(J):-NOTEXT;
        FOR J:=1 STEP 1 UNTIL MAX_STORAGES DO
        STORAGE_NNAME(J):-NOTEXT;
        TRANS_NNAME:-NOTEXT;
    END;
    COMMENT  ************************************
    INITIALISATION
    ********************************************;
    INTEGER  U ;
    REAL  TIME_ORIGIN, SIMULATION_START_TIME ;
    U :=987654321;
    PASSE := 1 ;
    MAXLENGTH:=11;
    LLENGTH:=(IF SECDEC<0 THEN 13 ELSE
    IF SECDEC=0 THEN 16 ELSE 17+SECDEC);
    WAITQ :-  NEW  HEAD ;
    WAIT_MONITEUR :-  NEW  WAIT_MONITOR ;
    FINISHED_OBJECTS:-NEW HEAD;
    INNER ;
    ERROR_REPORT ;
    IF  NOT NOREPORT THEN STANDARD_REPORT ;
END  GPSSS DEFINITION
COMMENT   L#KARMOTTAGNING MED PROVTAGNING ;
GP3S2(3,4,1,'M',-1) BEGIN
    TRANSACTION CLASS PATIENT (TID1,TID2) ;
    REAL TID1 , TID2 ;
    BEGIN
      PROCEDURE TILL_STATION (NUM) ;
      INTEGER NUM ;
      BEGIN    ENTER_QUEUE( NUM ) ;
        WAIT_UNTIL(CONTENTS_STATION(NUM)=0
        OR CONTENTS_STATION(NUM+1)=0);
        LEAVE_QUEUE( NUM ) ;
        IF CONTENTS_STATION ( NUM ) = 0 THEN
        ENTER_STATION( NUM ) ELSE
        ENTER_STATION( NUM + 1 ) ;
        HOLD(IF NUM=1 THEN TID1 ELSE TID2);
        IF STATION(NUM).OCCUPIER==THIS TRANSACTION
        THEN LEAVE_STATION( NUM ) ELSE
        LEAVE_STATION( NUM + 1 );
      END PROC. TILL_STATION ;
      ENTER_STORAGE(1,1) ;
      FOR I := 1,3 DO TILL_STATION( I ) ;
      LEAVE_STORAGE( 1 , 1 ) ;
    END PATIENT ;
    INTEGER I , J , U1 , U2;
    OBJECT_TRACE_ON := TRUE ;
    TIME_SPENT_ONLY := TRUE ;
    SET_STORAGE( 1 , 10 ) ;
    QUEUE_NAME( 1," K@N TILL PROVTAGNINGEN" ) ;
    QUEUE_NAME( 3," V#NTRUMMET TILL L#KARNA " ) ;
    STORAGE_NAME( 1 ," L#KARHUSET " ) ;
    STATION_NAME( 1 ," PROVSTATION - 1 - " ) ;
    STATION_NAME( 2 ," PROVSTATION - 2 - " ) ;
    STATION_NAME( 3," / HOS L#KARE - ETT -") ;
    STATION_NAME( 4," / HOS L#KARE - TV$ -") ;
    BEGIN_TIME(9.00); U1:=123987 ; U2:=987123 ;
    FOR J := 1 STEP 1 UNTIL 10 DO BEGIN
      ACTIVATE NEW PATIENT( NORMAL( 60 , 20 , U1 ) ,
      UNIFORM(20 , 120 , U2 ) ) DELAY 0 ;
      HOLD( NEGEXP( 2/60 , U ) );
    END INIT PATIENT ;
    HOLD_UNTIL_READY;
    TRACE_OBJECTS;
  END ;
END
//