U0 LexBackupLastChar(CCompCtrl *cc) { CLexFile *tmpf=cc->lex_include_stack; tmpf->buf_ptr=cc->cur_buf_ptr; if (cc->flags & CCF_USE_LAST_U16) { tmpf->last_U16=cc->last_U16; cc->flags&=~CCF_USE_LAST_U16; } else tmpf->last_U16=0; } U0 LexPush(CCompCtrl *cc) {//Create token-stream save point. CLexFile *tmpf; LexBackupLastChar(cc); if (cc->lex_include_stack->last_U16) cc->flags|=CCF_USE_LAST_U16; tmpf=MAllocIdent(cc->lex_include_stack); tmpf->next=cc->lex_parse_stack; cc->lex_parse_stack=tmpf; } U0 LexPopRestore(CCompCtrl *cc) {//Restore token-stream saved-point. //Bad things can happen if you cross an #include file boundary. CLexFile *tmpf=cc->lex_parse_stack; cc->cur_buf_ptr=tmpf->buf_ptr; if (cc->last_U16=tmpf->last_U16) cc->flags|=CCF_USE_LAST_U16; else cc->flags&=~CCF_USE_LAST_U16; MemCopy(cc->lex_include_stack(U8 *)+sizeof(U8 *),tmpf(U8 *)+sizeof(U8 *), sizeof(CLexFile)-sizeof(U8 *)); cc->lex_parse_stack=tmpf->next; Free(tmpf); } U0 LexPopNoRestore(CCompCtrl *cc) {//Don't restore token-stream saved-point. CLexFile *tmpf=cc->lex_parse_stack; cc->lex_parse_stack=tmpf->next; Free(tmpf); } I64 MemberMetaData(U8 *needle_str,CMemberList *haystack_member_list) {//Find meta data name, return meta data val. See $LK,"::/Demo/ClassMeta.CC"$. CMemberListMeta *meta=haystack_member_list->meta; while (meta) { if (!StrCompare(meta->str,needle_str)) return meta->user_data; meta=meta->next; } return 0; } CMemberListMeta *MemberMetaFind(U8 *needle_str,CMemberList *haystack_member_list) {//Find meta data name, return meta data struct. See $LK,"::/Demo/ClassMeta.CC"$. CMemberListMeta *meta=haystack_member_list->meta; while (meta) { if (!StrCompare(meta->str,needle_str)) return meta; meta=meta->next; } return NULL; } CMemberList *MemberFind(U8 *needle_str,CHashClass *haystack_class) {//Find class member. See $LK,"ClassRep",A="MN:ClassRep"$() and $LK,"DocForm",A="MN:DocForm"$(). I64 i; CMemberList *tmpm; do { tmpm=haystack_class->member_list_and_root; while (tmpm) { if (!(i=StrCompare(tmpm->str,needle_str))) { tmpm->use_count++; return tmpm; } if (i<=0) tmpm=tmpm->left; else tmpm=tmpm->right; } } while (haystack_class=haystack_class->base_class); return NULL; } CMemberList *MemberClassBaseFind(CHashClass *needle_class, CHashClass *haystack_class) {//Find class member class base. For finding dup class local vars. CMemberList *tmpm; tmpm=haystack_class->member_class_base_root; while (tmpm) { if (needle_class==tmpm->member_class_base) return tmpm; if (needle_classmember_class_base) tmpm=tmpm->left_class_base; else tmpm=tmpm->right_class_base; } return NULL; } U0 MemberAdd(CCompCtrl *cc,CMemberList *tmpm,CHashClass *tmpc,I64 mode) { U8 *st=tmpm->str; CMemberList **tmpm1,*tmpm2; if (MemberFind(st,tmpc) && StrCompare(st,"pad") && StrCompare(st,"reserved") && StrCompare(st,"_anon_")) LexExcept(cc,"Duplicate member at "); tmpm1=&tmpc->member_list_and_root; while (tmpm2=*tmpm1) { if (StrCompare(tmpm2->str,st)<=0) tmpm1=&tmpm2->left; else tmpm1=&tmpm2->right; } *tmpm1=tmpm; if (mode==PRS1B_LOCAL_VAR) { tmpm->member_class_base= tmpm->member_class-tmpm->member_class->ptr_stars_count; if (Bt(&cc->opts,OPTf_WARN_DUP_TYPES) && MemberClassBaseFind(tmpm->member_class_base,tmpc)) LexWarn(cc,"Duplicate type at "); tmpm1=&tmpc->member_class_base_root; while (tmpm2=*tmpm1) { if (tmpm->member_class_basemember_class_base) tmpm1=&tmpm2->left_class_base; else if (tmpm->member_class_base>tmpm2->member_class_base) tmpm1=&tmpm2->right_class_base; else { tmpm1=NULL; break; } } if (tmpm1) *tmpm1=tmpm; } else tmpm->member_class_base=NULL; tmpm->left=NULL; tmpm->right=NULL; tmpm->left_class_base=NULL; tmpm->right_class_base=NULL; tmpm2=tmpc->last_in_member_list; tmpm2->next=tmpc->last_in_member_list=tmpm; } CMemberList *MemberListNew(I64 _reg) { CMemberList *res=CAlloc(sizeof(CMemberList)); res->reg=_reg; return res; } Bool MemberListCmp(CMemberList *tmpm1,CMemberList *tmpm2,I64 count=I64_MAX) { while (tmpm1 && tmpm2 && count--) { if (StrCompare(tmpm1->str,tmpm2->str) || tmpm1->member_class!=tmpm2->member_class || tmpm1->member_class_base!=tmpm2->member_class_base) return FALSE; if (tmpm1->flags&MLF_DEFAULT_AVAILABLE || tmpm2->flags&MLF_DEFAULT_AVAILABLE) { if (tmpm1->flags&(MLF_DEFAULT_AVAILABLE|MLF_STR_DEFAULT_AVAILABLE)!= tmpm2->flags&(MLF_DEFAULT_AVAILABLE|MLF_STR_DEFAULT_AVAILABLE)) return FALSE; if (tmpm1->flags&MLF_STR_DEFAULT_AVAILABLE) { if (StrCompare(tmpm1->default_val,tmpm2->default_val)) return FALSE; } else if (tmpm1->default_val!=tmpm2->default_val) return FALSE; } tmpm1=tmpm1->next; tmpm2=tmpm2->next; } if (count<0 || !tmpm1 && !tmpm2) return TRUE; else return FALSE; } U0 MemberListDel(CMemberList *tmpm) { CMemberList *tmpm1; CMemberListMeta *tmp_meta,*tmp_meta1; while (tmpm) { tmpm1=tmpm->next; Free(tmpm->str); LinkedListDel(tmpm->dim.next); if (tmpm->flags & MLF_STR_DEFAULT_AVAILABLE) Free(tmpm->default_val); if (tmpm->flags & MLF_FUN) HashDel(tmpm->fun_ptr-tmpm->fun_ptr->ptr_stars_count); tmp_meta=tmpm->meta; while (tmp_meta) { tmp_meta1=tmp_meta->next; Free(tmp_meta->str); if (tmp_meta->flags&MLMF_IS_STR) Free(tmp_meta->user_data); Free(tmp_meta); tmp_meta=tmp_meta1; } Free(tmpm); tmpm=tmpm1; } } U0 ClassMemberListDel(CHashClass *tmpc) { MemberListDel(tmpc->member_list_and_root); tmpc->size=0; tmpc->last_in_member_list=&tmpc->member_list_and_root; tmpc->member_list_and_root=NULL; tmpc->member_class_base_root=NULL; tmpc->member_count=0; if (tmpc->type&HTT_FUN) tmpc(CHashFun *)->arg_count=0; } I64 MemberListSize(CHashClass *tmpc) { CMemberList *tmpm; CMemberListMeta *tmp_meta; I64 res=0; tmpm=tmpc->member_list_and_root; while (tmpm) { res+=MSize2(tmpm->str); res+=LinkedListSize(tmpm->dim.next); if (tmpm->flags & MLF_STR_DEFAULT_AVAILABLE) res+=MSize2(tmpm->default_val); if (tmpm->flags & MLF_FUN) res+=HashEntrySize2(tmpm->fun_ptr-tmpm->fun_ptr->ptr_stars_count); tmp_meta=tmpm->meta; while (tmp_meta) { res+=MSize2(tmp_meta->str); if (tmp_meta->flags&MLMF_IS_STR) res+=MSize2(tmp_meta->user_data); res+=MSize2(tmp_meta); tmp_meta=tmp_meta->next; } res+=MSize2(tmpm); tmpm=tmpm->next; } return res; } U8 *LexExtStr(CCompCtrl *cc,I64 *_size=NULL,Bool lex_next=TRUE) {//Lex $LK,"TK_STR",A="MN:TK_STR"$'s to one combined str. _size includes terminator. I64 len=cc->cur_str_len,len1,len2; U8 *st=cc->cur_str,*st1,*st2; cc->cur_str=NULL; while (cc->token==TK_STR) { st1=st; len1=len; if (!lex_next && LexGetChar(cc)!='\\') { cc->flags|=CCF_USE_LAST_U16; break; } if (Lex(cc)==TK_STR) { len2=cc->cur_str_len; st2=cc->cur_str; cc->cur_str=NULL; len=len1+len2-1; st=MAlloc(len); if (len1>1) MemCopy(st,st1,len1-1); MemCopy(st+len1-1,st2,len2); Free(st1); Free(st2); } } if (_size) *_size=len; return st; }