Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

run all -e -E -L commands given, in order #23775

Merged
merged 3 commits into from
Sep 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

@iblislin iblislin Jan 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In C struct, this field named as cmds, it's inconsistent.
Is this intended?

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