/* Make a list of all autodocs in short format */

#include <exec/memory.h>

#include "global.h"
#include "misc.h"
#include "adfile.h"
#include "shortad.h"

/***********************************************/

struct ShortAutodocEntry *ShortAutodocArray;

/***********************************************/

static int InternalSearchShortAutodoc(char *Name)
{
	int Index;

	for (Index = 1; Index <= (int) ShortAutodocArray[Index].Name; Index++)
	{
		if (!strcmp(ShortAutodocArray[Index].Name, Name))
		{
			return (Index);
		}
	}
	return (0);
}

/***********************************************/

static int GetResidentIndex(struct AutodocNode *AutodocNode)
{
	static struct
	{
		char *Name;
		int Length;
	}
	ResidentTypes[] =
	{
		"library", 7,			/* 0 */
			"device", 6,		/* 1 */
			"datatype", 8,		/* 2 */
			"lib", 3,			/* 3 */
			"resource", 8		/* 4 */
	};

	int Index;
	char *ResidentTypeEnd;
	int Length;

	if (AutodocNode)
	{
		ResidentTypeEnd = FindSlash(AutodocNode->Node.Name);
		Length = ResidentTypeEnd - AutodocNode->Node.Name;
		for (Index = 0; Index < 5; Index++)
		{
			if (ResidentTypes[Index].Length <= Length)
			{
				if (!memcmp(ResidentTypeEnd - ResidentTypes[Index].Length, ResidentTypes[Index].Name, ResidentTypes[Index].Length))
				{
					return (Index);
				}
			}
		}
	}
	return (5);
}

/***********************************************/

BOOL MakeShortAutodocs(void)
{
	struct AutodocNode *TempNode, *PrevNode;
	int Index;
	int CurrentNode;
	int ExistingNode;

	if (ShortAutodocArray = AllocVec((((int) AutodocArray[0]) + 1) * sizeof(struct ShortAutodocEntry), MEMF_CLEAR))
	{
		for (CurrentNode = 1; CurrentNode <= (int) AutodocArray[0]; CurrentNode++)
		{
			if (Break())
				return (FALSE);
			if ((int) ShortAutodocArray[0].Name && (ExistingNode = InternalSearchShortAutodoc(FindSlash(AutodocArray[CurrentNode]->Node.Name) + 1)))
			{
				Index = GetResidentIndex(AutodocArray[CurrentNode]);
				TempNode = ShortAutodocArray[ExistingNode].AutodocNode;
				PrevNode = NULL;
				while (Index > GetResidentIndex(TempNode))
				{
					PrevNode = TempNode;
					TempNode = TempNode->ShortLink;
				}
				AutodocArray[CurrentNode]->ShortLink = TempNode;
				if (PrevNode)
				{
					PrevNode->ShortLink = AutodocArray[CurrentNode];
				}
				else
				{
					ShortAutodocArray[ExistingNode].AutodocNode = AutodocArray[CurrentNode];
				}
			}
			else
			{
				(int) (ShortAutodocArray[0].Name)++;
				ShortAutodocArray[(int) ShortAutodocArray[0].Name].Name = FindSlash(AutodocArray[CurrentNode]->Node.Name) + 1;
				ShortAutodocArray[(int) ShortAutodocArray[0].Name].AutodocNode = AutodocArray[CurrentNode];
			}
		}
		for (CurrentNode = 1; CurrentNode < (int) (ShortAutodocArray[0].Name); CurrentNode++)
		{
			if (Break())
				return (FALSE);
			for (Index = CurrentNode + 1; Index <= (int) (ShortAutodocArray[0].Name); Index++)
			{
				if (strcmp(ShortAutodocArray[Index].Name, ShortAutodocArray[CurrentNode].Name) < 0)
				{
					TempNode = ShortAutodocArray[Index].AutodocNode;
					ShortAutodocArray[Index].AutodocNode = ShortAutodocArray[CurrentNode].AutodocNode;
					ShortAutodocArray[CurrentNode].AutodocNode = TempNode;
					TempNode = (struct AutodocNode *) ShortAutodocArray[Index].Name;
					ShortAutodocArray[Index].Name = ShortAutodocArray[CurrentNode].Name;
					ShortAutodocArray[CurrentNode].Name = (char *) TempNode;
				}
			}
		}
		return (TRUE);
	}
	PrintFault(ERROR_NO_FREE_STORE, NULL);
	return (FALSE);
}

/***********************************************/

struct AutodocNode *SearchShortAutodoc(char *Name)
{
	int OldIndex;
	int Upper, Lower;
	int Index;
	int Result;
	struct AutodocNode *AutodocNode;

	Lower = 1;
	Upper = (int) (ShortAutodocArray[0].Name) + 1;
	Index = 0;
	do
	{
		OldIndex = Index;
		Index = (Upper + Lower) / 2;
		if (!(Result = strcmp(ShortAutodocArray[Index].Name, Name)))
		{
			Upper = strlen(CurrentUnit);
			AutodocNode = ShortAutodocArray[Index].AutodocNode;
			while (AutodocNode)
			{
				if (!memcmp(CurrentUnit, AutodocNode->Node.Name, Upper))
				{
					if (AutodocNode->Node.Name[Upper] == '/')
					{
						return (AutodocNode);
					}
				}
				AutodocNode = AutodocNode->ShortLink;
			}
			AutodocNode = ShortAutodocArray[Index].AutodocNode;
			if (AutodocNode == CurrentAutodocNode)
			{
				AutodocNode = AutodocNode->ShortLink;
			}
			return (AutodocNode);
		}
		if (Result < 0)
		{
			Lower = Index;
		}
		else
		{
			Upper = Index;
		}
	}
	while (Index != OldIndex);
	return (NULL);
}

/***********************************************/

BOOL PrintShortAutodocList(void)
{
	int Index;

	if (FPrintf(XRefFile, "\n/* Functions and Commands, without subsystem */\n") == -1)
	{
		PrintFault(IoErr(), Arguments.XRefFile);
		return (FALSE);
	}
	for (Index = 1; Index <= (int) ShortAutodocArray[0].Name; Index++)
	{
		if (FPrintf(XRefFile, "\x22%s\x22 \x22%s\x22 0 %ld /* %s */\n", ShortAutodocArray[Index].Name, ShortAutodocArray[Index].AutodocNode->File, ShortAutodocArray[Index].AutodocNode->Type, ShortAutodocArray[Index].AutodocNode->Node.Name) == -1)
		{
			PrintFault(IoErr(), Arguments.XRefFile);
			return (FALSE);
		}
	}
	return (TRUE);
}
