aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded
diff options
context:
space:
mode:
Diffstat (limited to 'erts/preloaded')
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin56052 -> 51424 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin102012 -> 102012 bytes
-rw-r--r--erts/preloaded/ebin/erts_internal.beambin6260 -> 6260 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin48592 -> 44700 bytes
-rw-r--r--erts/preloaded/ebin/otp_ring0.beambin1452 -> 1452 bytes
-rw-r--r--erts/preloaded/ebin/prim_eval.beambin1324 -> 1324 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin44780 -> 44892 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin72612 -> 72612 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin23284 -> 23284 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin14160 -> 14160 bytes
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl321
-rw-r--r--erts/preloaded/src/init.erl397
-rw-r--r--erts/preloaded/src/prim_file.erl1
13 files changed, 270 insertions, 449 deletions
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index 8ccbd1e36b..6ee26b7575 100644
--- a/erts/preloaded/ebin/erl_prim_loader.beam
+++ b/erts/preloaded/ebin/erl_prim_loader.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index 87a48525bb..77f25653a3 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam
index 191dd332e2..4e1cb7f8a0 100644
--- a/erts/preloaded/ebin/erts_internal.beam
+++ b/erts/preloaded/ebin/erts_internal.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index a78d9abc20..a44b022931 100644
--- a/erts/preloaded/ebin/init.beam
+++ b/erts/preloaded/ebin/init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam
index 9cc91be343..328520844d 100644
--- a/erts/preloaded/ebin/otp_ring0.beam
+++ b/erts/preloaded/ebin/otp_ring0.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_eval.beam b/erts/preloaded/ebin/prim_eval.beam
index e84c8ffd2d..8d6c1927fd 100644
--- a/erts/preloaded/ebin/prim_eval.beam
+++ b/erts/preloaded/ebin/prim_eval.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index e1b2a1c8eb..1221c513db 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index 8853ae8bda..fa617f1f51 100644
--- a/erts/preloaded/ebin/prim_inet.beam
+++ b/erts/preloaded/ebin/prim_inet.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam
index 563e604a1d..83e1e49974 100644
--- a/erts/preloaded/ebin/prim_zip.beam
+++ b/erts/preloaded/ebin/prim_zip.beam
Binary files differ
diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam
index 304783ae37..8f654e3abf 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 9f6cba33bd..5f88029585 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -42,7 +42,7 @@
-include("inet_boot.hrl").
%% Public
--export([start/3, set_path/1, get_path/0, get_file/1, get_files/2,
+-export([start/0, set_path/1, get_path/0, get_file/1,
list_dir/1, read_file_info/1, read_link_info/1, get_cwd/0, get_cwd/1]).
%% Used by erl_boot_server
@@ -64,12 +64,10 @@
-record(state,
{loader :: 'efile' | 'inet',
hosts = [] :: [host()], % hosts list (to boot from)
- id, % not used any more?
data :: 'noport' | port(), % data port etc
- timeout :: timeout(), % idle timeout
+ timeout :: timeout(), % idle timeout
%% Number of timeouts before archives are released
n_timeouts :: non_neg_integer(),
- multi_get = false :: boolean(),
prim_state :: prim_state()}). % state for efile code loader
-define(IDLE_TIMEOUT, 60000). %% tear inet connection after 1 minutes
@@ -103,26 +101,13 @@ debug(#prim_state{debug = Deb}, Term) ->
%%% Interface Functions.
%%% --------------------------------------------------------
--spec start(Id, Loader, Hosts) ->
+-spec start() ->
{'ok', Pid} | {'error', What} when
- Id :: term(),
- Loader :: atom() | string(),
- Hosts :: Host | [Host],
- Host :: host(),
Pid :: pid(),
What :: term().
-start(Id, Pgm, Hosts) when is_atom(Hosts) ->
- start(Id, Pgm, [Hosts]);
-start(Id, Pgm0, Hosts) ->
- Pgm = if
- is_atom(Pgm0) ->
- atom_to_list(Pgm0);
- true ->
- Pgm0
- end,
+start() ->
Self = self(),
- Pid = spawn_link(fun() -> start_it(Pgm, Id, Self, Hosts) end),
- register(erl_prim_loader, Pid),
+ Pid = spawn_link(fun() -> start_it(Self) end),
receive
{Pid,ok} ->
{ok,Pid};
@@ -130,26 +115,40 @@ start(Id, Pgm0, Hosts) ->
{error,Reason}
end.
-%% Hosts must be a list of form ['1.2.3.4' ...]
-start_it("inet", Id, Pid, Hosts) ->
+start_it(Parent) ->
process_flag(trap_exit, true),
- ?dbg(inet, {Id,Pid,Hosts}),
+ register(erl_prim_loader, self()),
+ Loader = case init:get_argument(loader) of
+ {ok,[[Loader0]]} ->
+ Loader0;
+ error ->
+ "efile"
+ end,
+ case Loader of
+ "efile" -> start_efile(Parent);
+ "inet" -> start_inet(Parent)
+ end.
+
+%% Hosts must be a list of form ['1.2.3.4' ...]
+start_inet(Parent) ->
+ Hosts = case init:get_argument(hosts) of
+ {ok,[Hosts0]} -> Hosts0;
+ _ -> []
+ end,
AL = ipv4_list(Hosts),
?dbg(addresses, AL),
{ok,Tcp} = find_master(AL),
- init_ack(Pid),
+ init_ack(Parent),
PS = prim_init(),
State = #state {loader = inet,
hosts = AL,
- id = Id,
data = Tcp,
timeout = ?IDLE_TIMEOUT,
n_timeouts = ?N_TIMEOUTS,
prim_state = PS},
- loop(State, Pid, []);
+ loop(State, Parent, []).
-start_it("efile", Id, Pid, _Hosts) ->
- process_flag(trap_exit, true),
+start_efile(Parent) ->
{ok, Port} = prim_file:start(),
%% Check that we started in a valid directory.
case prim_file:get_cwd(Port) of
@@ -160,20 +159,14 @@ start_it("efile", Id, Pid, _Hosts) ->
erlang:display(Report),
exit({error, invalid_current_directory});
_ ->
- init_ack(Pid)
+ init_ack(Parent)
end,
- MultiGet = case erlang:system_info(thread_pool_size) of
- 0 -> false;
- _ -> true
- end,
PS = prim_init(),
State = #state {loader = efile,
- id = Id,
data = Port,
timeout = infinity,
- multi_get = MultiGet,
prim_state = PS},
- loop(State, Pid, []).
+ loop(State, Parent, []).
init_ack(Pid) ->
Pid ! {self(),ok},
@@ -198,20 +191,6 @@ get_file(File) when is_atom(File) ->
get_file(File) ->
check_file_result(get_file, File, request({get_file,File})).
--spec get_files([{atom(), string()}],
- fun((atom(),binary(),string()) -> 'ok' | {'error', atom()})) ->
- 'ok' | {'error', atom()}.
-get_files(ModFiles, Fun) ->
- case request({get_files,{ModFiles,Fun}}) of
- E = {error,_M} ->
- E;
- {error,Reason,M} ->
- check_file_result(get_files, M, {error,Reason}),
- {error,M};
- ok ->
- ok
- end.
-
-spec list_dir(Dir) -> {'ok', Filenames} | 'error' when
Dir :: string(),
Filenames :: [Filename :: string()].
@@ -310,76 +289,59 @@ check_file_result(_, _, Other) ->
%%% The main loop.
%%% --------------------------------------------------------
-loop(State, Parent, Paths) ->
+loop(St0, Parent, Paths) ->
receive
+ {Pid,{set_path,NewPaths}} when is_pid(Pid) ->
+ Pid ! {self(),ok},
+ loop(St0, Parent, to_strs(NewPaths));
{Pid,Req} when is_pid(Pid) ->
- %% erlang:display(Req),
- {Resp,State2,Paths2} =
- case Req of
- {set_path,NewPaths} ->
- {ok,State,to_strs(NewPaths)};
- {get_path,_} ->
- {{ok,Paths},State,Paths};
- {get_file,File} ->
- {Res,State1} = handle_get_file(State, Paths, File),
- {Res,State1,Paths};
- {get_files,{ModFiles,Fun}} ->
- {Res,State1} = handle_get_files(State, ModFiles, Paths, Fun),
- {Res,State1,Paths};
- {list_dir,Dir} ->
- {Res,State1} = handle_list_dir(State, Dir),
- {Res,State1,Paths};
- {read_file_info,File} ->
- {Res,State1} = handle_read_file_info(State, File),
- {Res,State1,Paths};
- {read_link_info,File} ->
- {Res,State1} = handle_read_link_info(State, File),
- {Res,State1,Paths};
- {get_cwd,[]} ->
- {Res,State1} = handle_get_cwd(State, []),
- {Res,State1,Paths};
- {get_cwd,[_]=Args} ->
- {Res,State1} = handle_get_cwd(State, Args),
- {Res,State1,Paths};
- {set_primary_archive,File,ArchiveBin,FileInfo,ParserFun} ->
- {Res,State1} =
- handle_set_primary_archive(State, File,
- ArchiveBin, FileInfo,
- ParserFun),
- {Res,State1,Paths};
- release_archives ->
- {Res,State1} = handle_release_archives(State),
- {Res,State1,Paths};
- _Other ->
- {ignore,State,Paths}
- end,
- if Resp =:= ignore -> ok;
- true -> Pid ! {self(),Resp}, ok
- end,
- if
- is_record(State2, state) ->
- loop(State2, Parent, Paths2);
- true ->
- exit({bad_state, Req, State2})
+ case handle_request(Req, Paths, St0) of
+ ignore ->
+ ok;
+ {Resp,#state{}=St1} ->
+ Pid ! {self(),Resp},
+ loop(St1, Parent, Paths);
+ {_,State2,_} ->
+ exit({bad_state,Req,State2})
end;
{'EXIT',Parent,W} ->
- _State1 = handle_stop(State),
+ _ = handle_stop(St0),
exit(W);
{'EXIT',P,W} ->
- State1 = handle_exit(State, P, W),
- loop(State1, Parent, Paths);
+ St1 = handle_exit(St0, P, W),
+ loop(St1, Parent, Paths);
_Message ->
- loop(State, Parent, Paths)
- after State#state.timeout ->
- State1 = handle_timeout(State, Parent),
- loop(State1, Parent, Paths)
+ loop(St0, Parent, Paths)
+ after St0#state.timeout ->
+ St1 = handle_timeout(St0, Parent),
+ loop(St1, Parent, Paths)
+ end.
+
+handle_request(Req, Paths, St0) ->
+ case Req of
+ {get_path,_} ->
+ {{ok,Paths},St0};
+ {get_file,File} ->
+ handle_get_file(St0, Paths, File);
+ {list_dir,Dir} ->
+ handle_list_dir(St0, Dir);
+ {read_file_info,File} ->
+ handle_read_file_info(St0, File);
+ {read_link_info,File} ->
+ handle_read_link_info(St0, File);
+ {get_cwd,[]} ->
+ handle_get_cwd(St0, []);
+ {get_cwd,[_]=Args} ->
+ handle_get_cwd(St0, Args);
+ {set_primary_archive,File,ArchiveBin,FileInfo,ParserFun} ->
+ handle_set_primary_archive(St0, File, ArchiveBin,
+ FileInfo, ParserFun);
+ release_archives ->
+ handle_release_archives(St0);
+ _ ->
+ ignore
end.
-handle_get_files(State = #state{multi_get = true}, ModFiles, Paths, Fun) ->
- ?SAFE2(efile_multi_get_file_from_port(State, ModFiles, Paths, Fun), State);
-handle_get_files(State, _ModFiles, _Paths, _Fun) -> % no multi get
- {{error,no_multi_get},State}.
-
handle_get_file(State = #state{loader = efile}, Paths, File) ->
?SAFE2(efile_get_file_from_port(State, File, Paths), State);
handle_get_file(State = #state{loader = inet}, Paths, File) ->
@@ -430,53 +392,6 @@ handle_timeout(State = #state{loader = inet}, Parent) ->
%%% Functions which handle efile as prim_loader (default).
%%% --------------------------------------------------------
-%%% Reading many files in parallel is an optimization.
-%%% See also comment in init.erl.
-
-%% -> {ok,State} | {{error,Module},State} | {{error,Reason,Module},State}
-efile_multi_get_file_from_port(State, ModFiles, Paths, Fun) ->
- Ref = make_ref(),
- %% More than 200 processes is no gain.
- Max = erlang:min(200, erlang:system_info(thread_pool_size)),
- efile_multi_get_file_from_port2(ModFiles, 0, Max, State, Paths, Fun, Ref, ok).
-
-efile_multi_get_file_from_port2([MF | MFs], Out, Max, State, Paths, Fun, Ref, Ret) when Out < Max ->
- Self = self(),
- _Pid = spawn(fun() -> efile_par_get_file(Ref, State, MF, Paths, Self, Fun) end),
- efile_multi_get_file_from_port2(MFs, Out+1, Max, State, Paths, Fun, Ref, Ret);
-efile_multi_get_file_from_port2(MFs, Out, Max, _State, Paths, Fun, Ref, Ret) when Out > 0 ->
- receive
- {Ref, ok, State1} ->
- efile_multi_get_file_from_port2(MFs, Out-1, Max, State1, Paths, Fun, Ref, Ret);
- {Ref, {error,_Mod} = Error, State1} ->
- efile_multi_get_file_from_port2(MFs, Out-1, Max, State1, Paths, Fun, Ref, Error);
- {Ref, MF, {error,emfile,State1}} ->
- %% Max can take negative values. Out cannot.
- efile_multi_get_file_from_port2([MF | MFs], Out-1, Max-1, State1, Paths, Fun, Ref, Ret);
- {Ref, {M,_F}, {error,Error,State1}} ->
- efile_multi_get_file_from_port2(MFs, Out-1, 0, State1, Paths, Fun, Ref, {error,Error,M})
- end;
-efile_multi_get_file_from_port2(_MFs, 0, _Max, State, _Paths, _Fun, _Ref, Ret) ->
- {Ret,State}.
-
-efile_par_get_file(Ref, State, {Mod,File} = MF, Paths, Pid, Fun) ->
- %% One port for each file read in "parallel":
- case prim_file:start() of
- {ok, Port} ->
- Port0 = State#state.data,
- State1 = State#state{data = Port},
- R = case efile_get_file_from_port(State1, File, Paths) of
- {{error,Reason},State2} ->
- {Ref,MF,{error,Reason,State2}};
- {{ok,BinFile,Full},State2} ->
- %% Fun(...) -> ok | {error,Mod}
- {Ref,Fun(Mod, BinFile, Full),State2#state{data=Port0}}
- end,
- prim_file:close(Port),
- Pid ! R;
- {error, Error} ->
- Pid ! {Ref,MF,{error,Error,State}}
- end.
%% -> {{ok,BinFile,File},State} | {{error,Reason},State}
efile_get_file_from_port(State, File, Paths) ->
@@ -1287,70 +1202,62 @@ path_join([Path],Acc) ->
path_join([Path|Paths],Acc) ->
path_join(Paths,"/" ++ reverse(Path) ++ Acc).
-name_split(ArchiveFile, File0) ->
- File = absname(File0),
- do_name_split(ArchiveFile, File).
-
-do_name_split(undefined, File) ->
+name_split(undefined, File) ->
%% Ignore primary archive
- case string_split(File, init:archive_extension(), []) of
+ RevExt = reverse(init:archive_extension()),
+ case archive_split(File, RevExt, []) of
no_split ->
- %% Plain file
{file, File};
- {split, _RevArchiveBase, RevArchiveFile, []} ->
- %% Top dir in archive
- ArchiveFile = reverse(RevArchiveFile),
- {archive, ArchiveFile, []};
- {split, _RevArchiveBase, RevArchiveFile, [$/ | FileInArchive]} ->
- %% File in archive
- ArchiveFile = reverse(RevArchiveFile),
- {archive, ArchiveFile, FileInArchive};
- {split, _RevArchiveBase, _RevArchiveFile, _FileInArchive} ->
- %% False match. Assume plain file
- {file, File}
+ Archive ->
+ Archive
end;
-do_name_split(ArchiveFile, File) ->
+name_split(ArchiveFile, File0) ->
%% Look first in primary archive
- case string_match(real_path(File), ArchiveFile, []) of
+ File = absname(File0),
+ case string_match(real_path(File), ArchiveFile) of
no_match ->
%% Archive or plain file
- do_name_split(undefined, File);
- {match, _RevPrimArchiveFile, FileInArchive} ->
+ name_split(undefined, File);
+ {match, FileInArchive} ->
%% Primary archive
{archive, ArchiveFile, FileInArchive}
end.
-string_match([Char | File], [Char | Archive], RevTop) ->
- string_match(File, Archive, [Char | RevTop]);
-string_match([] = File, [], RevTop) ->
- {match, RevTop, File};
-string_match([$/ | File], [], RevTop) ->
- {match, RevTop, File};
-string_match(_File, _Archive, _RevTop) ->
+string_match([Char | File], [Char | Archive]) ->
+ string_match(File, Archive);
+string_match([] = File, []) ->
+ {match, File};
+string_match([$/ | File], []) ->
+ {match, File};
+string_match(_File, _Archive) ->
no_match.
-string_split([Char | File], [Char | Ext] = FullExt, RevTop) ->
- RevTop2 = [Char | RevTop],
- string_split2(File, Ext, RevTop, RevTop2, File, FullExt, RevTop2);
-string_split([Char | File], Ext, RevTop) ->
- string_split(File, Ext, [Char | RevTop]);
-string_split([], _Ext, _RevTop) ->
- no_split.
-
-string_split2([Char | File], [Char | Ext], RevBase, RevTop, SaveFile, SaveExt, SaveTop) ->
- string_split2(File, Ext, RevBase, [Char | RevTop], SaveFile, SaveExt, SaveTop);
-string_split2(File, [], RevBase, RevTop, _SaveFile, _SaveExt, _SaveTop) ->
- {split, RevBase, RevTop, File};
-string_split2(_, _Ext, _RevBase, _RevTop, SaveFile, SaveExt, SaveTop) ->
- string_split(SaveFile, SaveExt, SaveTop).
+archive_split("/"++File, RevExt, Acc) ->
+ case is_prefix(RevExt, Acc) of
+ false ->
+ archive_split(File, RevExt, [$/|Acc]);
+ true ->
+ ArchiveFile = absname(reverse(Acc)),
+ {archive, ArchiveFile, File}
+ end;
+archive_split([H|T], RevExt, Acc) ->
+ archive_split(T, RevExt, [H|Acc]);
+archive_split([], RevExt, Acc) ->
+ case is_prefix(RevExt, Acc) of
+ false ->
+ no_split;
+ true ->
+ ArchiveFile = absname(reverse(Acc)),
+ {archive, ArchiveFile, []}
+ end.
+
+is_prefix([H|T1], [H|T2]) -> is_prefix(T1, T2);
+is_prefix([_|_], _) -> false;
+is_prefix([], _ ) -> true.
%% Parse list of ipv4 addresses
ipv4_list([H | T]) ->
- IPV = if is_atom(H) -> ipv4_address(atom_to_list(H));
- is_list(H) -> ipv4_address(H);
- true -> {error,einal}
- end,
- case IPV of
+ case ipv4_address(H) of
{ok,IP} -> [IP | ipv4_list(T)];
_ -> ipv4_list(T)
end;
@@ -1415,8 +1322,6 @@ absname_vr([Drive, $\: | NameRest], _) ->
%% Assumes normalized name
pathtype(Name) when is_list(Name) ->
case erlang:system_info(os_type) of
- {ose, _} ->
- unix_pathtype(Name);
{unix, _} ->
unix_pathtype(Name);
{win32, _} ->
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index 0ad5824ad1..383c4a1ec6 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -23,7 +23,6 @@
%% a local file or distributed from another erlang node.
%%
%% Flags:
-%% -id Identity : identity of the system.
%% -boot File : Absolute file name of the boot script.
%% -boot_var Var Value
%% : $Var in the boot script is expanded to
@@ -75,6 +74,19 @@
subscribed = []}).
-type state() :: #state{}.
+%% Data for eval_script/2.
+-record(es,
+ {init,
+ debug,
+ path,
+ pa,
+ pz,
+ path_choice,
+ prim_load,
+ load_mode,
+ vars
+ }).
+
-define(ON_LOAD_HANDLER, init__boot__on_load_handler).
debug(false, _) -> ok;
@@ -169,8 +181,7 @@ boot(BootArgs) ->
process_flag(trap_exit, true),
{Start0,Flags,Args} = parse_boot_args(BootArgs),
Start = map(fun prepare_run_args/1, Start0),
- Flags0 = flags_to_atoms_again(Flags),
- boot(Start,Flags0,Args).
+ boot(Start, Flags, Args).
prepare_run_args({eval, [Expr]}) ->
{eval,Expr};
@@ -202,16 +213,6 @@ map(_F, []) ->
map(F, [X|Rest]) ->
[F(X) | map(F, Rest)].
-flags_to_atoms_again([]) ->
- [];
-flags_to_atoms_again([{F0,L0}|Rest]) ->
- L = L0,
- F = b2a(F0),
- [{F,L}|flags_to_atoms_again(Rest)];
-flags_to_atoms_again([{F0}|Rest]) ->
- F = b2a(F0),
- [{F}|flags_to_atoms_again(Rest)].
-
-spec code_path_choice() -> 'relaxed' | 'strict'.
code_path_choice() ->
case get_argument(code_path_choice) of
@@ -337,7 +338,7 @@ boot_loop(BootPid, State) ->
end.
ensure_loaded(Module, Loaded) ->
- File = concat([Module,objfile_extension()]),
+ File = atom_to_list(Module) ++ objfile_extension(),
case catch load_mod(Module,File) of
{ok, FullName} ->
{{module, Module}, [{Module, FullName}|Loaded]};
@@ -451,9 +452,9 @@ do_handle_msg(Msg,State) ->
%%% -------------------------------------------------
make_permanent(Boot,Config,Flags0,State) ->
- case set_flag('-boot',Boot,Flags0) of
+ case set_flag(boot, Boot, Flags0) of
{ok,Flags1} ->
- case set_flag('-config',Config,Flags1) of
+ case set_flag(config, Config, Flags1) of
{ok,Flags} ->
{ok,State#state{flags = Flags}};
Error ->
@@ -691,17 +692,15 @@ sleep(T) -> receive after T -> ok end.
%%% The loader shall run for ever!
%%% -------------------------------------------------
-start_prim_loader(Init,Id,Pgm,Nodes,Path,{Pa,Pz}) ->
- case erl_prim_loader:start(Id,Pgm,Nodes) of
- {ok,Pid} when Path =:= false ->
- InitPath = append(Pa,["."|Pz]),
- erl_prim_loader:set_path(InitPath),
- add_to_kernel(Init,Pid),
- Pid;
+start_prim_loader(Init, Path0, {Pa,Pz}) ->
+ Path = case Path0 of
+ false -> Pa ++ ["."|Pz];
+ _ -> Path0
+ end,
+ case erl_prim_loader:start() of
{ok,Pid} ->
erl_prim_loader:set_path(Path),
- add_to_kernel(Init,Pid),
- Pid;
+ add_to_kernel(Init, Pid);
{error,Reason} ->
erlang:display({"cannot start loader",Reason}),
exit(Reason)
@@ -715,13 +714,6 @@ add_to_kernel(Init,Pid) ->
ok
end.
-prim_load_flags(Flags) ->
- PortPgm = get_flag('-loader',Flags,<<"efile">>),
- Hosts = get_flag_list('-hosts', Flags, []),
- Id = get_flag('-id',Flags,none),
- Path = get_flag_list('-path',Flags,false),
- {PortPgm, Hosts, Id, Path}.
-
%%% -------------------------------------------------
%%% The boot process fetches a boot script and loads
%%% all modules specified and starts spec. processes.
@@ -734,24 +726,23 @@ do_boot(Flags,Start) ->
do_boot(Init,Flags,Start) ->
process_flag(trap_exit,true),
- {Pgm0,Nodes,Id,Path} = prim_load_flags(Flags),
- Root = b2s(get_flag('-root',Flags)),
- PathFls = path_flags(Flags),
- Pgm = b2s(Pgm0),
- _Pid = start_prim_loader(Init,b2a(Id),Pgm,bs2as(Nodes),
- bs2ss(Path),PathFls),
+ Root = get_root(Flags),
+ Path = get_flag_list(path, Flags, false),
+ {Pa,Pz} = PathFls = path_flags(Flags),
+ start_prim_loader(Init, bs2ss(Path), PathFls),
BootFile = bootfile(Flags,Root),
BootList = get_boot(BootFile,Root),
- LoadMode = b2a(get_flag('-mode',Flags,false)),
- Deb = b2a(get_flag('-init_debug',Flags,false)),
+ LoadMode = b2a(get_flag(mode, Flags, false)),
+ Deb = b2a(get_flag(init_debug, Flags, false)),
catch ?ON_LOAD_HANDLER ! {init_debug_flag,Deb},
- BootVars = get_flag_args('-boot_var',Flags),
- ParallelLoad =
- (Pgm =:= "efile") and (erlang:system_info(thread_pool_size) > 0),
+ BootVars = get_boot_vars(Root, Flags),
PathChoice = code_path_choice(),
- eval_script(BootList,Init,PathFls,{Root,BootVars},Path,
- {true,LoadMode,ParallelLoad},Deb,PathChoice),
+ Es = #es{init=Init,debug=Deb,path=Path,pa=Pa,pz=Pz,
+ path_choice=PathChoice,
+ prim_load=true,load_mode=LoadMode,
+ vars=BootVars},
+ eval_script(BootList, Es),
%% To help identifying Purify windows that pop up,
%% print the node name into the Purify log.
@@ -759,21 +750,43 @@ do_boot(Init,Flags,Start) ->
start_em(Start).
+get_root(Flags) ->
+ case get_argument(root, Flags) of
+ {ok,[[Root]]} ->
+ Root;
+ _ ->
+ exit(no_or_multiple_root_variables)
+ end.
+
+get_boot_vars(Root, Flags) ->
+ BootVars = get_boot_vars_1(#{}, Flags),
+ RootKey = <<"ROOT">>,
+ BootVars#{RootKey=>Root}.
+
+get_boot_vars_1(Vars, [{boot_var,[Key,Value]}|T]) ->
+ get_boot_vars_1(Vars#{Key=>Value}, T);
+get_boot_vars_1(_, [{boot_var,_}|_]) ->
+ exit(invalid_boot_var_argument);
+get_boot_vars_1(Vars, [_|T]) ->
+ get_boot_vars_1(Vars, T);
+get_boot_vars_1(Vars, []) ->
+ Vars.
+
bootfile(Flags,Root) ->
- b2s(get_flag('-boot',Flags,concat([Root,"/bin/start"]))).
+ b2s(get_flag(boot, Flags, Root++"/bin/start")).
path_flags(Flags) ->
- Pa = append(reverse(get_flag_args('-pa',Flags))),
- Pz = append(get_flag_args('-pz',Flags)),
+ Pa = append(reverse(get_flag_args(pa, Flags))),
+ Pz = append(get_flag_args(pz, Flags)),
{bs2ss(Pa),bs2ss(Pz)}.
get_boot(BootFile0,Root) ->
- BootFile = concat([BootFile0,".boot"]),
+ BootFile = BootFile0 ++ ".boot",
case get_boot(BootFile) of
{ok, CmdList} ->
CmdList;
not_found -> %% Check for default.
- BootF = concat([Root,"/bin/",BootFile]),
+ BootF = Root ++ "/bin/" ++ BootFile,
case get_boot(BootF) of
{ok, CmdList} ->
CmdList;
@@ -807,93 +820,67 @@ get_boot(BootFile) ->
%% boot process hangs (we want to ensure syncronicity).
%%
-eval_script([{progress,Info}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) ->
- debug(Deb,{progress,Info}),
+eval_script([{progress,Info}=Progress|T], #es{debug=Deb}=Es) ->
+ debug(Deb, Progress),
init ! {self(),progress,Info},
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([{preLoaded,_}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) ->
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([{path,Path}|CfgL],Init,{Pa,Pz},Vars,false,Ph,Deb,PathChoice) ->
+ eval_script(T, Es);
+eval_script([{preLoaded,_}|T], #es{}=Es) ->
+ eval_script(T, Es);
+eval_script([{path,Path}|T], #es{path=false,pa=Pa,pz=Pz,
+ path_choice=PathChoice,
+ vars=Vars}=Es) ->
RealPath0 = make_path(Pa, Pz, Path, Vars),
RealPath = patch_path(RealPath0, PathChoice),
erl_prim_loader:set_path(RealPath),
- eval_script(CfgL,Init,{Pa,Pz},Vars,false,Ph,Deb,PathChoice);
-eval_script([{path,_}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) ->
+ eval_script(T, Es);
+eval_script([{path,_}|T], #es{}=Es) ->
%% Ignore, use the command line -path flag.
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([{kernel_load_completed}|CfgL],Init,PathFs,Vars,P,{_,embedded,Par},Deb,PathChoice) ->
- eval_script(CfgL,Init,PathFs,Vars,P,{true,embedded,Par},Deb,PathChoice);
-eval_script([{kernel_load_completed}|CfgL],Init,PathFs,Vars,P,{_,E,Par},Deb,PathChoice) ->
- eval_script(CfgL,Init,PathFs,Vars,P,{false,E,Par},Deb,PathChoice);
-eval_script([{primLoad,Mods}|CfgL],Init,PathFs,Vars,P,{true,E,Par},Deb,PathChoice)
+ eval_script(T, Es);
+eval_script([{kernel_load_completed}|T], #es{load_mode=Mode}=Es0) ->
+ Es = case Mode of
+ embedded -> Es0;
+ _ -> Es0#es{prim_load=false}
+ end,
+ eval_script(T, Es);
+eval_script([{primLoad,[Mod]}|T], #es{prim_load=true}=Es) ->
+ %% Common special case (loading of error_handler). Nothing
+ %% to gain by parallel loading.
+ File = atom_to_list(Mod) ++ objfile_extension(),
+ {ok,Full} = load_mod(Mod, File),
+ init ! {self(),loaded,{Mod,Full}}, % Tell init about loaded module
+ eval_script(T, Es);
+eval_script([{primLoad,Mods}|T], #es{init=Init,prim_load=PrimLoad}=Es)
when is_list(Mods) ->
- if
- Par =:= true ->
- par_load_modules(Mods,Init);
+ case PrimLoad of
true ->
- load_modules(Mods)
+ load_modules(Mods, Init);
+ false ->
+ %% Do not load now, code_server does that dynamically!
+ ok
end,
- eval_script(CfgL,Init,PathFs,Vars,P,{true,E,Par},Deb,PathChoice);
-eval_script([{primLoad,_Mods}|CfgL],Init,PathFs,Vars,P,{false,E,Par},Deb,PathChoice) ->
- %% Do not load now, code_server does that dynamically!
- eval_script(CfgL,Init,PathFs,Vars,P,{false,E,Par},Deb,PathChoice);
-eval_script([{kernelProcess,Server,{Mod,Fun,Args}}|CfgL],Init,
- PathFs,Vars,P,Ph,Deb,PathChoice) ->
- debug(Deb,{start,Server}),
- start_in_kernel(Server,Mod,Fun,Args,Init),
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([{apply,{Mod,Fun,Args}}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) ->
- debug(Deb,{apply,{Mod,Fun,Args}}),
- apply(Mod,Fun,Args),
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([],_,_,_,_,_,_,_) ->
+ eval_script(T, Es);
+eval_script([{kernelProcess,Server,{Mod,Fun,Args}}|T],
+ #es{init=Init,debug=Deb}=Es) ->
+ debug(Deb, {start,Server}),
+ start_in_kernel(Server, Mod, Fun, Args, Init),
+ eval_script(T, Es);
+eval_script([{apply,{Mod,Fun,Args}}=Apply|T], #es{debug=Deb}=Es) ->
+ debug(Deb, Apply),
+ apply(Mod, Fun, Args),
+ eval_script(T, Es);
+eval_script([], #es{}) ->
ok;
-eval_script(What,_,_,_,_,_,_,_) ->
+eval_script(What, #es{}) ->
exit({'unexpected command in bootfile',What}).
-load_modules([Mod|Mods]) ->
- File = concat([Mod,objfile_extension()]),
+load_modules([Mod|Mods], Init) ->
+ File = atom_to_list(Mod) ++ objfile_extension(),
{ok,Full} = load_mod(Mod,File),
- init ! {self(),loaded,{Mod,Full}}, %% Tell init about loaded module
- load_modules(Mods);
-load_modules([]) ->
+ Init ! {self(),loaded,{Mod,Full}}, %Tell init about loaded module
+ load_modules(Mods, Init);
+load_modules([], _) ->
ok.
-%%% An optimization: erl_prim_loader gets the chance of loading many
-%%% files in parallel, using threads. This will reduce the seek times,
-%%% and loaded code can be processed while other threads are waiting
-%%% for the disk. The optimization is not tried unless the loader is
-%%% "efile" and there is a non-empty pool of threads.
-%%%
-%%% Many threads are needed to get a good result, so it would be
-%%% beneficial to load several applications in parallel. However,
-%%% measurements show that the file system handles one directory at a
-%%% time, regardless if parallel threads are created for files on
-%%% several directories (a guess: writing the meta information when
-%%% the file was last read ('mtime'), forces the file system to sync
-%%% between directories).
-
-par_load_modules(Mods,Init) ->
- Ext = objfile_extension(),
- ModFiles = [{Mod,concat([Mod,Ext])} || Mod <- Mods,
- not erlang:module_loaded(Mod)],
- Self = self(),
- Fun = fun(Mod, BinCode, FullName) ->
- case catch load_mod_code(Mod, BinCode, FullName) of
- {ok, _} ->
- Init ! {Self,loaded,{Mod,FullName}},
- ok;
- _EXIT ->
- {error, Mod}
- end
- end,
- case erl_prim_loader:get_files(ModFiles, Fun) of
- ok ->
- ok;
- {error,Mod} ->
- exit({'cannot load',Mod,get_files})
- end.
-
make_path(Pa, Pz, Path, Vars) ->
append([Pa,append([fix_path(Path,Vars),Pz])]).
@@ -908,34 +895,25 @@ fix_path([Path|Ps], Vars) ->
fix_path(_, _) ->
[].
-add_var("$ROOT/" ++ Path, {Root,_}) ->
- concat([Root, "/", Path]);
-add_var([$$|Path0], {_,VarList}) ->
- {Var,Path} = extract_var(Path0,[]),
- Value = b2s(get_var_value(list_to_binary(Var),VarList)),
- concat([Value, "/", Path]);
-add_var(Path, _) ->
+add_var("$"++Path0, Vars) ->
+ {Var,Path} = extract_var(Path0, []),
+ Key = list_to_binary(Var),
+ case Vars of
+ #{Key:=Value0} ->
+ Value = b2s(Value0),
+ Value ++ "/" ++ Path;
+ _ ->
+ Error0 = "cannot expand $" ++ Var ++ " in bootfile",
+ Error = list_to_atom(Error0),
+ exit(Error)
+ end;
+add_var(Path, _) ->
Path.
extract_var([$/|Path],Var) -> {reverse(Var),Path};
extract_var([H|T],Var) -> extract_var(T,[H|Var]);
extract_var([],Var) -> {reverse(Var),[]}.
-%% get_var_value(Var, [Vars]) where Vars == [atom()]
-get_var_value(Var,[Vars|VarList]) ->
- case get_var_val(Var,Vars) of
- {ok, Value} ->
- Value;
- _ ->
- get_var_value(Var,VarList)
- end;
-get_var_value(Var,[]) ->
- exit(list_to_atom(concat(["cannot expand \$", Var, " in bootfile"]))).
-
-get_var_val(Var,[Var,Value|_]) -> {ok, Value};
-get_var_val(Var,[_,_|Vars]) -> get_var_val(Var,Vars);
-get_var_val(_,_) -> false.
-
patch_path(Dirs, strict) ->
Dirs;
patch_path(Dirs, relaxed) ->
@@ -1049,18 +1027,10 @@ start_it({eval,Bin}) ->
{value, _Value, _Bs} = erl_eval:exprs(Expr, erl_eval:new_bindings()),
ok;
start_it([_|_]=MFA) ->
- Ref = make_ref(),
- case catch {Ref,case MFA of
- [M] -> M:start();
- [M,F] -> M:F();
- [M,F|Args] -> M:F(Args) % Args is a list
- end} of
- {Ref,R} ->
- R;
- {'EXIT',Reason} ->
- exit(Reason);
- Other ->
- throw(Other)
+ case MFA of
+ [M] -> M:start();
+ [M,F] -> M:F();
+ [M,F|Args] -> M:F(Args) % Args is a list
end.
%%
@@ -1102,7 +1072,7 @@ load_mod_code(Mod, BinCode, FullName) ->
%% --------------------------------------------------------
shutdown_timer(Flags) ->
- case get_flag('-shutdown_time',Flags,infinity) of
+ case get_flag(shutdown_time, Flags, infinity) of
infinity ->
self();
Time ->
@@ -1152,14 +1122,10 @@ parse_boot_args([B|Bs], Ss, Fs, As) ->
eval_arg ->
{Expr,Rest} = get_args(Bs, []),
parse_boot_args(Rest, [{eval, Expr}|Ss], Fs, As);
- flag ->
+ {flag,A} ->
{F,Rest} = get_args(Bs, []),
- Fl = case F of
- [] -> [B];
- FF -> [B,FF]
- end,
- parse_boot_args(Rest, Ss,
- [list_to_tuple(Fl)|Fs], As);
+ Fl = {A,F},
+ parse_boot_args(Rest, Ss, [Fl|Fs], As);
arg ->
parse_boot_args(Bs, Ss, Fs, [B|As]);
end_args ->
@@ -1173,12 +1139,8 @@ check(<<"-s">>) -> start_arg;
check(<<"-run">>) -> start_arg2;
check(<<"-eval">>) -> eval_arg;
check(<<"--">>) -> end_args;
-check(X) when is_binary(X) ->
- case binary_to_list(X) of
- [$-|_Rest] -> flag;
- _Chars -> arg %Even empty atoms
- end;
-check(_X) -> arg. %This should never occur
+check(<<"-",Flag/binary>>) -> {flag,b2a(Flag)};
+check(_) -> arg.
get_args([B|Bs], As) ->
case check(B) of
@@ -1187,7 +1149,7 @@ get_args([B|Bs], As) ->
start_arg2 -> {reverse(As), [B|Bs]};
eval_arg -> {reverse(As), [B|Bs]};
end_args -> {reverse(As), Bs};
- flag -> {reverse(As), [B|Bs]};
+ {flag,_} -> {reverse(As), [B|Bs]};
arg ->
get_args(Bs, [B|As])
end;
@@ -1199,44 +1161,28 @@ get_args([], As) -> {reverse(As),[]}.
%% atom() if a single arg was given.
%% list(atom()) if several args were given.
%%
-get_flag(F,Flags,Default) ->
- case catch get_flag(F,Flags) of
- {'EXIT',_} ->
- Default;
- Value ->
- Value
- end.
-
-get_flag(F,Flags) ->
- case search(F,Flags) of
- {value,{F,[V]}} ->
+get_flag(F, Flags, Default) ->
+ case lists:keyfind(F, 1, Flags) of
+ {F,[]} ->
+ true;
+ {F,[V]} ->
V;
- {value,{F,V}} ->
+ {F,V} ->
V;
- {value,{F}} -> % Flag given!
- true;
_ ->
- exit(list_to_atom(concat(["no ",F," flag"])))
+ Default
end.
%%
%% Internal get_flag function, with default value.
%% Return: list(atom())
%%
-get_flag_list(F,Flags,Default) ->
- case catch get_flag_list(F,Flags) of
- {'EXIT',_} ->
- Default;
- Value ->
- Value
- end.
-
-get_flag_list(F,Flags) ->
- case search(F,Flags) of
- {value,{F,V}} ->
+get_flag_list(F, Flags, Default) ->
+ case lists:keyfind(F, 1, Flags) of
+ {F,[_|_]=V} ->
V;
_ ->
- exit(list_to_atom(concat(["no ",F," flag"])))
+ Default
end.
%%
@@ -1246,21 +1192,15 @@ get_flag_list(F,Flags) ->
%%
get_flag_args(F,Flags) -> get_flag_args(F,Flags,[]).
-get_flag_args(F,[{F,V}|Flags],Acc) when is_list(V) ->
- get_flag_args(F,Flags,[V|Acc]);
get_flag_args(F,[{F,V}|Flags],Acc) ->
- get_flag_args(F,Flags,[[V]|Acc]);
+ get_flag_args(F,Flags,[V|Acc]);
get_flag_args(F,[_|Flags],Acc) ->
get_flag_args(F,Flags,Acc);
get_flag_args(_,[],Acc) ->
reverse(Acc).
get_arguments([{F,V}|Flags]) ->
- [$-|Fl] = atom_to_list(F),
- [{list_to_atom(Fl),to_strings(V)}|get_arguments(Flags)];
-get_arguments([{F}|Flags]) ->
- [$-|Fl] = atom_to_list(F),
- [{list_to_atom(Fl),[]}|get_arguments(Flags)];
+ [{F,to_strings(V)}|get_arguments(Flags)];
get_arguments([]) ->
[].
@@ -1268,44 +1208,26 @@ to_strings([H|T]) when is_atom(H) -> [atom_to_list(H)|to_strings(T)];
to_strings([H|T]) when is_binary(H) -> [b2s(H)|to_strings(T)];
to_strings([]) -> [].
-get_argument(Arg,Flags) ->
- Args = get_arguments(Flags),
- case get_argument1(Arg,Args) of
- [] ->
- error;
- Value ->
- {ok,Value}
+get_argument(Arg, Flags) ->
+ case get_argument1(Arg, Flags) of
+ [] -> error;
+ Value -> {ok,Value}
end.
-get_argument1(Arg,[{Arg,V}|Args]) ->
- [V|get_argument1(Arg,Args)];
-get_argument1(Arg,[_|Args]) ->
- get_argument1(Arg,Args);
-get_argument1(_,[]) ->
+get_argument1(Arg, [{Arg,V}|Args]) ->
+ [to_strings(V)|get_argument1(Arg, Args)];
+get_argument1(Arg, [_|Args]) ->
+ get_argument1(Arg, Args);
+get_argument1(_, []) ->
[].
set_argument([{Flag,_}|Flags],Flag,Value) ->
[{Flag,[Value]}|Flags];
-set_argument([{Flag}|Flags],Flag,Value) ->
- [{Flag,[Value]}|Flags];
set_argument([Item|Flags],Flag,Value) ->
[Item|set_argument(Flags,Flag,Value)];
set_argument([],Flag,Value) ->
[{Flag,[Value]}].
-concat([A|T]) when is_atom(A) ->
- atom_to_list(A) ++ concat(T);
-concat([C|T]) when is_integer(C), 0 =< C, C =< 255 ->
- [C|concat(T)];
-concat([Bin|T]) when is_binary(Bin) ->
- binary_to_list(Bin) ++ concat(T);
-concat([S|T]) ->
- S ++ concat(T);
-concat([]) ->
- [].
-
-append(L, Z) -> L ++ Z.
-
append([E]) -> E;
append([H|T]) ->
H ++ append(T);
@@ -1320,13 +1242,6 @@ reverse([A, B]) ->
reverse([A, B | L]) ->
lists:reverse(L, [B, A]). % BIF
-search(Key, [H|_T]) when is_tuple(H), element(1, H) =:= Key ->
- {value, H};
-search(Key, [_|T]) ->
- search(Key, T);
-search(_Key, []) ->
- false.
-
-spec objfile_extension() -> nonempty_string().
objfile_extension() ->
".beam".
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index c87b2645ec..2eb1b1d408 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -1276,6 +1276,7 @@ lseek_position(_) ->
%% Translates the response from the driver into
%% {ok, Result} or {error, Reason}.
+-dialyzer({no_improper_lists, translate_response/2}).
translate_response(?FILE_RESP_OK, []) ->
ok;
translate_response(?FILE_RESP_ERROR, List) when is_list(List) ->