U0 LexBackupLastChar(CCompCtrl *cc)
{
        CLexFile *tmpf = cc->lex_include_stack;

        tmpf->buf_ptr = cc->cur_buf_ptr;
        if (cc->flags & CCF_USE_LAST_U16)
        {
                tmpf->last_U16 = cc->last_U16;
                cc->flags &= ~CCF_USE_LAST_U16;
        }
        else
                tmpf->last_U16 = 0;
}

U0 LexPush(CCompCtrl *cc)
{//Create token-stream save point.
        CLexFile *tmpf;

        LexBackupLastChar(cc);
        if (cc->lex_include_stack->last_U16)
                cc->flags |= CCF_USE_LAST_U16;
        tmpf = MAllocIdent(cc->lex_include_stack);
        tmpf->next = cc->lex_parse_stack;
        cc->lex_parse_stack = tmpf;
}

U0 LexPopRestore(CCompCtrl *cc)
{//Restore token-stream saved-point.
//Bad things can happen if you cross an #include file boundary.
        CLexFile *tmpf = cc->lex_parse_stack;

        cc->cur_buf_ptr = tmpf->buf_ptr;
        if (cc->last_U16 = tmpf->last_U16)
                cc->flags |= CCF_USE_LAST_U16;
        else
                cc->flags &= ~CCF_USE_LAST_U16;
        MemCopy(cc->lex_include_stack(U8 *) + sizeof(U8 *), tmpf(U8 *) + sizeof(U8 *), sizeof(CLexFile) - sizeof(U8 *));
        cc->lex_parse_stack = tmpf->next;
        Free(tmpf);
}

U0 LexPopNoRestore(CCompCtrl *cc)
{//Don't restore token-stream saved-point.
        CLexFile *tmpf = cc->lex_parse_stack;

        cc->lex_parse_stack = tmpf->next;
        Free(tmpf);
}

I64 MemberMetaData(U8 *needle_str, CMemberList *haystack_member_list)
{//Find meta data name, return meta data val. See ::/Demo/ClassMeta.CC.
        CMemberListMeta *meta = haystack_member_list->meta;

        while (meta)
        {
                if (!StrCompare(meta->str, needle_str))
                        return meta->user_data;
                meta = meta->next;
        }

        return 0;
}

CMemberListMeta *MemberMetaFind(U8 *needle_str, CMemberList *haystack_member_list)
{//Find meta data name, return meta data struct. See ::/Demo/ClassMeta.CC.
        CMemberListMeta *meta = haystack_member_list->meta;

        while (meta)
        {
                if (!StrCompare(meta->str, needle_str))
                        return meta;
                meta = meta->next;
        }

        return NULL;
}

CMemberList *MemberFind(U8 *needle_str, CHashClass *haystack_class)
{//Find class member. See ClassRep() and DocForm().
        I64                      i;
        CMemberList     *tmpm;

        do
        {
                tmpm = haystack_class->member_list_and_root;
                while (tmpm)
                {
                        if (!(i = StrCompare(tmpm->str, needle_str)))
                        {
                                tmpm->use_count++;
                                return tmpm;
                        }
                        if (i <= 0)
                                tmpm = tmpm->left;
                        else
                                tmpm = tmpm->right;
                }
        }
        while (haystack_class = haystack_class->base_class);

        return NULL;
}

CMemberList *MemberClassBaseFind(CHashClass *needle_class, CHashClass *haystack_class)
{//Find class member class base. For finding dup class local vars.
        CMemberList *tmpm;

        tmpm = haystack_class->member_class_base_root;
        while (tmpm)
        {
                if (needle_class == tmpm->member_class_base)
                        return tmpm;
                if (needle_class < tmpm->member_class_base)
                        tmpm = tmpm->left_class_base;
                else
                        tmpm = tmpm->right_class_base;
        }

        return NULL;
}

U0 MemberAdd(CCompCtrl *cc, CMemberList *tmpm, CHashClass *tmpc, I64 mode)
{
        U8                       *st = tmpm->str;
        CMemberList     **tmpm1, *tmpm2;

        if (MemberFind(st, tmpc) && StrCompare(st, "pad") && StrCompare(st, "reserved") && StrCompare(st, "_anon_"))
                LexExcept(cc, "Duplicate member at ");
        tmpm1 = &tmpc->member_list_and_root;
        while (tmpm2 = *tmpm1)
        {
                if (StrCompare(tmpm2->str, st) <= 0)
                        tmpm1 = &tmpm2->left;
                else
                        tmpm1 = &tmpm2->right;
        }
        *tmpm1 = tmpm;

        if (mode == PRS1B_LOCAL_VAR)
        {
                tmpm->member_class_base = tmpm->member_class - tmpm->member_class->ptr_stars_count;
                if (Bt(&cc->opts, OPTf_WARN_DUP_TYPES) && MemberClassBaseFind(tmpm->member_class_base, tmpc))
                        LexWarn(cc, "Duplicate type at ");
                tmpm1 = &tmpc->member_class_base_root;
                while (tmpm2 = *tmpm1)
                {
                        if (tmpm->member_class_base < tmpm2->member_class_base)
                                tmpm1 = &tmpm2->left_class_base;
                        else if (tmpm->member_class_base > tmpm2->member_class_base)
                                tmpm1 = &tmpm2->right_class_base;
                        else
                        {
                                tmpm1 = NULL;
                                break;
                        }
                }
                if (tmpm1)
                        *tmpm1 = tmpm;
        }
        else
                tmpm->member_class_base = NULL;

        tmpm->left = NULL;
        tmpm->right = NULL;
        tmpm->left_class_base = NULL;
        tmpm->right_class_base = NULL;
        tmpm2 = tmpc->last_in_member_list;
        tmpm2->next = tmpc->last_in_member_list = tmpm;
}

CMemberList *MemberListNew(I64 _reg)
{
        CMemberList *res = CAlloc(sizeof(CMemberList));

        res->reg = _reg;

        return res;
}

Bool MemberListCmp(CMemberList *tmpm1, CMemberList *tmpm2, I64 count=I64_MAX)
{
        while (tmpm1 && tmpm2 && count--)
        {
                if (StrCompare(tmpm1->str,tmpm2->str) ||
                                tmpm1->member_class              != tmpm2->member_class ||
                                tmpm1->member_class_base != tmpm2->member_class_base)
                        return FALSE;
                if (tmpm1->flags & MLF_DEFAULT_AVAILABLE || tmpm2->flags & MLF_DEFAULT_AVAILABLE)
                {
                        if (tmpm1->flags & (MLF_DEFAULT_AVAILABLE | MLF_STR_DEFAULT_AVAILABLE) !=
                                        tmpm2->flags & (MLF_DEFAULT_AVAILABLE | MLF_STR_DEFAULT_AVAILABLE))
                                return FALSE;
                        if (tmpm1->flags & MLF_STR_DEFAULT_AVAILABLE)
                        {
                                if (StrCompare(tmpm1->default_val, tmpm2->default_val))
                                        return FALSE;
                        }
                        else if (tmpm1->default_val != tmpm2->default_val)
                                return FALSE;
                }
                tmpm1 = tmpm1->next;
                tmpm2 = tmpm2->next;
        }
        if (count < 0 || !tmpm1 && !tmpm2)
                return TRUE;
        else
                return FALSE;
}

U0 MemberListDel(CMemberList *tmpm)
{
        CMemberList             *tmpm1;
        CMemberListMeta *tmp_meta, *tmp_meta1;

        while (tmpm)
        {
                tmpm1 = tmpm->next;
                Free(tmpm->str);
                LinkedListDel(tmpm->dim.next);
                if (tmpm->flags & MLF_STR_DEFAULT_AVAILABLE)
                        Free(tmpm->default_val);
                if (tmpm->flags & MLF_FUN)
                        HashDel(tmpm->fun_ptr - tmpm->fun_ptr->ptr_stars_count);
                tmp_meta = tmpm->meta;
                while (tmp_meta)
                {
                        tmp_meta1 = tmp_meta->next;
                        Free(tmp_meta->str);
                        if (tmp_meta->flags & MLMF_IS_STR)
                                Free(tmp_meta->user_data);
                        Free(tmp_meta);
                        tmp_meta = tmp_meta1;
                }
                Free(tmpm);
                tmpm = tmpm1;
        }
}

U0 ClassMemberListDel(CHashClass *tmpc)
{
        MemberListDel(tmpc->member_list_and_root);
        tmpc->size = 0;
        tmpc->last_in_member_list = &tmpc->member_list_and_root;
        tmpc->member_list_and_root = NULL;
        tmpc->member_class_base_root = NULL;
        tmpc->member_count = 0;
        if (tmpc->type & HTT_FUN)
                tmpc(CHashFun *)->arg_count = 0;
}

I64 MemberListSize(CHashClass *tmpc)
{
        CMemberList             *tmpm;
        CMemberListMeta *tmp_meta;
        I64                              res = 0;

        tmpm = tmpc->member_list_and_root;
        while (tmpm)
        {
                res += MSize2(tmpm->str);
                res += LinkedListSize(tmpm->dim.next);
                if (tmpm->flags & MLF_STR_DEFAULT_AVAILABLE)
                        res += MSize2(tmpm->default_val);
                if (tmpm->flags & MLF_FUN)
                        res += HashEntrySize2(tmpm->fun_ptr - tmpm->fun_ptr->ptr_stars_count);
                tmp_meta = tmpm->meta;
                while (tmp_meta)
                {
                        res += MSize2(tmp_meta->str);
                        if (tmp_meta->flags & MLMF_IS_STR)
                                res += MSize2(tmp_meta->user_data);
                        res += MSize2(tmp_meta);
                        tmp_meta = tmp_meta->next;
                }
                res += MSize2(tmpm);
                tmpm = tmpm->next;
        }

        return res;
}

U8 *LexExtStr(CCompCtrl *cc, I64 *_size=NULL, Bool lex_next=TRUE)
{//Lex TK_STR's to one combined str. _size includes terminator.
        I64 len = cc->cur_str_len, len1, len2;
        U8 *st = cc->cur_str, *st1, *st2;

        cc->cur_str = NULL;
        while (cc->token == TK_STR)
        {
                st1 = st;
                len1 = len;
                if (!lex_next && LexCharGet(cc) != '\\')
                {
                        cc->flags |= CCF_USE_LAST_U16;
                        break;
                }
                if (Lex(cc) == TK_STR)
                {
                        len2 = cc->cur_str_len;
                        st2 = cc->cur_str;
                        cc->cur_str = NULL;
                        len = len1 + len2 - 1;
                        st = MAlloc(len);
                        if (len1 > 1)
                                MemCopy(st, st1, len1 - 1);
                        MemCopy(st + len1 - 1, st2, len2);
                        Free(st1);
                        Free(st2);
                }
        }
        if (_size)
                *_size = len;

        return st;
}