
package DATA_PKG is

  subtype HEADERS is INTEGER;
  type MSG_BLOCKS is array (1..80) of CHARACTER;
  type IO_FILE is array (1..10) of HEADERS;

end DATA_PKG;
with DATA_PKG;use DATA_PKG; 
package Q_PKG is
  type FLAG is (SUCCESS,FAILURE);
  type QUEUES is private;
  
  procedure ENQUEUE(Q:in out QUEUES; ITEM:in HEADERS; RESULT:in out FLAG);

  procedure DEQUEUE(Q:in out QUEUES; ITEM:out HEADERS; RESULT:in out FLAG);

  private

    MAX_SIZE   :  constant := 10;
    subtype MODNUM is INTEGER range 0..MAX_SIZE;
    type QITEM is array(0..MAX_SIZE) of HEADERS;
    type QUEUES is
      record
        ITEMS    :  QITEM;
        HEAD     :  MODNUM:=0;
        TAIL     :  MODNUM:=0;
      end record;

end Q_PKG;

with DATA_PKG;use DATA_PKG;
with Q_PKG;use Q_PKG;
package SWITCH_PKG is

  procedure START(Q: in out QUEUES; FILE: in IO_FILE);

end SWITCH_PKG;

with DATA_PKG;use DATA_PKG;
package body Q_PKG is

  function MODADD1(I:MODNUM) return MODNUM is
    begin
      return((I+1) mod MAX_SIZE);
    end MODADD1;

  function EMPTY(Q:in QUEUES) return BOOLEAN is
    begin
      return(Q.TAIL=Q.HEAD);
    end EMPTY;

  function FULL(Q:in QUEUES) return BOOLEAN is
    begin
      return(MODADD1(Q.TAIL)=Q.HEAD);
    end FULL;

  procedure ENQUEUE(Q:in out QUEUES; ITEM: in HEADERS; RESULT: in out FLAG) is
    begin
      if not FULL(Q)
        then
          Q.ITEMS(Q.TAIL):=ITEM;
          Q.TAIL:=MODADD1(Q.TAIL);
          RESULT:=SUCCESS;
        else
          RESULT:=FAILURE;
          end if;
    end ENQUEUE;

procedure DEQUEUE(Q:in out QUEUES; ITEM: out HEADERS; RESULT:in out FLAG) is
    begin
      if not EMPTY(Q)
        then
          ITEM:=Q.ITEMS(Q.HEAD);
          Q.HEAD:=MODADD1(Q.HEAD);
          RESULT:=SUCCESS;
        else
          RESULT:=FAILURE;
      end if;
    end DEQUEUE;

end Q_PKG;  
with TEXT_IO;use TEXT_IO;
with Q_PKG;use Q_PKG;
with DATA_PKG;use DATA_PKG;
package body SWITCH_PKG is

package INT_IO is new INTEGER_IO(INTEGER);
use INT_IO;

  function RANDOM(SEED:in INTEGER) return INTEGER is
    begin
      return ((SEED**2+2153) mod 10000);
    end RANDOM;

  procedure START (Q:in out QUEUES; FILE:in IO_FILE) is

    SEED      :  INTEGER;
    COUNT     :  INTEGER:=1;
    RESULT    :  FLAG:=SUCCESS;
    ITEM      :  HEADERS;
 
    begin
      PUT("Input a random number from 0 to 10,000");
 --     GET(SEED);
      SEED := 987;
      SEED:=SEED mod 10000;
      loop
        SEED:=RANDOM(SEED);
        if COUNT<=FILE'LAST and SEED<5000 
          then
            ENQUEUE(Q,FILE(COUNT),RESULT);
            if RESULT=SUCCESS
              then
                COUNT:=COUNT+1;
              else
                NEW_LINE;
                put("Enqueue failed--queue was full.");
            end if;
          else
            DEQUEUE(Q,ITEM,RESULT);
            if RESULT=SUCCESS
              then
                NEW_LINE;
                put("Dequeued ");
                put(ITEM);
              else
                NEW_LINE;
                put("Dequeue failed--queue was empty.");                
            end if;
        end if;
        exit when COUNT>FILE'LAST and RESULT=FAILURE;
      end loop;
    end START;

end SWITCH_PKG;    
with SWITCH_PKG;use SWITCH_PKG;
with Q_PKG;use Q_PKG;
with DATA_PKG;use DATA_PKG;
procedure OPERATOR is

  OPERATOR_Q  :    QUEUES;
  TEST_FILE : IO_FILE:=(12,13,84,81,22,54,24,26,88,80);     

 
  begin
    START(OPERATOR_Q, TEST_FILE);
  end OPERATOR;
