xref: /src/sys/contrib/zstd/programs/zstdcli.c (revision 5ff13fbc199bdf5f0572845351c68ee5ca828e71)
1902c8ce7SBaptiste Daroussin /*
2b3392d84SAllan Jude  * Copyright (c) Yann Collet, Facebook, Inc.
3a19eddc3SBaptiste Daroussin  * All rights reserved.
4a19eddc3SBaptiste Daroussin  *
5902c8ce7SBaptiste Daroussin  * This source code is licensed under both the BSD-style license (found in the
6902c8ce7SBaptiste Daroussin  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7902c8ce7SBaptiste Daroussin  * in the COPYING file in the root directory of this source tree).
8653667f9SBaptiste Daroussin  * You may select, at your option, one of the above-listed licenses.
9a19eddc3SBaptiste Daroussin  */
10a19eddc3SBaptiste Daroussin 
11a19eddc3SBaptiste Daroussin 
12a19eddc3SBaptiste Daroussin /*-************************************
13a19eddc3SBaptiste Daroussin *  Tuning parameters
14a19eddc3SBaptiste Daroussin **************************************/
15a19eddc3SBaptiste Daroussin #ifndef ZSTDCLI_CLEVEL_DEFAULT
16a19eddc3SBaptiste Daroussin #  define ZSTDCLI_CLEVEL_DEFAULT 3
17a19eddc3SBaptiste Daroussin #endif
18a19eddc3SBaptiste Daroussin 
19a19eddc3SBaptiste Daroussin #ifndef ZSTDCLI_CLEVEL_MAX
20902c8ce7SBaptiste Daroussin #  define ZSTDCLI_CLEVEL_MAX 19   /* without using --ultra */
21a19eddc3SBaptiste Daroussin #endif
22a19eddc3SBaptiste Daroussin 
23f6ae9767SConrad Meyer #ifndef ZSTDCLI_NBTHREADS_DEFAULT
24f6ae9767SConrad Meyer #  define ZSTDCLI_NBTHREADS_DEFAULT 1
25f6ae9767SConrad Meyer #endif
26a19eddc3SBaptiste Daroussin 
27a19eddc3SBaptiste Daroussin /*-************************************
28a19eddc3SBaptiste Daroussin *  Dependencies
29a19eddc3SBaptiste Daroussin **************************************/
30a19eddc3SBaptiste Daroussin #include "platform.h" /* IS_CONSOLE, PLATFORM_POSIX_VERSION */
31a19eddc3SBaptiste Daroussin #include "util.h"     /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
32af73257bSConrad Meyer #include <stdlib.h>   /* getenv */
33a19eddc3SBaptiste Daroussin #include <string.h>   /* strcmp, strlen */
34bc64b5ceSConrad Meyer #include <stdio.h>    /* fprintf(), stdin, stdout, stderr */
35a19eddc3SBaptiste Daroussin #include <errno.h>    /* errno */
36bc64b5ceSConrad Meyer #include <assert.h>   /* assert */
37bc64b5ceSConrad Meyer 
38902c8ce7SBaptiste Daroussin #include "fileio.h"   /* stdinmark, stdoutmark, ZSTD_EXTENSION */
39a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOBENCH
40af73257bSConrad Meyer #  include "benchzstd.h"  /* BMK_benchFiles */
41a19eddc3SBaptiste Daroussin #endif
42a19eddc3SBaptiste Daroussin #ifndef ZSTD_NODICT
43902c8ce7SBaptiste Daroussin #  include "dibio.h"  /* ZDICT_cover_params_t, DiB_trainFromFiles() */
44a19eddc3SBaptiste Daroussin #endif
45b3392d84SAllan Jude #ifndef ZSTD_NOTRACE
46b3392d84SAllan Jude #  include "zstdcli_trace.h"
47b3392d84SAllan Jude #endif
48bc64b5ceSConrad Meyer #include "../lib/zstd.h"  /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */
49a19eddc3SBaptiste Daroussin 
50a19eddc3SBaptiste Daroussin 
51a19eddc3SBaptiste Daroussin /*-************************************
52a19eddc3SBaptiste Daroussin *  Constants
53a19eddc3SBaptiste Daroussin **************************************/
54a19eddc3SBaptiste Daroussin #define COMPRESSOR_NAME "zstd command line interface"
55a19eddc3SBaptiste Daroussin #ifndef ZSTD_VERSION
56a19eddc3SBaptiste Daroussin #  define ZSTD_VERSION "v" ZSTD_VERSION_STRING
57a19eddc3SBaptiste Daroussin #endif
58a19eddc3SBaptiste Daroussin #define AUTHOR "Yann Collet"
59a19eddc3SBaptiste Daroussin #define WELCOME_MESSAGE "*** %s %i-bits %s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(size_t)*8), ZSTD_VERSION, AUTHOR
60a19eddc3SBaptiste Daroussin 
61ffcbc2d7SBaptiste Daroussin #define ZSTD_ZSTDMT "zstdmt"
62a19eddc3SBaptiste Daroussin #define ZSTD_UNZSTD "unzstd"
63a19eddc3SBaptiste Daroussin #define ZSTD_CAT "zstdcat"
6442239e68SConrad Meyer #define ZSTD_ZCAT "zcat"
65a19eddc3SBaptiste Daroussin #define ZSTD_GZ "gzip"
66a19eddc3SBaptiste Daroussin #define ZSTD_GUNZIP "gunzip"
67a19eddc3SBaptiste Daroussin #define ZSTD_GZCAT "gzcat"
68a19eddc3SBaptiste Daroussin #define ZSTD_LZMA "lzma"
69affe9eafSBaptiste Daroussin #define ZSTD_UNLZMA "unlzma"
70a19eddc3SBaptiste Daroussin #define ZSTD_XZ "xz"
71affe9eafSBaptiste Daroussin #define ZSTD_UNXZ "unxz"
72653667f9SBaptiste Daroussin #define ZSTD_LZ4 "lz4"
73653667f9SBaptiste Daroussin #define ZSTD_UNLZ4 "unlz4"
74a19eddc3SBaptiste Daroussin 
75a19eddc3SBaptiste Daroussin #define KB *(1 <<10)
76a19eddc3SBaptiste Daroussin #define MB *(1 <<20)
77a19eddc3SBaptiste Daroussin #define GB *(1U<<30)
78a19eddc3SBaptiste Daroussin 
79902c8ce7SBaptiste Daroussin #define DISPLAY_LEVEL_DEFAULT 2
80a19eddc3SBaptiste Daroussin 
81a19eddc3SBaptiste Daroussin static const char*    g_defaultDictName = "dictionary";
82a19eddc3SBaptiste Daroussin static const unsigned g_defaultMaxDictSize = 110 KB;
83a19eddc3SBaptiste Daroussin static const int      g_defaultDictCLevel = 3;
84a19eddc3SBaptiste Daroussin static const unsigned g_defaultSelectivityLevel = 9;
85653667f9SBaptiste Daroussin static const unsigned g_defaultMaxWindowLog = 27;
86a19eddc3SBaptiste Daroussin #define OVERLAP_LOG_DEFAULT 9999
87653667f9SBaptiste Daroussin #define LDM_PARAM_DEFAULT 9999  /* Default for parameters where 0 is valid */
88a19eddc3SBaptiste Daroussin static U32 g_overlapLog = OVERLAP_LOG_DEFAULT;
89653667f9SBaptiste Daroussin static U32 g_ldmHashLog = 0;
90653667f9SBaptiste Daroussin static U32 g_ldmMinMatch = 0;
91af73257bSConrad Meyer static U32 g_ldmHashRateLog = LDM_PARAM_DEFAULT;
92653667f9SBaptiste Daroussin static U32 g_ldmBucketSizeLog = LDM_PARAM_DEFAULT;
93a19eddc3SBaptiste Daroussin 
94a19eddc3SBaptiste Daroussin 
95706cfae4SConrad Meyer #define DEFAULT_ACCEL 1
96706cfae4SConrad Meyer 
97706cfae4SConrad Meyer typedef enum { cover, fastCover, legacy } dictType;
98706cfae4SConrad Meyer 
99a19eddc3SBaptiste Daroussin /*-************************************
100a19eddc3SBaptiste Daroussin *  Display Macros
101a19eddc3SBaptiste Daroussin **************************************/
102bc64b5ceSConrad Meyer #define DISPLAY_F(f, ...)    fprintf((f), __VA_ARGS__)
103bc64b5ceSConrad Meyer #define DISPLAYOUT(...)      DISPLAY_F(stdout, __VA_ARGS__)
104bc64b5ceSConrad Meyer #define DISPLAY(...)         DISPLAY_F(stderr, __VA_ARGS__)
105ffcbc2d7SBaptiste Daroussin #define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
106902c8ce7SBaptiste Daroussin static int g_displayLevel = DISPLAY_LEVEL_DEFAULT;   /* 0 : no display,  1: errors,  2 : + result + interaction + warnings,  3 : + progression,  4 : + information */
107a19eddc3SBaptiste Daroussin 
108a19eddc3SBaptiste Daroussin 
109a19eddc3SBaptiste Daroussin /*-************************************
110b3392d84SAllan Jude *  Check Version (when CLI linked to dynamic library)
111b3392d84SAllan Jude **************************************/
112b3392d84SAllan Jude 
113b3392d84SAllan Jude /* Due to usage of experimental symbols and capabilities by the CLI,
114b3392d84SAllan Jude  * the CLI must be linked against a dynamic library of same version */
checkLibVersion(void)115b3392d84SAllan Jude static void checkLibVersion(void)
116b3392d84SAllan Jude {
117b3392d84SAllan Jude     if (strcmp(ZSTD_VERSION_STRING, ZSTD_versionString())) {
118b3392d84SAllan Jude         DISPLAYLEVEL(1, "Error : incorrect library version (expecting : %s ; actual : %s ) \n",
119b3392d84SAllan Jude                     ZSTD_VERSION_STRING, ZSTD_versionString());
120b3392d84SAllan Jude         DISPLAYLEVEL(1, "Please update library to version %s, or use stand-alone zstd binary \n",
121b3392d84SAllan Jude                     ZSTD_VERSION_STRING);
122b3392d84SAllan Jude         exit(1);
123b3392d84SAllan Jude     }
124b3392d84SAllan Jude }
125b3392d84SAllan Jude 
126b3392d84SAllan Jude 
127b3392d84SAllan Jude /*-************************************
128a19eddc3SBaptiste Daroussin *  Command Line
129a19eddc3SBaptiste Daroussin **************************************/
130bc64b5ceSConrad Meyer /* print help either in `stderr` or `stdout` depending on originating request
131bc64b5ceSConrad Meyer  * error (badusage) => stderr
132bc64b5ceSConrad Meyer  * help (usage_advanced) => stdout
133bc64b5ceSConrad Meyer  */
usage(FILE * f,const char * programName)134bc64b5ceSConrad Meyer static void usage(FILE* f, const char* programName)
135a19eddc3SBaptiste Daroussin {
136bc64b5ceSConrad Meyer     DISPLAY_F(f, "Usage : \n");
137bc64b5ceSConrad Meyer     DISPLAY_F(f, "      %s [args] [FILE(s)] [-o file] \n", programName);
138bc64b5ceSConrad Meyer     DISPLAY_F(f, "\n");
139bc64b5ceSConrad Meyer     DISPLAY_F(f, "FILE    : a filename \n");
140bc64b5ceSConrad Meyer     DISPLAY_F(f, "          with no FILE, or when FILE is - , read standard input\n");
141bc64b5ceSConrad Meyer     DISPLAY_F(f, "Arguments : \n");
142a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOCOMPRESS
143bc64b5ceSConrad Meyer     DISPLAY_F(f, " -#     : # compression level (1-%d, default: %d) \n", ZSTDCLI_CLEVEL_MAX, ZSTDCLI_CLEVEL_DEFAULT);
144a19eddc3SBaptiste Daroussin #endif
145a19eddc3SBaptiste Daroussin #ifndef ZSTD_NODECOMPRESS
146bc64b5ceSConrad Meyer     DISPLAY_F(f, " -d     : decompression \n");
147a19eddc3SBaptiste Daroussin #endif
148bc64b5ceSConrad Meyer     DISPLAY_F(f, " -D DICT: use DICT as Dictionary for compression or decompression \n");
149bc64b5ceSConrad Meyer     DISPLAY_F(f, " -o file: result stored into `file` (only 1 output file) \n");
150b3392d84SAllan Jude     DISPLAY_F(f, " -f     : disable input and output checks. Allows overwriting existing files,\n");
151b3392d84SAllan Jude     DISPLAY_F(f, "          input from console, output to stdout, operating on links,\n");
152b3392d84SAllan Jude     DISPLAY_F(f, "          block devices, etc.\n");
153bc64b5ceSConrad Meyer     DISPLAY_F(f, "--rm    : remove source file(s) after successful de/compression \n");
154bc64b5ceSConrad Meyer     DISPLAY_F(f, " -k     : preserve source file(s) (default) \n");
155bc64b5ceSConrad Meyer     DISPLAY_F(f, " -h/-H  : display help/long help and exit \n");
156a19eddc3SBaptiste Daroussin }
157a19eddc3SBaptiste Daroussin 
usage_advanced(const char * programName)158bc64b5ceSConrad Meyer static void usage_advanced(const char* programName)
159a19eddc3SBaptiste Daroussin {
160bc64b5ceSConrad Meyer     DISPLAYOUT(WELCOME_MESSAGE);
161bc64b5ceSConrad Meyer     usage(stdout, programName);
162bc64b5ceSConrad Meyer     DISPLAYOUT( "\n");
163bc64b5ceSConrad Meyer     DISPLAYOUT( "Advanced arguments : \n");
164bc64b5ceSConrad Meyer     DISPLAYOUT( " -V     : display Version number and exit \n");
165bc64b5ceSConrad Meyer 
166b3392d84SAllan Jude     DISPLAYOUT( " -c     : write to standard output (even if it is the console) \n");
167bc64b5ceSConrad Meyer 
168bc64b5ceSConrad Meyer     DISPLAYOUT( " -v     : verbose mode; specify multiple times to increase verbosity \n");
169bc64b5ceSConrad Meyer     DISPLAYOUT( " -q     : suppress warnings; specify twice to suppress errors too \n");
170b3392d84SAllan Jude     DISPLAYOUT( "--[no-]progress : forcibly display, or never display the progress counter.\n");
171b3392d84SAllan Jude     DISPLAYOUT( "                  note: any (de)compressed output to terminal will mix with progress counter text. \n");
172bc64b5ceSConrad Meyer 
173ffcbc2d7SBaptiste Daroussin #ifdef UTIL_HAS_CREATEFILELIST
174bc64b5ceSConrad Meyer     DISPLAYOUT( " -r     : operate recursively on directories \n");
175f6ae9767SConrad Meyer     DISPLAYOUT( "--filelist FILE : read list of files to operate upon from FILE \n");
176f6ae9767SConrad Meyer     DISPLAYOUT( "--output-dir-flat DIR : processed files are stored into DIR \n");
177a19eddc3SBaptiste Daroussin #endif
178bc64b5ceSConrad Meyer 
179f6ae9767SConrad Meyer #ifdef UTIL_HAS_MIRRORFILELIST
180f6ae9767SConrad Meyer     DISPLAYOUT( "--output-dir-mirror DIR : processed files are stored into DIR respecting original directory structure \n");
181f6ae9767SConrad Meyer #endif
182f6ae9767SConrad Meyer 
183f6ae9767SConrad Meyer 
184f6ae9767SConrad Meyer #ifndef ZSTD_NOCOMPRESS
185f6ae9767SConrad Meyer     DISPLAYOUT( "--[no-]check : during compression, add XXH64 integrity checksum to frame (default: enabled)");
186f6ae9767SConrad Meyer #ifndef ZSTD_NODECOMPRESS
187f6ae9767SConrad Meyer     DISPLAYOUT( ". If specified with -d, decompressor will ignore/validate checksums in compressed frame (default: validate).");
188f6ae9767SConrad Meyer #endif
189f6ae9767SConrad Meyer #else
190f6ae9767SConrad Meyer #ifdef ZSTD_NOCOMPRESS
191f6ae9767SConrad Meyer     DISPLAYOUT( "--[no-]check : during decompression, ignore/validate checksums in compressed frame (default: validate).");
192f6ae9767SConrad Meyer #endif
193f6ae9767SConrad Meyer #endif /* ZSTD_NOCOMPRESS */
194b3392d84SAllan Jude 
195b3392d84SAllan Jude #ifndef ZSTD_NOTRACE
196b3392d84SAllan Jude     DISPLAYOUT( "\n");
197b3392d84SAllan Jude     DISPLAYOUT( "--trace FILE : log tracing information to FILE.");
198b3392d84SAllan Jude #endif
199f6ae9767SConrad Meyer     DISPLAYOUT( "\n");
200f6ae9767SConrad Meyer 
201bc64b5ceSConrad Meyer     DISPLAYOUT( "--      : All arguments after \"--\" are treated as files \n");
202bc64b5ceSConrad Meyer 
203bc64b5ceSConrad Meyer #ifndef ZSTD_NOCOMPRESS
204bc64b5ceSConrad Meyer     DISPLAYOUT( "\n");
205bc64b5ceSConrad Meyer     DISPLAYOUT( "Advanced compression arguments : \n");
206bc64b5ceSConrad Meyer     DISPLAYOUT( "--ultra : enable levels beyond %i, up to %i (requires more memory) \n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel());
207bc64b5ceSConrad Meyer     DISPLAYOUT( "--long[=#]: enable long distance matching with given window log (default: %u) \n", g_defaultMaxWindowLog);
208bc64b5ceSConrad Meyer     DISPLAYOUT( "--fast[=#]: switch to very fast compression levels (default: %u) \n", 1);
209bc64b5ceSConrad Meyer     DISPLAYOUT( "--adapt : dynamically adapt compression level to I/O conditions \n");
210b3392d84SAllan Jude     DISPLAYOUT( "--[no-]row-match-finder : force enable/disable usage of fast row-based matchfinder for greedy, lazy, and lazy2 strategies \n");
211b3392d84SAllan Jude     DISPLAYOUT( "--patch-from=FILE : specify the file to be used as a reference point for zstd's diff engine. \n");
212bc64b5ceSConrad Meyer # ifdef ZSTD_MULTITHREAD
213bc64b5ceSConrad Meyer     DISPLAYOUT( " -T#    : spawns # compression threads (default: 1, 0==# cores) \n");
214bc64b5ceSConrad Meyer     DISPLAYOUT( " -B#    : select size of each job (default: 0==automatic) \n");
215bc64b5ceSConrad Meyer     DISPLAYOUT( "--single-thread : use a single thread for both I/O and compression (result slightly different than -T1) \n");
216b3392d84SAllan Jude     DISPLAYOUT( "--auto-threads={physical,logical} (default: physical} : use either physical cores or logical cores as default when specifying -T0 \n");
217bc64b5ceSConrad Meyer     DISPLAYOUT( "--rsyncable : compress using a rsync-friendly method (-B sets block size) \n");
218bc64b5ceSConrad Meyer # endif
219bc64b5ceSConrad Meyer     DISPLAYOUT( "--exclude-compressed: only compress files that are not already compressed \n");
220bc64b5ceSConrad Meyer     DISPLAYOUT( "--stream-size=# : specify size of streaming input from `stdin` \n");
221bc64b5ceSConrad Meyer     DISPLAYOUT( "--size-hint=# optimize compression parameters for streaming input of approximately this size \n");
222bc64b5ceSConrad Meyer     DISPLAYOUT( "--target-compressed-block-size=# : generate compressed block of approximately targeted size \n");
223bc64b5ceSConrad Meyer     DISPLAYOUT( "--no-dictID : don't write dictID into header (dictionary compression only) \n");
224bc64b5ceSConrad Meyer     DISPLAYOUT( "--[no-]compress-literals : force (un)compressed literals \n");
225bc64b5ceSConrad Meyer 
226bc64b5ceSConrad Meyer     DISPLAYOUT( "--format=zstd : compress files to the .zst format (default) \n");
227a19eddc3SBaptiste Daroussin #ifdef ZSTD_GZCOMPRESS
228bc64b5ceSConrad Meyer     DISPLAYOUT( "--format=gzip : compress files to the .gz format \n");
229a19eddc3SBaptiste Daroussin #endif
230a19eddc3SBaptiste Daroussin #ifdef ZSTD_LZMACOMPRESS
231bc64b5ceSConrad Meyer     DISPLAYOUT( "--format=xz : compress files to the .xz format \n");
232bc64b5ceSConrad Meyer     DISPLAYOUT( "--format=lzma : compress files to the .lzma format \n");
233a19eddc3SBaptiste Daroussin #endif
234ffcbc2d7SBaptiste Daroussin #ifdef ZSTD_LZ4COMPRESS
235bc64b5ceSConrad Meyer     DISPLAYOUT( "--format=lz4 : compress files to the .lz4 format \n");
236a19eddc3SBaptiste Daroussin #endif
237bc64b5ceSConrad Meyer #endif  /* !ZSTD_NOCOMPRESS */
238bc64b5ceSConrad Meyer 
239a19eddc3SBaptiste Daroussin #ifndef ZSTD_NODECOMPRESS
240bc64b5ceSConrad Meyer     DISPLAYOUT( "\n");
241bc64b5ceSConrad Meyer     DISPLAYOUT( "Advanced decompression arguments : \n");
242bc64b5ceSConrad Meyer     DISPLAYOUT( " -l     : print information about zstd compressed files \n");
243bc64b5ceSConrad Meyer     DISPLAYOUT( "--test  : test compressed file integrity \n");
244bc64b5ceSConrad Meyer     DISPLAYOUT( " -M#    : Set a memory usage limit for decompression \n");
245ffcbc2d7SBaptiste Daroussin # if ZSTD_SPARSE_DEFAULT
246bc64b5ceSConrad Meyer     DISPLAYOUT( "--[no-]sparse : sparse mode (default: enabled on file, disabled on stdout) \n");
247ffcbc2d7SBaptiste Daroussin # else
248bc64b5ceSConrad Meyer     DISPLAYOUT( "--[no-]sparse : sparse mode (default: disabled) \n");
249ffcbc2d7SBaptiste Daroussin # endif
250bc64b5ceSConrad Meyer #endif  /* ZSTD_NODECOMPRESS */
251bc64b5ceSConrad Meyer 
252a19eddc3SBaptiste Daroussin #ifndef ZSTD_NODICT
253bc64b5ceSConrad Meyer     DISPLAYOUT( "\n");
254bc64b5ceSConrad Meyer     DISPLAYOUT( "Dictionary builder : \n");
255bc64b5ceSConrad Meyer     DISPLAYOUT( "--train ## : create a dictionary from a training set of files \n");
256bc64b5ceSConrad Meyer     DISPLAYOUT( "--train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args \n");
257bc64b5ceSConrad Meyer     DISPLAYOUT( "--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args \n");
258bc64b5ceSConrad Meyer     DISPLAYOUT( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u) \n", g_defaultSelectivityLevel);
259bc64b5ceSConrad Meyer     DISPLAYOUT( " -o DICT : DICT is dictionary name (default: %s) \n", g_defaultDictName);
260bc64b5ceSConrad Meyer     DISPLAYOUT( "--maxdict=# : limit dictionary to specified size (default: %u) \n", g_defaultMaxDictSize);
261bc64b5ceSConrad Meyer     DISPLAYOUT( "--dictID=# : force dictionary ID to specified value (default: random) \n");
262a19eddc3SBaptiste Daroussin #endif
263bc64b5ceSConrad Meyer 
264a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOBENCH
265bc64b5ceSConrad Meyer     DISPLAYOUT( "\n");
266bc64b5ceSConrad Meyer     DISPLAYOUT( "Benchmark arguments : \n");
267bc64b5ceSConrad Meyer     DISPLAYOUT( " -b#    : benchmark file(s), using # compression level (default: %d) \n", ZSTDCLI_CLEVEL_DEFAULT);
268bc64b5ceSConrad Meyer     DISPLAYOUT( " -e#    : test all compression levels successively from -b# to -e# (default: 1) \n");
269bc64b5ceSConrad Meyer     DISPLAYOUT( " -i#    : minimum evaluation time in seconds (default: 3s) \n");
270bc64b5ceSConrad Meyer     DISPLAYOUT( " -B#    : cut file into independent blocks of size # (default: no block) \n");
271bc64b5ceSConrad Meyer     DISPLAYOUT( " -S     : output one benchmark result per input file (default: consolidated result) \n");
272bc64b5ceSConrad Meyer     DISPLAYOUT( "--priority=rt : set process priority to real-time \n");
273a19eddc3SBaptiste Daroussin #endif
274bc64b5ceSConrad Meyer 
275a19eddc3SBaptiste Daroussin }
276a19eddc3SBaptiste Daroussin 
badusage(const char * programName)277bc64b5ceSConrad Meyer static void badusage(const char* programName)
278a19eddc3SBaptiste Daroussin {
279a19eddc3SBaptiste Daroussin     DISPLAYLEVEL(1, "Incorrect parameters \n");
280bc64b5ceSConrad Meyer     if (g_displayLevel >= 2) usage(stderr, programName);
281a19eddc3SBaptiste Daroussin }
282a19eddc3SBaptiste Daroussin 
waitEnter(void)283a19eddc3SBaptiste Daroussin static void waitEnter(void)
284a19eddc3SBaptiste Daroussin {
285a19eddc3SBaptiste Daroussin     int unused;
286a19eddc3SBaptiste Daroussin     DISPLAY("Press enter to continue... \n");
287a19eddc3SBaptiste Daroussin     unused = getchar();
288a19eddc3SBaptiste Daroussin     (void)unused;
289a19eddc3SBaptiste Daroussin }
290a19eddc3SBaptiste Daroussin 
lastNameFromPath(const char * path)291ffcbc2d7SBaptiste Daroussin static const char* lastNameFromPath(const char* path)
292ffcbc2d7SBaptiste Daroussin {
293ffcbc2d7SBaptiste Daroussin     const char* name = path;
294ffcbc2d7SBaptiste Daroussin     if (strrchr(name, '/')) name = strrchr(name, '/') + 1;
295ffcbc2d7SBaptiste Daroussin     if (strrchr(name, '\\')) name = strrchr(name, '\\') + 1; /* windows */
296ffcbc2d7SBaptiste Daroussin     return name;
297ffcbc2d7SBaptiste Daroussin }
298ffcbc2d7SBaptiste Daroussin 
299ffcbc2d7SBaptiste Daroussin /*! exeNameMatch() :
300ffcbc2d7SBaptiste Daroussin     @return : a non-zero value if exeName matches test, excluding the extension
301ffcbc2d7SBaptiste Daroussin    */
exeNameMatch(const char * exeName,const char * test)302ffcbc2d7SBaptiste Daroussin static int exeNameMatch(const char* exeName, const char* test)
303ffcbc2d7SBaptiste Daroussin {
304ffcbc2d7SBaptiste Daroussin     return !strncmp(exeName, test, strlen(test)) &&
305ffcbc2d7SBaptiste Daroussin         (exeName[strlen(test)] == '\0' || exeName[strlen(test)] == '.');
306ffcbc2d7SBaptiste Daroussin }
307ffcbc2d7SBaptiste Daroussin 
errorOut(const char * msg)308706cfae4SConrad Meyer static void errorOut(const char* msg)
309706cfae4SConrad Meyer {
310706cfae4SConrad Meyer     DISPLAY("%s \n", msg); exit(1);
311706cfae4SConrad Meyer }
312706cfae4SConrad Meyer 
313af73257bSConrad Meyer /*! readU32FromCharChecked() :
314af73257bSConrad Meyer  * @return 0 if success, and store the result in *value.
31542239e68SConrad Meyer  *  allows and interprets K, KB, KiB, M, MB and MiB suffix.
31642239e68SConrad Meyer  *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.
317af73257bSConrad Meyer  * @return 1 if an overflow error occurs */
readU32FromCharChecked(const char ** stringPtr,unsigned * value)318af73257bSConrad Meyer static int readU32FromCharChecked(const char** stringPtr, unsigned* value)
319a19eddc3SBaptiste Daroussin {
320a19eddc3SBaptiste Daroussin     unsigned result = 0;
321706cfae4SConrad Meyer     while ((**stringPtr >='0') && (**stringPtr <='9')) {
322bc64b5ceSConrad Meyer         unsigned const max = ((unsigned)(-1)) / 10;
323bc64b5ceSConrad Meyer         unsigned last = result;
3243f774a5eSConrad Meyer         if (result > max) return 1; /* overflow error */
3253f774a5eSConrad Meyer         result *= 10;
3263f774a5eSConrad Meyer         result += (unsigned)(**stringPtr - '0');
327bc64b5ceSConrad Meyer         if (result < last) return 1; /* overflow error */
3283f774a5eSConrad Meyer         (*stringPtr)++ ;
329706cfae4SConrad Meyer     }
330a19eddc3SBaptiste Daroussin     if ((**stringPtr=='K') || (**stringPtr=='M')) {
331706cfae4SConrad Meyer         unsigned const maxK = ((unsigned)(-1)) >> 10;
3323f774a5eSConrad Meyer         if (result > maxK) return 1; /* overflow error */
333a19eddc3SBaptiste Daroussin         result <<= 10;
334706cfae4SConrad Meyer         if (**stringPtr=='M') {
3353f774a5eSConrad Meyer             if (result > maxK) return 1; /* overflow error */
336706cfae4SConrad Meyer             result <<= 10;
337706cfae4SConrad Meyer         }
338706cfae4SConrad Meyer         (*stringPtr)++;  /* skip `K` or `M` */
339a19eddc3SBaptiste Daroussin         if (**stringPtr=='i') (*stringPtr)++;
340a19eddc3SBaptiste Daroussin         if (**stringPtr=='B') (*stringPtr)++;
341a19eddc3SBaptiste Daroussin     }
342af73257bSConrad Meyer     *value = result;
343af73257bSConrad Meyer     return 0;
344af73257bSConrad Meyer }
345af73257bSConrad Meyer 
346af73257bSConrad Meyer /*! readU32FromChar() :
347af73257bSConrad Meyer  * @return : unsigned integer value read from input in `char` format.
348af73257bSConrad Meyer  *  allows and interprets K, KB, KiB, M, MB and MiB suffix.
349af73257bSConrad Meyer  *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.
350af73257bSConrad Meyer  *  Note : function will exit() program if digit sequence overflows */
readU32FromChar(const char ** stringPtr)351af73257bSConrad Meyer static unsigned readU32FromChar(const char** stringPtr) {
352bc64b5ceSConrad Meyer     static const char errorMsg[] = "error: numeric value overflows 32-bit unsigned int";
353af73257bSConrad Meyer     unsigned result;
354af73257bSConrad Meyer     if (readU32FromCharChecked(stringPtr, &result)) { errorOut(errorMsg); }
355a19eddc3SBaptiste Daroussin     return result;
356a19eddc3SBaptiste Daroussin }
357a19eddc3SBaptiste Daroussin 
358b3392d84SAllan Jude /*! readIntFromChar() :
359b3392d84SAllan Jude  * @return : signed integer value read from input in `char` format.
360b3392d84SAllan Jude  *  allows and interprets K, KB, KiB, M, MB and MiB suffix.
361b3392d84SAllan Jude  *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.
362b3392d84SAllan Jude  *  Note : function will exit() program if digit sequence overflows */
readIntFromChar(const char ** stringPtr)363b3392d84SAllan Jude static int readIntFromChar(const char** stringPtr) {
364b3392d84SAllan Jude     static const char errorMsg[] = "error: numeric value overflows 32-bit int";
365b3392d84SAllan Jude     int sign = 1;
366b3392d84SAllan Jude     unsigned result;
367b3392d84SAllan Jude     if (**stringPtr=='-') {
368b3392d84SAllan Jude         (*stringPtr)++;
369b3392d84SAllan Jude         sign = -1;
370b3392d84SAllan Jude     }
371b3392d84SAllan Jude     if (readU32FromCharChecked(stringPtr, &result)) { errorOut(errorMsg); }
372b3392d84SAllan Jude     return (int) result * sign;
373b3392d84SAllan Jude }
374b3392d84SAllan Jude 
375bc64b5ceSConrad Meyer /*! readSizeTFromCharChecked() :
376bc64b5ceSConrad Meyer  * @return 0 if success, and store the result in *value.
377bc64b5ceSConrad Meyer  *  allows and interprets K, KB, KiB, M, MB and MiB suffix.
378bc64b5ceSConrad Meyer  *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.
379bc64b5ceSConrad Meyer  * @return 1 if an overflow error occurs */
readSizeTFromCharChecked(const char ** stringPtr,size_t * value)380bc64b5ceSConrad Meyer static int readSizeTFromCharChecked(const char** stringPtr, size_t* value)
381bc64b5ceSConrad Meyer {
382bc64b5ceSConrad Meyer     size_t result = 0;
383bc64b5ceSConrad Meyer     while ((**stringPtr >='0') && (**stringPtr <='9')) {
384bc64b5ceSConrad Meyer         size_t const max = ((size_t)(-1)) / 10;
385bc64b5ceSConrad Meyer         size_t last = result;
386bc64b5ceSConrad Meyer         if (result > max) return 1; /* overflow error */
387bc64b5ceSConrad Meyer         result *= 10;
388bc64b5ceSConrad Meyer         result += (size_t)(**stringPtr - '0');
389bc64b5ceSConrad Meyer         if (result < last) return 1; /* overflow error */
390bc64b5ceSConrad Meyer         (*stringPtr)++ ;
391bc64b5ceSConrad Meyer     }
392bc64b5ceSConrad Meyer     if ((**stringPtr=='K') || (**stringPtr=='M')) {
393bc64b5ceSConrad Meyer         size_t const maxK = ((size_t)(-1)) >> 10;
394bc64b5ceSConrad Meyer         if (result > maxK) return 1; /* overflow error */
395bc64b5ceSConrad Meyer         result <<= 10;
396bc64b5ceSConrad Meyer         if (**stringPtr=='M') {
397bc64b5ceSConrad Meyer             if (result > maxK) return 1; /* overflow error */
398bc64b5ceSConrad Meyer             result <<= 10;
399bc64b5ceSConrad Meyer         }
400bc64b5ceSConrad Meyer         (*stringPtr)++;  /* skip `K` or `M` */
401bc64b5ceSConrad Meyer         if (**stringPtr=='i') (*stringPtr)++;
402bc64b5ceSConrad Meyer         if (**stringPtr=='B') (*stringPtr)++;
403bc64b5ceSConrad Meyer     }
404bc64b5ceSConrad Meyer     *value = result;
405bc64b5ceSConrad Meyer     return 0;
406bc64b5ceSConrad Meyer }
407bc64b5ceSConrad Meyer 
408bc64b5ceSConrad Meyer /*! readSizeTFromChar() :
409bc64b5ceSConrad Meyer  * @return : size_t value read from input in `char` format.
410bc64b5ceSConrad Meyer  *  allows and interprets K, KB, KiB, M, MB and MiB suffix.
411bc64b5ceSConrad Meyer  *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.
412bc64b5ceSConrad Meyer  *  Note : function will exit() program if digit sequence overflows */
readSizeTFromChar(const char ** stringPtr)413bc64b5ceSConrad Meyer static size_t readSizeTFromChar(const char** stringPtr) {
414bc64b5ceSConrad Meyer     static const char errorMsg[] = "error: numeric value overflows size_t";
415bc64b5ceSConrad Meyer     size_t result;
416bc64b5ceSConrad Meyer     if (readSizeTFromCharChecked(stringPtr, &result)) { errorOut(errorMsg); }
417bc64b5ceSConrad Meyer     return result;
418bc64b5ceSConrad Meyer }
419bc64b5ceSConrad Meyer 
420a19eddc3SBaptiste Daroussin /** longCommandWArg() :
421a19eddc3SBaptiste Daroussin  *  check if *stringPtr is the same as longCommand.
422a19eddc3SBaptiste Daroussin  *  If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
423a19eddc3SBaptiste Daroussin  * @return 0 and doesn't modify *stringPtr otherwise.
424a19eddc3SBaptiste Daroussin  */
longCommandWArg(const char ** stringPtr,const char * longCommand)425ea684039SConrad Meyer static int longCommandWArg(const char** stringPtr, const char* longCommand)
426a19eddc3SBaptiste Daroussin {
427a19eddc3SBaptiste Daroussin     size_t const comSize = strlen(longCommand);
428a19eddc3SBaptiste Daroussin     int const result = !strncmp(*stringPtr, longCommand, comSize);
429a19eddc3SBaptiste Daroussin     if (result) *stringPtr += comSize;
430a19eddc3SBaptiste Daroussin     return result;
431a19eddc3SBaptiste Daroussin }
432a19eddc3SBaptiste Daroussin 
433a19eddc3SBaptiste Daroussin 
434a19eddc3SBaptiste Daroussin #ifndef ZSTD_NODICT
43590f4bdbeSConrad Meyer 
43690f4bdbeSConrad Meyer static const unsigned kDefaultRegression = 1;
437a19eddc3SBaptiste Daroussin /**
438a19eddc3SBaptiste Daroussin  * parseCoverParameters() :
439ffcbc2d7SBaptiste Daroussin  * reads cover parameters from *stringPtr (e.g. "--train-cover=k=48,d=8,steps=32") into *params
440a19eddc3SBaptiste Daroussin  * @return 1 means that cover parameters were correct
441a19eddc3SBaptiste Daroussin  * @return 0 in case of malformed parameters
442a19eddc3SBaptiste Daroussin  */
parseCoverParameters(const char * stringPtr,ZDICT_cover_params_t * params)443affe9eafSBaptiste Daroussin static unsigned parseCoverParameters(const char* stringPtr, ZDICT_cover_params_t* params)
444a19eddc3SBaptiste Daroussin {
445a19eddc3SBaptiste Daroussin     memset(params, 0, sizeof(*params));
446a19eddc3SBaptiste Daroussin     for (; ;) {
447a19eddc3SBaptiste Daroussin         if (longCommandWArg(&stringPtr, "k=")) { params->k = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
448a19eddc3SBaptiste Daroussin         if (longCommandWArg(&stringPtr, "d=")) { params->d = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
449a19eddc3SBaptiste Daroussin         if (longCommandWArg(&stringPtr, "steps=")) { params->steps = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
450706cfae4SConrad Meyer         if (longCommandWArg(&stringPtr, "split=")) {
451706cfae4SConrad Meyer           unsigned splitPercentage = readU32FromChar(&stringPtr);
452706cfae4SConrad Meyer           params->splitPoint = (double)splitPercentage / 100.0;
453706cfae4SConrad Meyer           if (stringPtr[0]==',') { stringPtr++; continue; } else break;
454706cfae4SConrad Meyer         }
455fa94c738SConrad Meyer         if (longCommandWArg(&stringPtr, "shrink")) {
456fa94c738SConrad Meyer           params->shrinkDictMaxRegression = kDefaultRegression;
457fa94c738SConrad Meyer           params->shrinkDict = 1;
458fa94c738SConrad Meyer           if (stringPtr[0]=='=') {
459fa94c738SConrad Meyer             stringPtr++;
460fa94c738SConrad Meyer             params->shrinkDictMaxRegression = readU32FromChar(&stringPtr);
461fa94c738SConrad Meyer           }
462fa94c738SConrad Meyer           if (stringPtr[0]==',') {
463fa94c738SConrad Meyer             stringPtr++;
464fa94c738SConrad Meyer             continue;
465fa94c738SConrad Meyer           }
466fa94c738SConrad Meyer           else break;
467fa94c738SConrad Meyer         }
468a19eddc3SBaptiste Daroussin         return 0;
469a19eddc3SBaptiste Daroussin     }
470a19eddc3SBaptiste Daroussin     if (stringPtr[0] != 0) return 0;
471fa94c738SConrad Meyer     DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nsteps=%u\nsplit=%u\nshrink%u\n", params->k, params->d, params->steps, (unsigned)(params->splitPoint * 100), params->shrinkDictMaxRegression);
472706cfae4SConrad Meyer     return 1;
473706cfae4SConrad Meyer }
474706cfae4SConrad Meyer 
475706cfae4SConrad Meyer /**
476706cfae4SConrad Meyer  * parseFastCoverParameters() :
477706cfae4SConrad Meyer  * reads fastcover parameters from *stringPtr (e.g. "--train-fastcover=k=48,d=8,f=20,steps=32,accel=2") into *params
478706cfae4SConrad Meyer  * @return 1 means that fastcover parameters were correct
479706cfae4SConrad Meyer  * @return 0 in case of malformed parameters
480706cfae4SConrad Meyer  */
parseFastCoverParameters(const char * stringPtr,ZDICT_fastCover_params_t * params)481706cfae4SConrad Meyer static unsigned parseFastCoverParameters(const char* stringPtr, ZDICT_fastCover_params_t* params)
482706cfae4SConrad Meyer {
483706cfae4SConrad Meyer     memset(params, 0, sizeof(*params));
484706cfae4SConrad Meyer     for (; ;) {
485706cfae4SConrad Meyer         if (longCommandWArg(&stringPtr, "k=")) { params->k = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
486706cfae4SConrad Meyer         if (longCommandWArg(&stringPtr, "d=")) { params->d = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
487706cfae4SConrad Meyer         if (longCommandWArg(&stringPtr, "f=")) { params->f = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
488706cfae4SConrad Meyer         if (longCommandWArg(&stringPtr, "steps=")) { params->steps = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
489706cfae4SConrad Meyer         if (longCommandWArg(&stringPtr, "accel=")) { params->accel = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
490706cfae4SConrad Meyer         if (longCommandWArg(&stringPtr, "split=")) {
491706cfae4SConrad Meyer           unsigned splitPercentage = readU32FromChar(&stringPtr);
492706cfae4SConrad Meyer           params->splitPoint = (double)splitPercentage / 100.0;
493706cfae4SConrad Meyer           if (stringPtr[0]==',') { stringPtr++; continue; } else break;
494706cfae4SConrad Meyer         }
495fa94c738SConrad Meyer         if (longCommandWArg(&stringPtr, "shrink")) {
496fa94c738SConrad Meyer           params->shrinkDictMaxRegression = kDefaultRegression;
497fa94c738SConrad Meyer           params->shrinkDict = 1;
498fa94c738SConrad Meyer           if (stringPtr[0]=='=') {
499fa94c738SConrad Meyer             stringPtr++;
500fa94c738SConrad Meyer             params->shrinkDictMaxRegression = readU32FromChar(&stringPtr);
501fa94c738SConrad Meyer           }
502fa94c738SConrad Meyer           if (stringPtr[0]==',') {
503fa94c738SConrad Meyer             stringPtr++;
504fa94c738SConrad Meyer             continue;
505fa94c738SConrad Meyer           }
506fa94c738SConrad Meyer           else break;
507fa94c738SConrad Meyer         }
508706cfae4SConrad Meyer         return 0;
509706cfae4SConrad Meyer     }
510706cfae4SConrad Meyer     if (stringPtr[0] != 0) return 0;
511fa94c738SConrad Meyer     DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nf=%u\nsteps=%u\nsplit=%u\naccel=%u\nshrink=%u\n", params->k, params->d, params->f, params->steps, (unsigned)(params->splitPoint * 100), params->accel, params->shrinkDictMaxRegression);
512a19eddc3SBaptiste Daroussin     return 1;
513a19eddc3SBaptiste Daroussin }
514ffcbc2d7SBaptiste Daroussin 
515ffcbc2d7SBaptiste Daroussin /**
516ffcbc2d7SBaptiste Daroussin  * parseLegacyParameters() :
5173f774a5eSConrad Meyer  * reads legacy dictionary builder parameters from *stringPtr (e.g. "--train-legacy=selectivity=8") into *selectivity
518ffcbc2d7SBaptiste Daroussin  * @return 1 means that legacy dictionary builder parameters were correct
519ffcbc2d7SBaptiste Daroussin  * @return 0 in case of malformed parameters
520ffcbc2d7SBaptiste Daroussin  */
parseLegacyParameters(const char * stringPtr,unsigned * selectivity)521ffcbc2d7SBaptiste Daroussin static unsigned parseLegacyParameters(const char* stringPtr, unsigned* selectivity)
522ffcbc2d7SBaptiste Daroussin {
523ffcbc2d7SBaptiste Daroussin     if (!longCommandWArg(&stringPtr, "s=") && !longCommandWArg(&stringPtr, "selectivity=")) { return 0; }
524ffcbc2d7SBaptiste Daroussin     *selectivity = readU32FromChar(&stringPtr);
525ffcbc2d7SBaptiste Daroussin     if (stringPtr[0] != 0) return 0;
526ffcbc2d7SBaptiste Daroussin     DISPLAYLEVEL(4, "legacy: selectivity=%u\n", *selectivity);
527ffcbc2d7SBaptiste Daroussin     return 1;
528ffcbc2d7SBaptiste Daroussin }
529ffcbc2d7SBaptiste Daroussin 
defaultCoverParams(void)530affe9eafSBaptiste Daroussin static ZDICT_cover_params_t defaultCoverParams(void)
531ffcbc2d7SBaptiste Daroussin {
532affe9eafSBaptiste Daroussin     ZDICT_cover_params_t params;
533ffcbc2d7SBaptiste Daroussin     memset(&params, 0, sizeof(params));
534ffcbc2d7SBaptiste Daroussin     params.d = 8;
535ffcbc2d7SBaptiste Daroussin     params.steps = 4;
536706cfae4SConrad Meyer     params.splitPoint = 1.0;
537fa94c738SConrad Meyer     params.shrinkDict = 0;
538fa94c738SConrad Meyer     params.shrinkDictMaxRegression = kDefaultRegression;
539706cfae4SConrad Meyer     return params;
540706cfae4SConrad Meyer }
541706cfae4SConrad Meyer 
defaultFastCoverParams(void)542706cfae4SConrad Meyer static ZDICT_fastCover_params_t defaultFastCoverParams(void)
543706cfae4SConrad Meyer {
544706cfae4SConrad Meyer     ZDICT_fastCover_params_t params;
545706cfae4SConrad Meyer     memset(&params, 0, sizeof(params));
546706cfae4SConrad Meyer     params.d = 8;
547706cfae4SConrad Meyer     params.f = 20;
548706cfae4SConrad Meyer     params.steps = 4;
549706cfae4SConrad Meyer     params.splitPoint = 0.75; /* different from default splitPoint of cover */
550706cfae4SConrad Meyer     params.accel = DEFAULT_ACCEL;
551fa94c738SConrad Meyer     params.shrinkDict = 0;
552fa94c738SConrad Meyer     params.shrinkDictMaxRegression = kDefaultRegression;
553ffcbc2d7SBaptiste Daroussin     return params;
554ffcbc2d7SBaptiste Daroussin }
555a19eddc3SBaptiste Daroussin #endif
556a19eddc3SBaptiste Daroussin 
557a19eddc3SBaptiste Daroussin 
558706cfae4SConrad Meyer /** parseAdaptParameters() :
559706cfae4SConrad Meyer  *  reads adapt parameters from *stringPtr (e.g. "--zstd=min=1,max=19) and store them into adaptMinPtr and adaptMaxPtr.
560706cfae4SConrad Meyer  *  Both adaptMinPtr and adaptMaxPtr must be already allocated and correctly initialized.
561706cfae4SConrad Meyer  *  There is no guarantee that any of these values will be updated.
562706cfae4SConrad Meyer  *  @return 1 means that parsing was successful,
563706cfae4SConrad Meyer  *  @return 0 in case of malformed parameters
564706cfae4SConrad Meyer  */
parseAdaptParameters(const char * stringPtr,int * adaptMinPtr,int * adaptMaxPtr)565706cfae4SConrad Meyer static unsigned parseAdaptParameters(const char* stringPtr, int* adaptMinPtr, int* adaptMaxPtr)
566706cfae4SConrad Meyer {
567706cfae4SConrad Meyer     for ( ; ;) {
568b3392d84SAllan Jude         if (longCommandWArg(&stringPtr, "min=")) { *adaptMinPtr = readIntFromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
569b3392d84SAllan Jude         if (longCommandWArg(&stringPtr, "max=")) { *adaptMaxPtr = readIntFromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
570706cfae4SConrad Meyer         DISPLAYLEVEL(4, "invalid compression parameter \n");
571706cfae4SConrad Meyer         return 0;
572706cfae4SConrad Meyer     }
573706cfae4SConrad Meyer     if (stringPtr[0] != 0) return 0; /* check the end of string */
574706cfae4SConrad Meyer     if (*adaptMinPtr > *adaptMaxPtr) {
575706cfae4SConrad Meyer         DISPLAYLEVEL(4, "incoherent adaptation limits \n");
576706cfae4SConrad Meyer         return 0;
577706cfae4SConrad Meyer     }
578706cfae4SConrad Meyer     return 1;
579706cfae4SConrad Meyer }
580706cfae4SConrad Meyer 
581706cfae4SConrad Meyer 
582a19eddc3SBaptiste Daroussin /** parseCompressionParameters() :
583af73257bSConrad Meyer  *  reads compression parameters from *stringPtr (e.g. "--zstd=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6") into *params
584a19eddc3SBaptiste Daroussin  *  @return 1 means that compression parameters were correct
585a19eddc3SBaptiste Daroussin  *  @return 0 in case of malformed parameters
586a19eddc3SBaptiste Daroussin  */
parseCompressionParameters(const char * stringPtr,ZSTD_compressionParameters * params)587a19eddc3SBaptiste Daroussin static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressionParameters* params)
588a19eddc3SBaptiste Daroussin {
589a19eddc3SBaptiste Daroussin     for ( ; ;) {
590a19eddc3SBaptiste Daroussin         if (longCommandWArg(&stringPtr, "windowLog=") || longCommandWArg(&stringPtr, "wlog=")) { params->windowLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
591a19eddc3SBaptiste Daroussin         if (longCommandWArg(&stringPtr, "chainLog=") || longCommandWArg(&stringPtr, "clog=")) { params->chainLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
592a19eddc3SBaptiste Daroussin         if (longCommandWArg(&stringPtr, "hashLog=") || longCommandWArg(&stringPtr, "hlog=")) { params->hashLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
593a19eddc3SBaptiste Daroussin         if (longCommandWArg(&stringPtr, "searchLog=") || longCommandWArg(&stringPtr, "slog=")) { params->searchLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
594af73257bSConrad Meyer         if (longCommandWArg(&stringPtr, "minMatch=") || longCommandWArg(&stringPtr, "mml=")) { params->minMatch = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
595a19eddc3SBaptiste Daroussin         if (longCommandWArg(&stringPtr, "targetLength=") || longCommandWArg(&stringPtr, "tlen=")) { params->targetLength = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
596affe9eafSBaptiste Daroussin         if (longCommandWArg(&stringPtr, "strategy=") || longCommandWArg(&stringPtr, "strat=")) { params->strategy = (ZSTD_strategy)(readU32FromChar(&stringPtr)); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
597a19eddc3SBaptiste Daroussin         if (longCommandWArg(&stringPtr, "overlapLog=") || longCommandWArg(&stringPtr, "ovlog=")) { g_overlapLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
598af73257bSConrad Meyer         if (longCommandWArg(&stringPtr, "ldmHashLog=") || longCommandWArg(&stringPtr, "lhlog=")) { g_ldmHashLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
599af73257bSConrad Meyer         if (longCommandWArg(&stringPtr, "ldmMinMatch=") || longCommandWArg(&stringPtr, "lmml=")) { g_ldmMinMatch = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
600af73257bSConrad Meyer         if (longCommandWArg(&stringPtr, "ldmBucketSizeLog=") || longCommandWArg(&stringPtr, "lblog=")) { g_ldmBucketSizeLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
601af73257bSConrad Meyer         if (longCommandWArg(&stringPtr, "ldmHashRateLog=") || longCommandWArg(&stringPtr, "lhrlog=")) { g_ldmHashRateLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
60242239e68SConrad Meyer         DISPLAYLEVEL(4, "invalid compression parameter \n");
603a19eddc3SBaptiste Daroussin         return 0;
604a19eddc3SBaptiste Daroussin     }
605a19eddc3SBaptiste Daroussin 
60642239e68SConrad Meyer     DISPLAYLEVEL(4, "windowLog=%d, chainLog=%d, hashLog=%d, searchLog=%d \n", params->windowLog, params->chainLog, params->hashLog, params->searchLog);
607af73257bSConrad Meyer     DISPLAYLEVEL(4, "minMatch=%d, targetLength=%d, strategy=%d \n", params->minMatch, params->targetLength, params->strategy);
608a19eddc3SBaptiste Daroussin     if (stringPtr[0] != 0) return 0; /* check the end of string */
609a19eddc3SBaptiste Daroussin     return 1;
610a19eddc3SBaptiste Daroussin }
611a19eddc3SBaptiste Daroussin 
printVersion(void)612902c8ce7SBaptiste Daroussin static void printVersion(void)
613902c8ce7SBaptiste Daroussin {
614f6ae9767SConrad Meyer     if (g_displayLevel < DISPLAY_LEVEL_DEFAULT) {
615f6ae9767SConrad Meyer         DISPLAYOUT("%s\n", ZSTD_VERSION_STRING);
616f6ae9767SConrad Meyer         return;
617f6ae9767SConrad Meyer     }
618f6ae9767SConrad Meyer 
619bc64b5ceSConrad Meyer     DISPLAYOUT(WELCOME_MESSAGE);
620bc64b5ceSConrad Meyer     if (g_displayLevel >= 3) {
621902c8ce7SBaptiste Daroussin     /* format support */
622bc64b5ceSConrad Meyer         DISPLAYOUT("*** supports: zstd");
623902c8ce7SBaptiste Daroussin     #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>0) && (ZSTD_LEGACY_SUPPORT<8)
624bc64b5ceSConrad Meyer         DISPLAYOUT(", zstd legacy v0.%d+", ZSTD_LEGACY_SUPPORT);
625902c8ce7SBaptiste Daroussin     #endif
626902c8ce7SBaptiste Daroussin     #ifdef ZSTD_GZCOMPRESS
627bc64b5ceSConrad Meyer         DISPLAYOUT(", gzip");
628902c8ce7SBaptiste Daroussin     #endif
629902c8ce7SBaptiste Daroussin     #ifdef ZSTD_LZ4COMPRESS
630bc64b5ceSConrad Meyer         DISPLAYOUT(", lz4");
631902c8ce7SBaptiste Daroussin     #endif
632902c8ce7SBaptiste Daroussin     #ifdef ZSTD_LZMACOMPRESS
633bc64b5ceSConrad Meyer         DISPLAYOUT(", lzma, xz ");
634902c8ce7SBaptiste Daroussin     #endif
635bc64b5ceSConrad Meyer         DISPLAYOUT("\n");
636bc64b5ceSConrad Meyer         if (g_displayLevel >= 4) {
637902c8ce7SBaptiste Daroussin             /* posix support */
638902c8ce7SBaptiste Daroussin         #ifdef _POSIX_C_SOURCE
639bc64b5ceSConrad Meyer             DISPLAYOUT("_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE);
640902c8ce7SBaptiste Daroussin         #endif
641902c8ce7SBaptiste Daroussin         #ifdef _POSIX_VERSION
642bc64b5ceSConrad Meyer             DISPLAYOUT("_POSIX_VERSION defined: %ldL \n", (long) _POSIX_VERSION);
643902c8ce7SBaptiste Daroussin         #endif
644902c8ce7SBaptiste Daroussin         #ifdef PLATFORM_POSIX_VERSION
645bc64b5ceSConrad Meyer             DISPLAYOUT("PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION);
646902c8ce7SBaptiste Daroussin         #endif
647bc64b5ceSConrad Meyer     }   }
648902c8ce7SBaptiste Daroussin }
649a19eddc3SBaptiste Daroussin 
650b3392d84SAllan Jude #define ZSTD_NB_STRATEGIES 9
651b3392d84SAllan Jude static const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { "", "ZSTD_fast",
652b3392d84SAllan Jude                 "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2",
653b3392d84SAllan Jude                 "ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"};
654b3392d84SAllan Jude 
655b3392d84SAllan Jude #ifndef ZSTD_NOCOMPRESS
656b3392d84SAllan Jude 
printDefaultCParams(const char * filename,const char * dictFileName,int cLevel)657b3392d84SAllan Jude static void printDefaultCParams(const char* filename, const char* dictFileName, int cLevel) {
658b3392d84SAllan Jude     unsigned long long fileSize = UTIL_getFileSize(filename);
659b3392d84SAllan Jude     const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0;
660b3392d84SAllan Jude     const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize);
661b3392d84SAllan Jude     if (fileSize != UTIL_FILESIZE_UNKNOWN) DISPLAY("%s (%u bytes)\n", filename, (unsigned)fileSize);
662b3392d84SAllan Jude     else DISPLAY("%s (src size unknown)\n", filename);
663b3392d84SAllan Jude     DISPLAY(" - windowLog     : %u\n", cParams.windowLog);
664b3392d84SAllan Jude     DISPLAY(" - chainLog      : %u\n", cParams.chainLog);
665b3392d84SAllan Jude     DISPLAY(" - hashLog       : %u\n", cParams.hashLog);
666b3392d84SAllan Jude     DISPLAY(" - searchLog     : %u\n", cParams.searchLog);
667b3392d84SAllan Jude     DISPLAY(" - minMatch      : %u\n", cParams.minMatch);
668b3392d84SAllan Jude     DISPLAY(" - targetLength  : %u\n", cParams.targetLength);
669b3392d84SAllan Jude     assert(cParams.strategy < ZSTD_NB_STRATEGIES + 1);
670b3392d84SAllan Jude     DISPLAY(" - strategy      : %s (%u)\n", ZSTD_strategyMap[(int)cParams.strategy], (unsigned)cParams.strategy);
671b3392d84SAllan Jude }
672b3392d84SAllan Jude 
printActualCParams(const char * filename,const char * dictFileName,int cLevel,const ZSTD_compressionParameters * cParams)673b3392d84SAllan Jude static void printActualCParams(const char* filename, const char* dictFileName, int cLevel, const ZSTD_compressionParameters* cParams) {
674b3392d84SAllan Jude     unsigned long long fileSize = UTIL_getFileSize(filename);
675b3392d84SAllan Jude     const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0;
676b3392d84SAllan Jude     ZSTD_compressionParameters actualCParams = ZSTD_getCParams(cLevel, fileSize, dictSize);
677b3392d84SAllan Jude     assert(g_displayLevel >= 4);
678b3392d84SAllan Jude     actualCParams.windowLog = cParams->windowLog == 0 ? actualCParams.windowLog : cParams->windowLog;
679b3392d84SAllan Jude     actualCParams.chainLog = cParams->chainLog == 0 ? actualCParams.chainLog : cParams->chainLog;
680b3392d84SAllan Jude     actualCParams.hashLog = cParams->hashLog == 0 ? actualCParams.hashLog : cParams->hashLog;
681b3392d84SAllan Jude     actualCParams.searchLog = cParams->searchLog == 0 ? actualCParams.searchLog : cParams->searchLog;
682b3392d84SAllan Jude     actualCParams.minMatch = cParams->minMatch == 0 ? actualCParams.minMatch : cParams->minMatch;
683b3392d84SAllan Jude     actualCParams.targetLength = cParams->targetLength == 0 ? actualCParams.targetLength : cParams->targetLength;
684b3392d84SAllan Jude     actualCParams.strategy = cParams->strategy == 0 ? actualCParams.strategy : cParams->strategy;
685b3392d84SAllan Jude     DISPLAY("--zstd=wlog=%d,clog=%d,hlog=%d,slog=%d,mml=%d,tlen=%d,strat=%d\n",
686b3392d84SAllan Jude             actualCParams.windowLog, actualCParams.chainLog, actualCParams.hashLog, actualCParams.searchLog,
687b3392d84SAllan Jude             actualCParams.minMatch, actualCParams.targetLength, actualCParams.strategy);
688b3392d84SAllan Jude }
689b3392d84SAllan Jude 
690b3392d84SAllan Jude #endif
691b3392d84SAllan Jude 
692af73257bSConrad Meyer /* Environment variables for parameter setting */
693af73257bSConrad Meyer #define ENV_CLEVEL "ZSTD_CLEVEL"
694f6ae9767SConrad Meyer #define ENV_NBTHREADS "ZSTD_NBTHREADS"    /* takes lower precedence than directly specifying -T# in the CLI */
695af73257bSConrad Meyer 
696bc64b5ceSConrad Meyer /* pick up environment variable */
init_cLevel(void)697af73257bSConrad Meyer static int init_cLevel(void) {
698af73257bSConrad Meyer     const char* const env = getenv(ENV_CLEVEL);
699bc64b5ceSConrad Meyer     if (env != NULL) {
700af73257bSConrad Meyer         const char* ptr = env;
701af73257bSConrad Meyer         int sign = 1;
702af73257bSConrad Meyer         if (*ptr == '-') {
703af73257bSConrad Meyer             sign = -1;
704af73257bSConrad Meyer             ptr++;
705af73257bSConrad Meyer         } else if (*ptr == '+') {
706af73257bSConrad Meyer             ptr++;
707af73257bSConrad Meyer         }
708af73257bSConrad Meyer 
709af73257bSConrad Meyer         if ((*ptr>='0') && (*ptr<='9')) {
710af73257bSConrad Meyer             unsigned absLevel;
711af73257bSConrad Meyer             if (readU32FromCharChecked(&ptr, &absLevel)) {
712af73257bSConrad Meyer                 DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: numeric value too large \n", ENV_CLEVEL, env);
713af73257bSConrad Meyer                 return ZSTDCLI_CLEVEL_DEFAULT;
714af73257bSConrad Meyer             } else if (*ptr == 0) {
715ea684039SConrad Meyer                 return sign * (int)absLevel;
716bc64b5ceSConrad Meyer         }   }
717af73257bSConrad Meyer 
718af73257bSConrad Meyer         DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid integer value \n", ENV_CLEVEL, env);
719af73257bSConrad Meyer     }
720af73257bSConrad Meyer 
721af73257bSConrad Meyer     return ZSTDCLI_CLEVEL_DEFAULT;
722af73257bSConrad Meyer }
723af73257bSConrad Meyer 
724f6ae9767SConrad Meyer #ifdef ZSTD_MULTITHREAD
init_nbThreads(void)725f6ae9767SConrad Meyer static unsigned init_nbThreads(void) {
726f6ae9767SConrad Meyer     const char* const env = getenv(ENV_NBTHREADS);
727f6ae9767SConrad Meyer     if (env != NULL) {
728f6ae9767SConrad Meyer         const char* ptr = env;
729f6ae9767SConrad Meyer         if ((*ptr>='0') && (*ptr<='9')) {
730f6ae9767SConrad Meyer             unsigned nbThreads;
731f6ae9767SConrad Meyer             if (readU32FromCharChecked(&ptr, &nbThreads)) {
732f6ae9767SConrad Meyer                 DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: numeric value too large \n", ENV_NBTHREADS, env);
733f6ae9767SConrad Meyer                 return ZSTDCLI_NBTHREADS_DEFAULT;
734f6ae9767SConrad Meyer             } else if (*ptr == 0) {
735f6ae9767SConrad Meyer                 return nbThreads;
736f6ae9767SConrad Meyer             }
737f6ae9767SConrad Meyer         }
738f6ae9767SConrad Meyer         DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid unsigned value \n", ENV_NBTHREADS, env);
739f6ae9767SConrad Meyer     }
740bc64b5ceSConrad Meyer 
741f6ae9767SConrad Meyer     return ZSTDCLI_NBTHREADS_DEFAULT;
742f6ae9767SConrad Meyer }
743f6ae9767SConrad Meyer #endif
744f6ae9767SConrad Meyer 
745f6ae9767SConrad Meyer #define NEXT_FIELD(ptr) {         \
746f6ae9767SConrad Meyer     if (*argument == '=') {       \
747f6ae9767SConrad Meyer         ptr = ++argument;         \
748f6ae9767SConrad Meyer         argument += strlen(ptr);  \
749f6ae9767SConrad Meyer     } else {                      \
750f6ae9767SConrad Meyer         argNb++;                  \
751f6ae9767SConrad Meyer         if (argNb >= argCount) {  \
752f6ae9767SConrad Meyer             DISPLAY("error: missing command argument \n"); \
753f6ae9767SConrad Meyer             CLEAN_RETURN(1);      \
754f6ae9767SConrad Meyer         }                         \
755f6ae9767SConrad Meyer         ptr = argv[argNb];        \
756f6ae9767SConrad Meyer         assert(ptr != NULL);      \
757f6ae9767SConrad Meyer         if (ptr[0]=='-') {        \
758f6ae9767SConrad Meyer             DISPLAY("error: command cannot be separated from its argument by another command \n"); \
759f6ae9767SConrad Meyer             CLEAN_RETURN(1);      \
760f6ae9767SConrad Meyer }   }   }
761f6ae9767SConrad Meyer 
762f6ae9767SConrad Meyer #define NEXT_UINT32(val32) {      \
763f6ae9767SConrad Meyer     const char* __nb;             \
764f6ae9767SConrad Meyer     NEXT_FIELD(__nb);             \
765f6ae9767SConrad Meyer     val32 = readU32FromChar(&__nb); \
766f6ae9767SConrad Meyer }
767f6ae9767SConrad Meyer 
768affe9eafSBaptiste Daroussin typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train, zom_list } zstd_operation_mode;
769a19eddc3SBaptiste Daroussin 
770a19eddc3SBaptiste Daroussin #define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
771a19eddc3SBaptiste Daroussin 
772706cfae4SConrad Meyer #ifdef ZSTD_NOCOMPRESS
773706cfae4SConrad Meyer /* symbols from compression library are not defined and should not be invoked */
774bc64b5ceSConrad Meyer # define MINCLEVEL  -99
775706cfae4SConrad Meyer # define MAXCLEVEL   22
776706cfae4SConrad Meyer #else
777706cfae4SConrad Meyer # define MINCLEVEL  ZSTD_minCLevel()
778706cfae4SConrad Meyer # define MAXCLEVEL  ZSTD_maxCLevel()
779706cfae4SConrad Meyer #endif
780706cfae4SConrad Meyer 
main(int argCount,const char * argv[])781b3392d84SAllan Jude int main(int argCount, const char* argv[])
782a19eddc3SBaptiste Daroussin {
783a19eddc3SBaptiste Daroussin     int argNb,
784ffcbc2d7SBaptiste Daroussin         followLinks = 0,
785b3392d84SAllan Jude         allowBlockDevices = 0,
786b3392d84SAllan Jude         forceStdin = 0,
78742239e68SConrad Meyer         forceStdout = 0,
788f6ae9767SConrad Meyer         hasStdout = 0,
78942239e68SConrad Meyer         ldmFlag = 0,
790a19eddc3SBaptiste Daroussin         main_pause = 0,
79142239e68SConrad Meyer         nbWorkers = 0,
792706cfae4SConrad Meyer         adapt = 0,
793b3392d84SAllan Jude         useRowMatchFinder = 0,
794706cfae4SConrad Meyer         adaptMin = MINCLEVEL,
795706cfae4SConrad Meyer         adaptMax = MAXCLEVEL,
796af73257bSConrad Meyer         rsyncable = 0,
797a19eddc3SBaptiste Daroussin         nextArgumentsAreFiles = 0,
79842239e68SConrad Meyer         operationResult = 0,
7991767cc49SConrad Meyer         separateFiles = 0,
80042239e68SConrad Meyer         setRealTimePrio = 0,
80142239e68SConrad Meyer         singleThread = 0,
802b3392d84SAllan Jude #ifdef ZSTD_MULTITHREAD
803b3392d84SAllan Jude         defaultLogicalCores = 0,
804b3392d84SAllan Jude #endif
805bc64b5ceSConrad Meyer         showDefaultCParams = 0,
806bc64b5ceSConrad Meyer         ultra=0,
807bc64b5ceSConrad Meyer         contentSize=1;
808706cfae4SConrad Meyer     double compressibility = 0.5;
809a19eddc3SBaptiste Daroussin     unsigned bench_nbSeconds = 3;   /* would be better if this value was synchronized from bench */
810a19eddc3SBaptiste Daroussin     size_t blockSize = 0;
8113f774a5eSConrad Meyer 
8123f774a5eSConrad Meyer     FIO_prefs_t* const prefs = FIO_createPreferences();
813f6ae9767SConrad Meyer     FIO_ctx_t* const fCtx = FIO_createContext();
814a19eddc3SBaptiste Daroussin     zstd_operation_mode operation = zom_compress;
815a19eddc3SBaptiste Daroussin     ZSTD_compressionParameters compressionParams;
816bc64b5ceSConrad Meyer     int cLevel = init_cLevel();
817bc64b5ceSConrad Meyer     int cLevelLast = MINCLEVEL - 1;  /* lower than minimum */
818a19eddc3SBaptiste Daroussin     unsigned recursive = 0;
819a19eddc3SBaptiste Daroussin     unsigned memLimit = 0;
820bc64b5ceSConrad Meyer     FileNamesTable* filenames = UTIL_allocateFileNamesTable((size_t)argCount);  /* argCount >= 1 */
821bc64b5ceSConrad Meyer     FileNamesTable* file_of_names = UTIL_allocateFileNamesTable((size_t)argCount);  /* argCount >= 1 */
822a19eddc3SBaptiste Daroussin     const char* programName = argv[0];
823a19eddc3SBaptiste Daroussin     const char* outFileName = NULL;
824ea684039SConrad Meyer     const char* outDirName = NULL;
825f6ae9767SConrad Meyer     const char* outMirroredDirName = NULL;
826a19eddc3SBaptiste Daroussin     const char* dictFileName = NULL;
827bc64b5ceSConrad Meyer     const char* patchFromDictFileName = NULL;
828a19eddc3SBaptiste Daroussin     const char* suffix = ZSTD_EXTENSION;
829a19eddc3SBaptiste Daroussin     unsigned maxDictSize = g_defaultMaxDictSize;
830a19eddc3SBaptiste Daroussin     unsigned dictID = 0;
831ea684039SConrad Meyer     size_t streamSrcSize = 0;
832fa94c738SConrad Meyer     size_t targetCBlockSize = 0;
833ea684039SConrad Meyer     size_t srcSizeHint = 0;
834a19eddc3SBaptiste Daroussin     int dictCLevel = g_defaultDictCLevel;
835a19eddc3SBaptiste Daroussin     unsigned dictSelect = g_defaultSelectivityLevel;
836a19eddc3SBaptiste Daroussin #ifndef ZSTD_NODICT
837affe9eafSBaptiste Daroussin     ZDICT_cover_params_t coverParams = defaultCoverParams();
838706cfae4SConrad Meyer     ZDICT_fastCover_params_t fastCoverParams = defaultFastCoverParams();
839706cfae4SConrad Meyer     dictType dict = fastCover;
840706cfae4SConrad Meyer #endif
841706cfae4SConrad Meyer #ifndef ZSTD_NOBENCH
842706cfae4SConrad Meyer     BMK_advancedParams_t benchParams = BMK_initAdvancedParams();
843a19eddc3SBaptiste Daroussin #endif
844b3392d84SAllan Jude     ZSTD_paramSwitch_e literalCompressionMode = ZSTD_ps_auto;
845a19eddc3SBaptiste Daroussin 
846653667f9SBaptiste Daroussin 
847a19eddc3SBaptiste Daroussin     /* init */
848b3392d84SAllan Jude     checkLibVersion();
849a19eddc3SBaptiste Daroussin     (void)recursive; (void)cLevelLast;    /* not used when ZSTD_NOBENCH set */
850bc64b5ceSConrad Meyer     (void)memLimit;
851bc64b5ceSConrad Meyer     assert(argCount >= 1);
852bc64b5ceSConrad Meyer     if ((filenames==NULL) || (file_of_names==NULL)) { DISPLAY("zstd: allocation error \n"); exit(1); }
853ffcbc2d7SBaptiste Daroussin     programName = lastNameFromPath(programName);
85442239e68SConrad Meyer #ifdef ZSTD_MULTITHREAD
855f6ae9767SConrad Meyer     nbWorkers = init_nbThreads();
85642239e68SConrad Meyer #endif
857a19eddc3SBaptiste Daroussin 
858a19eddc3SBaptiste Daroussin     /* preset behaviors */
859706cfae4SConrad Meyer     if (exeNameMatch(programName, ZSTD_ZSTDMT)) nbWorkers=0, singleThread=0;
860ffcbc2d7SBaptiste Daroussin     if (exeNameMatch(programName, ZSTD_UNZSTD)) operation=zom_decompress;
861fa94c738SConrad Meyer     if (exeNameMatch(programName, ZSTD_CAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; outFileName=stdoutmark; g_displayLevel=1; }     /* supports multiple formats */
862fa94c738SConrad Meyer     if (exeNameMatch(programName, ZSTD_ZCAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; outFileName=stdoutmark; g_displayLevel=1; }    /* behave like zcat, also supports multiple formats */
8633f774a5eSConrad Meyer     if (exeNameMatch(programName, ZSTD_GZ)) { suffix = GZ_EXTENSION; FIO_setCompressionType(prefs, FIO_gzipCompression); FIO_setRemoveSrcFile(prefs, 1); }        /* behave like gzip */
8643f774a5eSConrad Meyer     if (exeNameMatch(programName, ZSTD_GUNZIP)) { operation=zom_decompress; FIO_setRemoveSrcFile(prefs, 1); }                                                     /* behave like gunzip, also supports multiple formats */
865fa94c738SConrad Meyer     if (exeNameMatch(programName, ZSTD_GZCAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; outFileName=stdoutmark; g_displayLevel=1; }   /* behave like gzcat, also supports multiple formats */
8663f774a5eSConrad Meyer     if (exeNameMatch(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; FIO_setCompressionType(prefs, FIO_lzmaCompression); FIO_setRemoveSrcFile(prefs, 1); }    /* behave like lzma */
8673f774a5eSConrad Meyer     if (exeNameMatch(programName, ZSTD_UNLZMA)) { operation=zom_decompress; FIO_setCompressionType(prefs, FIO_lzmaCompression); FIO_setRemoveSrcFile(prefs, 1); } /* behave like unlzma, also supports multiple formats */
8683f774a5eSConrad Meyer     if (exeNameMatch(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; FIO_setCompressionType(prefs, FIO_xzCompression); FIO_setRemoveSrcFile(prefs, 1); }          /* behave like xz */
8693f774a5eSConrad Meyer     if (exeNameMatch(programName, ZSTD_UNXZ)) { operation=zom_decompress; FIO_setCompressionType(prefs, FIO_xzCompression); FIO_setRemoveSrcFile(prefs, 1); }     /* behave like unxz, also supports multiple formats */
8703f774a5eSConrad Meyer     if (exeNameMatch(programName, ZSTD_LZ4)) { suffix = LZ4_EXTENSION; FIO_setCompressionType(prefs, FIO_lz4Compression); }                                       /* behave like lz4 */
8713f774a5eSConrad Meyer     if (exeNameMatch(programName, ZSTD_UNLZ4)) { operation=zom_decompress; FIO_setCompressionType(prefs, FIO_lz4Compression); }                                   /* behave like unlz4, also supports multiple formats */
872a19eddc3SBaptiste Daroussin     memset(&compressionParams, 0, sizeof(compressionParams));
873a19eddc3SBaptiste Daroussin 
874706cfae4SConrad Meyer     /* init crash handler */
875706cfae4SConrad Meyer     FIO_addAbortHandler();
876706cfae4SConrad Meyer 
877a19eddc3SBaptiste Daroussin     /* command switches */
878a19eddc3SBaptiste Daroussin     for (argNb=1; argNb<argCount; argNb++) {
879a19eddc3SBaptiste Daroussin         const char* argument = argv[argNb];
880a19eddc3SBaptiste Daroussin         if (!argument) continue;   /* Protection if argument empty */
881a19eddc3SBaptiste Daroussin 
882bc64b5ceSConrad Meyer         if (nextArgumentsAreFiles) {
883bc64b5ceSConrad Meyer             UTIL_refFilename(filenames, argument);
884bc64b5ceSConrad Meyer             continue;
885bc64b5ceSConrad Meyer         }
886bc64b5ceSConrad Meyer 
887a19eddc3SBaptiste Daroussin         /* "-" means stdin/stdout */
888a19eddc3SBaptiste Daroussin         if (!strcmp(argument, "-")){
889bc64b5ceSConrad Meyer             UTIL_refFilename(filenames, stdinmark);
890a19eddc3SBaptiste Daroussin             continue;
891bc64b5ceSConrad Meyer         }
892a19eddc3SBaptiste Daroussin 
893a19eddc3SBaptiste Daroussin         /* Decode commands (note : aggregated commands are allowed) */
894a19eddc3SBaptiste Daroussin         if (argument[0]=='-') {
895a19eddc3SBaptiste Daroussin 
896a19eddc3SBaptiste Daroussin             if (argument[1]=='-') {
897a19eddc3SBaptiste Daroussin                 /* long commands (--long-word) */
898a19eddc3SBaptiste Daroussin                 if (!strcmp(argument, "--")) { nextArgumentsAreFiles=1; continue; }   /* only file names allowed from now on */
899affe9eafSBaptiste Daroussin                 if (!strcmp(argument, "--list")) { operation=zom_list; continue; }
900a19eddc3SBaptiste Daroussin                 if (!strcmp(argument, "--compress")) { operation=zom_compress; continue; }
901a19eddc3SBaptiste Daroussin                 if (!strcmp(argument, "--decompress")) { operation=zom_decompress; continue; }
902a19eddc3SBaptiste Daroussin                 if (!strcmp(argument, "--uncompress")) { operation=zom_decompress; continue; }
903b3392d84SAllan Jude                 if (!strcmp(argument, "--force")) { FIO_overwriteMode(prefs); forceStdin=1; forceStdout=1; followLinks=1; allowBlockDevices=1; continue; }
904bc64b5ceSConrad Meyer                 if (!strcmp(argument, "--version")) { printVersion(); CLEAN_RETURN(0); }
905bc64b5ceSConrad Meyer                 if (!strcmp(argument, "--help")) { usage_advanced(programName); CLEAN_RETURN(0); }
906ffcbc2d7SBaptiste Daroussin                 if (!strcmp(argument, "--verbose")) { g_displayLevel++; continue; }
907ffcbc2d7SBaptiste Daroussin                 if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; }
908ffcbc2d7SBaptiste Daroussin                 if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; g_displayLevel-=(g_displayLevel==2); continue; }
909a19eddc3SBaptiste Daroussin                 if (!strcmp(argument, "--ultra")) { ultra=1; continue; }
9103f774a5eSConrad Meyer                 if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(prefs, 2); continue; }
9113f774a5eSConrad Meyer                 if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(prefs, 0); continue; }
9123f774a5eSConrad Meyer                 if (!strcmp(argument, "--sparse")) { FIO_setSparseWrite(prefs, 2); continue; }
9133f774a5eSConrad Meyer                 if (!strcmp(argument, "--no-sparse")) { FIO_setSparseWrite(prefs, 0); continue; }
914a19eddc3SBaptiste Daroussin                 if (!strcmp(argument, "--test")) { operation=zom_test; continue; }
915706cfae4SConrad Meyer                 if (!strcmp(argument, "--train")) { operation=zom_train; if (outFileName==NULL) outFileName=g_defaultDictName; continue; }
9163f774a5eSConrad Meyer                 if (!strcmp(argument, "--no-dictID")) { FIO_setDictIDFlag(prefs, 0); continue; }
9173f774a5eSConrad Meyer                 if (!strcmp(argument, "--keep")) { FIO_setRemoveSrcFile(prefs, 0); continue; }
9183f774a5eSConrad Meyer                 if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(prefs, 1); continue; }
919a19eddc3SBaptiste Daroussin                 if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; }
920bc64b5ceSConrad Meyer                 if (!strcmp(argument, "--show-default-cparams")) { showDefaultCParams = 1; continue; }
921bc64b5ceSConrad Meyer                 if (!strcmp(argument, "--content-size")) { contentSize = 1; continue; }
922bc64b5ceSConrad Meyer                 if (!strcmp(argument, "--no-content-size")) { contentSize = 0; continue; }
923706cfae4SConrad Meyer                 if (!strcmp(argument, "--adapt")) { adapt = 1; continue; }
924b3392d84SAllan Jude                 if (!strcmp(argument, "--no-row-match-finder")) { useRowMatchFinder = 1; continue; }
925b3392d84SAllan Jude                 if (!strcmp(argument, "--row-match-finder")) { useRowMatchFinder = 2; continue; }
926bc64b5ceSConrad Meyer                 if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badusage(programName); CLEAN_RETURN(1); } continue; }
92742239e68SConrad Meyer                 if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; }
9283f774a5eSConrad Meyer                 if (!strcmp(argument, "--format=zstd")) { suffix = ZSTD_EXTENSION; FIO_setCompressionType(prefs, FIO_zstdCompression); continue; }
929a19eddc3SBaptiste Daroussin #ifdef ZSTD_GZCOMPRESS
9303f774a5eSConrad Meyer                 if (!strcmp(argument, "--format=gzip")) { suffix = GZ_EXTENSION; FIO_setCompressionType(prefs, FIO_gzipCompression); continue; }
931a19eddc3SBaptiste Daroussin #endif
932a19eddc3SBaptiste Daroussin #ifdef ZSTD_LZMACOMPRESS
9333f774a5eSConrad Meyer                 if (!strcmp(argument, "--format=lzma")) { suffix = LZMA_EXTENSION; FIO_setCompressionType(prefs, FIO_lzmaCompression);  continue; }
9343f774a5eSConrad Meyer                 if (!strcmp(argument, "--format=xz")) { suffix = XZ_EXTENSION; FIO_setCompressionType(prefs, FIO_xzCompression);  continue; }
935a19eddc3SBaptiste Daroussin #endif
936ffcbc2d7SBaptiste Daroussin #ifdef ZSTD_LZ4COMPRESS
9373f774a5eSConrad Meyer                 if (!strcmp(argument, "--format=lz4")) { suffix = LZ4_EXTENSION; FIO_setCompressionType(prefs, FIO_lz4Compression);  continue; }
938ffcbc2d7SBaptiste Daroussin #endif
939af73257bSConrad Meyer                 if (!strcmp(argument, "--rsyncable")) { rsyncable = 1; continue; }
940b3392d84SAllan Jude                 if (!strcmp(argument, "--compress-literals")) { literalCompressionMode = ZSTD_ps_enable; continue; }
941b3392d84SAllan Jude                 if (!strcmp(argument, "--no-compress-literals")) { literalCompressionMode = ZSTD_ps_disable; continue; }
942b3392d84SAllan Jude                 if (!strcmp(argument, "--no-progress")) { FIO_setProgressSetting(FIO_ps_never); continue; }
943b3392d84SAllan Jude                 if (!strcmp(argument, "--progress")) { FIO_setProgressSetting(FIO_ps_always); continue; }
944ea684039SConrad Meyer                 if (!strcmp(argument, "--exclude-compressed")) { FIO_setExcludeCompressedFile(prefs, 1); continue; }
945f6ae9767SConrad Meyer 
946a19eddc3SBaptiste Daroussin                 /* long commands with arguments */
947a19eddc3SBaptiste Daroussin #ifndef ZSTD_NODICT
948ffcbc2d7SBaptiste Daroussin                 if (longCommandWArg(&argument, "--train-cover")) {
949ffcbc2d7SBaptiste Daroussin                   operation = zom_train;
950706cfae4SConrad Meyer                   if (outFileName == NULL)
951ffcbc2d7SBaptiste Daroussin                       outFileName = g_defaultDictName;
952706cfae4SConrad Meyer                   dict = cover;
953a19eddc3SBaptiste Daroussin                   /* Allow optional arguments following an = */
954a19eddc3SBaptiste Daroussin                   if (*argument == 0) { memset(&coverParams, 0, sizeof(coverParams)); }
955bc64b5ceSConrad Meyer                   else if (*argument++ != '=') { badusage(programName); CLEAN_RETURN(1); }
956bc64b5ceSConrad Meyer                   else if (!parseCoverParameters(argument, &coverParams)) { badusage(programName); CLEAN_RETURN(1); }
957a19eddc3SBaptiste Daroussin                   continue;
958a19eddc3SBaptiste Daroussin                 }
959706cfae4SConrad Meyer                 if (longCommandWArg(&argument, "--train-fastcover")) {
960706cfae4SConrad Meyer                   operation = zom_train;
961706cfae4SConrad Meyer                   if (outFileName == NULL)
962706cfae4SConrad Meyer                       outFileName = g_defaultDictName;
963706cfae4SConrad Meyer                   dict = fastCover;
964706cfae4SConrad Meyer                   /* Allow optional arguments following an = */
965706cfae4SConrad Meyer                   if (*argument == 0) { memset(&fastCoverParams, 0, sizeof(fastCoverParams)); }
966bc64b5ceSConrad Meyer                   else if (*argument++ != '=') { badusage(programName); CLEAN_RETURN(1); }
967bc64b5ceSConrad Meyer                   else if (!parseFastCoverParameters(argument, &fastCoverParams)) { badusage(programName); CLEAN_RETURN(1); }
968706cfae4SConrad Meyer                   continue;
969706cfae4SConrad Meyer                 }
970ffcbc2d7SBaptiste Daroussin                 if (longCommandWArg(&argument, "--train-legacy")) {
971ffcbc2d7SBaptiste Daroussin                   operation = zom_train;
972706cfae4SConrad Meyer                   if (outFileName == NULL)
973ffcbc2d7SBaptiste Daroussin                       outFileName = g_defaultDictName;
974706cfae4SConrad Meyer                   dict = legacy;
975ffcbc2d7SBaptiste Daroussin                   /* Allow optional arguments following an = */
976ffcbc2d7SBaptiste Daroussin                   if (*argument == 0) { continue; }
977bc64b5ceSConrad Meyer                   else if (*argument++ != '=') { badusage(programName); CLEAN_RETURN(1); }
978bc64b5ceSConrad Meyer                   else if (!parseLegacyParameters(argument, &dictSelect)) { badusage(programName); CLEAN_RETURN(1); }
979ffcbc2d7SBaptiste Daroussin                   continue;
980ffcbc2d7SBaptiste Daroussin                 }
981a19eddc3SBaptiste Daroussin #endif
982f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--threads")) { NEXT_UINT32(nbWorkers); continue; }
983f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--memlimit")) { NEXT_UINT32(memLimit); continue; }
984f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--memory")) { NEXT_UINT32(memLimit); continue; }
985f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--memlimit-decompress")) { NEXT_UINT32(memLimit); continue; }
986bc64b5ceSConrad Meyer                 if (longCommandWArg(&argument, "--block-size=")) { blockSize = readSizeTFromChar(&argument); continue; }
987f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--maxdict")) { NEXT_UINT32(maxDictSize); continue; }
988f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--dictID")) { NEXT_UINT32(dictID); continue; }
989bc64b5ceSConrad Meyer                 if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) { badusage(programName); CLEAN_RETURN(1); } continue; }
990bc64b5ceSConrad Meyer                 if (longCommandWArg(&argument, "--stream-size=")) { streamSrcSize = readSizeTFromChar(&argument); continue; }
991bc64b5ceSConrad Meyer                 if (longCommandWArg(&argument, "--target-compressed-block-size=")) { targetCBlockSize = readSizeTFromChar(&argument); continue; }
992bc64b5ceSConrad Meyer                 if (longCommandWArg(&argument, "--size-hint=")) { srcSizeHint = readSizeTFromChar(&argument); continue; }
993f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--output-dir-flat")) { NEXT_FIELD(outDirName); continue; }
994b3392d84SAllan Jude #ifdef ZSTD_MULTITHREAD
995b3392d84SAllan Jude                 if (longCommandWArg(&argument, "--auto-threads")) {
996b3392d84SAllan Jude                     const char* threadDefault = NULL;
997b3392d84SAllan Jude                     NEXT_FIELD(threadDefault);
998b3392d84SAllan Jude                     if (strcmp(threadDefault, "logical") == 0)
999b3392d84SAllan Jude                         defaultLogicalCores = 1;
1000b3392d84SAllan Jude                     continue;
1001b3392d84SAllan Jude                 }
1002b3392d84SAllan Jude #endif
1003f6ae9767SConrad Meyer #ifdef UTIL_HAS_MIRRORFILELIST
1004f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--output-dir-mirror")) { NEXT_FIELD(outMirroredDirName); continue; }
1005f6ae9767SConrad Meyer #endif
1006b3392d84SAllan Jude #ifndef ZSTD_NOTRACE
1007b3392d84SAllan Jude                 if (longCommandWArg(&argument, "--trace")) { char const* traceFile; NEXT_FIELD(traceFile); TRACE_enable(traceFile); continue; }
1008b3392d84SAllan Jude #endif
1009f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--patch-from")) { NEXT_FIELD(patchFromDictFileName); continue; }
1010653667f9SBaptiste Daroussin                 if (longCommandWArg(&argument, "--long")) {
1011653667f9SBaptiste Daroussin                     unsigned ldmWindowLog = 0;
1012653667f9SBaptiste Daroussin                     ldmFlag = 1;
1013653667f9SBaptiste Daroussin                     /* Parse optional window log */
1014653667f9SBaptiste Daroussin                     if (*argument == '=') {
1015653667f9SBaptiste Daroussin                         ++argument;
1016653667f9SBaptiste Daroussin                         ldmWindowLog = readU32FromChar(&argument);
1017653667f9SBaptiste Daroussin                     } else if (*argument != 0) {
1018653667f9SBaptiste Daroussin                         /* Invalid character following --long */
1019bc64b5ceSConrad Meyer                         badusage(programName);
1020bc64b5ceSConrad Meyer                         CLEAN_RETURN(1);
1021653667f9SBaptiste Daroussin                     }
1022653667f9SBaptiste Daroussin                     /* Only set windowLog if not already set by --zstd */
1023653667f9SBaptiste Daroussin                     if (compressionParams.windowLog == 0)
1024653667f9SBaptiste Daroussin                         compressionParams.windowLog = ldmWindowLog;
1025653667f9SBaptiste Daroussin                     continue;
1026653667f9SBaptiste Daroussin                 }
1027706cfae4SConrad Meyer #ifndef ZSTD_NOCOMPRESS   /* linking ZSTD_minCLevel() requires compression support */
102842239e68SConrad Meyer                 if (longCommandWArg(&argument, "--fast")) {
1029706cfae4SConrad Meyer                     /* Parse optional acceleration factor */
103042239e68SConrad Meyer                     if (*argument == '=') {
1031706cfae4SConrad Meyer                         U32 const maxFast = (U32)-ZSTD_minCLevel();
103242239e68SConrad Meyer                         U32 fastLevel;
103342239e68SConrad Meyer                         ++argument;
103442239e68SConrad Meyer                         fastLevel = readU32FromChar(&argument);
1035706cfae4SConrad Meyer                         if (fastLevel > maxFast) fastLevel = maxFast;
1036706cfae4SConrad Meyer                         if (fastLevel) {
1037706cfae4SConrad Meyer                             dictCLevel = cLevel = -(int)fastLevel;
1038706cfae4SConrad Meyer                         } else {
1039bc64b5ceSConrad Meyer                             badusage(programName);
1040bc64b5ceSConrad Meyer                             CLEAN_RETURN(1);
1041706cfae4SConrad Meyer                         }
104242239e68SConrad Meyer                     } else if (*argument != 0) {
104342239e68SConrad Meyer                         /* Invalid character following --fast */
1044bc64b5ceSConrad Meyer                         badusage(programName);
1045bc64b5ceSConrad Meyer                         CLEAN_RETURN(1);
104642239e68SConrad Meyer                     } else {
104742239e68SConrad Meyer                         cLevel = -1;  /* default for --fast */
104842239e68SConrad Meyer                     }
104942239e68SConrad Meyer                     continue;
105042239e68SConrad Meyer                 }
1051706cfae4SConrad Meyer #endif
1052bc64b5ceSConrad Meyer 
1053f6ae9767SConrad Meyer                 if (longCommandWArg(&argument, "--filelist")) {
1054f6ae9767SConrad Meyer                     const char* listName;
1055f6ae9767SConrad Meyer                     NEXT_FIELD(listName);
1056f6ae9767SConrad Meyer                     UTIL_refFilename(file_of_names, listName);
1057bc64b5ceSConrad Meyer                     continue;
1058bc64b5ceSConrad Meyer                 }
1059bc64b5ceSConrad Meyer 
1060a19eddc3SBaptiste Daroussin                 /* fall-through, will trigger bad_usage() later on */
1061a19eddc3SBaptiste Daroussin             }
1062a19eddc3SBaptiste Daroussin 
1063a19eddc3SBaptiste Daroussin             argument++;
1064a19eddc3SBaptiste Daroussin             while (argument[0]!=0) {
1065f6ae9767SConrad Meyer 
1066a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOCOMPRESS
1067a19eddc3SBaptiste Daroussin                 /* compression Level */
1068a19eddc3SBaptiste Daroussin                 if ((*argument>='0') && (*argument<='9')) {
1069ea684039SConrad Meyer                     dictCLevel = cLevel = (int)readU32FromChar(&argument);
1070a19eddc3SBaptiste Daroussin                     continue;
1071a19eddc3SBaptiste Daroussin                 }
1072a19eddc3SBaptiste Daroussin #endif
1073a19eddc3SBaptiste Daroussin 
1074a19eddc3SBaptiste Daroussin                 switch(argument[0])
1075a19eddc3SBaptiste Daroussin                 {
1076a19eddc3SBaptiste Daroussin                     /* Display help */
1077bc64b5ceSConrad Meyer                 case 'V': printVersion(); CLEAN_RETURN(0);   /* Version Only */
1078a19eddc3SBaptiste Daroussin                 case 'H':
1079bc64b5ceSConrad Meyer                 case 'h': usage_advanced(programName); CLEAN_RETURN(0);
1080a19eddc3SBaptiste Daroussin 
1081a19eddc3SBaptiste Daroussin                      /* Compress */
1082a19eddc3SBaptiste Daroussin                 case 'z': operation=zom_compress; argument++; break;
1083a19eddc3SBaptiste Daroussin 
1084a19eddc3SBaptiste Daroussin                      /* Decoding */
1085a19eddc3SBaptiste Daroussin                 case 'd':
1086a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOBENCH
1087706cfae4SConrad Meyer                         benchParams.mode = BMK_decodeOnly;
108842239e68SConrad Meyer                         if (operation==zom_bench) { argument++; break; }  /* benchmark decode (hidden option) */
1089a19eddc3SBaptiste Daroussin #endif
1090a19eddc3SBaptiste Daroussin                         operation=zom_decompress; argument++; break;
1091a19eddc3SBaptiste Daroussin 
1092a19eddc3SBaptiste Daroussin                     /* Force stdout, even if stdout==console */
1093a19eddc3SBaptiste Daroussin                 case 'c': forceStdout=1; outFileName=stdoutmark; argument++; break;
1094a19eddc3SBaptiste Daroussin 
1095a19eddc3SBaptiste Daroussin                     /* Use file content as dictionary */
1096f6ae9767SConrad Meyer                 case 'D': argument++; NEXT_FIELD(dictFileName); break;
1097a19eddc3SBaptiste Daroussin 
1098a19eddc3SBaptiste Daroussin                     /* Overwrite */
1099b3392d84SAllan Jude                 case 'f': FIO_overwriteMode(prefs); forceStdin=1; forceStdout=1; followLinks=1; allowBlockDevices=1; argument++; break;
1100a19eddc3SBaptiste Daroussin 
1101a19eddc3SBaptiste Daroussin                     /* Verbose mode */
1102ffcbc2d7SBaptiste Daroussin                 case 'v': g_displayLevel++; argument++; break;
1103a19eddc3SBaptiste Daroussin 
1104a19eddc3SBaptiste Daroussin                     /* Quiet mode */
1105ffcbc2d7SBaptiste Daroussin                 case 'q': g_displayLevel--; argument++; break;
1106a19eddc3SBaptiste Daroussin 
1107ffcbc2d7SBaptiste Daroussin                     /* keep source file (default) */
11083f774a5eSConrad Meyer                 case 'k': FIO_setRemoveSrcFile(prefs, 0); argument++; break;
1109a19eddc3SBaptiste Daroussin 
1110a19eddc3SBaptiste Daroussin                     /* Checksum */
11113f774a5eSConrad Meyer                 case 'C': FIO_setChecksumFlag(prefs, 2); argument++; break;
1112a19eddc3SBaptiste Daroussin 
1113a19eddc3SBaptiste Daroussin                     /* test compressed file */
1114a19eddc3SBaptiste Daroussin                 case 't': operation=zom_test; argument++; break;
1115a19eddc3SBaptiste Daroussin 
1116a19eddc3SBaptiste Daroussin                     /* destination file name */
1117f6ae9767SConrad Meyer                 case 'o': argument++; NEXT_FIELD(outFileName); break;
1118a19eddc3SBaptiste Daroussin 
1119bc64b5ceSConrad Meyer                     /* limit memory */
1120a19eddc3SBaptiste Daroussin                 case 'M':
1121a19eddc3SBaptiste Daroussin                     argument++;
1122a19eddc3SBaptiste Daroussin                     memLimit = readU32FromChar(&argument);
1123a19eddc3SBaptiste Daroussin                     break;
1124affe9eafSBaptiste Daroussin                 case 'l': operation=zom_list; argument++; break;
1125a19eddc3SBaptiste Daroussin #ifdef UTIL_HAS_CREATEFILELIST
1126a19eddc3SBaptiste Daroussin                     /* recursive */
1127a19eddc3SBaptiste Daroussin                 case 'r': recursive=1; argument++; break;
1128a19eddc3SBaptiste Daroussin #endif
1129a19eddc3SBaptiste Daroussin 
1130a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOBENCH
1131a19eddc3SBaptiste Daroussin                     /* Benchmark */
1132a19eddc3SBaptiste Daroussin                 case 'b':
1133a19eddc3SBaptiste Daroussin                     operation=zom_bench;
1134a19eddc3SBaptiste Daroussin                     argument++;
1135a19eddc3SBaptiste Daroussin                     break;
1136a19eddc3SBaptiste Daroussin 
1137a19eddc3SBaptiste Daroussin                     /* range bench (benchmark only) */
1138a19eddc3SBaptiste Daroussin                 case 'e':
1139a19eddc3SBaptiste Daroussin                     /* compression Level */
1140a19eddc3SBaptiste Daroussin                     argument++;
1141ea684039SConrad Meyer                     cLevelLast = (int)readU32FromChar(&argument);
1142a19eddc3SBaptiste Daroussin                     break;
1143a19eddc3SBaptiste Daroussin 
1144a19eddc3SBaptiste Daroussin                     /* Modify Nb Iterations (benchmark only) */
1145a19eddc3SBaptiste Daroussin                 case 'i':
1146a19eddc3SBaptiste Daroussin                     argument++;
1147a19eddc3SBaptiste Daroussin                     bench_nbSeconds = readU32FromChar(&argument);
1148a19eddc3SBaptiste Daroussin                     break;
1149a19eddc3SBaptiste Daroussin 
1150a19eddc3SBaptiste Daroussin                     /* cut input into blocks (benchmark only) */
1151a19eddc3SBaptiste Daroussin                 case 'B':
1152a19eddc3SBaptiste Daroussin                     argument++;
1153a19eddc3SBaptiste Daroussin                     blockSize = readU32FromChar(&argument);
1154a19eddc3SBaptiste Daroussin                     break;
1155a19eddc3SBaptiste Daroussin 
11561767cc49SConrad Meyer                     /* benchmark files separately (hidden option) */
11571767cc49SConrad Meyer                 case 'S':
11581767cc49SConrad Meyer                     argument++;
11591767cc49SConrad Meyer                     separateFiles = 1;
11601767cc49SConrad Meyer                     break;
11611767cc49SConrad Meyer 
1162a19eddc3SBaptiste Daroussin #endif   /* ZSTD_NOBENCH */
1163a19eddc3SBaptiste Daroussin 
1164a19eddc3SBaptiste Daroussin                     /* nb of threads (hidden option) */
1165a19eddc3SBaptiste Daroussin                 case 'T':
1166a19eddc3SBaptiste Daroussin                     argument++;
1167ea684039SConrad Meyer                     nbWorkers = (int)readU32FromChar(&argument);
1168a19eddc3SBaptiste Daroussin                     break;
1169a19eddc3SBaptiste Daroussin 
1170a19eddc3SBaptiste Daroussin                     /* Dictionary Selection level */
1171a19eddc3SBaptiste Daroussin                 case 's':
1172a19eddc3SBaptiste Daroussin                     argument++;
1173a19eddc3SBaptiste Daroussin                     dictSelect = readU32FromChar(&argument);
1174a19eddc3SBaptiste Daroussin                     break;
1175a19eddc3SBaptiste Daroussin 
1176a19eddc3SBaptiste Daroussin                     /* Pause at the end (-p) or set an additional param (-p#) (hidden option) */
1177a19eddc3SBaptiste Daroussin                 case 'p': argument++;
1178a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOBENCH
1179a19eddc3SBaptiste Daroussin                     if ((*argument>='0') && (*argument<='9')) {
1180706cfae4SConrad Meyer                         benchParams.additionalParam = (int)readU32FromChar(&argument);
1181a19eddc3SBaptiste Daroussin                     } else
1182a19eddc3SBaptiste Daroussin #endif
1183a19eddc3SBaptiste Daroussin                         main_pause=1;
1184a19eddc3SBaptiste Daroussin                     break;
1185706cfae4SConrad Meyer 
1186706cfae4SConrad Meyer                     /* Select compressibility of synthetic sample */
1187706cfae4SConrad Meyer                 case 'P':
1188f6ae9767SConrad Meyer                     argument++;
1189706cfae4SConrad Meyer                     compressibility = (double)readU32FromChar(&argument) / 100;
1190706cfae4SConrad Meyer                     break;
1191706cfae4SConrad Meyer 
1192a19eddc3SBaptiste Daroussin                     /* unknown command */
1193bc64b5ceSConrad Meyer                 default : badusage(programName); CLEAN_RETURN(1);
1194a19eddc3SBaptiste Daroussin                 }
1195a19eddc3SBaptiste Daroussin             }
1196a19eddc3SBaptiste Daroussin             continue;
1197a19eddc3SBaptiste Daroussin         }   /* if (argument[0]=='-') */
1198a19eddc3SBaptiste Daroussin 
1199bc64b5ceSConrad Meyer         /* none of the above : add filename to list */
1200bc64b5ceSConrad Meyer         UTIL_refFilename(filenames, argument);
1201a19eddc3SBaptiste Daroussin     }
1202a19eddc3SBaptiste Daroussin 
1203a19eddc3SBaptiste Daroussin     /* Welcome message (if verbose) */
1204a19eddc3SBaptiste Daroussin     DISPLAYLEVEL(3, WELCOME_MESSAGE);
1205a19eddc3SBaptiste Daroussin 
120642239e68SConrad Meyer #ifdef ZSTD_MULTITHREAD
120742239e68SConrad Meyer     if ((nbWorkers==0) && (!singleThread)) {
120842239e68SConrad Meyer         /* automatically set # workers based on # of reported cpus */
1209b3392d84SAllan Jude         if (defaultLogicalCores) {
1210b3392d84SAllan Jude             nbWorkers = UTIL_countLogicalCores();
1211b3392d84SAllan Jude             DISPLAYLEVEL(3, "Note: %d logical core(s) detected \n", nbWorkers);
1212b3392d84SAllan Jude         } else {
121342239e68SConrad Meyer             nbWorkers = UTIL_countPhysicalCores();
121442239e68SConrad Meyer             DISPLAYLEVEL(3, "Note: %d physical core(s) detected \n", nbWorkers);
1215ffcbc2d7SBaptiste Daroussin         }
1216b3392d84SAllan Jude     }
1217706cfae4SConrad Meyer #else
1218706cfae4SConrad Meyer     (void)singleThread; (void)nbWorkers;
121942239e68SConrad Meyer #endif
1220ffcbc2d7SBaptiste Daroussin 
1221ffcbc2d7SBaptiste Daroussin     g_utilDisplayLevel = g_displayLevel;
1222b3392d84SAllan Jude 
1223b3392d84SAllan Jude #ifdef UTIL_HAS_CREATEFILELIST
1224ffcbc2d7SBaptiste Daroussin     if (!followLinks) {
1225bc64b5ceSConrad Meyer         unsigned u, fileNamesNb;
1226bc64b5ceSConrad Meyer         unsigned const nbFilenames = (unsigned)filenames->tableSize;
1227bc64b5ceSConrad Meyer         for (u=0, fileNamesNb=0; u<nbFilenames; u++) {
1228bc64b5ceSConrad Meyer             if ( UTIL_isLink(filenames->fileNames[u])
1229bc64b5ceSConrad Meyer              && !UTIL_isFIFO(filenames->fileNames[u])
1230ea684039SConrad Meyer             ) {
1231bc64b5ceSConrad Meyer                 DISPLAYLEVEL(2, "Warning : %s is a symbolic link, ignoring \n", filenames->fileNames[u]);
1232ffcbc2d7SBaptiste Daroussin             } else {
1233bc64b5ceSConrad Meyer                 filenames->fileNames[fileNamesNb++] = filenames->fileNames[u];
1234bc64b5ceSConrad Meyer         }   }
1235bc64b5ceSConrad Meyer         if (fileNamesNb == 0 && nbFilenames > 0)  /* all names are eliminated */
12363f774a5eSConrad Meyer             CLEAN_RETURN(1);
1237bc64b5ceSConrad Meyer         filenames->tableSize = fileNamesNb;
1238bc64b5ceSConrad Meyer     }   /* if (!followLinks) */
1239bc64b5ceSConrad Meyer 
1240bc64b5ceSConrad Meyer     /* read names from a file */
1241bc64b5ceSConrad Meyer     if (file_of_names->tableSize) {
1242bc64b5ceSConrad Meyer         size_t const nbFileLists = file_of_names->tableSize;
1243bc64b5ceSConrad Meyer         size_t flNb;
1244bc64b5ceSConrad Meyer         for (flNb=0; flNb < nbFileLists; flNb++) {
1245bc64b5ceSConrad Meyer             FileNamesTable* const fnt = UTIL_createFileNamesTable_fromFileName(file_of_names->fileNames[flNb]);
1246bc64b5ceSConrad Meyer             if (fnt==NULL) {
1247bc64b5ceSConrad Meyer                 DISPLAYLEVEL(1, "zstd: error reading %s \n", file_of_names->fileNames[flNb]);
1248bc64b5ceSConrad Meyer                 CLEAN_RETURN(1);
1249ffcbc2d7SBaptiste Daroussin             }
1250bc64b5ceSConrad Meyer             filenames = UTIL_mergeFileNamesTable(filenames, fnt);
1251bc64b5ceSConrad Meyer         }
1252bc64b5ceSConrad Meyer     }
1253bc64b5ceSConrad Meyer 
1254a19eddc3SBaptiste Daroussin     if (recursive) {  /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
1255bc64b5ceSConrad Meyer         UTIL_expandFNT(&filenames, followLinks);
1256a19eddc3SBaptiste Daroussin     }
1257706cfae4SConrad Meyer #else
1258706cfae4SConrad Meyer     (void)followLinks;
1259a19eddc3SBaptiste Daroussin #endif
1260902c8ce7SBaptiste Daroussin 
1261affe9eafSBaptiste Daroussin     if (operation == zom_list) {
1262902c8ce7SBaptiste Daroussin #ifndef ZSTD_NODECOMPRESS
1263bc64b5ceSConrad Meyer         int const ret = FIO_listMultipleFiles((unsigned)filenames->tableSize, filenames->fileNames, g_displayLevel);
1264affe9eafSBaptiste Daroussin         CLEAN_RETURN(ret);
1265902c8ce7SBaptiste Daroussin #else
1266902c8ce7SBaptiste Daroussin         DISPLAY("file information is not supported \n");
1267902c8ce7SBaptiste Daroussin         CLEAN_RETURN(1);
1268902c8ce7SBaptiste Daroussin #endif
1269affe9eafSBaptiste Daroussin     }
1270902c8ce7SBaptiste Daroussin 
1271a19eddc3SBaptiste Daroussin     /* Check if benchmark is selected */
1272a19eddc3SBaptiste Daroussin     if (operation==zom_bench) {
1273a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOBENCH
1274706cfae4SConrad Meyer         benchParams.blockSize = blockSize;
1275706cfae4SConrad Meyer         benchParams.nbWorkers = nbWorkers;
1276ea684039SConrad Meyer         benchParams.realTime = (unsigned)setRealTimePrio;
1277706cfae4SConrad Meyer         benchParams.nbSeconds = bench_nbSeconds;
1278706cfae4SConrad Meyer         benchParams.ldmFlag = ldmFlag;
1279ea684039SConrad Meyer         benchParams.ldmMinMatch = (int)g_ldmMinMatch;
1280ea684039SConrad Meyer         benchParams.ldmHashLog = (int)g_ldmHashLog;
1281b3392d84SAllan Jude         benchParams.useRowMatchFinder = useRowMatchFinder;
1282653667f9SBaptiste Daroussin         if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) {
1283ea684039SConrad Meyer             benchParams.ldmBucketSizeLog = (int)g_ldmBucketSizeLog;
1284653667f9SBaptiste Daroussin         }
1285af73257bSConrad Meyer         if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) {
1286ea684039SConrad Meyer             benchParams.ldmHashRateLog = (int)g_ldmHashRateLog;
1287653667f9SBaptiste Daroussin         }
12883f774a5eSConrad Meyer         benchParams.literalCompressionMode = literalCompressionMode;
1289706cfae4SConrad Meyer 
1290706cfae4SConrad Meyer         if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
1291706cfae4SConrad Meyer         if (cLevelLast > ZSTD_maxCLevel()) cLevelLast = ZSTD_maxCLevel();
1292706cfae4SConrad Meyer         if (cLevelLast < cLevel) cLevelLast = cLevel;
1293706cfae4SConrad Meyer         if (cLevelLast > cLevel)
1294706cfae4SConrad Meyer             DISPLAYLEVEL(3, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast);
1295bc64b5ceSConrad Meyer         if (filenames->tableSize > 0) {
1296706cfae4SConrad Meyer             if(separateFiles) {
1297706cfae4SConrad Meyer                 unsigned i;
1298bc64b5ceSConrad Meyer                 for(i = 0; i < filenames->tableSize; i++) {
1299706cfae4SConrad Meyer                     int c;
1300bc64b5ceSConrad Meyer                     DISPLAYLEVEL(3, "Benchmarking %s \n", filenames->fileNames[i]);
1301706cfae4SConrad Meyer                     for(c = cLevel; c <= cLevelLast; c++) {
1302bc64b5ceSConrad Meyer                         BMK_benchFilesAdvanced(&filenames->fileNames[i], 1, dictFileName, c, &compressionParams, g_displayLevel, &benchParams);
1303bc64b5ceSConrad Meyer                 }   }
1304706cfae4SConrad Meyer             } else {
1305706cfae4SConrad Meyer                 for(; cLevel <= cLevelLast; cLevel++) {
1306bc64b5ceSConrad Meyer                     BMK_benchFilesAdvanced(filenames->fileNames, (unsigned)filenames->tableSize, dictFileName, cLevel, &compressionParams, g_displayLevel, &benchParams);
1307bc64b5ceSConrad Meyer             }   }
1308706cfae4SConrad Meyer         } else {
1309706cfae4SConrad Meyer             for(; cLevel <= cLevelLast; cLevel++) {
1310706cfae4SConrad Meyer                 BMK_syntheticTest(cLevel, compressibility, &compressionParams, g_displayLevel, &benchParams);
1311bc64b5ceSConrad Meyer         }   }
1312706cfae4SConrad Meyer 
13131767cc49SConrad Meyer #else
1314706cfae4SConrad Meyer         (void)bench_nbSeconds; (void)blockSize; (void)setRealTimePrio; (void)separateFiles; (void)compressibility;
1315a19eddc3SBaptiste Daroussin #endif
1316a19eddc3SBaptiste Daroussin         goto _end;
1317a19eddc3SBaptiste Daroussin     }
1318a19eddc3SBaptiste Daroussin 
1319a19eddc3SBaptiste Daroussin     /* Check if dictionary builder is selected */
1320a19eddc3SBaptiste Daroussin     if (operation==zom_train) {
1321a19eddc3SBaptiste Daroussin #ifndef ZSTD_NODICT
1322affe9eafSBaptiste Daroussin         ZDICT_params_t zParams;
1323affe9eafSBaptiste Daroussin         zParams.compressionLevel = dictCLevel;
1324ea684039SConrad Meyer         zParams.notificationLevel = (unsigned)g_displayLevel;
1325affe9eafSBaptiste Daroussin         zParams.dictID = dictID;
1326706cfae4SConrad Meyer         if (dict == cover) {
1327ffcbc2d7SBaptiste Daroussin             int const optimize = !coverParams.k || !coverParams.d;
1328ea684039SConrad Meyer             coverParams.nbThreads = (unsigned)nbWorkers;
1329affe9eafSBaptiste Daroussin             coverParams.zParams = zParams;
1330b3392d84SAllan Jude             operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, blockSize, NULL, &coverParams, NULL, optimize, memLimit);
1331706cfae4SConrad Meyer         } else if (dict == fastCover) {
1332706cfae4SConrad Meyer             int const optimize = !fastCoverParams.k || !fastCoverParams.d;
1333ea684039SConrad Meyer             fastCoverParams.nbThreads = (unsigned)nbWorkers;
1334706cfae4SConrad Meyer             fastCoverParams.zParams = zParams;
1335b3392d84SAllan Jude             operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, blockSize, NULL, NULL, &fastCoverParams, optimize, memLimit);
1336a19eddc3SBaptiste Daroussin         } else {
1337affe9eafSBaptiste Daroussin             ZDICT_legacy_params_t dictParams;
1338a19eddc3SBaptiste Daroussin             memset(&dictParams, 0, sizeof(dictParams));
1339a19eddc3SBaptiste Daroussin             dictParams.selectivityLevel = dictSelect;
1340affe9eafSBaptiste Daroussin             dictParams.zParams = zParams;
1341b3392d84SAllan Jude             operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, blockSize, &dictParams, NULL, NULL, 0, memLimit);
1342a19eddc3SBaptiste Daroussin         }
1343706cfae4SConrad Meyer #else
1344706cfae4SConrad Meyer         (void)dictCLevel; (void)dictSelect; (void)dictID;  (void)maxDictSize; /* not used when ZSTD_NODICT set */
1345706cfae4SConrad Meyer         DISPLAYLEVEL(1, "training mode not available \n");
1346706cfae4SConrad Meyer         operationResult = 1;
1347a19eddc3SBaptiste Daroussin #endif
1348a19eddc3SBaptiste Daroussin         goto _end;
1349a19eddc3SBaptiste Daroussin     }
1350a19eddc3SBaptiste Daroussin 
1351902c8ce7SBaptiste Daroussin #ifndef ZSTD_NODECOMPRESS
1352ea684039SConrad Meyer     if (operation==zom_test) { FIO_setTestMode(prefs, 1); outFileName=nulmark; FIO_setRemoveSrcFile(prefs, 0); }  /* test mode */
1353902c8ce7SBaptiste Daroussin #endif
1354902c8ce7SBaptiste Daroussin 
1355a19eddc3SBaptiste Daroussin     /* No input filename ==> use stdin and stdout */
1356bc64b5ceSConrad Meyer     if (filenames->tableSize == 0) UTIL_refFilename(filenames, stdinmark);
1357bc64b5ceSConrad Meyer     if (!strcmp(filenames->fileNames[0], stdinmark) && !outFileName)
135842239e68SConrad Meyer         outFileName = stdoutmark;  /* when input is stdin, default output is stdout */
1359a19eddc3SBaptiste Daroussin 
1360a19eddc3SBaptiste Daroussin     /* Check if input/output defined as console; trigger an error in this case */
1361b3392d84SAllan Jude     if (!forceStdin
1362b3392d84SAllan Jude      && !strcmp(filenames->fileNames[0], stdinmark)
1363b3392d84SAllan Jude      && IS_CONSOLE(stdin) ) {
1364f6ae9767SConrad Meyer         DISPLAYLEVEL(1, "stdin is a console, aborting\n");
1365bc64b5ceSConrad Meyer         CLEAN_RETURN(1);
1366bc64b5ceSConrad Meyer     }
136742239e68SConrad Meyer     if ( outFileName && !strcmp(outFileName, stdoutmark)
136842239e68SConrad Meyer       && IS_CONSOLE(stdout)
1369bc64b5ceSConrad Meyer       && !strcmp(filenames->fileNames[0], stdinmark)
137042239e68SConrad Meyer       && !forceStdout
1371bc64b5ceSConrad Meyer       && operation!=zom_decompress ) {
1372f6ae9767SConrad Meyer         DISPLAYLEVEL(1, "stdout is a console, aborting\n");
1373bc64b5ceSConrad Meyer         CLEAN_RETURN(1);
1374bc64b5ceSConrad Meyer     }
1375a19eddc3SBaptiste Daroussin 
1376a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOCOMPRESS
1377a19eddc3SBaptiste Daroussin     /* check compression level limits */
1378a19eddc3SBaptiste Daroussin     {   int const maxCLevel = ultra ? ZSTD_maxCLevel() : ZSTDCLI_CLEVEL_MAX;
1379a19eddc3SBaptiste Daroussin         if (cLevel > maxCLevel) {
1380a19eddc3SBaptiste Daroussin             DISPLAYLEVEL(2, "Warning : compression level higher than max, reduced to %i \n", maxCLevel);
1381a19eddc3SBaptiste Daroussin             cLevel = maxCLevel;
1382a19eddc3SBaptiste Daroussin     }   }
1383a19eddc3SBaptiste Daroussin #endif
1384a19eddc3SBaptiste Daroussin 
1385bc64b5ceSConrad Meyer     if (showDefaultCParams) {
1386bc64b5ceSConrad Meyer         if (operation == zom_decompress) {
1387bc64b5ceSConrad Meyer             DISPLAY("error : can't use --show-default-cparams in decomrpession mode \n");
1388bc64b5ceSConrad Meyer             CLEAN_RETURN(1);
1389bc64b5ceSConrad Meyer         }
1390bc64b5ceSConrad Meyer     }
1391bc64b5ceSConrad Meyer 
1392bc64b5ceSConrad Meyer     if (dictFileName != NULL && patchFromDictFileName != NULL) {
1393bc64b5ceSConrad Meyer         DISPLAY("error : can't use -D and --patch-from=# at the same time \n");
1394bc64b5ceSConrad Meyer         CLEAN_RETURN(1);
1395bc64b5ceSConrad Meyer     }
1396bc64b5ceSConrad Meyer 
1397bc64b5ceSConrad Meyer     if (patchFromDictFileName != NULL && filenames->tableSize > 1) {
1398bc64b5ceSConrad Meyer         DISPLAY("error : can't use --patch-from=# on multiple files \n");
1399bc64b5ceSConrad Meyer         CLEAN_RETURN(1);
1400bc64b5ceSConrad Meyer     }
1401bc64b5ceSConrad Meyer 
1402f6ae9767SConrad Meyer     /* No status message in pipe mode (stdin - stdout) */
1403f6ae9767SConrad Meyer     hasStdout = outFileName && !strcmp(outFileName,stdoutmark);
1404f6ae9767SConrad Meyer 
1405b3392d84SAllan Jude     if ((hasStdout || !IS_CONSOLE(stderr)) && (g_displayLevel==2)) g_displayLevel=1;
1406a19eddc3SBaptiste Daroussin 
1407a19eddc3SBaptiste Daroussin     /* IO Stream/File */
1408f6ae9767SConrad Meyer     FIO_setHasStdoutOutput(fCtx, hasStdout);
1409f6ae9767SConrad Meyer     FIO_setNbFilesTotal(fCtx, (int)filenames->tableSize);
1410f6ae9767SConrad Meyer     FIO_determineHasStdinInput(fCtx, filenames);
1411ffcbc2d7SBaptiste Daroussin     FIO_setNotificationLevel(g_displayLevel);
1412b3392d84SAllan Jude     FIO_setAllowBlockDevices(prefs, allowBlockDevices);
1413bc64b5ceSConrad Meyer     FIO_setPatchFromMode(prefs, patchFromDictFileName != NULL);
1414bc64b5ceSConrad Meyer     if (memLimit == 0) {
1415bc64b5ceSConrad Meyer         if (compressionParams.windowLog == 0) {
1416bc64b5ceSConrad Meyer             memLimit = (U32)1 << g_defaultMaxWindowLog;
1417bc64b5ceSConrad Meyer         } else {
1418bc64b5ceSConrad Meyer             memLimit = (U32)1 << (compressionParams.windowLog & 31);
1419bc64b5ceSConrad Meyer     }   }
1420bc64b5ceSConrad Meyer     if (patchFromDictFileName != NULL)
1421bc64b5ceSConrad Meyer         dictFileName = patchFromDictFileName;
1422bc64b5ceSConrad Meyer     FIO_setMemLimit(prefs, memLimit);
1423a19eddc3SBaptiste Daroussin     if (operation==zom_compress) {
1424a19eddc3SBaptiste Daroussin #ifndef ZSTD_NOCOMPRESS
1425bc64b5ceSConrad Meyer         FIO_setContentSize(prefs, contentSize);
14263f774a5eSConrad Meyer         FIO_setNbWorkers(prefs, nbWorkers);
1427ea684039SConrad Meyer         FIO_setBlockSize(prefs, (int)blockSize);
1428ea684039SConrad Meyer         if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(prefs, (int)g_overlapLog);
1429ea684039SConrad Meyer         FIO_setLdmFlag(prefs, (unsigned)ldmFlag);
1430ea684039SConrad Meyer         FIO_setLdmHashLog(prefs, (int)g_ldmHashLog);
1431ea684039SConrad Meyer         FIO_setLdmMinMatch(prefs, (int)g_ldmMinMatch);
1432ea684039SConrad Meyer         if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) FIO_setLdmBucketSizeLog(prefs, (int)g_ldmBucketSizeLog);
1433ea684039SConrad Meyer         if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) FIO_setLdmHashRateLog(prefs, (int)g_ldmHashRateLog);
1434ea684039SConrad Meyer         FIO_setAdaptiveMode(prefs, (unsigned)adapt);
1435b3392d84SAllan Jude         FIO_setUseRowMatchFinder(prefs, useRowMatchFinder);
14363f774a5eSConrad Meyer         FIO_setAdaptMin(prefs, adaptMin);
14373f774a5eSConrad Meyer         FIO_setAdaptMax(prefs, adaptMax);
14383f774a5eSConrad Meyer         FIO_setRsyncable(prefs, rsyncable);
1439ea684039SConrad Meyer         FIO_setStreamSrcSize(prefs, streamSrcSize);
1440fa94c738SConrad Meyer         FIO_setTargetCBlockSize(prefs, targetCBlockSize);
1441ea684039SConrad Meyer         FIO_setSrcSizeHint(prefs, srcSizeHint);
14423f774a5eSConrad Meyer         FIO_setLiteralCompressionMode(prefs, literalCompressionMode);
1443706cfae4SConrad Meyer         if (adaptMin > cLevel) cLevel = adaptMin;
1444706cfae4SConrad Meyer         if (adaptMax < cLevel) cLevel = adaptMax;
1445653667f9SBaptiste Daroussin 
1446bc64b5ceSConrad Meyer         /* Compare strategies constant with the ground truth */
1447bc64b5ceSConrad Meyer         { ZSTD_bounds strategyBounds = ZSTD_cParam_getBounds(ZSTD_c_strategy);
1448bc64b5ceSConrad Meyer           assert(ZSTD_NB_STRATEGIES == strategyBounds.upperBound);
1449bc64b5ceSConrad Meyer           (void)strategyBounds; }
1450bc64b5ceSConrad Meyer 
1451b3392d84SAllan Jude         if (showDefaultCParams || g_displayLevel >= 4) {
1452bc64b5ceSConrad Meyer             size_t fileNb;
1453bc64b5ceSConrad Meyer             for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) {
1454b3392d84SAllan Jude                 if (showDefaultCParams)
1455b3392d84SAllan Jude                     printDefaultCParams(filenames->fileNames[fileNb], dictFileName, cLevel);
1456b3392d84SAllan Jude                 if (g_displayLevel >= 4)
1457b3392d84SAllan Jude                     printActualCParams(filenames->fileNames[fileNb], dictFileName, cLevel, &compressionParams);
1458bc64b5ceSConrad Meyer             }
1459bc64b5ceSConrad Meyer         }
1460bc64b5ceSConrad Meyer 
1461b3392d84SAllan Jude         if (g_displayLevel >= 4)
1462b3392d84SAllan Jude             FIO_displayCompressionParameters(prefs);
1463bc64b5ceSConrad Meyer         if ((filenames->tableSize==1) && outFileName)
1464f6ae9767SConrad Meyer             operationResult = FIO_compressFilename(fCtx, prefs, outFileName, filenames->fileNames[0], dictFileName, cLevel, compressionParams);
1465a19eddc3SBaptiste Daroussin         else
1466f6ae9767SConrad Meyer             operationResult = FIO_compressMultipleFilenames(fCtx, prefs, filenames->fileNames, outMirroredDirName, outDirName, outFileName, suffix, dictFileName, cLevel, compressionParams);
1467a19eddc3SBaptiste Daroussin #else
1468b3392d84SAllan Jude         (void)contentSize; (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; (void)ZSTD_strategyMap; (void)useRowMatchFinder; /* not used when ZSTD_NOCOMPRESS set */
1469a19eddc3SBaptiste Daroussin         DISPLAY("Compression not supported \n");
1470a19eddc3SBaptiste Daroussin #endif
1471a19eddc3SBaptiste Daroussin     } else {  /* decompression or test */
1472a19eddc3SBaptiste Daroussin #ifndef ZSTD_NODECOMPRESS
1473bc64b5ceSConrad Meyer         if (filenames->tableSize == 1 && outFileName) {
1474f6ae9767SConrad Meyer             operationResult = FIO_decompressFilename(fCtx, prefs, outFileName, filenames->fileNames[0], dictFileName);
1475bc64b5ceSConrad Meyer         } else {
1476f6ae9767SConrad Meyer             operationResult = FIO_decompressMultipleFilenames(fCtx, prefs, filenames->fileNames, outMirroredDirName, outDirName, outFileName, dictFileName);
1477653667f9SBaptiste Daroussin         }
1478a19eddc3SBaptiste Daroussin #else
1479a19eddc3SBaptiste Daroussin         DISPLAY("Decompression not supported \n");
1480a19eddc3SBaptiste Daroussin #endif
1481a19eddc3SBaptiste Daroussin     }
1482a19eddc3SBaptiste Daroussin 
1483a19eddc3SBaptiste Daroussin _end:
14843f774a5eSConrad Meyer     FIO_freePreferences(prefs);
1485f6ae9767SConrad Meyer     FIO_freeContext(fCtx);
1486a19eddc3SBaptiste Daroussin     if (main_pause) waitEnter();
1487bc64b5ceSConrad Meyer     UTIL_freeFileNamesTable(filenames);
1488bc64b5ceSConrad Meyer     UTIL_freeFileNamesTable(file_of_names);
1489b3392d84SAllan Jude #ifndef ZSTD_NOTRACE
1490b3392d84SAllan Jude     TRACE_finish();
1491b3392d84SAllan Jude #endif
1492bc64b5ceSConrad Meyer 
1493a19eddc3SBaptiste Daroussin     return operationResult;
1494a19eddc3SBaptiste Daroussin }
1495