Skip to content

Commit

Permalink
run all -e -E -L commands given, in order (#23775)
Browse files Browse the repository at this point in the history
fix #23665
  • Loading branch information
vtjnash authored and StefanKarpinski committed Sep 22, 2017
1 parent 221361b commit e009ac6
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 97 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ This section lists changes that do not have deprecation warnings.
simplified: if the arguments have different sizes (in bits), then the type of the larger
argument is used. If the arguments have the same size, the unsigned type is used ([#9292]).

* All command line arguments passed via `-e`, `-E`, and `-L` will be executed in the order
given on the command line ([#23665]).

Library improvements
--------------------

Expand Down
104 changes: 56 additions & 48 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -250,74 +250,82 @@ function process_options(opts::JLOptions)
idxs = find(x -> x == "--", ARGS)
length(idxs) > 0 && deleteat!(ARGS, idxs[1])
end
repl = true
quiet = (opts.quiet != 0)
startup = (opts.startupfile != 2)
history_file = (opts.historyfile != 0)
color_set = (opts.color != 0)
global have_color = (opts.color == 1)
global is_interactive = (opts.isinteractive != 0)

# pre-process command line argument list
arg_is_program = !isempty(ARGS)
repl = !arg_is_program
cmds = unsafe_load_commands(opts.commands)
for (cmd, arg) in cmds
if cmd == 'e'
arg_is_program = false
repl = false
elseif cmd == 'E'
arg_is_program = false
repl = false
elseif cmd == 'L'
# nothing
else
warn("unexpected command -$cmd'$arg'")
end
end

# remove filename from ARGS
arg_is_program = opts.eval == C_NULL && opts.print == C_NULL && !isempty(ARGS)
global PROGRAM_FILE = arg_is_program ? shift!(ARGS) : ""

while true
# startup worker.
# opts.startupfile, opts.load, etc should should not be processed for workers.
if opts.worker == 1
# does not return
if opts.cookie != C_NULL
start_worker(unsafe_string(opts.cookie))
else
start_worker()
end
# startup worker.
# opts.startupfile, opts.load, etc should should not be processed for workers.
if opts.worker == 1
# does not return
if opts.cookie != C_NULL
start_worker(unsafe_string(opts.cookie))
else
start_worker()
end
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(unsafe_string(opts.machinefile)))
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(unsafe_string(opts.machinefile)))
end

# load ~/.juliarc file
startup && load_juliarc()
# load ~/.juliarc file
startup && load_juliarc()

# load file immediately on all processors
if opts.load != C_NULL
# process cmds list
for (cmd, arg) in cmds
if cmd == 'e'
eval(Main, parse_input_line(arg))
elseif cmd == 'E'
invokelatest(show, eval(Main, parse_input_line(arg)))
println()
elseif cmd == 'L'
# load file immediately on all processors
@sync for p in procs()
@async remotecall_fetch(include, p, Main, unsafe_string(opts.load))
@async remotecall_wait(include, p, Main, arg)
end
end
# eval expression
if opts.eval != C_NULL
repl = false
eval(Main, parse_input_line(unsafe_string(opts.eval)))
break
end
# eval expression and show result
if opts.print != C_NULL
repl = false
show(eval(Main, parse_input_line(unsafe_string(opts.print))))
println()
break
end
# load file
if !isempty(PROGRAM_FILE)
# program
repl = false
if !is_interactive
ccall(:jl_exit_on_sigint, Void, (Cint,), 1)
end
include(Main, PROGRAM_FILE)
end

# load file
if arg_is_program
# program
if !is_interactive
ccall(:jl_exit_on_sigint, Void, (Cint,), 1)
end
break
include(Main, PROGRAM_FILE)
end
repl |= is_interactive
return (quiet,repl,startup,color_set,history_file)
return (quiet, repl, startup, color_set, history_file)
end

function load_juliarc()
Expand Down
20 changes: 17 additions & 3 deletions base/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ struct JLOptions
banner::Int8
julia_home::Ptr{UInt8}
julia_bin::Ptr{UInt8}
eval::Ptr{UInt8}
print::Ptr{UInt8}
load::Ptr{UInt8}
commands::Ptr{Ptr{UInt8}} # (e)eval, (E)print, (L)load
image_file::Ptr{UInt8}
cpu_target::Ptr{UInt8}
nprocs::Int32
Expand Down Expand Up @@ -58,8 +56,24 @@ function show(io::IO, opt::JLOptions)
v = getfield(opt, i)
if isa(v, Ptr{UInt8})
v = (v != C_NULL) ? unsafe_string(v) : ""
elseif isa(v, Ptr{Ptr{UInt8}})
v = unsafe_load_commands(v)
end
print(io, f, " = ", repr(v), i < nfields ? ", " : "")
end
print(io, ")")
end

function unsafe_load_commands(v::Ptr{Ptr{UInt8}})
cmds = Pair{Char, String}[]
v == C_NULL && return cmds
i = 1
while true
s = unsafe_load(v, i)
s == C_NULL && break
e = Char(unsafe_load(s))
push!(cmds, e => unsafe_string(s + 1))
i += 1
end
return cmds
end
2 changes: 2 additions & 0 deletions base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ function show(io::IO, ::MIME"text/plain", opt::JLOptions)
v = getfield(opt, i)
if isa(v, Ptr{UInt8})
v = (v != C_NULL) ? unsafe_string(v) : ""
elseif isa(v, Ptr{Ptr{UInt8}})
v = unsafe_load_commands(v)
end
println(io, " ", f, " = ", repr(v), i < nfields ? "," : "")
end
Expand Down
2 changes: 1 addition & 1 deletion doc/man/julia.1
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Evaluate <expr>

.TP
-E, --print <expr>
Evaluate and show <expr>
Evaluate <expr> and display the result

.TP
-L, --load <file>
Expand Down
2 changes: 1 addition & 1 deletion doc/src/manual/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ julia [switches] -- [programfile] [args...]
Enable or disable incremental precompilation of modules
-e, --eval <expr> Evaluate <expr>
-E, --print <expr> Evaluate and show <expr>
-E, --print <expr> Evaluate <expr> and display the result
-L, --load <file> Load <file> immediately on all processors
-p, --procs {N|auto} Integer value N launches N additional local worker processes
Expand Down
72 changes: 49 additions & 23 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,40 +434,58 @@ int isabspath(const char *in)
return 0; // relative path
}

static char *abspath(const char *in)
static char *abspath(const char *in, int nprefix)
{ // compute an absolute path location, so that chdir doesn't change the file reference
// ignores (copies directly over) nprefix characters at the start of abspath
#ifndef _OS_WINDOWS_
char *out = realpath(in, NULL);
if (!out) {
if (in[0] == PATHSEPSTRING[0]) {
out = strdup(in);
char *out = realpath(in + nprefix, NULL);
if (out) {
if (nprefix > 0) {
size_t sz = strlen(out) + 1;
char *cpy = (char*)malloc(sz + nprefix);
if (!cpy)
jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno));
memcpy(cpy, in, nprefix);
memcpy(cpy + nprefix, out, sz);
free(out);
out = cpy;
}
}
else {
size_t sz = strlen(in + nprefix) + 1;
if (in[nprefix] == PATHSEPSTRING[0]) {
out = (char*)malloc(sz + nprefix);
if (!out)
jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno));
memcpy(out, in, sz + nprefix);
}
else {
size_t path_size = PATH_MAX;
size_t len = strlen(in);
char *path = (char*)malloc(PATH_MAX);
if (!path)
jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno));
if (uv_cwd(path, &path_size)) {
jl_error("fatal error: unexpected error while retrieving current working directory");
}
if (path_size + len + 2 >= PATH_MAX) {
jl_error("fatal error: current working directory path too long");
}
path[path_size] = PATHSEPSTRING[0];
memcpy(path + path_size + 1, in, len+1);
out = strdup(path);
out = (char*)malloc(path_size + 1 + sz + nprefix);
memcpy(out, in, nprefix);
memcpy(out + nprefix, path, path_size);
out[nprefix + path_size] = PATHSEPSTRING[0];
memcpy(out + nprefix + path_size + 1, in + nprefix, sz);
free(path);
}
}
#else
DWORD n = GetFullPathName(in, 0, NULL, NULL);
DWORD n = GetFullPathName(in + nprefix, 0, NULL, NULL);
if (n <= 0) {
jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed");
}
char *out = (char*)malloc(n);
DWORD m = GetFullPathName(in, n, out, NULL);
char *out = (char*)malloc(n + nprefix);
DWORD m = GetFullPathName(in + nprefix, n, out + nprefix, NULL);
if (n != m + 1) {
jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed");
}
memcpy(out, in, nprefix);
#endif
return out;
}
Expand Down Expand Up @@ -498,7 +516,7 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel)
}
}
if (jl_options.julia_home)
jl_options.julia_home = abspath(jl_options.julia_home);
jl_options.julia_home = abspath(jl_options.julia_home, 0);
free(free_path);
free_path = NULL;
if (jl_options.image_file) {
Expand All @@ -513,22 +531,30 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel)
jl_options.image_file = free_path;
}
if (jl_options.image_file)
jl_options.image_file = abspath(jl_options.image_file);
jl_options.image_file = abspath(jl_options.image_file, 0);
if (free_path) {
free(free_path);
free_path = NULL;
}
}
if (jl_options.outputo)
jl_options.outputo = abspath(jl_options.outputo);
jl_options.outputo = abspath(jl_options.outputo, 0);
if (jl_options.outputji)
jl_options.outputji = abspath(jl_options.outputji);
jl_options.outputji = abspath(jl_options.outputji, 0);
if (jl_options.outputbc)
jl_options.outputbc = abspath(jl_options.outputbc);
jl_options.outputbc = abspath(jl_options.outputbc, 0);
if (jl_options.machinefile)
jl_options.machinefile = abspath(jl_options.machinefile);
if (jl_options.load)
jl_options.load = abspath(jl_options.load);
jl_options.machinefile = abspath(jl_options.machinefile, 0);

const char **cmdp = jl_options.cmds;
if (cmdp) {
for (; *cmdp; cmdp++) {
const char *cmd = *cmdp;
if (cmd[0] == 'L') {
*cmdp = abspath(cmd, 1);
}
}
}
}

static void jl_set_io_wait(int v)
Expand Down
Loading

0 comments on commit e009ac6

Please sign in to comment.