diff --git a/base/client.jl b/base/client.jl index 85890939fe113..8303bbdb6a204 100644 --- a/base/client.jl +++ b/base/client.jl @@ -207,110 +207,77 @@ function init_bind_addr() LPROC.bind_port = UInt16(bind_port) end -# NOTE: This set of required arguments need to be kept in sync with the required arguments defined in ui/repl.c -let reqarg = Set(UTF8String["--home", "-H", - "--eval", "-e", - "--print", "-E", - "--post-boot", "-P", - "--load", "-L", - "--sysimage", "-J", - "--cpu-target", "-C", - "--procs", "-p", - "--machinefile", - "--color", - "--history-file", - "--startup-file", - "--compile", - "--check-bounds", - "--depwarn", - "--inline", - "--output-o", - "--output-ji", - "--output-bc", - "--bind-to", - "--precompiled"]) - global process_options - function process_options(opts::JLOptions, args::Vector{UTF8String}) - if !isempty(args) - arg = first(args) - if !isempty(arg) && arg[1] == '-' && in(arg, reqarg) - println(STDERR, "julia: option `$arg` is missing an argument") - exit(1) - end - idxs = find(x -> x == "--", args) - if length(idxs) > 1 - println(STDERR, "julia: redundant option terminator `--`") - exit(1) - end - deleteat!(ARGS, idxs) +function process_options(opts::JLOptions, args::Vector{UTF8String}) + if !isempty(args) + arg = first(args) + idxs = find(x -> x == "--", args) + if length(idxs) > 1 + println(STDERR, "julia: redundant option terminator `--`") + exit(1) end - repl = true - startup = (opts.startupfile != 2) - history_file = (opts.historyfile != 0) - quiet = (opts.quiet != 0) - color_set = (opts.color != 0) - global have_color = (opts.color == 1) - global is_interactive = (opts.isinteractive != 0) - while true - # load ~/.juliarc file - startup && load_juliarc() - - # startup worker - if opts.worker != 0 - start_worker() # does not return - end - # add processors - if opts.nprocs > 0 - addprocs(opts.nprocs) - end - # load processes from machine file - if opts.machinefile != C_NULL - addprocs(load_machine_file(bytestring(opts.machinefile))) - end - # load file immediately on all processors - if opts.load != C_NULL - @sync for p in procs() - @async remotecall_fetch(p, include, bytestring(opts.load)) - end - end - # eval expression - if opts.eval != C_NULL - repl = false - eval(Main, parse_input_line(bytestring(opts.eval))) - break - end - # eval expression and show result - if opts.print != C_NULL - repl = false - show(eval(Main, parse_input_line(bytestring(opts.print)))) - println() - break - end - # eval expression but don't disable interactive mode - if opts.postboot != C_NULL - eval(Main, parse_input_line(bytestring(opts.postboot))) - end - # load file - if !isempty(args) - if !isempty(args[1]) && args[1][1] != '-' - # program - repl = false - # remove filename from ARGS - shift!(ARGS) - if !is_interactive - ccall(:jl_exit_on_sigint, Void, (Cint,), 1) - end - include(args[1]) - else - println(STDERR, "julia: unknown option `$(args[1])`") - exit(1) - end + deleteat!(ARGS, idxs) + end + repl = true + startup = (opts.startupfile != 2) + history_file = (opts.historyfile != 0) + quiet = (opts.quiet != 0) + color_set = (opts.color != 0) + global have_color = (opts.color == 1) + global is_interactive = (opts.isinteractive != 0) + while true + # load ~/.juliarc file + startup && load_juliarc() + + # startup worker + if opts.worker != 0 + start_worker() # does not return + end + # add processors + if opts.nprocs > 0 + addprocs(opts.nprocs) + end + # load processes from machine file + if opts.machinefile != C_NULL + addprocs(load_machine_file(bytestring(opts.machinefile))) + end + # load file immediately on all processors + if opts.load != C_NULL + @sync for p in procs() + @async remotecall_fetch(p, include, bytestring(opts.load)) end + end + # eval expression + if opts.eval != C_NULL + repl = false + eval(Main, parse_input_line(bytestring(opts.eval))) + break + end + # eval expression and show result + if opts.print != C_NULL + repl = false + show(eval(Main, parse_input_line(bytestring(opts.print)))) + println() break end - repl |= is_interactive - return (quiet,repl,startup,color_set,history_file) + # eval expression but don't disable interactive mode + if opts.postboot != C_NULL + eval(Main, parse_input_line(bytestring(opts.postboot))) + end + # load file + if !isempty(args) && !isempty(args[1]) + # program + repl = false + # remove filename from ARGS + shift!(ARGS) + if !is_interactive + ccall(:jl_exit_on_sigint, Void, (Cint,), 1) + end + include(args[1]) + end + break end + repl |= is_interactive + return (quiet,repl,startup,color_set,history_file) end const roottask = current_task() diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index ab1736524519c..664c25c4a0b88 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -193,4 +193,9 @@ let exename = `$(joinpath(JULIA_HOME, Base.julia_exename())) --precompiled=yes` # issue #10562 @test readchomp(`$exename -e 'println(ARGS);' ''`) == "UTF8String[\"\"]" + # issue #12679 + @test readchomp(pipeline(ignorestatus(`$exename -f --compile=yes -foo`),stderr=`cat`)) == "ERROR: unknown option `-o`" + @test readchomp(pipeline(ignorestatus(`$exename -f -p`),stderr=`cat`)) == "ERROR: option `-p/--procs` is missing an argument" + @test readchomp(pipeline(ignorestatus(`$exename -f --inline`),stderr=`cat`)) == "ERROR: option `--inline` is missing an argument" + @test readchomp(pipeline(ignorestatus(`$exename -f -e "@show ARGS" -now -- julia RUN.jl`),stderr=`cat`)) == "ERROR: unknown option `-n`" end diff --git a/ui/repl.c b/ui/repl.c index 1e59fe76044f7..ea9cab2f85440 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -160,27 +160,40 @@ void parse_opts(int *argcp, char ***argvp) { 0, 0, 0, 0 } }; // getopt handles argument parsing up to -- delineator - int lastind = optind; int argc = *argcp; + char **argv = *argvp; if (argc > 0) { for (int i=0; i < argc; i++) { - if (!strcmp((*argvp)[i], "--")) { + if (!strcmp(argv[i], "--")) { argc = i; break; } } } - int c; char *endptr; - opterr = 0; - int skip = 0; - while ((c = getopt_long(argc,*argvp,shortopts,longopts,0)) != -1) { + opterr = 0; // suppress getopt warning messages + while (1) { + int lastind = optind; + int c = getopt_long(argc, argv, shortopts, longopts, 0); + if (c == -1) break; switch (c) { case 0: break; case '?': - if (optind != lastind) skip++; - lastind = optind; + case ':': + if (optopt) { + for (struct option *o = longopts; o->val; o++) { + if (optopt == o->val) { + if (strchr(shortopts, o->val)) + jl_errorf("option `-%c/--%s` is missing an argument", o->val, o->name); + else + jl_errorf("option `--%s` is missing an argument", o->name); + } + } + jl_errorf("unknown option `-%c`", optopt); + } else { + jl_errorf("unknown option `%s`", argv[lastind]); + } break; case 'v': // version jl_printf(JL_STDOUT, "julia version %s\n", JULIA_VERSION_STRING); @@ -391,7 +404,6 @@ void parse_opts(int *argcp, char ***argvp) } jl_options.code_coverage = codecov; jl_options.malloc_log = malloclog; - optind -= skip; *argvp += optind; *argcp -= optind; }