Annotation of sbbs/sbbs3/lzh.c, revision 1.1.1.1

1.1       root        1: /* lzh.c */
                      2: 
                      3: /* Synchronet LZH compression library */
                      4: 
                      5: /* $Id: lzh.c,v 1.3 2000/10/26 02:53:26 rswindell Exp $ */
                      6: 
                      7: /**************************************************************************** 
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    * 
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Rob Swindell's conversion of 1988 LZH (LHarc) encoding functions                    * 
                     12:  * Based on Japanese version 29-NOV-1988                                                                       * 
                     13:  * LZSS coded by Haruhiko Okumura                                                                                      * 
                     14:  * Adaptive Huffman Coding coded by Haruyasu Yoshizaki                                         * 
                     15:  *                                                                                                                                                     *
                     16:  * Anonymous FTP access to the most recent released source is available at     *
                     17:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     18:  *                                                                                                                                                     *
                     19:  * Anonymous CVS access to the development source and modification history     *
                     20:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     21:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     22:  *     (just hit return, no password is necessary)                                                     *
                     23:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     24:  *                                                                                                                                                     *
                     25:  * For Synchronet coding style and modification guidelines, see                                *
                     26:  * http://www.synchro.net/source.html                                                                          *
                     27:  *                                                                                                                                                     *
                     28:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     29:  * format) via e-mail to [email protected]                                                                      *
                     30:  *                                                                                                                                                     *
                     31:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     32:  ****************************************************************************/
                     33: 
                     34: #include <stdio.h>
                     35: #include <stdlib.h>
                     36: #include <string.h>
                     37: #include <ctype.h>
                     38: #include <malloc.h>
                     39: #include "lzh.h"
                     40: 
                     41: /****************************************************************************/
                     42: /* Memory allocation macros for various compilers and environments                     */
                     43: /* MALLOC is used for allocations of 64k or less                                                       */
                     44: /* FREE is used to free buffers allocated with MALLOC                                          */
                     45: /* LMALLOC is used for allocations of possibly larger than 64k                         */
                     46: /* LFREE is used to free buffers allocated with LMALLOC                                        */
                     47: /* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer        */
                     48: /****************************************************************************/
                     49: #if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
                     50:        #if defined(__TURBOC__)
                     51:                #define REALLOC(x,y) farrealloc(x,y)
                     52:                #define LMALLOC(x) farmalloc(x)
                     53:                #define MALLOC(x) farmalloc(x)
                     54:                #define LFREE(x) farfree(x)
                     55:                #define FREE(x) farfree(x)
                     56:        #elif defined(__WATCOMC__)
                     57:                #define REALLOC realloc
                     58:                #define LMALLOC(x) halloc(x,1)  /* far heap, but slow */
                     59:                #define MALLOC malloc                   /* far heap, but 64k max */
                     60:                #define LFREE hfree
                     61:                #define FREE free
                     62:        #else   /* Other 16-bit Compiler */
                     63:                #define REALLOC realloc
                     64:                #define LMALLOC malloc
                     65:                #define MALLOC malloc
                     66:                #define LFREE free
                     67:                #define FREE free
                     68:        #endif
                     69: #else          /* 32-bit Compiler or Small Memory Model */
                     70:        #define REALLOC realloc
                     71:        #define LMALLOC malloc
                     72:        #define MALLOC malloc
                     73:        #define LFREE free
                     74:        #define FREE free
                     75: #endif
                     76: 
                     77: 
                     78: 
                     79: /* LZSS Parameters */
                     80: 
                     81: #define LZH_N                  4096    /* Size of string buffer */
                     82: #define LZH_F                  60              /* Size of look-ahead buffer */
                     83: #define LZH_THRESHOLD  2
                     84: #define LZH_NIL                LZH_N   /* End of tree's node  */
                     85: 
                     86: #ifdef LZH_DYNAMIC_BUF
                     87: 
                     88: unsigned char *lzh_text_buf;
                     89: short int      lzh_match_position, lzh_match_length,
                     90:          *lzh_lson, *lzh_rson, *lzh_dad;
                     91: 
                     92: #else
                     93: 
                     94: unsigned char lzh_text_buf[LZH_N + LZH_F - 1];
                     95: short int        lzh_match_position, lzh_match_length,
                     96:                lzh_lson[LZH_N + 1], lzh_rson[LZH_N + 257], lzh_dad[LZH_N + 1];
                     97: 
                     98: #endif
                     99: 
                    100: 
                    101: void lzh_init_tree(void)  /* Initializing tree */
                    102: {
                    103:        short int  i;
                    104: 
                    105:        for (i = LZH_N + 1; i <= LZH_N + 256; i++)
                    106:                lzh_rson[i] = LZH_NIL;                  /* root */
                    107:        for (i = 0; i < LZH_N; i++)
                    108:                lzh_dad[i] = LZH_NIL;                   /* node */
                    109: }
                    110: 
                    111: /******************************/
                    112: /* Inserting node to the tree */
                    113: /* Only used during encoding  */
                    114: /******************************/
                    115: void lzh_insert_node(short int r)
                    116: {
                    117:        short int  i, p, cmp;
                    118:        unsigned char  *key;
                    119:        unsigned c;
                    120: 
                    121:        cmp = 1;
                    122:        key = lzh_text_buf+r;
                    123:        p = LZH_N + 1 + key[0];
                    124:        lzh_rson[r] = lzh_lson[r] = LZH_NIL;
                    125:        lzh_match_length = 0;
                    126:        for ( ; ; ) {
                    127:                if (cmp >= 0) {
                    128:                        if (lzh_rson[p] != LZH_NIL)
                    129:                                p = lzh_rson[p];
                    130:                        else {
                    131:                                lzh_rson[p] = r;
                    132:                                lzh_dad[r] = p;
                    133:                                return;
                    134:                        }
                    135:                } else {
                    136:                        if (lzh_lson[p] != LZH_NIL)
                    137:                                p = lzh_lson[p];
                    138:                        else {
                    139:                                lzh_lson[p] = r;
                    140:                                lzh_dad[r] = p;
                    141:                                return;
                    142:                        }
                    143:                }
                    144:                for (i = 1; i < LZH_F; i++)
                    145:                        if ((cmp = key[i] - lzh_text_buf[p + i]) != 0)
                    146:                                break;
                    147:                if (i > LZH_THRESHOLD) {
                    148:                        if (i > lzh_match_length) {
                    149:                                lzh_match_position = ((r - p) & (LZH_N - 1)) - 1;
                    150:                                if ((lzh_match_length = i) >= LZH_F)
                    151:                                        break;
                    152:                        }
                    153:                        if (i == lzh_match_length) {
                    154:                                if ((c = ((r - p) & (LZH_N - 1)) - 1) 
                    155:                                        < (unsigned)lzh_match_position) {
                    156:                                        lzh_match_position = c;
                    157:                                }
                    158:                        }
                    159:                }
                    160:        }
                    161:        lzh_dad[r] = lzh_dad[p];
                    162:        lzh_lson[r] = lzh_lson[p];
                    163:        lzh_rson[r] = lzh_rson[p];
                    164:        lzh_dad[lzh_lson[p]] = r;
                    165:        lzh_dad[lzh_rson[p]] = r;
                    166:        if (lzh_rson[lzh_dad[p]] == p)
                    167:                lzh_rson[lzh_dad[p]] = r;
                    168:        else
                    169:                lzh_lson[lzh_dad[p]] = r;
                    170:        lzh_dad[p] = LZH_NIL;  /* remove p */
                    171: }
                    172: 
                    173: void lzh_delete_node(short int p)  /* Deleting node from the tree */
                    174: {
                    175:        short int  q;
                    176: 
                    177:        if (lzh_dad[p] == LZH_NIL)
                    178:                return;                 /* unregistered */
                    179:        if (lzh_rson[p] == LZH_NIL)
                    180:                q = lzh_lson[p];
                    181:        else
                    182:        if (lzh_lson[p] == LZH_NIL)
                    183:                q = lzh_rson[p];
                    184:        else {
                    185:                q = lzh_lson[p];
                    186:                if (lzh_rson[q] != LZH_NIL) {
                    187:                        do {
                    188:                                q = lzh_rson[q];
                    189:                        } while (lzh_rson[q] != LZH_NIL);
                    190:                        lzh_rson[lzh_dad[q]] = lzh_lson[q];
                    191:                        lzh_dad[lzh_lson[q]] = lzh_dad[q];
                    192:                        lzh_lson[q] = lzh_lson[p];
                    193:                        lzh_dad[lzh_lson[p]] = q;
                    194:                }
                    195:                lzh_rson[q] = lzh_rson[p];
                    196:                lzh_dad[lzh_rson[p]] = q;
                    197:        }
                    198:        lzh_dad[q] = lzh_dad[p];
                    199:        if (lzh_rson[lzh_dad[p]] == p)
                    200:                lzh_rson[lzh_dad[p]] = q;
                    201:        else
                    202:                lzh_lson[lzh_dad[p]] = q;
                    203:        lzh_dad[p] = LZH_NIL;
                    204: }
                    205: 
                    206: /* Huffman coding parameters */
                    207: 
                    208: #define LZH_N_CHAR             (256 - LZH_THRESHOLD + LZH_F)
                    209:                                        /* character code (= 0..LZH_N_CHAR-1) */
                    210: #define LZH_T          (LZH_N_CHAR * 2 - 1)    /* Size of table */
                    211: #define LZH_R          (LZH_T - 1)             /* root position */
                    212: #define MAX_FREQ       0x8000
                    213:                                        /* update when cumulative frequency */
                    214:                                        /* reaches to this value */
                    215: 
                    216: /*
                    217:  * Tables for encoding/decoding upper 6 bits of
                    218:  * sliding dictionary pointer
                    219:  */
                    220: /* encoder table */
                    221: uchar lzh_p_len[64] = {
                    222:        0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
                    223:        0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
                    224:        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
                    225:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    226:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    227:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    228:        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
                    229:        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
                    230: };
                    231: 
                    232: uchar lzh_p_code[64] = {
                    233:        0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
                    234:        0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
                    235:        0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
                    236:        0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
                    237:        0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
                    238:        0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
                    239:        0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
                    240:        0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
                    241: };
                    242: 
                    243: /* decoder table */
                    244: uchar lzh_d_code[256] = {
                    245:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    246:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    247:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    248:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    249:        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    250:        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    251:        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
                    252:        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
                    253:        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
                    254:        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
                    255:        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
                    256:        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
                    257:        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
                    258:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    259:        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
                    260:        0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
                    261:        0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
                    262:        0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
                    263:        0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
                    264:        0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
                    265:        0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
                    266:        0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
                    267:        0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
                    268:        0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
                    269:        0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
                    270:        0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
                    271:        0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
                    272:        0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
                    273:        0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
                    274:        0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
                    275:        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
                    276:        0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
                    277: };
                    278: 
                    279: uchar lzh_d_len[256] = {
                    280:        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
                    281:        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
                    282:        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
                    283:        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
                    284:        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
                    285:        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
                    286:        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
                    287:        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
                    288:        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
                    289:        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
                    290:        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
                    291:        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
                    292:        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
                    293:        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
                    294:        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
                    295:        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
                    296:        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
                    297:        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
                    298:        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
                    299:        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
                    300:        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
                    301:        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
                    302:        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
                    303:        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
                    304:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    305:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    306:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    307:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    308:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    309:        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
                    310:        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
                    311:        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
                    312: };
                    313: 
                    314: #ifdef LZH_DYNAMIC_BUF
                    315: 
                    316: unsigned short *lzh_freq=NULL;  /* cumulative freq table */
                    317: 
                    318: /*
                    319:  * pointing parent nodes.
                    320:  * area [LZH_T..(LZH_T + LZH_N_CHAR - 1)] are pointers for leaves
                    321:  */
                    322: short int *lzh_prnt=NULL;
                    323: 
                    324: /* pointing children nodes (son[], son[] + 1)*/
                    325: short int *lzh_son=NULL;
                    326: 
                    327: #else  /* STATIC */
                    328: 
                    329: unsigned short lzh_freq[LZH_T + 1];   /* cumulative freq table */
                    330: short int lzh_prnt[LZH_T + LZH_N_CHAR];
                    331: short int lzh_son[LZH_T + 1];            /* bug fixed by Digital Dynamics */
                    332: 
                    333: #endif
                    334: 
                    335: 
                    336: unsigned short lzh_getbuf = 0;         /* Was just "unsigned" fixed 04/12/95 */
                    337: uchar lzh_getlen = 0;
                    338: 
                    339: int lzh_getbit(uchar *inbuf, long *incnt, long inlen)    /* get one bit */
                    340: {
                    341:        short int i;
                    342: 
                    343:        while (lzh_getlen <= 8) {
                    344:                if((*incnt)>=inlen)
                    345:                        i=0;
                    346:                else
                    347:                        i=inbuf[(*incnt)++];
                    348:                lzh_getbuf |= i << (8 - lzh_getlen);
                    349:                lzh_getlen += 8;
                    350:        }
                    351:        i = lzh_getbuf;
                    352:        lzh_getbuf <<= 1;
                    353:        lzh_getlen--;
                    354:        return (i < 0);
                    355: }
                    356: 
                    357: short int lzh_getbyte(uchar *inbuf, long *incnt, long inlen)   /* get a byte */
                    358: {
                    359:        unsigned short i;
                    360: 
                    361:        while (lzh_getlen <= 8) {
                    362:                if((*incnt)>=inlen)
                    363:                        i=0;
                    364:                else
                    365:                        i=inbuf[(*incnt)++];
                    366:                lzh_getbuf |= i << (8 - lzh_getlen);
                    367:                lzh_getlen += 8;
                    368:        }
                    369:        i = lzh_getbuf;
                    370:        lzh_getbuf <<= 8;
                    371:        lzh_getlen -= 8;
                    372:        return i >> 8;
                    373: }
                    374: 
                    375: unsigned lzh_putbuf = 0;
                    376: uchar lzh_putlen = 0;
                    377: 
                    378: /* output c bits */
                    379: void lzh_putcode(short int l, unsigned short c, uchar *outbuf, long *outlen)
                    380: {
                    381:        lzh_putbuf |= c >> lzh_putlen;
                    382:        if ((lzh_putlen += l) >= 8) {
                    383:                outbuf[(*outlen)++]=(lzh_putbuf >> 8);
                    384:                if ((lzh_putlen -= 8) >= 8) {
                    385:                        outbuf[(*outlen)++]=lzh_putbuf;
                    386:                        lzh_putlen -= 8;
                    387:                        lzh_putbuf = c << (l - lzh_putlen);
                    388:                } else {
                    389:                        lzh_putbuf <<= 8;
                    390:                }
                    391:        }
                    392: }
                    393: 
                    394: 
                    395: /* initialize freq tree */
                    396: 
                    397: void lzh_start_huff(void)
                    398: {
                    399:        short int i, j;
                    400: 
                    401: lzh_getbuf = 0;        /* Added by Digital Dynamics for repeating operations */
                    402: lzh_getlen = 0;
                    403: lzh_putbuf = 0;
                    404: lzh_putlen = 0;
                    405: 
                    406:        for (i = 0; i < LZH_N_CHAR; i++) {
                    407:                lzh_freq[i] = 1;
                    408:                lzh_son[i] = i + LZH_T;
                    409:                lzh_prnt[i + LZH_T] = i;
                    410:        }
                    411:        i = 0; j = LZH_N_CHAR;
                    412:        while (j <= LZH_R) {
                    413:                lzh_freq[j] = lzh_freq[i] + lzh_freq[i + 1];
                    414:                lzh_son[j] = i;
                    415:                lzh_prnt[i] = lzh_prnt[i + 1] = j;
                    416:                i += 2; j++;
                    417:        }
                    418:        lzh_freq[LZH_T] = 0xffff;
                    419:     lzh_prnt[LZH_R] = 0;
                    420: }
                    421: 
                    422: 
                    423: /* reconstruct freq tree */
                    424: 
                    425: void lzh_reconst(void)
                    426: {
                    427:        short int i, j, k;
                    428:        unsigned short f, l;
                    429: 
                    430:        /* halven cumulative freq for leaf nodes */
                    431:        j = 0;
                    432:        for (i = 0; i < LZH_T; i++) {
                    433:                if (lzh_son[i] >= LZH_T) {
                    434:                        lzh_freq[j] = (lzh_freq[i] + 1) / 2;
                    435:                        lzh_son[j] = lzh_son[i];
                    436:                        j++;
                    437:                }
                    438:        }
                    439:        /* make a tree : first, connect children nodes */
                    440:        for (i = 0, j = LZH_N_CHAR; j < LZH_T; i += 2, j++) {
                    441:                k = i + 1;
                    442:                f = lzh_freq[j] = lzh_freq[i] + lzh_freq[k];
                    443:                for (k = j - 1; f < lzh_freq[k]; k--);
                    444:                k++;
                    445:                l = (j - k) * 2;
                    446:                
                    447:                /* movmem() is Turbo-C dependent
                    448:                   rewritten to memmove() by Kenji */
                    449:                
                    450:                /* movmem(&lzh_freq[k], &lzh_freq[k + 1], l); */
                    451:                (void)memmove(lzh_freq+k+1,lzh_freq+k, l);
                    452:                lzh_freq[k] = f;
                    453:                /* movmem(&lzh_son[k], &lzh_son[k + 1], l); */
                    454:                (void)memmove(lzh_son+k+1,lzh_son+k, l);
                    455:                lzh_son[k] = i;
                    456:        }
                    457:        /* connect parent nodes */
                    458:        for (i = 0; i < LZH_T; i++) {
                    459:                if ((k = lzh_son[i]) >= LZH_T) {
                    460:                        lzh_prnt[k] = i;
                    461:                } else {
                    462:                        lzh_prnt[k] = lzh_prnt[k + 1] = i;
                    463:                }
                    464:        }
                    465: }
                    466: 
                    467: /* update freq tree */
                    468: 
                    469: void lzh_update(short int c)
                    470: {
                    471:        short int i, j, k, l;
                    472: 
                    473:        if (lzh_freq[LZH_R] == MAX_FREQ) {
                    474:                lzh_reconst();
                    475:        }
                    476:        c = lzh_prnt[c + LZH_T];
                    477:        do {
                    478:                k = ++lzh_freq[c];
                    479: 
                    480:                /* swap nodes to keep the tree freq-ordered */
                    481:                if (k > lzh_freq[l = c + 1]) {
                    482:                        while (k > lzh_freq[++l]);
                    483:                        l--;
                    484:                        lzh_freq[c] = lzh_freq[l];
                    485:                        lzh_freq[l] = k;
                    486: 
                    487:                        i = lzh_son[c];
                    488:                        lzh_prnt[i] = l;
                    489:                        if (i < LZH_T) lzh_prnt[i + 1] = l;
                    490: 
                    491:                        j = lzh_son[l];
                    492:                        lzh_son[l] = i;
                    493: 
                    494:                        lzh_prnt[j] = c;
                    495:                        if (j < LZH_T) lzh_prnt[j + 1] = c;
                    496:                        lzh_son[c] = j;
                    497: 
                    498:                        c = l;
                    499:                }
                    500:        } while ((c = lzh_prnt[c]) != 0);       /* do it until reaching the root */
                    501: }
                    502: 
                    503: unsigned short lzh_code, lzh_len;
                    504: 
                    505: void lzh_encode_char(unsigned short c, uchar *outbuf, long *outlen)
                    506: {
                    507:        unsigned short i;
                    508:        short int j, k;
                    509: 
                    510:        i = 0;
                    511:        j = 0;
                    512:        k = lzh_prnt[c + LZH_T];
                    513: 
                    514:        /* search connections from leaf node to the root */
                    515:        do {
                    516:                i >>= 1;
                    517: 
                    518:                /*
                    519:                if node's address is odd, output 1
                    520:                else output 0
                    521:                */
                    522:                if (k & 1) i += 0x8000;
                    523: 
                    524:                j++;
                    525:        } while ((k = lzh_prnt[k]) != LZH_R);
                    526:        lzh_putcode(j, i, outbuf, outlen);
                    527:        lzh_code = i;
                    528:        lzh_len = j;
                    529:        lzh_update(c);
                    530: }
                    531: 
                    532: void lzh_encode_position(unsigned short c, uchar *outbuf, long *outlen)
                    533: {
                    534:        unsigned short i;
                    535: 
                    536:        /* output upper 6 bits with encoding */
                    537:        i = c >> 6;
                    538:        lzh_putcode(lzh_p_len[i], (unsigned short)(lzh_p_code[i] << 8), outbuf, outlen);
                    539: 
                    540:        /* output lower 6 bits directly */
                    541:        lzh_putcode(6, (unsigned short)((c & 0x3f) << 10), outbuf, outlen);
                    542: }
                    543: 
                    544: void lzh_encode_end(uchar *outbuf, long *outlen)
                    545: {
                    546:        if (lzh_putlen) {
                    547:                outbuf[(*outlen)++]=(lzh_putbuf >> 8);
                    548:        }
                    549: }
                    550: 
                    551: short int lzh_decode_char(uchar *inbuf, long *incnt, long inlen)
                    552: {
                    553:        unsigned short c;
                    554: 
                    555:        c = lzh_son[LZH_R];
                    556: 
                    557:        /*
                    558:         * start searching tree from the root to leaves.
                    559:         * choose node #(lzh_son[]) if input bit == 0
                    560:         * else choose #(lzh_son[]+1) (input bit == 1)
                    561:         */
                    562:        while (c < LZH_T) {
                    563:                c += lzh_getbit(inbuf,incnt,inlen);
                    564:                c = lzh_son[c];
                    565:        }
                    566:        c -= LZH_T;
                    567:        lzh_update(c);
                    568:        return c;
                    569: }
                    570: 
                    571: short int lzh_decode_position(uchar *inbuf, long *incnt, long inlen)
                    572: {
                    573:        unsigned short i, j, c;
                    574: 
                    575:        /* decode upper 6 bits from given table */
                    576:        i = lzh_getbyte(inbuf,incnt,inlen);
                    577:        c = (unsigned)lzh_d_code[i] << 6;
                    578:        j = lzh_d_len[i];
                    579: 
                    580:        /* input lower 6 bits directly */
                    581:        j -= 2;
                    582:        while (j--) {
                    583:                i = (i << 1) + lzh_getbit(inbuf,incnt,inlen);
                    584:        }
                    585:        return c | i & 0x3f;
                    586: }
                    587: 
                    588: /* Compression */
                    589: 
                    590: /* Encoding/Compressing */
                    591: /* Returns length of outbuf */
                    592: long LZHCALL lzh_encode(uchar *inbuf, long inlen, uchar *outbuf)
                    593: {
                    594:        short int  i, c, len, r, s, last_match_length;
                    595:        long incnt,outlen; /* textsize=0; */
                    596: 
                    597: #ifdef LZH_DYNAMIC_BUF
                    598: 
                    599:        if((lzh_text_buf=(uchar *)MALLOC(LZH_N + LZH_F - 1))==NULL)
                    600:                return(-1);
                    601:        if((lzh_freq=(unsigned short*)MALLOC((LZH_T + 1)*sizeof(unsigned short)))==NULL) {
                    602:                FREE(lzh_text_buf);
                    603:                return(-1); }
                    604:        if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
                    605:                FREE(lzh_text_buf);
                    606:                FREE(lzh_freq);
                    607:                return(-1); }
                    608:        if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
                    609:                FREE(lzh_text_buf);
                    610:                FREE(lzh_prnt);
                    611:                FREE(lzh_freq);
                    612:                return(-1); }
                    613:        if((lzh_lson=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
                    614:                FREE(lzh_text_buf);
                    615:                FREE(lzh_prnt);
                    616:                FREE(lzh_freq);
                    617:                FREE(lzh_son);
                    618:                return(-1); }
                    619:        if((lzh_rson=(short *)MALLOC((LZH_N + 257)*sizeof(short)))==NULL) {
                    620:                FREE(lzh_text_buf);
                    621:                FREE(lzh_prnt);
                    622:                FREE(lzh_freq);
                    623:                FREE(lzh_son);
                    624:                FREE(lzh_lson);
                    625:                return(-1); }
                    626:        if((lzh_dad=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
                    627:                FREE(lzh_text_buf);
                    628:                FREE(lzh_prnt);
                    629:                FREE(lzh_freq);
                    630:                FREE(lzh_son);
                    631:         FREE(lzh_lson);
                    632:                FREE(lzh_rson);
                    633:                return(-1); }
                    634: #endif
                    635: 
                    636:        incnt=0;
                    637:        memcpy(outbuf,&inlen,sizeof(inlen));
                    638:        outlen=sizeof(inlen);
                    639:        if(!inlen) {
                    640: #ifdef LZH_DYNAMIC_BUF
                    641:                FREE(lzh_text_buf);
                    642:                FREE(lzh_prnt);
                    643:                FREE(lzh_freq);
                    644:                FREE(lzh_son);
                    645:         FREE(lzh_lson);
                    646:         FREE(lzh_rson);
                    647:                FREE(lzh_dad);
                    648: #endif
                    649:                return(outlen); }
                    650:        lzh_start_huff();
                    651:        lzh_init_tree();
                    652:        s = 0;
                    653:        r = LZH_N - LZH_F;
                    654:        for (i = s; i < r; i++)
                    655:                lzh_text_buf[i] = ' ';
                    656:        for (len = 0; len < LZH_F && incnt<inlen; len++)
                    657:                lzh_text_buf[r + len] = inbuf[incnt++];
                    658:        /* textsize = len; */
                    659:        for (i = 1; i <= LZH_F; i++)
                    660:                lzh_insert_node((short)(r - i));
                    661:        lzh_insert_node(r);
                    662:        do {
                    663:                if (lzh_match_length > len)
                    664:                        lzh_match_length = len;
                    665:                if (lzh_match_length <= LZH_THRESHOLD) {
                    666:                        lzh_match_length = 1;
                    667:                        lzh_encode_char(lzh_text_buf[r],outbuf,&outlen);
                    668:                } else {
                    669:                        lzh_encode_char((unsigned short)(255 - LZH_THRESHOLD + lzh_match_length)
                    670:                                ,outbuf,&outlen);
                    671:                        lzh_encode_position(lzh_match_position
                    672:                                ,outbuf,&outlen);
                    673:                }
                    674:                last_match_length = lzh_match_length;
                    675:                for (i = 0; i < last_match_length && incnt<inlen; i++) {
                    676:                        lzh_delete_node(s);
                    677:                        c=inbuf[incnt++];
                    678:                        lzh_text_buf[s] = (uchar)c;
                    679:                        if (s < LZH_F - 1)
                    680:                                lzh_text_buf[s + LZH_N] = (uchar)c;
                    681:                        s = (s + 1) & (LZH_N - 1);
                    682:                        r = (r + 1) & (LZH_N - 1);
                    683:                        lzh_insert_node(r);
                    684:                }
                    685: /***
                    686:                if ((textsize += i) > printcount) {
                    687:                        printf("%12ld\r", textsize);
                    688:                        printcount += 1024;
                    689:                }
                    690: ***/
                    691:                while (i++ < last_match_length) {
                    692:                        lzh_delete_node(s);
                    693:                        s = (s + 1) & (LZH_N - 1);
                    694:                        r = (r + 1) & (LZH_N - 1);
                    695:                        if (--len) lzh_insert_node(r);
                    696:                }
                    697:        } while (len > 0);
                    698:        lzh_encode_end(outbuf,&outlen);
                    699: /*
                    700:        printf("input: %ld (%ld) bytes\n", inlen,textsize);
                    701:        printf("output: %ld bytes\n", outlen);
                    702:        printf("output/input: %.3f\n", (double)outlen / inlen);
                    703: */
                    704: 
                    705: #ifdef LZH_DYNAMIC_BUF
                    706:        FREE(lzh_text_buf);
                    707:        FREE(lzh_prnt);
                    708:        FREE(lzh_freq);
                    709:        FREE(lzh_son);
                    710:        FREE(lzh_lson);
                    711:        FREE(lzh_rson);
                    712:        FREE(lzh_dad);
                    713: #endif
                    714: 
                    715:        return(outlen);
                    716: }
                    717: 
                    718: /* Decoding/Uncompressing */
                    719: /* Returns length of outbuf */
                    720: long LZHCALL lzh_decode(uchar *inbuf, long inlen, uchar *outbuf)
                    721: {
                    722:        short int  i, j, k, r, c;
                    723:        unsigned long int  count;
                    724:        long incnt,textsize;
                    725: 
                    726: #ifdef LZH_DYNAMIC_BUF
                    727: 
                    728:        if((lzh_text_buf=(uchar *)MALLOC((LZH_N + LZH_F - 1)*2))==NULL)
                    729:                return(-1);
                    730:        if((lzh_freq=(unsigned short *)MALLOC((LZH_T + 1)*sizeof(unsigned short)))
                    731:                ==NULL) {
                    732:                FREE(lzh_text_buf);
                    733:                return(-1); }
                    734:        if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
                    735:                FREE(lzh_text_buf);
                    736:                FREE(lzh_freq);
                    737:                return(-1); }
                    738:        if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
                    739:                FREE(lzh_text_buf);
                    740:                FREE(lzh_prnt);
                    741:                FREE(lzh_freq);
                    742:                return(-1); }
                    743: 
                    744: #endif
                    745: 
                    746:        incnt=0;
                    747:        memcpy(&textsize,inbuf,sizeof(textsize));
                    748:        incnt+=sizeof(textsize);
                    749:        if (textsize == 0) {
                    750: #ifdef LZH_DYNAMIC_BUF
                    751:                FREE(lzh_text_buf);
                    752:                FREE(lzh_prnt);
                    753:                FREE(lzh_freq);
                    754:                FREE(lzh_son);
                    755: #endif
                    756:                return(textsize); }
                    757:        lzh_start_huff();
                    758:        for (i = 0; i < LZH_N - LZH_F; i++)
                    759:                *(lzh_text_buf+i) = ' ';
                    760:        r = LZH_N - LZH_F;
                    761:     for (count = 0; count < (unsigned long)textsize; ) {
                    762:                c = lzh_decode_char(inbuf,&incnt,inlen);
                    763:                if (c < 256) {
                    764:                        outbuf[count]=(uchar)c;
                    765: #if 0
                    766:                        if(r>(LZH_N + LZH_F - 1) || r<0) {
                    767:                                printf("Overflow! (%d)\n",r);
                    768:                                getch();
                    769:                                exit(-1); }
                    770: #endif
                    771:                        *(lzh_text_buf+r) = (uchar)c;
                    772:                        r++;
                    773:                        r &= (LZH_N - 1);
                    774:                        count++;
                    775:                } else {
                    776:                        i = (r - lzh_decode_position(inbuf,&incnt,inlen) - 1)
                    777:                                & (LZH_N - 1);
                    778:                        j = c - 255 + LZH_THRESHOLD;
                    779:                        for (k = 0; k < j && count<(unsigned long)textsize; k++) {
                    780:                                c = lzh_text_buf[(i + k) & (LZH_N - 1)];
                    781:                                outbuf[count]=(uchar)c;
                    782: #if 0
                    783:                                if(r>(LZH_N + LZH_F - 1) || r<0) {
                    784:                                        printf("Overflow! (%d)\n",r);
                    785:                                        exit(-1); }
                    786: #endif
                    787:                                *(lzh_text_buf+r) = (uchar)c;
                    788:                                r++;
                    789:                                r &= (LZH_N - 1);
                    790:                                count++;
                    791:                        }
                    792:                }
                    793:        }
                    794: /***
                    795:        printf("%12ld\n", count);
                    796: ***/
                    797: 
                    798: #ifdef LZH_DYNAMIC_BUF
                    799:        FREE(lzh_text_buf);
                    800:        FREE(lzh_prnt);
                    801:        FREE(lzh_freq);
                    802:        FREE(lzh_son);
                    803: #endif
                    804: 
                    805: return(count);
                    806: }
                    807: 
                    808: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.