program adtdemo (infile1,output);
    {adtdemo reads a file of single digit integers, one per line, and puts
     them into a list L. The list is then printed, purged of duplicate elements
     and printed again.}

{- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      LIST ADT (an ARRAY implementataion)

NOTE:-     1. The array size is determined by maxln, and is set for 100
              elements.

           2. An empty list has the position variable L.last set to 0.}

const
  maxln = 100;
type
  position = integer;
  infotype = integer;
  list = record
           info: array[1..maxln] of infotype;
           last: position
         end;

{- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}

var
  infile1: text;
  L: list;

{- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}

procedure ERROR;
  begin
  { * * COMPILER SPECIFIC FEATURE FOLLOWS * *}
  abort('ERROR',0,0);
  { * * END CSF * *}
  end;
function FIRST (var L: list): position;
  begin
    FIRST:= 1
  end;
function ENDLIS (var L: list): position;
  begin
    ENDLIS:= L.last + 1
  end;
function NEXT (p: position; var L: list): position;
  begin
    if ((p > L.last) or (p < 1))
      then
        ERROR
      else
        NEXT:= p + 1
  end;
function RETRIEVE (p: position; var L: list): infotype;
  begin
    if ((p > L.last) or (p < 1))
      then
        ERROR
      else
        RETRIEVE:= L.info[p]
  end;
procedure DELETE (p: position; var L: list);
  var
    q: position;
  begin
    if ((p > L.last) or (p < 1))
      then
        ERROR
      else
        begin
          L.last:= L.last - 1;
          for q:= p to L.last do
            L.info[q]:= L.info[q+1]
        end
  end;
procedure MAKENULL (var L: list);
  begin
    L.last:= 0
  end;
procedure INSERT (x: infotype; p: position; var L: list);
  var
    q: position;
  begin
    if L.last >= maxln
      then
        ERROR
      else
        if ((p > L.last+1) or (p < 1))
          then
            ERROR
          else
            begin
              for q:=L.last downto p do
                L.info[q+1]:= L.info[q];
              L.last:= L.last+1;
              L.info[p]:= x
            end
  end;

{- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}

procedure read_in (var f: text; var L: list);
    {read_in reads the input text file and puts the elements in list L. One
     single digit integer per line is the expected file format.}
  var
    p: position;
    v: infotype;
  begin
    p:= FIRST(L);
    while not eof(f) do
      begin
        readln (f,v);
        INSERT (v, p, L);
        p:= NEXT(p, L)
      end
  end;

procedure print_out (var L: list);
    {print_out prints list L, after a linefeed. The elements are expected to be
     single digit integers (a field width of 2 is used with no formatting) if
     this is not the case the output will look confused.}
  var
    p: position;
  begin
    writeln;
    p:= FIRST(L);
    while p <> ENDLIS(L) do
      begin
        write (RETRIEVE(p, L):2);
        p:= NEXT(p, L)
      end
  end;

function SAME (a,b: infotype): boolean;
    {SAME returns true if its arguments are identical, false otherwise}
  begin
    SAME:= a=b
  end;

procedure purge (var L: list);
    {purge removes duplicate elements from list L}
  var
    p,q: position;  {p will be the "current" position in L, and q will move
                     ahead to find equal elements}
  begin
    p:= FIRST(L);
    while p <> ENDLIS(L) do
      begin
        q:= NEXT(p, L);
        while q <> ENDLIS(L) do
          if SAME (RETRIEVE(p, L), RETRIEVE(q, L))
            then
              DELETE(q, L)
            else
              q:= NEXT(q, L);
        p:= NEXT(p, L)
      end  {while}
  end;   {purge}

{     *  *  *     MAIN PROGRAM CODE STARTS HERE    *  *  *}

begin
  reset(infile1);
  MAKENULL(L);
  read_in (infile1, L);
  print_out (L);
  purge (L);
  print_out (L)
end.
