/*program adtdemo
     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.*/

#include <stdio.h>
#include <stdlib.h>
#define maxln 100

typedef int position;
typedef int infotype;
typedef struct {
  infotype info[maxln];
  position last;
} list;

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/


main()
{
  void ERROR(void);
  position FIRST(list *);
  position ENDLIS(list *);
  position NEXT(position, list *);
  infotype RETRIEVE(position, list *);
  void DELETE(position, list *);
  void MAKENULL(list *);
  void INSERT(infotype, position, list *);
  void print_out(list *);
  void purge(list *);
  int SAME(infotype, infotype);

  list L;
  position p;
  infotype v;
  FILE *fp;

  MAKENULL(&L);
  if((fp = fopen("INDATL", "r"))==NULL) ERROR();
  p= FIRST(&L);
  do {
    fscanf(fp,"%d",&v);
    INSERT (v, p, &L);
    p= NEXT(p, &L);
  } while (!feof(fp));
  fclose(fp);
  print_out (&L);
  purge(&L);
  print_out (&L);
  return 0;
}

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

void ERROR (void)
{
  exit (1);
}
position FIRST (list *L)
{
  return 1;
}
position ENDLIS (list *L)
{
  return L->last + 1;
}
position NEXT (position p, list *L)
{
  if ((p > L->last) || (p < 1)) ERROR();
  else return ++p;
}
infotype RETRIEVE (position p, list *L)
{
  if ((p > L->last) || (p < 1)) ERROR();
  else return L->info[p];
}
void DELETE (position p, list *L)
{
  position q;

  if ((p > L->last) || (p < 1)) ERROR();
  else {
    L->last--;
    for (q=p; q<=L->last; q++) L->info[q] = L->info[q+1];
  }
}
void MAKENULL (list *L)
{
  L->last= 0;
}
void INSERT (infotype x, position p, list *L)
{
  position q;

  if (L->last >= maxln) ERROR();
  else if ((p > L->last+1) || (p < 1)) ERROR();
  else {
    for (q=L->last; q>=p; q--)  L->info[q+1]= L->info[q];
    L->last++;
    L->info[p]= x;
  }
}

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/


void print_out (list *L)
   /*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.*/
{
  position p;

  printf("\n");
  p= FIRST(L);
  while (p != ENDLIS(L)) {
    printf("%3d",RETRIEVE(p, L));
    p= NEXT(p, L);
  }
  printf("\n");
}

int SAME (infotype a, infotype b)
    /*SAME returns true if its arguments are identical, false otherwise*/
{
  return a==b;
}

void purge (list *L)
    /*purge removes duplicate elements from list L*/
{
  position p, q;  /*p will be the "current" position in L, and q will move
                     ahead to find equal elements*/
  p= FIRST(L);
  while (p != ENDLIS(L)) {
    q= NEXT(p, L);
    while (q != ENDLIS(L)) {
      if (SAME (RETRIEVE(p, L), RETRIEVE(q, L))) DELETE(q, L);
      else q= NEXT(q, L);
    }
    p= NEXT(p, L);
  }
}
