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

#define BUFFSIZE 1024

void dointeractive(void);
void dosort(char *filename, char *outfilename);
void dousage(char *arg0);
int sortfunction(const void *ain, const void *bin);

typedef struct
	{
	char *word;
	char *pattern;
	} Word;

int main(int argc, char *argv[])
{
/* if no arguments, do an interactive session */
if (argc<=1)
	{
	dointeractive();
	return -1;
	}
	
/* else, sort the file whose path was first argument */
if (argc==3 && strcmp(argv[1],"-h"))
	{
	dosort(argv[1],argv[2]);
	return -1;
	}
	
/* They're clueless. let's give the user some help.  */
dousage(argv[0]);

return 0;
}

void dousage(char *arg0)
{
printf("Usage: %s <infilename> <outfilename>\n",arg0);

}

void dointeractive(void)
{
char infilename[BUFFSIZE];
char outfilename[BUFFSIZE];

printf("What is the name of the dictionary you wish to prepare?\n:");
gets(infilename);

if (infilename[0]=='\n')
	return;

printf("Write to what file?\n:");
gets(outfilename);

if (outfilename[0]=='\n')
	return;

dosort(infilename,outfilename);
}

void dosort(char *filename, char *outfilename)
{
int allocatedwords=0;
int thisword=0;
Word *array=NULL;
char buffer[BUFFSIZE];
FILE *file;
int length=0;
int loop=0,a=0,end=0;
char thisletter;
int memoryallocated=0;
char map[256];
int i,outpos;

file=fopen(filename,"r");
if (file==NULL)
	return;
	
printf("loading dictionary...\n");

while (fgets(buffer,BUFFSIZE,file))
	{
	/* skip any lines of numbers */
	if (atoi(buffer)>0)
		continue;
		
	if (thisword>=allocatedwords)
		{
		allocatedwords+=10000;
		array=realloc(array, allocatedwords*sizeof(Word));
		if (array==NULL)
			{
			printf("could not allocate %i bytes\n",memoryallocated+allocatedwords*sizeof(Word));
			exit(0);
			}
		}
	
	length=strlen(buffer);
	
	i=0;
	outpos=0;

	/* strip the string of anything but letters */
	while(buffer[i]!=0)
	  {
	    if (isalpha(buffer[i]))
	      {
		buffer[outpos]=buffer[i];
		outpos++;
	      }
	    else
	      length--;

	    i++;
	  }

	buffer[length]='\0';
	
	array[thisword].word=malloc(length+1);
	array[thisword].pattern=malloc(length+1);
	if (array[thisword].pattern==NULL || array[thisword].pattern==NULL)
		{
		printf("could not allocate %i bytes\n",memoryallocated+allocatedwords*sizeof(Word));
		exit(0);
		}
			
	memcpy(array[thisword].word,buffer,length+1);
	memoryallocated+=2*(length+1);
	thisword++;
	}

fclose(file);

printf("patterning...\n");

for (loop=0;loop<thisword;loop++)
	{
	length=strlen(array[loop].word);

	/* clear the map */
	for (a='A';a<='Z';a++)
		map[a]=0;
	
	thisletter='A';
	
	for (a=0;a<length;a++)
		{
		if (map[(int) array[loop].word[(int) a]]==0)
			{
			map[(int) array[loop].word[(int) a]]=thisletter;
			thisletter++;
			}
		array[loop].pattern[(int) a]=map[(int) array[loop].word[(int) a]];
		}
	
	array[loop].pattern[(int) a]=0;
	
	}

printf("sorting...\n");
	
qsort(array,thisword,sizeof(Word),sortfunction);

printf("writing...\n");

file=fopen(outfilename,"w+");
fprintf(file,"\n");

loop=0;

while (loop<thisword-1)
	{
	end=loop+1;
	while (!strcmp(array[end].pattern,array[loop].pattern))
		end++;
	
	fprintf(file,"%i\n",end-loop);
	for (a=loop;a<end;a++)
		fprintf(file,"%s\n",array[a].word);

	loop=end;
	}
	
fclose(file);

printf("done with %i words!\n",thisword);
}

int sortfunction(const void *ain, const void *bin)
{
Word *a=(Word*) ain;
Word *b=(Word*) bin;

return (strcmp(a->pattern,b->pattern));
}

