#help_index "Debugging/Dump"
Bool ClassRep2(CDoc *doc, U8 *_d, U8 *class_name=lastclass, Bool u8_chars, Bool force,
                           I64 depth, I64 max_depth, Bool dynamic, I64 types=HTT_CLASS, I64 offset=0)
{//See ::/Demo/LastClass.CC.
        I64                      i, j, stars, *ptr;
        CMemberList *ml;
        CDocEntry       *doc_e;
        Bool             unlock;
        CHashClass      *tmpc, *tmpc2;

        if (depth >= max_depth)
                return TRUE;
        if (!(tmpc = HashFind(class_name, Fs->hash_table, types)))
        {
                DocPrint(doc, "Class Not Found.\n");
                return FALSE;
        }
        if (!force && (!CheckPtr(_d) || !CheckPtr(_d(U8 *) + tmpc->size)))
        {
                DocPrint(doc, "Bad Ptr:%016X\n", _d);
                return FALSE;
        }
        if (tmpc->base_class && !ClassRep2(doc, _d, tmpc->base_class->str, depth, max_depth, dynamic, types, offset))
                return FALSE;
        unlock = DocLock(doc);
        DocPrint(doc, "Class:\"%s\"\n", class_name);
        ml = tmpc->member_list_and_root;
        while (ml)
        {
                tmpc2 = ml->member_class;
                ptr = _d(U8 *) + ml->offset;
                DocPrint(doc, "%08X ", ptr(U8 *) + offset);
                stars = tmpc2->ptr_stars_count;
                tmpc2 = OptClassFwd(tmpc2);
                tmpc2 -= tmpc2->ptr_stars_count;
                if (tmpc2->type & HTT_INTERNAL_TYPE)
                {
                        DocPrint(doc, "$GREEN$%-20ts:$FG$", ml->str);
                        if (stars == 1 && (tmpc2->raw_type == RT_I8 || tmpc2->raw_type == RT_U8))
                        {
                                ptr = *ptr;
                                if (CheckPtr(ptr))
                                {
                                        if (dynamic)
                                        {
                                                doc_e = DocPrint(doc, "$DA-TRM-P+RD,LEN=64,A=\"%%40ts\"$\n");
                                                doc_e->data = ptr;
                                                DocDataFormat(doc, doc_e);
                                        }
                                        else
                                                DocPrint(doc, "%40ts\n", ptr);
                                }
                        }
                        else if (!stars)
                        {
                                j = MinI64(ml->dim.total_count, 32);
                                if ((tmpc2->raw_type == RT_I8 || tmpc2->raw_type == RT_U8) && u8_chars)
                                {
                                        if (j == 1)
                                        {
                                                if (dynamic)
                                                {
                                                        doc_e = DocPrint(doc, "$DA-TRM+RD+UD,RT=U8,A=\"%%c\"$\n");
                                                        doc_e->data = ptr;
                                                }
                                                else
                                                        DocPrint(doc, "%c\n", *ptr(U8 *));
                                        }
                                        else
                                        {
                                                if (dynamic)
                                                {
                                                        doc_e = DocPrint(doc, "$DA-TRM-P+RD,LEN=64,A=\"%%40ts\"$\n");
                                                        doc_e->data = ptr;
                                                        DocDataFormat(doc, doc_e);
                                                }
                                                else
                                                        DocPrint(doc, "%40ts\n", ptr);
                                        }
                                }
                                for (i = 0; i < j; i++)
                                {
                                        switch (tmpc2->raw_type)
                                        {
                                                case RT_I0:
                                                case RT_U0:
                                                        break;

                                                case RT_I8:
                                                        if (dynamic)
                                                        {
                                                                doc_e = DocPrint(doc, "$DA-TRM+RD+UD,RT=I8,A=\"%%02X\"$ ");
                                                                doc_e->data = ptr(I8 *)++;
                                                        }
                                                        else
                                                                DocPrint(doc, "%02X ", *ptr(I8 *)++);
                                                        break;

                                                case RT_U8:
                                                        if (dynamic)
                                                        {
                                                                doc_e = DocPrint(doc, "$DA-TRM+RD+UD,RT=U8,A=\"%%02X\"$ ");
                                                                doc_e->data = ptr(U8 *)++;
                                                        }
                                                        else
                                                                DocPrint(doc, "%02X ", *ptr(U8 *)++);
                                                        break;

                                                case RT_I16:
                                                        if (dynamic)
                                                        {
                                                                doc_e = DocPrint(doc, "$DA-TRM+RD+UD,RT=I16,A=\"%%04X\"$ ");
                                                                doc_e->data = ptr(I16 *)++;
                                                        }
                                                        else
                                                                DocPrint(doc, "%04X ", *ptr(I16 *)++);
                                                        break;

                                                case RT_U16:
                                                        if (dynamic)
                                                        {
                                                                doc_e = DocPrint(doc, "$DA-TRM+RD+UD,RT=U16,A=\"%%04X\"$ ");
                                                                doc_e->data = ptr(U16 *)++;
                                                        }
                                                        else
                                                                DocPrint(doc, "%04X ", *ptr(U16 *)++);
                                                        break;

                                                case RT_I32:
                                                        if (dynamic)
                                                        {
                                                                doc_e = DocPrint(doc, "$DA-TRM+RD+UD,RT=I32,A=\"%%08X\"$ ");
                                                                doc_e->data = ptr(I32 *)++;
                                                        }
                                                        else
                                                                DocPrint(doc, "%08X ", *ptr(I32 *)++);
                                                        break;

                                                case RT_U32:
                                                        if (dynamic)
                                                        {
                                                                doc_e = DocPrint(doc, "$DA-TRM+RD+UD,RT=U32,A=\"%%08X\"$ ");
                                                                doc_e->data = ptr(U32 *)++;
                                                        }
                                                        else
                                                                DocPrint(doc, "%08X ", *ptr(U32 *)++);
                                                        break;

                                                case RT_U64:
                                                        if (dynamic)
                                                        {
                                                                doc_e = DocPrint(doc, "$DA-TRM+RD+UD,RT=U64,A=\"%%08X\"$ ");
                                                                doc_e->data = ptr(U64 *)++;
                                                        }
                                                        else
                                                                DocPrint(doc, "%08X ", *ptr(U64 *)++);
                                                        break;

                                                case RT_F64:
                                                        if (dynamic)
                                                        {
                                                                doc_e = DocPrint(doc, "$DA-TRM+RD+UD,RT=F64,A=\"%%16g\"$ ");
                                                                doc_e->data = ptr(F64 *)++;
                                                        }
                                                        else
                                                                DocPrint(doc, "%16g ", *ptr(I64 *)++);
                                                        break;

                                                default:
                                                        if (dynamic)
                                                        {
                                                                doc_e = DocPrint(doc, "$DA-TRM+RD+UD,A=\"%%016X\"$ ");
                                                                doc_e->data = ptr(I64 *)++;
                                                        }
                                                        else
                                                                DocPrint(doc, "%016X ", *ptr(I64 *)++);
                                        }
                                        if (dynamic)
                                                DocDataFormat(doc, doc_e);
                                }
                                if (j < ml->dim.total_count)
                                        DocPrint(doc, "...");
                        }
                        else
                                DocPrint(doc, "%016X", *ptr);
                        DocPrint(doc,"\n");
                }
                else
                {
                        if (depth < 2)
                        {
                                if (stars == 1 && !CheckPtr(*ptr))
                                        DocPrint(doc, "%-20ts:%016X\n", ml->str, *ptr);
                                else
                                {
                                        DocPrint(doc, "$TR,\"%s\"$\n", ml->str);
                                        DocPrint(doc, "$ID,2$");
                                        if (!stars)
                                                ClassRep2(doc, ptr, tmpc2->str, u8_chars, force, depth + 1, max_depth, dynamic);
                                        else if (stars == 1)
                                                ClassRep2(doc, *ptr, tmpc2->str, u8_chars, force, depth + 1, max_depth, dynamic);
                                        DocPrint(doc, "$ID,-2$");
                                }
                        }
                        else
                                DocPrint(doc, "%-20ts\n", ml->str);
                }
                ml = ml->next;
        }
        if (unlock)
                DocUnlock(doc);

        return TRUE;
}

public U0 ClassRep(U8 *_d, U8 *class_name=lastclass, I64 max_depth=2, Bool u8_chars=FALSE, Bool force=FALSE,
                                   Bool fun=FALSE, I64 offset=0)
{//Displays members of a record by using the compiler's info.
        CDoc *doc;
        I64   type;

        if (IsRaw)
                doc = DocNew;
        else
        {
                DocMax;
                doc = DocPut;
        }
        if (fun)
                type = HTT_FUN;
        else
                type = HTT_CLASS;

        ClassRep2(doc, _d, class_name, u8_chars, force, 0, max_depth, FALSE, type, offset);

        DocPrint(doc, "\n");
        DocRecalc(doc);

        if (IsRaw)
        {
                DocDump(doc, 100000);
                DocDel(doc);
        }
}

public U0 ClassRepD(U8 *_d, U8 *class_name=lastclass, I64 max_depth=2, Bool u8_chars=FALSE, Bool force=FALSE,
                                        Bool fun=FALSE, I64 offset=0)
{//Dynamic ClassRep. Uses hex_ed widget for live changes.
        CDoc *doc;

        if (IsRaw)
                doc = DocNew;
        else
        {
                DocMax;
                doc = DocPut;
        }
        if (fun)
                ClassRep2(doc, _d, class_name, u8_chars, force, 0, max_depth, TRUE, HTT_FUN, offset);
        else
                ClassRep2(doc, _d, class_name, u8_chars, force, 0, max_depth, TRUE, HTT_CLASS, offset);
        DocPrint(doc, "\n");
        DocRecalc(doc);
        if (IsRaw)
        {
                DocDump(doc, 100000);
                DocDel(doc);
        }
}

U0 UpdateRegVarImg(CHashFun *tmpf, U8 *_b, CTask *task)
{
        CMemberList     *ml;
        CHashClass      *tmpc;

        ml = tmpf->member_list_and_root;
        while (ml)
        {
                if (ml->reg != REG_NONE)
                {
                        tmpc = OptClassFwd(ml->member_class);
                        MemCopy(_b + ml->offset, TaskRegAddr(task, ml->reg), tmpc->size);
                }
                ml = ml->next;
        }
}

public U0 FunRep(U8 *st, U8 *rbp=NULL, I64 max_depth=2, CTask *task=NULL)
{//Shows names and vals of a fun's local vars using compiler's info.
        I64                      size;
        U8                      *img;
        CHashFun        *tmpf = HashFind(st, Fs->hash_table, HTT_FUN);
        CMemberList     *tmpm;

        if (tmpf)
        {
                if (rbp)
                {
                        if (task)
                        {       //tmpf->size is negative.  It's the bottom
                                //of the fun local var space relative to RBP.
                                size = tmpf->arg_count * 8 - tmpf->size + 16;

                                img = MAlloc(size);
                                MemCopy(img, rbp + tmpf->size, size);
                                UpdateRegVarImg(tmpf, img - tmpf->size, task);
                                ClassRep(img - tmpf->size, st, max_depth, FALSE, FALSE, TRUE, rbp - img + tmpf->size);
                                Free(img);
                        }
                        else
                                ClassRep(rbp, st, max_depth, FALSE, FALSE, TRUE);
                }
                else
                {
                        tmpm = tmpf->member_list_and_root;
                        while (tmpm)
                        {
                                if (0 <= tmpm->reg < REG_REGS_NUM)
                                        "%08Z %s\n", tmpm->reg, "ST_U64_REGS", tmpm->str;
                                else
                                        "%08tX %s\n", tmpm->offset, tmpm->str;
                                tmpm = tmpm->next;
                        }
                        "%08tX Stack Size\n", tmpf->size;
                }
        }
}

#help_index "Debugging/Unassemble"
public U0 Uf(U8 *st)
{//Unassembles a named fun
        I64                      i;
        CHashSrcSym     *tmpf;
        CDebugInfo      *debug_info;

        if (tmpf = HashFind(st, Fs->hash_table, HTT_FUN | HTT_EXPORT_SYS_SYM))
        {
                if (tmpf->type & HTT_FUN)
                        FunRep(st);
                if (debug_info = tmpf->debug_info)
                {
                        i = debug_info->body[debug_info->max_line + 1 - debug_info->min_line] - debug_info->body[0];
                        Un(debug_info->body[0], i);
                        "Code Size:%04X\n", i;
                }
                else
                        U(HashVal(tmpf));
        }
}