Skip to content

Commit

Permalink
better cmdline option err handling (fixes #12679)
Browse files Browse the repository at this point in the history
Moves all the cmdline option error handling code from client.jl to
repl.c.

(cherry picked from commit dff1c90)
ref #13245
  • Loading branch information
nolta authored and tkelman committed Oct 31, 2015
1 parent 0b47230 commit 192e140
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 108 deletions.
165 changes: 66 additions & 99 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -212,110 +212,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()
Expand Down
5 changes: 5 additions & 0 deletions test/cmdlineargs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,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
30 changes: 21 additions & 9 deletions ui/repl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 192e140

Please sign in to comment.