#include "filasm.h"
struct FilaMStr
{
    size_t tamanho, base, topo;
    void **m;
};
FilaM *FMcria(size_t tamanho)
{
    FilaM *f;
    
    if((f = malloc(sizeof(*f))) == 0)
	return 0;
    if(tamanho == 0)
	f->tamanho = FMTAMANHO + 1;
    else
	f->tamanho = tamanho + 1;
    if((f->m = calloc(f->tamanho, sizeof(void *))) == 0)
    {
	free(f);
	return 0;
    }
    f->topo = f->base = 0;
    return f;
}
void FMdestroi(FilaM *f)
{
    if(f == 0)
	return;
    free(f->m);
    free(f);
}
FilaM *FMesvazia(FilaM *f)
{
    if(f != 0)
	f->topo = f->base;
    return f;
}
size_t FMquantos(FilaM *f)
{
    if(f == 0)
	return 0;
    return f->topo >= f->base ? f->topo - f->base : f->topo - f->base +
	f->tamanho;
}
int FMcheia(FilaM *f)
{
    if(f == 0)
	return 0;
    return FMquantos(f) == f->tamanho - 1;
}
FilaM *FMpoe(FilaM *f, void *d)
{
    if(f == 0 || FMcheia(f))
	return 0;
    f->m[f->topo++] = d;
    if(f->topo == f->tamanho)
	f->topo = 0;
    return f;
}
void *FMtira(FilaM *f)
{
    void *d;
    
    if(f == 0 || f->topo == f->base)
	return 0;
    d = f->m[f->base++];
    if(f->base == f->tamanho)
	f->base = 0;
    return d;
}
#ifdef TESTE
#include <stdio.h>
int main(void)
{
    FilaM *f;
    int val, *pval;
    
    f = FMcria(7);
    
    do
    {
	printf("Valor a inserir (0 para sair, negativo para retirar): ");
	if(scanf("%d", &val) != 1)
	    return EXIT_FAILURE;
	if(val < 0)
	{
	    printf("Retirando: ");
	    if((pval = FMtira(f)) == 0)
		puts("fila vazia!");
	    else
	    {
		printf("Retirei %d.\n", *pval);
		free(pval);
	    }
	}
	else if(val > 0)
	{
	    printf("Inserindo: ");
	    if((pval = malloc(sizeof(int))) == 0)
		return EXIT_FAILURE;
	    *pval = val;
	    if(FMpoe(f, pval) == 0)
		puts("pilha cheia!");
	    else
		printf("Inseri %d.\n", val);
	}
    }
    while(val != 0);
    if(FMcheia(f))
	puts("Esta' cheia!");
    
    if(FMquantos(f) != 0)
    {
	printf("Retirando:");
	while((pval = FMtira(f)) != 0)
	{
	    printf(" %d", *pval);
	    free(pval);
	}
	putchar('\n');
    }
    
    FMdestroi(f);
    return EXIT_SUCCESS;
}
#endif