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 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);
}