Example #1
0
void genif(SNODE *stmt)
/*
 *      generate code to evaluate an if statement.
 */
{
    int lab1, lab2;
	int areg, sreg;
    lab1 = nextlabel++; /* else label */
    lab2 = nextlabel++; /* exit label */
    InitRegs(); /* clear temps */
	ChooseRegs(&areg, &sreg);
    falsejp(stmt->exp, areg, sreg, lab1);
    genstmt(stmt->s1);
    if (stmt->s2 != 0)
     /* else part exists */
    {
        gen_codes(op_jmp, 0, make_label(lab2), 0);
        gen_label(lab1);
        genstmt(stmt->s2);
        gen_label(lab2);
    }
    else
     /* no else code */
        gen_label(lab1);
}
Example #2
0
/*  Assums the dseg is the next higher seg value from the cseg	*/
void loadds(void)
{
    gen_code(op_push, makesegreg(DS), 0);
    gen_code(op_push, makesegreg(CS), 0);
    gen_codes(op_add, 2, make_stack(0), make_immed(8));
    gen_code(op_pop, makesegreg(DS), 0);
}
Example #3
0
void gen_for(SNODE *stmt)
/*
 *      generate code to evaluate a for loop
 */
{
    int old_break, old_cont, exit_label, loop_label, start_label;
	int areg, sreg;
    old_break = breaklab;
    old_cont = contlab;
    loop_label = nextlabel++;
    contlab = nextlabel++;
    start_label = nextlabel++;
    exit_label = nextlabel++;
    InitRegs();
    if (stmt->label != 0)
    {
        gen_void_external(stmt->label);
    }

    gen_codes(op_jmp, 0, make_label(start_label), 0);
    gen_label(loop_label);
    if (stmt->s1 != 0)
    {
        breaklab = exit_label;
        genstmt(stmt->s1);
    }
    if (stmt->lst)
        gen_line(stmt->lst);
    gen_label(contlab);
    InitRegs();
    if (stmt->s2 != 0)
    {
        gen_void_external(stmt->s2);
    }
    gen_label(start_label);
    InitRegs();
	ChooseRegs(&areg, &sreg);
    if (stmt->exp != 0)
        truejp(stmt->exp, areg, sreg, loop_label);
    else
        gen_codes(op_jmp, 0, make_label(loop_label), 0);
    gen_label(exit_label);
    breaklab = old_break;
    contlab = old_cont;
}
Example #4
0
void gencompactswitch(SNODE *stmt, struct cases *cs)
{
    int tablab, size;
    AMODE *ap,  *ap2;
    LLONG_TYPE i;
    tablab = nextlabel++;
    InitRegs();
    size = natural_size(stmt->exp);
    if (size == BESZ_QWORD || size ==  - BESZ_QWORD)
    {
	    ap = gen_expr_external(stmt->exp, FALSE, F_AXDX, BESZ_QWORD);
        if (cs->bottom)
        {
            gen_codes(op_sub, BESZ_DWORD, makedreg(EAX), make_immed(cs->bottom));
            #if sizeof(LLONG_TYPE) == 4
                gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom < 0
                    ?  - 1: 0));
            #else 
                gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom >>
                    32));
            #endif 
        }
Example #5
0
void call_library(char *lib_name)
/*
 *      generate a call to a library routine.
 */
{
    AMODE *ap;
    ap = set_symbol(lib_name, 1);
	if (prm_lscrtdll)
	{
		ap->mode = am_direct;
	}
    gen_codes(op_call, 0, ap, 0);
}
Example #6
0
void genwhile(SNODE *stmt)
/*
 *      generate code to evaluate a while statement.
 */
{
    int lab1, lab2, lab3;
	int areg, sreg;
    InitRegs(); /* initialize temp registers */
    lab1 = contlab; /* save old continue label */
    contlab = nextlabel++; /* new continue label */
    if (stmt->s1 != 0)
     /* has block */
    {
        lab2 = breaklab; /* save old break label */
        breaklab = nextlabel++;
        gen_codes(op_jmp, 0, make_label(contlab), 0);
        lab3 = nextlabel++;
        gen_label(lab3);
        genstmt(stmt->s1);
        gen_label(contlab);
        if (stmt->lst)
            gen_line(stmt->lst);
        InitRegs();
		ChooseRegs(&areg, &sreg);
        truejp(stmt->exp, areg, sreg, lab3);
        gen_label(breaklab);
        breaklab = lab2; /* restore old break label */
    }
    else
     /* no loop code */
    {
        if (stmt->lst)
            gen_line(stmt->lst);
        gen_label(contlab);
        InitRegs();
		ChooseRegs(&areg, &sreg);
        truejp(stmt->exp, areg, sreg, contlab);
    }
    contlab = lab1; /* restore old continue label */
}
Example #7
0
/* ===========================================================================
 * Construct one Huffman tree and assigns the code bit strings and lengths.
 * Update the total bit length for the current block.
 * IN assertion: the field freq is set for all tree elements.
 * OUT assertions: the fields len and code are set to the optimal bit length
 *     and corresponding code. The length opt_len is updated; static_len is
 *     also updated if stree is not null. The field max_code is set.
 */
void build_tree(tree_desc near *desc)
    //tree_desc near *desc; /* the tree descriptor */
{
    ct_data near *tree   = desc->dyn_tree;
    ct_data near *stree  = desc->static_tree;
    int elems            = desc->elems;
    int n, m;          /* iterate over heap elements */
    int max_code = -1; /* largest code with non zero frequency */
    int node = elems;  /* next internal node of the tree */

    /* Construct the initial heap, with least frequent element in
     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
     * heap[0] is not used.
     */
    heap_len = 0, heap_max = HEAP_SIZE;

    for (n = 0; n < elems; n++) {
        if (tree[n].Freq != 0) {
            heap[++heap_len] = max_code = n;
            depth[n] = 0;
        } else {
            tree[n].Len = 0;
        }
    }

    /* The pkzip format requires that at least one distance code exists,
     * and that at least one bit should be sent even if there is only one
     * possible code. So to avoid special checks later on we force at least
     * two codes of non zero frequency.
     */
    while (heap_len < 2) {
        int new_ = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);
        tree[new_].Freq = 1;
        depth[new_] = 0;
        opt_len--; if (stree) static_len -= stree[new_].Len;
        /* new is 0 or 1 so it does not have extra bits */
    }
    desc->max_code = max_code;

    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
     * establish sub-heaps of increasing lengths:
     */
    for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n);

    /* Construct the Huffman tree by repeatedly combining the least two
     * frequent nodes.
     */
    do {
        pqremove(tree, n);   /* n = node of least frequency */
        m = heap[SMALLEST];  /* m = node of next least frequency */

        heap[--heap_max] = n; /* keep the nodes sorted by frequency */
        heap[--heap_max] = m;

        /* Create a new node father of n and m */
        tree[node].Freq = (u16)(tree[n].Freq + tree[m].Freq);
        depth[node] = (u8) (max(depth[n], depth[m]) + 1);
        tree[n].Dad = tree[m].Dad = (u16)node;

        /* and insert the new node in the heap */
        heap[SMALLEST] = node++;
        pqdownheap(tree, SMALLEST);

    } while (heap_len >= 2);

    heap[--heap_max] = heap[SMALLEST];

    /* At this point, the fields freq and dad are set. We can now
     * generate the bit lengths.
     */
    gen_bitlen((tree_desc near *)desc);

    /* The field len is now set, we can generate the bit codes */
    gen_codes ((ct_data near *)tree, max_code);
}
Example #8
0
/* ===========================================================================
 * Allocate the match buffer, initialize the various tables and save the
 * location of the internal file attribute (ascii/binary) and method
 * (DEFLATE/STORE).
 */
void ct_init(int* method)
    //ush  *attr;   /* pointer to internal file attribute */
    //int  *method; /* pointer to compression method */
{
    int n;        /* iterates over tree elements */
    int bits;     /* bit counter */
    int length;   /* length value */
    int code;     /* code value */
    int dist;     /* distance index */

    file_method = method;
    cmpr_bytelen = cmpr_len_bits = 0L;
#ifdef _DEBUG
    input_len = 0L;
#endif

    if (static_dtree[0].Len != 0) return; /* ct_init already called */

    /* Initialize the mapping length (0..255) -> length code (0..28) */
    length = 0;
    for (code = 0; code < LENGTH_CODES-1; code++) {
        base_length[code] = length;
        for (n = 0; n < (1<<extra_lbits[code]); n++) {
            length_code[length++] = (u8)code;
        }
    }
    Assert(length == 256);//, "ct_init: length != 256");
    /* Note that the length 255 (match length 258) can be represented
     * in two different ways: code 284 + 5 bits or code 285, so we
     * overwrite length_code[255] to use the best encoding:
     */
    length_code[length-1] = (u8)code;

    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
    dist = 0;
    for (code = 0 ; code < 16; code++) {
        base_dist[code] = dist;
        for (n = 0; n < (1<<extra_dbits[code]); n++) {
            dist_code[dist++] = (u8)code;
        }
    }
    Assert(dist == 256);//, "ct_init: dist != 256");
    dist >>= 7; /* from now on, all distances are divided by 128 */
    for ( ; code < D_CODES; code++) {
        base_dist[code] = dist << 7;
        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
            dist_code[256 + dist++] = (u8)code;
        }
    }
    Assert(dist == 256);//, "ct_init: 256+dist != 512");

    /* Construct the codes of the static literal tree */
    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
    n = 0;
    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
    /* Codes 286 and 287 do not exist, but we must include them in the
     * tree construction to get a canonical Huffman tree (longest code
     * all ones)
     */
    gen_codes((ct_data near *)static_ltree, L_CODES+1);

    /* The static distance tree is trivial: */
    for (n = 0; n < D_CODES; n++) {
        static_dtree[n].Len = 5;
        static_dtree[n].Code = (u16)bi_reverse(n, 5);
    }

    /* Initialize the first block of the first file: */
    init_block();
}
Example #9
0
void loadregs(void)
/*
 * initialize allocated registers
 */
{
    CSE *csp;
    ENODE *exptr;
    unsigned mask, rmask, i, fmask, frmask, size;
    AMODE *ap,  *ap2;
    csp = olist;
    while (csp != 0)
    {
        int sz;
        if (csp->reg !=  - 1)
        {
             /* see if preload needed */
            exptr = csp->exp;
            if (!lvalue(exptr) || ((SYM*)exptr->v.p[0]->v.p[0])->funcparm)
            {
                exptr = csp->exp;
                InitRegs();
                sz = csp->size;
                ap = gen_expr_external(exptr, FALSE, F_MEM | F_DREG | F_IMMED, sz);
                if (csp->reg < 16)
                {
                    if (ap->mode == am_dreg)
                        peep_tail->oper1->preg = csp->reg;
                    else
                    {
                        if (csp->reg > 3 && chksize(BESZ_WORD, sz))
                            DIAG("byte sized non-register in analyze");
                        ap2 = makedreg(csp->reg);
                        ap2->length = BESZ_DWORD;
                        if (ap->mode == am_immed || ap->length == BESZ_DWORD || ap
                            ->length ==  - BESZ_DWORD)
                            gen_codes(op_mov, BESZ_DWORD, ap2, ap);
                        else
                            if (sz < 0)
                                gen_code(op_movsx, ap2, ap);
                            else
                                gen_code(op_movzx, ap2, ap);
                    }
                }
                else
                if (csp->reg < 32)
                {
                    if (ap->mode == am_dreg)
                        peep_tail->oper1->preg = csp->reg - 12;
                    else
                    {
                        if (csp->reg - 12 > 3 && chksize(BESZ_WORD, sz))
                            DIAG("byte sized non-register in analyze");
                        ap2 = makedreg(csp->reg - 12);
                        ap2->length = BESZ_DWORD;
                        if (ap->mode == am_immed || ap->length == BESZ_DWORD || ap
                            ->length ==  - BESZ_DWORD)
                            gen_codes(op_mov, BESZ_DWORD, ap2, ap);
                        else
                            if (sz < 0)
                                gen_code(op_movsx, ap2, ap);
                            else
                                gen_code(op_movzx, ap2, ap);
                    }
                }
                else
                {
                    /* Should never get here */
                    DIAG("float reg assigned in analyze");
                }
                if (lvalue(exptr) && ((SYM*)exptr->v.p[0]->v.p[0])->funcparm)
                {
                    ((SYM*)exptr->v.p[0]->v.p[0])->mainsym->inreg = TRUE;
                    ((SYM*)exptr->v.p[0]->v.p[0])->mainsym->value.i =  - csp
                        ->reg - (csp->size < 0 ?  - csp->size: csp->size) *256;
                }
            }
        }
        csp = csp->next;
    }
    gen_label(startlab);
}
Example #10
0
void allocate(int datareg, int addreg, int floatreg, SNODE *block)
/*
 *      allocate will allocate registers for the expressions that have
 *      a high enough desirability.  It also puts the function
 * header, consisting of saved registers and stack decrments for local
 * variables
 */
{
    CSE *csp;
    ENODE *exptr;
    unsigned mask, rmask, i, fmask, frmask, size;
    AMODE *ap,  *ap2;
    mask = asmMask;
    rmask = asmRMask;
    fmask = frmask = 0;
    for (i = cf_freedata; i < datareg; i++)
    {
        rmask = rmask | (1 << (15-i));
        mask = mask | (1 << i);
    }
    for (i = cf_freeaddress + 16; i < addreg; i++)
    {
        rmask = rmask | (1 << (23-i));
        mask = mask | (1 << (i - 8));
    }
    while (bsort(&olist))
        ;
     /* sort the expression list */
    csp = olist;
    while (csp != 0)
    {
        if (csp->reg ==  - 1 && !(csp->exp->cflags &DF_VOL) && !csp->voidf)
        {
            if (desire(csp) < 3)
                csp->reg =  - 1;
            else
            {
                if (csp->exp->nodetype == en_rcon || csp->exp->nodetype ==
                    en_fcon || csp->exp->nodetype == en_lrcon || csp->exp
                    ->nodetype == en_floatref || csp->exp->nodetype ==
                    en_doubleref || csp->exp->nodetype == en_longdoubleref ||
                    csp->exp->nodetype == en_fimaginarycon || 
                    csp->exp->nodetype == en_rimaginarycon ||
                    csp->exp->nodetype == en_lrimaginarycon ||
                    csp->exp->nodetype == en_fimaginaryref || 
                    csp->exp->nodetype == en_rimaginaryref ||
                    csp->exp->nodetype == en_lrimaginaryref) {}
                else if ((csp->duses <= csp->uses / 4) && (datareg < cf_maxdata)
                    && dataregs)
                    csp->reg = (datareg)++;
                else if (!(csp->size == 1 || csp->size ==  - 1 || csp->size ==
                    5) && (addreg < cf_maxaddress) && addrregs)
                    csp->reg = (addreg)++;
                else if ((datareg < cf_maxdata) && dataregs)
                    csp->reg = (datareg)++;
                if (csp->reg !=  - 1)
                //                        if (lvalue(csp->exp))
                //                           csp->seg = defseg(csp->exp->v.p[0]) ;
                //                        else
				if (!csp->seg)
				{
                    csp->seg = defseg(csp->exp);
					if (csp->seg)
						csp->reg = -1;
				}
            }

        }
        if (csp->reg !=  - 1)
        {
            if (lvalue(csp->exp) && !((SYM*)csp->exp->v.p[0]->v.p[0])->funcparm)
            {
                ((SYM*)csp->exp->v.p[0]->v.p[0])->mainsym->inreg = TRUE;
                ((SYM*)csp->exp->v.p[0]->v.p[0])->mainsym->value.i =  - csp
                    ->reg - (csp->size < 0 ?  - csp->size: csp->size) *256;
            }
            if (csp->reg < 16)
            {
                rmask = rmask | (1 << (15-csp->reg));
                mask = mask | (1 << csp->reg);
            }
            if (csp->reg < 32)
            {
                rmask = rmask | (1 << (23-csp->reg));
                mask = mask | (1 << (csp->reg - 8));
            }
            else
            {
                frmask = frmask | (1 << (39-csp->reg));
                fmask = fmask | (1 << (csp->reg - 32));
            }
        }
        csp = csp->next;
    }
    allocstack(); /* Allocate stack space for the local vars */
    floatstack_mode = 0; /* no space for floating point temps */
    if (currentfunc->intflag || currentfunc->faultflag)
    {
        mask = 0;
        rmask = 0;
        if (currentfunc->loadds)
            loadds();
        if (prm_farkeyword)
        {
            GenPush(ES + 24, am_dreg, 0);
            GenPush(FS + 24, am_dreg, 0);
            GenPush(GS + 24, am_dreg, 0);
        }
        gen_code(op_pushad, 0, 0);
    }
    if ((conscount || try_block_list || currentfunc->value.classdata.throwlist
        && currentfunc->value.classdata.throwlist->data) && prm_xcept)
    {
        xceptoffs = lc_maxauto += sizeof(XCEPTDATA);
    }
	if (prm_debug)
	{
        rmask = rmask | (1 << (15-EBX));
        mask = mask | (1 << EBX);
        rmask = rmask | (1 << (15-ESI-4));
        mask = mask | (1 << (ESI+4));
        rmask = rmask | (1 << (15-EDI-4));
        mask = mask | (1 << (EDI+4));
	}
    if (prm_cplusplus && prm_xcept || (funcfloat || lc_maxauto || currentfunc
        ->tp->lst.head && currentfunc->tp->lst.head != (SYM*) - 1)
         || (currentfunc->value.classdata.cppflags &PF_MEMBER) && !(currentfunc
             ->value.classdata.cppflags &PF_STATIC)
     || !prm_smartframes || !stackframeoff)
    {
        /* enter is *really* inefficient so we will not use it */
        if (!currentfunc->intflag)
            gen_codes(op_push, 4, makedreg(EBP), 0);
        gen_codes(op_mov, 4, makedreg(EBP), makedreg(ESP));
        if (lc_maxauto)
            gen_code(op_sub, makedreg(ESP), make_immed(lc_maxauto));
        // FIXME ... could auto-alloc an FP value when no frame!
        frame_ins = peep_tail;
    }
    else
        frame_ins = 0;
    if (mask != 0)
        PushRegs(rmask);
    save_mask = mask;
    if (fmask != 0)
        fsave_mask = fmask;
    if (currentfunc->loadds && !currentfunc->intflag)
    {
        loadds();

    }
    if (prm_stackcheck && lc_maxauto)
    {
        AMODE *ap1;
        ap = set_symbol("__stackerror", 1);
        ap1 = set_symbol("__stackbottom", 0);
        ap1->mode = am_direct;
        gen_codes(op_cmp, 4, makedreg(ESP), ap1);
        gen_codes(op_jb, 0, ap, 0);
    }
    AddProfilerData();
    if ((conscount || try_block_list || currentfunc->value.classdata.throwlist
        && currentfunc->value.classdata.throwlist->data) && prm_xcept)
    {
        currentfunc->value.classdata.conslabel = nextlabel++;
        currentfunc->value.classdata.destlabel = nextlabel++;
        gen_codes(op_mov, 4, makedreg(EAX), make_label(nextlabel - 2));
        call_library("__InitExceptBlock");
        gen_label(nextlabel - 1);
    }
}
Example #11
0
/* Allocate the match buffer and initialize the various tables. */
CodeTree::CodeTree(int deflate_level, BufferedTransformation &outQ)
  : BitOutput(outQ),
	deflate_level(deflate_level),
	dyn_ltree(HEAP_SIZE), dyn_dtree(2*D_CODES+1),
	bl_tree(2*BL_CODES+1),
	bl_count(MAX_BITS+1),
	l_desc(dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0),
	d_desc(dyn_dtree, static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS, 0),
	bl_desc(bl_tree, (ct_data *)0, extra_blbits, 0,     BL_CODES, MAX_BL_BITS, 0),
	heap(2*L_CODES+1),
	depth(2*L_CODES+1),
	length_code(MAX_MATCH-MIN_MATCH+1),
	dist_code(512),
	base_length(LENGTH_CODES),
	base_dist(D_CODES),
	l_buf(LIT_BUFSIZE),
	d_buf(DIST_BUFSIZE),
	flag_buf(LIT_BUFSIZE/8)
{

   unsigned int n;    /* iterates over tree elements */
   int bits;      /* bit counter */
   int length;    /* length value */
   register int code; /* code value */
   int dist;      /* distance index */

	compressed_len = input_len = 0L;

   /* Initialize the mapping length (0..255) -> length code (0..28) */
   length = 0;
   for (code=0; code < LENGTH_CODES-1; code++) {
	  base_length[code] = length;
	  for (n=0; n < (1<<extra_lbits[code]); n++) {
		 length_code[length++] = (byte)code;
	  }
   }
   assert (length == 256);
	/* Note that the length 255 (match length 258) can be represented
	   in two different ways: code 284 + 5 bits or code 285, so we
	   overwrite length_code[255] to use the best encoding:     */
   length_code[length-1] = (byte)code;

   /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
   dist = 0;
   for (code=0 ; code < 16; code++) {
	  base_dist[code] = dist;
	  for (n=0; n < (1<<extra_dbits[code]); n++) {
		 dist_code[dist++] = (byte)code;
	  }
   }
   assert (dist == 256);
   dist >>= 7; /* from now on, all distances are divided by 128 */
   for (; code < D_CODES; code++) {
	  base_dist[code] = dist << 7;
	  for (n=0; n < (1<<(extra_dbits[code]-7)); n++) {
		 dist_code[256 + dist++] = (byte)code;
	  }
   }
   assert (dist == 256);

   if (!streesBuilt)
   {
	   /* Construct the codes of the static literal tree */
	   for (bits=0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
	   n = 0;
	   while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
	   while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
	   while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
	   while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
	   /* Codes 286 and 287 do not exist, but we must include them in the tree
		  construction to get a canonical Huffman tree (longest code all ones) */
	   gen_codes(static_ltree, L_CODES+1);

	   /* The static distance tree is trivial: */
	   for (n=0; n < D_CODES; n++) {
		  static_dtree[n].Len = 5;
		  static_dtree[n].Code = reverse(n, 5);
	   }
	   streesBuilt = true;
   }

   /* Initialize the first block of the first file: */
   init_block();
}
Example #12
0
static void build_tree(
    z_stream&	s,
    tree_desc*	desc )
{
    ct_data* tree         = desc->dyn_tree;
    const ct_data* stree  = desc->stat_desc->static_tree;
    int elems             = desc->stat_desc->elems;
    int max_code		  = -1;
    int n, m;
    int node;

    s.heap_len = 0, s.heap_max = HEAP_SIZE;

    for( n = 0 ; n < elems ; n++ )
    {
        if( tree[ n ].Freq )
        {
            s.heap[ ++s.heap_len ] = max_code = n;
            s.depth[ n ] = 0;
        }
        else
        {
            tree[ n ].Len = 0;
        }
    }

    while( s.heap_len < 2 )
    {
        node = s.heap[ ++s.heap_len ] = ( max_code < 2 ? ++max_code : 0 );
        tree[ node ].Freq = 1;
        s.depth[ node ] = 0;
        s.opt_len--;
        if( stree )
            s.static_len -= stree[ node ].Len;
    }

    desc->max_code = max_code;

    for( n = s.heap_len / 2 ; n >= 1 ; n-- )
        pqdownheap( s, tree, n );

    node = elems;

    do
    {
        pqremove( s, tree, n );
        m = s.heap[ SMALLEST ];

        s.heap[ --s.heap_max ] = n;
        s.heap[ --s.heap_max ] = m;

        tree[ node ].Freq = tree[ n ].Freq + tree[ m ].Freq;
        s.depth[ node ] = (unsigned char) ( ( s.depth[ n ] >= s.depth[ m ] ? s.depth[ n ] : s.depth[ m ] ) + 1 );
        tree[ n ].Dad = tree[ m ].Dad = (unsigned short) node;

        s.heap[ SMALLEST ] = node++;
        pqdownheap( s, tree, SMALLEST );

    }
    while( s.heap_len >= 2 );

    s.heap[ --s.heap_max ] = s.heap[ SMALLEST ];

    gen_bitlen( s, (tree_desc*) desc );
    gen_codes( (ct_data*) tree, max_code, s.bl_count );
}