/*---------------------------------------------------------------
                              stack

Il  programma  fa uso di uno stack. Legge da input dei valori in-
teri e li impila, mettendoli in ordine. Viene fatto  uso  di  una
pila ausiliaria.


     Formati dei dati

op[valore]
ove:
  op  e'  un codice (1 carattere) che indica l'azione desiderata.
     Valori ammessi:
        c fornisce il numero di elementi presenti nella pila
        d elimina l'elemento in cima allo stack
        e fine del programma
        i inserzione di un nuovo valore
        l lista gli elementi presenti
        q fine del programma
  valore e' una quantita' intera. La presenza e' obbligatoria nel
     caso dell'inserzione.


     Messaggistica

manca il valore da immettere
     autoesplicativo

operazione ignota
     vedi elenco sopra

stack gia' vuoto
     non e' possibile eliminare un elemento

stack pieno
     non e' possibile inserire un nuovo elemento (la capacita' di
     default e': 20)

stack vuoto
     non ci sono elementi
---------------------------------------------------------------*/

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

#define And   &&
#define Not   !
#define True  1
#define False Not True

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

int main (void)
{
  char  *riga;
  int   basta, i, index, len, *stack;
  void  insert (int *, int, int);

  basta = False;
  index = 0;
  riga = (char *) calloc (max_len_linea, sizeof (char));
  stack = (int *) calloc (max_elem_stack, sizeof (int));
  printf ("formato dei dati:\n");
  printf ("     c        fornisce il numero dei dati presenti\n");
  printf ("     d        eliminazione dell'ultimo dato presente\n");
  printf ("     e        uscita\n");
  printf ("     ixxxxx   inserisce il numero xxxx\n");
  printf ("     l        lista i 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", index);
            break;
          case 'd':
            if (index)
              --index;
            else
              printf ("stack gia' vuoto\n");
            break;
          case 'e':
          case 'q':
            basta = True;
            break;
          case 'i':
            if (len == 1)
              fprintf (stderr, "manca il valore da immettere\n");
            else
              {
                if (index == (max_elem_stack - 1))
                  printf ("stack pieno\n");
                else
                  {
                    insert (stack, index, atoi (riga + 1));    
                    ++index;
                  }
              }
            break;
          case 'l':
            if (index)
              for (i = 0; i < index; i++)
                printf ("%d\n", stack [i]);
            else
              printf ("stack vuoto\n");
            break;
        }
      if (Not basta)
        {
          printf ("> ");
          fgets (riga, max_len_linea, stdin);
        }
    }
  free ((void *) riga);
  free ((void *) stack);
  exit (EXIT_SUCCESS);
}

void insert (int *s, int i, int val)
{
  int   j = 0, k, *tmp;

  tmp = (int *) malloc (i * sizeof (int));
  for (k = i - 1; k >= 0; k--)
    if (s [k] > val)
      tmp [j++] = s[k];
    else 
      break;
  s [++k] = val;
  for (--j; j >= 0; j--)
    s [++k] = tmp [j];
  free ((void *) tmp);
}