Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : #include <limits.h>
4 : : #include <errno.h>
5 : :
6 : : #include "julia.h"
7 : : #include "julia_internal.h"
8 : :
9 : : #include <unistd.h>
10 : : #include <getopt.h>
11 : : #include "julia_assert.h"
12 : :
13 : : #ifdef _OS_WINDOWS_
14 : : char *shlib_ext = ".dll";
15 : : #elif defined(_OS_DARWIN_)
16 : : char *shlib_ext = ".dylib";
17 : : #else
18 : : char *shlib_ext = ".so";
19 : : #endif
20 : :
21 : : static const char system_image_path[256] = "\0" JL_SYSTEM_IMAGE_PATH;
22 : 602 : JL_DLLEXPORT const char *jl_get_default_sysimg_path(void)
23 : : {
24 : 602 : return &system_image_path[1];
25 : : }
26 : :
27 : : static int jl_options_initialized = 0;
28 : :
29 : 1204 : JL_DLLEXPORT void jl_init_options(void)
30 : : {
31 [ + + ]: 1204 : if (jl_options_initialized)
32 : 602 : return;
33 : 602 : jl_options =
34 : : (jl_options_t){ 0, // quiet
35 : : -1, // banner
36 : : NULL, // julia_bindir
37 : : NULL, // julia_bin
38 : : NULL, // cmds
39 : : NULL, // image_file (will be filled in below)
40 : : NULL, // cpu_target ("native", "core2", etc...)
41 : : 0, // nthreadpools
42 : : 0, // nthreads
43 : : NULL, // nthreads_per_pool
44 : : 0, // nprocs
45 : : NULL, // machine_file
46 : : NULL, // project
47 : : 0, // isinteractive
48 : : 0, // color
49 : : JL_OPTIONS_HISTORYFILE_ON, // history file
50 : : 0, // startup file
51 : : JL_OPTIONS_COMPILE_DEFAULT, // compile_enabled
52 : : 0, // code_coverage
53 : : 0, // malloc_log
54 : : NULL, // tracked_path
55 : : 2, // opt_level
56 : : 0, // opt_level_min
57 : : #ifdef JL_DEBUG_BUILD
58 : : 2, // debug_level [debug build]
59 : : #else
60 : : 1, // debug_level [release build]
61 : : #endif
62 : : JL_OPTIONS_CHECK_BOUNDS_DEFAULT, // check_bounds
63 : : JL_OPTIONS_DEPWARN_OFF, // deprecation warning
64 : : 0, // method overwrite warning
65 : : 1, // can_inline
66 : : JL_OPTIONS_POLLY_ON, // polly
67 : : NULL, // trace_compile
68 : : JL_OPTIONS_FAST_MATH_DEFAULT,
69 : : 0, // worker
70 : : NULL, // cookie
71 : : JL_OPTIONS_HANDLE_SIGNALS_ON,
72 : : JL_OPTIONS_USE_SYSIMAGE_NATIVE_CODE_YES,
73 : : JL_OPTIONS_USE_COMPILED_MODULES_YES,
74 : : NULL, // bind-to
75 : : NULL, // output-bc
76 : : NULL, // output-unopt-bc
77 : : NULL, // output-o
78 : : NULL, // output-asm
79 : : NULL, // output-ji
80 : : NULL, // output-code_coverage
81 : : 0, // incremental
82 : : 0, // image_file_specified
83 : : JL_OPTIONS_WARN_SCOPE_ON, // ambiguous scope warning
84 : : 0, // image-codegen
85 : : 0, // rr-detach
86 : : 0, // strip-metadata
87 : : 0, // strip-ir
88 : : 0, // heap-size-hint
89 : : };
90 : 602 : jl_options_initialized = 1;
91 : : }
92 : :
93 : : static const char usage[] = "\n julia [switches] -- [programfile] [args...]\n\n";
94 : : static const char opts[] =
95 : : "Switches (a '*' marks the default value, if applicable):\n\n"
96 : : " -v, --version Display version information\n"
97 : : " -h, --help Print this message (--help-hidden for more)\n"
98 : : " --help-hidden Uncommon options not shown by `-h`\n\n"
99 : :
100 : : // startup options
101 : : " --project[={<dir>|@.}] Set <dir> as the home project/environment\n"
102 : : " -J, --sysimage <file> Start up with the given system image file\n"
103 : : " -H, --home <dir> Set location of `julia` executable\n"
104 : : " --startup-file={yes*|no} Load `JULIA_DEPOT_PATH/config/startup.jl`; if `JULIA_DEPOT_PATH`\n"
105 : : " environment variable is unset, load `~/.julia/config/startup.jl`\n"
106 : : " --handle-signals={yes*|no} Enable or disable Julia's default signal handlers\n"
107 : : " --sysimage-native-code={yes*|no}\n"
108 : : " Use native code from system image if available\n"
109 : : " --compiled-modules={yes*|no}\n"
110 : : " Enable or disable incremental precompilation of modules\n\n"
111 : :
112 : : // actions
113 : : " -e, --eval <expr> Evaluate <expr>\n"
114 : : " -E, --print <expr> Evaluate <expr> and display the result\n"
115 : : " -L, --load <file> Load <file> immediately on all processors\n\n"
116 : :
117 : : // parallel options
118 : : " -t, --threads {auto|N[,auto|M]}\n"
119 : : " Enable N[+M] threads; N threads are assigned to the `default`\n"
120 : : " threadpool, and if M is specified, M threads are assigned to the\n"
121 : : " `interactive` threadpool; \"auto\" tries to infer a useful\n"
122 : : " default number of threads to use but the exact behavior might change\n"
123 : : " in the future. Currently sets N to the number of CPUs assigned to\n"
124 : : " this Julia process based on the OS-specific affinity assignment\n"
125 : : " interface if supported (Linux and Windows) or to the number of CPU\n"
126 : : " threads if not supported (MacOS) or if process affinity is not\n"
127 : : " configured, and sets M to 1.\n"
128 : : " -p, --procs {N|auto} Integer value N launches N additional local worker processes\n"
129 : : " \"auto\" launches as many workers as the number of local CPU threads (logical cores)\n"
130 : : " --machine-file <file> Run processes on hosts listed in <file>\n\n"
131 : :
132 : : // interactive options
133 : : " -i Interactive mode; REPL runs and `isinteractive()` is true\n"
134 : : " -q, --quiet Quiet startup: no banner, suppress REPL warnings\n"
135 : : " --banner={yes|no|auto*} Enable or disable startup banner\n"
136 : : " --color={yes|no|auto*} Enable or disable color text\n"
137 : : " --history-file={yes*|no} Load or save history\n\n"
138 : :
139 : : // error and warning options
140 : : " --depwarn={yes|no*|error} Enable or disable syntax and method deprecation warnings (`error` turns warnings into errors)\n"
141 : : " --warn-overwrite={yes|no*} Enable or disable method overwrite warnings\n"
142 : : " --warn-scope={yes*|no} Enable or disable warning for ambiguous top-level scope\n\n"
143 : :
144 : : // code generation options
145 : : " -C, --cpu-target <target> Limit usage of CPU features up to <target>; set to `help` to see the available options\n"
146 : : " -O, --optimize={0,1,2*,3} Set the optimization level (level 3 if `-O` is used without a level)\n"
147 : : " --min-optlevel={0*,1,2,3} Set a lower bound on the optimization level\n"
148 : : #ifdef JL_DEBUG_BUILD
149 : : " -g [{0,1,2*}] Set the level of debug info generation in the julia-debug build\n"
150 : : #else
151 : : " -g [{0,1*,2}] Set the level of debug info generation (level 2 if `-g` is used without a level)\n"
152 : : #endif
153 : : " --inline={yes*|no} Control whether inlining is permitted, including overriding @inline declarations\n"
154 : : " --check-bounds={yes|no|auto*}\n"
155 : : " Emit bounds checks always, never, or respect @inbounds declarations\n"
156 : : #ifdef USE_POLLY
157 : : " --polly={yes*|no} Enable or disable the polyhedral optimizer Polly (overrides @polly declaration)\n"
158 : : #endif
159 : :
160 : : // instrumentation options
161 : : " --code-coverage[={none*|user|all}]\n"
162 : : " Count executions of source lines (omitting setting is equivalent to `user`)\n"
163 : : " --code-coverage=@<path>\n"
164 : : " Count executions but only in files that fall under the given file path/directory.\n"
165 : : " The `@` prefix is required to select this option. A `@` with no path will track the\n"
166 : : " current directory.\n"
167 : :
168 : : " --code-coverage=tracefile.info\n"
169 : : " Append coverage information to the LCOV tracefile (filename supports format tokens)\n"
170 : : // TODO: These TOKENS are defined in `runtime_ccall.cpp`. A more verbose `--help` should include that list here.
171 : : " --track-allocation[={none*|user|all}]\n"
172 : : " Count bytes allocated by each source line (omitting setting is equivalent to `user`)\n"
173 : : " --track-allocation=@<path>\n"
174 : : " Count bytes but only in files that fall under the given file path/directory.\n"
175 : : " The `@` prefix is required to select this option. A `@` with no path will track the\n"
176 : : " current directory.\n"
177 : : " --bug-report=KIND Launch a bug report session. It can be used to start a REPL, run a script, or evaluate\n"
178 : : " expressions. It first tries to use BugReporting.jl installed in current environment and\n"
179 : : " fallbacks to the latest compatible BugReporting.jl if not. For more information, see\n"
180 : : " --bug-report=help.\n\n"
181 : :
182 : : " --heap-size-hint=<size> Forces garbage collection if memory usage is higher than that value.\n"
183 : : " The memory hint might be specified in megabytes(500M) or gigabytes(1G)\n\n"
184 : : ;
185 : :
186 : : static const char opts_hidden[] =
187 : : "Switches (a '*' marks the default value, if applicable):\n\n"
188 : : // code generation options
189 : : " --compile={yes*|no|all|min}\n"
190 : : " Enable or disable JIT compiler, or request exhaustive or minimal compilation\n\n"
191 : :
192 : : // compiler output options
193 : : " --output-o <name> Generate an object file (including system image data)\n"
194 : : " --output-ji <name> Generate a system image data file (.ji)\n"
195 : : " --strip-metadata Remove docstrings and source location info from system image\n"
196 : : " --strip-ir Remove IR (intermediate representation) of compiled functions\n\n"
197 : :
198 : : // compiler debugging (see the devdocs for tips on using these options)
199 : : " --output-unopt-bc <name> Generate unoptimized LLVM bitcode (.bc)\n"
200 : : " --output-bc <name> Generate LLVM bitcode (.bc)\n"
201 : : " --output-asm <name> Generate an assembly file (.s)\n"
202 : : " --output-incremental={yes|no*}\n"
203 : : " Generate an incremental output file (rather than complete)\n"
204 : : " --trace-compile={stderr,name}\n"
205 : : " Print precompile statements for methods compiled during execution or save to a path\n"
206 : : " --image-codegen Force generate code in imaging mode\n"
207 : : ;
208 : :
209 : 602 : JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp)
210 : : {
211 : : enum { opt_machinefile = 300,
212 : : opt_color,
213 : : opt_history_file,
214 : : opt_startup_file,
215 : : opt_compile,
216 : : opt_code_coverage,
217 : : opt_track_allocation,
218 : : opt_check_bounds,
219 : : opt_output_unopt_bc,
220 : : opt_output_bc,
221 : : opt_depwarn,
222 : : opt_warn_overwrite,
223 : : opt_warn_scope,
224 : : opt_inline,
225 : : opt_polly,
226 : : opt_trace_compile,
227 : : opt_math_mode,
228 : : opt_worker,
229 : : opt_bind_to,
230 : : opt_handle_signals,
231 : : opt_optlevel_min,
232 : : opt_output_o,
233 : : opt_output_asm,
234 : : opt_output_ji,
235 : : opt_use_precompiled,
236 : : opt_use_compilecache,
237 : : opt_incremental,
238 : : opt_help_hidden,
239 : : opt_banner,
240 : : opt_sysimage_native_code,
241 : : opt_compiled_modules,
242 : : opt_machine_file,
243 : : opt_project,
244 : : opt_bug_report,
245 : : opt_image_codegen,
246 : : opt_rr_detach,
247 : : opt_strip_metadata,
248 : : opt_strip_ir,
249 : : opt_heap_size_hint,
250 : : };
251 : : static const char* const shortopts = "+vhqH:e:E:L:J:C:it:p:O:g:";
252 : : static const struct option longopts[] = {
253 : : // exposed command line options
254 : : // NOTE: This set of required arguments need to be kept in sync
255 : : // with the required arguments defined in base/options.jl `struct JLOptions`
256 : : { "version", no_argument, 0, 'v' },
257 : : { "help", no_argument, 0, 'h' },
258 : : { "help-hidden", no_argument, 0, opt_help_hidden },
259 : : { "quiet", no_argument, 0, 'q' },
260 : : { "banner", required_argument, 0, opt_banner },
261 : : { "home", required_argument, 0, 'H' },
262 : : { "eval", required_argument, 0, 'e' },
263 : : { "print", required_argument, 0, 'E' },
264 : : { "load", required_argument, 0, 'L' },
265 : : { "bug-report", required_argument, 0, opt_bug_report },
266 : : { "sysimage", required_argument, 0, 'J' },
267 : : { "sysimage-native-code", required_argument, 0, opt_sysimage_native_code },
268 : : { "compiled-modules",required_argument, 0, opt_compiled_modules },
269 : : { "cpu-target", required_argument, 0, 'C' },
270 : : { "procs", required_argument, 0, 'p' },
271 : : { "threads", required_argument, 0, 't' },
272 : : { "machine-file", required_argument, 0, opt_machine_file },
273 : : { "project", optional_argument, 0, opt_project },
274 : : { "color", required_argument, 0, opt_color },
275 : : { "history-file", required_argument, 0, opt_history_file },
276 : : { "startup-file", required_argument, 0, opt_startup_file },
277 : : { "compile", required_argument, 0, opt_compile },
278 : : { "code-coverage", optional_argument, 0, opt_code_coverage },
279 : : { "track-allocation",optional_argument, 0, opt_track_allocation },
280 : : { "optimize", optional_argument, 0, 'O' },
281 : : { "min-optlevel", optional_argument, 0, opt_optlevel_min },
282 : : { "check-bounds", required_argument, 0, opt_check_bounds },
283 : : { "output-bc", required_argument, 0, opt_output_bc },
284 : : { "output-unopt-bc", required_argument, 0, opt_output_unopt_bc },
285 : : { "output-o", required_argument, 0, opt_output_o },
286 : : { "output-asm", required_argument, 0, opt_output_asm },
287 : : { "output-ji", required_argument, 0, opt_output_ji },
288 : : { "output-incremental",required_argument, 0, opt_incremental },
289 : : { "depwarn", required_argument, 0, opt_depwarn },
290 : : { "warn-overwrite", required_argument, 0, opt_warn_overwrite },
291 : : { "warn-scope", required_argument, 0, opt_warn_scope },
292 : : { "inline", required_argument, 0, opt_inline },
293 : : { "polly", required_argument, 0, opt_polly },
294 : : { "trace-compile", required_argument, 0, opt_trace_compile },
295 : : { "math-mode", required_argument, 0, opt_math_mode },
296 : : { "handle-signals", required_argument, 0, opt_handle_signals },
297 : : // hidden command line options
298 : : { "worker", optional_argument, 0, opt_worker },
299 : : { "bind-to", required_argument, 0, opt_bind_to },
300 : : { "lisp", no_argument, 0, 1 },
301 : : { "image-codegen", no_argument, 0, opt_image_codegen },
302 : : { "rr-detach", no_argument, 0, opt_rr_detach },
303 : : { "strip-metadata", no_argument, 0, opt_strip_metadata },
304 : : { "strip-ir", no_argument, 0, opt_strip_ir },
305 : : { "heap-size-hint", required_argument, 0, opt_heap_size_hint },
306 : : { 0, 0, 0, 0 }
307 : : };
308 : :
309 : : // If CPUID specific binaries are enabled, this varies between runs, so initialize
310 : : // it here, rather than as part of the static initialization above.
311 : 602 : jl_options.image_file = jl_get_default_sysimg_path();
312 : 602 : jl_options.cmds = NULL;
313 : :
314 : 602 : int ncmds = 0;
315 : 602 : const char **cmds = NULL;
316 : 602 : int codecov = JL_LOG_NONE;
317 : 602 : int malloclog = JL_LOG_NONE;
318 : 602 : int argc = *argcp;
319 : 602 : char **argv = *argvp;
320 : : char *endptr;
321 : 602 : opterr = 0; // suppress getopt warning messages
322 : 5828 : while (1) {
323 : 6430 : int lastind = optind;
324 : 6430 : int c = getopt_long(argc, argv, shortopts, longopts, 0);
325 [ + + ]: 6430 : if (c == -1) break;
326 : 5857 : restart_switch:
327 [ - + + + : 5859 : switch (c) {
+ - + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
- - + - +
+ + + - +
+ + + + +
- - + - -
- - ]
328 : 0 : case 0:
329 : 0 : break;
330 : 1 : case 1:
331 : 1 : jl_errorf("--lisp must be specified as the first argument");
332 : : break;
333 : 13 : case '?':
334 : : case ':':
335 [ + + ]: 13 : if (optopt) {
336 [ + + ]: 12 : if (optopt == 'g') {
337 : 1 : c = 'g';
338 : 1 : goto restart_switch;
339 : : }
340 [ + + ]: 225 : for (const struct option *o = longopts; o->val; o++) {
341 [ + + ]: 223 : if (optopt == o->val) {
342 [ + + ]: 9 : if (o->has_arg == optional_argument) {
343 : 1 : c = o->val;
344 : 1 : goto restart_switch;
345 : : }
346 [ + + + - ]: 8 : else if (o->val <= 0xff && strchr(shortopts, o->val)) {
347 : 7 : jl_errorf("option `-%c/--%s` is missing an argument", o->val, o->name);
348 : : }
349 : : else {
350 : 1 : jl_errorf("option `--%s` is missing an argument", o->name);
351 : : }
352 : : }
353 : : }
354 : 2 : jl_errorf("unknown option `-%c`", optopt);
355 : : }
356 : : else {
357 : 1 : jl_errorf("unknown option `%s`", argv[lastind]);
358 : : }
359 : : break;
360 : 3 : case 'v': // version
361 : 3 : jl_printf(JL_STDOUT, "julia version %s\n", JULIA_VERSION_STRING);
362 : 3 : exit(0);
363 : 2 : case 'h': // help
364 : 2 : jl_printf(JL_STDOUT, "%s%s", usage, opts);
365 : 2 : exit(0);
366 : 0 : case opt_help_hidden:
367 : 0 : jl_printf(JL_STDOUT, "%s%s", usage, opts_hidden);
368 : 0 : exit(0);
369 : 648 : case 'g': // debug info
370 [ + + ]: 648 : if (optarg != NULL) {
371 [ + + ]: 647 : if (!strcmp(optarg,"0"))
372 : 2 : jl_options.debug_level = 0;
373 [ + + ]: 645 : else if (!strcmp(optarg,"1"))
374 : 2 : jl_options.debug_level = 1;
375 [ + - ]: 643 : else if (!strcmp(optarg,"2"))
376 : 643 : jl_options.debug_level = 2;
377 : : else
378 : 0 : jl_errorf("julia: invalid argument to -g (%s)", optarg);
379 : 647 : break;
380 : : }
381 : : else {
382 : 1 : jl_options.debug_level = 2;
383 : : }
384 : 1 : break;
385 : 2 : case 'H': // home
386 : 2 : jl_options.julia_bindir = strdup(optarg);
387 [ - + ]: 2 : if (!jl_options.julia_bindir)
388 : 0 : jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno));
389 : 2 : break;
390 : 349 : case 'e': // eval
391 : : case 'E': // print
392 : : case 'L': // load
393 : : case opt_bug_report: // bug
394 : : {
395 : 349 : size_t sz = strlen(optarg) + 1;
396 : 349 : char *arg = (char*)malloc_s(sz + 1);
397 : : const char **newcmds;
398 [ + - ]: 349 : arg[0] = c == opt_bug_report ? 'B' : c;
399 : 349 : memcpy(arg + 1, optarg, sz);
400 : 349 : newcmds = (const char**)realloc_s(cmds, (ncmds + 2) * sizeof(char*));
401 : 349 : cmds = newcmds;
402 : 349 : cmds[ncmds] = arg;
403 : 349 : ncmds++;
404 : 349 : cmds[ncmds] = 0;
405 : 349 : jl_options.cmds = cmds;
406 : 349 : break;
407 : : }
408 : 648 : case 'J': // sysimage
409 : 648 : jl_options.image_file = strdup(optarg);
410 [ - + ]: 648 : if (!jl_options.image_file)
411 : 0 : jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno));
412 : 648 : jl_options.image_file_specified = 1;
413 : 648 : break;
414 : 9 : case 'q': // quiet
415 : 9 : jl_options.quiet = 1;
416 [ + + ]: 9 : if (jl_options.banner < 0)
417 : 7 : jl_options.banner = 0;
418 : 9 : break;
419 : 6 : case opt_banner: // banner
420 [ + + ]: 6 : if (!strcmp(optarg, "yes"))
421 : 3 : jl_options.banner = 1;
422 [ + - ]: 3 : else if (!strcmp(optarg, "no"))
423 : 3 : jl_options.banner = 0;
424 [ # # ]: 0 : else if (!strcmp(optarg, "auto"))
425 : 0 : jl_options.banner = -1;
426 : : else
427 : 0 : jl_errorf("julia: invalid argument to --banner={yes|no|auto} (%s)", optarg);
428 : 6 : break;
429 : 4 : case opt_sysimage_native_code:
430 [ + + ]: 4 : if (!strcmp(optarg,"yes"))
431 : 2 : jl_options.use_sysimage_native_code = JL_OPTIONS_USE_SYSIMAGE_NATIVE_CODE_YES;
432 [ + - ]: 2 : else if (!strcmp(optarg,"no"))
433 : 2 : jl_options.use_sysimage_native_code = JL_OPTIONS_USE_SYSIMAGE_NATIVE_CODE_NO;
434 : : else
435 : 0 : jl_errorf("julia: invalid argument to --sysimage-native-code={yes|no} (%s)", optarg);
436 : 4 : break;
437 : 14 : case opt_compiled_modules:
438 [ + + ]: 14 : if (!strcmp(optarg,"yes"))
439 : 10 : jl_options.use_compiled_modules = JL_OPTIONS_USE_COMPILED_MODULES_YES;
440 [ + + ]: 4 : else if (!strcmp(optarg,"no"))
441 : 3 : jl_options.use_compiled_modules = JL_OPTIONS_USE_COMPILED_MODULES_NO;
442 : : else
443 : 1 : jl_errorf("julia: invalid argument to --compiled-modules={yes|no} (%s)", optarg);
444 : 13 : break;
445 : 650 : case 'C': // cpu-target
446 : 650 : jl_options.cpu_target = strdup(optarg);
447 [ - + ]: 650 : if (!jl_options.cpu_target)
448 : 0 : jl_error("julia: failed to allocate memory");
449 : 650 : break;
450 : 15 : case 't': // threads
451 : 15 : errno = 0;
452 : 15 : jl_options.nthreadpools = 1;
453 : 15 : long nthreads = -1, nthreadsi = 0;
454 [ + + ]: 15 : if (!strncmp(optarg, "auto", 4)) {
455 : 3 : jl_options.nthreads = -1;
456 [ - + ]: 3 : if (optarg[4] == ',') {
457 [ # # ]: 0 : if (!strncmp(&optarg[5], "auto", 4))
458 : 0 : nthreadsi = 1;
459 : : else {
460 : 0 : errno = 0;
461 : 0 : nthreadsi = strtol(&optarg[5], &endptr, 10);
462 [ # # # # : 0 : if (errno != 0 || endptr == &optarg[5] || *endptr != 0 || nthreadsi < 1 || nthreadsi >= INT16_MAX)
# # # # #
# ]
463 : 0 : jl_errorf("julia: -t,--threads=auto,<m>; m must be an integer >= 1");
464 : : }
465 : 0 : jl_options.nthreadpools++;
466 : : }
467 : : }
468 : : else {
469 : 12 : nthreads = strtol(optarg, &endptr, 10);
470 [ + - + - : 12 : if (errno != 0 || optarg == endptr || nthreads < 1 || nthreads >= INT16_MAX)
+ + - + ]
471 : 2 : jl_errorf("julia: -t,--threads=<n>[,auto|<m>]; n must be an integer >= 1");
472 [ - + ]: 10 : if (*endptr == ',') {
473 [ # # ]: 0 : if (!strncmp(&endptr[1], "auto", 4))
474 : 0 : nthreadsi = 1;
475 : : else {
476 : 0 : errno = 0;
477 : : char *endptri;
478 : 0 : nthreadsi = strtol(&endptr[1], &endptri, 10);
479 [ # # # # : 0 : if (errno != 0 || endptri == &endptr[1] || *endptri != 0 || nthreadsi < 1 || nthreadsi >= INT16_MAX)
# # # # #
# ]
480 : 0 : jl_errorf("julia: -t,--threads=<n>,<m>; n and m must be integers >= 1");
481 : : }
482 : 0 : jl_options.nthreadpools++;
483 : : }
484 : 10 : jl_options.nthreads = nthreads + nthreadsi;
485 : : }
486 : 13 : int16_t *ntpp = (int16_t *)malloc_s(jl_options.nthreadpools * sizeof(int16_t));
487 : 13 : ntpp[0] = (int16_t)nthreads;
488 [ - + ]: 13 : if (jl_options.nthreadpools == 2)
489 : 0 : ntpp[1] = (int16_t)nthreadsi;
490 : 13 : jl_options.nthreads_per_pool = ntpp;
491 : 13 : break;
492 : 8 : case 'p': // procs
493 : 8 : errno = 0;
494 [ - + ]: 8 : if (!strcmp(optarg,"auto")) {
495 : 0 : jl_options.nprocs = jl_effective_threads();
496 : : }
497 : : else {
498 : 8 : long nprocs = strtol(optarg, &endptr, 10);
499 [ + - + - : 8 : if (errno != 0 || optarg == endptr || *endptr != 0 || nprocs < 1 || nprocs >= INT16_MAX)
+ + + + -
+ ]
500 : 2 : jl_errorf("julia: -p,--procs=<n> must be an integer >= 1");
501 : 6 : jl_options.nprocs = (int)nprocs;
502 : : }
503 : 6 : break;
504 : 1 : case opt_machine_file:
505 : 1 : jl_options.machine_file = strdup(optarg);
506 [ - + ]: 1 : if (!jl_options.machine_file)
507 : 0 : jl_error("julia: failed to allocate memory");
508 : 1 : break;
509 : 5 : case opt_project:
510 [ + - ]: 5 : jl_options.project = optarg ? strdup(optarg) : "@.";
511 : 5 : break;
512 : 305 : case opt_color:
513 [ + + ]: 305 : if (!strcmp(optarg, "yes"))
514 : 64 : jl_options.color = JL_OPTIONS_COLOR_ON;
515 [ + + ]: 241 : else if (!strcmp(optarg, "no"))
516 : 206 : jl_options.color = JL_OPTIONS_COLOR_OFF;
517 [ + + ]: 35 : else if (!strcmp(optarg, "auto"))
518 : 34 : jl_options.color = JL_OPTIONS_COLOR_AUTO;
519 : : else
520 : 1 : jl_errorf("julia: invalid argument to --color={yes|no|auto} (%s)", optarg);
521 : 304 : break;
522 : 89 : case opt_history_file:
523 [ + + ]: 89 : if (!strcmp(optarg,"yes"))
524 : 1 : jl_options.historyfile = JL_OPTIONS_HISTORYFILE_ON;
525 [ + + ]: 88 : else if (!strcmp(optarg,"no"))
526 : 87 : jl_options.historyfile = JL_OPTIONS_HISTORYFILE_OFF;
527 : : else
528 : 1 : jl_errorf("julia: invalid argument to --history-file={yes|no} (%s)", optarg);
529 : 88 : break;
530 : 1177 : case opt_startup_file:
531 [ + + ]: 1177 : if (!strcmp(optarg,"yes"))
532 : 7 : jl_options.startupfile = JL_OPTIONS_STARTUPFILE_ON;
533 [ + + ]: 1170 : else if (!strcmp(optarg,"no"))
534 : 1169 : jl_options.startupfile = JL_OPTIONS_STARTUPFILE_OFF;
535 : : else
536 : 1 : jl_errorf("julia: invalid argument to --startup-file={yes|no} (%s)", optarg);
537 : 1176 : break;
538 : 8 : case opt_compile:
539 [ + + ]: 8 : if (!strcmp(optarg,"yes"))
540 : 2 : jl_options.compile_enabled = JL_OPTIONS_COMPILE_ON;
541 [ - + ]: 6 : else if (!strcmp(optarg,"no"))
542 : 0 : jl_options.compile_enabled = JL_OPTIONS_COMPILE_OFF;
543 [ - + ]: 6 : else if (!strcmp(optarg,"all"))
544 : 0 : jl_options.compile_enabled = JL_OPTIONS_COMPILE_ALL;
545 [ + - ]: 6 : else if (!strcmp(optarg,"min"))
546 : 6 : jl_options.compile_enabled = JL_OPTIONS_COMPILE_MIN;
547 : : else
548 : 0 : jl_errorf("julia: invalid argument to --compile (%s)", optarg);
549 : 8 : break;
550 : 15 : case opt_code_coverage:
551 [ + + ]: 15 : if (optarg != NULL) {
552 : 14 : size_t endof = strlen(optarg);
553 [ + + ]: 14 : if (!strcmp(optarg, "user"))
554 : 1 : codecov = JL_LOG_USER;
555 [ + + ]: 13 : else if (!strcmp(optarg, "all"))
556 : 1 : codecov = JL_LOG_ALL;
557 [ + + ]: 12 : else if (!strcmp(optarg, "none"))
558 : 1 : codecov = JL_LOG_NONE;
559 [ + - + + ]: 11 : else if (endof > 5 && !strcmp(optarg + endof - 5, ".info")) {
560 [ + - ]: 8 : if (codecov == JL_LOG_NONE)
561 : 8 : codecov = JL_LOG_ALL;
562 : 8 : jl_options.output_code_coverage = optarg;
563 : : }
564 [ + - ]: 3 : else if (!strncmp(optarg, "@", 1)) {
565 : 3 : codecov = JL_LOG_PATH;
566 : 3 : jl_options.tracked_path = optarg + 1; // skip `@`
567 : : }
568 : : else
569 : 0 : jl_errorf("julia: invalid argument to --code-coverage (%s)", optarg);
570 : 14 : break;
571 : : }
572 : : else {
573 : 1 : codecov = JL_LOG_USER;
574 : : }
575 : 1 : break;
576 : 4 : case opt_track_allocation:
577 [ + + ]: 4 : if (optarg != NULL) {
578 [ + + ]: 3 : if (!strcmp(optarg,"user"))
579 : 2 : malloclog = JL_LOG_USER;
580 [ - + ]: 1 : else if (!strcmp(optarg,"all"))
581 : 0 : malloclog = JL_LOG_ALL;
582 [ + - ]: 1 : else if (!strcmp(optarg,"none"))
583 : 1 : malloclog = JL_LOG_NONE;
584 [ # # ]: 0 : else if (!strncmp(optarg, "@", 1)) {
585 : 0 : malloclog = JL_LOG_PATH;
586 : 0 : jl_options.tracked_path = optarg + 1; // skip `@`
587 : : }
588 : : else
589 : 0 : jl_errorf("julia: invalid argument to --track-allocation (%s)", optarg);
590 : 3 : break;
591 : : }
592 : : else {
593 : 1 : malloclog = JL_LOG_USER;
594 : : }
595 : 1 : break;
596 : 112 : case 'O': // optimize
597 [ + + ]: 112 : if (optarg != NULL) {
598 [ + - ]: 110 : if (!strcmp(optarg,"0"))
599 : 110 : jl_options.opt_level = 0;
600 [ # # ]: 0 : else if (!strcmp(optarg,"1"))
601 : 0 : jl_options.opt_level = 1;
602 [ # # ]: 0 : else if (!strcmp(optarg,"2"))
603 : 0 : jl_options.opt_level = 2;
604 [ # # ]: 0 : else if (!strcmp(optarg,"3"))
605 : 0 : jl_options.opt_level = 3;
606 : : else
607 : 0 : jl_errorf("julia: invalid argument to -O (%s)", optarg);
608 : 110 : break;
609 : : }
610 : : else {
611 : 2 : jl_options.opt_level = 3;
612 : : }
613 : 2 : break;
614 : 1 : case opt_optlevel_min: // minimum module optimize level
615 [ + - ]: 1 : if (optarg != NULL) {
616 [ - + ]: 1 : if (!strcmp(optarg,"0"))
617 : 0 : jl_options.opt_level_min = 0;
618 [ - + ]: 1 : else if (!strcmp(optarg,"1"))
619 : 0 : jl_options.opt_level_min = 1;
620 [ + - ]: 1 : else if (!strcmp(optarg,"2"))
621 : 1 : jl_options.opt_level_min = 2;
622 [ # # ]: 0 : else if (!strcmp(optarg,"3"))
623 : 0 : jl_options.opt_level_min = 3;
624 : : else
625 : 0 : jl_errorf("julia: invalid argument to --min-optlevel (%s)", optarg);
626 : 1 : break;
627 : : }
628 : : else {
629 : 0 : jl_options.opt_level_min = 0;
630 : : }
631 : 0 : break;
632 : 23 : case 'i': // isinteractive
633 : 23 : jl_options.isinteractive = 1;
634 : 23 : break;
635 : 645 : case opt_check_bounds:
636 [ + + ]: 645 : if (!strcmp(optarg,"yes"))
637 : 641 : jl_options.check_bounds = JL_OPTIONS_CHECK_BOUNDS_ON;
638 [ + + ]: 4 : else if (!strcmp(optarg,"no"))
639 : 2 : jl_options.check_bounds = JL_OPTIONS_CHECK_BOUNDS_OFF;
640 [ + + ]: 2 : else if (!strcmp(optarg,"auto"))
641 : 1 : jl_options.check_bounds = JL_OPTIONS_CHECK_BOUNDS_DEFAULT;
642 : : else
643 : 1 : jl_errorf("julia: invalid argument to --check-bounds={yes|no|auto} (%s)", optarg);
644 : 644 : break;
645 : 0 : case opt_output_bc:
646 : 0 : jl_options.outputbc = optarg;
647 [ # # ]: 0 : if (!jl_options.image_file_specified) jl_options.image_file = NULL;
648 : 0 : break;
649 : 0 : case opt_output_unopt_bc:
650 : 0 : jl_options.outputunoptbc = optarg;
651 [ # # ]: 0 : if (!jl_options.image_file_specified) jl_options.image_file = NULL;
652 : 0 : break;
653 : 1 : case opt_output_o:
654 : 1 : jl_options.outputo = optarg;
655 [ + - ]: 1 : if (!jl_options.image_file_specified) jl_options.image_file = NULL;
656 : 1 : break;
657 : 0 : case opt_output_asm:
658 : 0 : jl_options.outputasm = optarg;
659 [ # # ]: 0 : if (!jl_options.image_file_specified) jl_options.image_file = NULL;
660 : 0 : break;
661 : 88 : case opt_output_ji:
662 : 88 : jl_options.outputji = optarg;
663 [ + + ]: 88 : if (!jl_options.image_file_specified) jl_options.image_file = NULL;
664 : 88 : break;
665 : 86 : case opt_incremental:
666 [ + - ]: 86 : if (!strcmp(optarg,"yes"))
667 : 86 : jl_options.incremental = 1;
668 [ # # ]: 0 : else if (!strcmp(optarg,"no"))
669 : 0 : jl_options.incremental = 0;
670 : : else
671 : 0 : jl_errorf("julia: invalid argument to --output-incremental={yes|no} (%s)", optarg);
672 : 86 : break;
673 : 657 : case opt_depwarn:
674 [ + + ]: 657 : if (!strcmp(optarg,"yes"))
675 : 4 : jl_options.depwarn = JL_OPTIONS_DEPWARN_ON;
676 [ + + ]: 653 : else if (!strcmp(optarg,"no"))
677 : 4 : jl_options.depwarn = JL_OPTIONS_DEPWARN_OFF;
678 [ + + ]: 649 : else if (!strcmp(optarg,"error"))
679 : 648 : jl_options.depwarn = JL_OPTIONS_DEPWARN_ERROR;
680 : : else
681 : 1 : jl_errorf("julia: invalid argument to --depwarn={yes|no|error} (%s)", optarg);
682 : 656 : break;
683 : 91 : case opt_warn_overwrite:
684 [ + - ]: 91 : if (!strcmp(optarg,"yes"))
685 : 91 : jl_options.warn_overwrite = JL_OPTIONS_WARN_OVERWRITE_ON;
686 [ # # ]: 0 : else if (!strcmp(optarg,"no"))
687 : 0 : jl_options.warn_overwrite = JL_OPTIONS_WARN_OVERWRITE_OFF;
688 : : else
689 : 0 : jl_errorf("julia: invalid argument to --warn-overwrite={yes|no} (%s)", optarg);
690 : 91 : break;
691 : 0 : case opt_warn_scope:
692 [ # # ]: 0 : if (!strcmp(optarg,"yes"))
693 : 0 : jl_options.warn_scope = JL_OPTIONS_WARN_SCOPE_ON;
694 [ # # ]: 0 : else if (!strcmp(optarg,"no"))
695 : 0 : jl_options.warn_scope = JL_OPTIONS_WARN_SCOPE_OFF;
696 : : else
697 : 0 : jl_errorf("julia: invalid argument to --warn-scope={yes|no} (%s)", optarg);
698 : 0 : break;
699 : 7 : case opt_inline:
700 [ + + ]: 7 : if (!strcmp(optarg,"yes"))
701 : 2 : jl_options.can_inline = 1;
702 [ + + ]: 5 : else if (!strcmp(optarg,"no"))
703 : 4 : jl_options.can_inline = 0;
704 : : else {
705 : 1 : jl_errorf("julia: invalid argument to --inline (%s)", optarg);
706 : : }
707 : 6 : break;
708 : 3 : case opt_polly:
709 [ + + ]: 3 : if (!strcmp(optarg,"yes"))
710 : 1 : jl_options.polly = JL_OPTIONS_POLLY_ON;
711 [ + + ]: 2 : else if (!strcmp(optarg,"no"))
712 : 1 : jl_options.polly = JL_OPTIONS_POLLY_OFF;
713 : : else {
714 : 1 : jl_errorf("julia: invalid argument to --polly (%s)", optarg);
715 : : }
716 : 2 : break;
717 : 3 : case opt_trace_compile:
718 : 3 : jl_options.trace_compile = strdup(optarg);
719 [ - + ]: 3 : if (!jl_options.trace_compile)
720 : 0 : jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno));
721 : 3 : break;
722 : 3 : case opt_math_mode:
723 [ + + ]: 3 : if (!strcmp(optarg,"ieee"))
724 : 1 : jl_options.fast_math = JL_OPTIONS_FAST_MATH_OFF;
725 [ + + ]: 2 : else if (!strcmp(optarg,"fast"))
726 : 1 : jl_options.fast_math = JL_OPTIONS_FAST_MATH_DEFAULT;
727 [ + - ]: 1 : else if (!strcmp(optarg,"user"))
728 : 1 : jl_options.fast_math = JL_OPTIONS_FAST_MATH_DEFAULT;
729 : : else
730 : 0 : jl_errorf("julia: invalid argument to --math-mode (%s)", optarg);
731 : 3 : break;
732 : 79 : case opt_worker:
733 : 79 : jl_options.worker = 1;
734 [ + + ]: 79 : if (optarg != NULL) {
735 : 3 : jl_options.cookie = strdup(optarg);
736 [ - + ]: 3 : if (!jl_options.cookie)
737 : 0 : jl_error("julia: failed to allocate memory");
738 : : }
739 : 79 : break;
740 : 82 : case opt_bind_to:
741 : 82 : jl_options.bindto = strdup(optarg);
742 [ - + ]: 82 : if (!jl_options.bindto)
743 : 0 : jl_error("julia: failed to allocate memory");
744 : 82 : break;
745 : 0 : case opt_handle_signals:
746 [ # # ]: 0 : if (!strcmp(optarg,"yes"))
747 : 0 : jl_options.handle_signals = JL_OPTIONS_HANDLE_SIGNALS_ON;
748 [ # # ]: 0 : else if (!strcmp(optarg,"no"))
749 : 0 : jl_options.handle_signals = JL_OPTIONS_HANDLE_SIGNALS_OFF;
750 : : else
751 : 0 : jl_errorf("julia: invalid argument to --handle-signals (%s)", optarg);
752 : 0 : break;
753 : 0 : case opt_image_codegen:
754 : 0 : jl_options.image_codegen = 1;
755 : 0 : break;
756 : 2 : case opt_rr_detach:
757 : 2 : jl_options.rr_detach = 1;
758 : 2 : break;
759 : 0 : case opt_strip_metadata:
760 : 0 : jl_options.strip_metadata = 1;
761 : 0 : break;
762 : 0 : case opt_strip_ir:
763 : 0 : jl_options.strip_ir = 1;
764 : 0 : break;
765 : 0 : case opt_heap_size_hint:
766 [ # # ]: 0 : if (optarg != NULL) {
767 : 0 : size_t endof = strlen(optarg);
768 : 0 : long double value = 0.0;
769 [ # # # # ]: 0 : if (sscanf(optarg, "%Lf", &value) == 1 && value > 1e-7) {
770 : 0 : char unit = optarg[endof - 1];
771 : 0 : uint64_t multiplier = 1ull;
772 [ # # # # : 0 : switch (unit) {
# ]
773 : 0 : case 'k':
774 : : case 'K':
775 : 0 : multiplier <<= 10;
776 : 0 : break;
777 : 0 : case 'm':
778 : : case 'M':
779 : 0 : multiplier <<= 20;
780 : 0 : break;
781 : 0 : case 'g':
782 : : case 'G':
783 : 0 : multiplier <<= 30;
784 : 0 : break;
785 : 0 : case 't':
786 : : case 'T':
787 : 0 : multiplier <<= 40;
788 : 0 : break;
789 : 0 : default:
790 : 0 : break;
791 : : }
792 : 0 : jl_options.heap_size_hint = (uint64_t)(value * multiplier);
793 : :
794 : 0 : jl_gc_set_max_memory(jl_options.heap_size_hint);
795 : : }
796 : : }
797 [ # # ]: 0 : if (jl_options.heap_size_hint == 0)
798 : 0 : jl_errorf("julia: invalid argument to --heap-size-hint without memory size specified");
799 : :
800 : 0 : break;
801 : 0 : default:
802 : 0 : jl_errorf("julia: unhandled option -- %c\n"
803 : : "This is a bug, please report it.", c);
804 : : }
805 : : }
806 : 573 : jl_options.code_coverage = codecov;
807 : 573 : jl_options.malloc_log = malloclog;
808 : 573 : int proc_args = *argcp < optind ? *argcp : optind;
809 : 573 : *argvp += proc_args;
810 : 573 : *argcp -= proc_args;
811 : 573 : }
812 : :
813 : 2 : JL_DLLEXPORT ssize_t jl_sizeof_jl_options(void)
814 : : {
815 : 2 : return sizeof(jl_options_t);
816 : : }
|