Annotation of sbbs/sbbs3/lzh.c, revision 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.