home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 13 / AACD13.ISO / AACD / Utilities / UnLZX2 / src / unlzx.c next >
C/C++ Source or Header  |  2000-08-02  |  35KB  |  1,303 lines

  1. /*
  2. **  LZX Extract in (supposedly) portable C.
  3. **
  4. **  Based on unlzx 1.0 by David Tritscher.
  5. **  Rewritten by Oliver Gantert <lucyg@t-online.de>
  6. **
  7. **  Compiled with vbcc/Amiga and lcc/Win32
  8. */
  9.  
  10. #include "unlzx.h"
  11.  
  12. #ifdef AMIGA
  13. static unsigned char *version_string = "$VER: UnLZX " UNLZX_VERSION " (" UNLZX_VERDATE ")";
  14. #endif
  15.  
  16. #ifndef PMATCH_MAXSTRLEN
  17. #define PMATCH_MAXSTRLEN  1024    /*  max string length  */
  18. #endif
  19.  
  20. unsigned char match_pattern[256] = { '*', '\0' };
  21. signed long use_outdir = 0;
  22. unsigned char output_dir[768] = { '\0' };
  23. unsigned char work_buffer[1024];
  24.  
  25. signed long mode;
  26.  
  27. unsigned char info_header[10];
  28. unsigned char archive_header[31];
  29. unsigned char header_filename[256];
  30. unsigned char header_comment[256];
  31.  
  32. unsigned long pack_size;
  33. unsigned long unpack_size;
  34.  
  35. unsigned long crc;
  36. unsigned long year, month, day;
  37. unsigned long hour, minute, second;
  38. unsigned char attributes;
  39. unsigned char pack_mode;
  40.  
  41. struct filename_node *filename_list;
  42.  
  43. unsigned char read_buffer[16384];
  44. unsigned char decrunch_buffer[66560];
  45.  
  46. unsigned char *source;
  47. unsigned char *destination;
  48. unsigned char *source_end;
  49. unsigned char *destination_end;
  50.  
  51. unsigned long decrunch_method;
  52. unsigned long decrunch_length;
  53. unsigned long last_offset;
  54. unsigned long global_control;
  55. signed long global_shift;
  56.  
  57. unsigned char offset_len[8];
  58. unsigned short offset_table[128];
  59. unsigned char huffman20_len[20];
  60. unsigned short huffman20_table[96];
  61. unsigned char literal_len[768];
  62. unsigned short literal_table[5120];
  63.  
  64. const unsigned char *month_str[16] =
  65. {
  66.   "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug",
  67.   "sep", "oct", "nov", "dec", "?13", "?14", "?15", "?16"
  68. };
  69.  
  70. unsigned long sum;
  71.  
  72. const unsigned long crc_table[256] =
  73. {
  74.   0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
  75.   0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
  76.   0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
  77.   0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
  78.   0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
  79.   0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
  80.   0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
  81.   0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
  82.   0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
  83.   0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
  84.   0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
  85.   0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
  86.   0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
  87.   0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
  88.   0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
  89.   0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
  90.   0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
  91.   0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
  92.   0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
  93.   0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
  94.   0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
  95.   0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
  96.   0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
  97.   0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
  98.   0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
  99.   0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
  100.   0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
  101.   0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
  102.   0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
  103.   0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
  104.   0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
  105.   0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
  106.   0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
  107.   0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
  108.   0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
  109.   0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
  110.   0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
  111.   0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
  112.   0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
  113.   0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
  114.   0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
  115.   0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
  116.   0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
  117. };
  118.  
  119. const unsigned char table_one[32] =
  120. {
  121.   0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
  122.   0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06,
  123.   0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a,
  124.   0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e
  125. };
  126.  
  127. const unsigned long table_two[32]=
  128. {
  129.   0,    1,    2,    3,
  130.   4,    6,    8,    12,
  131.   16,   24,   32,   48,
  132.   64,   96,   128,  192,
  133.   256,  384,  512,  768,
  134.   1024, 1536, 2048, 3072,
  135.   4096, 6144, 8192, 12288,
  136.   16384,24576,32768,49152
  137. };
  138.  
  139. const unsigned long table_three[16]=
  140. {
  141.   0,    1,    3,    7,
  142.   15,   31,   63,   127,
  143.   255,  511,  1023, 2047,
  144.   4095, 8191, 16383,32767
  145. };
  146.  
  147. const unsigned char table_four[34]=
  148. {
  149.   0,    1,    2,    3,
  150.   4,    5,    6,    7,
  151.   8,    9,    10,   11,
  152.   12,   13,   14,   15,
  153.   16,   0,    1,    2,
  154.   3,    4,    5,    6,
  155.   7,    8,    9,    10,
  156.   11,   12,   13,   14,
  157.   15,   16
  158. };
  159.  
  160. /* -------------------------------------------------------------------------- */
  161.  
  162. int pmatch(const char *mask, const char *name)
  163. {
  164.   int           calls = 0,
  165.                 wild  = 0,
  166.                 q     = 0;
  167.   const char  * m     = mask,
  168.               * n     = name,
  169.               * ma    = mask,
  170.               * na    = name;
  171.  
  172.   for(;;)
  173.   {
  174.     if (++calls > PMATCH_MAXSTRLEN) return(1);
  175.     if (*m == '*')
  176.     {
  177.       while (*m == '*') ++m;
  178.       wild = 1;
  179.       ma = m;
  180.       na = n;
  181.     }
  182.     if (!*m)
  183.     {
  184.       if (!*n) return(0);
  185.       for (--m; (m > mask) && (*m == '?'); --m);
  186.       if ((*m == '*') && (m > mask) && (m[-1] != '\\')) return(0);
  187.       if (!wild) return(1);
  188.       m = ma;
  189.     }
  190.     else if (!*n)
  191.     {
  192.       while(*m == '*') ++m;
  193.       return(*m != 0);
  194.     }
  195.     if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
  196.     {
  197.       ++m;
  198.       q = 1;
  199.     }
  200.     else
  201.     {
  202.       q = 0;
  203.     }
  204.     if ((tolower(*m) != tolower(*n)) && ((*m != '?') || q))
  205.     {
  206.       if (!wild) return(1);
  207.       m = ma;
  208.       n = ++na;
  209.     }
  210.     else
  211.     {
  212.       if (*m) ++m;
  213.       if (*n) ++n;
  214.     }
  215.   }
  216. }
  217.  
  218. void just_wait(void)
  219. {
  220.   /*
  221.       Under certain conditions UnLZX needs to wait
  222.       some cycles for disk access to finish. This
  223.       only seems to happen on fast CPUs, but it
  224.       doesn't hurt anyway...
  225.   */
  226. }
  227.  
  228. unsigned long argopt(unsigned char * ao_strg, unsigned long ao_argc, unsigned char **ao_argv)
  229. {
  230.   while(ao_argc > 1)
  231.   {
  232.     if (!strcmp(ao_strg, ao_argv[ao_argc - 1]))
  233.       return(ao_argc - 1);
  234.     ao_argc--;
  235.   }
  236.   return(0);
  237. }
  238.  
  239. void crc_calc(unsigned char *memory, unsigned long length)
  240. {
  241.   unsigned long temp;
  242.  
  243.   if (length)
  244.   {
  245.     temp = ~sum;
  246.     do
  247.     {
  248.       temp = crc_table[(*memory++ ^ temp) & 255] ^ (temp >> 8);
  249.     } while(--length);
  250.     sum = ~temp;
  251.   }
  252. }
  253.  
  254. signed long make_decode_table(signed long number_symbols, signed long table_size, unsigned char *length, unsigned short *table)
  255. {
  256.   unsigned char bit_num = 0;
  257.   signed long symbol, abort = 0;
  258.   unsigned long leaf, table_mask, bit_mask, pos, fill, next_symbol, reverse;
  259.  
  260.   pos = 0;
  261.   table_mask = 1 << table_size;
  262.   bit_mask = table_mask >> 1;
  263.   bit_num++;
  264.   while ((!abort) && (bit_num <= table_size))
  265.   {
  266.     for (symbol = 0; symbol < number_symbols; symbol++)
  267.     {
  268.       if (length[symbol] == bit_num)
  269.       {
  270.         reverse = pos;
  271.         leaf = 0;
  272.         fill = table_size;
  273.         do
  274.         {
  275.           leaf = (leaf << 1)+(reverse & 1);
  276.           reverse >>= 1;
  277.         } while (--fill);
  278.         if ((pos += bit_mask) > table_mask)
  279.         {
  280.           abort = 1;
  281.           break;
  282.         }
  283.         fill = bit_mask;
  284.         next_symbol = 1 << bit_num;
  285.         do
  286.         {
  287.           table[leaf] = symbol;
  288.           leaf += next_symbol;
  289.         } while (--fill);
  290.       }
  291.     }
  292.     bit_mask >>= 1;
  293.     bit_num++;
  294.   }
  295.   if ((!abort) && (pos != table_mask))
  296.   {
  297.     for (symbol = pos; symbol < table_mask; symbol++)
  298.     {
  299.       reverse = symbol;
  300.       leaf = 0;
  301.       fill = table_size;
  302.       do
  303.       {
  304.         leaf = (leaf << 1)+(reverse & 1);
  305.         reverse >>= 1;
  306.       } while (--fill);
  307.       table[leaf] = 0;
  308.     }
  309.     next_symbol = table_mask >> 1;
  310.     pos <<= 16;
  311.     table_mask <<= 16;
  312.     bit_mask = 32768;
  313.     while((!abort) && (bit_num <= 16))
  314.     {
  315.       for(symbol = 0; symbol < number_symbols; symbol++)
  316.       {
  317.         if (length[symbol] == bit_num)
  318.         {
  319.           reverse = pos >> 16;
  320.           leaf = 0;
  321.           fill = table_size;
  322.           do
  323.           {
  324.             leaf = (leaf << 1)+(reverse & 1);
  325.             reverse >>= 1;
  326.           } while (--fill);
  327.           for (fill = 0; fill < bit_num - table_size; fill++)
  328.           {
  329.             if (!table[leaf])
  330.             {
  331.               table[(next_symbol << 1)] = 0;
  332.               table[(next_symbol << 1) + 1] = 0;
  333.               table[leaf] = next_symbol++;
  334.             }
  335.             leaf = table[leaf] << 1;
  336.             leaf += (pos >> (15 - fill)) & 1;
  337.           }
  338.           table[leaf] = symbol;
  339.           if ((pos += bit_mask) > table_mask)
  340.           {
  341.             abort = 1;
  342.             break;
  343.           }
  344.         }
  345.       }
  346.       bit_mask >>= 1;
  347.       bit_num++;
  348.     }
  349.   }
  350.   if (pos != table_mask) abort = 1;
  351.   return(abort);
  352. }
  353.  
  354. signed long read_literal_table(void)
  355. {
  356.   signed long shift = global_shift, abort = 0;
  357.   unsigned long control = global_control, temp, symbol, pos, count, fix, max_symbol;
  358.  
  359.   if (shift < 0)
  360.   {
  361.     shift += 16;
  362.     control += *source++ << (8 + shift);
  363.     control += *source++ << shift;
  364.   }
  365.   decrunch_method = control & 7;
  366.   control >>= 3;
  367.   if ((shift -= 3) < 0)
  368.   {
  369.     shift += 16;
  370.     control += *source++ << (8 + shift);
  371.     control += *source++ << shift;
  372.   }
  373.   if ((!abort) && (decrunch_method == 3))
  374.   {
  375.     for (temp = 0; temp < 8; temp++)
  376.     {
  377.       offset_len[temp] = control & 7;
  378.       control >>= 3;
  379.       if ((shift -= 3) < 0)
  380.       {
  381.         shift += 16;
  382.         control += *source++ << (8 + shift);
  383.         control += *source++ << shift;
  384.       }
  385.     }
  386.     abort = make_decode_table(8, 7, offset_len, offset_table);
  387.   }
  388.   if (!abort)
  389.   {
  390.     decrunch_length = (control & 255) << 16;
  391.     control >>= 8;
  392.     if ((shift -= 8) < 0)
  393.     {
  394.       shift += 16;
  395.       control += *source++ << (8 + shift);
  396.       control += *source++ << shift;
  397.     }
  398.     decrunch_length += (control & 255) << 8;
  399.     control >>= 8;
  400.     if ((shift -= 8) < 0)
  401.     {
  402.       shift += 16;
  403.       control += *source++ << (8 + shift);
  404.       control += *source++ << shift;
  405.     }
  406.     decrunch_length += (control & 255);
  407.     control >>= 8;
  408.     if ((shift -= 8) < 0)
  409.     {
  410.       shift += 16;
  411.       control += *source++ << (8 + shift);
  412.       control += *source++ << shift;
  413.     }
  414.   }
  415.   if ((!abort) && (decrunch_method != 1))
  416.   {
  417.     pos = 0;
  418.     fix = 1;
  419.     max_symbol = 256;
  420.     do
  421.     {
  422.       for (temp = 0; temp < 20; temp++)
  423.       {
  424.         huffman20_len[temp] = control & 15;
  425.         control >>= 4;
  426.         if ((shift -= 4) < 0)
  427.         {
  428.           shift += 16;
  429.           control += *source++ << (8 + shift);
  430.           control += *source++ << shift;
  431.         }
  432.       }
  433.       if (abort = make_decode_table(20, 6, huffman20_len, huffman20_table)) break;
  434.       do
  435.       {
  436.         if ((symbol = huffman20_table[control & 63]) >= 20)
  437.         {
  438.           do
  439.           {
  440.             symbol = huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  441.             if (!shift--)
  442.             {
  443.               shift += 16;
  444.               control += *source++ << 24;
  445.               control += *source++ << 16;
  446.             }
  447.             control >>= 1;
  448.           } while(symbol >= 20);
  449.           temp = 6;
  450.         }
  451.         else
  452.         {
  453.           temp = huffman20_len[symbol];
  454.         }
  455.         control >>= temp;
  456.         if ((shift -= temp) < 0)
  457.         {
  458.           shift += 16;
  459.           control += *source++ << (8 + shift);
  460.           control += *source++ << shift;
  461.         }
  462.         switch(symbol)
  463.         {
  464.           case 17:
  465.           case 18:
  466.             if(symbol == 17)
  467.             {
  468.               temp = 4;
  469.               count = 3;
  470.             }
  471.             else
  472.             {
  473.               temp = 6 - fix;
  474.               count = 19;
  475.             }
  476.             count += (control & table_three[temp]) + fix;
  477.             control >>= temp;
  478.             if ((shift -= temp) < 0)
  479.             {
  480.               shift += 16;
  481.               control += *source++ << (8 + shift);
  482.               control += *source++ << shift;
  483.             }
  484.             while ((pos < max_symbol) && (count--)) literal_len[pos++] = 0;
  485.           break;
  486.           case 19:
  487.             count = (control & 1) + 3 + fix;
  488.             if (!shift--)
  489.             {
  490.               shift += 16;
  491.               control += *source++ << 24;
  492.               control += *source++ << 16;
  493.             }
  494.             control >>= 1;
  495.             if ((symbol = huffman20_table[control & 63]) >= 20)
  496.             {
  497.               do
  498.               {
  499.                 symbol = huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  500.                 if (!shift--)
  501.                 {
  502.                   shift += 16;
  503.                   control += *source++ << 24;
  504.                   control += *source++ << 16;
  505.                 }
  506.                 control >>= 1;
  507.               } while(symbol >= 20);
  508.               temp = 6;
  509.             }
  510.             else
  511.             {
  512.               temp = huffman20_len[symbol];
  513.             }
  514.             control >>= temp;
  515.             if ((shift -= temp) < 0)
  516.             {
  517.               shift += 16;
  518.               control += *source++ << (8 + shift);
  519.               control += *source++ << shift;
  520.             }
  521.             symbol = table_four[literal_len[pos] + 17 - symbol];
  522.             while ((pos < max_symbol) && (count--)) literal_len[pos++] = symbol;
  523.           break;
  524.           default:
  525.             symbol = table_four[literal_len[pos] + 17 - symbol];
  526.             literal_len[pos++] = symbol;
  527.           break;
  528.         }
  529.       } while(pos < max_symbol);
  530.       fix--;
  531.       max_symbol += 512;
  532.     } while(max_symbol == 768);
  533.     if(!abort) abort = make_decode_table(768, 12, literal_len, literal_table);
  534.   }
  535.   global_control = control;
  536.   global_shift = shift;
  537.   return(abort);
  538. }
  539.  
  540. void decrunch(void)
  541. {
  542.   unsigned long control = global_control, temp, symbol, count;
  543.   signed long shift = global_shift;
  544.   unsigned char *string;
  545.  
  546.   do
  547.   {
  548.     if ((symbol = literal_table[control & 4095]) >= 768)
  549.     {
  550.       control >>= 12;
  551.       if ((shift -= 12) < 0)
  552.       {
  553.         shift += 16;
  554.         control += *source++ << (8 + shift);
  555.         control += *source++ << shift;
  556.       }
  557.       do
  558.       {
  559.         symbol = literal_table[(control & 1) + (symbol << 1)];
  560.         if (!shift--)
  561.         {
  562.           shift += 16;
  563.           control += *source++ << 24;
  564.           control += *source++ << 16;
  565.         }
  566.         control >>= 1;
  567.       } while(symbol >= 768);
  568.     }
  569.     else
  570.     {
  571.       temp = literal_len[symbol];
  572.       control >>= temp;
  573.       if ((shift -= temp) < 0)
  574.       {
  575.         shift += 16;
  576.         control += *source++ << (8 + shift);
  577.         control += *source++ << shift;
  578.       }
  579.     }
  580.     if (symbol < 256)
  581.     {
  582.       *destination++ = symbol;
  583.     }
  584.     else
  585.     {
  586.       symbol -= 256;
  587.       count = table_two[temp = symbol & 31];
  588.       temp = table_one[temp];
  589.       if ((temp >= 3) && (decrunch_method == 3))
  590.       {
  591.         temp -= 3;
  592.         count += ((control & table_three[temp]) << 3);
  593.         control >>= temp;
  594.         if ((shift -= temp) < 0)
  595.         {
  596.           shift += 16;
  597.           control += *source++ << (8 + shift);
  598.           control += *source++ << shift;
  599.         }
  600.         count += (temp = offset_table[control & 127]);
  601.         temp = offset_len[temp];
  602.       }
  603.       else
  604.       {
  605.         count += control & table_three[temp];
  606.         if (!count) count = last_offset;
  607.       }
  608.       control >>= temp;
  609.       if ((shift -= temp) < 0)
  610.       {
  611.         shift += 16;
  612.         control += *source++ << (8 + shift);
  613.         control += *source++ << shift;
  614.       }
  615.       last_offset = count;
  616.       count = table_two[temp = (symbol >> 5) & 15] + 3;
  617.       temp = table_one[temp];
  618.       count += (control & table_three[temp]);
  619.       control >>= temp;
  620.       if ((shift -= temp) < 0)
  621.       {
  622.         shift += 16;
  623.         control += *source++ << (8 + shift);
  624.         control += *source++ << shift;
  625.       }
  626.       string = (decrunch_buffer + last_offset < destination) ? destination - last_offset : destination + 65536 - last_offset;
  627.       do
  628.       {
  629.         *destination++ = *string++;
  630.       } while(--count);
  631.     }
  632.   } while((destination < destination_end) && (source < source_end));
  633.   global_control = control;
  634.   global_shift = shift;
  635. }
  636.  
  637. FILE *open_output(unsigned char * filename)
  638. {
  639.   unsigned long temp;
  640.   FILE *file;
  641.  
  642.   if (!(file = fopen(filename, "wb")))
  643.   {
  644.     for(temp = 0; filename[temp]; temp++)
  645.     {
  646.       if (filename[temp] == '/')
  647.       {
  648.         filename[temp] = 0;
  649.         mkdir(filename, 511);
  650.         filename[temp] = '/';
  651.       }
  652.     }
  653.     file = fopen(filename, "wb");
  654.   }
  655.   return(file);
  656. }
  657.  
  658. signed long extract_normal(FILE *in_file)
  659. {
  660.   struct filename_node *node;
  661.   FILE *out_file = 0;
  662.   unsigned char *pos, *temp;
  663.   unsigned long count;
  664.   signed long abort = 0;
  665.  
  666.   global_control = 0;
  667.   global_shift = -16;
  668.   last_offset = 1;
  669.   unpack_size = 0;
  670.   decrunch_length = 0;
  671.   for(count = 0; count < 8; count++) offset_len[count] = 0;
  672.   for(count = 0; count < 768; count ++) literal_len[count] = 0;
  673.   source_end = (source = read_buffer + 16384) - 1024;
  674.   pos = destination_end = destination = decrunch_buffer + 65794;
  675.   for (node = filename_list; (!abort) && node; node = node->next)
  676.   {
  677.     sum = 0;
  678.     printf("Extracting \"%s\"...", node->filename);
  679.     if (use_outdir)
  680.     {
  681.       strcpy(work_buffer, output_dir);
  682.       strcat(work_buffer, node->filename);
  683.     }
  684.     else
  685.     {
  686.       strcpy(work_buffer, node->filename);
  687.     }
  688.     fflush(stdout);
  689.     if (!pmatch(match_pattern, node->filename))
  690.       out_file = open_output(work_buffer);
  691.     else
  692.       out_file = 0;
  693.     unpack_size = node->length;
  694.     while(unpack_size > 0)
  695.     {
  696.       if (pos == destination)
  697.       {
  698.         if(source >= source_end)
  699.         {
  700.           temp = read_buffer;
  701.           if (count = temp - source + 16384)
  702.           {
  703.             do
  704.             {
  705.               *temp++ = *source++;
  706.             } while(--count);
  707.           }
  708.           source = read_buffer;
  709.           count = source - temp + 16384;
  710.           if (pack_size < count) count = pack_size;
  711.           if (fread(temp, 1, count, in_file) != count)
  712.           {
  713.             printf("\n");
  714. #ifdef UNLZX_DEBUG
  715.             if (ferror(in_file))
  716.             {
  717.               perror("FRead(Data)");
  718.             }
  719.             else
  720.             {
  721.               fprintf(stderr, "EOF: Data\n");
  722.             }
  723. #endif
  724.             abort = 1;
  725.             break;
  726.           }
  727.           pack_size -= count;
  728.           temp += count;
  729.           if (source >= temp) break;
  730.         }
  731.         if (decrunch_length <= 0)
  732.         {
  733.           if (read_literal_table()) break;
  734.         }
  735.         if (destination >= decrunch_buffer + 65794)
  736.         {
  737.           if (count = destination - decrunch_buffer - 65536)
  738.           {
  739.             temp = (destination = decrunch_buffer) + 65536;
  740.             do
  741.             {
  742.               *destination++ = *temp++;
  743.             } while(--count);
  744.           }
  745.           pos = destination;
  746.         }
  747.         destination_end = destination + decrunch_length;
  748.         if(destination_end > decrunch_buffer + 65794) destination_end = decrunch_buffer + 65794;
  749.         temp = destination;
  750.         decrunch();
  751.         decrunch_length -= (destination - temp);
  752.       }
  753.       count = destination - pos;
  754.       if (count > unpack_size) count = unpack_size;
  755.       crc_calc(pos, count);
  756.       if (out_file)
  757.       {
  758.         if (fwrite(pos, 1, count, out_file) != count)
  759.         {
  760. #ifdef UNLZX_DEBUG
  761.           perror("FWrite");
  762. #endif
  763.           fclose(out_file);
  764.           out_file = 0;
  765.         }
  766.       }
  767.       unpack_size -= count;
  768.       pos += count;
  769.     }
  770.     if (out_file)
  771.     {
  772.       fclose(out_file);
  773.       if (!abort) printf(" crc %s\n", (node->crc == sum) ? "good" : "bad");
  774.     }
  775.   }
  776.   return(abort);
  777. }
  778.  
  779. signed long extract_store(FILE *in_file)
  780. {
  781.   struct filename_node *node;
  782.   FILE *out_file;
  783.   unsigned long count;
  784.   signed long abort = 0;
  785.  
  786.   for (node = filename_list; (!abort) && (node); node = node->next)
  787.   {
  788.     sum = 0;
  789.     printf("Storing \"%s\"...", node->filename);
  790.     if (use_outdir)
  791.     {
  792.       strcpy(work_buffer, output_dir);
  793.       strcat(work_buffer, node->filename);
  794.     }
  795.     else
  796.     {
  797.       strcpy(work_buffer, node->filename);
  798.     }
  799.     fflush(stdout);
  800.     if (!pmatch(match_pattern, node->filename))
  801.       out_file = open_output(work_buffer);
  802.     else
  803.       out_file = 0;
  804.     unpack_size = node->length;
  805.     if (unpack_size > pack_size) unpack_size = pack_size;
  806.     while (unpack_size > 0)
  807.     {
  808.       count = (unpack_size > 16384) ? 16384 : unpack_size;
  809.       if (fread(read_buffer, 1, count, in_file) != count)
  810.       {
  811.         printf("\n");
  812. #ifdef UNLZX_DEBUG
  813.         if (ferror(in_file))
  814.         {
  815.           perror("FRead(Data)");
  816.         }
  817.         else
  818.         {
  819.           fprintf(stderr, "EOF: Data\n");
  820.         }
  821. #endif
  822.         abort = 1;
  823.         break;
  824.       }
  825.       pack_size -= count;
  826.       crc_calc(read_buffer, count);
  827.       if (out_file)
  828.       {
  829.         if (fwrite(read_buffer, 1, count, out_file) != count)
  830.         {
  831. #ifdef UNLZX_DEBUG
  832.           perror("FWrite");
  833. #endif
  834.           fclose(out_file);
  835.           out_file = 0;
  836.         }
  837.       }
  838.       unpack_size -= count;
  839.     }
  840.     if (out_file)
  841.     {
  842.       fclose(out_file);
  843.       if (!abort) printf(" crc %s\n", (node->crc == sum) ? "good" : "bad");
  844.     }
  845.   }
  846.   return(abort);
  847. }
  848.  
  849. signed long extract_unknown(FILE *in_file)
  850. {
  851.   struct filename_node *node;
  852.  
  853.   for (node = filename_list; (node); node = node->next)
  854.   {
  855.     printf("Unknown \"%s\"\n", node->filename);
  856.   }
  857.   return(0);
  858. }
  859.  
  860. signed long extract_archive(FILE *in_file)
  861. {
  862.   unsigned long temp;
  863.   struct filename_node **filename_next;
  864.   struct filename_node *node;
  865.   struct filename_node *temp_node;
  866.   signed long actual, abort, result = 1;
  867.  
  868.   filename_list = 0;
  869.   filename_next = &filename_list;
  870.   do
  871.   {
  872.     abort = 1;
  873.     actual = fread(archive_header, 1, 31, in_file);
  874.     if (!ferror(in_file))
  875.     {
  876.       if (actual)
  877.       {
  878.         if (actual == 31)
  879.         {
  880.           sum = 0;
  881.           crc = (archive_header[29] << 24) + (archive_header[28] << 16) + (archive_header[27] << 8) + archive_header[26];
  882.           archive_header[29] =
  883.           archive_header[28] =
  884.           archive_header[27] =
  885.           archive_header[26] = 0;
  886.           crc_calc(archive_header, 31);
  887.           temp = archive_header[30];
  888.           actual = fread(header_filename, 1, temp, in_file);
  889.           if (!ferror(in_file))
  890.           {
  891.             if (actual == temp)
  892.             {
  893.               header_filename[temp] = 0;
  894.               crc_calc(header_filename, temp);
  895.               temp = archive_header[14];
  896.               actual = fread(header_comment, 1, temp, in_file);
  897.               if (!ferror(in_file))
  898.               {
  899.                 if (actual == temp)
  900.                 {
  901.                   header_comment[temp] = 0;
  902.                   crc_calc(header_comment, temp);
  903.                   if (sum == crc)
  904.                   {
  905.                     unpack_size = (archive_header[5] << 24) + (archive_header[4] << 16) + (archive_header[3] << 8) + archive_header[2];
  906.                     pack_size = (archive_header[9] << 24) + (archive_header[8] << 16) + (archive_header[7] << 8) + archive_header[6];
  907.                     pack_mode = archive_header[11];
  908.                     crc = (archive_header[25] << 24) + (archive_header[24] << 16) + (archive_header[23] << 8) + archive_header[22];
  909.                     if (node = (struct filename_node *)malloc(sizeof(struct filename_node)))
  910.                     {
  911.                       *filename_next = node;
  912.                       filename_next = &(node->next);
  913.                       node->next = 0;
  914.                       node->length = unpack_size;
  915.                       node->crc = crc;
  916.                       for (temp = 0; node->filename[temp] = header_filename[temp]; temp++);
  917.                       if (pack_size)
  918.                       {
  919.                         switch(pack_mode)
  920.                         {
  921.                           case 0:
  922.                             abort = extract_store(in_file);
  923.                           break;
  924.                           case 2:
  925.                             abort = extract_normal(in_file);
  926.                           break;
  927.                           default:
  928.                             abort = extract_unknown(in_file);
  929.                           break;
  930.                         }
  931.                         if (abort) break;
  932.                         temp_node = filename_list;
  933.                         while (node = temp_node)
  934.                         {
  935.                           temp_node = node->next;
  936.                           free(node);
  937.                         }
  938.                         filename_list = 0;
  939.                         filename_next = &filename_list;
  940.                         if (fseek(in_file, pack_size, SEEK_CUR))
  941.                         {
  942. #ifdef UNLZX_DEBUG
  943.                           perror("FSeek(Data)");
  944. #endif
  945.                           break;
  946.                         }
  947.                       }
  948.                       else
  949.                       {
  950.                         abort = 0;
  951.                       }
  952.                     }
  953. #ifdef UNLZX_DEBUG
  954.                     else
  955.                     {
  956.                       fprintf(stderr, "MAlloc(Filename_node)\n");
  957.                     }
  958. #endif
  959.                   }
  960. #ifdef UNLZX_DEBUG
  961.                   else
  962.                   {
  963.                     fprintf(stderr, "CRC: Archive_Header\n");
  964.                   }
  965. #endif
  966.                 }
  967. #ifdef UNLZX_DEBUG
  968.                 else
  969.                 {
  970.                   fprintf(stderr, "EOF: Header_Comment\n");
  971.                 }
  972. #endif
  973.               }
  974. #ifdef UNLZX_DEBUG
  975.               else
  976.               {
  977.                 perror("FRead(Header_Comment)");
  978.               }
  979. #endif
  980.             }
  981. #ifdef UNLZX_DEBUG
  982.             else
  983.             {
  984.               fprintf(stderr, "EOF: Header_Filename\n");
  985.             }
  986. #endif
  987.           }
  988. #ifdef UNLZX_DEBUG
  989.           else
  990.           {
  991.             perror("FRead(Header_Filename)");
  992.           }
  993. #endif
  994.         }
  995. #ifdef UNLZX_DEBUG
  996.         else
  997.         {
  998.           fprintf(stderr, "EOF: Archive_Header\n");
  999.         }
  1000. #endif
  1001.       }
  1002.       else
  1003.       {
  1004.         result = 0;
  1005.       }
  1006.     }
  1007. #ifdef UNLZX_DEBUG
  1008.     else
  1009.     {
  1010.       perror("FRead(Archive_Header)");
  1011.     }
  1012. #endif
  1013.   } while(!abort);
  1014.   temp_node = filename_list;
  1015.   while(node = temp_node)
  1016.   {
  1017.     temp_node = node->next;
  1018.     free(node);
  1019.   }
  1020.   return(result);
  1021. }
  1022.  
  1023. signed long view_archive(FILE *in_file)
  1024. {
  1025.   unsigned long temp, total_pack = 0, total_unpack = 0, total_files = 0, merge_size = 0;
  1026.   signed long actual, abort, result = 1;
  1027.  
  1028.   printf("Unpacked   Packed Time     Date        Attrib   Name\n");
  1029.   printf("-------- -------- -------- ----------- -------- ----\n");
  1030.   do
  1031.   {
  1032.     abort = 1;
  1033.     actual = fread(archive_header, 1, 31, in_file);
  1034.     if (!ferror(in_file))
  1035.     {
  1036.       if (actual)
  1037.       {
  1038.         if (actual == 31)
  1039.         {
  1040.           sum = 0;
  1041.           crc = (archive_header[29] << 24) + (archive_header[28] << 16) + (archive_header[27] << 8) + archive_header[26];
  1042.           archive_header[29] =
  1043.           archive_header[28] =
  1044.           archive_header[27] =
  1045.           archive_header[26] = 0;
  1046.           crc_calc(archive_header, 31);
  1047.           temp = archive_header[30];
  1048.           actual = fread(header_filename, 1, temp, in_file);
  1049.           if (!ferror(in_file))
  1050.           {
  1051.             if (actual == temp)
  1052.             {
  1053.               header_filename[temp] = 0;
  1054.               crc_calc(header_filename, temp);
  1055.               temp = archive_header[14];
  1056.               actual = fread(header_comment, 1, temp, in_file);
  1057.               if (!ferror(in_file))
  1058.               {
  1059.                 if (actual == temp)
  1060.                 {
  1061.                   header_comment[temp] = 0;
  1062.                   crc_calc(header_comment, temp);
  1063.                   if (sum == crc)
  1064.                   {
  1065.                     attributes = archive_header[0];
  1066.                     unpack_size = (archive_header[5] << 24) + (archive_header[4] << 16) + (archive_header[3] << 8) + archive_header[2];
  1067.                     pack_size = (archive_header[9] << 24) + (archive_header[8] << 16) + (archive_header[7] << 8) + archive_header[6];
  1068.                     temp = (archive_header[18] << 24) + (archive_header[19] << 16) + (archive_header[20] << 8) + archive_header[21];
  1069.                     year = ((temp >> 17) & 63) + 1970;
  1070.                     month = (temp >> 23) & 15;
  1071.                     day = (temp >> 27) & 31;
  1072.                     hour = (temp >> 12) & 31;
  1073.                     minute = (temp >> 6) & 63;
  1074.                     second = temp & 63;
  1075.                     total_pack += pack_size;
  1076.                     total_unpack += unpack_size;
  1077.                     total_files++;
  1078.                     merge_size += unpack_size;
  1079.                     printf("%8ld ", unpack_size);
  1080.                     if (archive_header[12] & 1)
  1081.                     {
  1082.                       printf("     n/a ");
  1083.                     }
  1084.                     else
  1085.                     {
  1086.                       printf("%8ld ", pack_size);
  1087.                     }
  1088.                     printf("%02ld:%02ld:%02ld ", hour, minute, second);
  1089.                     printf("%2ld-%s-%4ld ", day, month_str[month], year);
  1090.                     printf("%c%c%c%c%c%c%c%c ",
  1091.                       (attributes & 32) ? 'h' : '-',
  1092.                       (attributes & 64) ? 's' : '-',
  1093.                       (attributes & 128) ? 'p' : '-',
  1094.                       (attributes & 16) ? 'a' : '-',
  1095.                       (attributes & 1) ? 'r' : '-',
  1096.                       (attributes & 2) ? 'w' : '-',
  1097.                       (attributes & 8) ? 'e' : '-',
  1098.                       (attributes & 4) ? 'd' : '-');
  1099.                     printf("\"%s\"\n", header_filename);
  1100.                     if(header_comment[0]) printf(": \"%s\"\n", header_comment);
  1101.                     if ((archive_header[12] & 1) && pack_size)
  1102.                     {
  1103.                       printf("%8ld %8ld Merged\n", merge_size, pack_size);
  1104.                     }
  1105.                     if (pack_size)
  1106.                     {
  1107.                       merge_size = 0;
  1108.                       if (!fseek(in_file, pack_size, SEEK_CUR))
  1109.                       {
  1110.                         abort = 0;
  1111.                         just_wait();
  1112.                       }
  1113. #ifdef UNLZX_DEBUG
  1114.                       else
  1115.                       {
  1116.                         perror("FSeek()");
  1117.                       }
  1118. #endif
  1119.                     }
  1120.                     else
  1121.                     {
  1122.                       abort = 0;
  1123.                     }
  1124.                   }
  1125. #ifdef UNLZX_DEBUG
  1126.                   else
  1127.                   {
  1128.                     fprintf(stderr, "CRC: Archive_Header\n");
  1129.                   }
  1130. #endif
  1131.                 }
  1132. #ifdef UNLZX_DEBUG
  1133.                 else
  1134.                 {
  1135.                   fprintf(stderr, "EOF: Header_Comment\n");
  1136.                 }
  1137. #endif
  1138.               }
  1139. #ifdef UNLZX_DEBUG
  1140.               else
  1141.               {
  1142.                 perror("FRead(Header_Comment)");
  1143.               }
  1144. #endif
  1145.             }
  1146. #ifdef UNLZX_DEBUG
  1147.             else
  1148.             {
  1149.               fprintf(stderr, "EOF: Header_Filename\n");
  1150.             }
  1151. #endif
  1152.           }
  1153. #ifdef UNLZX_DEBUG
  1154.           else
  1155.           {
  1156.             perror("FRead(Header_Filename)");
  1157.           }
  1158. #endif
  1159.         }
  1160. #ifdef UNLZX_DEBUG
  1161.         else
  1162.         {
  1163.           fprintf(stderr, "EOF: Archive_Header\n");
  1164.         }
  1165. #endif
  1166.       }
  1167.       else
  1168.       {
  1169.         printf("-------- -------- -------- ----------- -------- ----\n");
  1170.         printf("%8ld %8ld ", total_unpack, total_pack);
  1171.         printf("%ld file%s\n", total_files, ((total_files == 1) ? "" : "s"));
  1172.         result = 0;
  1173.       }
  1174.     }
  1175. #ifdef UNLZX_DEBUG
  1176.     else
  1177.     {
  1178.       perror("FRead(Archive_Header)");
  1179.     }
  1180. #endif
  1181.   } while(!abort);
  1182.   return(result);
  1183. }
  1184.  
  1185. signed long process_archive(unsigned char * filename)
  1186. {
  1187.   signed long result = 1, actual;
  1188.   FILE *in_file;
  1189.  
  1190.   if (in_file = fopen(filename,"rb"))
  1191.   {
  1192.     actual = fread(info_header, 1, 10, in_file);
  1193.     if (!ferror(in_file))
  1194.     {
  1195.       if (actual == 10)
  1196.       {
  1197.         if ((info_header[0] == 76) && (info_header[1] == 90) && (info_header[2] == 88))
  1198.         {
  1199.           switch (mode)
  1200.           {
  1201.             case 1:
  1202.               result = extract_archive(in_file);
  1203.             break;
  1204.             case 2:
  1205.               result = view_archive(in_file);
  1206.             break;
  1207.           }
  1208.         }
  1209. #ifdef UNLZX_DEBUG
  1210.         else
  1211.         {
  1212.           fprintf(stderr, "Info_Header: Bad ID\n");
  1213.         }
  1214. #endif
  1215.       }
  1216. #ifdef UNLZX_DEBUG
  1217.       else
  1218.       {
  1219.         fprintf(stderr, "EOF: Info_Header\n");
  1220.       }
  1221. #endif
  1222.     }
  1223. #ifdef UNLZX_DEBUG
  1224.     else
  1225.     {
  1226.       perror("FRead(Info_Header)");
  1227.     }
  1228. #endif
  1229.     fclose(in_file);
  1230.   }
  1231. #ifdef UNLZX_DEBUG
  1232.   else
  1233.   {
  1234.     perror("FOpen(Archive)");
  1235.   }
  1236. #endif
  1237.   return(result);
  1238. }
  1239.  
  1240. int main(int argc, char **argv)
  1241. {
  1242.   int result = 0;
  1243.   unsigned long option;
  1244.   unsigned char tmp;
  1245.  
  1246.   if (option = argopt("-p", (unsigned long)argc, (unsigned char **)argv))
  1247.   {
  1248.     if (++option < argc)
  1249.     {
  1250.       strcpy(match_pattern, argv[option]);
  1251.     }
  1252.   }
  1253.   if (option = argopt("-o", (unsigned long)argc, (unsigned char **)argv))
  1254.   {
  1255.     if (++option < argc)
  1256.     {
  1257.       strcpy(output_dir, argv[option]);
  1258.       use_outdir = 1;
  1259.  
  1260.       tmp = strlen(output_dir) - 1;
  1261. #ifdef AMIGA
  1262.       if ((output_dir[tmp] != '/') && (output_dir[tmp] != ':'))
  1263.       {
  1264.         output_dir[tmp+1] = '/';
  1265. #else
  1266.       if (output_dir[tmp] != '\\')
  1267.       {
  1268.         output_dir[tmp+1] = '\\';
  1269. #endif
  1270.         output_dir[tmp+2] = '\0';
  1271.       }
  1272.     }
  1273.   }
  1274.  
  1275.   if (option = argopt("-v", (unsigned long)argc, (unsigned char **)argv))
  1276.   {
  1277.     mode = 2;
  1278.   }
  1279.   else if (option = argopt("-x", (unsigned long)argc, (unsigned char **)argv))
  1280.   {
  1281.     mode = 1;
  1282.   }
  1283.   else
  1284.   {
  1285.     result = 1;
  1286.   }
  1287.   if ((!result) && (++option < argc))
  1288.   {
  1289.     result = process_archive(argv[option]);
  1290.   }
  1291.   else
  1292.   {
  1293.     printf( "Usage: %s <options>\n", argv[0] );
  1294.     printf( "\t-v <archive> : list archive\n"
  1295.             "\t-x <archive> : extract archive\n"
  1296.             "\t-p <pattern> : only matching files\n"
  1297.             "\t-o <outpath> : destination path\n" );
  1298.     result = 2;
  1299.   }
  1300.   return(result);
  1301. }
  1302.  
  1303.