I64 HashTypeNum(CHash *tmph) {//Return bit num of hash type, limited to just types. if (tmph) return Bsf(tmph->type & HTG_TYPE_MASK); return -1; } I64 HashVal(CHash *tmph) {//Returns most likely desired value. switch [HashTypeNum(tmph)] { case HTt_EXPORT_SYS_SYM: return tmph(CHashExport *)->val; case HTt_IMPORT_SYS_SYM: return tmph(CHashImport *)->module_base; case HTt_DEFINE_STR: case HTt_CLASS: case HTt_INTERNAL_TYPE: case HTt_WORD: case HTt_DICT_WORD: case HTt_OPCODE: case HTt_HELP_FILE: return tmph; case HTt_GLOBAL_VAR: if (tmph(CHashGlobalVar *)->flags & GVF_EXTERN) return &tmph(CHashGlobalVar *)->data_addr; else return tmph(CHashGlobalVar *)->data_addr; case HTt_FUN: if (Bt(&tmph(CHashFun *)->flags, Cf_EXTERN)) return tmph; else return tmph(CHashFun *)->exe_addr; case HTt_REG: return tmph(CHashReg *)->reg_num | tmph(CHashReg *)->reg_type << 8; case HTt_KEYWORD: case HTt_ASM_KEYWORD: case HTt_MODULE: case HTt_FILE: case HTt_FRAME_PTR: return tmph(CHashGeneric *)->user_data0; case -1: //nobound switch case HTt_TYPES_NUM: //nobound switch default: return 0; } } CHashTable *HashTableNew(I64 size, CTask *mem_task=NULL) {//New hash table, power-of-two in size. CHashTable *table; table = CAlloc(sizeof(CHashTable), mem_task); table->body = CAlloc(size << 3, mem_task); table->mask = size - 1; return table; } U0 HashDel(CHashSrcSym *tmph) {//Free a std ZealOS system hash entry. if (!tmph) return; if (!(tmph->type & HTT_DICT_WORD)) Free(tmph->str); if (tmph->type & HTG_SRC_SYM) { Free(tmph->src_link); Free(tmph->idx); Free(tmph->import_name); LinkedListDel(tmph->ie_list); if (tmph->type & (HTT_FUN | HTT_EXPORT_SYS_SYM)) Free(tmph->debug_info); if (tmph->type & (HTT_FUN | HTT_CLASS)) //Assumes code not on heap, so doesn't Free. //ClassMemberListDel() is an import to the Kernel module ClassMemberListDel(tmph); else if (tmph->type & HTT_DEFINE_STR) Free(tmph(CHashDefineStr *)->data); else if (tmph->type & HTT_GLOBAL_VAR) { if (!(tmph(CHashGlobalVar *)->flags & GVF_ALIAS)) Free(tmph(CHashGlobalVar *)->data_addr); LinkedListDel(tmph(CHashGlobalVar *)->dim.next); if (tmph(CHashGlobalVar *)->fun_ptr) HashDel(tmph(CHashGlobalVar *)->fun_ptr - tmph(CHashGlobalVar *)->fun_ptr->ptr_stars_count); } } else if (tmph->type & HTT_FILE) Free(tmph(CHashGeneric *)->user_data0); Free(tmph); } U0 HashTableDel(CHashTable *table) {//Free std system hash table, calling HashDel() on entries. I64 i; CHashSrcSym *tmph, *tmph1; if (!table) return; for (i = 0; i <= table->mask; i++) { tmph = table->body[i]; while (tmph) { tmph1 = tmph->next; HashDel(tmph); tmph = tmph1; } } Free(table->body); Free(table); } I64 HashTablePurge(CHashTable *table) {//Eliminate ExportSysSyms that have been usurped. I64 i, res = 0; CHashSrcSym *tmph, *tmph1, *tmph2; if (!table) return 0; PUSHFD CLI //Precaution for (i = 0; i <= table->mask; i++) { tmph = table->body[i]; while (tmph) { tmph1 = tmph->next; //We delete only older ones if (tmph->type & (HTT_FUN | HTT_GLOBAL_VAR)) { tmph2 = tmph->next; //Older always later in chain while (tmph2) { if ((tmph2->type & HTT_EXPORT_SYS_SYM || tmph2->type & HTG_TYPE_MASK == HTT_INVALID) && !StrCompare(tmph2->str, tmph->str)) { if (tmph2->type & HTG_TYPE_MASK == HTT_INVALID) tmph2->type = HTT_KEYWORD;//Won't delete HTT_INVALID HashRemDel(tmph2, table); res++; break; } tmph2 = tmph2->next; } } tmph = tmph1; } } POPFD return res; } CHashGeneric *HashGenericAdd(U8 *name, I64 type, I64 u0=0, I64 u1=0, I64 u2=0, CTask *task=NULL) {//Add any type to task hash_table, 3 user_data values. if (!task) task = Fs; CHashGeneric *res = CAlloc(sizeof(CHashGeneric), task); res->type = type; res->user_data0 = u0; res->user_data1 = u1; res->user_data2 = u2; res->str = StrNew(name, task); HashAdd(res, task->hash_table); return res; } U0 HashSrcFileSet(CCompCtrl *cc, CHashSrcSym *h, I64 line_num_offset=0) {//Set CHashSrcSym link and help_index by cur cc pos. CLexFile *tmpf = cc->lex_include_stack; I64 line_num = tmpf->line_num + line_num_offset; if (line_num < 1) line_num = 1; Free(h->src_link); h->src_link = MStrPrint("FL:%s,%d", tmpf->full_name, line_num); if (Bt(&cc->opts, OPTf_KEEP_PRIVATE)) h->type |= HTF_PRIVATE; Free(h->idx); if (cc->cur_help_idx && *cc->cur_help_idx) h->idx = StrNew(cc->cur_help_idx); else h->idx = NULL; } CHashGeneric *HashPublic(U8 *st, I64 mask, Bool val=TRUE) {//Mark a hash entry as public and HashSrcFileSet(). CHashGeneric *res; if (res = HashFind(st, Fs->hash_table, mask)) { if (val) res->type |= HTF_PUBLIC; else res->type &= ~HTF_PUBLIC; if (res->type & HTG_SRC_SYM) HashSrcFileSet(Fs->last_cc, res); return res; } else return NULL; } I64 HashListAdd(U8 *list, I64 type, CHashTable *table) {//Add a list to a hash table. I64 i = 0; CHashGeneric *tmph; if (list) { while (*list) { if (*list == '@') list++; else i++; tmph = CAlloc(sizeof(CHashGeneric)); tmph->user_data0 = i - 1; tmph->str = StrNew(list); tmph->type = type; HashAdd(tmph, table); while (*list++); } } return i; } I64 HashDefineListAdd(U8 *dname, I64 type, CHashTable *table) {//Add define list to a hash table. See ::/System/DolDoc/DocInit.CC. CHashDefineStr *tmph; if (tmph = HashFind(dname, Fs->hash_table, HTT_DEFINE_STR)) return HashListAdd(tmph->data, type, table); else return 0; } I64 FramePtr(U8 *name, CTask *task=NULL) {//Find entry in task->hash_table, Return user_data. CHashGeneric *tmph; if (!task) task = Fs; if (tmph = HashFind(name, task->hash_table, HTT_FRAME_PTR)) return tmph->user_data0; else return 0; } CHashGeneric *FramePtrAdd(U8 *name, I64 val=0, CTask *task=NULL) {//Add named value to task->hash_table. return HashGenericAdd(name, HTT_FRAME_PTR, val, 0, 0, task); } I64 FramePtrSet(U8 *name, I64 val, CTask *task=NULL) {//Find hash entry in task->hash_table. Change user_data0. CHashGeneric *tmph; if (!task) task = Fs; if (tmph = HashFind(name, task->hash_table, HTT_FRAME_PTR)) return LXchgI64(&tmph->user_data0, val); else return 0; } I64 FramePtrDel(U8 *name, CTask *task=NULL) {//Remove entry and delete. CHashGeneric *tmph; I64 res = 0; if (!task) task = Fs; if (tmph = HashFind(name, task->hash_table, HTT_FRAME_PTR)) { res = tmph->user_data0; HashRemDel(tmph, task->hash_table); } return res; }