I64 HashEntrySize(CHashSrcSym *tmph)
{//Logical size of a std system hash entry.
	CDebugInfo	*debug_info;
	CBinFile	*bfh;

	switch (HashTypeNum(tmph))
	{
		case HTt_DEFINE_STR:
			return MSize(tmph(CHashDefineStr *)->data);

		case HTt_GLOBAL_VAR:
		case HTt_CLASS:
		case HTt_INTERNAL_TYPE:
			return tmph(CHashClass *)->size;

		case HTt_FUN:
			if (debug_info = tmph->debug_info)
				return debug_info->body[debug_info->max_line + 1 - debug_info->min_line] - debug_info->body[0];
			else
				return -1;

		case HTt_FILE:
			return MSize(tmph(CHashGeneric *)->user_data0);

		case HTt_MODULE:
			if (StrCompare(tmph->str, KERNEL_MODULE_NAME))
				return MSize(tmph(CHashGeneric *)->user_data0);
			else
			{
				bfh = mem_boot_base - sizeof(CBinFile);
				return bfh->file_size;
			}

		case HTt_WORD:
			return StrLen(tmph->str);
	}

	return -1;
}

I64 HashEntrySize2(CHashSrcSym *tmph)
{//Memory size of a std system hash entry.
	CDebugInfo	*debug_info;
	I64			 res = MSize2(tmph);

	if (!(tmph->type & HTT_DICT_WORD))
		res += MSize2(tmph->str);
	if (tmph->type & HTG_SRC_SYM)
	{
		res += MSize2(tmph->src_link);
		res += MSize2(tmph->idx);
		res += MSize2(tmph->import_name);
		res += LinkedListSize(tmph->ie_list);
		if (tmph->type & (HTT_FUN | HTT_EXPORT_SYS_SYM))
			res += MSize2(tmph->debug_info);
		if (tmph->type & HTT_CLASS)
			res += MemberListSize(tmph);
		else if (tmph->type & HTT_FUN)
		{
			res += MemberListSize(tmph);
			if (debug_info = tmph->debug_info)
//This should be $LK,"MSize",A="MN:MSize"$() but it would crash on AOT .BIN file funs.
				res += debug_info->body[debug_info->max_line + 1 - debug_info->min_line] - debug_info->body[0];
		}
		else if (tmph->type & HTT_DEFINE_STR)
			res += MSize2(tmph(CHashDefineStr *)->data);
		else if (tmph->type & HTT_GLOBAL_VAR)
		{
			res += LinkedListSize(tmph(CHashGlobalVar *)->dim.next);
			if (!(tmph(CHashGlobalVar *)->flags & GVF_ALIAS))
				res += MSize2(tmph(CHashGlobalVar *)->data_addr);
			if (tmph(CHashGlobalVar *)->fun_ptr)
				res += HashEntrySize2(tmph(CHashGlobalVar *)->fun_ptr - tmph(CHashGlobalVar *)->fun_ptr->ptr_stars_count);
		}
	}
	else if (tmph->type & HTT_FILE)
		res += MSize2(tmph(CHashGeneric *)->user_data0);
	else if (tmph->type & HTT_MODULE && StrCompare(tmph->str, KERNEL_MODULE_NAME))
		res += MSize2(tmph(CHashGeneric *)->user_data0);

	return res;
}

I64 HashTableSize2(CHashTable *table)
{//Memory size of std system hash table and all entries.
	I64			 i, res = 0;
	CHashSrcSym	*tmph;

	if (!table)
		return 0;
	for (i = 0; i <= table->mask; i++)
	{
		tmph = table->body[i];
		while (tmph)
		{
			res += HashEntrySize2(tmph);
			tmph = tmph->next;
		}
	}
	res += MSize2(table->body);
	res += MSize2(table);
	return res;
}

U0 MapFileWrite(CHashTable *h, U8 *map_name, U8 drv_let)
{
	CHashSrcSym	*tmph;
	I64			 i, size;
	U8			*src_link;
	CDoc		*doc;
	CDocBin		*tmpb;
	CDebugInfo	*debug_info;

	doc = DocNew(map_name);
	doc->flags |= DOCF_NO_CURSOR;
	for (i = 0; i <= h->mask; i++)
	{
		tmph = h->body[i];
		while (tmph)
		{
			if (tmph->src_link && !(tmph->type & (HTF_IMPORT | HTF_PRIVATE)))
			{
				src_link = StrNew(tmph->src_link);
				if (drv_let && StrLen(src_link) >= 4)
					src_link[3] = drv_let;
				if (debug_info = tmph->debug_info)
				{
					size = offset(CDebugInfo.body) + sizeof(U32) * (debug_info->max_line + 2 - debug_info->min_line);
					if (size > MSize(debug_info))
					{
						"Corrupt Map Entry\n";
						debug_info = NULL;
					}
					else
					{
						if (debug_info->min_line <= debug_info->max_line)
						{
							tmpb = CAlloc(sizeof(CDocBin));
							tmpb->size = size;
							tmpb->data = MAlloc(size);
							MemCopy(tmpb->data, debug_info, size);
							tmpb->num = doc->cur_bin_num++;
							tmpb->use_count = 1;
							QueueInsert(tmpb, doc->bin_head.last);
						}
						else
							debug_info = NULL;
					}
				}
				if (debug_info)
					DocPrint(doc,"$$LK,\"%s\",A=\"%s\",BI=%d$$\n", tmph->str, src_link, tmpb->num);
				else
					DocPrint(doc,"$$LK,\"%s\",A=\"%s\"$$\n", tmph->str, src_link);

				Free(src_link);
			}
			tmph = tmph->next;
		}
	}
	DocBinsValidate(doc);
	DocWrite(doc);
	DocDel(doc);
}

