home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 March / PCO3_97.ISO / filesbbs / os2 / lzo026.arj / LZO026.ZIP / lzo-0.26 / lzo_test.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-16  |  35.0 KB  |  1,458 lines

  1. /* lzo_test.c -- comprehensive test driver for the LZO library
  2.  
  3.    This file is part of the LZO real-time data compression library.
  4.  
  5.    Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
  6.    Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
  7.  
  8.    The LZO library is free software; you can redistribute it and/or
  9.    modify it under the terms of the GNU General Public License as
  10.    published by the Free Software Foundation; either version 2 of
  11.    the License, or (at your option) any later version.
  12.  
  13.    The LZO library is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with the LZO library; see the file COPYING.
  20.    If not, write to the Free Software Foundation, Inc.,
  21.    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22.  
  23.    Markus F.X.J. Oberhumer
  24.    markus.oberhumer@jk.uni-linz.ac.at
  25.  */
  26.  
  27.  
  28. #include <lzoconf.h>
  29.  
  30. #if defined(LZO_HAVE_CONFIG_AC)
  31. #  include <config.ac>
  32. #endif
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <stdarg.h>
  37. #include <string.h>
  38. #include <ctype.h>
  39. #include <limits.h>
  40. #include <assert.h>
  41. #if defined(__DJGPP__) || defined(__BORLANDC__)
  42. #  include <dir.h>
  43. #endif
  44. #if defined(HAVE_UNISTD_H) || defined(__DJGPP__) || defined(__EMX__)
  45. #  include <unistd.h>
  46. #endif
  47.  
  48. #include <time.h>
  49. #if !defined(CLOCKS_PER_SEC) && defined(CLK_TCK)
  50. #  define CLOCKS_PER_SEC    CLK_TCK
  51. #endif
  52. #if defined(UCLOCKS_PER_SEC)
  53. #  undef clock
  54. #  undef clock_t
  55. #  undef CLOCKS_PER_SEC
  56. #  define clock()            uclock()
  57. #  define clock_t            uclock_t
  58. #  define CLOCKS_PER_SEC    UCLOCKS_PER_SEC
  59. #endif
  60.  
  61.  
  62. /*************************************************************************
  63. //
  64. **************************************************************************/
  65.  
  66. #define HAVE_LZO1_H
  67. #define HAVE_LZO1A_H
  68. #define HAVE_LZO1B_H
  69. #define HAVE_LZO1C_H
  70. #define HAVE_LZO1F_H
  71. #define HAVE_LZO1X_H
  72. #define HAVE_LZO2A_H
  73. #if 1 && !defined(HAVE_ZLIB_H) && defined(MFX)
  74. #define HAVE_ZLIB_H
  75. #endif
  76.  
  77. #if defined(__LZO_MSDOS16)
  78. #undef HAVE_LZO1_H
  79. #undef HAVE_LZO1A_H
  80. #undef HAVE_LZO1C_H
  81. #undef HAVE_LZO2A_H
  82. #undef HAVE_LZO2B_H
  83. #undef HAVE_ZLIB_H
  84. #endif
  85.  
  86.  
  87. /*************************************************************************
  88. // define all methods
  89. **************************************************************************/
  90.  
  91. enum {
  92. /* compression algorithms */
  93.     M_LZO1B_1  =     1,
  94.     M_LZO1B_2, M_LZO1B_3, M_LZO1B_4, M_LZO1B_5,
  95.     M_LZO1B_6, M_LZO1B_7, M_LZO1B_8, M_LZO1B_9,
  96.  
  97.     M_LZO1C_1  =    11,
  98.     M_LZO1C_2, M_LZO1C_3, M_LZO1C_4, M_LZO1C_5,
  99.     M_LZO1C_6, M_LZO1C_7, M_LZO1C_8, M_LZO1C_9,
  100.  
  101.     M_LZO1     =    21,
  102.     M_LZO1A    =    31,
  103.  
  104.     M_LZO1B_99 =   901,
  105.     M_LZO1B_999=   902,
  106.     M_LZO1C_99 =   911,
  107.     M_LZO1C_999=   912,
  108.     M_LZO1_99  =   921,
  109.     M_LZO1A_99 =   931,
  110.  
  111.     M_LZO1F_1  =    61,
  112.     M_LZO1F_999=   962,
  113.     M_LZO1X_1  =    71,
  114.     M_LZO1X_999=   972,
  115.  
  116.     M_LZO2A_999=   942,
  117.     M_LZO2B_999=   952,
  118.  
  119.     M_LAST_LZO_COMPRESSOR = 998,
  120.  
  121. /* other compressors */
  122.     M_ZLIB_8_1 =  1101,
  123.     M_ZLIB_8_2, M_ZLIB_8_3, M_ZLIB_8_4, M_ZLIB_8_5,
  124.     M_ZLIB_8_6, M_ZLIB_8_7, M_ZLIB_8_8, M_ZLIB_8_9,
  125.  
  126. /* dummy compressor */
  127.     M_MEMCPY   =   999,
  128.  
  129.     M_LAST_COMPRESSOR = 4999,
  130.  
  131. /* dummy algorithms */
  132.     M_MEMSET   =  5001,
  133.  
  134. /* checksum algorithms */
  135.     M_ADLER32  =  6001,
  136.  
  137.     M_UNUSED
  138. };
  139.  
  140.  
  141. #if defined(LZO_99_UNSUPPORTED)
  142. #define M_LZO1_99        (-1)
  143. #define M_LZO1A_99        (-1)
  144. #define M_LZO1B_99        (-1)
  145. #define M_LZO1C_99        (-1)
  146. #endif
  147. #if defined(LZO_999_UNSUPPORTED)
  148. #define M_LZO1B_999        (-1)
  149. #define M_LZO1C_999        (-1)
  150. #define M_LZO1F_999        (-1)
  151. #define M_LZO1X_999        (-1)
  152. #define M_LZO2A_999        (-1)
  153. #define M_LZO2B_999        (-1)
  154. #endif
  155.  
  156.  
  157. /* LZO algorithms */
  158. #if defined(HAVE_LZO1_H)
  159. #  include <lzo1.h>
  160. #endif
  161. #if defined(HAVE_LZO1A_H)
  162. #  include <lzo1a.h>
  163. #endif
  164. #if defined(HAVE_LZO1B_H)
  165. #  include <lzo1b.h>
  166. #endif
  167. #if defined(HAVE_LZO1C_H)
  168. #  include <lzo1c.h>
  169. #endif
  170. #if defined(HAVE_LZO1F_H)
  171. #  include <lzo1f.h>
  172. #endif
  173. #if defined(HAVE_LZO1X_H)
  174. #  include <lzo1x.h>
  175. #endif
  176. #if defined(HAVE_LZO2A_H)
  177. #  include <lzo2a.h>
  178. #endif
  179. #if defined(HAVE_LZO2B_H)
  180. #  include <lzo2b.h>
  181. #endif
  182.  
  183. /* other compressors */
  184. #if defined(HAVE_ZLIB_H)
  185. #  include <zlib.h>
  186. #endif
  187. #if defined(MFX)
  188. #  include "contrib/t_config.ch"
  189. #endif
  190.  
  191.  
  192. /*************************************************************************
  193. //
  194. **************************************************************************/
  195.  
  196. #if 1
  197.    /* always use the fast decompressors */
  198. #  define lzo1b_decompress_safe        lzo1b_decompress
  199. #  define lzo1c_decompress_safe        lzo1c_decompress
  200. #  define lzo1f_decompress_safe        lzo1f_decompress
  201. #  define lzo1x_decompress_safe        lzo1x_decompress
  202. #  define lzo2a_decompress_safe        lzo2a_decompress
  203. #  define lzo2b_decompress_safe        lzo2b_decompress
  204. #endif
  205.  
  206.  
  207. #if defined(HAVE_LZO1X_H)
  208. int method = M_LZO1X_1;
  209. #elif defined(HAVE_LZO1B_H)
  210. int method = M_LZO1B_1;
  211. #elif defined(HAVE_LZO1C_H)
  212. int method = M_LZO1C_1;
  213. #elif defined(HAVE_LZO1F_H)
  214. int method = M_LZO1F_1;
  215. #else
  216. int method = 0;
  217. #endif
  218.  
  219. int verbose = 2;
  220.  
  221. lzo_bool use_assembler_decompressor = 0;
  222. lzo_bool try_to_compress_0_bytes = 1;
  223.  
  224. /* set these to 1 to measure the speed impact of a checksum (option '-a') */
  225. lzo_bool compute_adler32 = 0;
  226. lzo_bool compute_crc32 = 0;
  227.  
  228. static lzo_uint32 adler_in, adler_out;
  229.  
  230.  
  231. static const short all_methods[] = {
  232.     M_LZO1,
  233.     M_LZO1A,
  234.     M_LZO1B_1, M_LZO1B_2, M_LZO1B_3, M_LZO1B_4, M_LZO1B_5,
  235.     M_LZO1B_6, M_LZO1B_7, M_LZO1B_8, M_LZO1B_9,
  236.     M_LZO1C_1, M_LZO1C_2, M_LZO1C_3, M_LZO1C_4, M_LZO1C_5,
  237.     M_LZO1C_6, M_LZO1C_7, M_LZO1C_8, M_LZO1C_9,
  238.     M_LZO1F_1,
  239.     M_LZO1X_1,
  240.     M_LZO1_99, M_LZO1A_99, M_LZO1B_99, M_LZO1C_99,
  241.     M_LZO1B_999, M_LZO1C_999, M_LZO1F_999, M_LZO1X_999,
  242.     M_LZO2A_999,
  243.     0
  244. };
  245.  
  246. static const short benchmark_methods[] = {
  247.     M_LZO1B_1, M_LZO1B_9,
  248.     M_LZO1C_1, M_LZO1C_9,
  249.     M_LZO1F_1,
  250.     M_LZO1X_1,
  251.     0
  252. };
  253.  
  254. static const short x1_methods[] = {
  255.     M_LZO1, M_LZO1A, M_LZO1B_1, M_LZO1C_1, M_LZO1F_1, M_LZO1X_1,
  256.     0
  257. };
  258.  
  259. static const short x99_methods[] = {
  260.     M_LZO1_99, M_LZO1A_99, M_LZO1B_99, M_LZO1C_99,
  261.     0
  262. };
  263.  
  264. static const short x999_methods[] = {
  265.     M_LZO1B_999, M_LZO1C_999, M_LZO1F_999, M_LZO1X_999,
  266.     M_LZO2A_999,
  267.     0
  268. };
  269.  
  270. static const short zlib_methods[] = {
  271.     M_ZLIB_8_1, M_ZLIB_8_2, M_ZLIB_8_3, M_ZLIB_8_4, M_ZLIB_8_5,
  272.     M_ZLIB_8_6, M_ZLIB_8_7, M_ZLIB_8_8, M_ZLIB_8_9,
  273.     0
  274. };
  275.  
  276. static const short avail_methods[] = {
  277.     0
  278. };
  279.  
  280.  
  281. /* exit codes of this test program */
  282. #define EXIT_OK            0
  283. #define EXIT_USAGE        1
  284. #define EXIT_FILE        2
  285. #define EXIT_MEM        3
  286. #define EXIT_ADLER        4
  287. #define EXIT_LZO_ERROR    5
  288. #define EXIT_LZO_INIT    6
  289.  
  290.  
  291. /*************************************************************************
  292. // work memory
  293. **************************************************************************/
  294.  
  295. #if (UINT_MAX >= 0xffffffffL)        /* 32 bit or more */
  296.  
  297. #define BLOCK_SIZE        (256*1024l)
  298. #define MAX_BLOCK_SIZE    (4*BLOCK_SIZE)
  299. #define DATA_LEN        (1024*1024l)
  300. #define WORK_LEN        (768*1024l)
  301.  
  302. #elif defined(__LZO_ATARI16)
  303.  
  304. /* adjust memory so that it works on a 4 meg Atari ST */
  305. #define BLOCK_SIZE        (256*1024l)
  306. #define MAX_BLOCK_SIZE    (1*BLOCK_SIZE)
  307. #define DATA_LEN        (1024*1024l)
  308. #define WORK_LEN        (768*1024l)
  309.  
  310. #else                                /* 16 bit MSDOS */
  311.  
  312. /* have to squeeze everything into ~600 kB  */
  313. #if 0
  314. #define BLOCK_SIZE        (256*1024l)
  315. #define MAX_BLOCK_SIZE    (256*1024l)
  316. #define DATA_LEN        (128*1024l)
  317. #else
  318. #define BLOCK_SIZE        32000u
  319. #define MAX_BLOCK_SIZE    32000u
  320. #define DATA_LEN        (60*1024l)
  321. #endif
  322. #define WORK_LEN        (64*1024l)
  323.  
  324. #endif
  325.  
  326.  
  327. static lzo_uint block_size = BLOCK_SIZE;
  328.  
  329. #ifndef LZO_MEMALLOC_T
  330. #define LZO_MEMALLOC_T    lzo_byte
  331. #endif
  332. static LZO_MEMALLOC_T    _block1[MAX_BLOCK_SIZE * 9L / 8 + 256 + 1024];
  333. static LZO_MEMALLOC_T    _block2[MAX_BLOCK_SIZE * 9L / 8 + 256 + 1024];
  334. static LZO_MEMALLOC_T    _data[DATA_LEN + 256];
  335. static LZO_MEMALLOC_T    _wrkmem[WORK_LEN + 256];
  336.  
  337. /* align memory blocks (cache issues) */
  338. static lzo_byte *block1 = NULL;
  339. static lzo_byte *block2 = NULL;
  340. static lzo_byte *data = NULL;
  341. static lzo_byte *wrkmem = NULL;
  342.  
  343. static void align_mem(void)
  344. {
  345.     block1 = (lzo_byte *) LZO_ALIGN(_block1,256);
  346.     block2 = (lzo_byte *) LZO_ALIGN(_block2,256);
  347.     data   = (lzo_byte *) LZO_ALIGN(_data,256);
  348.     wrkmem = (lzo_byte *) LZO_ALIGN(_wrkmem,256);
  349. }
  350.  
  351.  
  352. /***********************************************************************
  353. // read from a file
  354. ************************************************************************/
  355.  
  356. lzo_uint my_fread(FILE *f, lzo_voidp s, lzo_uint len)
  357. {
  358. #if (LZO_UINT_MAX <= UINT_MAX)
  359.     return fread(s,1,len,f);
  360. #else
  361.     lzo_byte *p = (lzo_byte *) s;
  362.     lzo_uint l = 0;
  363.     size_t k;
  364.     unsigned char buf[512], *b;
  365.  
  366.     while (l < len)
  367.     {
  368.         k = len - l > sizeof(buf) ? sizeof(buf) : (size_t) (len - l);
  369.         k = fread(buf,1,k,f);
  370.         if (k <= 0)
  371.             break;
  372.         l += k;
  373.         b = buf;
  374.         do *p++ = *b++; while (--k > 0);
  375.     }
  376.     return l;
  377. #endif
  378. }
  379.  
  380.  
  381. /*************************************************************************
  382. // compress a block
  383. **************************************************************************/
  384.  
  385. static int
  386. do_compress(const lzo_byte *in, lzo_byte *out,
  387.                   lzo_uint in_len, lzo_uint *out_len)
  388. {
  389.     int r = -100;
  390.     unsigned long o_len = ULONG_MAX;
  391.  
  392.     if (method <= 0)
  393.         ;
  394. #if defined(HAVE_LZO1_H)
  395.     else if (method == M_LZO1)
  396.         r = lzo1_compress(in,in_len,out,out_len,wrkmem);
  397. #if !defined(LZO_99_UNSUPPORTED)
  398.     else if (method == M_LZO1_99 && (WORK_LEN >= LZO1_99_MEM_COMPRESS))
  399.         r = lzo1_99_compress(in,in_len,out,out_len,wrkmem);
  400. #endif
  401. #endif
  402. #if defined(HAVE_LZO1A_H)
  403.     else if (method == M_LZO1A)
  404.         r = lzo1a_compress(in,in_len,out,out_len,wrkmem);
  405. #if !defined(LZO_99_UNSUPPORTED)
  406.     else if (method == M_LZO1A_99 && (WORK_LEN >= LZO1A_99_MEM_COMPRESS))
  407.         r = lzo1a_99_compress(in,in_len,out,out_len,wrkmem);
  408. #endif
  409. #endif
  410. #if defined(HAVE_LZO1B_H)
  411.     else if (method >= M_LZO1B_1 && method <= M_LZO1B_9)
  412.     {
  413.         int clevel = method - M_LZO1B_1 + 1;
  414.         r = lzo1b_compress(in,in_len,out,out_len,wrkmem,clevel);
  415.     }
  416. #if !defined(LZO_99_UNSUPPORTED)
  417.     else if (method == M_LZO1B_99 && (WORK_LEN >= LZO1B_99_MEM_COMPRESS))
  418.         r = lzo1b_99_compress(in,in_len,out,out_len,wrkmem);
  419. #endif
  420. #if !defined(LZO_999_UNSUPPORTED)
  421.     else if (method == M_LZO1B_999 && (WORK_LEN >= LZO1B_999_MEM_COMPRESS))
  422.         r = lzo1b_999_compress(in,in_len,out,out_len,wrkmem);
  423. #endif
  424. #endif
  425. #if defined(HAVE_LZO1C_H)
  426.     else if (method >= M_LZO1C_1 && method <= M_LZO1C_9)
  427.     {
  428.         int clevel = method - M_LZO1C_1 + 1;
  429.         r = lzo1c_compress(in,in_len,out,out_len,wrkmem,clevel);
  430.     }
  431. #if !defined(LZO_99_UNSUPPORTED)
  432.     else if (method == M_LZO1C_99 && (WORK_LEN >= LZO1C_99_MEM_COMPRESS))
  433.         r = lzo1c_99_compress(in,in_len,out,out_len,wrkmem);
  434. #endif
  435. #if !defined(LZO_999_UNSUPPORTED)
  436.     else if (method == M_LZO1C_999 && (WORK_LEN >= LZO1C_999_MEM_COMPRESS))
  437.         r = lzo1c_999_compress(in,in_len,out,out_len,wrkmem);
  438. #endif
  439. #endif
  440. #if defined(HAVE_LZO1F_H)
  441.     else if (method == M_LZO1F_1)
  442.         r = lzo1f_1_compress(in,in_len,out,out_len,wrkmem);
  443. #if !defined(LZO_999_UNSUPPORTED)
  444.     else if (method == M_LZO1F_999 && (WORK_LEN >= LZO1F_999_MEM_COMPRESS))
  445.         r = lzo1f_999_compress(in,in_len,out,out_len,wrkmem);
  446. #endif
  447. #endif
  448. #if defined(HAVE_LZO1X_H)
  449.     else if (method == M_LZO1X_1)
  450.         r = lzo1x_1_compress(in,in_len,out,out_len,wrkmem);
  451. #if !defined(LZO_999_UNSUPPORTED)
  452.     else if (method == M_LZO1X_999 && (WORK_LEN >= LZO1F_999_MEM_COMPRESS))
  453.         r = lzo1x_999_compress(in,in_len,out,out_len,wrkmem);
  454. #endif
  455. #endif
  456. #if defined(HAVE_LZO2A_H)
  457. #if !defined(LZO_999_UNSUPPORTED)
  458.     else if (method == M_LZO2A_999 && (WORK_LEN >= LZO2A_999_MEM_COMPRESS))
  459.         r = lzo2a_999_compress(in,in_len,out,out_len,wrkmem);
  460. #endif
  461. #endif
  462. #if defined(HAVE_LZO2B_H)
  463. #if !defined(LZO_999_UNSUPPORTED)
  464.     else if (method == M_LZO2B_999 && (WORK_LEN >= LZO2B_999_MEM_COMPRESS))
  465.         r = lzo2b_999_compress(in,in_len,out,out_len,wrkmem);
  466. #endif
  467. #endif
  468. #if defined(HAVE_ZLIB_H)
  469.     else if (method >= M_ZLIB_8_1 && method <= M_ZLIB_8_9)
  470.     {
  471.         /* use the undocumented feature to suppress the zlib header */
  472.         z_stream stream;
  473.         int err;
  474.         int level = method - M_ZLIB_8_1 + 1;
  475.  
  476.         stream.next_in = (lzo_byte *) in;        /* UNCONST */
  477.         stream.avail_in = in_len;
  478.         stream.next_out = out;
  479.         stream.avail_out = *out_len;
  480.  
  481.         stream.zalloc = (alloc_func)0;
  482.         stream.zfree = (free_func)0;
  483.         *out_len = 0;
  484. #if 0
  485.         err = deflateInit(&stream, level);
  486. #else
  487.         err = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS,
  488.                            MAX_MEM_LEVEL > 8 ? 8 : MAX_MEM_LEVEL,
  489.                            Z_DEFAULT_STRATEGY);
  490. #endif
  491.         if (err == Z_OK)
  492.         {
  493.             err = deflate(&stream, Z_FINISH);
  494.             if (err != Z_STREAM_END)
  495.             {
  496.                 deflateEnd(&stream);
  497.                 err = err == Z_OK ? Z_BUF_ERROR : err;
  498.             }
  499.             else
  500.             {
  501.                 *out_len = (lzo_uint) stream.total_out;
  502.                 err = deflateEnd(&stream);
  503.             }
  504.         }
  505.         r = err == Z_OK ? 0 : -1;
  506.     }
  507. #endif
  508. #if defined(MFX)
  509. #  include "contrib/t_comp.ch"
  510. #endif
  511.     else if (method == M_MEMCPY)
  512.     {
  513.         lzo_memcpy(out,in,in_len);
  514.         *out_len = in_len; r = 0;
  515.     }
  516.     else if (method == M_MEMSET)
  517.     {
  518.         lzo_memset(out,0,in_len);
  519.         *out_len = in_len; r = 0;
  520.     }
  521.     else if (method == M_ADLER32)
  522.     {
  523.         lzo_uint32 adler;
  524.         adler = lzo_adler32(0, NULL, 0);
  525.         adler = lzo_adler32(adler, out, in_len);
  526.         *out_len = in_len; r = 0;
  527.     }
  528.     else
  529.         *out_len = 0;
  530.  
  531.     if (o_len != ULONG_MAX)
  532.         *out_len = (lzo_uint) o_len;
  533.  
  534.     if (r == 0 && compute_adler32)
  535.     {
  536.         lzo_uint32 adler;
  537.         adler = lzo_adler32(0, NULL, 0);
  538.         adler = lzo_adler32(adler, in, in_len);
  539.         adler_in = adler;
  540.     }
  541. #if defined(HAVE_ZLIB_H)
  542.     if (r == 0 && compute_crc32)
  543.     {
  544.         uLong crc;
  545.         crc = crc32(0L, Z_NULL, 0);
  546.         crc = crc32(crc, in, in_len);
  547.     }
  548. #endif
  549.  
  550.     return r;
  551. }
  552.  
  553.  
  554. /*************************************************************************
  555. // decompress a block
  556. **************************************************************************/
  557.  
  558. static int
  559. do_decompress(const lzo_byte *in, lzo_byte *out,
  560.               lzo_uint in_len, lzo_uint *out_len)
  561. {
  562.     int r = -100;
  563.     unsigned long o_len = ULONG_MAX;
  564.  
  565.     if (method <= 0)
  566.         ;
  567. #if defined(HAVE_LZO1_H)
  568.     else if (method == M_LZO1 || method == M_LZO1_99)
  569.         r = lzo1_decompress(in,in_len,out,out_len,wrkmem);
  570. #endif
  571. #if defined(HAVE_LZO1A_H)
  572.     else if (method == M_LZO1A || method == M_LZO1A_99)
  573.         r = lzo1a_decompress(in,in_len,out,out_len,NULL);
  574. #endif
  575. #if defined(HAVE_LZO1B_H)
  576.     else if (method >= M_LZO1B_1 && method <= M_LZO1B_9)
  577.         r = lzo1b_decompress(in,in_len,out,out_len,wrkmem);
  578.     else if (method == M_LZO1B_99 || method == M_LZO1B_999)
  579.         r = lzo1b_decompress_safe(in,in_len,out,out_len,wrkmem);
  580. #endif
  581. #if defined(HAVE_LZO1C_H)
  582. #if defined(LZO1C_DECOMPRESS_ASM)
  583.     else if (use_assembler_decompressor &&
  584.         ((method >= M_LZO1C_1 && method <= M_LZO1C_9) ||
  585.          (method == M_LZO1C_99 || method == M_LZO1C_999)))
  586.         r = lzo1c_decompress_asm(in,in_len,out,out_len,wrkmem);
  587. #endif
  588.     else if (method >= M_LZO1C_1 && method <= M_LZO1C_9)
  589.         r = lzo1c_decompress(in,in_len,out,out_len,wrkmem);
  590.     else if (method == M_LZO1C_99 || method == M_LZO1C_999)
  591.         r = lzo1c_decompress_safe(in,in_len,out,out_len,wrkmem);
  592. #endif
  593. #if defined(HAVE_LZO1F_H)
  594. #if defined(LZO1F_DECOMPRESS_ASM)
  595.     else if (use_assembler_decompressor &&
  596.          (method == M_LZO1F_1 || method == M_LZO1F_999))
  597.         r = lzo1f_decompress_asm(in,in_len,out,out_len,wrkmem);
  598. #endif
  599.     else if (method == M_LZO1F_1)
  600.         r = lzo1f_decompress(in,in_len,out,out_len,wrkmem);
  601.     else if (method == M_LZO1F_999)
  602.         r = lzo1f_decompress_safe(in,in_len,out,out_len,wrkmem);
  603. #endif
  604. #if defined(HAVE_LZO1X_H)
  605. #if defined(LZO1X_DECOMPRESS_ASM)
  606.     else if (use_assembler_decompressor &&
  607.          (method == M_LZO1X_1 || method == M_LZO1X_999))
  608.         r = lzo1x_decompress_asm(in,in_len,out,out_len,wrkmem);
  609. #endif
  610.     else if (method == M_LZO1X_1)
  611.         r = lzo1x_decompress(in,in_len,out,out_len,wrkmem);
  612.     else if (method == M_LZO1X_999)
  613.         r = lzo1x_decompress_safe(in,in_len,out,out_len,wrkmem);
  614. #endif
  615. #if defined(HAVE_LZO2A_H)
  616.     else if (method == M_LZO2A_999)
  617.         r = lzo2a_decompress_safe(in,in_len,out,out_len,wrkmem);
  618. #endif
  619. #if defined(HAVE_LZO2B_H)
  620.     else if (method == M_LZO2B_999)
  621.         r = lzo2b_decompress_safe(in,in_len,out,out_len,wrkmem);
  622. #endif
  623. #if defined(HAVE_ZLIB_H)
  624.     else if (method >= M_ZLIB_8_1 && method <= M_ZLIB_8_9)
  625.     {
  626.         /* use the undocumented feature to suppress the zlib header */
  627.         z_stream stream;
  628.         int err;
  629.  
  630.         stream.next_in = (lzo_byte *) in;        /* UNCONST */
  631.         stream.avail_in = in_len;
  632.         stream.next_out = out;
  633.         stream.avail_out = *out_len;
  634.  
  635.         stream.zalloc = (alloc_func)0;
  636.         stream.zfree = (free_func)0;
  637.         *out_len = 0;
  638. #if 0
  639.         err = inflateInit(&stream);
  640. #else
  641.         err = inflateInit2(&stream, -MAX_WBITS);
  642. #endif
  643.         if (err == Z_OK)
  644.         {
  645.             err = inflate(&stream, Z_FINISH);
  646.             if (err == Z_OK)        /* sometimes returns Z_OK !!! */
  647.             {
  648.                 *out_len = (lzo_uint) stream.total_out;
  649.                 err = inflateEnd(&stream);
  650.             }
  651.             else if (err == Z_STREAM_END)
  652.             {
  653.                 *out_len = (lzo_uint) stream.total_out;
  654.                 err = inflateEnd(&stream);
  655.             }
  656.             else
  657.                 inflateEnd(&stream);
  658.         }
  659.         r = err == Z_OK ? 0 : -1;
  660.     }
  661. #endif
  662. #if defined(MFX)
  663. #  include "contrib/t_decomp.ch"
  664. #endif
  665.     else if (method == M_MEMCPY)
  666.     {
  667.         lzo_memcpy(out,in,in_len);
  668.         *out_len = in_len; r = 0;
  669.     }
  670.     else if (method == M_MEMSET)
  671.     {
  672.         lzo_memset(out,0,in_len);
  673.         *out_len = in_len; r = 0;
  674.     }
  675.     else if (method == M_ADLER32)
  676.     {
  677.         lzo_uint32 adler;
  678.         adler = lzo_adler32(0, NULL, 0);
  679.         adler = lzo_adler32(adler, out, in_len);
  680.         *out_len = in_len; r = 0;
  681.     }
  682.     else
  683.         *out_len = 0;
  684.  
  685.     if (o_len != ULONG_MAX)
  686.         *out_len = (lzo_uint) o_len;
  687.  
  688.     if (r == 0 && compute_adler32)
  689.     {
  690.         lzo_uint32 adler;
  691.         adler = lzo_adler32(0, NULL, 0);
  692.         adler = lzo_adler32(adler, out, *out_len);
  693.         adler_out = adler;
  694.     }
  695. #if defined(HAVE_ZLIB_H)
  696.     if (r == 0 && compute_crc32)
  697.     {
  698.         uLong crc;
  699.         crc = crc32(0L, Z_NULL, 0);
  700.         crc = crc32(crc, out, *out_len);
  701.     }
  702. #endif
  703.  
  704.     return r;
  705. }
  706.  
  707.  
  708. /*************************************************************************
  709. // method info
  710. **************************************************************************/
  711.  
  712. static char method_name[16+1];
  713.  
  714. static lzo_bool info(FILE *f)
  715. {
  716.     char *s = method_name;
  717.  
  718.     s[0] = 0;
  719.     if (method <= 0)
  720.         ;
  721. #if defined(HAVE_LZO1_H)
  722.     else if (method == M_LZO1)
  723.     {
  724.         int rbits, clevel;
  725.         lzo1_info(&rbits,&clevel);
  726.         sprintf(s,"LZO1-%d",clevel);
  727.     }
  728. #if !defined(LZO_99_UNSUPPORTED)
  729.     else if (method == M_LZO1_99 && (WORK_LEN >= LZO1_99_MEM_COMPRESS))
  730.         sprintf(s,"LZO1-99");
  731. #endif
  732. #endif
  733. #if defined(HAVE_LZO1A_H)
  734.     else if (method == M_LZO1A)
  735.     {
  736.         int rbits, clevel;
  737.         lzo1a_info(&rbits,&clevel);
  738.         sprintf(s,"LZO1A-%d",clevel);
  739.     }
  740. #if !defined(LZO_99_UNSUPPORTED)
  741.     else if (method == M_LZO1A_99 && (WORK_LEN >= LZO1A_99_MEM_COMPRESS))
  742.         sprintf(s,"LZO1A-99");
  743. #endif
  744. #endif
  745. #if defined(HAVE_LZO1B_H)
  746.     else if (method >= M_LZO1B_1 && method <= M_LZO1B_9)
  747.     {
  748.         int clevel = method - M_LZO1B_1 + 1;
  749.         sprintf(s,"LZO1B-%d",clevel);
  750.     }
  751. #if !defined(LZO_99_UNSUPPORTED)
  752.     else if (method == M_LZO1B_99 && (WORK_LEN >= LZO1B_99_MEM_COMPRESS))
  753.         sprintf(s,"LZO1B-99");
  754. #endif
  755. #if !defined(LZO_999_UNSUPPORTED)
  756.     else if (method == M_LZO1B_999 && (WORK_LEN >= LZO1B_999_MEM_COMPRESS))
  757.         sprintf(s,"LZO1B-999");
  758. #endif
  759. #endif
  760. #if defined(HAVE_LZO1C_H)
  761.     else if (method >= M_LZO1C_1 && method <= M_LZO1C_9)
  762.     {
  763.         int clevel = method - M_LZO1C_1 + 1;
  764.         sprintf(s,"LZO1C-%d",clevel);
  765.     }
  766. #if !defined(LZO_99_UNSUPPORTED)
  767.     else if (method == M_LZO1C_99 && (WORK_LEN >= LZO1C_99_MEM_COMPRESS))
  768.         sprintf(s,"LZO1C-99");
  769. #endif
  770. #if !defined(LZO_999_UNSUPPORTED)
  771.     else if (method == M_LZO1C_999 && (WORK_LEN >= LZO1C_999_MEM_COMPRESS))
  772.         sprintf(s,"LZO1C-999");
  773. #endif
  774. #endif
  775. #if defined(HAVE_LZO1F_H)
  776.     else if (method == M_LZO1F_1)
  777.         sprintf(s,"LZO1F-1");
  778. #if !defined(LZO_999_UNSUPPORTED)
  779.     else if (method == M_LZO1F_999 && (WORK_LEN >= LZO1F_999_MEM_COMPRESS))
  780.         sprintf(s,"LZO1F-999");
  781. #endif
  782. #endif
  783. #if defined(HAVE_LZO1X_H)
  784.     else if (method == M_LZO1X_1)
  785.         sprintf(s,"LZO1X-1");
  786. #if !defined(LZO_999_UNSUPPORTED)
  787.     else if (method == M_LZO1X_999 && (WORK_LEN >= LZO1X_999_MEM_COMPRESS))
  788.         sprintf(s,"LZO1X-999");
  789. #endif
  790. #endif
  791. #if defined(HAVE_LZO2A_H)
  792. #if !defined(LZO_999_UNSUPPORTED)
  793.     else if (method == M_LZO2A_999 && (WORK_LEN >= LZO2A_999_MEM_COMPRESS))
  794.         sprintf(s,"LZO2A-999");
  795. #endif
  796. #endif
  797. #if defined(HAVE_LZO2B_H)
  798. #if !defined(LZO_999_UNSUPPORTED)
  799.     else if (method == M_LZO2B_999 && (WORK_LEN >= LZO2B_999_MEM_COMPRESS))
  800.         sprintf(s,"LZO2B-999");
  801. #endif
  802. #endif
  803. #if defined(HAVE_ZLIB_H)
  804.     else if (method >= M_ZLIB_8_1 && method <= M_ZLIB_8_9)
  805.         sprintf(s,"zlib-%d/%d", Z_DEFLATED, method - M_ZLIB_8_1 + 1);
  806. #endif
  807. #if defined(MFX)
  808. #  include "contrib/t_info.ch"
  809. #endif
  810.     else if (method == M_MEMCPY)
  811.         sprintf(s,"memcpy()");
  812.     else if (method == M_MEMSET)
  813.         sprintf(s,"memset()");
  814.     else if (method == M_ADLER32)
  815.         sprintf(s,"adler32");
  816.  
  817.     if (s[0] == 0)
  818.     {
  819.         if (f != NULL)
  820.         {
  821.             fprintf(f,"invalid method %d !\n",method);
  822.             exit(EXIT_USAGE);
  823.         }
  824.         return 0;
  825.     }
  826.     else
  827.     {
  828.         if (f != NULL)
  829.             fprintf(f,"%s",s);
  830.         return 1;
  831.     }
  832. }
  833.  
  834.  
  835. /*************************************************************************
  836. // compress and decompress a file
  837. **************************************************************************/
  838.  
  839. static int do_file(const char *name, int c_loops, int d_loops, lzo_uint32 *ad)
  840. {
  841.     FILE *f;
  842.     int i, r = 0;
  843.     lzo_uint l = 0, t_len = 0;
  844.     unsigned long ll;
  845.     int blocks = 0;
  846.     int t_loops = 1;
  847.     clock_t t_time = 0, c_time = 0, d_time = 0;
  848.     clock_t t_start, c_start, d_start;
  849.     unsigned long t_bytes, c_bytes, d_bytes;
  850.     double t_kbs, c_kbs, d_kbs;
  851.     double t_secs, c_secs, d_secs;
  852.     double perc, bits;
  853.     lzo_uint32 adler;
  854.  
  855.     if (c_loops < 1)  c_loops = 1;
  856.     if (d_loops < 1)  d_loops = 1;
  857.  
  858.     fflush(stdout);
  859.     fflush(stderr);
  860.  
  861.     adler_in = adler_out = 0;
  862.     if (ad)
  863.         *ad = 0;
  864.  
  865.     /* read the whole file */
  866.     f = fopen(name,"rb");
  867.     if (f == NULL)
  868.     {
  869.         fprintf(stderr,"%s: ",name);
  870.         perror("fopen");
  871.         return 0;                /* do not raise an error */
  872.     }
  873.     l = my_fread(f,data,DATA_LEN);
  874.     if (fclose(f) != 0)
  875.     {
  876.         fprintf(stderr,"%s: ",name);
  877.         perror("fclose");
  878.         return EXIT_FILE;
  879.     }
  880.  
  881.     adler = lzo_adler32(0, NULL, 0);
  882.     adler = lzo_adler32(adler, data, l);
  883.     if (ad)
  884.         *ad = adler;
  885.  
  886.     if (verbose >= 2)
  887.     {
  888.         printf("File %s: %lu bytes   adler32 = 0x%08lx\n",
  889.                 name, (long) l, (long) adler);
  890.         printf("  compressing %lu bytes (%d/%d/%d loops, %lu block-size)\n",
  891.                 (long) l, t_loops, c_loops, d_loops, (long) block_size);
  892.         printf("  "); info(stdout); printf("\n");
  893.     }
  894.  
  895.     /* compress the file */
  896.  
  897.     t_start = clock();
  898.     for (i = 0; i < t_loops; i++)
  899.     {
  900.         lzo_uint len, c_len, c_len_max, d_len;
  901.         lzo_byte *d = data;
  902.  
  903.         len = l;
  904.         t_len = 0;
  905.         blocks = 0;
  906.         if (len > 0 || try_to_compress_0_bytes) do
  907.         {
  908.             int j;
  909.             lzo_byte *dd = d;
  910.             lzo_byte *b1 = block1;
  911.             lzo_byte *b2 = block2;
  912.             const lzo_uint bl = len > block_size ? block_size : len;
  913.             lzo_uint bl_overwrite = bl;
  914. #if !defined(__BOUNDS_CHECKING_ON)
  915.             unsigned char random_byte;
  916. #endif
  917.  
  918.             if (use_assembler_decompressor)
  919.                 bl_overwrite += 3;        /* may overwrite 3 bytes past the end */
  920.  
  921.             blocks++;
  922.  
  923. #if defined(__BOUNDS_CHECKING_ON)
  924.             /* malloc a block of the exact block size to detect
  925.              * any overun.
  926.              */
  927.             dd = malloc(bl_overwrite);
  928.             if (dd == NULL)
  929.                 return EXIT_MEM;
  930.             memcpy(dd,d,bl);
  931.             b2 = dd;
  932. #endif
  933.  
  934.         /* compress a block */
  935.             c_len = c_len_max = 0;
  936.             c_start = clock();
  937.             for (j = r = 0; r == 0 && j < c_loops; j++)
  938.             {
  939.                 c_len = sizeof(_block1) - 256;
  940.                 r = do_compress(dd,b1,bl,&c_len);
  941.                 if (r == 0 && c_len > c_len_max)
  942.                     c_len_max = c_len;
  943.             }
  944.             c_time += clock() - c_start;
  945.             if (r != 0)
  946.             {
  947.                 printf("  compression failed in block %d (%d) (%lu %lu)\n",
  948.                     blocks, r, (long)c_len, (long)bl);
  949.                 return EXIT_LZO_ERROR;
  950.             }
  951.  
  952.         /* decompress the block and verify */
  953. #if defined(__BOUNDS_CHECKING_ON)
  954.             lzo_memset(b2,0,bl);
  955. #else
  956.             lzo_memset(b2,0,bl_overwrite);
  957.             /* check that no data past the end gets overwritten */
  958.             random_byte = (unsigned char) c_start;
  959.             b2[bl_overwrite] = random_byte;
  960. #endif
  961.             d_start = clock();
  962.             for (j = r = 0; r == 0 && j < d_loops; j++)
  963.             {
  964.                 d_len = bl;
  965.                 r = do_decompress(b1,b2,c_len,&d_len);
  966.                 if (d_len != bl)
  967.                     break;
  968.             }
  969.             d_time += clock() - d_start;
  970.             if (r != 0)
  971.             {
  972.                 printf("  decompression failed in block %d (%d) "
  973.                     "(%lu %lu %lu)\n", blocks, r,
  974.                     (long)c_len, (long)d_len, (long)bl);
  975.                 return EXIT_LZO_ERROR;
  976.             }
  977.             if (d_len != bl)
  978.             {
  979.                 printf("  decompression size error in block %d (%lu %lu %lu)\n",
  980.                     blocks, (long)c_len, (long)d_len, (long)bl);
  981.                 return EXIT_LZO_ERROR;
  982.             }
  983.             if (method <= M_LAST_COMPRESSOR)
  984.             {
  985.                 if (lzo_memcmp(d,b2,bl) != 0)
  986.                 {
  987.                     lzo_uint x = 0;
  988.                     while (x < bl && b2[x] == d[x])
  989.                         x++;
  990.                     printf("  decompression data error in block %d at offset "
  991.                         "%lu (%lu %lu)\n", blocks, (long)x,
  992.                         (long)c_len, (long)d_len);
  993.                     if (compute_adler32)
  994.                         printf("      checksum: 0x%08lx 0x%08lx\n",
  995.                             (long)adler_in, (long)adler_out);
  996. #if 0
  997.                     printf("Orig:  ");
  998.                     for (j = (x >= 10 ? -10 : 0); j <= 10 && x + j < bl; j++)
  999.                         printf(" %02x", (int)b2[x+j]);
  1000.                     printf("\nDecomp:");
  1001.                     for (j = (x >= 10 ? -10 : 0); j <= 10 && x + j < bl; j++)
  1002.                         printf(" %02x", (int)d[x+j]);
  1003.                     printf("\n");
  1004. #endif
  1005.                     return EXIT_LZO_ERROR;
  1006.                 }
  1007.                 if (compute_adler32 && adler_in != adler_out)
  1008.                 {
  1009.                     printf("  checksum error in block %d (%lu %lu)\n",
  1010.                         blocks, (long)c_len, (long)d_len);
  1011.                     printf("      checksum: 0x%08lx 0x%08lx\n",
  1012.                         (long)adler_in, (long)adler_out);
  1013.                     return EXIT_LZO_ERROR;
  1014.                 }
  1015.             }
  1016. #if !defined(__BOUNDS_CHECKING_ON)
  1017.             if (b2[bl_overwrite] != random_byte)
  1018.             {
  1019.                 printf("  decompression overwrite error in block %d "
  1020.                     "(%lu %lu %lu)\n",
  1021.                     blocks, (long)c_len, (long)d_len, (long)bl);
  1022.                 return EXIT_LZO_ERROR;
  1023.             }
  1024. #endif
  1025.  
  1026. #if defined(__BOUNDS_CHECKING_ON)
  1027.             if (dd != d)
  1028.                 free(dd);
  1029. #endif
  1030.             d += bl;
  1031.             len -= bl;
  1032.             t_len += c_len_max;
  1033.         }
  1034.         while (len > 0);
  1035.     }
  1036.     t_time += clock() - t_start;
  1037.  
  1038.  
  1039.     /* print some statistics */
  1040.  
  1041.     ll = l;
  1042.     perc = (ll > 0) ? t_len * 100.0 / ll : 0;
  1043.     bits = perc * 0.08;
  1044.     t_secs = t_time / (double)(CLOCKS_PER_SEC);
  1045.     t_bytes = (ll * c_loops + ll * d_loops) * t_loops;
  1046.     t_kbs = (t_secs > 0.001) ? (t_bytes / t_secs) / 1000.0 : 0;
  1047.     c_secs = c_time / (double)(CLOCKS_PER_SEC);
  1048.     c_bytes = ll * c_loops * t_loops;
  1049.     c_kbs = (c_secs > 0.001) ? (c_bytes / c_secs) / 1000.0 : 0;
  1050.     d_secs = d_time / (double)(CLOCKS_PER_SEC);
  1051.     d_bytes = ll * d_loops * t_loops;
  1052.     d_kbs = (d_secs > 0.001) ? (d_bytes / d_secs) / 1000.0 : 0;
  1053.  
  1054.     if (verbose >= 2)
  1055.     {
  1056.         printf("  compressed into %lu bytes, %.2f%%   %.3f\n",
  1057.             (long) t_len, perc, bits);
  1058.  
  1059.         printf("%-15s %5d: ","overall", t_loops);
  1060.         printf("%10lu bytes, %8.2f secs, %8.2f KB/sec\n",
  1061.                 t_bytes, t_secs, t_kbs);
  1062.         printf("%-15s %5d: ","compress", c_loops);
  1063.         printf("%10lu bytes, %8.2f secs, %8.2f KB/sec\n",
  1064.                 c_bytes, c_secs, c_kbs);
  1065.         printf("%-15s %5d: ","decompress", d_loops);
  1066.         printf("%10lu bytes, %8.2f secs, %8.2f KB/sec\n",
  1067.                 d_bytes, d_secs, d_kbs);
  1068.         printf("\n");
  1069.     }
  1070.  
  1071.     /* create a line for util/table.pl */
  1072.  
  1073.     if (verbose >= 1)
  1074.     {
  1075.         /* get basename */
  1076.         const char *n, *nn;
  1077.         for (nn = n = name; *nn; nn++)
  1078.             if (*nn == '/' || *nn == '\\' || *nn == ':')
  1079.                 n = nn + 1;
  1080.  
  1081.         info(NULL);
  1082.         printf("%-8s | %-14s %7ld %4d %7ld %6.1f %5.2f %8.2f %8.2f |\n",
  1083.             method_name,
  1084.             n, (long) l, blocks, (long) t_len, perc, bits, c_kbs, d_kbs);
  1085.     }
  1086.  
  1087.     if (verbose >= 2)
  1088.         printf("\n");
  1089.  
  1090.     return EXIT_OK;
  1091. }
  1092.  
  1093.  
  1094. /*************************************************************************
  1095. // Calgary Corpus test suite driver
  1096. **************************************************************************/
  1097.  
  1098. static const struct
  1099. {
  1100.     const char *name;
  1101.     int loops;
  1102.     lzo_uint32 adler;
  1103. }
  1104. corpus[] =
  1105. {
  1106.     { "bib",       8,  0x4bd09e98L },
  1107.     { "book1",     1,  0xd4d3613eL },
  1108.     { "book2",     1,  0x6fe14cc3L },
  1109.     { "geo",       6,  0xf3cc5be0L },
  1110.     { "news",      2,  0x2ed405b8L },
  1111.     { "obj1",     35,  0x3887dd2cL },
  1112.     { "obj2",      4,  0xf89407c4L },
  1113.     { "paper1",   17,  0xfe65ce62L },
  1114.     { "paper2",   11,  0x1238b7c2L },
  1115.     { "pic",       4,  0xf61a5702L },
  1116.     { "progc",    25,  0x4c00ba45L },
  1117.     { "progl",    20,  0x4cba738eL },
  1118.     { "progp",    28,  0x7495b92bL },
  1119.     { "trans",    15,  0x52a2cec8L }
  1120. };
  1121.  
  1122.  
  1123. static int do_corpus(const char *path, int c_loops, int d_loops)
  1124. {
  1125.     int i;
  1126.     size_t n;
  1127.     char name[256];
  1128.  
  1129.     if (path == NULL || strlen(path) >= sizeof(name) - 12)
  1130.         return EXIT_USAGE;
  1131.  
  1132.     strcpy(name,path);
  1133.     n = strlen(name);
  1134.     if (n > 0 && name[n-1] != '/' && name[n-1] != '\\')
  1135.     {
  1136.         strcat(name,"/");
  1137.         n++;
  1138.     }
  1139.  
  1140.     for (i = 0; i < (int) (sizeof(corpus)/sizeof(*(corpus))); i++)
  1141.     {
  1142.         lzo_uint32 adler;
  1143.         int c = c_loops * corpus[i].loops;
  1144.         int d = d_loops * corpus[i].loops;
  1145.         int r;
  1146.  
  1147.         strcpy(name+n,corpus[i].name);
  1148.         r = do_file(name, c, d, &adler);
  1149.         if (r != 0)
  1150.             return r;
  1151.         if (adler != corpus[i].adler)
  1152.             return EXIT_ADLER;
  1153.     }
  1154.     return EXIT_OK;
  1155. }
  1156.  
  1157.  
  1158. /*************************************************************************
  1159. //
  1160. **************************************************************************/
  1161.  
  1162. static void usage(const char *name, int show_methods)
  1163. {
  1164.     FILE *f;
  1165.     int i;
  1166.  
  1167.     f = stdout;
  1168.  
  1169.     fflush(stdout); fflush(stderr);
  1170.  
  1171.     fprintf(f,"Usage: %s [option..] file...\n", name);
  1172.     fprintf(f,"\n");
  1173.     fprintf(f,"Options:\n");
  1174.     fprintf(f,"  -m#     compression method\n");
  1175.     fprintf(f,"  -b#     set input block size (default %ld)\n",
  1176.         (long) block_size);
  1177.     fprintf(f,"  -n#     number of compression/decompression runs\n");
  1178.     fprintf(f,"  -c#     number of compression runs\n");
  1179.     fprintf(f,"  -d#     number of decompression runs\n");
  1180.     fprintf(f,"  -z      use assembler decompressor (if available)\n");
  1181.     fprintf(f,"  -s dir  process Calgary Corpus test suite in directory 'dir'\n");
  1182.     fprintf(f,"  -@      read list of files to compress from stdin\n");
  1183.     fprintf(f,"  -q      be quiet\n");
  1184.     fprintf(f,"  -Q      be very quiet\n");
  1185.     fprintf(f,"  -L      display software license\n");
  1186.  
  1187.     if (show_methods)
  1188.     {
  1189.         fprintf(f,"\n");
  1190.         fprintf(f,"The following compression methods are available:\n");
  1191.         fprintf(f,"\n");
  1192.  
  1193.         for (i = 0; i <= M_LAST_COMPRESSOR; i++)
  1194.         {
  1195.             method = i;
  1196.             if (info(NULL))
  1197.             {
  1198.                 char n[16];
  1199.                 sprintf(n,"-m%d",i);
  1200.                 fprintf(f,"  %-6s  %s\n",n,method_name);
  1201.             }
  1202.         }
  1203.     }
  1204.     else
  1205.     {
  1206.         fprintf(f,"\n");
  1207.         fprintf(f,"Type '%s -m' to list all available methods.\n", name);
  1208.     }
  1209.  
  1210.     fflush(f);
  1211.     exit(EXIT_USAGE);
  1212. }
  1213.  
  1214.  
  1215. static void license(void)
  1216. {
  1217.     FILE *f;
  1218.  
  1219.     f = stdout;
  1220.  
  1221.     fflush(stdout); fflush(stderr);
  1222.  
  1223. fprintf(f,
  1224. "   The LZO library is free software; you can redistribute it and/or\n"
  1225. "   modify it under the terms of the GNU General Public License as\n"
  1226. "   published by the Free Software Foundation; either version 2 of\n"
  1227. "   the License, or (at your option) any later version.\n"
  1228. "\n"
  1229. "   The LZO library is distributed in the hope that it will be useful,\n"
  1230. "   but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  1231. "   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  1232. "   GNU General Public License for more details.\n"
  1233. "\n"
  1234. "   You should have received a copy of the GNU General Public License\n"
  1235. "   along with the LZO library; see the file COPYING.\n"
  1236. "   If not, write to the Free Software Foundation, Inc.,\n"
  1237. "   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"
  1238. "\n"
  1239. "   Markus F.X.J. Oberhumer\n"
  1240. "   markus.oberhumer@jk.uni-linz.ac.at\n"
  1241. "\n"
  1242.     );
  1243.  
  1244.     fflush(f);
  1245.     exit(EXIT_OK);
  1246. }
  1247.  
  1248.  
  1249. /*************************************************************************
  1250. //
  1251. **************************************************************************/
  1252.  
  1253. int main(int argc, char *argv[])
  1254. {
  1255.     int i = 1, ii, j = 0;
  1256.     int c_loops = 0;
  1257.     int d_loops = 0;
  1258.     int r = EXIT_OK;
  1259.     const char *corpus_path = NULL;
  1260.     lzo_bool read_from_stdin = 0;
  1261.     const short *methods = NULL;
  1262.     int a_method = 0;
  1263.     const char *argv0 = "";
  1264.     time_t t_total;
  1265.  
  1266. #if defined(__EMX__)
  1267.     _response(&argc,&argv);
  1268.     _wildcard(&argc,&argv);
  1269. #endif
  1270.  
  1271.     argv0 = argv[0];
  1272.     align_mem();
  1273.  
  1274.     printf("\nLZO real-time data compression library (v%s, %s).\n",
  1275.             LZO_VERSION_STRING, LZO_VERSION_DATE);
  1276.     printf("Copyright (C) 1996, 1997 Markus Franz Xaver Johannes Oberhumer\n\n");
  1277.  
  1278.     if (lzo_init() != LZO_E_OK)
  1279.     {
  1280.         printf("lzo_init() failed !!!\n");
  1281.         exit(EXIT_LZO_INIT);
  1282.     }
  1283.  
  1284.     if (argc < 2)
  1285.         usage(argv0,0);
  1286.  
  1287.     if (i < argc && isdigit(argv[i][0]) && argv[i][0] > '0')
  1288.         method = atoi(&argv[i++][0]), methods = NULL;
  1289.  
  1290.     for ( ; i < argc && argv[i][0] == '-'; i++)
  1291.     {
  1292.         char *p = argv[i];
  1293.  
  1294.         if (isdigit(p[1]))
  1295.             method = atoi(p+1), methods = NULL;
  1296.         else if (strncmp(p,"-m",2) == 0)
  1297.         {
  1298.             if (isdigit(p[2]))
  1299.                 method = atoi(p+2), methods = NULL;
  1300.             else if (strcmp(p,"-mall") == 0)
  1301.                 methods = all_methods;
  1302.             else if (strcmp(p,"-mavail") == 0)
  1303.                 methods = avail_methods;
  1304.             else if (strcmp(p,"-mbench") == 0)
  1305.                 methods = benchmark_methods;
  1306.             else if (strcmp(p,"-mx1") == 0)
  1307.                 methods = x1_methods;
  1308.             else if (strcmp(p,"-mx99") == 0)
  1309.                 methods = x99_methods;
  1310.             else if (strcmp(p,"-mx999") == 0)
  1311.                 methods = x999_methods;
  1312.             else if (strcmp(p,"-mzlib") == 0)
  1313.                 methods = zlib_methods;
  1314. #if defined(MFX)
  1315. #  include "contrib/t_opt_m.ch"
  1316. #endif
  1317.             else
  1318.                 usage(argv0,1);
  1319.         }
  1320.         else if (strcmp(p,"-a") == 0)
  1321.             compute_adler32 = 1;
  1322.         else if (strncmp(p,"-b",2) == 0)
  1323.         {
  1324.             if (isdigit(p[2]))
  1325.                 block_size = atoi(p+2);
  1326.             else
  1327.                 block_size = MAX_BLOCK_SIZE;
  1328.         }
  1329.         else if (strncmp(p,"-c",2) == 0 && isdigit(p[2]))
  1330.             c_loops = atoi(p+2);
  1331.         else if (strncmp(p,"-d",2) == 0 && isdigit(p[2]))
  1332.             d_loops = atoi(p+2);
  1333.         else if (strcmp(p,"-h") == 0 || strcmp(p,"-?") == 0)
  1334.             usage(argv0,0);
  1335.         else if (strcmp(p,"--help") == 0)
  1336.             usage(argv0,0);
  1337.         else if (strcmp(p,"-L") == 0 || strcmp(p,"--license") == 0)
  1338.             license();
  1339.         else if (strncmp(p,"-n",2) == 0 && isdigit(p[2]))
  1340.             c_loops = atoi(p+2), d_loops = c_loops;
  1341.         else if (strcmp(p,"-q") == 0)
  1342.             verbose = 1;
  1343.         else if (strcmp(p,"-Q") == 0)
  1344.             verbose = 0;
  1345.         else if (strncmp(p,"-s",2) == 0 && i + 1 < argc)
  1346.         {
  1347.             if (isdigit(p[2]))
  1348.                 c_loops = atoi(p+2), d_loops = c_loops;
  1349.             corpus_path = argv[++i];
  1350.         }
  1351.         else if (strcmp(p,"--version") == 0)
  1352.             exit(r);
  1353.         else if (strcmp(p,"-z") == 0)
  1354.             use_assembler_decompressor = 1;
  1355.         else if (strcmp(p,"-@") == 0)
  1356.             read_from_stdin = 1;
  1357.         else
  1358.         {
  1359.             printf("%s: invalid option '%s'\n\n",argv0,p);
  1360.             usage(argv0,0);
  1361.         }
  1362.     }
  1363.  
  1364.     if (methods != NULL && read_from_stdin)
  1365.     {
  1366.         printf("%s: cannot use multiple methods and '-@'\n", argv0);
  1367.         exit(EXIT_USAGE);
  1368.     }
  1369.  
  1370.     if (block_size < 16)
  1371.         block_size = 16;
  1372.     if (block_size > MAX_BLOCK_SIZE)
  1373.         block_size = MAX_BLOCK_SIZE;
  1374.  
  1375.     t_total = time(NULL);
  1376.     ii = i;
  1377.     do {
  1378.         i = ii;
  1379.         if (i >= argc && corpus_path == NULL && !read_from_stdin)
  1380.             usage(argv0,0);
  1381.         if (methods != NULL && j == 0 && verbose >= 1)
  1382.             printf("%lu block-size\n\n", (long) block_size);
  1383.  
  1384.         if (methods == avail_methods)
  1385.         {
  1386.             lzo_bool found = 0;
  1387.             while (!found && a_method <= M_LAST_COMPRESSOR)
  1388.             {
  1389.                 method = a_method++;
  1390.                 found = info(NULL);
  1391.             }
  1392.             if (!found)
  1393.                 break;
  1394.         }
  1395.         else if (methods != NULL)
  1396.         {
  1397.             while ((method = *methods++) < 0)
  1398.                 ;
  1399.             if (method == 0)
  1400.                 break;
  1401.             if (!info(NULL))
  1402.                 info(stdout);
  1403.         }
  1404.         else
  1405.         {
  1406.             if (!info(NULL))
  1407.                 info(stdout);
  1408.             if (verbose >= 1)
  1409.             {
  1410.                 info(stdout);
  1411.                 printf(" algorithm   %lu block-size\n\n", (long) block_size);
  1412.             }
  1413.         }
  1414.  
  1415.         if (corpus_path != NULL)
  1416.             r = do_corpus(corpus_path,c_loops,d_loops);
  1417.         else
  1418.         {
  1419.             for ( ; i < argc && r == EXIT_OK; i++)
  1420.                 r = do_file(argv[i],c_loops,d_loops,NULL);
  1421.             if (read_from_stdin)
  1422.             {
  1423.                 char buf[512], *p;
  1424.  
  1425.                 while (r == EXIT_OK && fgets(buf,sizeof(buf)-1,stdin) != NULL)
  1426.                 {
  1427.                     buf[sizeof(buf)-1] = 0;
  1428.                     p = buf + strlen(buf);
  1429.                     if (p > buf)
  1430.                         while (--p > buf && isspace(((unsigned char) *p)))
  1431.                             *p = 0;
  1432.                     p = buf;
  1433.                     while (*p && isspace(((unsigned char) *p)))
  1434.                         p++;
  1435.                     if (*p)
  1436.                         r = do_file(p,c_loops,d_loops,NULL);
  1437.                 }
  1438.                 read_from_stdin = 0;
  1439.             }
  1440.         }
  1441.         j++;
  1442.     }
  1443.     while (r == EXIT_OK && methods != NULL);
  1444.  
  1445.     if (r == EXIT_OK && methods != NULL && verbose >= 1)
  1446.     {
  1447.         t_total = time(NULL) - t_total;
  1448.         printf("\nexecution time: %lu seconds\n", (long) t_total);
  1449.     }
  1450.  
  1451.     return r;
  1452. }
  1453.  
  1454. /*
  1455. vi:ts=4
  1456. */
  1457.  
  1458.