home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / macutils.lzh / MACUTILS / MACUNPACK / lzh.c < prev    next >
C/C++ Source or Header  |  1995-09-18  |  19KB  |  777 lines

  1. #include "macunpack.h"
  2. #ifdef LZH
  3. #include "globals.h"
  4. #include "lzh.h"
  5. #include "crc.h"
  6. #include "../fileio/wrfile.h"
  7. #include "../fileio/machdr.h"
  8. #include "../util/masks.h"
  9. #include "../util/util.h"
  10. #include "bits_be.h"
  11.  
  12. #define LZ5LOOKAHEAD    18    /* look ahead buffer size for LArc */
  13. #define LZ5BUFFSIZE    8192
  14. #define LZ5MASK        8191
  15. #define LZSLOOKAHEAD    17
  16. #define LZSBUFFSIZE    4096
  17. #define LZSMASK        4095
  18. #define LZBUFFSIZE    8192    /* Max of above buffsizes */
  19.  
  20. extern char *malloc();
  21. extern char *realloc();
  22. extern void de_lzah();
  23. extern unsigned char (*lzah_getbyte)();
  24. extern void de_lzh();
  25.  
  26. typedef struct methodinfo {
  27.     char *name;
  28.     int number;
  29. };
  30.  
  31. static struct methodinfo methods[] = {
  32.     {"-lh0-", lh0},
  33.     {"-lh1-", lh1},
  34.     {"-lh2-", lh2},
  35.     {"-lh3-", lh3},
  36.     {"-lh4-", lh4},
  37.     {"-lh5-", lh5},
  38.     {"-lz4-", lz4},
  39.     {"-lz5-", lz5},
  40.     {"-lzs-", lzs}
  41. };
  42. static char *lzh_archive;
  43. static char *lzh_pointer;
  44. static char *lzh_data;
  45. static char *lzh_finfo;
  46. static int lzh_fsize;
  47. static int lzh_kind;
  48. static int oldsize;
  49. static char *lzh_file;
  50. static int lzh_filesize;
  51. static char *lzh_current;
  52. static char *tmp_out_ptr;
  53. static char lzh_lzbuf[LZBUFFSIZE];
  54.  
  55. static int lzh_filehdr();
  56. static int lzh_checkm();
  57. static char *lzh_methname();
  58. static void lzh_wrfile();
  59. static void lzh_skip();
  60. static void lzh_nocomp();
  61. #ifdef UNTESTED
  62. static void lzh_lzss1();
  63. static void lzh_lzss2();
  64. #endif /* UNTESTED */
  65. static void lzh_lzah();
  66. static unsigned char lzh_getbyte();
  67. #ifdef UNDEF
  68. static void lzh_lh2();
  69. static void lzh_lh3();
  70. #endif /* UNDEF */
  71. #ifdef UNTESTED
  72. static void lzh_lzh12();
  73. #endif /* UNTESTED */
  74. static void lzh_lzh13();
  75.  
  76. void lzh(kind)
  77. int kind;
  78. {
  79.     struct fileHdr filehdr;
  80.     int m, i, j;
  81.     char loc_name[64];
  82.     char dirinfo[INFOBYTES];
  83.  
  84.     updcrc = arc_updcrc;
  85.     crcinit = arc_crcinit;
  86.     write_it = 1;
  87.     lzh_fsize = 0;
  88.     lzh_kind = kind;
  89.     if(lzh_archive == NULL) {
  90.     lzh_archive = malloc((unsigned)in_data_size);
  91.     oldsize = in_data_size;
  92.     } else if(in_data_size > oldsize) {
  93.     lzh_archive = realloc(lzh_archive, (unsigned)in_data_size);
  94.     oldsize = in_data_size;
  95.     }
  96.     if(lzh_archive == NULL) {
  97.     (void)fprintf(stderr, "Insufficient memory for archive.\n");
  98.     exit(1);
  99.     }
  100.     if(fread(lzh_archive, 1, in_data_size, infp) != in_data_size) {
  101.     (void)fprintf(stderr, "Can't read archive.\n");
  102. #ifdef SCAN
  103.     do_error("macunpack: Can't read archive");
  104. #endif /* SCAN */
  105.     exit(1);
  106.     }
  107.     lzh_pointer = lzh_archive;
  108.     while(1) {
  109.     if(in_data_size == 0) {
  110.         break;
  111.     }
  112.     if(lzh_filehdr(&filehdr) == 0) {
  113.         break;
  114.     }
  115.     m = lzh_checkm(&filehdr);
  116.     if(m < 0) {
  117.         (void)fprintf(stderr,
  118.             "Skipping file: \"%s\"; unknown method: %.5s.\n",
  119.             text, filehdr.method);
  120.         lzh_skip(&filehdr);
  121.         continue;
  122.     }
  123.     if(!write_it) {
  124.         /*  We are skipping a folder.  Skip the file if lzh_finfo is a
  125.         prefix of or identical to the folder info in the file. */
  126.         if(lzh_fsize <= filehdr.extendsize &&
  127.            !strncmp(lzh_finfo, filehdr.extend, lzh_fsize)) {
  128.         /* It was true, so we skip. */
  129.         lzh_skip(&filehdr);
  130.         continue;
  131.         }
  132.         /*  We have left the folder we were skipping. */
  133.     }
  134.     /*  Now we must leave folders until lzh_finfo is a proper prefix or
  135.         identical to the folder info in the file. */
  136.     while(lzh_fsize > filehdr.extendsize ||
  137.           strncmp(lzh_finfo, filehdr.extend, lzh_fsize)) {
  138.         /*  Not a proper prefix, leave folder.  First determine which! */
  139.         i = lzh_fsize - 1;
  140.         while(--i >= 0 && lzh_finfo[i] != ':');
  141.         i = i + 1;
  142.         transname(lzh_finfo + i, loc_name, lzh_fsize - i - 1);
  143.         lzh_fsize = i;
  144.         if(write_it) {
  145.         indent--;
  146.         if(!info_only) {
  147.             enddir();
  148.         }
  149.         if(list) {
  150.             do_indent(indent);
  151.             (void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name);
  152.         }
  153.         }
  154.         write_it = 1;
  155.     }
  156.     write_it = 1;
  157.     /*  lzh_finfo is a proper prefix or identical, just show so. */
  158.     lzh_finfo = filehdr.extend;
  159.     /*  Now enter directories while lzh_finfo is smaller than extend. */
  160.     while(lzh_fsize < filehdr.extendsize) {
  161.         i = lzh_fsize;
  162.         while(lzh_finfo[++i] != ':');
  163.         transname(lzh_finfo + lzh_fsize, loc_name, i - lzh_fsize);
  164.         for(j = 0; j < INFOBYTES; j++) {
  165.         dirinfo[j] = 0;
  166.         }
  167.         dirinfo[I_NAMEOFF] = i - lzh_fsize;
  168.         copy(dirinfo + I_NAMEOFF + 1, lzh_finfo + lzh_fsize, i - lzh_fsize);
  169.         lzh_fsize = i + 1;
  170.         if(list) {
  171.         do_indent(indent);
  172.         (void)fprintf(stderr, "folder=\"%s\"", loc_name);
  173.         if(query) {
  174.             write_it = do_query();
  175.         } else {
  176.             (void)fputc('\n', stderr);
  177.         }
  178.         if(write_it) {
  179.             indent++;
  180.         }
  181.         }
  182.         if(write_it && !info_only) {
  183.         do_mkdir(loc_name, dirinfo);
  184.         }
  185.         if(!write_it) {
  186.         break;
  187.         }
  188.     }
  189.     if(!write_it) {
  190.         lzh_skip(&filehdr);
  191.     } else {
  192.         lzh_wrfile(&filehdr, m);
  193.     }
  194.     }
  195.     /*  Leaving some more directories! */
  196.     while(lzh_fsize != 0) {
  197.     i = lzh_fsize - 1;
  198.     while(--i >= 0 && lzh_finfo[i] != ':');
  199.     i = i + 1;
  200.     transname(lzh_finfo + i, loc_name, lzh_fsize - i - 1);
  201.     lzh_fsize = i;
  202.     if(write_it) {
  203.     }
  204.     if(write_it) {
  205.         indent--;
  206.         if(!info_only) {
  207.         enddir();
  208.         }
  209.         if(list) {
  210.         do_indent(indent);
  211.         (void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name);
  212.         }
  213.     }
  214.     }
  215. }
  216.  
  217. static int lzh_filehdr(f)
  218. struct fileHdr *f;
  219. {
  220.     register int i;
  221.     char *hdr;
  222.     int c;
  223.     int ext_ptr;
  224.     int chk_sum = 0;
  225.     char *ptr;
  226.  
  227.     if(in_data_size <= 0) {
  228.     return 0;
  229.     }
  230.     for(i = 0; i < INFOBYTES; i++) {
  231.     info[i] = '\0';
  232.     }
  233.     hdr = lzh_pointer;
  234.     in_data_size -= 2;
  235.     lzh_pointer += 2;
  236.     if(in_data_size < 0) {
  237.     in_data_size++;
  238.     }
  239.     f->hsize = (unsigned char)hdr[L_HSIZE];
  240.     if(f->hsize == 0) {
  241.     return 0;
  242.     }
  243.     f->hcrc = (unsigned char)hdr[L_HCRC];
  244.     ptr = hdr + L_METHOD;
  245.     in_data_size -= f->hsize;
  246.     lzh_pointer += f->hsize;
  247.     copy(&(f->method[0]), hdr + L_METHOD, 5);
  248.     f->psize = get4i(hdr + L_PSIZE);
  249.     f->upsize = get4i(hdr + L_UPSIZE);
  250.     f->lastmod = get4i(hdr + L_LASTMOD);
  251.     f->attribute = hdr[L_ATTRIBUTE + 1];
  252.     if(f->attribute < 2) {
  253.     for(i = 0; i < f->hsize; i++) {
  254.         chk_sum += *ptr++;
  255.     }
  256.     chk_sum &= BYTEMASK;
  257.     if(chk_sum != f->hcrc) {
  258.         (void)fprintf(stderr,
  259.             "Header checksum error; got %.2x, must be %.2x.\n",
  260.             chk_sum, f->hcrc);
  261. #ifdef SCAN
  262.         do_error("macunpack: Header checksum error");
  263. #endif /* SCAN */
  264.         exit(1);
  265.     }
  266.     f->nlength = (unsigned char)hdr[L_NLENGTH];
  267.     info[I_NAMEOFF] = f->nlength;
  268.     copy(info + I_NAMEOFF + 1, hdr + L_NAME, (int)f->nlength);
  269.     transname(hdr + L_NAME, text, (int)f->nlength);
  270.     ext_ptr = L_NLENGTH + f->nlength + 1;
  271.     f->crc = get2i(hdr + ext_ptr + L_CRC);
  272.     if(f->attribute == 1) {
  273.         f->etype = hdr[ext_ptr + L_ETYPE];
  274.         f->extendsize = hdr[ext_ptr + L_EXTENDSZ];
  275.         f->extend = hdr + ext_ptr + L_EXTEND;
  276.     } else {
  277.         f->extend = NULL;
  278.         f->extendsize = 0;
  279.     }
  280.     } else if(f->attribute == 2) {
  281.     in_data_size += 2;
  282.     lzh_pointer -= 2;
  283.     f->nlength = hdr[L_2EXTENDSZ] - 3;
  284.     info[I_NAMEOFF] = f->nlength;
  285.     copy(info + I_NAMEOFF + 1, hdr + L_2EXTEND + 2, (int)f->nlength);
  286.     transname(hdr + L_2EXTEND + 2, text, (int)f->nlength);
  287.     ext_ptr = 
  288.     f->crc = get2i(hdr + L_2CRC);
  289.     f->etype = hdr[L_2ETYPE];
  290.     ext_ptr = L_2EXTEND + 2 + f->nlength;
  291.     f->extendsize = hdr[ext_ptr + L_EEXTENDSZ];
  292.     f->extend = hdr + ext_ptr + L_EEXTEND;
  293.     } else {
  294.     (void)fprintf(stderr, "Unknown file header format (%d).\n",
  295.         (int)f->attribute);
  296. #ifdef SCAN
  297.     do_error("macunpack: Unknown file header format");
  298. #endif /* SCAN */
  299.     exit(1);
  300.     }
  301.     if(f->extend != NULL) {
  302.     if(f->extendsize > 5) {
  303.         f->extend += 2;
  304.         hdr = f->extend;
  305.         f->extendsize -= 3;
  306.         for(i = 0; i < f->extendsize; i++) {
  307.         c = *hdr++;
  308.         if((c & BYTEMASK) == BYTEMASK) {
  309.             hdr[-1] = ':';
  310.             c = ':';
  311.         }
  312.         }
  313.         c = *hdr++;
  314.         if(c == 5) {
  315.           hdr += 5;
  316.         }
  317.     } else {
  318.          if(f->extendsize == 5) {
  319.         hdr = f->extend;
  320.         f->extend = NULL;
  321.         f->extendsize = 0;
  322.         hdr += 5;
  323.         } else {
  324.         hdr = f->extend;
  325.         f->extend = NULL;
  326.         f->extendsize = 0;
  327.         }
  328.     }
  329.     } else {
  330.     hdr = hdr + ext_ptr;
  331.     }
  332.     lzh_data = hdr;
  333.     if(f->attribute != 0) {
  334.     lzh_data++;
  335.     }
  336.     return 1;
  337. }
  338.  
  339. static int lzh_checkm(f)
  340. struct fileHdr *f;
  341. {
  342.     int i, nummeth;
  343.     char *meth;
  344.  
  345.     meth = f->method;
  346.     nummeth = sizeof(methods) / sizeof(struct methodinfo);
  347.     for(i = 0; i < nummeth; i++) {
  348.     if(!strncmp(methods[i].name, meth, 5)) {
  349.         return methods[i].number;
  350.     }
  351.     }
  352.     return -1;
  353. }
  354.  
  355. static char *lzh_methname(n)
  356. int n;
  357. {
  358.     if(n > sizeof(methods) / sizeof(struct methodinfo)) {
  359.     return NULL;
  360.     }
  361.     return methods[n].name;
  362. }
  363.  
  364. static void lzh_wrfile(filehdr, method)
  365. struct fileHdr *filehdr;
  366. int method;
  367. {
  368.     char ftype[5], fauth[5];
  369.     int rsrcLength, dataLength;
  370.     int doit;
  371.     char *mname;
  372.     unsigned long crc;
  373.  
  374.     if(filehdr->upsize > lzh_filesize) {
  375.     if(lzh_filesize == 0) {
  376.         lzh_file = malloc((unsigned)filehdr->upsize);
  377.     } else {
  378.         lzh_file = realloc(lzh_file, (unsigned)filehdr->upsize);
  379.     }
  380.     if(lzh_file == NULL) {
  381.         (void)fprintf(stderr, "Insufficient memory to unpack file.\n");
  382.         exit(1);
  383.     }
  384.     }
  385.     switch(method) {
  386.     case lz4:
  387.     lzh_nocomp((unsigned long)128);
  388.     break;
  389. #ifdef UNTESTED
  390.     case lz5:
  391.     lzh_lzss1((unsigned long)128);
  392.     break;
  393.     case lzs:
  394.     lzh_lzss2((unsigned long)128);
  395.     break;
  396. #endif /* UNTESTED */
  397.     case lh0:
  398.     lzh_nocomp((unsigned long)128);
  399.     break;
  400.     case lh1:
  401.     lzh_lzah((unsigned long)128);
  402.     break;
  403. #ifdef UNDEF
  404.     case lh2:
  405.     lzh_lh2((unsigned long)128);
  406.     break;
  407.     case lh3:
  408.     lzh_lh3((unsigned long)128);
  409.     break;
  410. #endif /* UNDEF */
  411. #ifdef UNTESTED
  412.     case lh4:
  413.     lzh_lzh12((unsigned long)128);
  414.     break;
  415. #endif /* UNTESTED */
  416.     case lh5:
  417.     lzh_lzh13((unsigned long)128);
  418.     break;
  419.     default:
  420.     mname = lzh_methname(method);
  421.     if(mname != NULL) {
  422.         do_indent(indent);
  423.         (void)fprintf(stderr,
  424.             "\tSorry, packing method not yet implemented.\n");
  425.         do_indent(indent);
  426.         (void)fprintf(stderr, "File = \"%s\"; ", text);
  427.         (void)fprintf(stderr, "method = %s, skipping file.\n", mname);
  428.         lzh_skip(filehdr);
  429.         return;
  430.     }
  431.     (void)fprintf(stderr,
  432.         "There is something very wrong with this program!\n");
  433. #ifdef SCAN
  434.     do_error("macunpack: program error");
  435. #endif /* SCAN */
  436.     exit(1);
  437.     }
  438.     /* Checks whether everything is packed as MacBinary. */
  439.     if(*lzh_file != 0 /* More checks possible here. */) {
  440.     do_indent(indent);
  441.     (void)fprintf(stderr, "File = \"%s\" ", text);
  442.     (void)fprintf(stderr, "not packed in MacBinary, skipping file.\n");
  443. #ifdef SCAN
  444.     do_error("macunpack: not MacBinary");
  445. #endif /* SCAN */
  446.     lzh_skip(filehdr);
  447.     return;
  448.     }
  449.     copy(info, lzh_file, 128);
  450.     rsrcLength = get4(info + I_RLENOFF);
  451.     dataLength = get4(info + I_DLENOFF);
  452.     transname(info + I_TYPEOFF, ftype, 4);
  453.     transname(info + I_AUTHOFF, fauth, 4);
  454.     if(list) {
  455.     do_indent(indent);
  456.     (void)fprintf(stderr,
  457.         "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
  458.         text, ftype, fauth, (long)dataLength, (long)rsrcLength);
  459.     }
  460.     if(info_only) {
  461.     doit = 0;
  462.     } else {
  463.     doit = 1;
  464.     }
  465.     if(query) {
  466.     doit = do_query();
  467.     } else if(list) {
  468.     (void)fputc('\n', stderr);
  469.     }
  470.     if(doit) {
  471.     define_name(text);
  472.     start_info(info, (unsigned long)rsrcLength, (unsigned long)dataLength);
  473.     }
  474.     switch(method) {
  475.     case lz4:
  476.     if(verbose) {
  477.         (void)fprintf(stderr, "\tNo Compression (%.5s)", filehdr->method);
  478.     }
  479.     if(doit) {
  480.         lzh_nocomp(filehdr->upsize);
  481.     }
  482.     break;
  483. #ifdef UNTESTED
  484.     case lz5:
  485.     if(verbose) {
  486.         (void)fprintf(stderr, "\tLZSS (%.5s) compressed (%4.1f%%)",
  487.             filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
  488.     }
  489.     if(doit) {
  490.         lzh_lzss1(filehdr->upsize);
  491.     }
  492.     break;
  493.     case lzs:
  494.     if(verbose) {
  495.         (void)fprintf(stderr, "\tLZSS (%.5s) compressed (%4.1f%%)",
  496.             filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
  497.     }
  498.     if(doit) {
  499.         lzh_lzss2(filehdr->upsize);
  500.     }
  501.     break;
  502. #endif /* UNTESTED */
  503.     case lh0:
  504.     if(verbose) {
  505.         (void)fprintf(stderr, "\tNo Compression (%.5s)", filehdr->method);
  506.     }
  507.     if(doit) {
  508.         lzh_nocomp(filehdr->upsize);
  509.     }
  510.     break;
  511.     case lh1:
  512.     if(verbose) {
  513.         (void)fprintf(stderr, "\tLZAH (%.5s) compressed (%4.1f%%)",
  514.             filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
  515.     }
  516.     if(doit) {
  517.         lzh_lzah(filehdr->upsize);
  518.     }
  519.     break;
  520. #ifdef UNDEF
  521.     case lh2:
  522.     if(verbose) {
  523.         (void)fprintf(stderr, "\tLZAH (%.5s) compressed (%4.1f%%)",
  524.             filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
  525.     }
  526.     if(doit) {
  527.         lzh_lh2(filehdr->upsize);
  528.     }
  529.     break;
  530.     case lh3:
  531.     if(verbose) {
  532.         (void)fprintf(stderr, "\tLZH (%.5s) compressed (%4.1f%%)",
  533.             filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
  534.     }
  535.     if(doit) {
  536.         lzh_lzh3(filehdr->upsize);
  537.     }
  538.     break;
  539. #endif /* UNDEF */
  540. #ifdef UNTESTED
  541.     case lh4:
  542.     if(verbose) {
  543.         (void)fprintf(stderr, "\tLZH (%.5s) compressed (%4.1f%%)",
  544.             filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
  545.     }
  546.     if(doit) {
  547.         lzh_lzh12(filehdr->upsize);
  548.     }
  549.     break;
  550. #endif /* UNTESTED */
  551.     case lh5:
  552.     if(verbose) {
  553.         (void)fprintf(stderr, "\tLZH (%.5s) compressed (%4.1f%%)",
  554.             filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
  555.     }
  556.     if(doit) {
  557.         lzh_lzh13(filehdr->upsize);
  558.     }
  559.     }
  560.     if(doit) {
  561.     crc = (*updcrc)(INIT_CRC, lzh_file, filehdr->upsize);
  562.     if(filehdr->crc != crc) {
  563.         (void)fprintf(stderr,
  564.             "CRC error on file: need 0x%04x, got 0x%04x\n",
  565.             filehdr->crc, (int)crc);
  566. #ifdef SCAN
  567.         do_error("macunpack: CRC error on file");
  568. #endif /* SCAN */
  569.         exit(1);
  570.     }
  571.     start_data();
  572.     copy(out_ptr, lzh_file + 128, (int)(filehdr->upsize - 128));
  573.     }
  574.     if(verbose) {
  575.     (void)fprintf(stderr, ".\n");
  576.     }
  577.     if(doit) {
  578.     end_file();
  579.     }
  580.     lzh_skip(filehdr);
  581. }
  582.  
  583. static void lzh_skip(filehdr)
  584. struct fileHdr *filehdr;
  585. {
  586.     lzh_pointer += filehdr->psize;
  587.     in_data_size -= filehdr->psize;
  588. }
  589.  
  590. /*---------------------------------------------------------------------------*/
  591. /*    -lz4- and -lh0: No compression                         */
  592. /*---------------------------------------------------------------------------*/
  593. static void lzh_nocomp(obytes)
  594. unsigned long obytes;
  595. {
  596.     copy(lzh_file, lzh_data, (int)obytes);
  597. }
  598.  
  599. #ifdef UNTESTED
  600. /*---------------------------------------------------------------------------*/
  601. /*    -lz5-: LZSS compression, variant 1                     */
  602. /*---------------------------------------------------------------------------*/
  603. static void lzh_lzss1(obytes)
  604. unsigned long obytes;
  605. {
  606.     int mask, ch, lzcnt, lzptr, ptr, count;
  607.     char *p = lzh_lzbuf;
  608.     int i, j;
  609.  
  610.     for(i = 0; i < 256; i++) {
  611.     for(j = 0; j < 13; j++) {
  612.         *p++ = i;
  613.     }
  614.     }
  615.     for(i = 0; i < 256; i++) {
  616.     *p++ = i;
  617.     }
  618.     for(i = 0; i < 256; i++) {
  619.     *p++ = 255 - i;
  620.     }
  621.     for(i = 0; i < 128; i++) {
  622.     *p++ = 0;
  623.     }
  624.     for(i = 0; i < 128; i++) {
  625.     *p++ = ' ';
  626.     }
  627.  
  628.     tmp_out_ptr = out_ptr;
  629.     out_ptr = lzh_file;
  630.     ptr = LZ5BUFFSIZE - LZ5LOOKAHEAD;
  631.     count = 0;
  632.     lzh_current = lzh_data;
  633.     while(obytes != 0) {
  634.     if(count == 0) {
  635.         mask = *lzh_current++ & BYTEMASK;
  636.         count = 8;
  637.     }
  638.     count--;
  639.     ch = *lzh_current++ & BYTEMASK;
  640.     if ((mask & 1) != 0) {
  641.         *out_ptr++ = ch;
  642.         lzh_lzbuf[ptr++] = ch;
  643.         ptr &= LZ5MASK;
  644.         obytes--;
  645.     } else {
  646.         lzcnt = *lzh_current++;
  647.         lzptr = (ch & 0x00ff) | ((lzcnt << 4) & 0x0f00);
  648.         lzcnt = (lzcnt & 0x000f) + 3;
  649.         obytes -= lzcnt;
  650.         do {
  651.         ch = lzh_lzbuf[lzptr++];
  652.         lzh_lzbuf[ptr++] = ch;
  653.         *out_ptr++ = ch;
  654.         lzptr &= LZ5MASK;
  655.         ptr &= LZ5MASK;
  656.         } while (--lzcnt != 0) ;
  657.     }
  658.     mask >>= 1;
  659.     }
  660.     out_ptr = tmp_out_ptr;
  661. }
  662.  
  663. /*---------------------------------------------------------------------------*/
  664. /*    -lzs-: LZSS compression, variant 2                     */
  665. /*---------------------------------------------------------------------------*/
  666. static void lzh_lzss2(obytes)
  667. unsigned long obytes;
  668. {
  669.     int ch, lzcnt, lzptr, ptr, i;
  670.  
  671.     tmp_out_ptr = out_ptr;
  672.     out_ptr = lzh_file;
  673.     ptr = LZSBUFFSIZE - LZSLOOKAHEAD;
  674.     for(i = 0; i < ptr; i++) {
  675.     lzh_lzbuf[i] = ' ';
  676.     }
  677.     for(i = ptr; i < LZSBUFFSIZE; i++) {
  678.     lzh_lzbuf[i] = 0;
  679.     }
  680.     bit_be_init_getbits();
  681.     bit_be_filestart = lzh_data;
  682.     bit_be_inbytes = -1;
  683.     while(obytes != 0) {
  684.     if(bit_be_getbits(1) == 0) {
  685.         ch = bit_be_getbits(8);
  686.         *out_ptr++ = ch;
  687.         lzh_lzbuf[ptr++] = ch;
  688.         ptr &= LZSMASK;
  689.         obytes--;
  690.     } else {
  691.         lzptr = bit_be_getbits(11);
  692.         lzcnt = bit_be_getbits(4) + 3;
  693.         obytes -= lzcnt;
  694.         do {
  695.         ch = lzh_lzbuf[lzptr++];
  696.         lzh_lzbuf[ptr++] = ch;
  697.         *out_ptr++ = ch;
  698.         lzptr &= LZSMASK;
  699.         ptr &= LZSMASK;
  700.         } while (--lzcnt != 0) ;
  701.     }
  702.     }
  703.     out_ptr = tmp_out_ptr;
  704. }
  705. #endif /* UNTESTED */
  706.  
  707. /*---------------------------------------------------------------------------*/
  708. /*    -lh1-: LZ compression plus adaptive Huffman encoding             */
  709. /*---------------------------------------------------------------------------*/
  710. static void lzh_lzah(obytes)
  711. unsigned long obytes;
  712. {
  713.     lzh_current = lzh_data + 2; /* SKIPPING BLOCKSIZE! */
  714.     tmp_out_ptr = out_ptr;
  715.     out_ptr = lzh_file;
  716.     lzah_getbyte = lzh_getbyte;
  717.     de_lzah(obytes);
  718.     out_ptr = tmp_out_ptr;
  719. }
  720.  
  721. static unsigned char lzh_getbyte()
  722. {
  723.     return *lzh_current++;
  724. }
  725.  
  726. #ifdef UNDEF
  727. /*---------------------------------------------------------------------------*/
  728. /*    -lh2-: LZ** compression                             */
  729. /*---------------------------------------------------------------------------*/
  730. static void lzh_lh2(obytes)
  731. unsigned long obytes;
  732. {
  733. }
  734.  
  735. /*---------------------------------------------------------------------------*/
  736. /*    -lh3-: LZ** compression                             */
  737. /*---------------------------------------------------------------------------*/
  738. static void lzh_lh3(obytes)
  739. unsigned long obytes;
  740. {
  741. }
  742. #endif /* UNDEF */
  743.  
  744. #ifdef UNTESTED
  745. /*---------------------------------------------------------------------------*/
  746. /*    -lh4-: LZ(12) compression plus Huffman encoding                 */
  747. /*---------------------------------------------------------------------------*/
  748. static void lzh_lzh12(obytes)
  749. unsigned long obytes;
  750. {
  751.     lzh_current = lzh_data;
  752.     tmp_out_ptr = out_ptr;
  753.     out_ptr = lzh_file;
  754.     /* Controlled by obytes only */
  755.     de_lzh((long)(-1), (long)obytes, &lzh_current, 12);
  756.     out_ptr = tmp_out_ptr;
  757. }
  758. #endif /* UNTESTED */
  759.  
  760. /*---------------------------------------------------------------------------*/
  761. /*    -lh5-: LZ(13) compression plus Huffman encoding                 */
  762. /*---------------------------------------------------------------------------*/
  763. static void lzh_lzh13(obytes)
  764. unsigned long obytes;
  765. {
  766.     lzh_current = lzh_data;
  767.     tmp_out_ptr = out_ptr;
  768.     out_ptr = lzh_file;
  769.     /* Controlled by obytes only */
  770.     de_lzh((long)(-1), (long)obytes, &lzh_current, 13);
  771.     out_ptr = tmp_out_ptr;
  772. }
  773. #else /* LZH */
  774. int lzh; /* keep lint and some compilers happy */
  775. #endif /* LZH */
  776.  
  777.