/*---------------------------------------------------------------
                           linkedlist

Il  programma  realizza  un  possibile  uso  di una lista di tipo
linked semplice. Legge da input dei valori interi e li  memorizza
consecutivamente  negli  elementi di una lista. I relativi punta-
tori sono arrangiati in modo  che  seguendoli  i  valori  immessi
siano ordinati in maniera  crescente. Un puntatore ausilisario e-
sterno indica l'elemento di partenza.


     Formato dei dati in ingresso

op[valore]

ove:
   op  e'  il  codice  di  1  carattere  che  indica l'operazione
     desiderata.  Valori possibili:
        c fornisce il numero di elementi presenti
        e fine del programma
        i inserzione (il valore e' obbligatorio)
        l lista i valori presenti, seguendo i link con  l'ausilio
          di un link esterno che punta al primo elemento
        q fine del programma
        t lista in maniera posizionale i valori presenti
   valore  e'  un numero intero. Obbligatorio  nel caso di inser-
     zione, e' ignorato -se presente- con le altre operazioni


     Messaggistica

lista piena
     non e' possibile inserire un nuovo elemento (la capacita' di
     default della lista e': 20)

lista vuota
     nella lista non ci sono elementi

manca il valore da immettere
     autoesplicativo

operazione ignota
     vedi elenco sopra
---------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define And   &&
#define Not   !
#define True  1
#define False Not True
typedef struct elem {int val, pross;} strel;

/*----------configurazione----------*/
const int max_elem_lista = 20;
const int max_len_linea = 15;
/*--------fineconfigurazione--------*/

int main (void)
{
  char          *riga;
  int           basta, len, nel, primo;
  strel         *ll;
  void          elenco (strel *, int);
  void          insert (strel *, int, int, int *);
  void          lista (strel *, int, int);

  basta = False;
  nel = primo = 0;
  ll = (strel *) calloc (max_elem_lista, sizeof (strel));
  riga = (char *) calloc (max_len_linea, sizeof (char));
  printf ("formato dei dati:\n");
  printf ("     c        fornisce il numero dei dati presenti\n");
  printf ("     e        uscita\n");
  printf ("     ixxxxx   inserisce il numero xxxx\n");
  printf ("     l        lista ordinata dei dati presenti\n");
  printf ("     t        lista posizionale dei dati presenti\n");
  printf ("> ");
  fgets (riga, max_len_linea, stdin);
  while (Not basta And Not feof (stdin))
    {
      len = strlen(riga);
      riga [--len] = '\0';
      switch (riga [0])
        {
          default:
            fprintf (stderr, "%c operazione ignota\n", riga[0]);
            break;
          case 'c':
            printf ("elementi presenti: %d\n", nel);
            break;
          case 'e':
          case 'q':
            basta = True;
            break;
          case 'i':
            if (len == 1)
              fprintf (stderr, "manca il valore da immettere\n");
            else
              {
                if (nel == (max_elem_lista - 1))
                  printf ("lista piena\n");
                else
                  {
                    insert (ll, nel, atoi (riga + 1), &primo);    
                    ++nel;
                  }
              }
            break;
          case 'l':
          case 't':
            if (nel)
              {
                if (riga [0] == 'l')
                  lista (ll, nel, primo);
                else
                  elenco (ll, nel);
              }
            else
              printf ("lista vuota\n");
            break;
        }
      if (Not basta)
        {
          printf ("> ");
          fgets (riga, max_len_linea, stdin);
        }
    }
  free ((void *) ll);
  free ((void *) riga);
  exit (EXIT_SUCCESS);
}

void lista (strel *ll, int l, int primo)
{
  int   j, k, tmp;

  j = primo;
  for (k = 0; k < l; k++)
    {
      printf ("%d\n", ll[j].val);
      tmp = ll[j].pross;
      j = tmp;
    }
}

void elenco (strel *ll, int l)
{
  int i;

  for (i = 0; i < l; i++)
    printf ("%d\n", ll[i].val);
}

void insert (strel *ll, int i, int numero, int *primo)
{
  int   basta, j, k, prec, tmp;

  j = *primo;
  prec = -1;
  basta = True;
  ll[i].val = numero;
  ll[i].pross = 0;
  for (k = 0; k < i; k++)
    {
      if (ll[j].val > numero)
        {
          basta = False;
          break;
        }
      else
        {
          tmp = ll[j].pross;
          prec = j;
          j = tmp;
        }
    }
  if (basta == False)
    {
      if (prec < 0)
        *primo = i;
      if (prec >= 0)
        ll[prec].pross = i;
      ll[i].pross = j;
    }
  else
    {
      if (k == 0)
        *primo = i;
      else
        ll[prec].pross = i;
    }
}