CHashClass *ParseClass(CCompCtrl *cc, I64 keyword, I64 fsp_flags, Bool is_extern)
{
        CHashClass *tmpc, *base_class;

        if (cc->token != TK_IDENT)
                LexExcept(cc, "Expecting identifier at ");
        if (is_extern)
        {
                tmpc = ParseClassNew;
                tmpc->str = cc->cur_str;
                cc->cur_str = NULL;
                HashAdd(tmpc, cc->htc.global_hash_table);
                LBts(&tmpc->flags, Cf_EXTERN);
                HashSrcFileSet(cc, tmpc);
                Lex(cc);
        }
        else
        {
                if (cc->flags & CCF_AOT_COMPILE)
                        tmpc = HashFind(cc->cur_str, cc->htc.global_hash_table, HTT_CLASS);
                else
                        tmpc = HashSingleTableFind(cc->cur_str, cc->htc.global_hash_table, HTT_CLASS);
                if (tmpc)
                {
                        if (!Bt(&tmpc->flags, Cf_EXTERN))
                                tmpc = NULL;
                        else if (tmpc->use_count < 3)
                                UnusedExternWarning(cc, tmpc);
                }
                if (tmpc)
                {
                        Free(tmpc->src_link);
                        tmpc->src_link = NULL;
                        Free(tmpc->idx);
                        tmpc->idx = NULL;
                }
                else
                {
                        tmpc = ParseClassNew;
                        tmpc->str = cc->cur_str;
                        cc->cur_str = NULL;
                        HashAdd(tmpc, cc->htc.global_hash_table);
                }
                LBtr(&tmpc->flags, Cf_EXTERN);
                if (fsp_flags & FSF_PUBLIC)
                        tmpc->type |= HTF_PUBLIC;
                tmpc->use_count = 0;
                if (cc->last_U16 == '\n')
                        HashSrcFileSet(cc, tmpc, -1);
                else
                        HashSrcFileSet(cc, tmpc,0);
                if (Lex(cc) == ':')
                {
                        if (Lex(cc) != TK_IDENT || !(base_class = cc->hash_entry) || !(base_class->type & HTT_CLASS))
                                LexExcept(cc, "Invalid class at ");
                        if (Lex(cc) == ',')
                                LexExcept(cc, "Only one base class allowed at this time at ");
                        tmpc->base_class = base_class;
                        tmpc->size += base_class->size;
                }
                if (keyword == KW_UNION)
                        ParseVarList(cc, tmpc, PRS0_NULL | PRS1_CLASS | PRSF_UNION);
                else
                        ParseVarList(cc, tmpc, PRS0_NULL | PRS1_CLASS);
                tmpc->size += tmpc->neg_offset;
        }
        return tmpc;
}

CHashFun *ParseFunJoin(CCompCtrl *cc, CHashClass *tmp_return, U8 *name, I64 fsp_flags)
{
        CMemberList     *tmpm, *header_list;
        CAOTCtrl        *aotc = cc->aotc;
        CHashClass      *header_return;
        CHashFun        *tmpf;
        I64                      header_arg_count;

        if (name)
        {//if not fun_ptr
                if (cc->flags & CCF_AOT_COMPILE)
                {
                        if ((tmpf = HashFind(name, cc->htc.global_hash_table, HTT_FUN)) && tmpf->type & HTF_IMPORT)
                                tmpf=NULL;
                }
                else
                        if ((tmpf = HashSingleTableFind(name, cc->htc.global_hash_table, HTT_FUN)) && !Bt(&tmpf->flags, Cf_EXTERN))
                                tmpf = NULL;
                if (tmpf && tmpf->use_count < 3)
                        UnusedExternWarning(cc, tmpf);
        }
        else
                tmpf = NULL;
        if (tmpf)
        {
                tmpf->used_reg_mask = REGG_CLOBBERED + REGG_SAVED + REGG_STACK_TMP;
                Free(tmpf->src_link);
                tmpf->src_link = NULL;
                Free(tmpf->idx);
                tmpf->idx = NULL;
                Free(name);
                header_arg_count = tmpf->arg_count;
                header_list = tmpf->member_list_and_root;
                header_return = tmpf->return_class;
                tmpf->member_list_and_root = NULL;
                ClassMemberListDel(tmpf);
        }
        else
        {
                tmpf = ParseFunNew;
                header_return = NULL;
                tmpf->used_reg_mask = REGG_CLOBBERED + REGG_SAVED + REGG_STACK_TMP;
                tmpf->clobbered_reg_mask = REGG_CLOBBERED + REGG_STACK_TMP;
                tmpf->str = name;
                if (cc->flags & CCF_AOT_COMPILE)
                        tmpf->exe_addr = aotc->rip;
                else
                        tmpf->exe_addr = &UndefinedExtern;
                LBts(&tmpf->flags, Cf_EXTERN);
                tmpf->flags |= fsp_flags & FSG_FUN_FLAGS1;
                if (name) //if not fun_ptr
                        HashAdd(tmpf, cc->htc.global_hash_table);
        }
        BEqual(&tmpf->type, HTf_PUBLIC, fsp_flags & FSF_PUBLIC);
        tmpf->return_class = tmp_return;
        tmpf->use_count = 0;
        HashSrcFileSet(cc, tmpf);
        ParseVarList(cc, tmpf, PRS0_NULL | PRS1_FUN_ARG);
        tmpf->arg_count = tmpf->member_count;
        if (0 < tmpf->arg_count << 3 <= I16_MAX && !Bt(&tmpf->flags, Ff_DOT_DOT_DOT))
                LBts(&tmpf->flags, Ff_RET1);
        tmpm = tmpf->member_list_and_root;
        while (tmpm)
        {
                tmpm->offset += 16; //RBP+RETURN
                tmpm = tmpm->next;
        }
        tmpf->size = 0;
        if (header_return)
        {
                if (OptionGet(OPTf_WARN_HEADER_MISMATCH))
                {
                        if (tmpf->return_class != header_return)
                        {
                                PrintWarn("Fun Header return mismatch '%s'\n", tmpf->str);
                                cc->warning_count++;
                        }
                        if (!MemberListCmp(tmpf->member_list_and_root, header_list, header_arg_count))
                        {
                                PrintWarn("Fun header args mismatch '%s'\n", tmpf->str);
                                cc->warning_count++;
                        }
                }
                MemberListDel(header_list);
        }

        return tmpf;
}

U0 ParseFun(CCompCtrl *cc, CHashClass *tmp_return, U8 *name, I64 fsp_flags)
{
        CMemberList     *tmpm;
        CCodeMisc       *saved_leave_label;
        I64                      i, j, size, *r;
        Bool             old_trace;

        cc->fun_lex_file = cc->lex_include_stack;
        cc->min_line=cc->max_line = cc->lex_include_stack->line_num;

        cc->flags &= ~CCF_NO_REG_OPT;
        cc->htc.local_var_list = cc->htc.fun = ParseFunJoin(cc, tmp_return, name, fsp_flags);

        COCPush(cc);
        Btr(&cc->flags, CCf_PASS_TRACE_PRESENT);
        COCInit(cc);
        ICAdd(cc, IC_ENTER, 0, 0);
        saved_leave_label = cc->lb_leave;
        cc->lb_leave = COCMiscNew(cc,CMT_LABEL);
        cc->flags &= ~CCF_HAS_RETURN;
        ParseStatement(cc,,, 0);

        if (cc->max_line < cc->min_line)
                cc->max_line = cc->min_line;

        if (cc->htc.fun->return_class->size && !(cc->flags & CCF_HAS_RETURN))
                LexWarn(cc, "Function should return val ");
        ICAdd(cc, IC_LABEL, cc->lb_leave, 0);
        cc->lb_leave = saved_leave_label;
        ICAdd(cc, IC_LEAVE, 0, cc->htc.fun->return_class);
        cc->htc.fun->size &= ~7;
        if (cc->flags & CCF_AOT_COMPILE)
        {
                cc->htc.fun->exe_addr = cc->aotc->rip;
                cc->htc.fun->type |= HTF_EXPORT | HTF_RESOLVE;
                r = COCCompile(cc, &size, &cc->htc.fun->debug_info, NULL);
                if (r)
                {
                        j = (size + 7) >> 3;
                        for (i = 0; i < j; i++)
                                AOTStoreCodeU64(cc, r[i]);
                        Free(r);
                }
        }
        else
        {
                old_trace = Btr(&cc->opts, OPTf_TRACE);
                cc->htc.fun->exe_addr = COCCompile(cc, &size, &cc->htc.fun->debug_info, NULL);
                if (old_trace)
                {
                        Bts(&cc->opts, OPTf_TRACE);
                        Un(cc->htc.fun->exe_addr, size, 64);
                }
                SysSymImportsResolve(cc->htc.fun->str);
        }
        LBtr(&cc->htc.fun->flags, Cf_EXTERN);
        COCPop(cc);
        tmpm = cc->htc.fun->member_list_and_root;
        while (tmpm)
        {
                if (tmpm->flags & MLF_NO_UNUSED_WARN)
                {
                        if (tmpm->use_count > 1 && StrCompare(tmpm->str, "_anon_"))
                                PrintWarn("Unneeded no_warn\n $LK,\"FL:%s,%d\"$ '%s' in '%s'\n",
                                                        cc->lex_include_stack->full_name, cc->lex_include_stack->line_num, tmpm->str, cc->htc.fun->str);
                }
                else if (!tmpm->use_count && OptionGet(OPTf_WARN_UNUSED_VAR))
                        PrintWarn("Unused var\n $LK,\"FL:%s,%d\"$ '%s' in '%s'\n",
                                                cc->lex_include_stack->full_name, cc->lex_include_stack->line_num, tmpm->str, cc->htc.fun->str);
                tmpm = tmpm->next;
        }
        cc->htc.local_var_list = cc->htc.fun=cc->fun_lex_file = NULL;
}

U0 ParseGlobalVarList(CCompCtrl *cc, I64 saved_mode, CHashClass *saved_tmpc, I64 saved_val, I64 fsp_flags)
{
        I64                              i, j, mode, k, val;
        U8                              *st;
        CHashExport             *tmpex;
        CHashGlobalVar  *tmpg;
        CAOTCtrl                *aotc = cc->aotc;
        CAOTHeapGlobal  *tmphg;
        CHashClass              *tmpc;
        CHashFun                *tmpf, *tmpf_fun_ptr;
        CArrayDim                tmpad;
        Bool                     has_alias, undef_array_size, is_array;

        while (TRUE)
        {
                tmpc = ParseType(cc, &saved_tmpc, &saved_mode, NULL, &st, &tmpf_fun_ptr, &tmpex, &tmpad, fsp_flags);

                if (!st)
                        return;
                if (tmpad.next)
                        is_array = TRUE;
                else if (tmpad.total_count < 0)
                {
                        is_array = TRUE;
                        tmpc--;
                }
                else
                        is_array = FALSE;

                val = saved_val;
                mode = saved_mode;
                if (tmpex && mode & 255 == PRS0_EXTERN && !(cc->flags & CCF_AOT_COMPILE) && tmpex->type & HTT_EXPORT_SYS_SYM)
                {
                        val = tmpex->val;
                        mode = PRS0__EXTERN | PRS1_NOT_REALLY__EXTERN;
                }
                if (cc->token == '(')
                {
                        switch (mode & 255)
                        {
                                case PRS0__INTERN:
                                        tmpf = ParseFunJoin(cc, tmpc, st, fsp_flags);
                                        tmpf->exe_addr = val;
                                        Bts(&tmpf->flags, Ff_INTERNAL);
                                        LBtr(&tmpf->flags, Cf_EXTERN);
                                        return;

                                case PRS0__EXTERN:
                                        if (!(fsp_flags & FSF__) && !(mode & PRS1_NOT_REALLY__EXTERN))
                                                LexExcept(cc, "Expecting label with underscore at ");
                                        tmpf = ParseFunJoin(cc, tmpc, st, fsp_flags);
                                        tmpf->exe_addr = val;
                                        SysSymImportsResolve(tmpf->str);
                                        LBtr(&tmpf->flags, Cf_EXTERN);
                                        if (saved_mode & 255 == PRS0__EXTERN)
                                                LBts(&tmpf->flags, Ff__EXTERN);
                                        if (cc->flags & CCF_AOT_COMPILE)
                                                tmpf->type |= HTF_RESOLVE;
                                        return;

                                case PRS0_EXTERN:
                                        ParseFunJoin(cc, tmpc, st, fsp_flags);
                                        return;

                                case PRS0__IMPORT:
                                        if (!(fsp_flags & FSF__))
                                                LexExcept(cc, "Expecting label with underscore at ");

                                case PRS0_IMPORT:
                                        if (!(cc->flags & CCF_AOT_COMPILE))
                                                LexExcept(cc, "import not needed at ");
                                        else
                                        {
                                                tmpf = ParseFunJoin(cc, tmpc, st, fsp_flags);
                                                tmpf->type |= HTF_IMPORT;
                                                if (mode & 255 == PRS0__IMPORT)
                                                        tmpf->import_name = StrNew(val);
                                                else
                                                        tmpf->import_name = StrNew(st);
                                        }
                                        return;

                                default:
                                        ParseFun(cc, tmpc, st, fsp_flags);
                                        return;
                        }
                }
                else
                {
                        if (tmpad.total_count < 0)
                        {
                                i = 0;
                                undef_array_size = TRUE;
                        }
                        else
                        {
                                i = tmpad.total_count;
                                undef_array_size = FALSE;
                        }
                        if (tmpf_fun_ptr)
                                j = sizeof(U8 *);
                        else
                                j = tmpc->size;
                        j *= i;
                        has_alias = FALSE;
                        tmphg = NULL;
                        switch (mode & 255)
                        {
                                case PRS0__EXTERN:
                                        if (cc->flags & CCF_AOT_COMPILE)
                                        {
                                                tmpg = CAlloc(sizeof(CHashGlobalVar));
                                                tmpg->data_addr_rip = val;
                                                tmpg->type = HTT_GLOBAL_VAR | HTF_EXPORT;
                                        }
                                        else
                                        {
                                                tmpg = CAlloc(sizeof(CHashGlobalVar), Fs->code_heap);
                                                tmpg->data_addr = val;
                                                tmpg->type = HTT_GLOBAL_VAR;
                                        }
                                        tmpg->flags |= GVF_ALIAS;
                                        break;

                                case PRS0__IMPORT:
                                case PRS0_IMPORT:
                                        if (!(cc->flags & CCF_AOT_COMPILE))
                                                LexExcept(cc, "import not needed at ");
                                        else
                                        {
                                                tmpg = CAlloc(sizeof(CHashGlobalVar));
                                                tmpg->type = HTT_GLOBAL_VAR | HTF_IMPORT;
                                                if (mode & 255 == PRS0__IMPORT)
                                                        tmpg->import_name = StrNew(val);
                                                else
                                                        tmpg->import_name = StrNew(st);
                                        }
                                        break;

                                case PRS0_EXTERN:
                                        if (cc->flags & CCF_AOT_COMPILE)
                                        {
                                                tmpg = CAlloc(sizeof(CHashGlobalVar));
                                                tmpg->type = HTT_GLOBAL_VAR;
                                        }
                                        else
                                        {
                                                tmpg = CAlloc(sizeof(CHashGlobalVar), Fs->code_heap);
                                                tmpg->type = HTT_GLOBAL_VAR | HTF_UNRESOLVED;
                                        }
                                        break;

                                default:
                                        if (cc->flags & CCF_AOT_COMPILE)
                                        {
                                                if (Bt(&cc->opts, OPTf_GLOBALS_ON_DATA_HEAP)) {
                                                        if (cc->token == '=')
                                                                LexExcept(cc, "Can't init global var on data heap in AOT module ");
                                                        tmpg = CAlloc(sizeof(CHashGlobalVar));
                                                        tmphg = tmpg->heap_global=CAlloc(sizeof(CAOTHeapGlobal));
                                                        tmphg->size = j;
                                                        tmphg->str = StrNew(st);
                                                        tmphg->next = aotc->heap_globals;
                                                        aotc->heap_globals = tmphg;
                                                        tmpg->flags = GVF_DATA_HEAP;
                                                        tmpg->type = HTT_GLOBAL_VAR; //TODO: HTF_EXPORT
                                                        if (tmpex && tmpex->type & HTT_GLOBAL_VAR) //TODO!! extern
                                                                LexExcept(cc, "Feature not implemented ");
                                                }
                                                else
                                                {
                                                        tmpg = CAlloc(sizeof(CHashGlobalVar));
                                                        if (cc->token == '=')
                                                                tmpg->data_addr = CAlloc(j);
                                                        if (tmpc->size >= 8) //align
                                                                while (aotc->rip & 7)
                                                                        AOTStoreCodeU8(cc, 0);
                                                        else if (tmpc->size == 4)
                                                                while (aotc->rip & 3)
                                                                        AOTStoreCodeU8(cc, 0);
                                                        else if (tmpc->size == 2)
                                                                while (aotc->rip & 1)
                                                                        AOTStoreCodeU8(cc, 0);
                                                        tmpg->data_addr_rip = aotc->rip;
                                                        tmpg->type = HTT_GLOBAL_VAR | HTF_EXPORT;
                                                        if (tmpex && tmpex->type & HTT_GLOBAL_VAR)
                                                                has_alias = TRUE;
                                                        for (k = 0; k < j; k++)
                                                                AOTStoreCodeU8(cc, 0); //Init AOT global to zero.
                                                }
                                        }
                                        else
                                        {
                                                if (Bt(&cc->opts, OPTf_GLOBALS_ON_DATA_HEAP))
                                                {
                                                        tmpg = CAlloc(sizeof(CHashGlobalVar), Fs->code_heap);
                                                        tmpg->data_addr = MAlloc(j);
                                                        tmpg->flags = GVF_DATA_HEAP;
                                                }
                                                else
                                                {
                                                        tmpg = CAlloc(sizeof(CHashGlobalVar), Fs->code_heap);
                                                        tmpg->data_addr = MAlloc(j, Fs->code_heap);
                                                }
                                                tmpg->type = HTT_GLOBAL_VAR;
                                                if (tmpex && tmpex->type & HTT_GLOBAL_VAR && tmpex->type & HTF_UNRESOLVED &&
                                                                MHeapCtrl(tmpex) == MHeapCtrl(tmpg))
                                                        has_alias = TRUE;
                                                if (sys_var_init_flag)
                                                        MemSet(tmpg->data_addr, sys_var_init_val, j);
                                        }
                        }
                        tmpg->dim.next = tmpad.next;
                        if (fsp_flags & FSF_PUBLIC)
                                tmpg->type |= HTF_PUBLIC;
                        tmpg->var_class = tmpc;
                        tmpg->str = st;
                        tmpg->size = j;
                        tmpg->dim.total_count = i;
                        tmpg->use_count = 0;
                        if (cc->last_U16 == '\n')
                                HashSrcFileSet(cc, tmpg, -1);
                        else
                                HashSrcFileSet(cc, tmpg, 0);
                        if (mode & 255 == PRS0_IMPORT || mode & 255 == PRS0__IMPORT)
                                tmpg->flags |= GVF_IMPORT;
                        if (mode & 255 == PRS0_EXTERN)
                                tmpg->flags |= GVF_EXTERN;
                        if (tmpf_fun_ptr)
                        {
                                tmpg->fun_ptr = tmpf_fun_ptr;
                                tmpg->flags |= GVF_FUN;
                        }
                        if (is_array)
                                tmpg->flags |= GVF_ARRAY;
                        HashAdd(tmpg, cc->htc.global_hash_table);
                        if (!(cc->flags & CCF_AOT_COMPILE) && !(tmpg->flags & GVF_EXTERN))
                                SysSymImportsResolve(tmpg->str);
                        if (cc->token == '=')
                        {
                                if (undef_array_size)
                                {
                                        LexPush(cc);
                                        LexPush(cc);
                                        Lex(cc);
                                        ParseGlobalInit(cc, tmpg, 1);
                                        LexPopNoRestore(cc);
                                        tmpg->size = tmpg->dim.total_count * tmpc->size;
                                        if (tmphg)
                                                tmphg->size = tmpg->size;
                                        if (cc->flags & CCF_AOT_COMPILE)
                                                for (k = 0; k < tmpg->size; k++)
                                                        AOTStoreCodeU8(cc, 0);
                                        else
                                                if (sys_var_init_flag)
                                                        MemSet(tmpg->data_addr, sys_var_init_val, k);
                                        LexPopRestore(cc);
                                }
                                LexPush(cc);
                                Lex(cc);
                                ParseGlobalInit(cc, tmpg, 2);
                                if (cc->flags & CCF_AOT_COMPILE)
                                        for (k = 0; k < tmpg->size; k++)
                                                AOTStoreCodeU8At(cc, tmpg->data_addr_rip + k, tmpg->data_addr[k]);
                                LexPopNoRestore(cc);
                        }
                        if (has_alias)
                        {
                                if (tmpex(CHashGlobalVar *)->use_count < 2)
                                {
                                        PrintWarn("Unused extern '%s'\n", tmpex(CHashGlobalVar *)->str);
                                        cc->warning_count++;
                                }
                                tmpex(CHashGlobalVar *)->flags |= GVF_ALIAS;
                                tmpex(CHashGlobalVar *)->data_addr = tmpg->data_addr;
                                tmpex(CHashGlobalVar *)->data_addr_rip = tmpg->data_addr_rip;
                        }
                        if (cc->token == ',')
                                Lex(cc);
                        else
                        {
                                if (cc->token != ';')
                                        LexExcept(cc, "Missing ';' at");
                                Lex(cc);
                                return;
                        }
                }
        }
}

U0 ParseIf(CCompCtrl *cc, I64 try_count, CCodeMisc *lb_break)
{
        CCodeMisc       *lb, *lb1;
        I64                      k;

        if (cc->token != '(')
                LexExcept(cc, "Expecting '(' at ");
        Lex(cc);
        if (!ParseExpression(cc, NULL, FALSE))
                throw('Compiler');
        if (cc->token != ')')
                LexExcept(cc, "Missing ')' at ");
        Lex(cc);
        lb = COCMiscNew(cc, CMT_LABEL);
        ICAdd(cc, IC_BR_ZERO, lb, 0);
        ParseStatement(cc, try_count, lb_break);
        k = ParseKeyWord(cc);
        if (k == KW_ELSE)
        {
                Lex(cc);
                lb1 = COCMiscNew(cc, CMT_LABEL);
                ICAdd(cc, IC_JMP, lb1, 0);
                ICAdd(cc, IC_LABEL, lb, 0);
                ParseStatement(cc, try_count, lb_break);
                ICAdd(cc, IC_LABEL, lb1, 0);
        }
        else
                ICAdd(cc, IC_LABEL, lb, 0);
}

U0 ParseWhile(CCompCtrl *cc, I64 try_count)
{
        CCodeMisc *lb, *lb_done;

        if (cc->token != '(')
                LexExcept(cc, "Expecting '(' at ");
        Lex(cc);
        lb = COCMiscNew(cc, CMT_LABEL);
        ICAdd(cc, IC_LABEL, lb, 0);
        if (!ParseExpression(cc, NULL,FALSE))
                throw('Compiler');
        if (cc->token != ')')
                LexExcept(cc, "Missing ')' at ");
        Lex(cc);
        lb_done = COCMiscNew(cc, CMT_LABEL);
        ICAdd(cc, IC_BR_ZERO, lb_done, 0);
        ParseStatement(cc, try_count, lb_done);
        ICAdd(cc, IC_JMP, lb, 0);
        ICAdd(cc, IC_LABEL, lb_done, 0);
}

U0 ParseDoWhile(CCompCtrl *cc, I64 try_count)
{
        CCodeMisc *lb, *lb_done;

        lb = COCMiscNew(cc, CMT_LABEL);
        lb_done = COCMiscNew(cc, CMT_LABEL);
        ICAdd(cc, IC_LABEL, lb, 0);
        ParseStatement(cc, try_count, lb_done);
        if (ParseKeyWord(cc) != KW_WHILE)
                LexExcept(cc, "Missing 'while' at");
        if (Lex(cc) != '(')
                LexExcept(cc, "Expecting '(' at ");
        Lex(cc);
        if (!ParseExpression(cc, NULL, FALSE))
                throw('Compiler');
        if (cc->token != ')')
                LexExcept(cc, "Missing ')' at ");
        ICAdd(cc, IC_BR_NOT_ZERO, lb, 0);
        ICAdd(cc, IC_LABEL, lb_done, 0);
        if (Lex(cc) != ';')
                LexExcept(cc, "Missing ';' at");
        Lex(cc);
}

U0 ParseFor(CCompCtrl *cc, I64 try_count)
{
        CCodeCtrl *tmpcbh;
        CCodeMisc *lb, *lb_done;

        if (cc->token != '(')
                LexExcept(cc, "Expecting '(' at ");
        Lex(cc);
        ParseStatement(cc, try_count);

        lb = COCMiscNew(cc, CMT_LABEL);
        ICAdd(cc, IC_LABEL, lb, 0);
        if (!ParseExpression(cc, NULL, FALSE))
                throw('Compiler');
        lb_done = COCMiscNew(cc, CMT_LABEL);
        ICAdd(cc, IC_BR_ZERO, lb_done, 0);
        if (cc->token != ';')
                LexExcept(cc, "Missing ';' at");
        Lex(cc);

        COCPush(cc);
        COCInit(cc);
        if (cc->token != ')')
                ParseStatement(cc, try_count, NULL, 0);
        COCPush(cc);
        tmpcbh = COCPopNoFree(cc);
        COCPop(cc);
        if (cc->token != ')')
                LexExcept(cc, "Missing ')' at ");
        Lex(cc);

        ParseStatement(cc, try_count, lb_done);
        COCAppend(cc, tmpcbh);
        ICAdd(cc, IC_JMP, lb, 0);
        ICAdd(cc, IC_LABEL, lb_done, 0);
}

class CSubSwitch
{
        CSubSwitch *next, *last;
        CCodeMisc  *lb_start, *lb_break;
};

class CSwitchCase
{
        CSwitchCase     *next;
        CCodeMisc       *label;
        I64                      val;
        CSubSwitch      *ss;
};

U0 ParseSwitch(CCompCtrl *cc, I64 try_count)
{
        CSwitchCase                     *header = NULL, *tmps, *tmps1;  //Leaks on except
        CSubSwitch                       head, *tmpss;                                  //Leaks on except
        CCodeMisc                       *lb_default, *lb_fwd_case, *mc_jt, *lb_entry, **jmp_table;
        CIntermediateCode       *tmpi_sub, *tmpi_cmp, *tmpi_jmp, *tmpi_start;
        Bool                             default_found = FALSE, nobound;
        I64                                      i, k_start = I64_MIN, k_end, lo = I64_MAX, hi = I64_MIN, range;

        if (cc->token == '(')
                nobound = FALSE;
        else if (cc->token == '[')
                nobound = TRUE;
        else
                LexExcept(cc, "Expecting '(' or '[' at ");
        Lex(cc);
        QueueInit(&head);

        head.last->lb_break = COCMiscNew(cc, CMT_LABEL);
        head.last->lb_break->use_count++;
        lb_default = COCMiscNew(cc, CMT_LABEL);
        lb_default->use_count++;
        mc_jt = COCMiscNew(cc, CMT_JMP_TABLE);
        mc_jt->begin = COCMiscNew(cc, CMT_LABEL);
        mc_jt->begin->use_count++;
        if (!ParseExpression(cc, NULL, FALSE))
                throw('Compiler');
        tmpi_sub = ICAdd(cc, IC_IMM_I64, 0, cmp.internal_types[RT_I64]);
        ICAdd(cc, IC_SUB, 0, cmp.internal_types[RT_I64]);
        tmpi_cmp = ICAdd(cc, IC_IMM_I64, 0, cmp.internal_types[RT_I64]);
        if (nobound)
        {
                ICAdd(cc, IC_NOBOUND_SWITCH, mc_jt, 0);
                if (cc->token != ']')
                        LexExcept(cc, "Missing ']' at ");
        }
        else
        {
                ICAdd(cc, IC_SWITCH, mc_jt, 0);
                if (cc->token != ')')
                        LexExcept(cc, "Missing ')' at ");
        }
        if (Lex(cc) != '{')
                LexExcept(cc, "Expecting '{' at ");
        Lex(cc);
        ICAdd(cc, IC_LABEL, mc_jt->begin, 0);
        while (TRUE)
        {
                while (cc->token && cc->token != '}')
                {
sw_cont:
                        switch (ParseKeyWord(cc))
                        {
                                case KW_END:
                                        goto sw_sub_end;

                                case KW_START:
                                        if (Lex(cc) == ':')
                                                Lex(cc);
                                        else
                                                LexExcept(cc, "Expecting ':' at ");
                                        tmpss = MAlloc(sizeof(CSubSwitch));
                                        QueueInsert(tmpss, head.last);
                                        head.last->lb_break = COCMiscNew(cc, CMT_LABEL);
                                        head.last->lb_break->use_count++;
                                        lb_fwd_case = COCMiscNew(cc, CMT_LABEL);
                                        tmpi_jmp = ICAdd(cc, IC_JMP, lb_fwd_case, 0);

                                        tmpss->lb_start = COCMiscNew(cc, CMT_LABEL);
                                        tmpi_start = ICAdd(cc, IC_LABEL, tmpss->lb_start, 0);
                                        while (cc->token && cc->token != '}')
                                        {
                                                switch (ParseKeyWord(cc))
                                                {
                                                        case KW_END:
                                                                OptFree(tmpi_jmp);
                                                                goto sw_sub_end;

                                                        case KW_START:
                                                        case KW_CASE:
                                                        case KW_DEFAULT:
                                                                if (cc->coc.coc_head.last == tmpi_start)
                                                                {
                                                                        OptFree(tmpi_jmp);
                                                                        tmpss->lb_start = NULL;
                                                                }
                                                                else
                                                                {
                                                                        ICAdd(cc, IC_RET, 0, 0);
                                                                        ICAdd(cc, IC_LABEL, lb_fwd_case, 0);
                                                                        ICAdd(cc, IC_SUB_CALL, tmpss->lb_start, 0);//In case fall-thru
                                                                }
                                                                goto sw_cont;

                                                        default:
                                                                ParseStatement(cc, try_count);
                                                }
                                        }
                                        break;

                                case KW_CASE:
                                        if (head.next != &head)
                                        {
                                                lb_fwd_case = COCMiscNew(cc, CMT_LABEL);
                                                tmpi_jmp = ICAdd(cc, IC_JMP, lb_fwd_case, 0);//In case fall-thru
                                        }
                                        Lex(cc);
                                        lb_entry = COCMiscNew(cc, CMT_LABEL);
                                        ICAdd(cc, IC_LABEL, lb_entry, 0);
                                        lb_entry->use_count++;
                                        if (head.next != &head)
                                        {
                                                tmpss = head.next;
                                                while (tmpss != &head)
                                                {
                                                        if (tmpss->lb_start)
                                                                ICAdd(cc, IC_SUB_CALL, tmpss->lb_start, 0);
                                                        tmpss = tmpss->next;
                                                }
                                                ICAdd(cc, IC_LABEL, lb_fwd_case, 0);
                                        }
                                        if (cc->token == ':')
                                        {
                                                if (k_start == I64_MIN)
                                                        k_start = 0;
                                                else
                                                        k_start++;
                                        }
                                        else
                                                k_start = LexExpressionI64(cc);
                                        if (k_start < lo)
                                                lo = k_start;
                                        if (k_start > hi)
                                                hi = k_start;
                                        if (cc->token == ':')
                                        {
                                                Lex(cc);
                                                tmps = MAlloc(sizeof(CSwitchCase));
                                                tmps->label = lb_entry;
                                                tmps->val = k_start;
                                                tmps->next = header;
                                                header = tmps;
                                        }
                                        else if (cc->token == TK_ELLIPSIS)
                                        {
                                                Lex(cc);
                                                k_end = LexExpressionI64(cc);
                                                if (cc->token == ':')
                                                {
                                                        Lex(cc);
                                                        if (k_end < lo)
                                                                lo = k_end;
                                                        if (k_end > hi)
                                                                hi = k_end;
                                                        if (k_start > k_end)
                                                                SwapI64(&k_start, &k_end);
                                                        for (i = k_start; i <= k_end; i++)
                                                        {
                                                                tmps = MAlloc(sizeof(CSwitchCase));
                                                                tmps->label = lb_entry;
                                                                tmps->val = i;
                                                                tmps->next = header;
                                                                header = tmps;
                                                        }
                                                        k_start = k_end;
                                                }
                                                else
                                                        LexExcept(cc, "Expecting ':' at ");
                                        }
                                        else
                                                LexExcept(cc, "Expecting ':' at ");
                                        break;

                                case KW_DEFAULT:
                                        if (head.next != &head)
                                        {
                                                lb_fwd_case = COCMiscNew(cc, CMT_LABEL);
                                                tmpi_jmp = ICAdd(cc, IC_JMP, lb_fwd_case, 0);//In case fall-thru
                                        }
                                        Lex(cc);
                                        ICAdd(cc, IC_LABEL, lb_default, 0);
                                        if (cc->token == ':')
                                                Lex(cc);
                                        else
                                                LexExcept(cc, "Expecting ':' at ");
                                        if (head.next != &head)
                                        {
                                                tmpss = head.next;
                                                while (tmpss != &head)
                                                {
                                                        if (tmpss->lb_start)
                                                                ICAdd(cc, IC_SUB_CALL, tmpss->lb_start, 0);
                                                        tmpss = tmpss->next;
                                                }
                                                ICAdd(cc, IC_LABEL, lb_fwd_case, 0);
                                        }
                                        default_found = TRUE;
                                        break;

                                default:
                                        ParseStatement(cc, try_count, head.last->lb_break);
                        }
                }
sw_sub_end:
                tmpss = head.last;
                ICAdd(cc, IC_LABEL, tmpss->lb_break, 0);
                if (tmpss == &head)
                {
                        if (cc->token != '}')
                                LexExcept(cc, "Missing '}' at ");
                        Lex(cc);
                        break;
                }
                else
                {
                        QueueRemove(tmpss);
                        Free(tmpss);
                        if (ParseKeyWord(cc) != KW_END)
                                LexExcept(cc, "Missing 'end' at ");
                        if (Lex(cc) == ':')
                                Lex(cc);
                        else
                                LexExcept(cc, "Expecting ':' at ");
                }
        }
        if (!default_found)
                ICAdd(cc, IC_LABEL, lb_default, 0);

        if (0 < lo <= 16)
                lo = 0;
        range = hi - lo + 1;
        if (lo > hi || !(0 < range <= 0xFFFF))
                LexExcept(cc, "switch range error at ");
        jmp_table = MAlloc((sizeof(CCodeMisc *) * range + 0x1FF) & ~0x1FF);
        MemSetI64(jmp_table, lb_default, range);
        tmpi_sub->ic_data = lo;
        tmpi_cmp->ic_data = range;
        tmps = header;
        while (tmps)
        {
                tmps1 = tmps->next;
                if (jmp_table[tmps->val - lo] != lb_default)
                        LexExcept(cc, "Duplicate case at ");
                else
                        jmp_table[tmps->val - lo] = tmps->label;
                Free(tmps);
                tmps = tmps1;
        }
        mc_jt->default = lb_default;
        mc_jt->jmp_table = jmp_table;
        mc_jt->range = range;
}

U0 ParseNoWarn(CCompCtrl *cc)
{
        CMemberList *tmpm;

        while (cc->token == TK_IDENT)
        {
                if (!(tmpm = cc->local_var_entry))
                        LexExcept(cc, "Expecting local var at ");
                tmpm->flags |= MLF_NO_UNUSED_WARN;
                if (Lex(cc) == ',')
                        Lex(cc);
                else if (cc->token != ';')
                        LexExcept(cc, "Expecting ',' at ");
        }
}

U0 ParseStreamBlk(CCompCtrl *cc)
{
        CLexHashTableContext    *htc = MAlloc(sizeof(CLexHashTableContext));
        CStreamBlk                              *tmpe = MAlloc(sizeof(CStreamBlk));

        tmpe->body = StrNew("");
        QueueInsert(tmpe, cc->last_stream_blk);
        COCPush(cc);
        QueueInit(&cc->coc.coc_next_misc);

        MemCopy(htc, &cc->htc, sizeof(CLexHashTableContext));
        htc->old_flags = cc->flags;
        cc->htc.next = htc;
        cc->htc.fun = cc->htc.local_var_list  =NULL;
        cc->htc.define_hash_table = cc->htc.hash_table_list =
                cc->htc.global_hash_table = cc->htc.local_hash_table = Fs->hash_table;
        cc->flags = cc->flags & ~(CCF_ASM_EXPRESSIONS | CCF_AOT_COMPILE) | CCF_EXE_BLK;
        if (cc->token == '{')
                Lex(cc);
        else
                LexExcept(cc, "Missing '}' at ");
        while (cc->token && cc->token != '}')
                ExeCmdLine(cc);

        MemCopy(&cc->htc, htc, sizeof(CLexHashTableContext));
        cc->flags = cc->flags & ~CCF_EXE_BLK | htc->old_flags & (CCF_ASM_EXPRESSIONS | CCF_EXE_BLK | CCF_AOT_COMPILE);
        Free(htc);
        COCPop(cc);
        QueueRemove(tmpe);
        if (*tmpe->body)
                LexIncludeStr(cc, "StreamBlk", tmpe->body, FALSE);
        else
                Free(tmpe->body);
        Free(tmpe);
        Lex(cc); //Skip '}'
}

U0 ParseTryBlk(CCompCtrl *cc, I64 try_count)
{
        CCodeMisc       *lb_catch, *lb_done, *lb_untry;
        CHashClass      *tmpc = cmp.internal_types[RT_PTR];
        CHashFun        *tmp_try   = HashFind("SysTry", cc->htc.hash_table_list, HTT_FUN),
                                *tmp_untry = HashFind("SysUntry", cc->htc.hash_table_list, HTT_FUN);

        if (!tmp_try || !tmp_untry)
                LexExcept(cc, "Missing header for SysTry() and SysUntry() at ");

        cc->flags |= CCF_NO_REG_OPT; //TODO:Currently no reg vars in funs with try/catch

        lb_catch = COCMiscNew(cc, CMT_LABEL);
        lb_done  = COCMiscNew(cc, CMT_LABEL);
        lb_untry = COCMiscNew(cc, CMT_LABEL);

        ICAdd(cc, IC_CALL_START, 0, 0);
        ICAdd(cc, IC_GET_LABEL, lb_untry, tmpc, ICF_PUSH_RES);
        ICAdd(cc, IC_GET_LABEL, lb_catch, tmpc, ICF_PUSH_RES);
        if (Bt(&tmp_try->flags, Cf_EXTERN))
        {
                cc->abs_counts.externs++;
                if (cc->flags & CCF_AOT_COMPILE)
                        ICAdd(cc, IC_CALL_IMPORT, tmp_try, tmpc);
                else
                        ICAdd(cc, IC_CALL_INDIRECT2, &tmp_try->exe_addr, tmpc);
        }
        else
                ICAdd(cc, IC_CALL, tmp_try->exe_addr, tmpc);
        if ((Bt(&tmp_try->flags, Ff_RET1) || Bt(&tmp_try->flags, Ff_ARGPOP)) && !Bt(&tmp_try->flags, Ff_NOARGPOP))
                ICAdd(cc, IC_ADD_RSP1, 16, tmpc);
        else
                ICAdd(cc, IC_ADD_RSP, 16, tmpc);
        ICAdd(cc, IC_CALL_END, 0, tmpc);
        ICAdd(cc, IC_END_EXP, 0, 0, ICF_RES_NOT_USED);

        ParseStatement(cc, try_count + 1);

        ICAdd(cc, IC_LABEL, lb_untry, 0);
        ICAdd(cc, IC_CALL_START, 0, 0);
        if (Bt(&tmp_untry->flags, Cf_EXTERN))
        {
                cc->abs_counts.externs++;
                if (cc->flags & CCF_AOT_COMPILE)
                        ICAdd(cc, IC_CALL_IMPORT, tmp_untry, tmpc);
                else
                        ICAdd(cc, IC_CALL_INDIRECT2, &tmp_untry->exe_addr, tmpc);
        }
        else
                ICAdd(cc, IC_CALL, tmp_untry->exe_addr, tmpc);
        ICAdd(cc, IC_CALL_END, 0, tmpc);
        ICAdd(cc, IC_END_EXP, 0, 0, ICF_RES_NOT_USED);

        ICAdd(cc, IC_JMP, lb_done, 0);

        if (ParseKeyWord(cc) != KW_CATCH)
                LexExcept(cc, "Missing 'catch' at");

        Lex(cc);
        ICAdd(cc, IC_LABEL, lb_catch, 0);
        ParseStatement(cc, try_count + 1);
        ICAdd(cc, IC_RET, 0, tmpc);
        ICAdd(cc, IC_LABEL, lb_done, 0);
}

Bool ParseStatement(CCompCtrl *cc, I64 try_count=0, CCodeMisc *lb_break=NULL, I64 comp_flags=CMPF_PRS_SEMICOLON)
{
        I64                      i, fsp_flags = 0;
        CHashExport     *tmpex;
        CCodeMisc       *g_lb;
        U8                      *import_name;
        CHashFun        *tmp_untry;
        CAOT            *tmpaot;

        if (comp_flags & CMPF_ONE_ASM_INS)
        {
                if (cc->flags & CCF_AOT_COMPILE || cc->aot_depth)
                        ParseAsmBlk(cc, CMPF_ONE_ASM_INS);
                else if (tmpaot = CompJoin(cc, CMPF_ASM_BLK | CMPF_ONE_ASM_INS))
                        CompFixUpJITAsm(cc, tmpaot);
                fsp_flags = FSF_ASM;
        }
        else
                while (TRUE)
                {
                        while (cc->token == ',')
                                Lex(cc);
                        if (cc->token == '{')
                        {
                                Lex(cc);
                                while (cc->token != '}' && cc->token != TK_EOF)
                                        ParseStatement(cc, try_count, lb_break);
                                if (cc->lex_include_stack == cc->fun_lex_file)
                                        cc->max_line = cc->lex_include_stack->line_num;
                                if (Lex(cc) != ',')
                                        goto sm_done;
                        }
                        else if (cc->token == ';')
                        {
                                if (comp_flags & CMPF_PRS_SEMICOLON)
                                        Lex(cc);
                                if (cc->token != ',')
                                        goto sm_done;
                        }
                        else
                        {
                                if (cc->token == TK_IDENT)
                                {
                                        if (tmpex = cc->hash_entry)
                                        {
                                                if (tmpex->type & HTT_KEYWORD)
                                                {
                                                        i = tmpex(CHashGeneric *)->user_data0;
                                                        switch [i]
                                                        {
                                                                case KW_KWS_NUM - 1: //nobound switch
                                                                default: //A keyword that is not valid here is just a symbol.
                                                                        goto sm_not_keyword_afterall;
                                                                start:
                                                                        case KW_ASM:
                                                                                if (cc->htc.fun)
                                                                                {
                                                                                        if (tmpaot = CompJoin(cc, CMPF_ASM_BLK))
                                                                                                ICAdd(cc, IC_ASM, tmpaot, 0);
                                                                                        Lex(cc); //Skip '}' of asm{}
                                                                                }
                                                                                else
                                                                                {
                                                                                        if (cc->flags & CCF_AOT_COMPILE || cc->aot_depth)
                                                                                        {
                                                                                                Lex(cc);
                                                                                                ParseAsmBlk(cc, 0);
                                                                                                if (cc->flags & CCF_AOT_COMPILE && cc->aot_depth == 1)
                                                                                                        Lex(cc); //Skip '}' of asm{}
                                                                                        }
                                                                                        else
                                                                                        {
                                                                                                if (tmpaot = CompJoin(cc, CMPF_ASM_BLK))
                                                                                                        CompFixUpJITAsm(cc, tmpaot);
                                                                                                Lex(cc); //Skip '}' of asm{}
                                                                                        }
                                                                                        fsp_flags = FSF_ASM;
                                                                                }
                                                                                break;
                                                                        start:
                                                                                Lex(cc);
                                                                                case KW_LOCK:
                                                                                        cc->lock_count++;
                                                                                        ParseStatement(cc, try_count);
                                                                                        cc->lock_count--;
                                                                                        break;

                                                                                case KW_TRY:
                                                                                        ParseTryBlk(cc, try_count);
                                                                                        break;

                                                                                case KW_IF:
                                                                                        ParseIf(cc, try_count, lb_break);
                                                                                        break;

                                                                                case KW_FOR:
                                                                                        ParseFor(cc, try_count);
                                                                                        break;

                                                                                case KW_WHILE:
                                                                                        ParseWhile(cc, try_count);
                                                                                        break;

                                                                                case KW_DO:
                                                                                        ParseDoWhile(cc, try_count);
                                                                                        break;

                                                                                case KW_SWITCH:
                                                                                        ParseSwitch(cc, try_count);
                                                                                        break;
                                                                        end:
                                                                end:
                                                                        if (cc->token != ',')
                                                                                goto sm_done;
                                                                        break;
                                                                start:
                                                                        if (cc->htc.fun)
                                                                                LexExcept(cc, "Not allowed in fun");
                                                                        Lex(cc);
                                                                        case KW__EXTERN:
                                                                                if (Bt(&cc->opts, OPTf_EXTERNS_TO_IMPORTS))
                                                                                        goto sm_underscore_import;
                                                                                if (cc->token != TK_IDENT || !(tmpex = cc->hash_entry) ||
                                                                                                !(tmpex->type & HTT_EXPORT_SYS_SYM))
                                                                                        LexExcept(cc, "Expecting system sym at ");
                                                                                if (*cc->cur_str == '_')
                                                                                        fsp_flags |= FSF__;
                                                                                i = tmpex->val;
                                                                                Lex(cc);
                                                                                if (cc->token != TK_IDENT || !(tmpex = cc->hash_entry) ||
                                                                                                !(tmpex->type & (HTT_CLASS | HTT_INTERNAL_TYPE)))
                                                                                        LexExcept(cc, "Expecting type at ");
                                                                                Lex(cc);
                                                                                ParseGlobalVarList(cc, PRS0__EXTERN | PRS1_NULL, tmpex, i, fsp_flags);
                                                                                break;

                                                                        case KW__IMPORT:
sm_underscore_import:
                                                                                if (cc->token != TK_IDENT)
                                                                                        LexExcept(cc, "Expecting system sym at ");
                                                                                if (*cc->cur_str == '_')
                                                                                        fsp_flags |= FSF__;
                                                                                import_name = cc->cur_str;
                                                                                cc->cur_str = 0;
                                                                                if (Lex(cc) != TK_IDENT || !(tmpex = cc->hash_entry) ||
                                                                                                !(tmpex->type & (HTT_CLASS | HTT_INTERNAL_TYPE)))
                                                                                        LexExcept(cc, "Expecting type at ");
                                                                                Lex(cc);
                                                                                ParseGlobalVarList(cc, PRS0__IMPORT | PRS1_NULL, tmpex, import_name, fsp_flags);
                                                                                Free(import_name);
                                                                                break;

                                                                        case KW_EXTERN:
                                                                                if (cc->token != TK_IDENT)
                                                                                        LexExcept(cc, "Expecting type at ");
                                                                                tmpex = cc->hash_entry;
                                                                                i = ParseKeyWord(cc);
                                                                                if (i == KW_CLASS || i == KW_UNION)
                                                                                {
                                                                                        Lex(cc);
                                                                                        ParseClass(cc, i, fsp_flags, TRUE);
                                                                                        fsp_flags &= FSF_ASM;
                                                                                        goto sm_semicolon;
                                                                                }
                                                                                if (!tmpex || !(tmpex->type & (HTT_CLASS | HTT_INTERNAL_TYPE)))
                                                                                        LexExcept(cc, "Expecting type at ");
                                                                                if (Bt(&cc->opts, OPTf_EXTERNS_TO_IMPORTS))
                                                                                        goto sm_import;
                                                                                Lex(cc);
                                                                                ParseGlobalVarList(cc, PRS0_EXTERN | PRS1_NULL, tmpex, 0, fsp_flags);
                                                                                break;

                                                                        case KW_IMPORT:
                                                                                if (cc->token != TK_IDENT || !(tmpex = cc->hash_entry) ||
                                                                                                !(tmpex->type & (HTT_CLASS | HTT_INTERNAL_TYPE)))
                                                                                        LexExcept(cc, "Expecting type at ");
sm_import:
                                                                                Lex(cc);
                                                                                ParseGlobalVarList(cc, PRS0_IMPORT | PRS1_NULL, tmpex, 0, fsp_flags);
                                                                                break;

                                                                        case KW__INTERN:
                                                                                i = LexExpressionI64(cc);
                                                                                if (cc->token != TK_IDENT || !(tmpex = cc->hash_entry) ||
                                                                                                !(tmpex->type & (HTT_CLASS | HTT_INTERNAL_TYPE)))
                                                                                        LexExcept(cc, "Expecting type at ");
                                                                                Lex(cc);
                                                                                ParseGlobalVarList(cc, PRS0__INTERN | PRS1_NULL, tmpex, i, fsp_flags);
                                                                                break;
                                                                end:
                                                                        fsp_flags &= FSF_ASM;
                                                                        break;
                                                                start:
                                                                        case KW_STATIC:
                                                                                fsp_flags = FSF_STATIC | fsp_flags & FSF_ASM;
                                                                                break;

                                                                        case KW_INTERRUPT:
                                                                                fsp_flags = FSF_INTERRUPT | FSF_NOARGPOP | fsp_flags & (FSG_FUN_FLAGS2 | FSF_ASM);
                                                                                break;

                                                                        case KW_HASERRCODE:
                                                                                fsp_flags = FSF_HASERRCODE | fsp_flags & (FSG_FUN_FLAGS2 | FSF_ASM);
                                                                                break;

                                                                        case KW_ARGPOP:
                                                                                fsp_flags = FSF_ARGPOP | fsp_flags & (FSG_FUN_FLAGS2 | FSF_ASM);
                                                                                break;

                                                                        case KW_NOARGPOP:
                                                                                fsp_flags = FSF_NOARGPOP | fsp_flags & (FSG_FUN_FLAGS2 | FSF_ASM);
                                                                                break;

                                                                        case KW_PUBLIC:
                                                                                fsp_flags = FSF_PUBLIC | fsp_flags & (FSG_FUN_FLAGS2 | FSF_ASM);
                                                                                break;
                                                                end:
                                                                        Lex(cc);
                                                                        break;

                                                                case KW_RETURN:
                                                                        if (!cc->htc.fun)
                                                                                LexExcept(cc, "Not in fun.  Can't return a val ");
                                                                        if (try_count)
                                                                        {
                                                                                tmp_untry = HashFind("SysUntry", cc->htc.hash_table_list, HTT_FUN);
                                                                                for (i = 0; i < try_count; i++)
                                                                                {
                                                                                        if (Bt(&tmp_untry->flags, Cf_EXTERN))
                                                                                        {
                                                                                                cc->abs_counts.externs++;
                                                                                                if (cc->flags & CCF_AOT_COMPILE)
                                                                                                        ICAdd(cc, IC_CALL_IMPORT, tmp_untry, cmp.internal_types[RT_PTR]);
                                                                                                else
                                                                                                        ICAdd(cc, IC_CALL_INDIRECT2, &tmp_untry->exe_addr,
                                                                                                                  cmp.internal_types[RT_PTR]);
                                                                                        }
                                                                                        else
                                                                                                ICAdd(cc, IC_CALL, tmp_untry->exe_addr, cmp.internal_types[RT_PTR]);
                                                                                }
                                                                        }
                                                                        if (Lex(cc) != ';')
                                                                        {
                                                                                if (!cc->htc.fun->return_class->size)
                                                                                        LexWarn(cc, "Function should NOT return val ");
                                                                                if (!ParseExpression(cc, NULL, FALSE))
                                                                                        throw('Compiler');
                                                                                ICAdd(cc, IC_RETURN_VAL, 0, cc->htc.fun->return_class);
                                                                                cc->flags |= CCF_HAS_RETURN;
                                                                        }
                                                                        else if (cc->htc.fun->return_class->size)
                                                                                LexWarn(cc, "Function should return val ");
                                                                        ICAdd(cc, IC_JMP, cc->lb_leave, 0);
                                                                        goto sm_semicolon;

                                                                case KW_GOTO:
                                                                        if (Lex(cc) != TK_IDENT)
                                                                                LexExcept(cc, "Expecting identifier at ");
                                                                        if (!(g_lb = COCGoToLabelFind(cc, cc->cur_str)))
                                                                        {
                                                                                g_lb = COCMiscNew(cc, CMT_GOTO_LABEL);
                                                                                g_lb->str = cc->cur_str;
                                                                                cc->cur_str = NULL;
                                                                        }
                                                                        g_lb->use_count++;
                                                                        ICAdd(cc, IC_JMP, g_lb, 0);
                                                                        Lex(cc);
                                                                        goto sm_semicolon;

                                                                case KW_BREAK:
                                                                        Lex(cc);
                                                                        if (!lb_break)
                                                                                LexExcept(cc, "'break' not allowed\n");
                                                                        ICAdd(cc, IC_JMP, lb_break, 0);
                                                                        goto sm_semicolon;

                                                                case KW_NO_WARN:
                                                                        Lex(cc);
                                                                        ParseNoWarn(cc);
                                                                        goto sm_semicolon;

                                                                case KW_UNION:
                                                                case KW_CLASS:
                                                                        Lex(cc);
                                                                        tmpex = ParseClass(cc, i, fsp_flags, FALSE);
                                                                        if (!cc->htc.fun && cc->token != ';') {
                                                                                ParseGlobalVarList(cc, PRS0_NULL | PRS1_NULL, tmpex, 0, fsp_flags);
                                                                                fsp_flags &= FSF_ASM;
                                                                                break;
                                                                        }
                                                                        else
                                                                        {
                                                                                fsp_flags &= FSF_ASM;
                                                                                goto sm_semicolon;
                                                                        }
                                                        }
                                                }
                                                else
                                                {//Ident, found in hash table, not keyword
sm_not_keyword_afterall:
                                                        if (tmpex->type & (HTT_CLASS | HTT_INTERNAL_TYPE))
                                                        {
                                                                if (cc->htc.fun)
                                                                {
                                                                        if (fsp_flags & FSF_STATIC)
                                                                                ParseVarList(cc, cc->htc.fun, PRS0_NULL | PRS1_STATIC_LOCAL_VAR);
                                                                        else
                                                                                ParseVarList(cc, cc->htc.fun, PRS0_NULL | PRS1_LOCAL_VAR);
                                                                        if (cc->token == '}')
                                                                                goto sm_done;
                                                                }
                                                                else
                                                                {
                                                                        Lex(cc);
                                                                        ParseGlobalVarList(cc, PRS0_NULL | PRS1_NULL, tmpex, 0, fsp_flags);
                                                                }
                                                        }
                                                        else
                                                        {
                                                                if (tmpex->type & (HTT_OPCODE | HTT_ASM_KEYWORD))
                                                                {
                                                                        if (cc->htc.fun)
                                                                        {
                                                                                if (tmpaot = CompJoin(cc, CMPF_ASM_BLK | CMPF_ONE_ASM_INS))
                                                                                        ICAdd(cc, IC_ASM, tmpaot, 0);
                                                                        }
                                                                        else
                                                                                LexExcept(cc, "Use Asm Blk at ");
                                                                        if (cc->token != ',')
                                                                                goto sm_done;
                                                                }
                                                                else
                                                                        goto sm_parse_exp;
                                                        }
                                                        fsp_flags &= FSF_ASM;
                                                }
                                        }
                                        else
                                        {//Ident, not in hash table
                                                if (cc->local_var_entry)
                                                        goto sm_parse_exp;
                                                if (!(g_lb = COCGoToLabelFind(cc, cc->cur_str)))
                                                {
                                                        g_lb = COCMiscNew(cc, CMT_GOTO_LABEL);
                                                        g_lb->str = cc->cur_str;
                                                        cc->cur_str = NULL;
                                                }
                                                else if (g_lb->flags & CMF_DEFINED)
                                                        LexExcept(cc, "Duplicate goto label at ");
                                                g_lb->flags |= CMF_DEFINED;
                                                ICAdd(cc, IC_LABEL, g_lb, 0);
                                                if (Lex(cc) == ':') //skip cur_str
                                                        Lex(cc); //skip colon
                                                else
                                                        LexExcept(cc, "Undefined identifier at ");
                                                if (!cc->htc.fun)
                                                        LexExcept(cc, "No global labels at ");
                                                if (cc->token != ',')
                                                        goto sm_done;
                                        }
                                }
                                else if (cc->token == TK_STR || cc->token == TK_CHAR_CONST)
                                {
                                        ParseFunCall(cc, NULL, FALSE, NULL);
                                        goto sm_semicolon;
                                }
                                else if (cc->token != TK_EOF)
                                {//Non-cur_str symbol, num or something
sm_parse_exp:
                                        if (!ParseExpression(cc, NULL, TRUE))
                                                throw('Compiler');
sm_semicolon:
                                        if (comp_flags & CMPF_PRS_SEMICOLON)
                                        {
                                                if (cc->token == ';')
                                                        Lex(cc);
                                                else if (cc->token != ',')
                                                        LexExcept(cc, "Missing ';' at");
                                        }
                                        if (cc->token != ',')
                                                goto sm_done;
                                }
                                else
                                        goto sm_done; //TK_EOF
                        }
                }
sm_done:

        return fsp_flags & FSF_ASM;
}