void AddXkey(const CStr *Xkey, XmapVal *val, int ntype) { CStr cs; cs.buf = Xkey->buf; cs.len = Xkey->len; if (Xkey->len == 0) { xprintf("%s", CGETS(9, 1, "AddXkey: Null extended-key not allowed.\n")); return; } if (ntype == XK_CMD && val->cmd == F_XKEY) { xprintf("%s", CGETS(9, 2, "AddXkey: sequence-lead-in command not allowed\n")); return; } if (Xmap == NULL) /* tree is initially empty. Set up new node to match Xkey[0] */ Xmap = GetFreeNode(&cs); /* it is properly initialized */ /* Now recurse through Xmap */ (void) TryNode(Xmap, &cs, val, ntype); return; }
/* Performs a Boundary Package-Merge step. Puts a new chain in the given list. The new chain is, depending on the weights, a leaf or a combination of two chains from the previous list. lists: The lists of chains. maxbits: Number of lists. leaves: The leaves, one per symbol. numsymbols: Number of leaves. pool: the node memory pool. index: The index of the list in which a new chain or leaf is required. */ static void BoundaryPM(Node* (*lists)[2], int maxbits, Node* leaves, int numsymbols, NodePool* pool, int index) { int lastcount = lists[index][1]->count; /* Count of last chain of list. */ if (unlikely(!index && lastcount >= numsymbols)) return; Node* newchain = GetFreeNode(lists, maxbits, pool); Node* oldchain = lists[index][1]; /* These are set up before the recursive calls below, so that there is a list pointing to the new node, to let the garbage collection know it's in use. */ lists[index][0] = oldchain; lists[index][1] = newchain; if (unlikely(!index)) { /* New leaf node in list 0. */ InitNode(leaves[lastcount].weight, lastcount + 1, 0, newchain); } else { size_t sum = lists[index - 1][0]->weight + lists[index - 1][1]->weight; if (lastcount < numsymbols && sum > leaves[lastcount].weight) { /* New leaf inserted in list, so count is incremented. */ InitNode(leaves[lastcount].weight, lastcount + 1, oldchain->tail, newchain); } else { InitNode(sum, lastcount, lists[index - 1][1], newchain); /* Two lookahead chains of previous list used up, create new ones. */ BoundaryPM(lists, maxbits, leaves, numsymbols, pool, index - 1); BoundaryPM(lists, maxbits, leaves, numsymbols, pool, index - 1); } } }
static void BoundaryPMfinal(Node* (*lists)[2], int maxbits, Node* leaves, int numsymbols, NodePool* pool, int index) { int lastcount = lists[index][1]->count; /* Count of last chain of list. */ Node* newchain = GetFreeNode(lists, maxbits, pool); Node* oldchain = lists[index][1]; /* These are set up before the recursive calls below, so that there is a list pointing to the new node, to let the garbage collection know it's in use. */ lists[index][0] = oldchain; lists[index][1] = newchain; size_t sum = lists[index - 1][0]->weight + lists[index - 1][1]->weight; if (lastcount < numsymbols && sum > leaves[lastcount].weight) { /* New leaf inserted in list, so count is incremented. */ InitNode(leaves[lastcount].weight, lastcount + 1, oldchain->tail, newchain); } else { InitNode(sum, lastcount, lists[index - 1][1], newchain); } }
/*將資料插入串列中*/ int InsertAfter(ListNode table[], char OldData[], char NewData[]) { /*在資料為OldData的節點之後,加入新節點,資料為NewData[]*/ int EmptyNode, i; EmptyNode = GetFreeNode(table); /*找空節點*/ if (EmptyNode == 0) { /*已經沒有空節點*/ return FALSE; /*告訴呼叫者此動作失敗*/ } strcpy(table[EmptyNode].data, NewData); /*複製資料到新節點*/ i = SearchNode(table, OldData); /*找出舊節點的位置*/ if (i == FALSE) { return FALSE; } table[EmptyNode].next = table[i].next; /*舊節點的次一元素變成新節點的次一元素*/ table[i].next = EmptyNode; /*改變舊節點的次一元素位置*/ return TRUE; /*成功*/ }
static int TryNode(XmapNode *ptr, CStr *str, XmapVal *val, int ntype) { /* * Find a node that matches *string or allocate a new one */ if (ptr->ch != *(str->buf)) { XmapNode *xm; for (xm = ptr; xm->sibling != NULL; xm = xm->sibling) if (xm->sibling->ch == *(str->buf)) break; if (xm->sibling == NULL) xm->sibling = GetFreeNode(str); /* setup new node */ ptr = xm->sibling; } str->buf++; str->len--; if (str->len == 0) { size_t len; /* we're there */ if (ptr->next != NULL) { PutFreeNode(ptr->next); /* lose longer Xkeys with this prefix */ ptr->next = NULL; } switch (ptr->type) { case XK_STR: case XK_EXE: xfree(ptr->val.str.buf); ptr->val.str.len = 0; break; case XK_NOD: case XK_CMD: break; default: abort(); break; } switch (ptr->type = ntype) { case XK_CMD: ptr->val = *val; break; case XK_STR: case XK_EXE: ptr->val.str.len = val->str.len; len = (val->str.len + 1) * sizeof(*ptr->val.str.buf); ptr->val.str.buf = xmalloc(len); (void) memcpy(ptr->val.str.buf, val->str.buf, len); break; default: abort(); break; } } else { /* still more chars to go */ if (ptr->next == NULL) ptr->next = GetFreeNode(str); /* setup new node */ (void) TryNode(ptr->next, str, val, ntype); } return (0); }