/*
	This eats a MUSH 2.0 flat database, and dumps a list of attribute
numbers that are actually *used*, in order.

	It assumes 8 bit chars.

	It chews in the entire DB, looking for lines that start with
'>', an actual attribute header line, see. It maintains (and grows as
necessary) a bitmap (I got fancy, nyah) of attribute numbers actually
used. You must have a working realloc(). When it's done,
it walks the bitmap, spitting out a list of the attribute numbers it
found, in order. It ignores the attribute numbers under A_USER_START
from filter.h.

	Finally, it writes a line on stderr indicating exactly how many
attribute numbers are used, and approximately (don't ask) how many
it found unused.

	Input DB in stdout, numbers file on stdout.
*/

#define SETBIT(a,n) ( (a)[n >> 3] |= (1 << ((n) & 0x07)) )
#define CLRBIT(a,n) ( (a)[n >> 3] &= ~(1 << ((n) & 0x07)) )
#define ISSET(a,n) ( (a)[n >> 3] & (1 << ((n) & 0x07)) )

#include <stdio.h>
#include "filter.h"

char *grow_map();

main(ac,av)
int	ac;
char *av[];
{
	int	ch;
	char	*bitmap;
	int	size = 0;
	int	i,used,avail;
	int	newsize;
	int	attrnum;
	int	got_attrcount = 0;

	/* Get an initial bitmap and zero it */

	size = 16;
	bitmap = (char *)malloc(size >> 3);
	
	if(!bitmap){
		fprintf(stderr,"Initial malloc failed. Aborting.\n");
		exit(1);
	}

	for(i=1; i < (size >> 3); i++)
		bitmap[i] = (char)0;

	/* Walk across stdin looking for +N and > lines. */

	while((ch = getchar()) != EOF){
		if(!got_attrcount && ch  == '+'){
			if((ch = getchar()) == 'N'){
				scanf("%d",&newsize);
				got_attrcount = 1;
				if(newsize > size){
					bitmap = grow_map(bitmap,size,newsize+64);
					size = newsize+64;
				}
			} else {
				ungetc(ch,stdin);
			}
		} else if(ch == '>'){
			scanf("%d",&attrnum);
#ifdef DEBUG_FILT1
			fprintf(stderr,"Read attrnum %d, %x\n",attrnum,
				bitmap[attrnum >> 3]);
#endif

			if(attrnum <= A_USER_START)
				continue;

			if(attrnum > size){
				bitmap = grow_map(bitmap,size,attrnum+64);
				size = attrnum+64;
			}
			SETBIT(bitmap,attrnum);
#ifdef DEBUG_FILT1
			fprintf(stderr,"%x\n",
				bitmap[attrnum >> 3]);
#endif
		}
		/* Eat up the rest of the line. */

		while(ch != '\n' && ch != EOF)
			ch = getchar();
	}

	/* Now walk across it, writing out the numbers actually used */

	used = avail = 0;
	for(i = 1;i <= size;i++){
		if(ISSET(bitmap,i)){
			used++;
			fprintf(stdout,"%d\n",i);
		} else {
			avail++;
		}
	}

	/* Dump stats on stderr */

	fprintf(stderr,"Used attr numbers: %d, Free attr numbers (approx): %d\n",
		used,avail - A_USER_START);

	
}

char *
grow_map(map,old,new)
char	*map;
int	old;
int	new;
{
	char	*newmap;

	/* Make it bigger */
	newmap = (char *)realloc(map,new >> 3);
	if(!newmap){
		fprintf(stderr,"realloc failed growing bitmap.\n");
		exit(1);
	}

	/* Clear new entries */

	for(old++;old < new;old++)
		CLRBIT(newmap,old);

	return(newmap);
}
