/*************************************************************************
* *
* Modulo per la gestione di code generiche *
* *
* realizzato dal Gruppo 17 di Lab2 Anno Accademico 1995/96 *
* *
* Lorenzo Claudio Valerio Riccardo Emiliano *
* Coronati Lanconelli Paolini Solmi Trentini *
* *
**************************************************************************/
/*
* Invariante:
*
* Sia E1, E2, ..., En la sequenza degli eventi di chiamata:
* E := { insertQueue(tp, x), ins1Queue(tp, x),
* x = removeQueue(tp), x = outQueue(tp, x) }
*
* Per ogni i, j tale che Ei := insertQueue(tp, x)
* Ej := y = removeQueue(tp) con i < j
* se |{Ek; 0 < k < i; Ek := insertQueue(tp, *)}| +
* |{Ek; 0 < k < j; Ek := ins1Queue(tp, *)}| =
* |{Ek; 0 < k < j; Ek := * = removeQueue(tp); * != NULL}| +
* |{Ek; 0 < k < i; Ek := * = outQueue(tp, *); * != NULL}| +
* |{Ek; i < k < j; Ek := z = outQueue(tp, z);
* (esiste El; 0 < l < j; El := ins1Queue(tp, z))}|
* e (per ogni Ek; i < k < j; Ek := * = removeQueue(tp) => * != x)
* e (per ogni Ek; i < k < j; Ek := * = outQueue(tp, *) => * != x)
* => x = y
*
* e per ogni i, j tale che Ei := ins1Queue(tp, x)
* Ej := y = removeQueue(tp) con i < j
* se |{Ek; i < k < j; Ek := ins1Queue(tp, *)}| =
* |{Ek; i < k < j; Ek := * = removeQueue(tp); * != NULL}| +
* |{Ek; i < k < j; Ek := z = outQueue(tp, z);
* (esiste El; i < l < j; El := ins1Queue(tp, z))}|
* e (per ogni Ek; i < k < j; Ek := * = removeQueue(tp) => * != x)
* e (per ogni Ek; i < k < j; Ek := * = outQueue(tp, *) => * != x)
* => x = y
*
* e per ogni i, j tale che Ei := insertQueue(tp, x)
* Ej := y = outQueue(tp, x) con i < j
* se (per ogni Ek; i < k < j; Ek := * = removeQueue(tp) => * != x)
* e (per ogni Ek; i < k < j; Ek := * = outQueue(tp, *) => * != x)
* => x = y
*
* e per ogni i, j tale che Ei := ins1Queue(tp, x)
* Ej := y = outQueue(tp, x) con i < j
* se (per ogni Ek; i < k < j; Ek := * = removeQueue(tp) => * != x)
* e (per ogni Ek; i < k < j; Ek := * = outQueue(tp, *) => * != x)
* => x = y
*/
#include "../h/const.h"
typedef struct elem_t
{
struct elem_t *next;
} elem_t;
/* -----------------------------------------------------------------------
* Funzioni per la gestione di una free-list, realizzata come una
* lista concatenata semplice
*/
/*
* Costruisce la free-list sull'array di elementi passato.
* Restituisce un puntatore alla free-list.
* sizeof(array) = noelem * elsize
* noelem >= 1
* elsize = sizeof(tipo_elemento_passato)
*/
elem_t *
initQueue(array, noelem, elsize)
elem_t *array;
register int noelem, elsize;
{
register elem_t *p = array;
while (--noelem)
p = p->next = (elem_t *) ((char *) p + elsize);
p->next = NULL;
return array;
}
/*
* Alloca un elemento prelevandolo dalla free-list.
* Restituisce NULL nel caso la free-list sia vuota
*/
elem_t *
AllocQueue(fp)
register elem_t **fp;
{
register elem_t *retp = *fp;
if (retp != NULL)
*fp = (*fp)->next;
return retp;
}
/*
* Dealloca un elemento riponendolo nella free-list
*/
freeQueue(p, fp)
elem_t *p, **fp;
{
p->next = *fp;
*fp = p;
}
/* ----------------------------------------------------------------------
* Funzioni di gestione di code generiche; la coda e` gestita come una
* lista circolare il cui ultimo elemento e` memorizzato in un puntatore.
* Nel caso di lista vuota tale puntatore sara` NULL
*/
/*
* Inserisce in coda
*/
insertQueue(tp, p)
register elem_t **tp, *p;
{
if (*tp == NULL)
*tp = p->next = p;
else
{
p->next = (*tp)->next;
*tp = (*tp)->next = p;
}
}
/*
* Inserisce in testa
*/
ins1Queue(tp, p)
register elem_t **tp, *p;
{
if (*tp == NULL)
*tp = p->next = p;
else
{
p->next = (*tp)->next;
(*tp)->next = p;
}
}
/*
* Rimuove il primo elemento della coda
*/
elem_t *
removeQueue(tp)
register elem_t **tp;
{
register elem_t *retp = NULL;
if (*tp != NULL)
{
/*
* controllo che ci sia piu` di 1 nodo in lista, in caso
* contrario mettera` il puntatore a NULL (lista vuota)
*/
if ((retp = (*tp)->next) == *tp)
*tp = NULL;
else
(*tp)->next = retp->next;
}
return retp;
}
/*
* Rimuove un elemento dato dalla coda; se l'elemento cercato
* non esiste, viene restituito NULL
*/
elem_t *
outQueue(tp, p)
elem_t **tp, *p;
{
register elem_t *prevp = *tp;
if (prevp == NULL)
return NULL;
else
{
/*
* Se la coda non e' vuota, la scandisce alla ricerca
* dell'elemento p
*/
while (prevp->next != p && prevp->next != *tp)
prevp = prevp->next;
if (prevp->next == p)
{
/* Gestione ultimo elemento della coda */
if (prevp == prevp->next)
*tp = NULL;
else
{
/*
* Se l'elemento ricercato coincide con
* l'ultimo elemento della coda, aggiorna il
* puntatore tp
*/
if (p == *tp)
*tp = prevp;
prevp->next = p->next;
}
return p;
} else
return NULL;
}
}
/*
* Restituisce il puntatore al primo elemento della coda
*/
elem_t *
headQueue(tp)
elem_t *tp;
{
return (tp == NULL) ? (elem_t *) NULL : tp->next;
}