#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <search.h>

struct item {
	char name [12];
	unsigned int line;		 		/* referenced line number */
	unsigned char flag;		/* true if definition */
	unsigned char filenumber;	/* file number */
	struct item *rp;
	struct item *lp;
	};


struct item *ptr, *ptr2, *ptr3;

char filename [20][15] = {"*MAIN*","","","","","","","","","","","","","","","","","","",""};

unsigned long count = 0;

int k = 0;
char last [15] = "";
FILE *file;

int compare(struct item *, struct item *);
void print_item(struct item *);

main()

{
	char buffer[80];
	int i,j,k;

	file = fopen("xref.dat","rt");
	ptr = 0;
	for (i=0; 1; i++)
		{
		if (!fgets(buffer, 80, file))
			break;
		if (!(ptr2 = (struct item *)calloc(1, sizeof(struct item))))
			{
			printf ("Couldn't allocate memory for item %d\n",i);
			exit(1);
			}
		memcpy(ptr2->name, buffer, 12);
		ptr2->filenumber = atoi(&buffer[13]);
		if (buffer[16] == ' ')
			ptr2->filenumber = 0;
		if (filename[ptr2->filenumber][0] == 0)
			memcpy(filename[ptr2->filenumber], &buffer[16], 8);
		ptr2->line = atoi(&buffer[30]);
		ptr2->flag = (buffer[34] == '*');
		if (!ptr)
			ptr = ptr2;
		else
			{
			for (ptr3=ptr; 1;)
				{
				if (compare(ptr3, ptr2) > 0)
					{
					if (!(ptr3->rp))
						{
						ptr3->rp = ptr2;
						break;
						}
					ptr3 = ptr3->rp;
					}
				else
					{
					if (!(ptr3->lp))
						{
						ptr3->lp = ptr2;
						break;
						}
					ptr3 = ptr3->lp;
					}
				}
			}
		}
	fclose (file);
	printf ("Compare called %ld times for %d items\n",count,i);
	file = fopen("crossref.lst","wt"); 
	fprintf(file,
		"                 DEFINITION     REFERENCES:\n");
	fprintf(file,
		"  SYMBOL         FILE   LINE     FILE   LINE     FILE   LINE     FILE   LINE     FILE   LINE     FILE   LINE     FILE   LINE\n");
	fprintf(file,
		"============   ======== ====   ======== ====   ======== ====   ======== ====   ======== ====   ======== ====   ======== ====\n\n");

	print_item(ptr);

	fprintf(file,"\n\n");
	fclose(file);
}

void print_item (ptr)
struct item *ptr;

{
	if (!ptr)
		return;
	print_item(ptr->rp);
	if (memcmp(last, ptr->name, 12))
		{
		if (k)
			{
			fprintf(file,"\n");
			}
		k = 1;
		fprintf(file,"%-12.12s   ",ptr->name);
		memcpy(last, ptr->name, 12);
		if (ptr->flag)
			{
			fprintf(file,"%-8.8s %4d   ",filename[ptr->filenumber],ptr->line);
			}
		else
			{
			fprintf(file,"                %-8.8s %4d   ",filename[ptr->filenumber],ptr->line);
			k++;
			}
		}
	else
		{
		if (ptr->flag)		/* second def - shouldn't happen */
			{
			if (k)
				{
				k=1;
				fprintf(file,"\n");
				}
			fprintf(file,"               %-8.8s %4d   ",filename[ptr->filenumber],ptr->line);
			}
		else
			{
			if (k == 7)
				{
				k = 0;
				fprintf(file,"\n");
				}
			if (!k)
				{
				k=1;
				fprintf(file,"                               ");
				}
			fprintf(file,"%-8.8s %4d   ",filename[ptr->filenumber],ptr->line);
			k++;
			}
		}
	print_item(ptr->lp);
}

int compare(p1, p2)
struct item *p1, *p2;

{
	int i;

	count++;
	if (i=strncmp(p1->name, p2->name, 12))
		return (i);
	if (p1->flag != p2->flag)
		return (p2->flag ? 1 : -1);
	if (i = (p1->filenumber - p2->filenumber))
		return (i);
	return (p1->line - p2->line);
}

