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 value. See ::/Demo/ClassMeta.CC. CMemberListMeta *meta = haystack_member_list->meta; while (meta) { if (!StrCompare(meta->str, needle_str)) return meta->user_data; meta = meta->next; } return 0; } CMemberListMeta *MemberMetaFind(U8 *needle_str, CMemberList *haystack_member_list) {//Find meta data name, return meta data struct. See ::/Demo/ClassMeta.CC. CMemberListMeta *meta = haystack_member_list->meta; while (meta) { if (!StrCompare(meta->str, needle_str)) return meta; meta = meta->next; } return NULL; } CMemberList *MemberFind(U8 *needle_str, CHashClass *haystack_class) {//Find class member. See ClassRep() and DocForm(). I64 i; CMemberList *tmpm; do { tmpm = haystack_class->member_list_and_root; while (tmpm) { if (!(i = StrCompare(tmpm->str, needle_str))) { tmpm->use_count++; return tmpm; } if (i <= 0) tmpm = tmpm->left; else tmpm = tmpm->right; } } while (haystack_class = haystack_class->base_class); return NULL; } CMemberList *MemberClassBaseFind(CHashClass *needle_class, CHashClass *haystack_class) {//Find class member class base. For finding duplicate class local variables. CMemberList *tmpm; tmpm = haystack_class->member_class_base_root; while (tmpm) { if (needle_class == tmpm->member_class_base) return tmpm; if (needle_class < tmpm->member_class_base) tmpm = tmpm->left_class_base; else tmpm = tmpm->right_class_base; } return NULL; } U0 MemberAdd(CCompCtrl *cc, CMemberList *tmpm, CHashClass *tmpc, I64 mode) { U8 *st = tmpm->str; CMemberList **tmpm1, *tmpm2; if (MemberFind(st, tmpc) && StrCompare(st, "pad") && StrCompare(st, "reserved") && StrCompare(st, "_anon_")) LexExcept(cc, "Duplicate member at "); tmpm1 = &tmpc->member_list_and_root; while (tmpm2 = *tmpm1) { if (StrCompare(tmpm2->str, st) <= 0) tmpm1 = &tmpm2->left; else tmpm1 = &tmpm2->right; } *tmpm1 = tmpm; if (mode == PRS1B_LOCAL_VAR) { tmpm->member_class_base = tmpm->member_class - tmpm->member_class->ptr_stars_count; if (Bt(&cc->opts, OPTf_WARN_DUP_TYPES) && MemberClassBaseFind(tmpm->member_class_base, tmpc)) LexWarn(cc, "Duplicate type at "); tmpm1 = &tmpc->member_class_base_root; while (tmpm2 = *tmpm1) { if (tmpm->member_class_base < tmpm2->member_class_base) tmpm1 = &tmpm2->left_class_base; else if (tmpm->member_class_base > tmpm2->member_class_base) tmpm1 = &tmpm2->right_class_base; else { tmpm1 = NULL; break; } } if (tmpm1) *tmpm1 = tmpm; } else tmpm->member_class_base = NULL; tmpm->left = NULL; tmpm->right = NULL; tmpm->left_class_base = NULL; tmpm->right_class_base = NULL; tmpm2 = tmpc->last_in_member_list; tmpm2->next = tmpc->last_in_member_list = tmpm; } CMemberList *MemberListNew(I64 _reg) { CMemberList *res = CAlloc(sizeof(CMemberList)); res->reg = _reg; return res; } Bool MemberListCmp(CMemberList *tmpm1, CMemberList *tmpm2, I64 count=I64_MAX) { while (tmpm1 && tmpm2 && count--) { if (StrCompare(tmpm1->str,tmpm2->str) || tmpm1->member_class != tmpm2->member_class || tmpm1->member_class_base != tmpm2->member_class_base) return FALSE; if (tmpm1->flags & MLF_DEFAULT_AVAILABLE || tmpm2->flags & MLF_DEFAULT_AVAILABLE) { if (tmpm1->flags & (MLF_DEFAULT_AVAILABLE | MLF_STR_DEFAULT_AVAILABLE) != tmpm2->flags & (MLF_DEFAULT_AVAILABLE | MLF_STR_DEFAULT_AVAILABLE)) return FALSE; if (tmpm1->flags & MLF_STR_DEFAULT_AVAILABLE) { if (StrCompare(tmpm1->default_val, tmpm2->default_val)) return FALSE; } else if (tmpm1->default_val != tmpm2->default_val) return FALSE; } tmpm1 = tmpm1->next; tmpm2 = tmpm2->next; } if (count < 0 || !tmpm1 && !tmpm2) return TRUE; else return FALSE; } U0 MemberListDel(CMemberList *tmpm) { CMemberList *tmpm1; CMemberListMeta *tmp_meta, *tmp_meta1; while (tmpm) { tmpm1 = tmpm->next; Free(tmpm->str); LinkedListDel(tmpm->dim.next); if (tmpm->flags & MLF_STR_DEFAULT_AVAILABLE) Free(tmpm->default_val); if (tmpm->flags & MLF_FUN) HashDel(tmpm->fun_ptr - tmpm->fun_ptr->ptr_stars_count); tmp_meta = tmpm->meta; while (tmp_meta) { tmp_meta1 = tmp_meta->next; Free(tmp_meta->str); if (tmp_meta->flags & MLMF_IS_STR) Free(tmp_meta->user_data); Free(tmp_meta); tmp_meta = tmp_meta1; } Free(tmpm); tmpm = tmpm1; } } U0 ClassMemberListDel(CHashClass *tmpc) { MemberListDel(tmpc->member_list_and_root); tmpc->size = 0; tmpc->last_in_member_list = &tmpc->member_list_and_root; tmpc->member_list_and_root = NULL; tmpc->member_class_base_root = NULL; tmpc->member_count = 0; if (tmpc->type & HTT_FUN) tmpc(CHashFun *)->arg_count = 0; } I64 MemberListSize(CHashClass *tmpc) { CMemberList *tmpm; CMemberListMeta *tmp_meta; I64 res = 0; tmpm = tmpc->member_list_and_root; while (tmpm) { res += MSize2(tmpm->str); res += LinkedListSize(tmpm->dim.next); if (tmpm->flags & MLF_STR_DEFAULT_AVAILABLE) res += MSize2(tmpm->default_val); if (tmpm->flags & MLF_FUN) res += HashEntrySize2(tmpm->fun_ptr - tmpm->fun_ptr->ptr_stars_count); tmp_meta = tmpm->meta; while (tmp_meta) { res += MSize2(tmp_meta->str); if (tmp_meta->flags & MLMF_IS_STR) res += MSize2(tmp_meta->user_data); res += MSize2(tmp_meta); tmp_meta = tmp_meta->next; } res += MSize2(tmpm); tmpm = tmpm->next; } return res; } U8 *LexExtStr(CCompCtrl *cc, I64 *_size=NULL, Bool lex_next=TRUE) {//Lex TK_STR's to one combined str. _size includes terminator. I64 len = cc->cur_str_len, len1, len2; U8 *st = cc->cur_str, *st1, *st2; cc->cur_str = NULL; while (cc->token == TK_STR) { st1 = st; len1 = len; if (!lex_next && LexCharGet(cc) != '\\') { cc->flags |= CCF_USE_LAST_U16; break; } if (Lex(cc) == TK_STR) { len2 = cc->cur_str_len; st2 = cc->cur_str; cc->cur_str = NULL; len = len1 + len2 - 1; st = MAlloc(len); if (len1 > 1) MemCopy(st, st1, len1 - 1); MemCopy(st + len1 - 1, st2, len2); Free(st1); Free(st2); } } if (_size) *_size = len; return st; }