Annotation of qemu/roms/ipxe/src/util/nrv2b.c, revision 1.1.1.1

1.1       root        1: /**************************************************************
                      2:     Form adapted from lzhuf.c
                      3:     written by Haruyasu Yoshizaki 11/20/1988
                      4:     some minor changes 4/6/1989
                      5:     comments translated by Haruhiko Okumura 4/7/1989
                      6: 
                      7:     minor beautifications and adjustments for compiling under Linux
                      8:     by Markus Gutschke <[email protected]>
                      9:                                                1997-01-27
                     10: 
                     11:     Modifications to allow use as a filter by Ken Yap
                     12:     <[email protected]>.
                     13: 
                     14:                                                1997-07-01
                     15: 
                     16:     Small mod to cope with running on big-endian machines
                     17:     by Jim Hague <[email protected])
                     18:                                                1998-02-06
                     19: 
                     20:     Make compression statistics report shorter
                     21:     by Ken Yap <[email protected]>.
                     22:                                                2001-04-25
                     23: 
                     24:     Replaced algorithm with nrv2b from ucl the compression
                     25:     library from upx.  That code is:
                     26:     Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
                     27:     And is distributed under the terms of the GPL.
                     28:     The conversion was performed 
                     29:     by Eric Biederman <[email protected]>.
                     30:                                              20 August 2002
                     31:                                                 
                     32: **************************************************************/
                     33: #define UCLPACK_COMPAT 0
                     34: #define NDEBUG 1
                     35: #include <stdio.h>
                     36: #include <stdlib.h>
                     37: #include <string.h>
                     38: #include <ctype.h>
                     39: #include <errno.h>
                     40: #ifdef __FreeBSD__
                     41: #include <inttypes.h>
                     42: #else
                     43: #include <stdint.h>
                     44: #endif
                     45: #include <limits.h>
                     46: #include <assert.h>
                     47: #if UCLPACK_COMPAT
                     48: #include <netinet/in.h>
                     49: #endif
                     50: 
                     51: #ifndef VERBOSE
                     52: #define Fprintf(x)
                     53: #define wterr     0
                     54: #else
                     55: #define Fprintf(x) fprintf x
                     56: #endif
                     57: 
                     58: #ifndef MAIN
                     59: extern
                     60: #endif
                     61: FILE  *infile, *outfile;
                     62: 
                     63: #if defined(ENCODE) || defined(DECODE)
                     64: 
                     65: #ifndef ENDIAN
                     66: #define ENDIAN   0
                     67: #endif
                     68: #ifndef BITSIZE
                     69: #define BITSIZE 32
                     70: #endif
                     71: 
                     72: static __inline__ void Error(char *message)
                     73: {
                     74:        Fprintf((stderr, "\n%s\n", message));
                     75:        exit(EXIT_FAILURE);
                     76: }
                     77: 
                     78: /* These will be a complete waste of time on a lo-endian */
                     79: /* system, but it only gets done once so WTF. */
                     80: static unsigned long i86ul_to_host(unsigned long ul)
                     81: {
                     82:        unsigned long res = 0;
                     83:        int i;
                     84:        union
                     85:        {
                     86:                unsigned char c[4];
                     87:                unsigned long ul;
                     88:        } u;
                     89: 
                     90:        u.ul = ul;
                     91:        for (i = 3; i >= 0; i--)
                     92:                res = (res << 8) + u.c[i];
                     93:        return res;
                     94: }
                     95: 
                     96: static unsigned long host_to_i86ul(unsigned long ul)
                     97: {
                     98:        int i;
                     99:        union
                    100:        {
                    101:                unsigned char c[4];
                    102:                unsigned long ul;
                    103:        } u;
                    104: 
                    105:        for (i = 0; i < 4; i++)
                    106:        {
                    107:                u.c[i] = ul & 0xff;
                    108:                ul >>= 8;
                    109:        }
                    110:        return u.ul;
                    111: }
                    112: #endif
                    113: 
                    114: 
                    115: 
                    116: #if UCLPACK_COMPAT
                    117: /* magic file header for compressed files */
                    118: static const unsigned char magic[8] =
                    119: { 0x00, 0xe9, 0x55, 0x43, 0x4c, 0xff, 0x01, 0x1a };
                    120: 
                    121: #endif
                    122: 
                    123: #ifdef ENCODE
                    124: /********** NRV2B_99 compression **********/
                    125: 
                    126: /* Note by limiting the ring buffer I have limited the maximum
                    127:  * offset to 64K.  Since etherboot rarely gets that big it
                    128:  * is not a problem and it gives me a firm guarantee
                    129:  * that I will never get a 3 byte string match that is encodes
                    130:  * to more than 9/8 it's original size.
                    131:  * That guaranteee is important to for the inplace decompressor.
                    132:  * There are better ways to do this if a larger offset and buffer
                    133:  * would give better compression.
                    134:  */
                    135: #define N       (65536ul)           /* size of ring buffer */
                    136: #define THRESHOLD       1           /* lower limit for match length */
                    137: #define F            2048           /* upper limit for match length */
                    138: #define M2_MAX_OFFSET                 0xd00
                    139: 
                    140: /* note: to use default values pass -1, i.e. initialize
                    141:  * this struct by a memset(x,0xff,sizeof(x)) */
                    142: struct ucl_compress_config
                    143: {
                    144:        int bb_endian;
                    145:        int bb_size;
                    146:        unsigned int max_offset;
                    147:        unsigned int max_match;
                    148:        int s_level;
                    149:        int h_level;
                    150:        int p_level;
                    151:        int c_flags;
                    152:        unsigned int m_size;
                    153: };
                    154: 
                    155: struct ucl_compress
                    156: {
                    157:        int init;
                    158: 
                    159:        unsigned int look;          /* bytes in lookahead buffer */
                    160:        
                    161:        unsigned int m_len;
                    162:        unsigned int m_off;
                    163:        
                    164:        unsigned int last_m_len;
                    165:        unsigned int last_m_off;
                    166:        
                    167:        const unsigned char *bp;
                    168:        const unsigned char *ip;
                    169:        const unsigned char *in;
                    170:        const unsigned char *in_end;
                    171:        unsigned char *out;
                    172:        
                    173:        uint64_t bb_b;
                    174:        unsigned bb_k;
                    175:        unsigned bb_c_endian;
                    176:        unsigned bb_c_s;
                    177:        unsigned bb_c_s8;
                    178:        unsigned char *bb_p;
                    179:        unsigned char *bb_op;
                    180:        
                    181:        struct ucl_compress_config conf;
                    182:        unsigned int *result;
                    183: 
                    184:        unsigned int textsize;      /* text size counter */
                    185:        unsigned int codesize;      /* code size counter */
                    186:        unsigned int printcount; /* counter for reporting progress every 1K
                    187:                                    bytes */
                    188: 
                    189:        
                    190:        /* some stats */
                    191:        unsigned long lit_bytes;
                    192:        unsigned long match_bytes;
                    193:        unsigned long rep_bytes;
                    194:        unsigned long lazy;
                    195: };
                    196: 
                    197: 
                    198: 
                    199: #define getbyte(c)  ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
                    200: 
                    201: #define UCL_E_OK               0
                    202: #define UCL_E_INVALID_ARGUMENT 1
                    203: #define UCL_E_OUT_OF_MEMORY    2
                    204: #define UCL_E_ERROR            3
                    205: 
                    206: /***********************************************************************
                    207: //
                    208: ************************************************************************/
                    209: 
                    210: #define SWD_HSIZE      16384
                    211: #define SWD_MAX_CHAIN  2048
                    212: #define SWD_BEST_OFF    1
                    213: 
                    214: #define HEAD3(b,p) \
                    215:     (((0x9f5f*(((((uint32_t)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
                    216: 
                    217: #define HEAD2(b,p)      (b[p] ^ ((unsigned)b[p+1]<<8))
                    218: #define NIL2              UINT_MAX
                    219: 
                    220: struct ucl_swd
                    221: {
                    222: /* public - "built-in" */
                    223:        unsigned int n;
                    224:        unsigned int f;
                    225:        unsigned int threshold;
                    226:        
                    227: /* public - configuration */
                    228:        unsigned int max_chain;
                    229:        unsigned int nice_length;
                    230:        int use_best_off;
                    231:        unsigned int lazy_insert;
                    232:        
                    233: /* public - output */
                    234:        unsigned int m_len;
                    235:        unsigned int m_off;
                    236:        unsigned int look;
                    237:        int b_char;
                    238: #if defined(SWD_BEST_OFF)
                    239:        unsigned int best_off[ SWD_BEST_OFF ];
                    240: #endif
                    241:        
                    242: /* semi public */
                    243:        struct ucl_compress *c;
                    244:        unsigned int m_pos;
                    245: #if defined(SWD_BEST_OFF)
                    246:        unsigned int best_pos[ SWD_BEST_OFF ];
                    247: #endif
                    248:        
                    249: /* private */
                    250:        const uint8_t *dict;
                    251:        const uint8_t *dict_end;
                    252:        unsigned int dict_len;
                    253:        
                    254: /* private */
                    255:        unsigned int ip;                /* input pointer (lookahead) */
                    256:        unsigned int bp;                /* buffer pointer */
                    257:        unsigned int rp;                /* remove pointer */
                    258:        unsigned int b_size;
                    259:        
                    260:        unsigned char *b_wrap;
                    261:        
                    262:        unsigned int node_count;
                    263:        unsigned int first_rp;
                    264: 
                    265:        unsigned char b [ N + F + F ];
                    266:        unsigned int head3 [ SWD_HSIZE ];
                    267:        unsigned int succ3 [ N + F ];
                    268:        unsigned int best3 [ N + F ];
                    269:        unsigned int llen3 [ SWD_HSIZE ];
                    270:        unsigned int head2 [ 65536U ];
                    271: };
                    272: 
                    273: #define s_head3(s,key)        s->head3[key]
                    274: 
                    275: 
                    276: #if !defined( NDEBUG)
                    277: static void assert_match(const struct ucl_swd * swd, unsigned int m_len,
                    278:        unsigned int m_off )
                    279: 
                    280: {
                    281:        const struct ucl_compress *c = swd->c;
                    282:        unsigned int d_off;
                    283:        
                    284:        assert(m_len >= 2);
                    285:        if (m_off <= (unsigned int) (c->bp - c->in))
                    286:        {
                    287:                assert(c->bp - m_off + m_len < c->ip);
                    288:                assert(memcmp(c->bp, c->bp - m_off, m_len) == 0);
                    289:        }
                    290:        else
                    291:        {
                    292:                assert(swd->dict != NULL);
                    293:                d_off = m_off - (unsigned int) (c->bp - c->in);
                    294:                assert(d_off <= swd->dict_len);
                    295:                if (m_len > d_off)
                    296:                {
                    297:                        assert(memcmp(c->bp, swd->dict_end - d_off, d_off) ==
                    298:                                0);
                    299: 
                    300:                        assert(c->in + m_len - d_off < c->ip);
                    301:                        assert(memcmp(c->bp + d_off, c->in, m_len - d_off) ==
                    302:                                0);
                    303: 
                    304:                }
                    305:                else
                    306:                {
                    307:                        assert(memcmp(c->bp, swd->dict_end - d_off, m_len) ==
                    308:                                0);
                    309: 
                    310:                }
                    311:        }
                    312: }
                    313: #else
                    314: #  define assert_match(a,b,c)   ((void)0)
                    315: #endif
                    316: 
                    317: /***********************************************************************
                    318: //
                    319: ************************************************************************/
                    320: 
                    321: 
                    322: static
                    323: void swd_initdict(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
                    324: 
                    325: {
                    326:        s->dict = s->dict_end = NULL;
                    327:        s->dict_len = 0;
                    328: 
                    329:        if (!dict || dict_len <= 0)
                    330:                return;
                    331:        if (dict_len > s->n)
                    332:        {
                    333:                dict += dict_len - s->n;
                    334:                dict_len = s->n;
                    335:        }
                    336: 
                    337:        s->dict = dict;
                    338:        s->dict_len = dict_len;
                    339:        s->dict_end = dict + dict_len;
                    340:        memcpy(s->b,dict,dict_len);
                    341:        s->ip = dict_len;
                    342: }
                    343: 
                    344: 
                    345: static
                    346: void swd_insertdict(struct ucl_swd *s, unsigned int node, unsigned int len)
                    347: {
                    348:        unsigned int key;
                    349: 
                    350:        s->node_count = s->n - len;
                    351:        s->first_rp = node;
                    352: 
                    353:        while (len-- > 0)
                    354:        {
                    355:                key = HEAD3(s->b,node);
                    356:                s->succ3[node] = s_head3(s,key);
                    357:                s->head3[key] = (unsigned int)(node);
                    358:                s->best3[node] = (unsigned int)(s->f + 1);
                    359:                s->llen3[key]++;
                    360:                assert(s->llen3[key] <= s->n);
                    361: 
                    362:                key = HEAD2(s->b,node);
                    363:                s->head2[key] = (unsigned int)(node);
                    364: 
                    365:                node++;
                    366:        }
                    367: }
                    368: 
                    369: /***********************************************************************
                    370: //
                    371: ************************************************************************/
                    372: 
                    373: 
                    374: static
                    375: int swd_init(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
                    376: {
                    377:        unsigned int i = 0;
                    378:        int c = 0;
                    379: 
                    380:        if (s->n == 0)
                    381:                s->n = N;
                    382:        if (s->f == 0)
                    383:                s->f = F;
                    384:        s->threshold = THRESHOLD;
                    385:        if (s->n > N || s->f > F)
                    386:                return UCL_E_INVALID_ARGUMENT;
                    387: 
                    388:        /* defaults */
                    389:        s->max_chain = SWD_MAX_CHAIN;
                    390:        s->nice_length = s->f;
                    391:        s->use_best_off = 0;
                    392:        s->lazy_insert = 0;
                    393: 
                    394:        s->b_size = s->n + s->f;
                    395:        if (s->b_size + s->f >= UINT_MAX)
                    396:                return UCL_E_ERROR;
                    397:        s->b_wrap = s->b + s->b_size;
                    398:        s->node_count = s->n;
                    399: 
                    400:        memset(s->llen3, 0, sizeof(s->llen3[0]) * SWD_HSIZE);
                    401:        for (i = 0; i < 65536U; i++)
                    402:                s->head2[i] = NIL2;
                    403: 
                    404:        s->ip = 0;
                    405:        swd_initdict(s,dict,dict_len);
                    406:        s->bp = s->ip;
                    407:        s->first_rp = s->ip;
                    408: 
                    409:        assert(s->ip + s->f <= s->b_size);
                    410: 
                    411:        s->look = (unsigned int) (s->c->in_end - s->c->ip);
                    412:        if (s->look > 0)
                    413:        {
                    414:                if (s->look > s->f)
                    415:                        s->look = s->f;
                    416:                memcpy(&s->b[s->ip],s->c->ip,s->look);
                    417:                s->c->ip += s->look;
                    418:                s->ip += s->look;
                    419:        }
                    420:        if (s->ip == s->b_size)
                    421:                s->ip = 0;
                    422: 
                    423:        if (s->look >= 2 && s->dict_len > 0)
                    424:                swd_insertdict(s,0,s->dict_len);
                    425: 
                    426:        s->rp = s->first_rp;
                    427:        if (s->rp >= s->node_count)
                    428:                s->rp -= s->node_count;
                    429:        else
                    430:                s->rp += s->b_size - s->node_count;
                    431: 
                    432:        /* unused i */
                    433:        /* unused c */
                    434:        return UCL_E_OK;
                    435: }
                    436: 
                    437: 
                    438: static
                    439: void swd_exit(struct ucl_swd *s)
                    440: {
                    441:        /* unused s */
                    442: 
                    443: }
                    444: 
                    445: #define swd_pos2off(s,pos) \
                    446:        (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
                    447: 
                    448: /***********************************************************************
                    449: //
                    450: ************************************************************************/
                    451: 
                    452: static __inline__
                    453: void swd_getbyte(struct ucl_swd *s)
                    454: {
                    455:        int c;
                    456: 
                    457:        if ((c = getbyte(*(s->c))) < 0)
                    458:        {
                    459:                if (s->look > 0)
                    460:                        --s->look;
                    461:        }
                    462:        else
                    463:        {
                    464:                s->b[s->ip] = (uint8_t)(c);
                    465:                if (s->ip < s->f)
                    466:                        s->b_wrap[s->ip] = (uint8_t)(c);
                    467:        }
                    468:        if (++s->ip == s->b_size)
                    469:                s->ip = 0;
                    470:        if (++s->bp == s->b_size)
                    471:                s->bp = 0;
                    472:        if (++s->rp == s->b_size)
                    473:                s->rp = 0;
                    474: }
                    475: /***********************************************************************
                    476: // remove node from lists
                    477: ************************************************************************/
                    478: 
                    479: static __inline__
                    480: void swd_remove_node(struct ucl_swd *s, unsigned int node)
                    481: {
                    482:        if (s->node_count == 0)
                    483:        {
                    484:                unsigned int key;
                    485:                
                    486: #ifdef UCL_DEBUG
                    487:                if (s->first_rp != UINT_MAX)
                    488:                {
                    489:                        if (node != s->first_rp)
                    490:                                printf("Remove %5d: %5d %5d %5d %5d %6d %6d\n",
                    491: 
                    492:                                        node, s->rp, s->ip, s->bp, s->first_rp,
                    493:                                        s->ip - node, s->ip - s->bp);
                    494:                        assert(node == s->first_rp);
                    495:                        s->first_rp = UINT_MAX;
                    496:                }
                    497: #endif
                    498:                
                    499:                key = HEAD3(s->b,node);
                    500:                assert(s->llen3[key] > 0);
                    501:                --s->llen3[key];
                    502:                
                    503:                key = HEAD2(s->b,node);
                    504:                assert(s->head2[key] != NIL2);
                    505:                if ((unsigned int) s->head2[key] == node)
                    506:                        s->head2[key] = NIL2;
                    507:        }
                    508:        else
                    509:                --s->node_count;
                    510: }
                    511: 
                    512: 
                    513: /***********************************************************************
                    514: //
                    515: ************************************************************************/
                    516: 
                    517: 
                    518: static
                    519: void swd_accept(struct ucl_swd *s, unsigned int n)
                    520: {
                    521:        assert(n <= s->look);
                    522: 
                    523:        if (n > 0) do
                    524:        {
                    525:                unsigned int key;
                    526: 
                    527:                swd_remove_node(s,s->rp);
                    528: 
                    529:                /* add bp into HEAD3 */
                    530:                key = HEAD3(s->b,s->bp);
                    531:                s->succ3[s->bp] = s_head3(s,key);
                    532:                s->head3[key] = (unsigned int)(s->bp);
                    533:                s->best3[s->bp] = (unsigned int)(s->f + 1);
                    534:                s->llen3[key]++;
                    535:                assert(s->llen3[key] <= s->n);
                    536: 
                    537:                /* add bp into HEAD2 */
                    538:                key = HEAD2(s->b,s->bp);
                    539:                s->head2[key] = (unsigned int)(s->bp);
                    540: 
                    541:                swd_getbyte(s);
                    542:        } while (--n > 0);
                    543: }
                    544: 
                    545: /***********************************************************************
                    546: //
                    547: ************************************************************************/
                    548: 
                    549: static
                    550: void swd_search(struct ucl_swd *s, unsigned int node, unsigned int cnt)
                    551: {
                    552:        const unsigned char *p1;
                    553:        const unsigned char *p2;
                    554:        const unsigned char *px;
                    555: 
                    556:        unsigned int m_len = s->m_len;
                    557:        const unsigned char * b  = s->b;
                    558:        const unsigned char * bp = s->b + s->bp;
                    559:        const unsigned char * bx = s->b + s->bp + s->look;
                    560:        unsigned char scan_end1;
                    561:        
                    562:        assert(s->m_len > 0);
                    563:        
                    564:        scan_end1 = bp[m_len - 1];
                    565:        for ( ; cnt-- > 0; node = s->succ3[node])
                    566:        {
                    567:                p1 = bp;
                    568:                p2 = b + node;
                    569:                px = bx;
                    570:                
                    571:                assert(m_len < s->look);
                    572:                
                    573:                if (
                    574:                        p2[m_len - 1] == scan_end1 &&
                    575:                        p2[m_len] == p1[m_len] &&
                    576:                        p2[0] == p1[0] &&
                    577:                        p2[1] == p1[1])
                    578:                {
                    579:                        unsigned int i;
                    580:                        assert(memcmp(bp,&b[node],3) == 0);
                    581:                        
                    582:                        p1 += 2; p2 += 2;
                    583:                        do {} while (++p1 < px && *p1 == *++p2);
                    584:                        i = p1 - bp;
                    585:                        
                    586: #ifdef UCL_DEBUG
                    587:                        if (memcmp(bp,&b[node],i) != 0)
                    588:                                printf("%5ld %5ld %02x%02x %02x%02x\n",
                    589:                                        (long)s->bp, (long) node,
                    590:                                        bp[0], bp[1], b[node], b[node+1]);
                    591: #endif
                    592:                        assert(memcmp(bp,&b[node],i) == 0);
                    593:                        
                    594: #if defined(SWD_BEST_OFF)
                    595:                        if (i < SWD_BEST_OFF)
                    596:                        {
                    597:                                if (s->best_pos[i] == 0)
                    598:                                        s->best_pos[i] = node + 1;
                    599:                        }
                    600: #endif
                    601:                        if (i > m_len)
                    602:                        {
                    603:                                s->m_len = m_len = i;
                    604:                                s->m_pos = node;
                    605:                                if (m_len == s->look)
                    606:                                        return;
                    607:                                if (m_len >= s->nice_length)
                    608:                                        return;
                    609:                                if (m_len > (unsigned int) s->best3[node])
                    610:                                        return;
                    611:                                scan_end1 = bp[m_len - 1];
                    612:                        }
                    613:                }
                    614:        }
                    615: }
                    616: 
                    617: static int swd_search2(struct ucl_swd *s)
                    618: {
                    619:        unsigned int key;
                    620:        
                    621:        assert(s->look >= 2);
                    622:        assert(s->m_len > 0);
                    623:        
                    624:        key = s->head2[ HEAD2(s->b,s->bp) ];
                    625:        if (key == NIL2)
                    626:                return 0;
                    627: #ifdef UCL_DEBUG
                    628:        if (memcmp(&s->b[s->bp],&s->b[key],2) != 0)
                    629:                printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
                    630:                        s->b[s->bp], s->b[s->bp+1], s->b[key], s->b[key+1]);
                    631: #endif
                    632:        assert(memcmp(&s->b[s->bp],&s->b[key],2) == 0);
                    633: #if defined(SWD_BEST_OFF)
                    634:        if (s->best_pos[2] == 0)
                    635:                s->best_pos[2] = key + 1;
                    636: #endif
                    637:        
                    638:        if (s->m_len < 2)
                    639:        {
                    640:                s->m_len = 2;
                    641:                s->m_pos = key;
                    642:        }
                    643:        return 1;
                    644: }
                    645: 
                    646: /***********************************************************************
                    647: //
                    648: ************************************************************************/
                    649: 
                    650: static
                    651: void swd_findbest(struct ucl_swd *s)
                    652: {
                    653:        unsigned int key;
                    654:        unsigned int cnt, node;
                    655:        unsigned int len;
                    656: 
                    657:        assert(s->m_len > 0);
                    658: 
                    659:        /* get current head, add bp into HEAD3 */
                    660:        key = HEAD3(s->b,s->bp);
                    661:        node = s->succ3[s->bp] = s_head3(s,key);
                    662:        cnt = s->llen3[key]++;
                    663:        assert(s->llen3[key] <= s->n + s->f);
                    664:        if (cnt > s->max_chain && s->max_chain > 0)
                    665:                cnt = s->max_chain;
                    666:        s->head3[key] = (unsigned int)(s->bp);
                    667: 
                    668:        s->b_char = s->b[s->bp];
                    669:        len = s->m_len;
                    670:        if (s->m_len >= s->look)
                    671:        {
                    672:                if (s->look == 0)
                    673:                        s->b_char = -1;
                    674:                s->m_off = 0;
                    675:                s->best3[s->bp] = (unsigned int)(s->f + 1);
                    676:        }
                    677:        else
                    678:        {
                    679:                if (swd_search2(s))
                    680:                        if (s->look >= 3)
                    681:                                swd_search(s,node,cnt);
                    682:                if (s->m_len > len)
                    683:                        s->m_off = swd_pos2off(s,s->m_pos);
                    684:                s->best3[s->bp] = (unsigned int)(s->m_len);
                    685: 
                    686: #if defined(SWD_BEST_OFF)
                    687:                if (s->use_best_off)
                    688:                {
                    689:                        int i;
                    690:                        for (i = 2; i < SWD_BEST_OFF; i++)
                    691:                                if (s->best_pos[i] > 0)
                    692:                                        s->best_off[i] =
                    693:                                                swd_pos2off(s,s->best_pos[i]-1);
                    694: 
                    695:                                else
                    696:                                        s->best_off[i] = 0;
                    697:                }
                    698: #endif
                    699:        }
                    700: 
                    701:        swd_remove_node(s,s->rp);
                    702: 
                    703:        /* add bp into HEAD2 */
                    704:        key = HEAD2(s->b,s->bp);
                    705:        s->head2[key] = (unsigned int)(s->bp);
                    706: }
                    707: 
                    708: 
                    709: /***********************************************************************
                    710: //
                    711: ************************************************************************/
                    712: 
                    713: static int
                    714: init_match ( struct ucl_compress *c, struct ucl_swd *s,
                    715:        const uint8_t *dict, unsigned int dict_len,
                    716:        uint32_t flags )
                    717: {
                    718:        int r;
                    719:        
                    720:        assert(!c->init);
                    721:        c->init = 1;
                    722:        
                    723:        s->c = c;
                    724:        
                    725:        c->last_m_len = c->last_m_off = 0;
                    726:        
                    727:        c->textsize = c->codesize = c->printcount = 0;
                    728:        c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
                    729:        c->lazy = 0;
                    730:        
                    731:        r = swd_init(s,dict,dict_len);
                    732:        if (r != UCL_E_OK)
                    733:        {
                    734:                swd_exit(s);
                    735:                return r;
                    736:        }
                    737:        
                    738:        s->use_best_off = (flags & 1) ? 1 : 0;
                    739:        return UCL_E_OK;
                    740: }
                    741: 
                    742: static int
                    743: find_match ( struct ucl_compress *c, struct ucl_swd *s,
                    744:        unsigned int this_len, unsigned int skip )
                    745: {
                    746:        assert(c->init);
                    747:        
                    748:        if (skip > 0)
                    749:        {
                    750:                assert(this_len >= skip);
                    751:                swd_accept(s, this_len - skip);
                    752:                c->textsize += this_len - skip + 1;
                    753:        }
                    754:        else
                    755:        {
                    756:                assert(this_len <= 1);
                    757:                c->textsize += this_len - skip;
                    758:        }
                    759:        
                    760:        s->m_len = THRESHOLD;
                    761: #ifdef SWD_BEST_OFF
                    762:        if (s->use_best_off)
                    763:                memset(s->best_pos,0,sizeof(s->best_pos));
                    764: #endif
                    765:        swd_findbest(s);
                    766:        c->m_len = s->m_len;
                    767:        c->m_off = s->m_off;
                    768:        
                    769:        swd_getbyte(s);
                    770:        
                    771:        if (s->b_char < 0)
                    772:        {
                    773:                c->look = 0;
                    774:                c->m_len = 0;
                    775:                swd_exit(s);
                    776:        }
                    777:        else
                    778:        {
                    779:                c->look = s->look + 1;
                    780:        }
                    781:        c->bp = c->ip - c->look;
                    782:        
                    783: #if 0
                    784:        /* brute force match search */
                    785:        if (c->m_len > THRESHOLD && c->m_len + 1 <= c->look)
                    786:        {
                    787:                const uint8_t *ip = c->bp;
                    788:                const uint8_t *m  = c->bp - c->m_off;
                    789:                const uint8_t *in = c->in;
                    790:                
                    791:                if (ip - in > N)
                    792:                        in = ip - N;
                    793:                for (;;)
                    794:                {
                    795:                        while (*in != *ip)
                    796:                                in++;
                    797:                        if (in == ip)
                    798:                                break;
                    799:                        if (in != m)
                    800:                                if (memcmp(in,ip,c->m_len+1) == 0)
                    801:                                        printf("%p %p %p %5d\n",in,ip,m,c->m_len);
                    802: 
                    803:                        in++;
                    804:                }
                    805:        }
                    806: #endif
                    807:        
                    808:        return UCL_E_OK;
                    809: }
                    810: 
                    811: 
                    812: static int bbConfig(struct ucl_compress *c, int endian, int bitsize)
                    813: {
                    814:        if (endian != -1)
                    815:        {
                    816:                if (endian != 0)
                    817:                        return UCL_E_ERROR;
                    818:                c->bb_c_endian = endian;
                    819:        }
                    820:        if (bitsize != -1)
                    821:        {
                    822:                if (bitsize != 8 && bitsize != 16 && bitsize != 32 && bitsize != 64)
                    823:                        return UCL_E_ERROR;
                    824:                c->bb_c_s = bitsize;
                    825:                c->bb_c_s8 = bitsize / 8;
                    826:        }
                    827:        c->bb_b = 0; c->bb_k = 0;
                    828:        c->bb_p = NULL;
                    829:        c->bb_op = NULL;
                    830:        return UCL_E_OK;
                    831: }
                    832: 
                    833: static void bbWriteBits(struct ucl_compress *c)
                    834: {
                    835:        uint8_t *p = c->bb_p;
                    836:        uint64_t b = c->bb_b;
                    837: 
                    838:        p[0] = (uint8_t)(b >>  0);
                    839:        if (c->bb_c_s >= 16)
                    840:        {
                    841:                p[1] = (uint8_t)(b >>  8);
                    842:                if (c->bb_c_s >= 32)
                    843:                {
                    844:                        p[2] = (uint8_t)(b >> 16);
                    845:                        p[3] = (uint8_t)(b >> 24);
                    846:                        if (c->bb_c_s == 64)
                    847:                        {
                    848:                                p[4] = (uint8_t)(b >> 32);
                    849:                                p[5] = (uint8_t)(b >> 40);
                    850:                                p[6] = (uint8_t)(b >> 48);
                    851:                                p[7] = (uint8_t)(b >> 56);
                    852:                        }
                    853:                }
                    854:        }
                    855: }
                    856: 
                    857: 
                    858: static void bbPutBit(struct ucl_compress *c, unsigned bit)
                    859: {
                    860:        assert(bit == 0 || bit == 1);
                    861:        assert(c->bb_k <= c->bb_c_s);
                    862: 
                    863:        if (c->bb_k < c->bb_c_s)
                    864:        {
                    865:                if (c->bb_k == 0)
                    866:                {
                    867:                        assert(c->bb_p == NULL);
                    868:                        c->bb_p = c->bb_op;
                    869:                        c->bb_op += c->bb_c_s8;
                    870:                }
                    871:                assert(c->bb_p != NULL);
                    872:                assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
                    873: 
                    874:                c->bb_b = (c->bb_b << 1) + bit;
                    875:                c->bb_k++;
                    876:        }
                    877:        else
                    878:        {
                    879:                assert(c->bb_p != NULL);
                    880:                assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
                    881: 
                    882:                bbWriteBits(c);
                    883:                c->bb_p = c->bb_op;
                    884:                c->bb_op += c->bb_c_s8;
                    885:                c->bb_b = bit;
                    886:                c->bb_k = 1;
                    887:        }
                    888: }
                    889: 
                    890: 
                    891: static void bbPutByte(struct ucl_compress *c, unsigned b)
                    892: {
                    893:        /**printf("putbyte %p %p %x  (%d)\n", op, bb_p, x, bb_k);*/
                    894:        assert(c->bb_p == NULL || c->bb_p + c->bb_c_s8 <= c->bb_op);
                    895:        *c->bb_op++ = (uint8_t)(b);
                    896: }
                    897: 
                    898: static void bbFlushBits(struct ucl_compress *c, unsigned filler_bit)
                    899: {
                    900:        if (c->bb_k > 0)
                    901:        {
                    902:                assert(c->bb_k <= c->bb_c_s);
                    903:                while (c->bb_k != c->bb_c_s)
                    904:                        bbPutBit(c, filler_bit);
                    905:                bbWriteBits(c);
                    906:                c->bb_k = 0;
                    907:        }
                    908:        c->bb_p = NULL;
                    909: }
                    910: 
                    911: 
                    912: 
                    913: /***********************************************************************
                    914: //
                    915: ************************************************************************/
                    916: 
                    917: 
                    918: static void code_prefix_ss11(struct ucl_compress *c, uint32_t i)
                    919: {
                    920:        if (i >= 2)
                    921:        {
                    922:                uint32_t t = 4;
                    923:                i += 2;
                    924:                do {
                    925:                        t <<= 1;
                    926:                } while (i >= t);
                    927:                t >>= 1;
                    928:                do {
                    929:                        t >>= 1;
                    930:                        bbPutBit(c, (i & t) ? 1 : 0);
                    931:                        bbPutBit(c, 0);
                    932:                } while (t > 2);
                    933:        }
                    934:        bbPutBit(c, (unsigned)i & 1);
                    935:        bbPutBit(c, 1);
                    936: }
                    937: 
                    938: static void
                    939: code_match(struct ucl_compress *c, unsigned int m_len, const unsigned int m_off)
                    940: 
                    941: {
                    942:        while (m_len > c->conf.max_match)
                    943:        {
                    944:                code_match(c, c->conf.max_match - 3, m_off);
                    945:                m_len -= c->conf.max_match - 3;
                    946:        }
                    947:        
                    948:        c->match_bytes += m_len;
                    949:        if (m_len > c->result[3])
                    950:                c->result[3] = m_len;
                    951:        if (m_off > c->result[1])
                    952:                c->result[1] = m_off;
                    953: 
                    954:        bbPutBit(c, 0);
                    955: 
                    956:        if (m_off == c->last_m_off)
                    957:        {
                    958:                bbPutBit(c, 0);
                    959:                bbPutBit(c, 1);
                    960:        }
                    961:        else
                    962:        {
                    963:                code_prefix_ss11(c, 1 + ((m_off - 1) >> 8));
                    964:                bbPutByte(c, (unsigned)m_off - 1);
                    965:        }
                    966:        m_len = m_len - 1 - (m_off > M2_MAX_OFFSET);
                    967:        if (m_len >= 4)
                    968:        {
                    969:                bbPutBit(c,0);
                    970:                bbPutBit(c,0);
                    971:                code_prefix_ss11(c, m_len - 4);
                    972:        }
                    973:        else
                    974:        {
                    975:                bbPutBit(c, m_len > 1);
                    976:                bbPutBit(c, (unsigned)m_len & 1);
                    977:        }
                    978: 
                    979:        c->last_m_off = m_off;
                    980: }
                    981: 
                    982: static void
                    983: code_run(struct ucl_compress *c, const uint8_t *ii, unsigned int lit)
                    984: {
                    985:        if (lit == 0)
                    986:                return;
                    987:        c->lit_bytes += lit;
                    988:        if (lit > c->result[5])
                    989:                c->result[5] = lit;
                    990:        do {
                    991:                bbPutBit(c, 1);
                    992:                bbPutByte(c, *ii++);
                    993:        } while (--lit > 0);
                    994: }
                    995: 
                    996: /***********************************************************************
                    997: //
                    998: ************************************************************************/
                    999: 
                   1000: static int
                   1001: len_of_coded_match(struct ucl_compress *c, unsigned int m_len, unsigned int
                   1002:        m_off)
                   1003: 
                   1004: {
                   1005:        int b;
                   1006:        if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
                   1007:                || m_off > c->conf.max_offset)
                   1008:                return -1;
                   1009:        assert(m_off > 0);
                   1010:        
                   1011:        m_len = m_len - 2 - (m_off > M2_MAX_OFFSET);
                   1012:        
                   1013:        if (m_off == c->last_m_off)
                   1014:                b = 1 + 2;
                   1015:        else
                   1016:        {
                   1017:                b = 1 + 10;
                   1018:                m_off = (m_off - 1) >> 8;
                   1019:                while (m_off > 0)
                   1020:                {
                   1021:                        b += 2;
                   1022:                        m_off >>= 1;
                   1023:                }
                   1024:        }
                   1025: 
                   1026:        b += 2;
                   1027:        if (m_len < 3)
                   1028:                return b;
                   1029:        m_len -= 3;
                   1030: 
                   1031:        do {
                   1032:                b += 2;
                   1033:                m_len >>= 1;
                   1034:        } while (m_len > 0);
                   1035: 
                   1036:        return b;
                   1037: }
                   1038: 
                   1039: int ucl_nrv2b_99_compress(
                   1040:        const uint8_t *in, unsigned long in_len,
                   1041:        uint8_t *out, unsigned long *out_len,
                   1042:        unsigned int *result)
                   1043: {
                   1044:        const uint8_t *ii;
                   1045:        unsigned int lit;
                   1046:        unsigned int m_len, m_off;
                   1047:        struct ucl_compress c_buffer;
                   1048:        struct ucl_compress * const c = &c_buffer;
                   1049:        struct ucl_swd *swd;
                   1050:        unsigned int result_buffer[16];
                   1051:        int r;
                   1052: 
                   1053: /* max compression */
                   1054: #define SC_TRY_LAZY    2
                   1055: #define SC_GOOD_LENGTH F
                   1056: #define SC_MAX_LAZY    F
                   1057: #define SC_NICE_LENGTH F
                   1058: #define SC_MAX_CHAIN   4096
                   1059: #define SC_FLAGS       1
                   1060: #define SC_MAX_OFFSET  N
                   1061:        
                   1062:        memset(c, 0, sizeof(*c));
                   1063:        c->ip = c->in = in;
                   1064:        c->in_end = in + in_len;
                   1065:        c->out = out;
                   1066:        c->result = result ? result : result_buffer;
                   1067:        memset(c->result, 0, 16*sizeof(*c->result));
                   1068:        c->result[0] = c->result[2] = c->result[4] = UINT_MAX;
                   1069:        result = NULL;
                   1070:        memset(&c->conf, 0xff, sizeof(c->conf));
                   1071:        r = bbConfig(c, ENDIAN, BITSIZE);
                   1072:        if (r == 0)
                   1073:                r = bbConfig(c, c->conf.bb_endian, c->conf.bb_size);
                   1074:        if (r != 0)
                   1075:                return UCL_E_INVALID_ARGUMENT;
                   1076:        c->bb_op = out;
                   1077:        
                   1078:        ii = c->ip;             /* point to start of literal run */
                   1079:        lit = 0;
                   1080:        
                   1081: 
                   1082:        swd = (struct ucl_swd *) malloc(sizeof(*swd));
                   1083:        if (!swd)
                   1084:                return UCL_E_OUT_OF_MEMORY;
                   1085: 
                   1086:        swd->f = F;
                   1087:        swd->n = N;
                   1088:        if (in_len >= 256 && in_len < swd->n)
                   1089:                swd->n = in_len;
                   1090:        if (swd->f < 8 || swd->n < 256)
                   1091:                return UCL_E_INVALID_ARGUMENT;
                   1092: 
                   1093:        r = init_match(c,swd,NULL,0, SC_FLAGS);
                   1094:        if (r != UCL_E_OK)
                   1095:        {
                   1096:                free(swd);
                   1097:                return r;
                   1098:        }
                   1099:        if (SC_MAX_CHAIN > 0)
                   1100:                swd->max_chain = SC_MAX_CHAIN;
                   1101:        if (SC_NICE_LENGTH > 0)
                   1102:                swd->nice_length = SC_NICE_LENGTH;
                   1103:        if (c->conf.max_match < swd->nice_length)
                   1104:                swd->nice_length = c->conf.max_match;
                   1105:        
                   1106:        c->last_m_off = 1;
                   1107:        r = find_match(c,swd,0,0);
                   1108:        if (r != UCL_E_OK)
                   1109:                return r;
                   1110:        while (c->look > 0)
                   1111:        {
                   1112:                unsigned int ahead;
                   1113:                unsigned int max_ahead;
                   1114:                int l1, l2;
                   1115:                
                   1116:                c->codesize = c->bb_op - out;
                   1117:                
                   1118:                m_len = c->m_len;
                   1119:                m_off = c->m_off;
                   1120:                
                   1121:                assert(c->bp == c->ip - c->look);
                   1122:                assert(c->bp >= in);
                   1123:                if (lit == 0)
                   1124:                        ii = c->bp;
                   1125:                assert(ii + lit == c->bp);
                   1126:                assert(swd->b_char == *(c->bp));
                   1127:                
                   1128:                if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
                   1129:                        || m_off > c->conf.max_offset)
                   1130:                {
                   1131:                        /* a literal */
                   1132:                        lit++;
                   1133:                        swd->max_chain = SC_MAX_CHAIN;
                   1134:                        r = find_match(c,swd,1,0);
                   1135:                        assert(r == 0);
                   1136:                        continue;
                   1137:                }
                   1138:                
                   1139:                /* a match */
                   1140:                assert_match(swd,m_len,m_off);
                   1141:                
                   1142:                /* shall we try a lazy match ? */
                   1143:                ahead = 0;
                   1144:                if (SC_TRY_LAZY <= 0 || m_len >= SC_MAX_LAZY || m_off ==
                   1145:                        c->last_m_off)
                   1146: 
                   1147:                {
                   1148:                        /* no */
                   1149:                        l1 = 0;
                   1150:                        max_ahead = 0;
                   1151:                }
                   1152:                else
                   1153:                {
                   1154:                        /* yes, try a lazy match */
                   1155:                        l1 = len_of_coded_match(c,m_len,m_off);
                   1156:                        assert(l1 > 0);
                   1157:                        max_ahead = SC_TRY_LAZY;
                   1158:                        if ((m_len - 1) < max_ahead) {
                   1159:                                max_ahead = m_len -1;
                   1160:                        }
                   1161:                }
                   1162:                
                   1163:                while (ahead < max_ahead && c->look > m_len)
                   1164:                {
                   1165:                        if (m_len >= SC_GOOD_LENGTH)
                   1166:                                swd->max_chain = SC_MAX_CHAIN >> 2;
                   1167:                        else
                   1168:                                swd->max_chain = SC_MAX_CHAIN;
                   1169:                        r = find_match(c,swd,1,0);
                   1170:                        ahead++;
                   1171:                        
                   1172:                        assert(r == 0);
                   1173:                        assert(c->look > 0);
                   1174:                        assert(ii + lit + ahead == c->bp);
                   1175:                        
                   1176:                        if (c->m_len < 2)
                   1177:                                continue;
                   1178:                        l2 = len_of_coded_match(c,c->m_len,c->m_off);
                   1179:                        if (l2 < 0)
                   1180:                                continue;
                   1181:                        if (l1 + (int)(ahead + c->m_len - m_len) * 5 > l2 +
                   1182:                                (int)(ahead) * 9)
                   1183:                        {
                   1184:                                c->lazy++;
                   1185:                                assert_match(swd,c->m_len,c->m_off);
                   1186:                                lit += ahead;
                   1187:                                assert(ii + lit == c->bp);
                   1188:                                goto lazy_match_done;
                   1189:                        }
                   1190:                }
                   1191:                
                   1192:                assert(ii + lit + ahead == c->bp);
                   1193:                
                   1194:                /* 1 - code run */
                   1195:                code_run(c,ii,lit);
                   1196:                lit = 0;
                   1197:                
                   1198:                /* 2 - code match */
                   1199:                code_match(c,m_len,m_off);
                   1200:                swd->max_chain = SC_MAX_CHAIN;
                   1201:                r = find_match(c,swd,m_len,1+ahead);
                   1202:                assert(r == 0);
                   1203:                
                   1204:        lazy_match_done: ;
                   1205:        }
                   1206:        
                   1207:        /* store final run */
                   1208:        code_run(c,ii,lit);
                   1209:        
                   1210:        /* EOF */
                   1211:        bbPutBit(c, 0);
                   1212:        code_prefix_ss11(c, 0x1000000U);
                   1213:        bbPutByte(c, 0xff);
                   1214: 
                   1215:        bbFlushBits(c, 0);
                   1216:        
                   1217:        assert(c->textsize == in_len);
                   1218:        c->codesize = c->bb_op - out;
                   1219:        *out_len = c->bb_op - out;
                   1220:        
                   1221: #if 0
                   1222:        printf("%7ld %7ld -> %7ld   %7ld %7ld   %ld  (max: %d %d %d)\n",
                   1223:                (long) c->textsize, (long) in_len, (long) c->codesize,
                   1224:                c->match_bytes, c->lit_bytes,  c->lazy,
                   1225:                c->result[1], c->result[3], c->result[5]);
                   1226: #endif
                   1227:        assert(c->lit_bytes + c->match_bytes == in_len);
                   1228:        
                   1229:        swd_exit(swd);
                   1230:        free(swd);
                   1231: 
                   1232:        return UCL_E_OK;
                   1233: }
                   1234: 
                   1235: 
                   1236: void Encode(void)  /* compression */
                   1237: {
                   1238:        uint8_t *in, *out;
                   1239:        unsigned long in_len, out_len;
                   1240:        uint32_t tw;
                   1241:        int r;
                   1242:        fseek(infile, 0, SEEK_END);
                   1243:        in_len = ftell(infile);
                   1244: #ifdef VERBOSE
                   1245:        if ((signed long)in_len < 0)
                   1246:                Fprintf((stderr, "Errno: %d", errno));
                   1247: #endif
                   1248: #if UCLPACK_COMPAT
                   1249:        {
                   1250:                uint8_t byte;
                   1251:                if (fwrite(magic, sizeof(magic), 1, outfile) != 1)
                   1252:                        Error("Can't write.");
                   1253:                tw = htonl(0); /* flags */
                   1254:                if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
                   1255:                        Error("Can't write.");
                   1256:                byte = 0x2b;            /* method */
                   1257:                if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
                   1258:                        Error("Can't write.");
                   1259:                byte = 10;              /* level */
                   1260:                if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
                   1261:                        Error("Can't write.");
                   1262:                tw = htonl(256*1024);           /* block_size */
                   1263:                if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
                   1264:                        Error("Can't write.");
                   1265:                tw = htonl(in_len);
                   1266:                if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
                   1267:                        Error("Can't write.");  /* output size of text */
                   1268:        }
                   1269: #else
                   1270:        tw = host_to_i86ul(in_len);
                   1271:        if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
                   1272:                Error("Can't write.");  /* output size of text */
                   1273: #endif 
                   1274:        if (in_len == 0)
                   1275:                return;
                   1276:        rewind(infile);
                   1277: 
                   1278:        in = malloc(in_len);
                   1279:        out_len = in_len + (in_len/8) + 256;
                   1280:        out = malloc(out_len);
                   1281:        if (!in || !out) {
                   1282:                Error("Can't malloc");
                   1283:        }
                   1284:        if (fread(in, in_len, 1, infile) != 1) {
                   1285:                Error("Can't read");
                   1286:        }
                   1287:        r = ucl_nrv2b_99_compress(in, in_len, out, &out_len, 0 );
                   1288:        if (r != UCL_E_OK)
                   1289:                Error("Compression failure\n");
                   1290: #if UCLPACK_COMPAT
                   1291:        tw = htonl(out_len);
                   1292:        if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
                   1293:                Error("Can't write.");  /* file size of text */
                   1294: 
                   1295: #endif
                   1296:        if (fwrite(out, out_len, 1, outfile) != 1) {
                   1297:                Error("Write error\n");
                   1298:        }
                   1299: #if UCLPACK_COMPAT
                   1300:        tw = htonl(0); /* EOF marker */
                   1301:        if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
                   1302:                Error("Can't write.");
                   1303: 
                   1304: #endif
                   1305: 
                   1306: #ifdef LONG_REPORT
                   1307:        Fprintf((stdout, "input size    %ld bytes\n", in_len));
                   1308:        Fprintf((stdout, "output size   %ld bytes\n", out_len));
                   1309:        Fprintf((stdout, "input/output  %.3f\n", (double)in_len / out_len));
                   1310: #else
                   1311:        Fprintf((stdout, "input/output = %ld/%ld = %.3f\n", in_len, out_len,
                   1312:                (double)in_len / out_len));
                   1313: #endif
                   1314:        
                   1315: }
                   1316: 
                   1317: #endif
                   1318: 
                   1319: #ifdef DECODE
                   1320: 
                   1321: #define GETBIT_8(bb, src, ilen) \
                   1322:     (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
                   1323: 
                   1324: #define GETBIT_LE16(bb, src, ilen) \
                   1325:     (bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256u)*2+1)>>16)&1))
                   1326: 
                   1327: #define GETBIT_LE32(bb, src, ilen) \
                   1328:     (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\
                   1329:     bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1))
                   1330: 
                   1331: #define GETBIT_LE64(bb, src, ilen) \
                   1332:     (bc > 0 ? ((bb>>--bc)&1) : (bc=63, \
                   1333:     bb=*(const uint64_t *)((src)+ilen),ilen+=8,(bb>>63)&1))
                   1334: 
                   1335: #if ENDIAN == 0 && BITSIZE == 8
                   1336: #define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen)
                   1337: #endif
                   1338: #if ENDIAN == 0 && BITSIZE == 16
                   1339: #define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen)
                   1340: #endif
                   1341: #if ENDIAN == 0 && BITSIZE == 32
                   1342: #define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen)
                   1343: #endif
                   1344: #if ENDIAN == 0 && BITSIZE == 64
                   1345: #define GETBIT(bb, src, ilen) GETBIT_LE64(bb, src, ilen)
                   1346: #endif
                   1347: #ifndef GETBIT
                   1348: #error "Bad Combination of ENDIAN and BITSIZE values specified"
                   1349: #endif
                   1350: 
                   1351: #undef SAFE
                   1352: 
                   1353: #ifdef SAFE
                   1354: #define FAIL(x,r)   if (x) { Error(r); }
                   1355: #else
                   1356: #define FAIL(x,r)
                   1357: #endif
                   1358: 
                   1359: void Decode(void)  /* recover */
                   1360: {
                   1361:        uint32_t tw;
                   1362:        uint8_t *src, *dst;
                   1363:        unsigned long max_src_len, src_len, dst_len;
                   1364:        unsigned long ilen = 0, olen = 0, last_m_off =  1;
                   1365: #if BITSIZE <= 32
                   1366:        uint32_t bb = 0;
                   1367: #elif BITSIZE == 64
                   1368:        uint64_t bb = 0;
                   1369: #endif
                   1370:        unsigned bc = 0;
                   1371: #if UCLPACK_COMPAT
                   1372:        if (fseek(infile, sizeof(magic) + sizeof(tw) + 1 + 1 + sizeof(tw),
                   1373:                SEEK_SET) != 0)
                   1374: 
                   1375:                Error("Seek Error");
                   1376:        if (fread(&tw, sizeof(tw), 1, infile) < 1)
                   1377:                Error("Can't read"); /* read size of text */
                   1378:        dst_len = ntohl(tw);
                   1379:        if (fread(&tw, sizeof(tw), 1, infile) < 1)
                   1380:                Error("Can't read"); /* read size of file */
                   1381:        max_src_len = ntohl(tw);
                   1382: #else
                   1383:        if (fread(&tw, sizeof(tw), 1, infile) < 1)
                   1384:                Error("Can't read"); /* read size of text */
                   1385:        dst_len = i86ul_to_host(tw);
                   1386:        max_src_len = dst_len + (dst_len/8) + 256;
                   1387: #endif
                   1388:        if (dst_len == 0)
                   1389:                return;
                   1390:        dst = malloc(dst_len);
                   1391:        if (!dst)
                   1392:                Error("Can't malloc");
                   1393:        src = malloc(max_src_len);
                   1394:        if (!src)
                   1395:                Error("Can't malloc");
                   1396:        src_len = fread(src, 1, max_src_len, infile);
                   1397:        if (src_len <= 0) 
                   1398:                Error("Can't read");
                   1399: 
                   1400:        for(;;) {
                   1401:                unsigned int m_off, m_len;
                   1402:                while(GETBIT(bb, src, ilen)) {
                   1403:                        FAIL(ilen >= src_len, "input overrun");
                   1404:                        FAIL(olen >= dst_len, "output  overrun");
                   1405:                        dst[olen++] = src[ilen++];
                   1406:                }
                   1407:                m_off = 1;
                   1408:                do {
                   1409:                        m_off = m_off*2 + GETBIT(bb, src, ilen);
                   1410:                        FAIL(ilen >= src_len, "input overrun");
                   1411:                        FAIL(m_off > 0xffffffU +3, "lookbehind overrun");
                   1412:                } while (!GETBIT(bb, src, ilen));
                   1413:                if (m_off == 2)
                   1414:                {
                   1415:                        m_off = last_m_off;
                   1416:                }
                   1417:                else
                   1418:                {
                   1419:                        FAIL(ilen >= src_len, "input overrun");
                   1420:                        m_off = (m_off - 3)*256 + src[ilen++];
                   1421:                        if (m_off == 0xffffffffU)
                   1422:                                break;
                   1423:                        last_m_off = ++m_off;
                   1424:                }
                   1425:                m_len = GETBIT(bb, src, ilen);
                   1426:                m_len = m_len*2 + GETBIT(bb, src, ilen);
                   1427:                if (m_len == 0) 
                   1428:                {
                   1429:                        m_len++;
                   1430:                        do {
                   1431:                                m_len = m_len*2 + GETBIT(bb, src, ilen);
                   1432:                                FAIL(ilen >= src_len, "input overrun");
                   1433:                                FAIL(m_len >= dst_len, "output overrun");
                   1434:                        } while(!GETBIT(bb, src, ilen));
                   1435:                        m_len += 2;
                   1436:                }
                   1437:                m_len += (m_off > 0xd00);
                   1438:                FAIL(olen + m_len > dst_len, "output overrun");
                   1439:                FAIL(m_off > olen, "lookbeind overrun");
                   1440:                {
                   1441:                        const uint8_t *m_pos;
                   1442:                        m_pos = dst + olen - m_off;
                   1443:                        dst[olen++] = *m_pos++;
                   1444:                        do {
                   1445:                                dst[olen++] = *m_pos++;
                   1446:                        } while(--m_len > 0);
                   1447:                }
                   1448:        }
                   1449:        FAIL(ilen < src_len, "input not consumed");
                   1450:        FAIL(ilen > src_len, "input overrun");
                   1451:        assert(ilen == src_len);
                   1452:        Fprintf((stderr, "%12ld\n", olen));
                   1453:        if (dst_len != olen) {
                   1454:                fprintf(stderr, "length != expected length\n");
                   1455:        }
                   1456:        if (fwrite(dst, olen, 1, outfile) != 1)
                   1457:                Error("Write error\n");
                   1458:        free(src);
                   1459:        free(dst);
                   1460: }
                   1461: #endif
                   1462: 
                   1463: #ifdef MAIN
                   1464: int main(int argc, char *argv[])
                   1465: {
                   1466:        char  *s;
                   1467:        FILE  *f;
                   1468:        int    c;
                   1469:        
                   1470:        if (argc == 2) {
                   1471:                outfile = stdout;
                   1472:                if ((f = tmpfile()) == NULL) {
                   1473:                        perror("tmpfile");
                   1474:                        return EXIT_FAILURE;
                   1475:                }
                   1476:                while ((c = getchar()) != EOF)
                   1477:                        fputc(c, f);
                   1478:                rewind(infile = f);
                   1479:        }
                   1480:        else if (argc != 4) {
                   1481:                Fprintf((stderr, "'nrv2b e file1 file2' encodes file1 into file2.\n"
                   1482:                        "'nrv2b d file2 file1' decodes file2 into file1.\n"));
                   1483:                return EXIT_FAILURE;
                   1484:        }
                   1485:        if (argc == 4) {
                   1486:                if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
                   1487:                        || (s = argv[2], (infile  = fopen(s, "rb")) == NULL)
                   1488:                        || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
                   1489:                        Fprintf((stderr, "??? %s\n", s));
                   1490:                        return EXIT_FAILURE;
                   1491:                }
                   1492:        }
                   1493:        if (toupper(*argv[1]) == 'E')
                   1494:                Encode();
                   1495:        else
                   1496:                Decode();
                   1497:        fclose(infile);
                   1498:        fclose(outfile);
                   1499:        return EXIT_SUCCESS;
                   1500: }
                   1501: #endif

unix.superglobalmegacorp.com

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