CHashClass *PrsClass(CCmpCtrl *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=PrsClassNew;
    tmpc->str=cc->cur_str;
    cc->cur_str=NULL;
    HashAdd(tmpc,cc->htc.glbl_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.glbl_hash_table,HTT_CLASS);
    else
      tmpc=HashSingleTableFind(cc->cur_str,cc->htc.glbl_hash_table,HTT_CLASS);
    if (tmpc) {
      if (!Bt(&tmpc->flags,Cf_EXTERN))
        tmpc=NULL;
      else if (tmpc->use_cnt<3)
        UnusedExternWarning(cc,tmpc);
    }
    if (tmpc) {
      Free(tmpc->src_link);
      tmpc->src_link=NULL;
      Free(tmpc->idx);
      tmpc->idx=NULL;
    } else {
      tmpc=PrsClassNew;
      tmpc->str=cc->cur_str;
      cc->cur_str=NULL;
      HashAdd(tmpc,cc->htc.glbl_hash_table);
    }
    LBtr(&tmpc->flags,Cf_EXTERN);
    if (fsp_flags&FSF_PUBLIC)
      tmpc->type|=HTF_PUBLIC;
    tmpc->use_cnt=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)
      PrsVarLst(cc,tmpc,PRS0_NULL|PRS1_CLASS|PRSF_UNION);
    else
      PrsVarLst(cc,tmpc,PRS0_NULL|PRS1_CLASS);
    tmpc->size+=tmpc->neg_offset;
  }
  return tmpc;
}

CHashFun *PrsFunJoin(CCmpCtrl *cc,CHashClass *tmp_return,
        U8 *name,I64 fsp_flags)
{
  CMemberLst *tmpm,*header_lst;
  CAOTCtrl *aotc=cc->aotc;
  CHashClass *header_return;
  CHashFun *tmpf;
  I64 header_arg_cnt;
  if (name) {//if not fun_ptr
    if (cc->flags&CCF_AOT_COMPILE) {
      if ((tmpf=HashFind(name,cc->htc.glbl_hash_table,HTT_FUN)) &&
            tmpf->type & HTF_IMPORT)
        tmpf=NULL;
    } else
      if ((tmpf=HashSingleTableFind(name,cc->htc.glbl_hash_table,HTT_FUN)) &&
            !Bt(&tmpf->flags,Cf_EXTERN))
        tmpf=NULL;
    if (tmpf && tmpf->use_cnt<3)
      UnusedExternWarning(cc,tmpf);
  } else
    tmpf=NULL;
  if (tmpf) {
    tmpf->used_reg_mask=REGG_CLOBBERED+REGG_SAVED+REGG_STK_TMP;
    Free(tmpf->src_link);
    tmpf->src_link=NULL;
    Free(tmpf->idx);
    tmpf->idx=NULL;
    Free(name);
    header_arg_cnt=tmpf->arg_cnt;
    header_lst=tmpf->member_lst_and_root;
    header_return=tmpf->return_class;
    tmpf->member_lst_and_root=NULL;
    ClassMemberLstDel(tmpf);
  } else {
    tmpf=PrsFunNew;
    header_return=NULL;
    tmpf->used_reg_mask=REGG_CLOBBERED+REGG_SAVED+REGG_STK_TMP;
    tmpf->clobbered_reg_mask=REGG_CLOBBERED+REGG_STK_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.glbl_hash_table);
  }
  BEqu(&tmpf->type,HTf_PUBLIC,fsp_flags&FSF_PUBLIC);
  tmpf->return_class=tmp_return;
  tmpf->use_cnt=0;
  HashSrcFileSet(cc,tmpf);
  PrsVarLst(cc,tmpf,PRS0_NULL|PRS1_FUN_ARG);
  tmpf->arg_cnt=tmpf->member_cnt;
  if (0<tmpf->arg_cnt<<3<=I16_MAX && !Bt(&tmpf->flags,Ff_DOT_DOT_DOT))
    LBts(&tmpf->flags,Ff_RET1);
  tmpm=tmpf->member_lst_and_root;
  while (tmpm) {
    tmpm->offset+=16; //RBP+RETURN
    tmpm=tmpm->next;
  }
  tmpf->size=0;
  if (header_return) {
    if (GetOption(OPTf_WARN_HEADER_MISMATCH)) {
      if (tmpf->return_class!=header_return) {
        PrintWarn("Fun Header return mismatch '%s'\n",tmpf->str);
        cc->warning_cnt++;
      }
      if (!MemberLstCmp(tmpf->member_lst_and_root,header_lst,header_arg_cnt)) {
        PrintWarn("Fun header args mismatch '%s'\n",tmpf->str);
        cc->warning_cnt++;
      }
    }
    MemberLstDel(header_lst);
  }
  return tmpf;
}

U0 PrsFun(CCmpCtrl *cc,CHashClass *tmp_return,U8 *name,I64 fsp_flags)
{
  CMemberLst *tmpm;
  CCodeMisc *saved_leave_label;
  I64 i,j,size,*r;
  Bool old_trace;

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

  cc->flags&=~CCF_NO_REG_OPT;
  cc->htc.local_var_lst=cc->htc.fun=PrsFunJoin(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;
  PrsStmt(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->dbg_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->dbg_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_lst_and_root;
  while (tmpm) {
    if (tmpm->flags & MLF_NO_UNUSED_WARN) {
      if (tmpm->use_cnt>1&&StrCmp(tmpm->str,"_anon_"))
        PrintWarn("Unneeded no_warn\n $LK,\"FL:%s,%d\"$ '%s' in '%s'\n",
              cc->lex_include_stk->full_name,cc->lex_include_stk->line_num,
              tmpm->str,cc->htc.fun->str);
    } else if (!tmpm->use_cnt && GetOption(OPTf_WARN_UNUSED_VAR))
      PrintWarn("Unused var\n $LK,\"FL:%s,%d\"$ '%s' in '%s'\n",
            cc->lex_include_stk->full_name,cc->lex_include_stk->line_num,
            tmpm->str,cc->htc.fun->str);
    tmpm=tmpm->next;
  }
  cc->htc.local_var_lst=cc->htc.fun=cc->fun_lex_file=NULL;
}

U0 PrsGlblVarLst(CCmpCtrl *cc,I64 saved_mode,CHashClass *saved_tmpc,
  I64 saved_val,I64 fsp_flags)
{
  I64 i,j,mode,k,val;
  U8 *st;
  CHashExport *tmpex;
  CHashGlblVar *tmpg;
  CAOTCtrl *aotc=cc->aotc;
  CAOTHeapGlbl *tmphg;
  CHashClass *tmpc;
  CHashFun *tmpf,*tmpf_fun_ptr;
  CArrayDim tmpad;
  Bool has_alias,undef_array_size,is_array;
  while (TRUE) {
    tmpc=PrsType(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_cnt<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=PrsFunJoin(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=PrsFunJoin(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:
          PrsFunJoin(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=PrsFunJoin(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:
          PrsFun(cc,tmpc,st,fsp_flags);
          return;
      }
    } else {
      if (tmpad.total_cnt<0) {
        i=0;
        undef_array_size=TRUE;
      } else {
        i=tmpad.total_cnt;
        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(CHashGlblVar));
            tmpg->data_addr_rip=val;
            tmpg->type=HTT_GLBL_VAR | HTF_EXPORT;
          } else {
            tmpg=CAlloc(sizeof(CHashGlblVar),Fs->code_heap);
            tmpg->data_addr=val;
            tmpg->type=HTT_GLBL_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(CHashGlblVar));
            tmpg->type=HTT_GLBL_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(CHashGlblVar));
            tmpg->type=HTT_GLBL_VAR;
          } else {
            tmpg=CAlloc(sizeof(CHashGlblVar),Fs->code_heap);
            tmpg->type=HTT_GLBL_VAR|HTF_UNRESOLVED;
          }
          break;
        default:
          if (cc->flags&CCF_AOT_COMPILE) {
            if (Bt(&cc->opts,OPTf_GLBLS_ON_DATA_HEAP)) {
              if (cc->token=='=')
                LexExcept(cc,"Can't init glbl var on data heap in AOT module ");
              tmpg=CAlloc(sizeof(CHashGlblVar));
              tmphg=tmpg->heap_glbl=CAlloc(sizeof(CAOTHeapGlbl));
              tmphg->size=j;
              tmphg->str=StrNew(st);
              tmphg->next=aotc->heap_glbls;
              aotc->heap_glbls=tmphg;
              tmpg->flags=GVF_DATA_HEAP;
              tmpg->type=HTT_GLBL_VAR; //TODO: HTF_EXPORT
              if (tmpex && tmpex->type & HTT_GLBL_VAR) //TODO!! extern
                LexExcept(cc,"Feature not implemented ");
            } else {
              tmpg=CAlloc(sizeof(CHashGlblVar));
              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_GLBL_VAR | HTF_EXPORT;
              if (tmpex && tmpex->type & HTT_GLBL_VAR)
                has_alias=TRUE;
              for (k=0;k<j;k++)
                AOTStoreCodeU8(cc,0); //Init AOT glbl to zero.
            }
          } else {
            if (Bt(&cc->opts,OPTf_GLBLS_ON_DATA_HEAP)) {
              tmpg=CAlloc(sizeof(CHashGlblVar),Fs->code_heap);
              tmpg->data_addr=MAlloc(j);
              tmpg->flags=GVF_DATA_HEAP;
            } else {
              tmpg=CAlloc(sizeof(CHashGlblVar),Fs->code_heap);
              tmpg->data_addr=MAlloc(j,Fs->code_heap);
            }
            tmpg->type=HTT_GLBL_VAR;
            if (tmpex && tmpex->type&HTT_GLBL_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_cnt=i;
      tmpg->use_cnt=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.glbl_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);
          PrsGlblInit(cc,tmpg,1);
          LexPopNoRestore(cc);
          tmpg->size=tmpg->dim.total_cnt*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);
        PrsGlblInit(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(CHashGlblVar *)->use_cnt<2) {
          PrintWarn("Unused extern '%s'\n",tmpex(CHashGlblVar *)->str);
          cc->warning_cnt++;
        }
        tmpex(CHashGlblVar *)->flags|=GVF_ALIAS;
        tmpex(CHashGlblVar *)->data_addr=tmpg->data_addr;
        tmpex(CHashGlblVar *)->data_addr_rip=tmpg->data_addr_rip;
      }
      if (cc->token==',')
        Lex(cc);
      else {
        if (cc->token!=';')
          LexExcept(cc,"Missing ';' at");
        Lex(cc);
        return;
      }
    }
  }
}

U0 PrsIf(CCmpCtrl *cc,I64 try_cnt,CCodeMisc *lb_break)
{
  CCodeMisc *lb,*lb1;
  I64 k;
  if (cc->token!='(')
    LexExcept(cc,"Expecting '(' at ");
  Lex(cc);
  if (!PrsExpression(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);
  PrsStmt(cc,try_cnt,lb_break);
  k=PrsKeyWord(cc);
  if (k==KW_ELSE) {
    Lex(cc);
    lb1=COCMiscNew(cc,CMT_LABEL);
    ICAdd(cc,IC_JMP,lb1,0);
    ICAdd(cc,IC_LABEL,lb,0);
    PrsStmt(cc,try_cnt,lb_break);
    ICAdd(cc,IC_LABEL,lb1,0);
  } else
    ICAdd(cc,IC_LABEL,lb,0);
}

U0 PrsWhile(CCmpCtrl *cc,I64 try_cnt)
{
  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 (!PrsExpression(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);
  PrsStmt(cc,try_cnt,lb_done);
  ICAdd(cc,IC_JMP,lb,0);
  ICAdd(cc,IC_LABEL,lb_done,0);
}

U0 PrsDoWhile(CCmpCtrl *cc,I64 try_cnt)
{
  CCodeMisc *lb,*lb_done;
  lb=COCMiscNew(cc,CMT_LABEL);
  lb_done=COCMiscNew(cc,CMT_LABEL);
  ICAdd(cc,IC_LABEL,lb,0);
  PrsStmt(cc,try_cnt,lb_done);
  if (PrsKeyWord(cc)!=KW_WHILE)
    LexExcept(cc,"Missing 'while' at");
  if (Lex(cc)!='(')
    LexExcept(cc,"Expecting '(' at ");
  Lex(cc);
  if (!PrsExpression(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 PrsFor(CCmpCtrl *cc,I64 try_cnt)
{
  CCodeCtrl *tmpcbh;
  CCodeMisc *lb,*lb_done;

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

  lb=COCMiscNew(cc,CMT_LABEL);
  ICAdd(cc,IC_LABEL,lb,0);
  if (!PrsExpression(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!=')')
    PrsStmt(cc,try_cnt,NULL,0);
  COCPush(cc);
  tmpcbh=COCPopNoFree(cc);
  COCPop(cc);
  if (cc->token!=')')
    LexExcept(cc,"Missing ')' at ");
  Lex(cc);

  PrsStmt(cc,try_cnt,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 PrsSwitch(CCmpCtrl *cc,I64 try_cnt)
{
  CSwitchCase *header=NULL,*tmps,*tmps1;        //Leaks on except
  CSubSwitch head,*tmpss;                       //Leaks on except
  CCodeMisc *lb_dft,*lb_fwd_case,*mc_jt,*lb_entry,**jmp_table;
  CIntermediateCode *tmpi_sub,*tmpi_cmp,*tmpi_jmp,*tmpi_start;
  Bool dft_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);
  QueInit(&head);

  head.last->lb_break=COCMiscNew(cc,CMT_LABEL);
  head.last->lb_break->use_cnt++;
  lb_dft=COCMiscNew(cc,CMT_LABEL);
  lb_dft->use_cnt++;
  mc_jt=COCMiscNew(cc,CMT_JMP_TABLE);
  mc_jt->begin=COCMiscNew(cc,CMT_LABEL);
  mc_jt->begin->use_cnt++;
  if (!PrsExpression(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 (PrsKeyWord(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));
          QueIns(tmpss,head.last);
          head.last->lb_break=COCMiscNew(cc,CMT_LABEL);
          head.last->lb_break->use_cnt++;
          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 (PrsKeyWord(cc)) {
              case KW_END:
                OptFree(tmpi_jmp);
                goto sw_sub_end;
              case KW_START:
              case KW_CASE:
              case KW_DFT:
                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:
                PrsStmt(cc,try_cnt);
            }
          }
          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_cnt++;
          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_DFT:
          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_dft,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);
          }
          dft_found=TRUE;
          break;
        default:
          PrsStmt(cc,try_cnt,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 {
      QueRem(tmpss);
      Free(tmpss);
      if (PrsKeyWord(cc)!=KW_END)
        LexExcept(cc,"Missing 'end' at ");
      if (Lex(cc)==':')
        Lex(cc);
      else
        LexExcept(cc,"Expecting ':' at ");
    }
  }
  if (!dft_found)
    ICAdd(cc,IC_LABEL,lb_dft,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_dft,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_dft)
      LexExcept(cc,"Duplicate case at ");
    else
      jmp_table[tmps->val-lo]=tmps->label;
    Free(tmps);
    tmps=tmps1;
  }
  mc_jt->dft=lb_dft;
  mc_jt->jmp_table=jmp_table;
  mc_jt->range=range;
}

U0 PrsNoWarn(CCmpCtrl *cc)
{
  CMemberLst *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 PrsStreamBlk(CCmpCtrl *cc)
{
  CLexHashTableContext *htc=MAlloc(sizeof(CLexHashTableContext));
  CStreamBlk *tmpe=MAlloc(sizeof(CStreamBlk));
  tmpe->body=StrNew("");
  QueIns(tmpe,cc->last_stream_blk);
  COCPush(cc);
  QueInit(&cc->coc.coc_next_misc);

  MemCpy(htc,&cc->htc,sizeof(CLexHashTableContext));
  htc->old_flags=cc->flags;
  cc->htc.next=htc;
  cc->htc.fun=cc->htc.local_var_lst=NULL;
  cc->htc.define_hash_table=cc->htc.hash_table_lst=
        cc->htc.glbl_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);

  MemCpy(&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);
  QueRem(tmpe);
  if (*tmpe->body)
    LexIncludeStr(cc,"StreamBlk",tmpe->body,FALSE);
  else
    Free(tmpe->body);
  Free(tmpe);
  Lex(cc); //Skip '}'
}

U0 PrsTryBlk(CCmpCtrl *cc,I64 try_cnt)
{
  CCodeMisc     *lb_catch,*lb_done,*lb_untry;
  CHashClass    *tmpc=cmp.internal_types[RT_PTR];
  CHashFun      *tmp_try=HashFind("SysTry",cc->htc.hash_table_lst,HTT_FUN),
        *tmp_untry=HashFind("SysUntry",cc->htc.hash_table_lst,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_cnts.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);

  PrsStmt(cc,try_cnt+1);

  ICAdd(cc,IC_LABEL,lb_untry,0);
  ICAdd(cc,IC_CALL_START,0,0);
  if (Bt(&tmp_untry->flags,Cf_EXTERN)) {
    cc->abs_cnts.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 (PrsKeyWord(cc)!=KW_CATCH)
    LexExcept(cc,"Missing 'catch' at");

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

Bool PrsStmt(CCmpCtrl *cc,I64 try_cnt=0,
  CCodeMisc *lb_break=NULL,I64 cmp_flags=CMPF_PRS_SEMICOLON)
{
  I64 i,fsp_flags=0;
  CHashExport *tmpex;
  CCodeMisc *g_lb;
  U8 *import_name;
  CHashFun *tmp_untry;
  CAOT *tmpaot;
  if (cmp_flags&CMPF_ONE_ASM_INS) {
    if (cc->flags&CCF_AOT_COMPILE || cc->aot_depth)
      PrsAsmBlk(cc,CMPF_ONE_ASM_INS);
    else if (tmpaot=CmpJoin(cc,CMPF_ASM_BLK|CMPF_ONE_ASM_INS))
      CmpFixUpJITAsm(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)
          PrsStmt(cc,try_cnt,lb_break);
        if (cc->lex_include_stk==cc->fun_lex_file)
          cc->max_line=cc->lex_include_stk->line_num;
        if (Lex(cc)!=',') goto sm_done;
      } else if (cc->token==';') {
        if (cmp_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=CmpJoin(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);
                        PrsAsmBlk(cc,0);
                        if (cc->flags&CCF_AOT_COMPILE && cc->aot_depth==1)
                          Lex(cc); //Skip '}' of asm{}
                      } else {
                        if (tmpaot=CmpJoin(cc,CMPF_ASM_BLK))
                          CmpFixUpJITAsm(cc,tmpaot);
                        Lex(cc); //Skip '}' of asm{}
                      }
                      fsp_flags=FSF_ASM;
                    }
                    break;
                  start:
                    Lex(cc);
                    case KW_LOCK:
                      cc->lock_cnt++;
                      PrsStmt(cc,try_cnt);
                      cc->lock_cnt--;
                      break;
                    case KW_TRY:
                      PrsTryBlk(cc,try_cnt);
                      break;
                    case KW_IF:
                      PrsIf(cc,try_cnt,lb_break);
                      break;
                    case KW_FOR:
                      PrsFor(cc,try_cnt);
                      break;
                    case KW_WHILE:
                      PrsWhile(cc,try_cnt);
                      break;
                    case KW_DO:
                      PrsDoWhile(cc,try_cnt);
                      break;
                    case KW_SWITCH:
                      PrsSwitch(cc,try_cnt);
                      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);
                    PrsGlblVarLst(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);
                    PrsGlblVarLst(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=PrsKeyWord(cc);
                    if (i==KW_CLASS||i==KW_UNION) {
                      Lex(cc);
                      PrsClass(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);
                    PrsGlblVarLst(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);
                    PrsGlblVarLst(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);
                    PrsGlblVarLst(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_cnt) {
                    tmp_untry=HashFind("SysUntry",
                          cc->htc.hash_table_lst,HTT_FUN);
                    for (i=0;i<try_cnt;i++) {
                      if (Bt(&tmp_untry->flags,Cf_EXTERN)) {
                        cc->abs_cnts.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 (!PrsExpression(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_cnt++;
                  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);
                  PrsNoWarn(cc);
                  goto sm_semicolon;
                case KW_UNION:
                case KW_CLASS:
                  Lex(cc);
                  tmpex=PrsClass(cc,i,fsp_flags,FALSE);
                  if (!cc->htc.fun && cc->token!=';') {
                    PrsGlblVarLst(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)
                    PrsVarLst(cc,cc->htc.fun,PRS0_NULL|PRS1_STATIC_LOCAL_VAR);
                  else
                    PrsVarLst(cc,cc->htc.fun,PRS0_NULL|PRS1_LOCAL_VAR);
                  if (cc->token=='}') goto sm_done;
                } else {
                  Lex(cc);
                  PrsGlblVarLst(cc,PRS0_NULL|PRS1_NULL,tmpex,0,fsp_flags);
                }
              } else {
                if (tmpex->type & (HTT_OPCODE|HTT_ASM_KEYWORD)) {
                  if (cc->htc.fun) {
                    if (tmpaot=CmpJoin(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_prs_exp;
              }
              fsp_flags&=FSF_ASM;
            }
          } else {//Ident, not in hash table
            if (cc->local_var_entry)
              goto sm_prs_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) {
          PrsFunCall(cc,NULL,FALSE,NULL);
          goto sm_semicolon;
        } else if (cc->token!=TK_EOF) {//Non-cur_str symbol, num or something
sm_prs_exp:
          if (!PrsExpression(cc,NULL,TRUE))
            throw('Compiler');
sm_semicolon:
          if (cmp_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;
}