lzotest.c 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066
  1. /* lzotest.c -- very comprehensive test driver for the LZO library
  2. This file is part of the LZO real-time data compression library.
  3. Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer
  4. All Rights Reserved.
  5. The LZO library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of
  8. the License, or (at your option) any later version.
  9. The LZO library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with the LZO library; see the file COPYING.
  15. If not, write to the Free Software Foundation, Inc.,
  16. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. Markus F.X.J. Oberhumer
  18. <markus@oberhumer.com>
  19. http://www.oberhumer.com/opensource/lzo/
  20. */
  21. #include <lzo/lzoconf.h>
  22. /*************************************************************************
  23. // util
  24. **************************************************************************/
  25. /* portability layer */
  26. #define WANT_LZO_MALLOC 1
  27. #define WANT_LZO_FREAD 1
  28. #define WANT_LZO_WILDARGV 1
  29. #define WANT_LZO_PCLOCK 1
  30. #define LZO_WANT_ACCLIB_GETOPT 1
  31. #include "examples/portab.h"
  32. #if defined(HAVE_STRNICMP) && !defined(HAVE_STRNCASECMP)
  33. # define strncasecmp(a,b,c) strnicmp(a,b,c)
  34. # define HAVE_STRNCASECMP 1
  35. #endif
  36. #if 0
  37. # define is_digit(x) (isdigit((unsigned char)(x)))
  38. # define is_space(x) (isspace((unsigned char)(x)))
  39. #else
  40. # define is_digit(x) ((unsigned)(x) - '0' <= 9)
  41. # define is_space(x) ((x)==' ' || (x)=='\t' || (x)=='\r' || (x)=='\n')
  42. #endif
  43. /*************************************************************************
  44. // compression include section
  45. **************************************************************************/
  46. #define HAVE_LZO1_H 1
  47. #define HAVE_LZO1A_H 1
  48. #define HAVE_LZO1B_H 1
  49. #define HAVE_LZO1C_H 1
  50. #define HAVE_LZO1F_H 1
  51. #define HAVE_LZO1X_H 1
  52. #define HAVE_LZO1Y_H 1
  53. #define HAVE_LZO1Z_H 1
  54. #define HAVE_LZO2A_H 1
  55. #if defined(NO_ZLIB_H) || (SIZEOF_INT < 4)
  56. #undef HAVE_ZLIB_H
  57. #endif
  58. #if defined(NO_BZLIB_H) || (SIZEOF_INT != 4)
  59. #undef HAVE_BZLIB_H
  60. #endif
  61. #if 0 && defined(LZO_OS_DOS16)
  62. /* don't make this test program too big */
  63. #undef HAVE_LZO1_H
  64. #undef HAVE_LZO1A_H
  65. #undef HAVE_LZO1C_H
  66. #undef HAVE_LZO1Z_H
  67. #undef HAVE_LZO2A_H
  68. #undef HAVE_LZO2B_H
  69. #undef HAVE_ZLIB_H
  70. #endif
  71. /* LZO algorithms */
  72. #if defined(HAVE_LZO1_H)
  73. # include <lzo/lzo1.h>
  74. #endif
  75. #if defined(HAVE_LZO1A_H)
  76. # include <lzo/lzo1a.h>
  77. #endif
  78. #if defined(HAVE_LZO1B_H)
  79. # include <lzo/lzo1b.h>
  80. #endif
  81. #if defined(HAVE_LZO1C_H)
  82. # include <lzo/lzo1c.h>
  83. #endif
  84. #if defined(HAVE_LZO1F_H)
  85. # include <lzo/lzo1f.h>
  86. #endif
  87. #if defined(HAVE_LZO1X_H)
  88. # include <lzo/lzo1x.h>
  89. #endif
  90. #if defined(HAVE_LZO1Y_H)
  91. # include <lzo/lzo1y.h>
  92. #endif
  93. #if defined(HAVE_LZO1Z_H)
  94. # include <lzo/lzo1z.h>
  95. #endif
  96. #if defined(HAVE_LZO2A_H)
  97. # include <lzo/lzo2a.h>
  98. #endif
  99. #if defined(HAVE_LZO2B_H)
  100. # include <lzo/lzo2b.h>
  101. #endif
  102. /* other compressors */
  103. #if defined(HAVE_ZLIB_H)
  104. # include <zlib.h>
  105. # define ALG_ZLIB 1
  106. #endif
  107. #if defined(HAVE_BZLIB_H)
  108. # include <bzlib.h>
  109. # define ALG_BZIP2 1
  110. #endif
  111. /*************************************************************************
  112. // enumerate all methods
  113. **************************************************************************/
  114. enum {
  115. /* compression algorithms */
  116. M_LZO1B_1 = 1,
  117. M_LZO1B_2, M_LZO1B_3, M_LZO1B_4, M_LZO1B_5,
  118. M_LZO1B_6, M_LZO1B_7, M_LZO1B_8, M_LZO1B_9,
  119. M_LZO1C_1 = 11,
  120. M_LZO1C_2, M_LZO1C_3, M_LZO1C_4, M_LZO1C_5,
  121. M_LZO1C_6, M_LZO1C_7, M_LZO1C_8, M_LZO1C_9,
  122. M_LZO1 = 21,
  123. M_LZO1A = 31,
  124. M_LZO1B_99 = 901,
  125. M_LZO1B_999 = 902,
  126. M_LZO1C_99 = 911,
  127. M_LZO1C_999 = 912,
  128. M_LZO1_99 = 921,
  129. M_LZO1A_99 = 931,
  130. M_LZO1F_1 = 61,
  131. M_LZO1F_999 = 962,
  132. M_LZO1X_1 = 71,
  133. M_LZO1X_1_11 = 111,
  134. M_LZO1X_1_12 = 112,
  135. M_LZO1X_1_15 = 115,
  136. M_LZO1X_999 = 972,
  137. M_LZO1Y_1 = 81,
  138. M_LZO1Y_999 = 982,
  139. M_LZO1Z_999 = 992,
  140. M_LZO2A_999 = 942,
  141. M_LZO2B_999 = 952,
  142. M_LAST_LZO_COMPRESSOR = 998,
  143. /* other compressors */
  144. #if defined(ALG_ZLIB)
  145. M_ZLIB_8_1 = 1101,
  146. M_ZLIB_8_2, M_ZLIB_8_3, M_ZLIB_8_4, M_ZLIB_8_5,
  147. M_ZLIB_8_6, M_ZLIB_8_7, M_ZLIB_8_8, M_ZLIB_8_9,
  148. #endif
  149. #if defined(ALG_BZIP2)
  150. M_BZIP2_1 = 1201,
  151. M_BZIP2_2, M_BZIP2_3, M_BZIP2_4, M_BZIP2_5,
  152. M_BZIP2_6, M_BZIP2_7, M_BZIP2_8, M_BZIP2_9,
  153. #endif
  154. /* dummy compressor - for benchmarking */
  155. M_MEMCPY = 999,
  156. M_LAST_COMPRESSOR = 4999,
  157. /* dummy algorithms - for benchmarking */
  158. M_MEMSET = 5001,
  159. /* checksum algorithms - for benchmarking */
  160. M_ADLER32 = 6001,
  161. M_CRC32 = 6002,
  162. #if defined(ALG_ZLIB)
  163. M_Z_ADLER32 = 6011,
  164. M_Z_CRC32 = 6012,
  165. #endif
  166. M_UNUSED
  167. };
  168. /*************************************************************************
  169. // command line options
  170. **************************************************************************/
  171. int opt_verbose = 2;
  172. long opt_c_loops = 0;
  173. long opt_d_loops = 0;
  174. const char *opt_corpus_path = NULL;
  175. const char *opt_dump_compressed_data = NULL;
  176. lzo_bool opt_use_safe_decompressor = 0;
  177. lzo_bool opt_use_asm_decompressor = 0;
  178. lzo_bool opt_use_asm_fast_decompressor = 0;
  179. lzo_bool opt_optimize_compressed_data = 0;
  180. int opt_dict = 0;
  181. lzo_uint opt_max_dict_len = LZO_UINT_MAX;
  182. const char *opt_dictionary_file = NULL;
  183. lzo_bool opt_read_from_stdin = 0;
  184. /* set these to 1 to measure the speed impact of a checksum */
  185. lzo_bool opt_compute_adler32 = 0;
  186. lzo_bool opt_compute_crc32 = 0;
  187. static lzo_uint32_t adler_in, adler_out;
  188. static lzo_uint32_t crc_in, crc_out;
  189. lzo_bool opt_execution_time = 0;
  190. int opt_pclock = -1;
  191. lzo_bool opt_clear_wrkmem = 0;
  192. static const lzo_bool opt_try_to_compress_0_bytes = 1;
  193. /*************************************************************************
  194. // misc globals
  195. **************************************************************************/
  196. static const char *progname = "";
  197. static lzo_pclock_handle_t pch;
  198. /* for statistics and benchmark */
  199. int opt_totals = 0;
  200. static unsigned long total_n = 0;
  201. static unsigned long total_c_len = 0;
  202. static unsigned long total_d_len = 0;
  203. static unsigned long total_blocks = 0;
  204. static double total_perc = 0.0;
  205. static const char *total_method_name = NULL;
  206. static unsigned total_method_names = 0;
  207. /* Note: the average value of a rate (e.g. compression speed) is defined
  208. * by the Harmonic Mean (and _not_ by the Arithmethic Mean ) */
  209. static unsigned long total_c_mbs_n = 0;
  210. static unsigned long total_d_mbs_n = 0;
  211. static double total_c_mbs_harmonic = 0.0;
  212. static double total_d_mbs_harmonic = 0.0;
  213. static double total_c_mbs_sum = 0.0;
  214. static double total_d_mbs_sum = 0.0;
  215. #if defined(HAVE_LZO1X_H)
  216. int default_method = M_LZO1X_1;
  217. #elif defined(HAVE_LZO1B_H)
  218. int default_method = M_LZO1B_1;
  219. #elif defined(HAVE_LZO1C_H)
  220. int default_method = M_LZO1C_1;
  221. #elif defined(HAVE_LZO1F_H)
  222. int default_method = M_LZO1F_1;
  223. #elif defined(HAVE_LZO1Y_H)
  224. int default_method = M_LZO1Y_1;
  225. #else
  226. int default_method = M_MEMCPY;
  227. #endif
  228. static const int benchmark_methods[] = {
  229. M_LZO1B_1, M_LZO1B_9,
  230. M_LZO1C_1, M_LZO1C_9,
  231. M_LZO1F_1,
  232. M_LZO1X_1,
  233. 0
  234. };
  235. static const int x1_methods[] = {
  236. M_LZO1, M_LZO1A, M_LZO1B_1, M_LZO1C_1, M_LZO1F_1, M_LZO1X_1, M_LZO1Y_1,
  237. 0
  238. };
  239. static const int x99_methods[] = {
  240. M_LZO1_99, M_LZO1A_99, M_LZO1B_99, M_LZO1C_99,
  241. 0
  242. };
  243. static const int x999_methods[] = {
  244. M_LZO1B_999, M_LZO1C_999, M_LZO1F_999, M_LZO1X_999, M_LZO1Y_999,
  245. M_LZO1Z_999,
  246. M_LZO2A_999,
  247. 0
  248. };
  249. /* exit codes of this test program */
  250. #define EXIT_OK 0
  251. #define EXIT_USAGE 1
  252. #define EXIT_FILE 2
  253. #define EXIT_MEM 3
  254. #define EXIT_ADLER 4
  255. #define EXIT_LZO_ERROR 5
  256. #define EXIT_LZO_INIT 6
  257. #define EXIT_INTERNAL 7
  258. /*************************************************************************
  259. // memory setup
  260. **************************************************************************/
  261. static lzo_uint opt_block_size;
  262. static lzo_uint opt_max_data_len;
  263. typedef struct {
  264. lzo_bytep ptr;
  265. lzo_uint len;
  266. lzo_uint32_t adler;
  267. lzo_uint32_t crc;
  268. lzo_bytep alloc_ptr;
  269. lzo_uint alloc_len;
  270. lzo_uint saved_len;
  271. } mblock_t;
  272. static mblock_t file_data; /* original uncompressed data */
  273. static mblock_t block_c; /* compressed data */
  274. static mblock_t block_d; /* decompressed data */
  275. static mblock_t block_w; /* wrkmem */
  276. static mblock_t dict;
  277. static void mb_alloc_extra(mblock_t *mb, lzo_uint len, lzo_uint extra_bottom, lzo_uint extra_top)
  278. {
  279. lzo_uint align = (lzo_uint) sizeof(lzo_align_t);
  280. mb->alloc_ptr = mb->ptr = NULL;
  281. mb->alloc_len = mb->len = 0;
  282. mb->alloc_len = extra_bottom + len + extra_top;
  283. if (mb->alloc_len == 0) mb->alloc_len = 1;
  284. mb->alloc_ptr = (lzo_bytep) lzo_malloc(mb->alloc_len);
  285. if (mb->alloc_ptr == NULL) {
  286. fprintf(stderr, "%s: out of memory (wanted %lu bytes)\n", progname, (unsigned long)mb->alloc_len);
  287. exit(EXIT_MEM);
  288. }
  289. if (mb->alloc_len >= align && __lzo_align_gap(mb->alloc_ptr, align) != 0) {
  290. fprintf(stderr, "%s: C library problem: malloc() returned misaligned pointer!\n", progname);
  291. exit(EXIT_MEM);
  292. }
  293. mb->ptr = mb->alloc_ptr + extra_bottom;
  294. mb->len = mb->saved_len = len;
  295. mb->adler = 1;
  296. mb->crc = 0;
  297. }
  298. static void mb_alloc(mblock_t *mb, lzo_uint len)
  299. {
  300. mb_alloc_extra(mb, len, 0, 0);
  301. }
  302. static void mb_free(mblock_t *mb)
  303. {
  304. if (!mb) return;
  305. if (mb->alloc_ptr) lzo_free(mb->alloc_ptr);
  306. mb->alloc_ptr = mb->ptr = NULL;
  307. mb->alloc_len = mb->len = 0;
  308. }
  309. static lzo_uint get_max_compression_expansion(int m, lzo_uint bl)
  310. {
  311. if (m == M_MEMCPY || m >= M_LAST_COMPRESSOR)
  312. return 0;
  313. if (m == M_LZO2A_999 || m == M_LZO2B_999)
  314. return bl / 8 + 256;
  315. if (m > 0 && m < M_LAST_LZO_COMPRESSOR)
  316. return bl / 16 + 64 + 3;
  317. return bl / 8 + 256;
  318. }
  319. static lzo_uint get_max_decompression_overrun(int m, lzo_uint bl)
  320. {
  321. LZO_UNUSED(m);
  322. LZO_UNUSED(bl);
  323. /* may overwrite 3 bytes past the end of the decompressed block */
  324. if (opt_use_asm_fast_decompressor)
  325. return (lzo_uint) sizeof(lzo_voidp) - 1;
  326. return 0;
  327. }
  328. /*************************************************************************
  329. // dictionary support
  330. **************************************************************************/
  331. static void dict_alloc(lzo_uint max_dict_len)
  332. {
  333. lzo_uint l = 0xbfff; /* MAX_DICT_LEN */
  334. if (max_dict_len > 0 && l > max_dict_len)
  335. l = max_dict_len;
  336. mb_alloc(&dict, l);
  337. }
  338. /* this default dictionary does not provide good contexts... */
  339. static void dict_set_default(void)
  340. {
  341. lzo_uint d = 0;
  342. unsigned i, j;
  343. dict.len = 16 * 256;
  344. if (dict.len > dict.alloc_len)
  345. dict.len = dict.alloc_len;
  346. lzo_memset(dict.ptr, 0, dict.len);
  347. for (i = 0; i < 256; i++)
  348. for (j = 0; j < 16; j++) {
  349. if (d >= dict.len)
  350. goto done;
  351. dict.ptr[d++] = (unsigned char) i;
  352. }
  353. done:
  354. dict.adler = lzo_adler32(1, dict.ptr, dict.len);
  355. }
  356. static void dict_load(const char *file_name)
  357. {
  358. FILE *fp;
  359. dict.len = 0;
  360. fp = fopen(file_name, "rb");
  361. if (fp)
  362. {
  363. dict.len = (lzo_uint) lzo_fread(fp, dict.ptr, dict.alloc_len);
  364. (void) fclose(fp);
  365. dict.adler = lzo_adler32(1, dict.ptr, dict.len);
  366. }
  367. }
  368. /*************************************************************************
  369. // compression database
  370. **************************************************************************/
  371. typedef struct
  372. {
  373. const char * name;
  374. int id;
  375. lzo_uint32_t mem_compress;
  376. lzo_uint32_t mem_decompress;
  377. lzo_compress_t compress;
  378. lzo_optimize_t optimize;
  379. lzo_decompress_t decompress;
  380. lzo_decompress_t decompress_safe;
  381. lzo_decompress_t decompress_asm;
  382. lzo_decompress_t decompress_asm_safe;
  383. lzo_decompress_t decompress_asm_fast;
  384. lzo_decompress_t decompress_asm_fast_safe;
  385. lzo_compress_dict_t compress_dict;
  386. lzo_decompress_dict_t decompress_dict_safe;
  387. }
  388. compress_t;
  389. #include "asm.h"
  390. #ifdef __cplusplus
  391. extern "C" {
  392. #endif
  393. #include "wrap.h"
  394. #define M_PRIVATE LZO_PRIVATE
  395. #define m_uint lzo_uint
  396. #define m_uint32_t lzo_uint32_t
  397. #define m_voidp lzo_voidp
  398. #define m_bytep lzo_bytep
  399. #define m_uintp lzo_uintp
  400. #include "wrapmisc.h"
  401. #ifdef __cplusplus
  402. } /* extern "C" */
  403. #endif
  404. static const compress_t compress_database[] = {
  405. #include "db.h"
  406. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
  407. };
  408. /*************************************************************************
  409. // method info
  410. **************************************************************************/
  411. static
  412. lzo_decompress_t get_decomp_info ( const compress_t *c, const char **nn )
  413. {
  414. lzo_decompress_t d = 0;
  415. const char *n = NULL;
  416. /* safe has priority over asm/fast */
  417. if (!d && opt_use_safe_decompressor && opt_use_asm_fast_decompressor)
  418. {
  419. d = c->decompress_asm_fast_safe;
  420. n = " [fs]";
  421. }
  422. if (!d && opt_use_safe_decompressor && opt_use_asm_decompressor)
  423. {
  424. d = c->decompress_asm_safe;
  425. n = " [as]";
  426. }
  427. if (!d && opt_use_safe_decompressor)
  428. {
  429. d = c->decompress_safe;
  430. n = " [s]";
  431. }
  432. if (!d && opt_use_asm_fast_decompressor)
  433. {
  434. d = c->decompress_asm_fast;
  435. n = " [f]";
  436. }
  437. if (!d && opt_use_asm_decompressor)
  438. {
  439. d = c->decompress_asm;
  440. n = " [a]";
  441. }
  442. if (!d)
  443. {
  444. d = c->decompress;
  445. n = "";
  446. }
  447. if (!d)
  448. n = "(null)";
  449. if (opt_dict && c->decompress_dict_safe)
  450. n = "";
  451. if (nn)
  452. *nn = n;
  453. return d;
  454. }
  455. static
  456. const compress_t *find_method_by_id ( int method )
  457. {
  458. const compress_t *db;
  459. size_t size = sizeof(compress_database) / sizeof(*(compress_database));
  460. size_t i;
  461. db = compress_database;
  462. for (i = 0; i < size && db->name != NULL; i++, db++)
  463. {
  464. if (method == db->id)
  465. return db;
  466. }
  467. return NULL;
  468. }
  469. static
  470. const compress_t *find_method_by_name ( const char *name )
  471. {
  472. const compress_t *db;
  473. size_t size = sizeof(compress_database) / sizeof(*(compress_database));
  474. size_t i;
  475. db = compress_database;
  476. for (i = 0; i < size && db->name != NULL; i++, db++)
  477. {
  478. size_t n = strlen(db->name);
  479. #if defined(HAVE_STRNCASECMP)
  480. if (strncasecmp(name,db->name,n) == 0 && (!name[n] || name[n] == ','))
  481. return db;
  482. #else
  483. if (strncmp(name,db->name,n) == 0 && (!name[n] || name[n] == ','))
  484. return db;
  485. #endif
  486. }
  487. return NULL;
  488. }
  489. static
  490. lzo_bool is_compressor ( const compress_t *c )
  491. {
  492. return (c->id <= M_LAST_COMPRESSOR || c->id >= 9721);
  493. }
  494. /*************************************************************************
  495. // check that memory gets accessed within bounds
  496. **************************************************************************/
  497. static void memchecker_init ( mblock_t *mb, lzo_uint l, unsigned char random_byte )
  498. {
  499. lzo_uint i;
  500. lzo_uint len = (lzo_uint) l;
  501. lzo_bytep p;
  502. assert(len <= mb->len);
  503. /* bottom */
  504. p = mb->ptr;
  505. for (i = 0; i < 16 && p > mb->alloc_ptr; i++)
  506. *--p = random_byte++;
  507. /* top */
  508. p = mb->ptr + len;
  509. for (i = 0; i < 16 && p < mb->alloc_ptr + mb->alloc_len; i++)
  510. *p++ = random_byte++;
  511. #if 0 || defined(LZO_DEBUG)
  512. /* fill in garbage */
  513. p = mb->ptr;
  514. random_byte |= 1;
  515. for (i = 0; i < len; i++, random_byte += 2)
  516. *p++ = random_byte;
  517. #endif
  518. }
  519. static int memchecker_check ( mblock_t *mb, lzo_uint l, unsigned char random_byte )
  520. {
  521. lzo_uint i;
  522. lzo_uint len = (lzo_uint) l;
  523. lzo_bytep p;
  524. assert(len <= mb->len);
  525. /* bottom */
  526. p = mb->ptr;
  527. for (i = 0; i < 16 && p > mb->alloc_ptr; i++)
  528. if (*--p != random_byte++)
  529. return -1;
  530. /* top */
  531. p = mb->ptr + len;
  532. for (i = 0; i < 16 && p < mb->alloc_ptr + mb->alloc_len; i++)
  533. if (*p++ != random_byte++)
  534. return -1;
  535. return 0;
  536. }
  537. /*************************************************************************
  538. // compress a block
  539. **************************************************************************/
  540. static
  541. int call_compressor ( const compress_t *c,
  542. const lzo_bytep src, lzo_uint src_len,
  543. lzo_bytep dst, lzo_uintp dst_len )
  544. {
  545. int r = -100;
  546. if (c && c->compress && block_w.len >= c->mem_compress)
  547. {
  548. unsigned char random_byte = (unsigned char) src_len;
  549. memchecker_init(&block_w, c->mem_compress, random_byte);
  550. if (opt_clear_wrkmem)
  551. lzo_memset(block_w.ptr, 0, c->mem_compress);
  552. if (opt_dict && c->compress_dict)
  553. r = c->compress_dict(src,src_len,dst,dst_len,block_w.ptr,dict.ptr,dict.len);
  554. else
  555. r = c->compress(src,src_len,dst,dst_len,block_w.ptr);
  556. if (memchecker_check(&block_w, c->mem_compress, random_byte) != 0)
  557. printf("WARNING: wrkmem overwrite error (compress) !!!\n");
  558. }
  559. if (r == 0 && opt_compute_adler32)
  560. {
  561. lzo_uint32_t adler;
  562. adler = lzo_adler32(0, NULL, 0);
  563. adler = lzo_adler32(adler, src, src_len);
  564. adler_in = adler;
  565. }
  566. if (r == 0 && opt_compute_crc32)
  567. {
  568. lzo_uint32_t crc;
  569. crc = lzo_crc32(0, NULL, 0);
  570. crc = lzo_crc32(crc, src, src_len);
  571. crc_in = crc;
  572. }
  573. return r;
  574. }
  575. /*************************************************************************
  576. // decompress a block
  577. **************************************************************************/
  578. static
  579. int call_decompressor ( const compress_t *c, lzo_decompress_t d,
  580. const lzo_bytep src, lzo_uint src_len,
  581. lzo_bytep dst, lzo_uintp dst_len )
  582. {
  583. int r = -100;
  584. if (c && d && block_w.len >= c->mem_decompress)
  585. {
  586. unsigned char random_byte = (unsigned char) src_len;
  587. memchecker_init(&block_w, c->mem_decompress, random_byte);
  588. if (opt_clear_wrkmem)
  589. lzo_memset(block_w.ptr, 0, c->mem_decompress);
  590. if (opt_dict && c->decompress_dict_safe)
  591. r = c->decompress_dict_safe(src,src_len,dst,dst_len,block_w.ptr,dict.ptr,dict.len);
  592. else
  593. r = d(src,src_len,dst,dst_len,block_w.ptr);
  594. if (memchecker_check(&block_w, c->mem_decompress, random_byte) != 0)
  595. printf("WARNING: wrkmem overwrite error (decompress) !!!\n");
  596. }
  597. if (r == 0 && opt_compute_adler32)
  598. adler_out = lzo_adler32(1, dst, *dst_len);
  599. if (r == 0 && opt_compute_crc32)
  600. crc_out = lzo_crc32(0, dst, *dst_len);
  601. return r;
  602. }
  603. /*************************************************************************
  604. // optimize a block
  605. **************************************************************************/
  606. static
  607. int call_optimizer ( const compress_t *c,
  608. lzo_bytep src, lzo_uint src_len,
  609. lzo_bytep dst, lzo_uintp dst_len )
  610. {
  611. if (c && c->optimize && block_w.len >= c->mem_decompress)
  612. return c->optimize(src,src_len,dst,dst_len,block_w.ptr);
  613. return 0;
  614. }
  615. /***********************************************************************
  616. // read a file
  617. ************************************************************************/
  618. static int load_file(const char *file_name, lzo_uint max_data_len)
  619. {
  620. FILE *fp;
  621. #if (HAVE_FTELLO)
  622. off_t ll = -1;
  623. #else
  624. long ll = -1;
  625. #endif
  626. lzo_uint l;
  627. int r;
  628. mblock_t *mb = &file_data;
  629. mb_free(mb);
  630. fp = fopen(file_name, "rb");
  631. if (fp == NULL)
  632. {
  633. fflush(stdout); fflush(stderr);
  634. fprintf(stderr, "%s: ", file_name);
  635. fflush(stderr);
  636. perror("fopen");
  637. fflush(stdout); fflush(stderr);
  638. return EXIT_FILE;
  639. }
  640. r = fseek(fp, 0, SEEK_END);
  641. if (r == 0)
  642. {
  643. #if (HAVE_FTELLO)
  644. ll = ftello(fp);
  645. #else
  646. ll = ftell(fp);
  647. #endif
  648. r = fseek(fp, 0, SEEK_SET);
  649. }
  650. if (r != 0 || ll < 0)
  651. {
  652. fflush(stdout); fflush(stderr);
  653. fprintf(stderr, "%s: ", file_name);
  654. fflush(stderr);
  655. perror("fseek");
  656. fflush(stdout); fflush(stderr);
  657. (void) fclose(fp);
  658. return EXIT_FILE;
  659. }
  660. l = (lzo_uint) ll;
  661. if (l > max_data_len) l = max_data_len;
  662. #if (HAVE_FTELLO)
  663. if ((off_t) l != ll) l = max_data_len;
  664. #else
  665. if ((long) l != ll) l = max_data_len;
  666. #endif
  667. mb_alloc(mb, l);
  668. mb->len = (lzo_uint) lzo_fread(fp, mb->ptr, mb->len);
  669. r = ferror(fp);
  670. if (fclose(fp) != 0 || r != 0)
  671. {
  672. mb_free(mb);
  673. fflush(stdout); fflush(stderr);
  674. fprintf(stderr, "%s: ", file_name);
  675. fflush(stderr);
  676. perror("fclose");
  677. fflush(stdout); fflush(stderr);
  678. return EXIT_FILE;
  679. }
  680. return EXIT_OK;
  681. }
  682. /***********************************************************************
  683. // print some compression statistics
  684. ************************************************************************/
  685. static double t_div(double a, double b)
  686. {
  687. return b > 0.00001 ? a / b : 0;
  688. }
  689. static double set_perc_d(double perc, char *s)
  690. {
  691. if (perc <= 0.0) {
  692. strcpy(s, "0.0");
  693. return 0;
  694. }
  695. if (perc <= 100 - 1.0 / 16) {
  696. sprintf(s, "%4.1f", perc);
  697. }
  698. else {
  699. long p = (long) (perc + 0.5);
  700. if (p < 100)
  701. strcpy(s, "???");
  702. else if (p >= 9999)
  703. strcpy(s, "9999");
  704. else
  705. sprintf(s, "%ld", p);
  706. }
  707. return perc;
  708. }
  709. static double set_perc(unsigned long c_len, unsigned long d_len, char *s)
  710. {
  711. double perc = 0.0;
  712. if (d_len > 0)
  713. perc = c_len * 100.0 / d_len;
  714. return set_perc_d(perc, s);
  715. }
  716. static
  717. void print_stats ( const char *method_name, const char *file_name,
  718. long t_loops, long c_loops, long d_loops,
  719. double t_secs, double c_secs, double d_secs,
  720. unsigned long c_len, unsigned long d_len,
  721. unsigned long blocks )
  722. {
  723. unsigned long x_len = d_len;
  724. unsigned long t_bytes, c_bytes, d_bytes;
  725. double c_mbs, d_mbs, t_mbs;
  726. double perc;
  727. char perc_str[4+1];
  728. perc = set_perc(c_len, d_len, perc_str);
  729. c_bytes = x_len * c_loops * t_loops;
  730. d_bytes = x_len * d_loops * t_loops;
  731. t_bytes = c_bytes + d_bytes;
  732. if (opt_pclock == 0)
  733. c_secs = d_secs = t_secs = 0.0;
  734. /* speed in uncompressed megabytes per second (1 megabyte = 1.000.000 bytes) */
  735. c_mbs = (c_secs > 0.001) ? (c_bytes / c_secs) / 1000000.0 : 0;
  736. d_mbs = (d_secs > 0.001) ? (d_bytes / d_secs) / 1000000.0 : 0;
  737. t_mbs = (t_secs > 0.001) ? (t_bytes / t_secs) / 1000000.0 : 0;
  738. total_n++;
  739. total_c_len += c_len;
  740. total_d_len += d_len;
  741. total_blocks += blocks;
  742. total_perc += perc;
  743. if (c_mbs > 0) {
  744. total_c_mbs_n += 1;
  745. total_c_mbs_harmonic += 1.0 / c_mbs;
  746. total_c_mbs_sum += c_mbs;
  747. }
  748. if (d_mbs > 0) {
  749. total_d_mbs_n += 1;
  750. total_d_mbs_harmonic += 1.0 / d_mbs;
  751. total_d_mbs_sum += d_mbs;
  752. }
  753. if (opt_verbose >= 2)
  754. {
  755. printf(" compressed into %lu bytes, %s%% (%s%.3f bits/byte)\n",
  756. c_len, perc_str, "", perc * 0.08);
  757. #if 0
  758. printf("%-15s %5ld: ","overall", t_loops);
  759. printf("%10lu bytes, %8.2f secs, %8.3f MB/sec\n",
  760. t_bytes, t_secs, t_mbs);
  761. #else
  762. LZO_UNUSED(t_mbs);
  763. #endif
  764. printf("%-15s %5ld: ","compress", c_loops);
  765. printf("%10lu bytes, %8.2f secs, %8.3f MB/sec\n",
  766. c_bytes, c_secs, c_mbs);
  767. printf("%-15s %5ld: ","decompress", d_loops);
  768. printf("%10lu bytes, %8.2f secs, %8.3f MB/sec\n",
  769. d_bytes, d_secs, d_mbs);
  770. printf("\n");
  771. }
  772. /* create a line for util/table.pl */
  773. if (opt_verbose >= 1)
  774. {
  775. /* get basename */
  776. const char *n, *nn, *b;
  777. for (nn = n = b = file_name; *nn; nn++)
  778. if (*nn == '/' || *nn == '\\' || *nn == ':')
  779. b = nn + 1;
  780. else
  781. n = b;
  782. printf("%-13s| %-14s %8lu %4lu %9lu %4s %s%8.3f %8.3f |\n",
  783. method_name, n, d_len, blocks, c_len, perc_str, "", c_mbs, d_mbs);
  784. }
  785. if (opt_verbose >= 2)
  786. printf("\n");
  787. }
  788. static
  789. void print_totals ( void )
  790. {
  791. char perc_str[4+1];
  792. if ((opt_verbose >= 1 && total_n > 1) || (opt_totals >= 2))
  793. {
  794. unsigned long n = total_n > 0 ? total_n : 1;
  795. const char *t1 = "-------";
  796. const char *t2 = total_method_names == 1 ? total_method_name : "";
  797. #if 1 && defined(__LZOLIB_PCLOCK_CH_INCLUDED)
  798. char pclock_mode[32+1];
  799. sprintf(pclock_mode, "[clock=%d]", pch.mode);
  800. t1 = pclock_mode;
  801. if (opt_pclock == 0) t1 = t2;
  802. #endif
  803. #if 1
  804. set_perc_d(total_perc / n, perc_str);
  805. printf("%-13s %-12s %10lu %4.1f %9lu %4s %8.3f %8.3f\n",
  806. t1, "***AVG***",
  807. total_d_len / n, total_blocks * 1.0 / n, total_c_len / n, perc_str,
  808. t_div((double)total_c_mbs_n, total_c_mbs_harmonic),
  809. t_div((double)total_d_mbs_n, total_d_mbs_harmonic));
  810. #endif
  811. set_perc(total_c_len, total_d_len, perc_str);
  812. printf("%-13s %-12s %10lu %4lu %9lu %4s %s%8.3f %8.3f\n",
  813. t2, "***TOTALS***",
  814. total_d_len, total_blocks, total_c_len, perc_str, "",
  815. t_div((double)total_c_mbs_n, total_c_mbs_harmonic),
  816. t_div((double)total_d_mbs_n, total_d_mbs_harmonic));
  817. }
  818. }
  819. /*************************************************************************
  820. // compress and decompress a file
  821. **************************************************************************/
  822. static __lzo_noinline
  823. int process_file ( const compress_t *c, lzo_decompress_t decompress,
  824. const char *method_name,
  825. const char *file_name,
  826. long t_loops, long c_loops, long d_loops )
  827. {
  828. long t_i;
  829. unsigned long blocks = 0;
  830. unsigned long compressed_len = 0;
  831. double t_time = 0, c_time = 0, d_time = 0;
  832. lzo_pclock_t t_start, t_stop, x_start, x_stop;
  833. FILE *fp_dump = NULL;
  834. if (opt_dump_compressed_data)
  835. fp_dump = fopen(opt_dump_compressed_data,"wb");
  836. /* process the file */
  837. lzo_pclock_flush_cpu_cache(&pch, 0);
  838. lzo_pclock_read(&pch, &t_start);
  839. for (t_i = 0; t_i < t_loops; t_i++)
  840. {
  841. lzo_uint len, c_len, c_len_max, d_len = 0;
  842. const lzo_bytep d = file_data.ptr;
  843. len = file_data.len;
  844. c_len = 0;
  845. blocks = 0;
  846. /* process blocks */
  847. if (len > 0 || opt_try_to_compress_0_bytes) do
  848. {
  849. lzo_uint bl;
  850. long c_i;
  851. int r;
  852. unsigned char random_byte = (unsigned char) file_data.len;
  853. #if 1 && defined(CLOCKS_PER_SEC)
  854. random_byte = (unsigned char) (random_byte ^ clock());
  855. #endif
  856. blocks++;
  857. bl = len > opt_block_size ? opt_block_size : len;
  858. /* update lengths for memchecker_xxx() */
  859. block_c.len = bl + get_max_compression_expansion(c->id, bl);
  860. block_d.len = bl + get_max_decompression_overrun(c->id, bl);
  861. #if defined(__LZO_CHECKER)
  862. /* malloc a block of the exact size to detect any overrun */
  863. assert(block_c.alloc_ptr == NULL);
  864. assert(block_d.alloc_ptr == NULL);
  865. mb_alloc(&block_c, block_c.len);
  866. mb_alloc(&block_d, block_d.len);
  867. #endif
  868. assert(block_c.len <= block_c.saved_len);
  869. assert(block_d.len <= block_d.saved_len);
  870. memchecker_init(&block_c, block_c.len, random_byte);
  871. memchecker_init(&block_d, block_d.len, random_byte);
  872. /* compress the block */
  873. c_len = c_len_max = 0;
  874. lzo_pclock_flush_cpu_cache(&pch, 0);
  875. lzo_pclock_read(&pch, &x_start);
  876. for (r = 0, c_i = 0; c_i < c_loops; c_i++)
  877. {
  878. c_len = block_c.len;
  879. r = call_compressor(c, d, bl, block_c.ptr, &c_len);
  880. if (r != 0)
  881. break;
  882. if (c_len > c_len_max)
  883. c_len_max = c_len;
  884. if (c_len > block_c.len)
  885. goto compress_overrun;
  886. }
  887. lzo_pclock_read(&pch, &x_stop);
  888. c_time += lzo_pclock_get_elapsed(&pch, &x_start, &x_stop);
  889. if (r != 0)
  890. {
  891. printf(" compression failed in block %lu (%d) (%lu %lu)\n",
  892. blocks, r, (unsigned long)c_len, (unsigned long)bl);
  893. return EXIT_LZO_ERROR;
  894. }
  895. if (memchecker_check(&block_c, block_c.len, random_byte) != 0)
  896. {
  897. compress_overrun:
  898. printf(" compression overwrite error in block %lu "
  899. "(%lu %lu %lu %lu)\n",
  900. blocks, (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl, (unsigned long)block_c.len);
  901. return EXIT_LZO_ERROR;
  902. }
  903. /* optimize the compressed block */
  904. if (c_len < bl && opt_optimize_compressed_data)
  905. {
  906. d_len = bl;
  907. r = call_optimizer(c, block_c.ptr, c_len, block_d.ptr, &d_len);
  908. if (r != 0 || d_len != bl)
  909. {
  910. printf(" optimization failed in block %lu (%d) "
  911. "(%lu %lu %lu)\n", blocks, r,
  912. (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl);
  913. return EXIT_LZO_ERROR;
  914. }
  915. if (memchecker_check(&block_c, block_c.len, random_byte) != 0 ||
  916. memchecker_check(&block_d, block_d.len, random_byte) != 0)
  917. {
  918. printf(" optimize overwrite error in block %lu "
  919. "(%lu %lu %lu %lu)\n",
  920. blocks, (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl, (unsigned long)block_c.len);
  921. return EXIT_LZO_ERROR;
  922. }
  923. }
  924. /* dump compressed data to disk */
  925. if (fp_dump)
  926. {
  927. lzo_uint l = (lzo_uint) lzo_fwrite(fp_dump, block_c.ptr, c_len);
  928. if (l != c_len || fflush(fp_dump) != 0) {
  929. /* write error */
  930. (void) fclose(fp_dump); fp_dump = NULL;
  931. }
  932. }
  933. /* decompress the block and verify */
  934. lzo_pclock_flush_cpu_cache(&pch, 0);
  935. lzo_pclock_read(&pch, &x_start);
  936. for (r = 0, c_i = 0; c_i < d_loops; c_i++)
  937. {
  938. d_len = bl;
  939. r = call_decompressor(c, decompress, block_c.ptr, c_len, block_d.ptr, &d_len);
  940. if (r != 0 || d_len != bl)
  941. break;
  942. }
  943. lzo_pclock_read(&pch, &x_stop);
  944. d_time += lzo_pclock_get_elapsed(&pch, &x_start, &x_stop);
  945. if (r != 0)
  946. {
  947. printf(" decompression failed in block %lu (%d) "
  948. "(%lu %lu %lu)\n", blocks, r,
  949. (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl);
  950. return EXIT_LZO_ERROR;
  951. }
  952. if (d_len != bl)
  953. {
  954. printf(" decompression size error in block %lu (%lu %lu %lu)\n",
  955. blocks, (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl);
  956. return EXIT_LZO_ERROR;
  957. }
  958. if (is_compressor(c))
  959. {
  960. if (lzo_memcmp(d, block_d.ptr, bl) != 0)
  961. {
  962. lzo_uint x = 0;
  963. while (x < bl && block_d.ptr[x] == d[x])
  964. x++;
  965. printf(" decompression data error in block %lu at offset "
  966. "%lu (%lu %lu)\n", blocks, (unsigned long)x,
  967. (unsigned long)c_len, (unsigned long)d_len);
  968. if (opt_compute_adler32)
  969. printf(" checksum: 0x%08lx 0x%08lx\n",
  970. (unsigned long)adler_in, (unsigned long)adler_out);
  971. #if 0
  972. printf("Orig: ");
  973. r = (x >= 10) ? -10 : 0 - (int) x;
  974. for (j = r; j <= 10 && x + j < bl; j++)
  975. printf(" %02x", (int)d[x+j]);
  976. printf("\nDecomp:");
  977. for (j = r; j <= 10 && x + j < bl; j++)
  978. printf(" %02x", (int)block_d.ptr[x+j]);
  979. printf("\n");
  980. #endif
  981. return EXIT_LZO_ERROR;
  982. }
  983. if ((opt_compute_adler32 && adler_in != adler_out) ||
  984. (opt_compute_crc32 && crc_in != crc_out))
  985. {
  986. printf(" checksum error in block %lu (%lu %lu)\n",
  987. blocks, (unsigned long)c_len, (unsigned long)d_len);
  988. printf(" adler32: 0x%08lx 0x%08lx\n",
  989. (unsigned long)adler_in, (unsigned long)adler_out);
  990. printf(" crc32: 0x%08lx 0x%08lx\n",
  991. (unsigned long)crc_in, (unsigned long)crc_out);
  992. return EXIT_LZO_ERROR;
  993. }
  994. }
  995. if (memchecker_check(&block_d, block_d.len, random_byte) != 0)
  996. {
  997. printf(" decompression overwrite error in block %lu "
  998. "(%lu %lu %lu %lu)\n",
  999. blocks, (unsigned long)c_len, (unsigned long)d_len,
  1000. (unsigned long)bl, (unsigned long)block_d.len);
  1001. return EXIT_LZO_ERROR;
  1002. }
  1003. #if defined(__LZO_CHECKER)
  1004. /* free in reverse order of allocations */
  1005. mb_free(&block_d);
  1006. mb_free(&block_c);
  1007. #endif
  1008. d += bl;
  1009. len -= bl;
  1010. compressed_len += (unsigned long) c_len_max;
  1011. }
  1012. while (len > 0);
  1013. }
  1014. lzo_pclock_read(&pch, &t_stop);
  1015. t_time += lzo_pclock_get_elapsed(&pch, &t_start, &t_stop);
  1016. if (fp_dump) {
  1017. (void) fclose(fp_dump); fp_dump = NULL;
  1018. }
  1019. opt_dump_compressed_data = NULL; /* only dump the first file */
  1020. print_stats(method_name, file_name,
  1021. t_loops, c_loops, d_loops,
  1022. t_time, c_time, d_time,
  1023. compressed_len, (unsigned long) file_data.len, blocks);
  1024. if (total_method_name != c->name) {
  1025. total_method_name = c->name;
  1026. total_method_names += 1;
  1027. }
  1028. return EXIT_OK;
  1029. }
  1030. static
  1031. int do_file ( int method, const char *file_name,
  1032. long c_loops, long d_loops,
  1033. lzo_uint32_tp p_adler, lzo_uint32_tp p_crc )
  1034. {
  1035. int r;
  1036. const compress_t *c;
  1037. lzo_decompress_t decompress;
  1038. lzo_uint32_t adler, crc;
  1039. char method_name[256+1];
  1040. const char *n;
  1041. const long t_loops = 1;
  1042. adler_in = adler_out = 0;
  1043. crc_in = crc_out = 0;
  1044. if (p_adler)
  1045. *p_adler = 0;
  1046. if (p_crc)
  1047. *p_crc = 0;
  1048. c = find_method_by_id(method);
  1049. if (c == NULL || c->name == NULL || c->compress == NULL)
  1050. return EXIT_INTERNAL;
  1051. decompress = get_decomp_info(c,&n);
  1052. if (!decompress || n == NULL || block_w.len < c->mem_decompress)
  1053. return EXIT_INTERNAL;
  1054. strcpy(method_name,c->name);
  1055. strcat(method_name,n);
  1056. if (c_loops < 1) c_loops = 1;
  1057. if (d_loops < 1) d_loops = 1;
  1058. fflush(stdout); fflush(stderr);
  1059. /* read the whole file */
  1060. r = load_file(file_name, opt_max_data_len);
  1061. if (r != 0)
  1062. return r;
  1063. /* compute some checksums */
  1064. adler = lzo_adler32(0, NULL, 0);
  1065. adler = lzo_adler32(adler, file_data.ptr, file_data.len);
  1066. if (p_adler)
  1067. *p_adler = adler;
  1068. crc = lzo_crc32(0, NULL, 0);
  1069. crc = lzo_crc32(crc, file_data.ptr, file_data.len);
  1070. if (p_crc)
  1071. *p_crc = crc;
  1072. if (opt_verbose >= 2)
  1073. {
  1074. printf("File %s: %lu bytes (0x%08lx, 0x%08lx)\n",
  1075. file_name, (unsigned long) file_data.len, (unsigned long) adler, (unsigned long) crc);
  1076. printf(" compressing %lu bytes (%ld/%ld/%ld loops, %lu block-size)\n",
  1077. (unsigned long) file_data.len, t_loops, c_loops, d_loops, (unsigned long) opt_block_size);
  1078. printf(" %s\n", method_name);
  1079. }
  1080. r = process_file(c, decompress, method_name, file_name,
  1081. t_loops, c_loops, d_loops);
  1082. return r;
  1083. }
  1084. /*************************************************************************
  1085. // Calgary Corpus and Silesia Corpus test suite driver
  1086. **************************************************************************/
  1087. struct corpus_entry_t
  1088. {
  1089. const char *name;
  1090. long loops;
  1091. lzo_uint32_t adler;
  1092. lzo_uint32_t crc;
  1093. };
  1094. const struct corpus_entry_t *opt_corpus = NULL;
  1095. static const struct corpus_entry_t calgary_corpus[] =
  1096. {
  1097. { "bib", 8, 0x4bd09e98L, 0xb856ebe8L },
  1098. { "book1", 1, 0xd4d3613eL, 0x24e19972L },
  1099. { "book2", 1, 0x6fe14cc3L, 0xba0f3f26L },
  1100. { "geo", 6, 0xf3cc5be0L, 0x4d3a6ed0L },
  1101. { "news", 2, 0x2ed405b8L, 0xcafac853L },
  1102. { "obj1", 35, 0x3887dd2cL, 0xc7b0cd26L },
  1103. { "obj2", 4, 0xf89407c4L, 0x3ae33007L },
  1104. { "paper1", 17, 0xfe65ce62L, 0x2b6baca0L },
  1105. { "paper2", 11, 0x1238b7c2L, 0xf76cba72L },
  1106. { "pic", 4, 0xf61a5702L, 0x4b17e59cL },
  1107. { "progc", 25, 0x4c00ba45L, 0x6fb16094L },
  1108. { "progl", 20, 0x4cba738eL, 0xddbf6baaL },
  1109. { "progp", 28, 0x7495b92bL, 0x493a1809L },
  1110. { "trans", 15, 0x52a2cec8L, 0xcdec06a6L },
  1111. { NULL, 0, 0x00000000L, 0x00000000L }
  1112. };
  1113. static const struct corpus_entry_t silesia_corpus[] =
  1114. {
  1115. { "dickens", 1, 0x170f606fL, 0xaf3a6b76L },
  1116. { "mozilla", 1, 0x1188dd4eL, 0x7fb0ab7dL },
  1117. { "mr", 1, 0xaea14b97L, 0xa341883fL },
  1118. { "nci", 1, 0x0af16f1fL, 0x60ff63d3L },
  1119. { "ooffice", 1, 0x83c8f689L, 0xa023e1faL },
  1120. { "osdb", 1, 0xb825b790L, 0xa0ca388cL },
  1121. { "reymont", 1, 0xce5c82caL, 0x50d35f03L },
  1122. { "samba", 1, 0x19dbb9f5L, 0x2beac5f3L },
  1123. { "sao", 1, 0x7edfc4a9L, 0xfda125bfL },
  1124. { "webster", 1, 0xf2962fc6L, 0x01f5a2e9L },
  1125. { "xml", 1, 0xeccd03d6L, 0xff8f3051L },
  1126. { "x-ray", 1, 0xc95435a0L, 0xc86a35c6L },
  1127. { NULL, 0, 0x00000000L, 0x00000000L }
  1128. };
  1129. static
  1130. int do_corpus ( const struct corpus_entry_t *corpus, int method, const char *path,
  1131. long c_loops, long d_loops )
  1132. {
  1133. size_t i, n;
  1134. char name[256];
  1135. if (path == NULL || strlen(path) >= sizeof(name) - 12)
  1136. return EXIT_USAGE;
  1137. strcpy(name,path);
  1138. n = strlen(name);
  1139. if (n > 0 && name[n-1] != '/' && name[n-1] != '\\' && name[n-1] != ':')
  1140. {
  1141. strcat(name,"/");
  1142. n++;
  1143. }
  1144. for (i = 0; corpus[i].name != NULL; i++)
  1145. {
  1146. lzo_uint32_t adler, crc;
  1147. long c = c_loops * corpus[i].loops;
  1148. long d = d_loops * corpus[i].loops;
  1149. int r;
  1150. strcpy(name+n,corpus[i].name);
  1151. r = do_file(method, name, c, d, &adler, &crc);
  1152. if (r != 0)
  1153. return r;
  1154. if (adler != corpus[i].adler)
  1155. {
  1156. printf(" invalid test suite\n");
  1157. return EXIT_ADLER;
  1158. }
  1159. if (corpus[i].crc && crc != corpus[i].crc)
  1160. {
  1161. printf(" internal checksum error !! (0x%08lx 0x%08lx)\n",
  1162. (unsigned long) crc, (unsigned long) corpus[i].crc);
  1163. return EXIT_INTERNAL;
  1164. }
  1165. }
  1166. return EXIT_OK;
  1167. }
  1168. /*************************************************************************
  1169. // usage
  1170. **************************************************************************/
  1171. static
  1172. void usage ( const char *name, int exit_code, lzo_bool show_methods )
  1173. {
  1174. FILE *fp;
  1175. int i;
  1176. fp = stdout;
  1177. fflush(stdout); fflush(stderr);
  1178. fprintf(fp,"Usage: %s [option..] file...\n", name);
  1179. fprintf(fp,"\n");
  1180. fprintf(fp,"Options:\n");
  1181. fprintf(fp," -m# compression method\n");
  1182. fprintf(fp," -b# set input block size (default %lu, max %lu)\n",
  1183. (unsigned long) opt_block_size, (unsigned long) opt_max_data_len);
  1184. fprintf(fp," -n# number of compression/decompression runs\n");
  1185. fprintf(fp," -c# number of compression runs\n");
  1186. fprintf(fp," -d# number of decompression runs\n");
  1187. fprintf(fp," -S use safe decompressor (if available)\n");
  1188. fprintf(fp," -A use assembler decompressor (if available)\n");
  1189. fprintf(fp," -F use fast assembler decompressor (if available)\n");
  1190. fprintf(fp," -O optimize compressed data (if available)\n");
  1191. fprintf(fp," -s DIR process Calgary Corpus test suite in directory `DIR'\n");
  1192. fprintf(fp," -@ read list of files to compress from stdin\n");
  1193. fprintf(fp," -q be quiet\n");
  1194. fprintf(fp," -Q be very quiet\n");
  1195. fprintf(fp," -v be verbose\n");
  1196. fprintf(fp," -L display software license\n");
  1197. if (show_methods)
  1198. {
  1199. #if defined(__LZOLIB_PCLOCK_CH_INCLUDED)
  1200. lzo_pclock_t t_dummy;
  1201. lzo_pclock_read(&pch, &t_dummy);
  1202. (void) lzo_pclock_get_elapsed(&pch, &t_dummy, &t_dummy);
  1203. fprintf(fp,"\nAll timings are recorded using pclock mode %d %s.\n", pch.mode, pch.name);
  1204. #endif
  1205. fprintf(fp,"\n\n");
  1206. fprintf(fp,"The following compression methods are available:\n");
  1207. fprintf(fp,"\n");
  1208. fprintf(fp," usage name memory available extras\n");
  1209. fprintf(fp," ----- ---- ------ ----------------\n");
  1210. for (i = 0; i <= M_LAST_COMPRESSOR; i++)
  1211. {
  1212. const compress_t *c;
  1213. c = find_method_by_id(i);
  1214. if (c)
  1215. {
  1216. char n[16];
  1217. const char *sep = " ";
  1218. unsigned long m = c->mem_compress;
  1219. sprintf(n,"-m%d",i);
  1220. fprintf(fp," %-6s %-13s",n,c->name);
  1221. #if 1
  1222. fprintf(fp,"%9lu", m);
  1223. #else
  1224. m = (m + 1023) / 1024;
  1225. fprintf(fp,"%6lu KiB", m);
  1226. #endif
  1227. if (c->decompress_safe)
  1228. { fprintf(fp, "%s%s", sep, "safe"); sep = ", "; }
  1229. if (c->decompress_asm)
  1230. { fprintf(fp, "%s%s", sep, "asm"); sep = ", "; }
  1231. if (c->decompress_asm_safe)
  1232. { fprintf(fp, "%s%s", sep, "asm+safe"); sep = ", "; }
  1233. if (c->decompress_asm_fast)
  1234. { fprintf(fp, "%s%s", sep, "fastasm"); sep = ", "; }
  1235. if (c->decompress_asm_fast_safe)
  1236. { fprintf(fp, "%s%s", sep, "fastasm+safe"); sep = ", "; }
  1237. if (c->optimize)
  1238. { fprintf(fp, "%s%s", sep, "optimize"); sep = ", "; }
  1239. fprintf(fp, "\n");
  1240. }
  1241. }
  1242. }
  1243. else
  1244. {
  1245. fprintf(fp,"\n");
  1246. fprintf(fp,"Type '%s -m' to list all available methods.\n", name);
  1247. }
  1248. fflush(fp);
  1249. if (exit_code < 0)
  1250. exit_code = EXIT_USAGE;
  1251. exit(exit_code);
  1252. }
  1253. static
  1254. void license(void)
  1255. {
  1256. FILE *fp;
  1257. fp = stdout;
  1258. fflush(stdout); fflush(stderr);
  1259. fprintf(fp,
  1260. " The LZO library is free software; you can redistribute it and/or\n"
  1261. " modify it under the terms of the GNU General Public License as\n"
  1262. " published by the Free Software Foundation; either version 2 of\n"
  1263. " the License, or (at your option) any later version.\n"
  1264. "\n"
  1265. " The LZO library is distributed in the hope that it will be useful,\n"
  1266. " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  1267. " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
  1268. " GNU General Public License for more details.\n"
  1269. );
  1270. fprintf(fp,
  1271. "\n"
  1272. " You should have received a copy of the GNU General Public License\n"
  1273. " along with the LZO library; see the file COPYING.\n"
  1274. " If not, write to the Free Software Foundation, Inc.,\n"
  1275. " 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
  1276. "\n"
  1277. " Markus F.X.J. Oberhumer\n"
  1278. " <markus@oberhumer.com>\n"
  1279. " http://www.oberhumer.com/opensource/lzo/\n"
  1280. "\n"
  1281. );
  1282. fflush(fp);
  1283. exit(EXIT_OK);
  1284. }
  1285. /*************************************************************************
  1286. // parse method option '-m'
  1287. **************************************************************************/
  1288. static int methods[256+1];
  1289. static int methods_n = 0;
  1290. static void add_method(int m)
  1291. {
  1292. int i;
  1293. if (m > 0)
  1294. {
  1295. if (!find_method_by_id(m)) {
  1296. fprintf(stdout,"%s: invalid method %d\n",progname,m);
  1297. exit(EXIT_USAGE);
  1298. }
  1299. for (i = 0; i < methods_n; i++)
  1300. if (methods[i] == m)
  1301. return;
  1302. if (methods_n >= 256)
  1303. {
  1304. fprintf(stderr,"%s: too many methods\n",progname);
  1305. exit(EXIT_USAGE);
  1306. }
  1307. methods[methods_n++] = m;
  1308. methods[methods_n] = 0;
  1309. }
  1310. }
  1311. static void add_methods(const int *ml)
  1312. {
  1313. while (*ml != 0)
  1314. add_method(*ml++);
  1315. }
  1316. static void add_all_methods(int first, int last)
  1317. {
  1318. int m;
  1319. for (m = first; m <= last; m++)
  1320. if (find_method_by_id(m) != NULL)
  1321. add_method(m);
  1322. }
  1323. static int m_strcmp(const char *a, const char *b)
  1324. {
  1325. size_t n;
  1326. if (a[0] == 0 || b[0] == 0)
  1327. return 1;
  1328. n = strlen(b);
  1329. if (strncmp(a,b,n) == 0 && (a[n] == 0 || a[n] == ','))
  1330. return 0;
  1331. return 1;
  1332. }
  1333. static lzo_bool m_strisdigit(const char *s)
  1334. {
  1335. for (;;)
  1336. {
  1337. if (!is_digit(*s))
  1338. return 0;
  1339. s++;
  1340. if (*s == 0 || *s == ',')
  1341. break;
  1342. }
  1343. return 1;
  1344. }
  1345. static void parse_methods(const char *p)
  1346. {
  1347. const compress_t *c;
  1348. for (;;)
  1349. {
  1350. if (p == NULL || p[0] == 0)
  1351. usage(progname,-1,1);
  1352. else if ((c = find_method_by_name(p)) != NULL)
  1353. add_method(c->id);
  1354. else if (m_strcmp(p,"all") == 0 || m_strcmp(p,"avail") == 0)
  1355. add_all_methods(1,M_LAST_COMPRESSOR);
  1356. else if (m_strcmp(p,"ALL") == 0)
  1357. {
  1358. add_all_methods(1,M_LAST_COMPRESSOR);
  1359. add_all_methods(9721,9729);
  1360. add_all_methods(9781,9789);
  1361. }
  1362. else if (m_strcmp(p,"lzo") == 0)
  1363. add_all_methods(1,M_MEMCPY);
  1364. else if (m_strcmp(p,"bench") == 0)
  1365. add_methods(benchmark_methods);
  1366. else if (m_strcmp(p,"m1") == 0)
  1367. add_methods(x1_methods);
  1368. else if (m_strcmp(p,"m99") == 0)
  1369. add_methods(x99_methods);
  1370. else if (m_strcmp(p,"m999") == 0)
  1371. add_methods(x999_methods);
  1372. else if (m_strcmp(p,"1x999") == 0)
  1373. add_all_methods(9721,9729);
  1374. else if (m_strcmp(p,"1y999") == 0)
  1375. add_all_methods(9821,9829);
  1376. #if defined(ALG_ZLIB)
  1377. else if (m_strcmp(p,"zlib") == 0)
  1378. add_all_methods(M_ZLIB_8_1,M_ZLIB_8_9);
  1379. #endif
  1380. #if defined(ALG_BZIP2)
  1381. else if (m_strcmp(p,"bzip2") == 0)
  1382. add_all_methods(M_BZIP2_1,M_BZIP2_9);
  1383. #endif
  1384. else if (m_strisdigit(p))
  1385. add_method(atoi(p));
  1386. else
  1387. {
  1388. printf("%s: invalid method '%s'\n\n",progname,p);
  1389. exit(EXIT_USAGE);
  1390. }
  1391. while (*p && *p != ',')
  1392. p++;
  1393. while (*p == ',')
  1394. p++;
  1395. if (*p == 0)
  1396. return;
  1397. }
  1398. }
  1399. /*************************************************************************
  1400. // options
  1401. **************************************************************************/
  1402. enum {
  1403. OPT_LONGOPT_ONLY = 512,
  1404. OPT_ADLER32,
  1405. OPT_CALGARY_CORPUS,
  1406. OPT_CLEAR_WRKMEM,
  1407. OPT_CRC32,
  1408. OPT_DICT,
  1409. OPT_DUMP,
  1410. OPT_EXECUTION_TIME,
  1411. OPT_MAX_DATA_LEN,
  1412. OPT_MAX_DICT_LEN,
  1413. OPT_SILESIA_CORPUS,
  1414. OPT_PCLOCK,
  1415. OPT_UNUSED
  1416. };
  1417. static const struct lzo_getopt_longopt_t longopts[] =
  1418. {
  1419. /* { name has_arg *flag val } */
  1420. {"help", 0, 0, 'h'+256}, /* give help */
  1421. {"license", 0, 0, 'L'}, /* display software license */
  1422. {"quiet", 0, 0, 'q'}, /* quiet mode */
  1423. {"verbose", 0, 0, 'v'}, /* verbose mode */
  1424. {"version", 0, 0, 'V'+256}, /* display version number */
  1425. {"adler32", 0, 0, OPT_ADLER32},
  1426. {"calgary-corpus", 1, 0, OPT_CALGARY_CORPUS},
  1427. {"clear-wrkmem", 0, 0, OPT_CLEAR_WRKMEM},
  1428. {"clock", 1, 0, OPT_PCLOCK},
  1429. {"corpus", 1, 0, OPT_CALGARY_CORPUS},
  1430. {"crc32", 0, 0, OPT_CRC32},
  1431. {"dict", 1, 0, OPT_DICT},
  1432. {"dump-compressed", 1, 0, OPT_DUMP},
  1433. {"execution-time", 0, 0, OPT_EXECUTION_TIME},
  1434. {"max-data-length", 1, 0, OPT_MAX_DATA_LEN},
  1435. {"max-dict-length", 1, 0, OPT_MAX_DICT_LEN},
  1436. {"silesia-corpus", 1, 0, OPT_SILESIA_CORPUS},
  1437. {"uclock", 1, 0, OPT_PCLOCK},
  1438. {"methods", 1, 0, 'm'},
  1439. {"totals", 0, 0, 'T'},
  1440. { 0, 0, 0, 0 }
  1441. };
  1442. static int do_option(lzo_getopt_p g, int optc)
  1443. {
  1444. #define mfx_optarg g->optarg
  1445. switch (optc)
  1446. {
  1447. case 'A':
  1448. opt_use_asm_decompressor = 1;
  1449. break;
  1450. case 'b':
  1451. opt_block_size = 0; /* set to opt_max_data_len later */
  1452. if (mfx_optarg)
  1453. {
  1454. if (!mfx_optarg || !is_digit(mfx_optarg[0]))
  1455. return optc;
  1456. opt_block_size = atol(mfx_optarg);
  1457. }
  1458. break;
  1459. case 'c':
  1460. case 'C':
  1461. if (!mfx_optarg || !is_digit(mfx_optarg[0]))
  1462. return optc;
  1463. opt_c_loops = atol(mfx_optarg);
  1464. break;
  1465. case 'd':
  1466. case 'D':
  1467. if (!mfx_optarg || !is_digit(mfx_optarg[0]))
  1468. return optc;
  1469. opt_d_loops = atol(mfx_optarg);
  1470. break;
  1471. case 'F':
  1472. opt_use_asm_fast_decompressor = 1;
  1473. break;
  1474. case 'h':
  1475. case 'H':
  1476. case '?':
  1477. case 'h'+256:
  1478. usage(progname,EXIT_OK,0);
  1479. break;
  1480. case 'L':
  1481. license();
  1482. break;
  1483. case 'm':
  1484. parse_methods(mfx_optarg);
  1485. break;
  1486. case 'n':
  1487. if (!mfx_optarg || !is_digit(mfx_optarg[0]))
  1488. return optc;
  1489. opt_c_loops = opt_d_loops = atol(mfx_optarg);
  1490. break;
  1491. case 'O':
  1492. opt_optimize_compressed_data = 1;
  1493. break;
  1494. case 'q':
  1495. opt_verbose -= 1;
  1496. break;
  1497. case 'Q':
  1498. opt_verbose = 0;
  1499. break;
  1500. case 's':
  1501. case OPT_CALGARY_CORPUS:
  1502. if (!mfx_optarg || !mfx_optarg[0])
  1503. return optc;
  1504. opt_corpus_path = mfx_optarg;
  1505. opt_corpus = calgary_corpus;
  1506. break;
  1507. case OPT_SILESIA_CORPUS:
  1508. if (!mfx_optarg || !mfx_optarg[0])
  1509. return optc;
  1510. opt_corpus_path = mfx_optarg;
  1511. opt_corpus = silesia_corpus;
  1512. break;
  1513. case 'S':
  1514. opt_use_safe_decompressor = 1;
  1515. break;
  1516. case 'T':
  1517. opt_totals += 1;
  1518. break;
  1519. case 'v':
  1520. opt_verbose += 1;
  1521. break;
  1522. case 'V':
  1523. case 'V'+256:
  1524. exit(EXIT_OK);
  1525. break;
  1526. case '@':
  1527. opt_read_from_stdin = 1;
  1528. break;
  1529. case '1': case '2': case '3': case '4': case '5':
  1530. case '6': case '7': case '8': case '9':
  1531. /* this is a dirty hack... */
  1532. if (g->shortpos == 0) {
  1533. char m[2]; m[0] = (char) optc; m[1] = 0;
  1534. parse_methods(m);
  1535. } else {
  1536. const char *m = &g->argv[g->optind][g->shortpos-1];
  1537. parse_methods(m);
  1538. ++g->optind; g->shortpos = 0;
  1539. }
  1540. break;
  1541. case OPT_ADLER32:
  1542. opt_compute_adler32 = 1;
  1543. break;
  1544. case OPT_CLEAR_WRKMEM:
  1545. opt_clear_wrkmem = 1;
  1546. break;
  1547. case OPT_CRC32:
  1548. opt_compute_crc32 = 1;
  1549. break;
  1550. case OPT_DICT:
  1551. opt_dict = 1;
  1552. opt_dictionary_file = mfx_optarg;
  1553. break;
  1554. case OPT_EXECUTION_TIME:
  1555. opt_execution_time = 1;
  1556. break;
  1557. case OPT_DUMP:
  1558. opt_dump_compressed_data = mfx_optarg;
  1559. break;
  1560. case OPT_MAX_DATA_LEN:
  1561. if (!mfx_optarg || !is_digit(mfx_optarg[0]))
  1562. return optc;
  1563. opt_max_data_len = atol(mfx_optarg);
  1564. break;
  1565. case OPT_MAX_DICT_LEN:
  1566. if (!mfx_optarg || !is_digit(mfx_optarg[0]))
  1567. return optc;
  1568. opt_max_dict_len = atol(mfx_optarg);
  1569. break;
  1570. case OPT_PCLOCK:
  1571. if (!mfx_optarg || !is_digit(mfx_optarg[0]))
  1572. return optc;
  1573. opt_pclock = atoi(mfx_optarg);
  1574. #if defined(__LZOLIB_PCLOCK_CH_INCLUDED)
  1575. if (opt_pclock > 0)
  1576. pch.mode = opt_pclock;
  1577. #endif
  1578. break;
  1579. case '\0':
  1580. return -1;
  1581. case ':':
  1582. return -2;
  1583. default:
  1584. fprintf(stderr,"%s: internal error in getopt (%d)\n",progname,optc);
  1585. return -3;
  1586. }
  1587. return 0;
  1588. #undef mfx_optarg
  1589. }
  1590. static void handle_opterr(lzo_getopt_p g, const char *f, void *v)
  1591. {
  1592. struct A { va_list ap; };
  1593. struct A *a = (struct A *) v;
  1594. fprintf( stderr, "%s: ", g->progname);
  1595. if (a)
  1596. vfprintf(stderr, f, a->ap);
  1597. else
  1598. fprintf( stderr, "UNKNOWN GETOPT ERROR");
  1599. fprintf( stderr, "\n");
  1600. }
  1601. static int get_options(int argc, char **argv)
  1602. {
  1603. lzo_getopt_t mfx_getopt;
  1604. int optc;
  1605. static const char shortopts[] =
  1606. "Ab::c:C:d:D:FhHLm::n:OqQs:STvV@123456789";
  1607. lzo_getopt_init(&mfx_getopt, 1, argc, argv);
  1608. mfx_getopt.progname = progname;
  1609. mfx_getopt.opterr = handle_opterr;
  1610. while ((optc = lzo_getopt(&mfx_getopt, shortopts, longopts, NULL)) >= 0)
  1611. {
  1612. if (do_option(&mfx_getopt, optc) != 0)
  1613. exit(EXIT_USAGE);
  1614. }
  1615. return mfx_getopt.optind;
  1616. }
  1617. /*************************************************************************
  1618. // main
  1619. **************************************************************************/
  1620. int __lzo_cdecl_main main(int argc, char *argv[])
  1621. {
  1622. int r = EXIT_OK;
  1623. int i, ii;
  1624. int m;
  1625. time_t t_total;
  1626. const char *s;
  1627. lzo_wildargv(&argc, &argv);
  1628. lzo_pclock_open_default(&pch);
  1629. progname = argv[0];
  1630. for (s = progname; *s; s++)
  1631. if ((*s == '/' || *s == '\\') && s[1])
  1632. progname = s + 1;
  1633. printf("\nLZO real-time data compression library (v%s, %s).\n",
  1634. lzo_version_string(), lzo_version_date());
  1635. printf("Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n");
  1636. /*
  1637. * Step 1: initialize the LZO library
  1638. */
  1639. if (lzo_init() != LZO_E_OK)
  1640. {
  1641. printf("internal error - lzo_init() failed !!!\n");
  1642. printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\n");
  1643. exit(1);
  1644. }
  1645. /*
  1646. * Step 2: setup default options
  1647. */
  1648. opt_max_data_len = 64 * 1024L * 1024L;
  1649. opt_block_size = 256 * 1024L;
  1650. #if (LZO_ARCH_M68K && LZO_OS_TOS)
  1651. /* reduce memory requirements for 14 MB machines */
  1652. opt_max_data_len = 8 * 1024L * 1024L;
  1653. #endif
  1654. /*
  1655. * Step 3: parse options
  1656. */
  1657. if (argc < 2)
  1658. usage(progname,-1,0);
  1659. i = get_options(argc,argv);
  1660. if (methods_n == 0)
  1661. add_method(default_method);
  1662. if (methods_n > 1 && opt_read_from_stdin)
  1663. {
  1664. printf("%s: cannot use multiple methods and '-@'\n", progname);
  1665. exit(EXIT_USAGE);
  1666. }
  1667. if (opt_block_size == 0)
  1668. opt_block_size = opt_max_data_len;
  1669. if (opt_block_size > opt_max_data_len)
  1670. opt_block_size = opt_max_data_len;
  1671. if (opt_c_loops < 1)
  1672. opt_c_loops = 1;
  1673. if (opt_d_loops < 1)
  1674. opt_d_loops = 1;
  1675. /*
  1676. * Step 4: start work
  1677. */
  1678. block_w.len = 0;
  1679. for (ii = 0; ii < methods_n; ii++) {
  1680. const compress_t *c = find_method_by_id(methods[ii]);
  1681. assert(c != NULL);
  1682. if (c->mem_compress > block_w.len)
  1683. block_w.len = c->mem_compress;
  1684. if (c->mem_decompress > block_w.len)
  1685. block_w.len = c->mem_decompress;
  1686. }
  1687. mb_alloc(&block_w, block_w.len);
  1688. lzo_memset(block_w.ptr, 0, block_w.len);
  1689. #if !defined(__LZO_CHECKER)
  1690. mb_alloc_extra(&block_c, opt_block_size + get_max_compression_expansion(-1, opt_block_size), 16, 16);
  1691. mb_alloc_extra(&block_d, opt_block_size + get_max_decompression_overrun(-1, opt_block_size), 16, 16);
  1692. #endif
  1693. if (opt_dict)
  1694. {
  1695. opt_optimize_compressed_data = 0;
  1696. dict_alloc(opt_max_dict_len);
  1697. if (opt_dictionary_file)
  1698. {
  1699. dict_load(opt_dictionary_file);
  1700. if (dict.len > 0)
  1701. printf("Using dictionary '%s', %lu bytes, ID 0x%08lx.\n",
  1702. opt_dictionary_file,
  1703. (unsigned long) dict.len, (unsigned long) dict.adler);
  1704. }
  1705. if (dict.len == 0)
  1706. {
  1707. dict_set_default();
  1708. printf("Using default dictionary, %lu bytes, ID 0x%08lx.\n",
  1709. (unsigned long) dict.len, (unsigned long) dict.adler);
  1710. }
  1711. }
  1712. t_total = time(NULL);
  1713. ii = i;
  1714. for (m = 0; m < methods_n && r == EXIT_OK; m++)
  1715. {
  1716. int method = methods[m];
  1717. i = ii;
  1718. if (i >= argc && opt_corpus_path == NULL && !opt_read_from_stdin)
  1719. usage(progname,-1,0);
  1720. if (m == 0 && opt_verbose >= 1)
  1721. printf("%lu block-size\n\n", (unsigned long) opt_block_size);
  1722. assert(find_method_by_id(method) != NULL);
  1723. if (opt_corpus_path != NULL)
  1724. r = do_corpus(opt_corpus, method, opt_corpus_path,
  1725. opt_c_loops, opt_d_loops);
  1726. else
  1727. {
  1728. for ( ; i < argc && r == EXIT_OK; i++)
  1729. {
  1730. r = do_file(method,argv[i],opt_c_loops,opt_d_loops,NULL,NULL);
  1731. if (r == EXIT_FILE) /* ignore file errors */
  1732. r = EXIT_OK;
  1733. }
  1734. if (opt_read_from_stdin)
  1735. {
  1736. char buf[512], *p;
  1737. while (r == EXIT_OK && fgets(buf,sizeof(buf)-1,stdin) != NULL)
  1738. {
  1739. buf[sizeof(buf)-1] = 0;
  1740. p = buf + strlen(buf);
  1741. while (p > buf && is_space(p[-1]))
  1742. *--p = 0;
  1743. p = buf;
  1744. while (*p && is_space(*p))
  1745. p++;
  1746. if (*p)
  1747. r = do_file(method,p,opt_c_loops,opt_d_loops,NULL,NULL);
  1748. if (r == EXIT_FILE) /* ignore file errors */
  1749. r = EXIT_OK;
  1750. }
  1751. opt_read_from_stdin = 0;
  1752. }
  1753. }
  1754. }
  1755. t_total = time(NULL) - t_total;
  1756. if (opt_totals)
  1757. print_totals();
  1758. if (opt_execution_time || (methods_n > 1 && opt_verbose >= 1))
  1759. printf("\n%s: execution time: %lu seconds\n", progname, (unsigned long) t_total);
  1760. if (r != EXIT_OK)
  1761. printf("\n%s: exit code: %d\n", progname, r);
  1762. lzo_pclock_close(&pch);
  1763. return r;
  1764. }
  1765. /* vim:set ts=4 sw=4 et: */