diff options
Diffstat (limited to 'lib')
176 files changed, 2359 insertions, 1262 deletions
diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml index c92566de37..57b032b3fd 100644 --- a/lib/common_test/doc/src/common_test_app.xml +++ b/lib/common_test/doc/src/common_test_app.xml @@ -144,7 +144,7 @@ <v> UserData = term()</v> <v> Conns = [atom()]</v> <v> CSSFile = string()</v> - <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs}]</v> + <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs} | {CTHModule, CTHInitArgs, CTHPriority}]</v> <v> CTHModule = atom()</v> <v> CTHInitArgs = term()</v> </type> diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml index 7d5c9f4750..0ece3199bb 100644 --- a/lib/common_test/doc/src/ct_hooks.xml +++ b/lib/common_test/doc/src/ct_hooks.xml @@ -81,12 +81,14 @@ <funcs> <func> - <name>Module:init(Id, Opts) -> State</name> + <name>Module:init(Id, Opts) -> {ok, State} | + {ok, State, Priority}</name> <fsummary>Initiates the Common Test Hook</fsummary> <type> <v>Id = reference() | term()</v> <v>Opts = term()</v> <v>State = term()</v> + <v>Priority = integer()</v> </type> <desc> @@ -103,6 +105,10 @@ if <seealso marker="#Module:id-1">id/1</seealso> is not implemented. </p> + <p><c>Priority</c> is the relative priority of this hook. Hooks with a + lower priority will be executed first. If no priority is given, + it will be set to 0. </p> + <p>For details about when init is called see <seealso marker="ct_hooks_chapter#scope">scope</seealso> in the User's Guide.</p> diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml index fc5ab48e1b..dbb4310040 100644 --- a/lib/common_test/doc/src/ct_hooks_chapter.xml +++ b/lib/common_test/doc/src/ct_hooks_chapter.xml @@ -94,9 +94,11 @@ <seealso marker="common_test#Module:init_per_group-2"> init_per_group/2</seealso>. <c>CTH</c> in this case can be either only the module name of the CTH or a tuple with the module name and the - initial arguments to the CTH. Eg: + initial arguments and optionally the hook priority of the CTH. Eg: <c>{ct_hooks,[my_cth_module]}</c> or - <c>{ct_hooks,[{my_cth_module,[{debug,true}]}]}</c></p> + <c>{ct_hooks,[{my_cth_module,[{debug,true}]}]}</c> or + <c>{ct_hooks,[{my_cth_module,[{debug,true}],500}]}</c> + </p> <section> <title>Overriding CTHs</title> @@ -109,7 +111,16 @@ <c>id</c> in both places, Common Test knows that this CTH has already been installed and will not try to install it again.</p> </section> - + + <section> + <title>CTH Priority</title> + <p>By default each CTH installed will be executed in the order which + they are installed. This is not always wanted so common_test allows + the user to specify a priority for each hook. The priority can either + be specified in the CTH <seealso marker="ct_hooks#Module:init-2">init/2 + </seealso> function or when installing the hook. The priority given at + installation will override the priority returned by the CTH. </p> + </section> </section> <marker id="scope"/> @@ -331,7 +342,7 @@ id(Opts) -> %% any common state. init(Id, Opts) -> {ok,D} = file:open(Id,[write]), - #state{ file_handle = D, total = 0, data = [] }. + {ok, #state{ file_handle = D, total = 0, data = [] }}. %% @doc Called before init_per_suite is called. pre_init_per_suite(Suite,Config,State) -> diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml index e6fb85634f..e668568795 100644 --- a/lib/common_test/doc/src/run_test_chapter.xml +++ b/lib/common_test/doc/src/run_test_chapter.xml @@ -488,7 +488,7 @@ LogDir = string() EventHandlers = atom() | [atom()] InitArgs = [term()] - CTHModules = [CTHModule | {CTHModule, CTHInitArgs}] + CTHModules = [CTHModule | {CTHModule, CTHInitArgs} | {CTHModule, CTHInitArgs, CTHPriority}] CTHModule = atom() CTHInitArgs = term() DirRef = DirAlias | Dir diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 809616d8e3..9e597edf38 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -240,7 +240,8 @@ add_defaults(Mod,Func,FuncInfo,DoInit) -> case (catch Mod:suite()) of {'EXIT',{undef,_}} -> SuiteInfo = merge_with_suite_defaults(Mod,[]), - case add_defaults1(Mod,Func,FuncInfo,SuiteInfo,DoInit) of + SuiteInfoNoCTH = [I || I <- SuiteInfo, element(1,I) =/= ct_hooks], + case add_defaults1(Mod,Func,FuncInfo,SuiteInfoNoCTH,DoInit) of Error = {error,_} -> {SuiteInfo,Error}; MergedInfo -> {SuiteInfo,MergedInfo} end; @@ -251,10 +252,11 @@ add_defaults(Mod,Func,FuncInfo,DoInit) -> (_) -> false end, SuiteInfo) of true -> - SuiteInfoNoCTH = - lists:keydelete(ct_hooks,1,SuiteInfo), - SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfoNoCTH), - case add_defaults1(Mod,Func,FuncInfo,SuiteInfo1,DoInit) of + SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfo), + SuiteInfoNoCTH = [I || I <- SuiteInfo1, + element(1,I) =/= ct_hooks], + case add_defaults1(Mod,Func,FuncInfo, + SuiteInfoNoCTH,DoInit) of Error = {error,_} -> {SuiteInfo1,Error}; MergedInfo -> {SuiteInfo1,MergedInfo} end; diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl index 984e04b90f..f243b87f54 100644 --- a/lib/common_test/src/ct_hooks.erl +++ b/lib/common_test/src/ct_hooks.erl @@ -31,11 +31,11 @@ -export([on_tc_skip/2]). -export([on_tc_fail/2]). --type proplist() :: [{atom(),term()}]. - %% If you change this, remember to update ct_util:look -> stop clause as well. -define(config_name, ct_hooks). +-record(ct_hook_config, {id, module, prio, scope, opts = [], state = []}). + %% ------------------------------------------------------------------------- %% API Functions %% ------------------------------------------------------------------------- @@ -44,22 +44,22 @@ -spec init(State :: term()) -> ok | {error, Reason :: term()}. init(Opts) -> - call([{Hook, call_id, undefined} || Hook <- get_new_hooks(Opts)], - ok, init, []). + call(get_new_hooks(Opts, undefined), ok, init, []). %% @doc Called after all suites are done. -spec terminate(Hooks :: term()) -> ok. terminate(Hooks) -> - call([{HookId, fun call_terminate/3} || {HookId,_,_} <- Hooks], + call([{HookId, fun call_terminate/3} + || #ct_hook_config{id = HookId} <- Hooks], ct_hooks_terminate_dummy, terminate, Hooks), ok. %% @doc Called as each test case is started. This includes all configuration %% tests. -spec init_tc(Mod :: atom(), Func :: atom(), Args :: list()) -> - NewConfig :: proplist() | + NewConfig :: proplists:proplist() | {skip, Reason :: term()} | {auto_skip, Reason :: term()} | {fail, Reason :: term()}. @@ -68,11 +68,11 @@ init_tc(ct_framework, _Func, Args) -> init_tc(Mod, init_per_suite, Config) -> Info = try proplists:get_value(ct_hooks, Mod:suite(),[]) of List when is_list(List) -> - [{ct_hooks,List}]; + [{?config_name,List}]; CTHook when is_atom(CTHook) -> - [{ct_hooks,[CTHook]}] + [{?config_name,[CTHook]}] catch error:undef -> - [{ct_hooks,[]}] + [{?config_name,[]}] end, call(fun call_generic/3, Config ++ Info, [pre_init_per_suite, Mod]); init_tc(Mod, end_per_suite, Config) -> @@ -92,7 +92,7 @@ init_tc(_Mod, TC, Config) -> Args :: list(), Result :: term(), Resturn :: term()) -> - NewConfig :: proplist() | + NewConfig :: proplists:proplist() | {skip, Reason :: term()} | {auto_skip, Reason :: term()} | {fail, Reason :: term()} | @@ -131,36 +131,48 @@ on_tc_fail(_How, {Suite, Case, Reason}) -> %% ------------------------------------------------------------------------- %% Internal Functions %% ------------------------------------------------------------------------- -call_id(Mod, Config, Meta) when is_atom(Mod) -> - call_id({Mod, []}, Config, Meta); -call_id({Mod, Opts}, Config, Scope) -> +call_id(#ct_hook_config{ module = Mod, opts = Opts} = Hook, Config, Scope) -> Id = catch_apply(Mod,id,[Opts], make_ref()), - {Config, {Id, scope(Scope), {Mod, {Id,Opts}}}}. + {Config, Hook#ct_hook_config{ id = Id, scope = scope(Scope)}}. -call_init({Mod,{Id,Opts}},Config,_Meta) -> - NewState = Mod:init(Id, Opts), - {Config, {Mod, NewState}}. - -call_terminate({Mod, State}, _, _) -> +call_init(#ct_hook_config{ module = Mod, opts = Opts, id = Id, prio = P} = Hook, + Config,_Meta) -> + case Mod:init(Id, Opts) of + {ok, NewState} when P =:= undefined -> + {Config, Hook#ct_hook_config{ state = NewState, prio = 0 } }; + {ok, NewState} -> + {Config, Hook#ct_hook_config{ state = NewState } }; + {ok, NewState, Prio} when P =:= undefined -> + %% Only set prio if not already set when installing hook + {Config, Hook#ct_hook_config{ state = NewState, prio = Prio } }; + {ok, NewState, _} -> + {Config, Hook#ct_hook_config{ state = NewState } }; + NewState -> %% Keep for backward compatability reasons + {Config, Hook#ct_hook_config{ state = NewState } } + end. + +call_terminate(#ct_hook_config{ module = Mod, state = State} = Hook, _, _) -> catch_apply(Mod,terminate,[State], ok), - {[],{Mod,State}}. + {[],Hook}. -call_cleanup({Mod, State}, Reason, [Function, _Suite | Args]) -> +call_cleanup(#ct_hook_config{ module = Mod, state = State} = Hook, + Reason, [Function, _Suite | Args]) -> NewState = catch_apply(Mod,Function, Args ++ [Reason, State], State), - {Reason, {Mod, NewState}}. + {Reason, Hook#ct_hook_config{ state = NewState } }. -call_generic({Mod, State}, Value, [Function | Args]) -> +call_generic(#ct_hook_config{ module = Mod, state = State} = Hook, + Value, [Function | Args]) -> {NewValue, NewState} = catch_apply(Mod, Function, Args ++ [Value, State], {Value,State}), - {NewValue, {Mod, NewState}}. + {NewValue, Hook#ct_hook_config{ state = NewState } }. %% Generic call function call(Fun, Config, Meta) -> maybe_lock(), Hooks = get_hooks(), - Res = call([{HookId,Fun} || {HookId,_, _} <- Hooks] ++ - get_new_hooks(Config, Fun), + Res = call(get_new_hooks(Config, Fun) ++ + [{HookId,Fun} || #ct_hook_config{id = HookId} <- Hooks], remove(?config_name,Config), Meta, Hooks), maybe_unlock(), Res. @@ -173,19 +185,20 @@ call(Fun, Config, Meta, NoChangeRet) when is_function(Fun) -> call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) -> try - {Config, {NewId, _, _} = NewHook} = call_id(Hook, Config, Meta), + {Config, #ct_hook_config{ id = NewId } = NewHook} = + call_id(Hook, Config, Meta), {NewHooks, NewRest} = - case lists:keyfind(NewId, 1, Hooks) of + case lists:keyfind(NewId, #ct_hook_config.id, Hooks) of false when NextFun =:= undefined -> {Hooks ++ [NewHook], - [{NewId, fun call_init/3} | Rest]}; + [{NewId, call_init} | Rest]}; ExistingHook when is_tuple(ExistingHook) -> {Hooks, Rest}; _ -> {Hooks ++ [NewHook], - [{NewId, fun call_init/3},{NewId,NextFun} | Rest]} + [{NewId, call_init}, {NewId,NextFun} | Rest]} end, - call(NewRest, Config, Meta, NewHooks) + call(resort(NewRest,NewHooks), Config, Meta, NewHooks) catch Error:Reason -> Trace = erlang:get_stacktrace(), ct_logs:log("Suite Hook","Failed to start a CTH: ~p:~p", @@ -193,13 +206,16 @@ call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) -> call([], {fail,"Failed to start CTH" ", see the CT Log for details"}, Meta, Hooks) end; +call([{HookId, call_init} | Rest], Config, Meta, Hooks) -> + call([{HookId, fun call_init/3} | Rest], Config, Meta, Hooks); call([{HookId, Fun} | Rest], Config, Meta, Hooks) -> try - {_,Scope,ModState} = lists:keyfind(HookId, 1, Hooks), - {NewConf, NewHookInfo} = Fun(ModState, Config, Meta), + Hook = lists:keyfind(HookId, #ct_hook_config.id, Hooks), + {NewConf, NewHook} = Fun(Hook, Config, Meta), NewCalls = get_new_hooks(NewConf, Fun), - NewHooks = lists:keyreplace(HookId, 1, Hooks, {HookId, Scope, NewHookInfo}), - call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, + NewHooks = lists:keyreplace(HookId, #ct_hook_config.id, Hooks, NewHook), + call(resort(NewCalls ++ Rest,NewHooks), %% Resort if call_init changed prio + remove(?config_name, NewConf), Meta, terminate_if_scope_ends(HookId, Meta, NewHooks)) catch throw:{error_in_cth_call,Reason} -> call(Rest, {fail, Reason}, Meta, @@ -237,19 +253,26 @@ terminate_if_scope_ends(HookId, [on_tc_skip,Suite,end_per_suite], Hooks) -> terminate_if_scope_ends(HookId, [Function,Tag|T], Hooks) when T =/= [] -> terminate_if_scope_ends(HookId,[Function,Tag],Hooks); terminate_if_scope_ends(HookId, Function, Hooks) -> - case lists:keyfind(HookId, 1, Hooks) of - {HookId, Function, _ModState} = Hook -> + case lists:keyfind(HookId, #ct_hook_config.id, Hooks) of + #ct_hook_config{ id = HookId, scope = Function} = Hook -> terminate([Hook]), - lists:keydelete(HookId, 1, Hooks); + lists:keydelete(HookId, #ct_hook_config.id, Hooks); _ -> Hooks end. %% Fetch hook functions get_new_hooks(Config, Fun) -> - lists:foldl(fun(NewHook, Acc) -> - [{NewHook, call_id, Fun} | Acc] - end, [], get_new_hooks(Config)). + lists:map(fun(NewHook) when is_atom(NewHook) -> + {#ct_hook_config{ module = NewHook }, call_id, Fun}; + ({NewHook,Opts}) -> + {#ct_hook_config{ module = NewHook, + opts = Opts}, call_id, Fun}; + ({NewHook,Opts,Prio}) -> + {#ct_hook_config{ module = NewHook, + opts = Opts, + prio = Prio }, call_id, Fun} + end, get_new_hooks(Config)). get_new_hooks(Config) when is_list(Config) -> lists:flatmap(fun({?config_name, HookConfigs}) -> @@ -264,7 +287,43 @@ save_suite_data_async(Hooks) -> ct_util:save_suite_data_async(?config_name, Hooks). get_hooks() -> - ct_util:read_suite_data(?config_name). + lists:keysort(#ct_hook_config.prio,ct_util:read_suite_data(?config_name)). + +%% Sort all calls in this order: +%% call_id < call_init < Hook Priority 1 < .. < Hook Priority N +%% If Hook Priority is equal, check when it has been installed and +%% sort on that instead. +resort(Calls, Hooks) -> + lists:sort( + fun({_,_,_},_) -> + true; + (_,{_,_,_}) -> + false; + ({_,call_init},_) -> + true; + (_,{_,call_init}) -> + false; + ({Id1,_},{Id2,_}) -> + P1 = (lists:keyfind(Id1, #ct_hook_config.id, Hooks))#ct_hook_config.prio, + P2 = (lists:keyfind(Id2, #ct_hook_config.id, Hooks))#ct_hook_config.prio, + if + P1 == P2 -> + %% If priorities are equal, we check the position in the + %% hooks list + pos(Id1,Hooks) < pos(Id2,Hooks); + true -> + P1 < P2 + end + end,Calls). + +pos(Id,Hooks) -> + pos(Id,Hooks,0). +pos(Id,[#ct_hook_config{ id = Id}|_],Num) -> + Num; +pos(Id,[_|Rest],Num) -> + pos(Id,Rest,Num+1). + + catch_apply(M,F,A, Default) -> try diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index c01e97b358..877ec9c7dd 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -521,8 +521,8 @@ script_usage() -> "\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]" "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" - "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" - "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" + "\n\t[-event_handler EvHandler1 and EvHandler2 .. EvHandlerN]" + "\n\t[-ct_hooks CTHook1 and CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -540,8 +540,8 @@ script_usage() -> "\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]" "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" - "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" - "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" + "\n\t[-event_handler EvHandler1 and EvHandler2 .. EvHandlerN]" + "\n\t[-ct_hooks CTHook1 and CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -2070,15 +2070,21 @@ ct_hooks_args2opts(Args) -> ct_hooks_args2opts( proplists:get_value(ct_hooks, Args, []),[]). +ct_hooks_args2opts([CTH,Arg,Prio,"and"| Rest],Acc) -> + ct_hooks_args2opts(Rest,[{list_to_atom(CTH), + parse_cth_args(Arg), + parse_cth_args(Prio)}|Acc]); ct_hooks_args2opts([CTH,Arg,"and"| Rest],Acc) -> ct_hooks_args2opts(Rest,[{list_to_atom(CTH), - parse_cth_args(Arg)}|Acc]); + parse_cth_args(Arg)}|Acc]); ct_hooks_args2opts([CTH], Acc) -> ct_hooks_args2opts([CTH,"and"],Acc); ct_hooks_args2opts([CTH, "and" | Rest], Acc) -> ct_hooks_args2opts(Rest,[list_to_atom(CTH)|Acc]); ct_hooks_args2opts([CTH, Args], Acc) -> ct_hooks_args2opts([CTH, Args, "and"],Acc); +ct_hooks_args2opts([CTH, Args, Prio], Acc) -> + ct_hooks_args2opts([CTH, Args, Prio, "and"],Acc); ct_hooks_args2opts([],Acc) -> lists:reverse(Acc). @@ -2225,7 +2231,14 @@ opts2args(EnvStartOpts) -> ({ct_hooks,CTHs}) when is_list(CTHs) -> io:format(user,"ct_hooks: ~p",[CTHs]), Strs = lists:flatmap( - fun({CTH,Arg}) -> + fun({CTH,Arg,Prio}) -> + [atom_to_list(CTH), + lists:flatten( + io_lib:format("~p",[Arg])), + lists:flatten( + io_lib:format("~p",[Prio])), + "and"]; + ({CTH,Arg}) -> [atom_to_list(CTH), lists:flatten( io_lib:format("~p",[Arg])), diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl index 8574d7aabc..5c99f0f9f7 100644 --- a/lib/common_test/test/ct_hooks_SUITE.erl +++ b/lib/common_test/test/ct_hooks_SUITE.erl @@ -83,7 +83,7 @@ all(suite) -> fail_post_suite_cth, skip_pre_suite_cth, skip_post_suite_cth, recover_post_suite_cth, update_config_cth, state_update_cth, options_cth, same_id_cth, - fail_n_skip_with_minimal_cth + fail_n_skip_with_minimal_cth, prio_cth ] ) . @@ -209,6 +209,11 @@ fail_n_skip_with_minimal_cth(Config) when is_list(Config) -> do_test(fail_n_skip_with_minimal_cth, "ct_cth_fail_one_skip_one_SUITE.erl", [minimal_terminate_cth],Config). +prio_cth(Config) when is_list(Config) -> + do_test(prio_cth, "ct_cth_prio_SUITE.erl", + [{empty_cth,[1000],1000},{empty_cth,[900],900}, + {prio_cth,[1100,100],100},{prio_cth,[1100]}],Config). + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS %%%----------------------------------------------------------------- @@ -296,9 +301,9 @@ test_events(two_empty_cth) -> {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,cth,{'_',id,[[]]}}, - {?eh,cth,{'_',init,['_',[]]}}, {?eh,cth,{'_',id,[[]]}}, {?eh,cth,{'_',init,['_',[]]}}, + {?eh,cth,{'_',init,['_',[]]}}, {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, @@ -365,9 +370,9 @@ test_events(minimal_and_maximal_cth) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,cth,{'_',id,[[]]}}, {negative,{?eh,cth,{'_',id,['_',[]]}}, {?eh,cth,{'_',init,['_',[]]}}}, - {?eh,cth,{'_',id,[[]]}}, {?eh,cth,{'_',init,['_',[]]}}, {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, @@ -954,8 +959,8 @@ test_events(same_id_cth) -> {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,cth,{'_',id,[[]]}}, - {?eh,cth,{'_',init,[same_id_cth,[]]}}, {?eh,cth,{'_',id,[[]]}}, + {?eh,cth,{'_',init,[same_id_cth,[]]}}, {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, {negative, @@ -1001,6 +1006,73 @@ test_events(fail_n_skip_with_minimal_cth) -> {?eh,stop_logging,[]} ]; +test_events(prio_cth) -> + + GenPre = fun(Func,States) -> + [{?eh,cth,{'_',Func,['_','_',State]}} || + State <- States] + end, + + GenPost = fun(Func,States) -> + [{?eh,cth,{'_',Func,['_','_','_',State]}} || + State <- States] + end, + + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}] ++ + + [{?eh,tc_start,{ct_cth_prio_SUITE,init_per_suite}}] ++ + GenPre(pre_init_per_suite, + [[1100,100],[800],[900],[1000],[1200,1050],[1100],[1200]]) ++ + GenPost(post_init_per_suite, + [[1100,100],[600,200],[600,600],[700],[800],[900],[1000], + [1200,1050],[1100],[1200]]) ++ + [{?eh,tc_done,{ct_cth_prio_SUITE,init_per_suite,ok}}, + + + [{?eh,tc_start,{ct_cth_prio_SUITE,{init_per_group,'_',[]}}}] ++ + GenPre(pre_init_per_group, + [[1100,100],[600,200],[600,600],[700],[800], + [900],[1000],[1200,1050],[1100],[1200]]) ++ + GenPost(post_init_per_group, + [[1100,100],[600,200],[600,600],[600],[700],[800], + [900],[900,900],[500,900],[1000],[1200,1050], + [1100],[1200]]) ++ + [{?eh,tc_done,{ct_cth_prio_SUITE,{init_per_group,'_',[]},ok}}] ++ + + [{?eh,tc_start,{ct_cth_prio_SUITE,test_case}}] ++ + GenPre(pre_init_per_testcase, + [[1100,100],[600,200],[600,600],[600],[700],[800], + [900],[900,900],[500,900],[1000],[1200,1050], + [1100],[1200]]) ++ + GenPost(post_end_per_testcase, + [[1100,100],[600,200],[600,600],[600],[700],[800], + [900],[900,900],[500,900],[1000],[1200,1050], + [1100],[1200]]) ++ + [{?eh,tc_done,{ct_cth_prio_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_cth_prio_SUITE,{end_per_group,'_',[]}}}] ++ + GenPre(pre_end_per_group, + [[1100,100],[600,200],[600,600],[600],[700],[800], + [900],[900,900],[500,900],[1000],[1200,1050], + [1100],[1200]]) ++ + GenPost(post_end_per_group, + [[1100,100],[600,200],[600,600],[600],[700],[800], + [900],[900,900],[500,900],[1000],[1200,1050], + [1100],[1200]]) ++ + [{?eh,tc_done,{ct_cth_prio_SUITE,{end_per_group,'_',[]},ok}}], + + {?eh,tc_start,{ct_cth_prio_SUITE,end_per_suite}}] ++ + GenPre(pre_end_per_suite, + [[1100,100],[600,200],[600,600],[700],[800],[900],[1000], + [1200,1050],[1100],[1200]]) ++ + GenPost(post_end_per_suite, + [[1100,100],[600,200],[600,600],[700],[800],[900],[1000], + [1200,1050],[1100],[1200]]) ++ + [{?eh,tc_done,{ct_cth_prio_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + test_events(ok) -> ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl new file mode 100644 index 0000000000..d564398cd0 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl @@ -0,0 +1,62 @@ +%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ct_cth_prio_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+suite() ->
+ ([{timetrap, {minutes, 10}},
+ {ct_hooks, [{empty_cth,[800],800},
+ {prio_cth,[1200]},{prio_cth,[1200,1050],1050}]}]).
+
+%% Test server callback functions
+init_per_suite(Config) ->
+ [{ct_hooks, [{empty_cth,[700],700},
+ {prio_cth,[600,600]},
+ {prio_cth,[600,200],200}]}|Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_G, Config) ->
+ [{ct_hooks, [{empty_cth,[600],600},
+ {prio_cth,[900,900]},{prio_cth,[500,900],900}]}|Config].
+
+end_per_group(_G, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+all() ->
+ [{group,test_group}].
+
+groups() ->
+ [{test_group,[],[test_case]}].
+
+%% Test cases starts here.
+test_case(Config) when is_list(Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl index ebebfd18a9..7befcfa57c 100644 --- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl @@ -59,8 +59,7 @@ -include_lib("common_test/src/ct_util.hrl").
-include_lib("common_test/include/ct_event.hrl").
--type proplist() :: list({atom(),term()}).
--type config() :: proplist().
+-type config() :: proplists:proplist(). -type reason() :: term().
-type skip_or_fail() :: {skip, reason()} |
{auto_skip, reason()} |
@@ -71,17 +70,17 @@ %% @doc Always called before any other callback function. Use this to initiate
%% any common state. It should return an state for this CTH.
--spec init(Id :: term(), Opts :: proplist()) ->
- State :: #state{}.
+-spec init(Id :: term(), Opts :: proplists:proplist()) -> + {ok, State :: #state{}}.
init(Id, Opts) ->
gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
data = {?MODULE, init, [Id, Opts]}}),
- Opts.
+ {ok,Opts}.
%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's
%% return the same ID the seconds CTH is ignored. This function should NOT
%% have any side effects as it might be called multiple times by common test.
--spec id(Opts :: proplist()) ->
+-spec id(Opts :: proplists:proplist()) -> Id :: term().
id(Opts) ->
gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl new file mode 100644 index 0000000000..82511ab0d3 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl @@ -0,0 +1,74 @@ +%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+-module(prio_cth).
+
+
+-include_lib("common_test/src/ct_util.hrl").
+
+
+%% CT Hooks
+-compile(export_all).
+
+id(Opts) ->
+ empty_cth:id(Opts).
+
+init(Id, Opts) ->
+ {ok, [Prio|_] = State} = empty_cth:init(Id, Opts),
+ {ok, State, Prio}.
+
+pre_init_per_suite(Suite, Config, State) ->
+ empty_cth:pre_init_per_suite(Suite,Config,State).
+
+post_init_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_init_per_suite(Suite,Config,Return,State).
+
+pre_end_per_suite(Suite,Config,State) ->
+ empty_cth:pre_end_per_suite(Suite,Config,State).
+
+post_end_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_end_per_suite(Suite,Config,Return,State).
+
+pre_init_per_group(Group,Config,State) ->
+ empty_cth:pre_init_per_group(Group,Config,State).
+
+post_init_per_group(Group,Config,Return,State) ->
+ empty_cth:post_init_per_group(Group,Config,Return,State).
+
+pre_end_per_group(Group,Config,State) ->
+ empty_cth:pre_end_per_group(Group,Config,State).
+
+post_end_per_group(Group,Config,Return,State) ->
+ empty_cth:post_end_per_group(Group,Config,Return,State).
+
+pre_init_per_testcase(TC,Config,State) ->
+ empty_cth:pre_init_per_testcase(TC,Config,State).
+
+post_end_per_testcase(TC,Config,Return,State) ->
+ empty_cth:post_end_per_testcase(TC,Config,Return,State).
+
+on_tc_fail(TC, Reason, State) ->
+ empty_cth:on_tc_fail(TC,Reason,State).
+
+on_tc_skip(TC, Reason, State) ->
+ empty_cth:on_tc_skip(TC,Reason,State).
+
+terminate(State) ->
+ empty_cth:terminate(State).
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl index 35c990c0be..9da48d3a4c 100644 --- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl @@ -29,7 +29,7 @@ init(Id, Opts) ->
State = empty_cth:init(Id, Opts),
- [init|State].
+ {ok, [init|State]}.
pre_init_per_suite(Suite, Config, State) ->
empty_cth:pre_init_per_suite(Suite,Config,State),
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index 7137dbc036..8cb16d8f09 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -1414,6 +1414,17 @@ do_clause(C, Arg, ArgType0, OrigArgType, Map, false -> true end; + [Pat0, Pat1] -> % binary comprehension + case cerl:is_c_cons(Pat0) of + true -> + not (cerl:is_c_var(cerl:cons_hd(Pat0)) andalso + cerl:is_c_var(cerl:cons_tl(Pat0)) andalso + cerl:is_c_var(Pat1) andalso + cerl:is_literal(Guard) andalso + (cerl:concrete(Guard) =:= true)); + false -> + true + end; _ -> true end; false -> @@ -2915,7 +2926,7 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab, {Warn, Msg} = case dialyzer_callgraph:lookup_name(FunLbl, Callgraph) of error -> {true, {unused_fun, []}}; - {ok, {_M, F, A}} = MFA -> + {ok, {_M, F, A} = MFA} -> {not sets:is_element(MFA, NoWarnUnused), {unused_fun, [F, A]}} end, diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index c45615d670..65c2ff76bb 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -1684,11 +1684,14 @@ solve_scc(SCC, Map, State, TryingUnit) -> true -> ?debug("SCC ~w reached fixpoint\n", [SCC]), NewTypes = unsafe_lookup_type_list(Funs, Map2), - case lists:all(fun(T) -> t_is_none(t_fun_range(T)) end, NewTypes) + case erl_types:any_none([t_fun_range(T) || T <- NewTypes]) andalso TryingUnit =:= false of true -> - UnitTypes = [t_fun(state__fun_arity(F, State), t_unit()) - || F <- Funs], + UnitTypes = + [case t_is_none(t_fun_range(T)) of + false -> T; + true -> t_fun(t_fun_args(T), t_unit()) + end || T <- NewTypes], Map3 = enter_type_lists(Funs, UnitTypes, Map2), solve_scc(SCC, Map3, State, true); false -> diff --git a/lib/dialyzer/test/Makefile b/lib/dialyzer/test/Makefile index 69a8fd742e..47deb17f1d 100644 --- a/lib/dialyzer/test/Makefile +++ b/lib/dialyzer/test/Makefile @@ -26,7 +26,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_tests_spec: $(INSTALL_DIR) $(RELSYSDIR) - chmod -f -R u+w $(RELSYSDIR) + chmod -R u+w $(RELSYSDIR) $(INSTALL_DATA) $(AUXILIARY_FILES) $(RELSYSDIR) @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) cd $(RELSYSDIR);\ diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 b/lib/dialyzer/test/r9c_SUITE_data/results/asn1 index ac83366bc8..571e562d0d 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 +++ b/lib/dialyzer/test/r9c_SUITE_data/results/asn1 @@ -2,7 +2,7 @@ asn1ct.erl:1500: The variable Err can never match since previous clauses completely covered the type #type{} asn1ct.erl:1596: The variable _ can never match since previous clauses completely covered the type 'ber_bin_v2' asn1ct.erl:1673: The pattern 'all' can never match the type 'asn1_module' | 'exclusive_decode' | 'partial_decode' -asn1ct.erl:672: The pattern <{'false', Result}, _, _> can never match the type <{'true','true'},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()],[any()]> +asn1ct.erl:672: The pattern <{'false', Result}, _, _> can never match the type <{'true','true'},atom() | binary() | [atom() | [any()] | char()],[any()]> asn1ct.erl:909: Guard test is_atom(Ext::[49 | 97 | 98 | 100 | 110 | 115]) can never succeed asn1ct_check.erl:1698: The pattern {'error', _} can never match the type [any()] asn1ct_check.erl:2733: The pattern {'type', Tag, _, _, _, _} can never match the type 'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_} diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/inets b/lib/dialyzer/test/r9c_SUITE_data/results/inets index fd5e36a3cd..6b16dba2ff 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/inets +++ b/lib/dialyzer/test/r9c_SUITE_data/results/inets @@ -7,9 +7,6 @@ http_lib.erl:286: The call http_lib:close('ip_comm' | {'ssl',_},any()) will neve http_lib.erl:424: The variable _ can never match since previous clauses completely covered the type any() http_lib.erl:438: The variable _ can never match since previous clauses completely covered the type any() http_lib.erl:99: Function getHeaderValue/2 will never be called -httpc_handler.erl:322: Function status_continue/2 has no local return -httpc_handler.erl:37: Function init_connection/2 has no local return -httpc_handler.erl:65: Function next_response_with_request/2 has no local return httpc_handler.erl:660: Function exit_session_ok/2 has no local return httpc_manager.erl:145: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}} httpc_manager.erl:160: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}} @@ -27,7 +24,7 @@ httpd_manager.erl:933: Function acceptor_status/1 will never be called httpd_request_handler.erl:374: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 66 | 98 | 100 | 103 | 105 | 111 | 116 | 121,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any()) httpd_request_handler.erl:378: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any()) httpd_request_handler.erl:401: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any()) -httpd_request_handler.erl:644: The call lists:reverse(Fields0::{'error',_} | {'ok',[[any()]]}) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) +httpd_request_handler.erl:644: The call lists:reverse(Fields0::{'error',_} | {'ok',_}) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) httpd_request_handler.erl:645: Function will never be called httpd_sup.erl:63: The variable Else can never match since previous clauses completely covered the type {'error',_} | {'ok',[any()],_,_} httpd_sup.erl:88: The pattern {'error', Reason} can never match the type {'ok',_,_} @@ -38,17 +35,17 @@ mod_auth_plain.erl:100: The variable _ can never match since previous clauses co mod_auth_plain.erl:159: The variable _ can never match since previous clauses completely covered the type [any()] mod_auth_plain.erl:83: The variable O can never match since previous clauses completely covered the type [any()] mod_cgi.erl:372: The pattern {'http_response', NewAccResponse} can never match the type 'ok' -mod_dir.erl:101: The call lists:flatten(nonempty_improper_list(atom() | binary() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) +mod_dir.erl:101: The call lists:flatten(nonempty_improper_list(atom() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) mod_dir.erl:72: The pattern {'error', Reason} can never match the type {'ok',[[[any()] | char()],...]} -mod_get.erl:135: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | binary() | [any()] | char()]> -mod_head.erl:80: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]> +mod_get.erl:135: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | [any()] | char()]> +mod_head.erl:80: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | [any()] | char()]> mod_htaccess.erl:460: The pattern {'error', BadData} can never match the type {'ok',_} -mod_include.erl:193: The pattern {_, Name, {[], []}} can never match the type {[any()],[any()],maybe_improper_list()} -mod_include.erl:195: The pattern {_, Name, {PathInfo, []}} can never match the type {[any()],[any()],maybe_improper_list()} -mod_include.erl:197: The pattern {_, Name, {PathInfo, QueryString}} can never match the type {[any()],[any()],maybe_improper_list()} -mod_include.erl:201: The variable Gurka can never match since previous clauses completely covered the type {[any()],[any()],maybe_improper_list()} -mod_include.erl:692: The pattern <{'read', Reason}, Info, Path> can never match the type <{'open',atom()},#mod{},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]> -mod_include.erl:706: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]> +mod_include.erl:193: The pattern {_, Name, {[], []}} can never match the type {[any()],[any()],string()} +mod_include.erl:195: The pattern {_, Name, {PathInfo, []}} can never match the type {[any()],[any()],string()} +mod_include.erl:197: The pattern {_, Name, {PathInfo, QueryString}} can never match the type {[any()],[any()],string()} +mod_include.erl:201: The variable Gurka can never match since previous clauses completely covered the type {[any()],[any()],string()} +mod_include.erl:692: The pattern <{'read', Reason}, Info, Path> can never match the type <{'open',atom()},#mod{},atom() | binary() | [atom() | [any()] | char()]> +mod_include.erl:706: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | [any()] | char()]> mod_include.erl:716: Function read_error/3 will never be called mod_include.erl:719: Function read_error/4 will never be called mod_security_server.erl:386: The variable O can never match since previous clauses completely covered the type [any()] diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia index e199581a0e..b0f4d12ae5 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia +++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia @@ -6,6 +6,9 @@ mnesia_bup.erl:111: The created fun has no local return mnesia_bup.erl:574: Function fallback_receiver/2 has no local return mnesia_bup.erl:967: Function uninstall_fallback_master/2 has no local return mnesia_checkpoint.erl:1014: The variable Error can never match since previous clauses completely covered the type {'ok',#checkpoint_args{nodes::[any()],retainers::[any(),...]}} +mnesia_checkpoint.erl:1209: Function system_continue/3 has no local return +mnesia_checkpoint.erl:792: Function retainer_loop/1 has no local return +mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> Void when is_subtype(Msg,term()), is_subtype(From,{pid(),Tag::_}), is_subtype(Parent,pid()), is_subtype(Module,module()), is_subtype(Debug,[dbg_opt()]), is_subtype(Misc,term()), is_subtype(Void,term()) mnesia_controller.erl:1666: The variable Tab can never match since previous clauses completely covered the type [any()] mnesia_controller.erl:1679: The pattern {'stop', Reason, Reply, State2} can never match the type {'noreply',_} | {'reply',_,_} | {'stop','shutdown',#state{}} mnesia_controller.erl:1685: The pattern {'noreply', State2, _Timeout} can never match the type {'reply',_,_} @@ -15,6 +18,7 @@ mnesia_frag.erl:294: The call mnesia_frag:remote_collect(Ref::reference(),{'erro mnesia_frag.erl:304: The call mnesia_frag:remote_collect(Ref::reference(),{'error',{'node_not_running',_}},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()])) mnesia_frag.erl:312: The call mnesia_frag:remote_collect(Ref::reference(),LocalRes::{'error',_},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()])) mnesia_index.erl:52: The call mnesia_lib:other_val(Var::{_,'commit_work' | 'index' | 'setorbag' | 'storage_type' | {'index',_}},_ReASoN_::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any()) +mnesia_lib.erl:1028: The pattern {'EXIT', Reason} can never match the type [any()] | {'error',_} mnesia_lib.erl:957: The pattern {'ok', {0, _}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()} mnesia_lib.erl:959: The pattern {'ok', {_, Bin}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()} mnesia_loader.erl:36: The call mnesia_lib:other_val(Var::{_,'access_mode' | 'cstruct' | 'db_nodes' | 'setorbag' | 'snmp' | 'storage_type'},Reason::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any()) @@ -30,5 +34,6 @@ mnesia_schema.erl:1258: Guard test FromS::'disc_copies' | 'disc_only_copies' | ' mnesia_schema.erl:1639: The pattern {'false', 'mandatory'} can never match the type {'false','optional'} mnesia_schema.erl:2434: The variable Reason can never match since previous clauses completely covered the type {'error',_} | {'ok',_} mnesia_schema.erl:451: Guard test UseDirAnyway::'false' == 'true' can never succeed +mnesia_text.erl:180: The variable T can never match since previous clauses completely covered the type {'error',{integer(),atom() | tuple(),_}} | {'ok',_} mnesia_tm.erl:1522: Function commit_participant/5 has no local return mnesia_tm.erl:2169: Function system_terminate/4 has no local return diff --git a/lib/dialyzer/test/race_SUITE_data/results/extract_translations b/lib/dialyzer/test/race_SUITE_data/results/extract_translations index f7d5abc6f5..62aa1aa511 100644 --- a/lib/dialyzer/test/race_SUITE_data/results/extract_translations +++ b/lib/dialyzer/test/race_SUITE_data/results/extract_translations @@ -1,5 +1,5 @@ -extract_translations.erl:140: The call ets:insert('files',{atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]) call in extract_translations.erl on line 135 +extract_translations.erl:140: The call ets:insert('files',{atom() | binary() | [atom() | [any()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | [any()] | char()]) call in extract_translations.erl on line 135 extract_translations.erl:146: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line 126 -extract_translations.erl:152: The call ets:insert('files',{atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]) call in extract_translations.erl on line 148 +extract_translations.erl:152: The call ets:insert('files',{atom() | binary() | [atom() | [any()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | [any()] | char()]) call in extract_translations.erl on line 148 extract_translations.erl:154: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line 126 diff --git a/lib/dialyzer/test/small_SUITE_data/results/flatten b/lib/dialyzer/test/small_SUITE_data/results/flatten index 4571214e49..8aa44dd002 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/flatten +++ b/lib/dialyzer/test/small_SUITE_data/results/flatten @@ -1,2 +1,2 @@ -flatten.erl:17: The call lists:flatten(nonempty_improper_list(atom() | binary() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) +flatten.erl:17: The call lists:flatten(nonempty_improper_list(atom() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) diff --git a/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl new file mode 100644 index 0000000000..c1e82bfa59 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl @@ -0,0 +1,8 @@ +-module(test). + +-export([bin_compr/0]). + +bin_compr() -> +% [ 0 || {N, V} <- [{a, b}] ]. % Works ok + << <<>> || {A, B} <- [{a, b}] >>. % Complains +% << <<>> || X <- [{a, b}] >>. % Works ok diff --git a/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl b/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl new file mode 100644 index 0000000000..8abf872b37 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl @@ -0,0 +1,35 @@ +%%--------------------------------------------------------------------- +%% From: Peer Stritzinger +%% Date: 1 May 2011 +%% Subject: Dialyzer v2.2.0 crash +%% +%% Binaries of the form <<_:N,_:_*M>> in specs resulted in a crash: +%% dialyzer: Analysis failed with error: {{case_clause,8}, +%% [{erl_types,t_form_to_string,1}, +%% {erl_types,t_form_to_string,1}, +%% {dialyzer_contracts,contract_to_string_1,1}, +%% {dialyzer_contracts,extra_contract_warning,6}, +%% {dialyzer_contracts,picky_contract_check,7}, +%% because function erl_types:t_form_to_string/1 was not the inverse +%% of erl_types:t_to_string/2. +%% +%% Fixed on the same date and send to OTP for inclusion. +%%--------------------------------------------------------------------- +-module(codec_can). + +-export([recv/3, decode/1]). + +-record(can_pkt, {id, data :: binary(), timestamp}). + +-type can_pkt() :: #can_pkt{}. +-type channel() :: atom() | pid() | {atom(),_}. + +-spec recv(<<_:64,_:_*8>>, fun((can_pkt()) -> R), channel()) -> R. +recv(Packet, Fun, Chan) -> + #can_pkt{id = Can_id, data = Can_data} = P = decode(Packet), + Fun(P). + +-spec decode(<<_:64,_:_*8>>) -> #can_pkt{id::<<_:11>>,timestamp::char()}. +decode(<<_:12, Len:4, Timestamp:16, 0:3, Id:11/bitstring, 0:18, + Data:Len/binary, _/binary>>) -> + #can_pkt{id = Id, data = Data, timestamp = Timestamp}. diff --git a/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl index 4f1268eba8..086df3464b 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl @@ -6,9 +6,7 @@ -export([parse/1]). --type proplist() :: [{atom(), any()}]. - --spec parse(string()) -> proplist(). +-spec parse(string()) -> proplists:proplist(). parse(FileName) -> {ok, IoDevice} = file:open(FileName, [read, binary, {encoding, utf8}]), do_parse(IoDevice, []). diff --git a/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl b/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl new file mode 100644 index 0000000000..2da708cb15 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl @@ -0,0 +1,21 @@ +%%===================================================================== +%% From: Ken Robinson +%% Date: 28/04/2011, 17:26 +%% +%% Program that produced borus "Function has no local return" warnings +%% due to erlang:list_to_bitstring/1 having erroneous hard coded type +%% information, namely accepting iolist() instead of bitstrlist(). +%% Fixed 29/04/2011. +%%===================================================================== + +-module(list_to_bitstring). + +-export([l2bs/0, l2bs_ok/0]). + +%% This function was producing a warning +l2bs() -> + erlang:list_to_bitstring([<<42>>, <<42:13>>]). + +%% while this one was ok. +l2bs_ok() -> + erlang:list_to_bitstring([<<42>>, <<42,42>>]). diff --git a/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl new file mode 100644 index 0000000000..5c24902590 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl @@ -0,0 +1,42 @@ +%% Dialyzer couldn't infer that monitor_diskspace would go in an infinite loop +%% instead of crashing due to the existence of list comprehensions that have a +%% normal success typing. These were added to the monitor_diskspace's SCC and +%% dialyzer_typesig didn't try to assign unit() to monitor_diskspace, as it +%% required all the members of the SCC to return none(). +%% +%% Testcase was submitted in erlang-questions mailing list by Prashanth Mundkur +%% (http://erlang.org/pipermail/erlang-questions/2011-May/058063.html) + +-module(no_return_bug). +-export([diskspace/1, monitor_diskspace/2, refresh_tags/1, monitor_launch/0]). + +-type diskinfo() :: {non_neg_integer(), non_neg_integer()}. + +-spec diskspace(nonempty_string()) -> {'ok', diskinfo()} | {'error', term()}. +diskspace(Path) -> + case Path of + "a" -> {ok, {0,0}}; + _ -> {error, error} + end. + +-spec monitor_diskspace(nonempty_string(), + [{diskinfo(), nonempty_string()}]) -> + no_return(). +monitor_diskspace(Root, Vols) -> + Df = fun(VolName) -> + diskspace(filename:join([Root, VolName])) + end, + NewVols = [{Space, VolName} + || {VolName, {ok, Space}} + <- [{VolName, Df(VolName)} + || {_OldSpace, VolName} <- Vols]], + monitor_diskspace(Root, NewVols). + +-spec refresh_tags(nonempty_string()) -> no_return(). +refresh_tags(Root) -> + {ok, _} = diskspace(Root), + refresh_tags(Root). + +monitor_launch() -> + spawn_link(fun() -> refresh_tags("abc") end), + spawn_link(fun() -> monitor_diskspace("root", [{{0,0}, "a"}]) end). diff --git a/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl b/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl new file mode 100644 index 0000000000..63daeee9e3 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl @@ -0,0 +1,7 @@ +-module(nowarnunused). + +-compile({nowarn_unused_function, return_error/2}). + +-spec return_error(integer(), any()) -> no_return(). +return_error(Line, Message) -> + throw({error, {Line, ?MODULE, Message}}). diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml index a87f59bad5..e7c530f1b8 100644 --- a/lib/diameter/doc/src/diameter_dict.xml +++ b/lib/diameter/doc/src/diameter_dict.xml @@ -105,7 +105,7 @@ quantity is insignificant.</p> <p> The tags, their arguments and the contents of each corresponding section are as follows. -Each section can occur only once unless otherwise specified. +Each section can occur at most once unless otherwise specified. The order in which sections are specified is unimportant.</p> <taglist> @@ -115,6 +115,7 @@ The order in which sections are specified is unimportant.</p> <p> Defines the integer Number as the Diameter Application Id of the application in question. +Required if the dictionary defines <c>@messages</c>. The section has empty content.</p> <p> @@ -370,7 +371,11 @@ Integer values can be prefixed with 0x to be interpreted as hexidecimal.</p> <p> -Can occur 0 or more times (with different values of Name).</p> +Can occur 0 or more times (with different values of Name). +The AVP in question can be defined in an inherited dictionary in order +to introduce additional values. +An AVP so extended must be referenced by in a <c>@messages</c> or +<c>@grouped</c> section.</p> <p> Example:</p> diff --git a/lib/diameter/src/compiler/diameter_codegen.erl b/lib/diameter/src/compiler/diameter_codegen.erl index 213ba0d22c..30caebc544 100644 --- a/lib/diameter/src/compiler/diameter_codegen.erl +++ b/lib/diameter/src/compiler/diameter_codegen.erl @@ -250,9 +250,14 @@ f_name(Name) -> %%% ------------------------------------------------------------------------ f_id(Spec) -> - Id = orddict:fetch(id, Spec), {?function, id, 0, - [{?clause, [], [], [?INTEGER(Id)]}]}. + [c_id(orddict:find(id, Spec))]}. + +c_id({ok, Id}) -> + {?clause, [], [], [?INTEGER(Id)]}; + +c_id(error) -> + ?UNEXPECTED(0). %%% ------------------------------------------------------------------------ %%% # vendor_id/0 @@ -454,9 +459,10 @@ avp(Spec) -> Native = get_value(avp_types, Spec), Custom = get_value(custom_types, Spec), Imported = get_value(import_avps, Spec), - avp([{N,T} || {N,_,T,_,_} <- Native], Imported, Custom). + Enums = get_value(enums, Spec), + avp([{N,T} || {N,_,T,_,_} <- Native], Imported, Custom, Enums). -avp(Native, Imported, Custom) -> +avp(Native, Imported, Custom, Enums) -> Dict = orddict:from_list(Native), report(native, Dict), @@ -470,8 +476,8 @@ avp(Native, Imported, Custom) -> false == lists:member(N, CustomNames) end, Native)) - ++ lists:flatmap(fun c_imported_avp/1, Imported) - ++ lists:flatmap(fun(C) -> c_custom_avp(C, Dict) end, Custom). + ++ lists:flatmap(fun(I) -> cs_imported_avp(I, Enums) end, Imported) + ++ lists:flatmap(fun(C) -> cs_custom_avp(C, Dict) end, Custom). c_base_avp({AvpName, T}) -> {?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)], @@ -487,23 +493,35 @@ base_avp(AvpName, 'Grouped') -> base_avp(_, Type) -> ?APPLY(diameter_types, Type, [?VAR('T'), ?VAR('Data')]). -c_imported_avp({Mod, Avps}) -> - lists:map(fun(A) -> imported_avp(Mod, A) end, Avps). +cs_imported_avp({Mod, Avps}, Enums) -> + lists:map(fun(A) -> imported_avp(Mod, A, Enums) end, Avps). -imported_avp(_Mod, {AvpName, _, 'Grouped' = T, _, _}) -> +imported_avp(_Mod, {AvpName, _, 'Grouped' = T, _, _}, _) -> c_base_avp({AvpName, T}); -imported_avp(Mod, {AvpName, _, _, _, _}) -> +imported_avp(Mod, {AvpName, _, 'Enumerated' = T, _, _}, Enums) -> + case lists:keymember(AvpName, 1, Enums) of + true -> + c_base_avp({AvpName, T}); + false -> + c_imported_avp(Mod, AvpName) + end; + +imported_avp(Mod, {AvpName, _, _, _, _}, _) -> + c_imported_avp(Mod, AvpName). + +c_imported_avp(Mod, AvpName) -> {?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)], [], [?APPLY(Mod, avp, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)])]}. -c_custom_avp({Mod, Avps}, Dict) -> - lists:map(fun(N) -> custom_avp(Mod, N, orddict:fetch(N, Dict)) end, Avps). +cs_custom_avp({Mod, Avps}, Dict) -> + lists:map(fun(N) -> c_custom_avp(Mod, N, orddict:fetch(N, Dict)) end, + Avps). -custom_avp(Mod, AvpName, Type) -> +c_custom_avp(Mod, AvpName, Type) -> {?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)], [], [?APPLY(Mod, AvpName, [?VAR('T'), ?ATOM(Type), ?VAR('Data')])]}. @@ -516,9 +534,25 @@ f_enumerated_avp(Spec) -> {?function, enumerated_avp, 3, enumerated_avp(Spec) ++ [?UNEXPECTED(3)]}. enumerated_avp(Spec) -> - lists:flatmap(fun c_enumerated_avp/1, get_value(enums, Spec)). + Enums = get_value(enums, Spec), + lists:flatmap(fun cs_enumerated_avp/1, Enums) + ++ lists:flatmap(fun({M,Es}) -> enumerated_avp(M, Es, Enums) end, + get_value(import_enums, Spec)). + +enumerated_avp(Mod, Es, Enums) -> + lists:flatmap(fun({N,_}) -> + cs_enumerated_avp(lists:keymember(N, 1, Enums), + Mod, + N) + end, + Es). -c_enumerated_avp({AvpName, Values}) -> +cs_enumerated_avp(true, Mod, Name) -> + [c_imported_avp(Mod, Name)]; +cs_enumerated_avp(false, _, _) -> + []. + +cs_enumerated_avp({AvpName, Values}) -> lists:flatmap(fun(V) -> c_enumerated_avp(AvpName, V) end, Values). c_enumerated_avp(AvpName, {I,_}) -> @@ -537,10 +571,14 @@ f_msg_header(Spec) -> {?function, msg_header, 1, msg_header(Spec) ++ [?UNEXPECTED(1)]}. msg_header(Spec) -> + msg_header(get_value(messages, Spec), Spec). + +msg_header([], _) -> + []; +msg_header(Msgs, Spec) -> ApplId = orddict:fetch(id, Spec), - lists:map(fun({M,C,F,_,_}) -> c_msg_header(M, C, F, ApplId) end, - get_value(messages, Spec)). + lists:map(fun({M,C,F,_,_}) -> c_msg_header(M, C, F, ApplId) end, Msgs). %% Note that any application id in the message header spec is ignored. @@ -616,10 +654,12 @@ f_empty_value(Spec) -> {?function, empty_value, 1, empty_value(Spec)}. empty_value(Spec) -> + Imported = lists:flatmap(fun avps/1, get_value(import_enums, Spec)), Groups = get_value(grouped, Spec) ++ lists:flatmap(fun avps/1, get_value(import_groups, Spec)), - Enums = get_value(enums, Spec) - ++ lists:flatmap(fun avps/1, get_value(import_enums, Spec)), + Enums = [T || {N,_} = T <- get_value(enums, Spec), + not lists:keymember(N, 1, Imported)] + ++ Imported, lists:map(fun c_empty_value/1, Groups ++ Enums) ++ [{?clause, [?VAR('Name')], [], [?CALL(empty, [?VAR('Name')])]}]. diff --git a/lib/diameter/src/compiler/diameter_spec_util.erl b/lib/diameter/src/compiler/diameter_spec_util.erl index 322d53a199..b60886b678 100644 --- a/lib/diameter/src/compiler/diameter_spec_util.erl +++ b/lib/diameter/src/compiler/diameter_spec_util.erl @@ -39,11 +39,11 @@ parse(Path, Options) -> {ok, B} = file:read_file(Path), Chunks = chunk(B), Spec = make_spec(Chunks), - true = enums_defined(Spec), %% sanity checks - true = groups_defined(Spec), %% + true = groups_defined(Spec), %% sanity checks true = customs_defined(Spec), %% Full = import_enums(import_groups(import_avps(insert_codes(Spec), Options))), + true = enums_defined(Full), %% sanity checks true = v_flags_set(Spec), Full. @@ -243,35 +243,48 @@ get_value(Key, Spec) -> %% with an appropriate type. enums_defined(Spec) -> - is_defined(Spec, 'Enumerated', enums). + Avps = get_value(avp_types, Spec), + Import = get_value(import_enums, Spec), + lists:all(fun({N,_}) -> + true = enum_defined(N, Avps, Import) + end, + get_value(enums, Spec)). -groups_defined(Spec) -> - is_defined(Spec, 'Grouped', grouped). +enum_defined(Name, Avps, Import) -> + case lists:keyfind(Name, 1, Avps) of + {Name, _, 'Enumerated', _, _} -> + true; + {Name, _, T, _, _} -> + ?ERROR({avp_has_wrong_type, Name, 'Enumerated', T}); + false -> + lists:any(fun({_,Is}) -> lists:keymember(Name, 1, Is) end, Import) + orelse ?ERROR({avp_not_defined, Name, 'Enumerated'}) + end. +%% Note that an AVP is imported only if referenced by a message or +%% grouped AVP, so the final branch will fail if an enum definition is +%% extended without this being the case. -is_defined(Spec, Type, Key) -> +groups_defined(Spec) -> Avps = get_value(avp_types, Spec), - lists:all(fun(T) -> true = is_local(name(Key, T), Type, Avps) end, - get_value(Key, Spec)). + lists:all(fun({N,_,_,_}) -> true = group_defined(N, Avps) end, + get_value(grouped, Spec)). -name(enums, {N,_}) -> N; -name(grouped, {N,_,_,_}) -> N. - -is_local(Name, Type, Avps) -> +group_defined(Name, Avps) -> case lists:keyfind(Name, 1, Avps) of - {Name, _, Type, _, _} -> + {Name, _, 'Grouped', _, _} -> true; {Name, _, T, _, _} -> - ?ERROR({avp_has_wrong_type, Name, Type, T}); + ?ERROR({avp_has_wrong_type, Name, 'Grouped', T}); false -> - ?ERROR({avp_not_defined, Name, Type}) + ?ERROR({avp_not_defined, Name, 'Grouped'}) end. customs_defined(Spec) -> Avps = get_value(avp_types, Spec), - lists:all(fun(A) -> true = is_local(A, Avps) end, + lists:all(fun(A) -> true = custom_defined(A, Avps) end, lists:flatmap(fun last/1, get_value(custom_types, Spec))). -is_local(Name, Avps) -> +custom_defined(Name, Avps) -> case lists:keyfind(Name, 1, Avps) of {Name, _, T, _, _} when T == 'Grouped'; T == 'Enumerated' -> @@ -510,6 +523,9 @@ choose(false, _, X) -> X. %% ------------------------------------------------------------------------ %% import_groups/1 %% import_enums/1 +%% +%% For each inherited module, store the content of imported AVP's of +%% type grouped/enumerated in a new key. import_groups(Spec) -> orddict:store(import_groups, import(grouped, Spec), Spec). diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile index 823e2f0311..b3648c7bb1 100644 --- a/lib/diameter/test/Makefile +++ b/lib/diameter/test/Makefile @@ -404,5 +404,5 @@ release_tests_spec: tests # $(HRL_FILES) $(ERL_FILES) \ # $(RELSYSDIR) # - chmod -f -R u+w $(RELSYSDIR) + chmod -R u+w $(RELSYSDIR) diff --git a/lib/docbuilder/src/docb_gen.erl b/lib/docbuilder/src/docb_gen.erl index 0d8d640324..75494314f1 100644 --- a/lib/docbuilder/src/docb_gen.erl +++ b/lib/docbuilder/src/docb_gen.erl @@ -18,6 +18,10 @@ -module(docb_gen). -export([module/1, module/2, users_guide/1, users_guide/2]). +-deprecated([{module,1,next_major_release}, + {module,2,next_major_release}, + {users_guide,1,next_major_release}, + {users_guide,2,next_major_release}]). -record(args, {suffix=".xml", layout=docb_edoc_xml_cb, diff --git a/lib/docbuilder/src/docb_transform.erl b/lib/docbuilder/src/docb_transform.erl index 9c7561b07b..736ac92274 100644 --- a/lib/docbuilder/src/docb_transform.erl +++ b/lib/docbuilder/src/docb_transform.erl @@ -18,6 +18,8 @@ -module(docb_transform). -export([file/1, file/2]). +-deprecated([{file,1,next_major_release}, + {file,2,next_major_release}]). %% file(File) -> ok | {error, Reason} %% file(File, Opts) -> ok | {error, Reason} diff --git a/lib/docbuilder/src/docb_xml_check.erl b/lib/docbuilder/src/docb_xml_check.erl index 8ae5cd2eac..5912e22e7b 100644 --- a/lib/docbuilder/src/docb_xml_check.erl +++ b/lib/docbuilder/src/docb_xml_check.erl @@ -18,6 +18,7 @@ -module(docb_xml_check). -export([validate/1]). +-deprecated([{validate,1,next_major_release}]). %% validate(File) -> ok | error | {error, badfile} %% File = string(), file name with or without ".xml" extension diff --git a/lib/docbuilder/vsn.mk b/lib/docbuilder/vsn.mk index 2475966ec2..6df438a537 100644 --- a/lib/docbuilder/vsn.mk +++ b/lib/docbuilder/vsn.mk @@ -1 +1 @@ -DOCB_VSN = 0.9.8.10 +DOCB_VSN = 0.9.8.11 diff --git a/lib/edoc/Makefile b/lib/edoc/Makefile index e512e390e3..1add669398 100644 --- a/lib/edoc/Makefile +++ b/lib/edoc/Makefile @@ -13,8 +13,6 @@ # Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings # AB. All Rights Reserved.'' # -# $Id$ -# include $(ERL_TOP)/make/target.mk include $(ERL_TOP)/make/$(TARGET)/otp.mk diff --git a/lib/edoc/doc/Makefile b/lib/edoc/doc/Makefile index a0f6484382..c5f68b25d0 100644 --- a/lib/edoc/doc/Makefile +++ b/lib/edoc/doc/Makefile @@ -13,8 +13,6 @@ # Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings # AB. All Rights Reserved.'' # -# $Id: Makefile,v 1.1.1.1 2004/10/04 13:53:33 richardc Exp $ -# include $(ERL_TOP)/make/target.mk include $(ERL_TOP)/make/$(TARGET)/otp.mk diff --git a/lib/edoc/doc/overview.edoc b/lib/edoc/doc/overview.edoc index bd603b7a13..fa699c6f08 100644 --- a/lib/edoc/doc/overview.edoc +++ b/lib/edoc/doc/overview.edoc @@ -1084,10 +1084,11 @@ Details: the Erlang programming language.</li> <li>`boolean()' is the subset of `atom()' consisting of the atoms `true' and `false'.</li> - <li>`char()' is a subset of - `integer()' representing character codes.</li> + <li>`char()' is the subset of `integer()' representing + Unicode character codes: hex 000000-10FFFF.</li> <li>`tuple()' is the set of all tuples `{...}'.</li> - <li>`list(T)' is just an alias for `[T]'.</li> + <li>`list(T)' is just an alias for `[T]'; list() is an alias + for `list(any())', i.e., `[any()]'.</li> <li>`nil()' is an alias for the empty list `[]'.</li> <li>`cons(H,T)' is the list constructor. This is usually not used directly. It is possible to recursively define `list(T) diff --git a/lib/edoc/doc/src/Makefile b/lib/edoc/doc/src/Makefile index 5ee0096f0f..b933094464 100644 --- a/lib/edoc/doc/src/Makefile +++ b/lib/edoc/doc/src/Makefile @@ -13,8 +13,6 @@ # Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings # AB. All Rights Reserved.'' # -# $Id$ -# include $(ERL_TOP)/make/target.mk include $(ERL_TOP)/make/$(TARGET)/otp.mk diff --git a/lib/edoc/include/Makefile b/lib/edoc/include/Makefile index 0533c27567..5b2ad38c9d 100644 --- a/lib/edoc/include/Makefile +++ b/lib/edoc/include/Makefile @@ -13,8 +13,6 @@ # Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings # AB. All Rights Reserved.'' # -# $Id$ -# include $(ERL_TOP)/make/target.mk include $(ERL_TOP)/make/$(TARGET)/otp.mk diff --git a/lib/edoc/priv/edoc_generate.src b/lib/edoc/priv/edoc_generate.src index e87fdbc902..7ec89207b0 100644 --- a/lib/edoc/priv/edoc_generate.src +++ b/lib/edoc/priv/edoc_generate.src @@ -14,9 +14,6 @@ # Portions created by Ericsson are Copyright 1999-2000, Ericsson # Utvecklings AB. All Rights Reserved.'' # -# $Id$ -# -# #EDOC_DIR=/clearcase/otp/internal_tools/edoc EDOC_DIR=/home/otp/sgml/edoc-%EDOC_VSN% diff --git a/lib/edoc/src/Makefile b/lib/edoc/src/Makefile index 9c5a9d30d1..fcb0b61292 100644 --- a/lib/edoc/src/Makefile +++ b/lib/edoc/src/Makefile @@ -23,7 +23,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/edoc-$(VSN) EBIN = ../ebin XMERL = ../../xmerl -ERL_COMPILE_FLAGS += -I../include -I$(XMERL)/include +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_deprecated_guard +ERL_COMPILE_FLAGS += -pa $(XMERL) -I../include -I$(XMERL)/include +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_deprecated_guard SOURCES= \ edoc.erl edoc_data.erl edoc_doclet.erl edoc_extract.erl \ diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl index 360f2dbc9e..a279f7dcb3 100644 --- a/lib/edoc/src/edoc.erl +++ b/lib/edoc/src/edoc.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @copyright 2001-2007 Richard Carlsson %% @author Richard Carlsson <[email protected]> %% @version {@version} @@ -60,8 +58,6 @@ -compile({no_auto_import,[error/1]}). --import(edoc_report, [report/2, report/3, error/1, error/3]). - -include("edoc.hrl"). @@ -179,8 +175,8 @@ application(App, Options) when is_atom(App) -> Dir when is_list(Dir) -> application(App, Dir, Options); _ -> - report("cannot find application directory for '~s'.", - [App]), + edoc_report:report("cannot find application directory for '~s'.", + [App]), exit(error) end. @@ -663,8 +659,8 @@ read_source(Name, Opts0) -> check_forms(Forms, Name), Forms; {error, R} -> - error({"error reading file '~s'.", - [edoc_lib:filename(Name)]}), + edoc_report:error({"error reading file '~s'.", + [edoc_lib:filename(Name)]}), exit({error, R}) end. @@ -688,11 +684,10 @@ check_forms(Fs, Name) -> error_marker -> case erl_syntax:error_marker_info(F) of {L, M, D} -> - error(L, Name, {format_error, M, D}); - + edoc_report:error(L, Name, {format_error, M, D}); Other -> - report(Name, "unknown error in " - "source code: ~w.", [Other]) + edoc_report:report(Name, "unknown error in " + "source code: ~w.", [Other]) end, exit(error); _ -> diff --git a/lib/edoc/src/edoc_data.erl b/lib/edoc/src/edoc_data.erl index 27f43dca5a..e3b5a0d51b 100644 --- a/lib/edoc/src/edoc_data.erl +++ b/lib/edoc/src/edoc_data.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @private %% @copyright 2003 Richard Carlsson %% @author Richard Carlsson <[email protected]> diff --git a/lib/edoc/src/edoc_doclet.erl b/lib/edoc/src/edoc_doclet.erl index 30eef3e63a..c66be9d7c7 100644 --- a/lib/edoc/src/edoc_doclet.erl +++ b/lib/edoc/src/edoc_doclet.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @copyright 2003-2006 Richard Carlsson %% @author Richard Carlsson <[email protected]> %% @see edoc @@ -52,7 +50,7 @@ -define(IMAGE, "erlang.png"). -define(NL, "\n"). --include("xmerl.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). %% Sources is the list of inputs in the order they were found. Packages %% and Modules are sorted lists of atoms without duplicates. (They diff --git a/lib/edoc/src/edoc_extract.erl b/lib/edoc/src/edoc_extract.erl index 5e28762c53..1209d86fe5 100644 --- a/lib/edoc/src/edoc_extract.erl +++ b/lib/edoc/src/edoc_extract.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id: $ -%% %% @copyright 2001-2003 Richard Carlsson %% @author Richard Carlsson <[email protected]> %% @see edoc @@ -238,8 +236,8 @@ file(File, Context, Env, Opts) -> case file:read_file(File) of {ok, Bin} -> {ok, text(binary_to_list(Bin), Context, Env, Opts, File)}; - {error, _R} = Error -> - Error + {error, _} = Error -> + Error end. @@ -298,8 +296,8 @@ get_module_info(Forms, File) -> {Name, Vars} = case lists:keyfind(module, 1, L) of {module, N} when is_atom(N) -> {N, none}; - {module, {N, _Vs} = NVs} when is_atom(N) -> - NVs; + {module, {N, _}=Mod} when is_atom(N) -> + Mod; _ -> report(File, "module name missing.", []), exit(error) diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl index 3ec87b7060..1c0841815f 100644 --- a/lib/edoc/src/edoc_layout.erl +++ b/lib/edoc/src/edoc_layout.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id: $ -%% %% @author Richard Carlsson <[email protected]> %% @copyright 2001-2006 Richard Carlsson %% @see edoc @@ -33,7 +31,7 @@ -import(edoc_report, [report/2]). --include("xmerl.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). -define(HTML_EXPORT, xmerl_html). -define(DEFAULT_XML_EXPORT, ?HTML_EXPORT). @@ -959,12 +957,16 @@ local_label(R) -> xhtml(Title, CSS, Body) -> [{html, [?NL, - {head, [?NL, - {title, Title}, - ?NL] ++ CSS}, - ?NL, - {body, [{bgcolor, "white"}], Body}, - ?NL] + {head, [?NL, + {meta, [{'http-equiv',"Content-Type"}, + {content, "text/html; charset=ISO-8859-1"}], + []}, + ?NL, + {title, Title}, + ?NL] ++ CSS}, + ?NL, + {body, [{bgcolor, "white"}], Body}, + ?NL] }, ?NL]. diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl index 585e30a2d2..6c698e83ef 100644 --- a/lib/edoc/src/edoc_lib.erl +++ b/lib/edoc/src/edoc_lib.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @copyright 2001-2003 Richard Carlsson %% @author Richard Carlsson <[email protected]> %% @see edoc @@ -40,7 +38,7 @@ -import(edoc_report, [report/2, warning/2]). -include("edoc.hrl"). --include("xmerl.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). -define(FILE_BASE, "/"). @@ -494,7 +492,7 @@ uri_get_file(File0) -> uri_get_http(URI) -> %% Try using option full_result=false case catch {ok, httpc:request(get, {URI,[]}, [], - [{full_result, false}])} of + [{full_result, false}])} of {'EXIT', _} -> uri_get_http_r10(URI); Result -> diff --git a/lib/edoc/src/edoc_parser.yrl b/lib/edoc/src/edoc_parser.yrl index 6943f1bdb8..3ce4cde4fb 100644 --- a/lib/edoc/src/edoc_parser.yrl +++ b/lib/edoc/src/edoc_parser.yrl @@ -23,9 +23,6 @@ %% USA %% %% Author contact: [email protected] -%% -%% $Id $ -%% %% ===================================================================== Nonterminals @@ -362,10 +359,10 @@ parse_spec(S, L) -> {ok, Spec} -> Spec; {error, E} -> - throw_error(E, L) + throw_error({parse_spec, E}, L) end; {error, E, _} -> - throw_error(E, L) + throw_error({parse_spec, E}, L) end. %% --------------------------------------------------------------------- diff --git a/lib/edoc/src/edoc_report.erl b/lib/edoc/src/edoc_report.erl index ee54c60c90..f082513bee 100644 --- a/lib/edoc/src/edoc_report.erl +++ b/lib/edoc/src/edoc_report.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @private %% @copyright 2001-2003 Richard Carlsson %% @author Richard Carlsson <[email protected]> diff --git a/lib/edoc/src/edoc_run.erl b/lib/edoc/src/edoc_run.erl index 96e5ea4631..1355db840f 100644 --- a/lib/edoc/src/edoc_run.erl +++ b/lib/edoc/src/edoc_run.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @copyright 2003 Richard Carlsson %% @author Richard Carlsson <[email protected]> %% @see edoc diff --git a/lib/edoc/src/edoc_scanner.erl b/lib/edoc/src/edoc_scanner.erl index 9d2e6f3aed..8e895ad1ad 100644 --- a/lib/edoc/src/edoc_scanner.erl +++ b/lib/edoc/src/edoc_scanner.erl @@ -13,8 +13,6 @@ %% AB. Portions created by Ericsson are Copyright 1999, Ericsson %% Utvecklings AB. All Rights Reserved.'' %% -%% $Id: $ -%% %% @private %% @copyright Richard Carlsson 2001-2003. Portions created by Ericsson %% are Copyright 1999, Ericsson Utvecklings AB. All Rights Reserved. diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl index 79a5d142bc..5acf8ac0d5 100644 --- a/lib/edoc/src/edoc_specs.erl +++ b/lib/edoc/src/edoc_specs.erl @@ -27,7 +27,6 @@ -include("edoc.hrl"). -include("edoc_types.hrl"). --type proplist() :: [proplists:property()]. -type syntaxTree() :: erl_syntax:syntaxTree(). -define(TOP_TYPE, term). @@ -87,8 +86,9 @@ dummy_spec(Form) -> #tag{name = spec, line = element(2, hd(TypeSpecs)), origin = code, data = S}. --spec docs(Forms::[syntaxTree()], CommentFun) -> dict() when - CommentFun :: fun(([syntaxTree()], Line :: term()) -> #tag{}). +-spec docs(Forms::[syntaxTree()], + CommentFun :: fun( ([syntaxTree()], Line :: term()) -> #tag{} )) + -> dict(). %% @doc Find comments after -type/-opaque declarations. %% Postcomments "inside" the type are skipped. @@ -98,7 +98,7 @@ docs(Forms, CommentFun) -> -type entry() :: #entry{}. -type module_info() :: #module{}. -type entries() :: [entry()]. --spec add_data(Entries::entries(), Options::proplist(), +-spec add_data(Entries::entries(), Options::proplists:proplist(), File::file:filename(), Module::module_info()) -> entries(). %% @doc Create tags a la EDoc for Erlang specifications and types. diff --git a/lib/edoc/src/edoc_tags.erl b/lib/edoc/src/edoc_tags.erl index 8ee8f87b5f..80989428ce 100644 --- a/lib/edoc/src/edoc_tags.erl +++ b/lib/edoc/src/edoc_tags.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @private %% @copyright 2001-2003 Richard Carlsson %% @author Richard Carlsson <[email protected]> diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl index e784b3359a..a54544868c 100644 --- a/lib/edoc/src/edoc_types.erl +++ b/lib/edoc/src/edoc_types.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @private %% @copyright 2001-2003 Richard Carlsson %% @author Richard Carlsson <[email protected]> @@ -34,13 +32,13 @@ %% @headerfile "edoc_types.hrl" -include("edoc_types.hrl"). --include("xmerl.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). is_predefined(any, 0) -> true; is_predefined(atom, 0) -> true; is_predefined(binary, 0) -> true; -is_predefined(bool, 0) -> true; +is_predefined(bool, 0) -> true; % kept for backwards compatibility is_predefined(char, 0) -> true; is_predefined(cons, 2) -> true; is_predefined(deep_string, 0) -> true; diff --git a/lib/edoc/src/edoc_wiki.erl b/lib/edoc/src/edoc_wiki.erl index ba33198787..2f2d14853c 100644 --- a/lib/edoc/src/edoc_wiki.erl +++ b/lib/edoc/src/edoc_wiki.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @private %% @copyright 2001-2003 Richard Carlsson %% @author Richard Carlsson <[email protected]> @@ -70,7 +68,7 @@ -export([parse_xml/2, expand_text/2]). -include("edoc.hrl"). --include("xmerl.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). -define(BASE_HEADING, 3). @@ -82,8 +80,8 @@ parse_xml(Data, Line) -> parse_xml_1(Text, Line) -> Text1 = "<doc>" ++ Text ++ "</doc>", - Options = [{line, Line}, {encoding, "iso-8859-1"}], - case catch {ok, xmerl_scan:string(Text1, Options)} of + Opts = [{line, Line}, {encoding, 'iso-8859-1'}], + case catch {ok, xmerl_scan:string(Text1, Opts)} of {ok, {E, _}} -> E#xmlElement.content; {'EXIT', {fatal, {Reason, L, _C}}} -> diff --git a/lib/edoc/src/otpsgml_layout.erl b/lib/edoc/src/otpsgml_layout.erl index 45f74b299e..d425dc0ed8 100644 --- a/lib/edoc/src/otpsgml_layout.erl +++ b/lib/edoc/src/otpsgml_layout.erl @@ -14,8 +14,6 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% %% @author Richard Carlsson <[email protected]> %% @author Kenneth Lundin <[email protected]> %% @copyright 2001-2004 Richard Carlsson @@ -34,7 +32,7 @@ -import(edoc_report, [report/2]). --include("xmerl.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). -define(SGML_EXPORT, xmerl_otpsgml). -define(DEFAULT_XML_EXPORT, ?SGML_EXPORT). diff --git a/lib/edoc/test/edoc_SUITE.erl b/lib/edoc/test/edoc_SUITE.erl index 0d57591e3e..5b95c35756 100644 --- a/lib/edoc/test/edoc_SUITE.erl +++ b/lib/edoc/test/edoc_SUITE.erl @@ -13,8 +13,6 @@ %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings %% AB. All Rights Reserved.'' %% -%% $Id$ -%% -module(edoc_SUITE). -include_lib("test_server/include/test_server.hrl"). diff --git a/lib/et/src/et_wx_viewer.erl b/lib/et/src/et_wx_viewer.erl index 7d4286ed9d..386f8fc86b 100644 --- a/lib/et/src/et_wx_viewer.erl +++ b/lib/et/src/et_wx_viewer.erl @@ -257,10 +257,10 @@ parse_opt([H | T], S, CollectorOpt) -> Actors = [create_actor(Name) || Name <- ActorNames2], parse_opt(T, S#state{actors = Actors}, CollectorOpt); {include, ActorNames} when is_list(ActorNames) -> - Actors = [opt_create_actor(Name, include, S#state.actors) || Name <- ActorNames], + Actors = [opt_create_actor(Name, include, S) || Name <- ActorNames], parse_opt(T, S#state{actors = Actors}, CollectorOpt); {exclude, ActorNames} when is_list(ActorNames) -> - Actors = [opt_create_actor(Name, exclude, S#state.actors) || Name <- ActorNames], + Actors = [opt_create_actor(Name, exclude, S) || Name <- ActorNames], parse_opt(T, S#state{actors = Actors}, CollectorOpt); {first_event, _FirstKey} -> %% NYI diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc index be05a13fba..2583f0be25 100644 --- a/lib/eunit/doc/overview.edoc +++ b/lib/eunit/doc/overview.edoc @@ -913,7 +913,7 @@ To make the descriptions simpler, we first list some definitions: <td>`CleanupX'</td><td>`(X::any(), R::any()) -> any()'</td> </tr> <tr> -<td>`Instantiator'</td><td>`((R::any()) -> Tests | {with, [AbstractTestFun::((any()) -> any())]}'</td> +<td>`Instantiator'</td><td>`((R::any()) -> Tests) | {with, [AbstractTestFun::((any()) -> any())]}'</td> </tr> <tr> <td>`Where'</td><td>`local | spawn | {spawn, Node::atom()}'</td> diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl index 82ba982f03..493ba60a2d 100644 --- a/lib/eunit/include/eunit.hrl +++ b/lib/eunit/include/eunit.hrl @@ -39,6 +39,7 @@ -ifndef(EUNIT_HRL). -define(EUNIT_HRL, true). + %% allow defining TEST to override NOTEST -ifdef(TEST). -undef(NOTEST). @@ -164,7 +165,7 @@ %% This is mostly a convenience which gives more detailed reports. %% Note: Guard is a guarded pattern, and can not be used for value. -ifdef(NOASSERT). --define(assertMatch(Guard,Expr),ok). +-define(assertMatch(Guard, Expr), ok). -else. -define(assertMatch(Guard, Expr), ((fun () -> @@ -174,17 +175,37 @@ [{module, ?MODULE}, {line, ?LINE}, {expression, (??Expr)}, - {expected, (??Guard)}, + {pattern, (??Guard)}, {value, __V}]}) end end)())). -endif. -define(_assertMatch(Guard, Expr), ?_test(?assertMatch(Guard, Expr))). +%% This is the inverse case of assertMatch, for convenience. +-ifdef(NOASSERT). +-define(assertNotMatch(Guard, Expr), ok). +-else. +-define(assertNotMatch(Guard, Expr), + ((fun () -> + __V = (Expr), + case __V of + Guard -> .erlang:error({assertNotMatch_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??Expr)}, + {pattern, (??Guard)}, + {value, __V}]}); + _ -> ok + end + end)())). +-endif. +-define(_assertNotMatch(Guard, Expr), ?_test(?assertNotMatch(Guard, Expr))). + %% This is a convenience macro which gives more detailed reports when %% the expected LHS value is not a pattern, but a computed value -ifdef(NOASSERT). --define(assertEqual(Expect,Expr),ok). +-define(assertEqual(Expect, Expr), ok). -else. -define(assertEqual(Expect, Expr), ((fun (__X) -> @@ -201,9 +222,29 @@ -endif. -define(_assertEqual(Expect, Expr), ?_test(?assertEqual(Expect, Expr))). +%% This is the inverse case of assertEqual, for convenience. +-ifdef(NOASSERT). +-define(assertNotEqual(Unexpected, Expr), ok). +-else. +-define(assertNotEqual(Unexpected, Expr), + ((fun (__X) -> + case (Expr) of + __X -> .erlang:error({assertNotEqual_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??Expr)}, + {value, __X}]}); + _ -> ok + end + end)(Unexpected))). +-endif. +-define(_assertNotEqual(Unexpected, Expr), + ?_test(?assertNotEqual(Unexpected, Expr))). + %% Note: Class and Term are patterns, and can not be used for value. +%% Term can be a guarded pattern, but Class cannot. -ifdef(NOASSERT). --define(assertException(Class, Term, Expr),ok). +-define(assertException(Class, Term, Expr), ok). -else. -define(assertException(Class, Term, Expr), ((fun () -> @@ -212,7 +253,7 @@ [{module, ?MODULE}, {line, ?LINE}, {expression, (??Expr)}, - {expected, + {pattern, "{ "++(??Class)++" , "++(??Term) ++" , [...] }"}, {unexpected_success, __V}]}) @@ -223,7 +264,7 @@ [{module, ?MODULE}, {line, ?LINE}, {expression, (??Expr)}, - {expected, + {pattern, "{ "++(??Class)++" , "++(??Term) ++" , [...] }"}, {unexpected_exception, @@ -243,6 +284,43 @@ -define(_assertExit(Term, Expr), ?_assertException(exit, Term, Expr)). -define(_assertThrow(Term, Expr), ?_assertException(throw, Term, Expr)). +%% This is the inverse case of assertException, for convenience. +%% Note: Class and Term are patterns, and can not be used for value. +%% Both Class and Term can be guarded patterns. +-ifdef(NOASSERT). +-define(assertNotException(Class, Term, Expr), ok). +-else. +-define(assertNotException(Class, Term, Expr), + ((fun () -> + try (Expr) of + _ -> ok + catch + __C:__T -> + case __C of + Class -> + case __T of + Term -> + .erlang:error({assertNotException_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??Expr)}, + {pattern, + "{ "++(??Class)++" , " + ++(??Term)++" , [...] }"}, + {unexpected_exception, + {__C, __T, + .erlang:get_stacktrace() + }}]}); + _ -> ok + end; + _ -> ok + end + end + end)())). +-endif. +-define(_assertNotException(Class, Term, Expr), + ?_test(?assertNotException(Class, Term, Expr))). + %% Macros for running operating system commands. (Note that these %% require EUnit to be present at runtime, or at least eunit_lib.) @@ -267,7 +345,7 @@ %% these are only used for testing; they always return 'ok' on success, %% and have no effect if debugging/testing is turned off -ifdef(NOASSERT). --define(assertCmdStatus(N, Cmd),ok). +-define(assertCmdStatus(N, Cmd), ok). -else. -define(assertCmdStatus(N, Cmd), ((fun () -> @@ -285,7 +363,7 @@ -define(assertCmd(Cmd), ?assertCmdStatus(0, Cmd)). -ifdef(NOASSERT). --define(assertCmdOutput(T, Cmd),ok). +-define(assertCmdOutput(T, Cmd), ok). -else. -define(assertCmdOutput(T, Cmd), ((fun () -> @@ -313,11 +391,12 @@ -define(debugHere, ok). -define(debugFmt(S, As), ok). -define(debugVal(E), (E)). --define(debugTime(S,E), (E)). +-define(debugTime(S, E), (E)). -else. -define(debugMsg(S), (begin - .io:fwrite(user, <<"~s:~w: ~s\n">>, [?FILE, ?LINE, S]), + .io:fwrite(user, <<"~s:~w:~w: ~s\n">>, + [?FILE, ?LINE, self(), S]), ok end)). -define(debugHere, (?debugMsg("<-"))). @@ -327,7 +406,7 @@ ?debugFmt(<<"~s = ~P">>, [(??E), __V, 15]), __V end)(E))). --define(debugTime(S,E), +-define(debugTime(S, E), ((fun () -> {__T0, _} = statistics(wall_clock), __V = (E), @@ -337,4 +416,5 @@ end)())). -endif. + -endif. % EUNIT_HRL diff --git a/lib/eunit/src/eunit.app.src b/lib/eunit/src/eunit.app.src index 4fd76588c3..5e16dfa2ce 100644 --- a/lib/eunit/src/eunit.app.src +++ b/lib/eunit/src/eunit.app.src @@ -5,17 +5,17 @@ {vsn, "%VSN%"}, {modules, [eunit, eunit_autoexport, - eunit_striptests, - eunit_server, + eunit_data, + eunit_lib, + eunit_listener, eunit_proc, eunit_serial, + eunit_server, + eunit_striptests, + eunit_surefire, eunit_test, eunit_tests, - eunit_lib, - eunit_listener, - eunit_data, - eunit_tty, - eunit_surefire]}, + eunit_tty]}, {registered,[]}, - {applications, [stdlib]}, + {applications, [kernel,stdlib]}, {env, []}]}. diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl index da35c5c2ec..15fc3bdf32 100644 --- a/lib/eunit/src/eunit.erl +++ b/lib/eunit/src/eunit.erl @@ -16,7 +16,7 @@ %% $Id: eunit.erl 339 2009-04-05 14:10:47Z rcarlsson $ %% %% @copyright 2004-2009 Micka�l R�mond, Richard Carlsson -%% @author Mickaël Rémond <[email protected]> +%% @author Micka�l R�mond <[email protected]> %% [http://www.process-one.net/] %% @author Richard Carlsson <[email protected]> %% [http://user.it.uu.se/~richardc/] diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl index 0543b6c543..288dd74ddf 100644 --- a/lib/eunit/src/eunit_data.erl +++ b/lib/eunit/src/eunit_data.erl @@ -146,8 +146,10 @@ iter_next(I = #iter{next = [T | Ts]}) -> iter_prev(#iter{prev = []}) -> none; -iter_prev(#iter{prev = [T | Ts], next = Next, pos = Pos} = I) -> - {T, I#iter{prev = Ts, next = [T | Next], pos = Pos - 1}}. +iter_prev(#iter{prev = [T | Ts]} = I) -> + {T, I#iter{prev = Ts, + next = [T | I#iter.next], + pos = I#iter.pos - 1}}. %% --------------------------------------------------------------------- @@ -363,7 +365,8 @@ parse({file, F} = T) when is_list(F) -> parse({dir, D}=T) when is_list(D) -> case eunit_lib:is_string(D) of true -> - {data, {"directory \"" ++ D ++ "\"", get_directory_modules(D)}}; + {data, {"directory \"" ++ D ++ "\"", + get_directory_module_tests(D)}}; false -> bad_test(T) end; @@ -385,10 +388,10 @@ parse({S, T1} = T) when is_list(S) -> end; parse({S, T1}) when is_binary(S) -> group(#group{tests = T1, desc = S}); -parse(T) when tuple_size(T) > 2, is_list(element(1, T)) -> +parse(T) when is_tuple(T), size(T) > 2, is_list(element(1, T)) -> [S | Es] = tuple_to_list(T), parse({S, list_to_tuple(Es)}); -parse(T) when tuple_size(T) > 2, is_binary(element(1, T)) -> +parse(T) when is_tuple(T), size(T) > 2, is_binary(element(1, T)) -> [S | Es] = tuple_to_list(T), parse({S, list_to_tuple(Es)}); parse(M) when is_atom(M) -> @@ -596,7 +599,7 @@ testfuns(Es, M, TestSuffix, GeneratorSuffix) -> %% --------------------------------------------------------------------- -%% Getting a test set from a file +%% Getting a test set from a file (text file or object file) %% @throws {file_read_error, {Reason::atom(), Message::string(), %% fileName()}} @@ -625,17 +628,23 @@ get_file_tests(F) -> is_module_filename(F) -> filename:extension(F) =:= code:objfile_extension(). +objfile_test({M, File}) -> + {setup, + fun () -> + %% TODO: better error/stacktrace for this internal fun + code:purge(M), + {module,M} = code:load_abs(filename:rootname(File)), + ok + end, + {module, M}}; objfile_test(File) -> + objfile_test({objfile_module(File), File}). + +objfile_module(File) -> try - {module, M} = lists:keyfind(module, 1, beam_lib:info(File)), - {setup, - fun () -> - %% TODO: better error/stacktrace for this internal fun - code:purge(M), - {module,M} = code:load_abs(filename:rootname(File)), - ok - end, - {module, M}} + {value, {module, M}} = lists:keysearch(module, 1, + beam_lib:info(File)), + M catch _:_ -> throw({file_read_error, @@ -644,15 +653,34 @@ objfile_test(File) -> %% --------------------------------------------------------------------- -%% Getting a list of module names from object files in a directory - -%% @throws {file_read_error, {Reason::atom(), Message::string(), -%% fileName()}} +%% Getting a set of module tests from the object files in a directory + +%% @throws {file_read_error, +%% {Reason::atom(), Message::string(), fileName()}} + +get_directory_module_tests(D) -> + Ms = get_directory_modules(D), + %% for all 'm' in the set, remove 'm_tests' if present + F = fun ({M,_}, S) -> + Name = atom_to_list(M), + case lists:suffix(?DEFAULT_TESTMODULE_SUFFIX, Name) of + false -> + Name1 = Name ++ ?DEFAULT_TESTMODULE_SUFFIX, + M1 = list_to_atom(Name1), + dict:erase(M1, S); + true -> + S + end + end, + [objfile_test(Obj) + || Obj <- dict:to_list(lists:foldl(F, dict:from_list(Ms), Ms))]. %% TODO: handle packages (recursive search for files) - get_directory_modules(D) -> - [objfile_test(filename:join(D, F)) + [begin + F1 = filename:join(D, F), + {objfile_module(F1), F1} + end || F <- eunit_lib:list_dir(D), is_module_filename(F)]. diff --git a/lib/eunit/src/eunit_server.erl b/lib/eunit/src/eunit_server.erl index bf1bb9bcef..2cdfef2668 100644 --- a/lib/eunit/src/eunit_server.erl +++ b/lib/eunit/src/eunit_server.erl @@ -59,8 +59,9 @@ watch(Server, Module, Opts) when is_atom(Module) -> watch_path(Server, Path, Opts) -> command(Server, {watch, {path, filename:flatten(Path)}, Opts}). +%% note that the user must use $ at the end to match whole paths only watch_regexp(Server, Regex, Opts) -> - case regexp:parse(Regex) of + case re:compile(Regex,[anchored]) of {ok, R} -> command(Server, {watch, {regexp, R}, Opts}); {error, _}=Error -> @@ -278,8 +279,8 @@ is_watched(Path, St) -> match_any(sets:to_list(St#state.regexps), Path). match_any([R | Rs], Str) -> - case regexp:first_match(Str, R) of - {match, _, _} -> true; + case re:run(Str, R, [{capture,none}]) of + match -> true; _ -> match_any(Rs, Str) end; match_any([], _Str) -> false. diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl index dfb08c90b2..6e0a447105 100644 --- a/lib/eunit/src/eunit_surefire.erl +++ b/lib/eunit/src/eunit_surefire.erl @@ -15,7 +15,7 @@ %% %% $Id: $ %% -%% @author Mickaël Rémond <[email protected]> +%% @author Micka�l R�mond <[email protected]> %% @copyright 2009 Micka�l R�mond, Paul Guyot %% @see eunit %% @doc Surefire reports for EUnit (Format used by Maven and Atlassian @@ -64,6 +64,7 @@ }). -record(testsuite, { + id = 0 :: integer(), name = <<>> :: binary(), time = 0 :: integer(), output = <<>> :: binary(), @@ -76,7 +77,7 @@ -record(state, {verbose = false, indent = 0, xmldir = ".", - testsuite = #testsuite{} + testsuites = [] :: [#testsuite{}] }). start() -> @@ -89,55 +90,60 @@ init(Options) -> XMLDir = proplists:get_value(dir, Options, ?XMLDIR), St = #state{verbose = proplists:get_bool(verbose, Options), xmldir = XMLDir, - testsuite = #testsuite{}}, + testsuites = []}, receive {start, _Reference} -> St end. terminate({ok, _Data}, St) -> - TestSuite = St#state.testsuite, + TestSuites = St#state.testsuites, XmlDir = St#state.xmldir, - write_report(TestSuite, XmlDir), + write_reports(TestSuites, XmlDir), ok; terminate({error, _Reason}, _St) -> %% Don't report any errors here, since eunit_tty takes care of that. %% Just terminate. ok. -handle_begin(group, Data, St) -> +handle_begin(Kind, Data, St) when Kind == group; Kind == test -> + %% Run this code both for groups and tests; test is a bit + %% surprising: This is a workaround for the fact that we don't get + %% a group (handle_begin(group, ...) for testsuites (modules) + %% which only have one test case. In that case we get a test case + %% with an id comprised of just one integer - the group id. NewId = proplists:get_value(id, Data), case NewId of [] -> St; - [_GroupId] -> + [GroupId] -> Desc = proplists:get_value(desc, Data), - TestSuite = St#state.testsuite, - NewTestSuite = TestSuite#testsuite{name = Desc}, - St#state{testsuite=NewTestSuite}; + TestSuite = #testsuite{id = GroupId, name = Desc}, + St#state{testsuites=store_suite(TestSuite, St#state.testsuites)}; %% Surefire format is not hierarchic: Ignore subgroups: _ -> St - end; -handle_begin(test, _Data, St) -> - St. + end. handle_end(group, Data, St) -> %% Retrieve existing test suite: case proplists:get_value(id, Data) of [] -> St; - [_GroupId|_] -> - TestSuite = St#state.testsuite, + [GroupId|_] -> + TestSuites = St#state.testsuites, + TestSuite = lookup_suite_by_group_id(GroupId, TestSuites), %% Update TestSuite data: Time = proplists:get_value(time, Data), Output = proplists:get_value(output, Data), NewTestSuite = TestSuite#testsuite{ time = Time, output = Output }, - St#state{testsuite=NewTestSuite} + St#state{testsuites=store_suite(NewTestSuite, TestSuites)} end; handle_end(test, Data, St) -> %% Retrieve existing test suite: - TestSuite = St#state.testsuite, + [GroupId|_] = proplists:get_value(id, Data), + TestSuites = St#state.testsuites, + TestSuite = lookup_suite_by_group_id(GroupId, TestSuites), %% Create test case: Name = format_name(proplists:get_value(source, Data), @@ -149,7 +155,7 @@ handle_end(test, Data, St) -> TestCase = #testcase{name = Name, description = Desc, time = Time,output = Output}, NewTestSuite = add_testcase_to_testsuite(Result, TestCase, TestSuite), - St#state{testsuite=NewTestSuite}. + St#state{testsuites=store_suite(NewTestSuite, TestSuites)}. %% Cancel group does not give information on the individual cancelled test case %% We ignore this event @@ -157,7 +163,9 @@ handle_cancel(group, _Data, St) -> St; handle_cancel(test, Data, St) -> %% Retrieve existing test suite: - TestSuite = St#state.testsuite, + [GroupId|_] = proplists:get_value(id, Data), + TestSuites = St#state.testsuites, + TestSuite = lookup_suite_by_group_id(GroupId, TestSuites), %% Create test case: Name = format_name(proplists:get_value(source, Data), @@ -171,7 +179,7 @@ handle_cancel(test, Data, St) -> NewTestSuite = TestSuite#testsuite{ skipped = TestSuite#testsuite.skipped+1, testcases=[TestCase|TestSuite#testsuite.testcases] }, - St#state{testsuite=NewTestSuite}. + St#state{testsuites=store_suite(NewTestSuite, TestSuites)}. format_name({Module, Function, Arity}, Line) -> lists:flatten([atom_to_list(Module), ":", atom_to_list(Function), "/", @@ -183,6 +191,12 @@ format_desc(Desc) when is_binary(Desc) -> format_desc(Desc) when is_list(Desc) -> Desc. +lookup_suite_by_group_id(GroupId, TestSuites) -> + #testsuite{} = lists:keyfind(GroupId, #testsuite.id, TestSuites). + +store_suite(#testsuite{id=GroupId} = TestSuite, TestSuites) -> + lists:keystore(GroupId, #testsuite.id, TestSuites, TestSuite). + %% Add testcase to testsuite depending on the result of the test. add_testcase_to_testsuite(ok, TestCaseTmp, TestSuite) -> TestCase = TestCaseTmp#testcase{ result = ok }, @@ -214,6 +228,10 @@ add_testcase_to_testsuite({error, Exception}, TestCaseTmp, TestSuite) -> %% Write a report to the XML directory. %% This function opens the report file, calls write_report_to/2 and closes the file. %% ---------------------------------------------------------------------------- +write_reports(TestSuites, XmlDir) -> + lists:foreach(fun(TestSuite) -> write_report(TestSuite, XmlDir) end, + TestSuites). + write_report(#testsuite{name = Name} = TestSuite, XmlDir) -> Filename = filename:join(XmlDir, lists:flatten(["TEST-", escape_suitename(Name)], ".xml")), case file:open(Filename, [write, raw]) of diff --git a/lib/eunit/src/eunit_test.erl b/lib/eunit/src/eunit_test.erl index d322c4b420..9ac1d1e7d9 100644 --- a/lib/eunit/src/eunit_test.erl +++ b/lib/eunit/src/eunit_test.erl @@ -131,12 +131,27 @@ macro_test_() -> [{module,_}, {line,_}, {expression,_}, - {expected,"[ _ ]"}, + {pattern,"[ _ ]"}, {value,[]}]}, _}} = run_testfun(F) end), ?_test(begin + {?LINE, F} = ?_assertNotMatch(ok, error), + {ok, ok} = run_testfun(F) + end), + ?_test(begin + {?LINE, F} = ?_assertNotMatch([_], [42]), + {error,{error,{assertNotMatch_failed, + [{module,_}, + {line,_}, + {expression,_}, + {pattern,"[ _ ]"}, + {value,[42]}]}, + _}} + = run_testfun(F) + end), + ?_test(begin {?LINE, F} = ?_assertEqual(ok, ok), {ok, ok} = run_testfun(F) end), @@ -152,6 +167,20 @@ macro_test_() -> = run_testfun(F) end), ?_test(begin + {?LINE, F} = ?_assertNotEqual(1, 0), + {ok, ok} = run_testfun(F) + end), + ?_test(begin + {?LINE, F} = ?_assertNotEqual(2, 1+1), + {error,{error,{assertNotEqual_failed, + [{module,_}, + {line,_}, + {expression,_}, + {value,2}]}, + _}} + = run_testfun(F) + end), + ?_test(begin {?LINE, F} = ?_assertException(error, badarith, erlang:error(badarith)), {ok, ok} = run_testfun(F) @@ -162,7 +191,7 @@ macro_test_() -> [{module,_}, {line,_}, {expression,_}, - {expected,_}, + {pattern,_}, {unexpected_success,ok}]}, _}} = run_testfun(F) @@ -174,15 +203,48 @@ macro_test_() -> [{module,_}, {line,_}, {expression,_}, - {expected,_}, + {pattern,_}, + {unexpected_exception, + {error,badarith,_}}]}, + _}} + = run_testfun(F) + end), + ?_test(begin + {?LINE, F} = ?_assertError(badarith, + erlang:error(badarith)), + {ok, ok} = run_testfun(F) + end), + ?_test(begin + {?LINE, F} = ?_assertExit(normal, exit(normal)), + {ok, ok} = run_testfun(F) + end), + ?_test(begin + {?LINE, F} = ?_assertThrow(foo, throw(foo)), + {ok, ok} = run_testfun(F) + end), + ?_test(begin + {?LINE, F} = ?_assertNotException(error, badarith, 42), + {ok, ok} = run_testfun(F) + end), + ?_test(begin + {?LINE, F} = ?_assertNotException(error, badarith, + erlang:error(badarg)), + {ok, ok} = run_testfun(F) + end), + ?_test(begin + {?LINE, F} = ?_assertNotException(error, badarith, + erlang:error(badarith)), + {error,{error,{assertNotException_failed, + [{module,_}, + {line,_}, + {expression,_}, + {pattern,_}, {unexpected_exception, {error,badarith,_}}]}, _}} = run_testfun(F) end) ]}. - -under_eunit_test() -> ?assert(?UNDER_EUNIT). -endif. diff --git a/lib/eunit/src/eunit_tests.erl b/lib/eunit/src/eunit_tests.erl index 37c0b4d6ae..a63d102d98 100644 --- a/lib/eunit/src/eunit_tests.erl +++ b/lib/eunit/src/eunit_tests.erl @@ -26,17 +26,17 @@ -include("eunit.hrl"). -ifdef(TEST). -%% Cause all the other modules to be tested as well as this one. -full_test_() -> - %%{application, eunit}. % this currently causes a loop - %% We use the below until loop detection is implemented - [eunit_autoexport, - eunit_striptests, - eunit_server, - eunit_proc, - eunit_serial, - eunit_test, - eunit_lib, - eunit_data, - eunit_tty]. +id(X) -> X. % for suppressing compiler warnings -endif. + +under_eunit_test() -> ?assert(?UNDER_EUNIT). + +let_test() -> ?assertEqual(42, ?LET(X, 17, X+25)). + +if_test_() -> + [?_assertEqual(17, ?IF(id(1) > 0, 17, 42)), + ?_assertEqual(42, ?IF(id(1) < 0, 17, 42))]. + +matches_test_() -> + [?_assert(?MATCHES("hel"++_, "hello")), + ?_assertNot(?MATCHES("hal"++_, "hello"))]. diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk index d7edd7977b..d933085bbc 100644 --- a/lib/eunit/vsn.mk +++ b/lib/eunit/vsn.mk @@ -1 +1 @@ -EUNIT_VSN = 2.1.7 +EUNIT_VSN = 2.2.0 diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index f1be658054..82e3675938 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -672,6 +672,9 @@ type(erlang, call_on_load_function, 1, Xs) -> type(erlang, cancel_timer, 1, Xs) -> strict(arg_types(erlang, cancel_timer, 1), Xs, fun (_) -> t_sup(t_integer(), t_atom('false')) end); +type(erlang, check_old_code, 1, Xs) -> + strict(arg_types(erlang, check_old_code, 1), Xs, + fun (_) -> t_boolean() end); type(erlang, check_process_code, 2, Xs) -> strict(arg_types(erlang, check_process_code, 2), Xs, fun (_) -> t_boolean() end); @@ -3395,6 +3398,8 @@ arg_types(erlang, call_on_load_function, 1) -> [t_atom()]; arg_types(erlang, cancel_timer, 1) -> [t_reference()]; +arg_types(erlang, check_old_code, 1) -> + [t_atom()]; arg_types(erlang, check_process_code, 2) -> [t_pid(), t_atom()]; arg_types(erlang, concat_binary, 1) -> diff --git a/lib/hipe/main/hipe.hrl.src b/lib/hipe/main/hipe.hrl.src index a1fbeda9cf..ec55c707ef 100644 --- a/lib/hipe/main/hipe.hrl.src +++ b/lib/hipe/main/hipe.hrl.src @@ -50,9 +50,8 @@ %% Flags: %% DEBUG - Turns on debugging. (Can be defined to a integer %% value to determine the level of debugging) -%% VERBOSE - More info is printed... %% HIPE_LOGGING - Turn on logging of messages with erl_logger. -%% DO_ASSERT - Turn on Assertions. +%% DO_ASSERT - Turn on assertions. %% TIMING - Turn on timing. %% HIPE_INSTRUMENT_COMPILER - Turn on instrumentation of the compiler. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -107,13 +106,9 @@ %% %% Define the exit macro %% --ifdef(VERBOSE). --define(EXIT(Reason), erlang:error({?MODULE,?LINE,Reason})). --else. -define(EXIT(Reason), ?msg("EXITED with reason ~w @~w:~w\n", [Reason,?MODULE,?LINE]), erlang:error({?MODULE,?LINE,Reason})). --endif. %% %% Assertions. diff --git a/lib/ic/doc/src/notes.xml b/lib/ic/doc/src/notes.xml index 5f6c31069c..de519d5f84 100644 --- a/lib/ic/doc/src/notes.xml +++ b/lib/ic/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1998</year><year>2010</year> + <year>1998</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -31,6 +31,22 @@ </header> <section> + <title>IC 4.2.27</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p> + Reduced compile overhead (Thanks to Haitao Li).</p> + <p> + Own Id: OTP-9460 </p> + </item> + </list> + </section> + </section> + + <section> <title>IC 4.2.26</title> <section> diff --git a/lib/ic/src/ic_pp.erl b/lib/ic/src/ic_pp.erl index db06118d32..8b53473caa 100644 --- a/lib/ic/src/ic_pp.erl +++ b/lib/ic/src/ic_pp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -92,6 +92,14 @@ %% %%====================================================================================== +%% Multiple Include Optimization +%% +%% Algorithm described at: +%% http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html +-record(mio, {valid = true, %% multiple include valid + cmacro, %% controlling macro of the current conditional directive + depth = 0, %% conditional directive depth + included = []}). @@ -130,7 +138,7 @@ run(FileList, FileName, IncDir, Flags) -> %%---------------------------------------------------------- %% Run the second phase, i.e expand macros %%---------------------------------------------------------- - {Out, Err, War, _Defs, IfCou} = expand(File, FileName, IncDir, Flags), + {Out, Err, War, _Defs, _Mio, IfCou} = expand(File, FileName, IncDir, Flags), %%---------------------------------------------------------- %% Check if all #if #ifdef #ifndef have a matching #endif @@ -155,9 +163,9 @@ run(FileList, FileName, IncDir, Flags) -> %% The entry for all included files %% %% -%% Output {Out, Defs, Err, War} +%% Output {Out, Err, War, Defs, MultipleIncludeValid} %%====================================================================================== -run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir) -> +run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir, Mio) -> %%---------------------------------------------------------- %% Run the first phase, i.e tokenise the file @@ -169,18 +177,21 @@ run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir) %%---------------------------------------------------------- %% Run the second phase, i.e expand macros %%---------------------------------------------------------- - - %% Try first pass without file info start/end - {OutT, ErrT, WarT, DefsT, IfCouT} = - expand(File, Defs, Err, War, [FileName|IncFile], IncDir), - - {Out2, Err2, War2, Defs2, IfCou2} = - case only_nls(OutT) of - true -> %% The file is defined before - {["\n"], ErrT, WarT, DefsT, IfCouT}; - false -> %% The file is not defined before, try second pass - expand([FileInfoStart|File]++FileInfoEnd, Defs, Err, War, [FileName|IncFile], IncDir) - end, + {Out2, Err2, War2, Defs2, Mio2, IfCou2} = + expand([FileInfoStart|File]++FileInfoEnd, Defs, Err, War, + [FileName|IncFile], IncDir, + #mio{included=Mio#mio.included}), + + MergeIncluded = sets:to_list(sets:from_list(Mio#mio.included ++ Mio2#mio.included)), + + Mio3 = + case {Mio2#mio.valid, Mio2#mio.cmacro} of + {V, Macro} when V == false; + Macro == undefined -> + update_mio(Mio#mio{included=MergeIncluded}); + {true, _} -> + update_mio({include, FileName}, Mio#mio{included=MergeIncluded}) + end, %%---------------------------------------------------------- %% Check if all #if #ifdef #ifndef have a matching #endif @@ -192,26 +203,7 @@ run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir) [] end, - {Out2, Defs2, Err2++IfError, War2}. - - - -%% Return true if there is no data -%% other than new lines -only_nls([]) -> - true; -only_nls(["\n"|Rem]) -> - only_nls(Rem); -only_nls(["\r","\n"|Rem]) -> - only_nls(Rem); -only_nls([_|_Rem]) -> - false. - - - - - - + {Out2, Defs2, Err2++IfError, War2, Mio3}. @@ -647,87 +639,86 @@ expand(List, FileName, IncDir, Flags) -> %% Get all definitions from preprocessor commnads %% and merge them on top of the file collected. CLDefs = get_cmd_line_defs(Flags), - expand(List, [], [], CLDefs, [FileName], IncDir, check_all, [], [], 1, FileName). - -expand(List, Defs, Err, War, [FileName|IncFile], IncDir) -> - expand(List, [], [], Defs, [FileName|IncFile], IncDir, check_all, Err, War, 1, FileName). + expand(List, [], [], CLDefs, [FileName], IncDir, #mio{}, check_all, [], [], 1, FileName). +expand(List, Defs, Err, War, [FileName|IncFile], IncDir, Mio) -> + expand(List, [], [], Defs, [FileName|IncFile], IncDir, Mio, check_all, Err, War, 1, FileName). %%======================================================= %% Main loop for the expansion %%======================================================= -expand([], Out, _SelfRef, Defs, _IncFile, _IncDir, IfCou, Err, War, _L, _FN) -> +expand([], Out, _SelfRef, Defs, _IncFile, _IncDir, Mio, IfCou, Err, War, _L, _FN) -> % io:format("~n ===============~n"), % io:format(" definitions ~p~n",[lists:reverse(Defs)]), % io:format(" found warnings ~p~n",[lists:reverse(War)]), % io:format(" found errors ~p~n",[lists:reverse(Err)]), % io:format(" ===============~n~n~n"), - {Out, Err, War, Defs, IfCou}; + {Out, Err, War, Defs, Mio, IfCou}; -expand([{file_info, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> - expand(Rem, Str++Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); +expand([{file_info, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> + expand(Rem, Str++Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN); %%--------------------------------------- %% Searching for endif, %% i.e skip all source lines until matching %% end if is encountered %%--------------------------------------- -expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) +expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) when Command == "ifdef" -> {_Removed, Rem2, _Nl} = read_to_nl(Rem), IfCou2 = {endif, Endif+1, IfLine}, - expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L, FN); + expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN); -expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) +expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) when Command == "ifndef" -> {_Removed, Rem2, _Nl} = read_to_nl(Rem), IfCou2 = {endif, Endif+1, IfLine}, - expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L, FN); + expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN); -expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) +expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) when Command == "if" -> - case pp_command(Command, Rem, Defs, IncDir, Err, War, L, FN) of + case pp_command(Command, Rem, Defs, IncDir, Mio, Err, War, L, FN) of {{'if', true}, Rem2, Err2, War2, Nl} -> IfCou2 = {endif, Endif+1, IfLine}, - expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN); + expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN); %% {{'if', false}, Rem2, Err2, War2, Nl} -> Not implemented yet {{'if', error}, Rem2, Err2, War2, Nl} -> IfCou2 = {endif, Endif, IfLine}, - expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN) + expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN) end; -expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) +expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) when Command == "endif" -> {_Removed, Rem2, Nl} = read_to_nl(Rem), case Endif of 1 -> - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L+Nl, FN); _ -> IfCou2 = {endif, Endif-1, IfLine}, - expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L+Nl, FN) + expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L+Nl, FN) end; -expand([{command,_Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) -> +expand([{command,_Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) -> {_Removed, Rem2, _Nl} = read_to_nl(Rem), IfCou2 = {endif, Endif, IfLine}, - expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L, FN); + expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN); %% Solves a bug when spaces in front of hashmark ! -expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) -> - expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN); +expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) -> + expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN); -expand([{nl,_Nl} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) -> - expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN); +expand([{nl,_Nl} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) -> + expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN); -expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) -> +expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) -> {_Removed, Rem2, Nl} = read_to_nl(Rem), - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN); @@ -736,121 +727,132 @@ expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, %%--------------------------------------- %% Check all tokens %%--------------------------------------- -expand([{nl, _N} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> - expand(Rem, [$\n | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L+1, FN); +expand([{nl, _N} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> + expand(Rem, [$\n | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L+1, FN); -expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> - expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); +expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> + expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN); -expand([space_exp | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> - expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); +expand([space_exp | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> + expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN); -expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L, FN) -> - case pp_command(Command, Rem, Defs, IncDir, Err, War, L, FN) of +expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L, FN) -> + case pp_command(Command, Rem, Defs, IncDir, Mio, Err, War, L, FN) of {define, Rem2, Defs2, Err2, War2, Nl} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN); {undef, Rem2, Defs2, Err2, War2, Nl} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN); {{include, ok}, FileName, FileCont, Rem2, Nl, Err2, War2} -> - {Out3, Defs3, Err3, War3} = - run_include(FileName, FileCont, Out, Defs, Err2, War2, L+Nl, IncFile, IncDir), + {Out3, Defs3, Err3, War3, Mio2} = + run_include(FileName, FileCont, Out, Defs, Err2, War2, L+Nl, IncFile, IncDir, Mio), Nls = [], Out4 = Out3++Nls++Out, - expand(Rem2, Out4, SelfRef, Defs3, IncFile, IncDir, check_all, Err3, War3, L+Nl, FN); + expand(Rem2, Out4, SelfRef, Defs3, IncFile, IncDir, Mio2, check_all, Err3, War3, L+Nl, FN); {{include, error}, Rem2, Nl, Err2, War2} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN); + + {{include, skip}, Rem2} -> + Out2 = [$\n|Out], + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+1, FN); {{ifdef, true}, Rem2, Err2, War2, Nl} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], + Out2 = lists:duplicate(Nl,$\n) ++ Out, IfCou2 = {endif, 1, L}, - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN); + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN); {{ifdef, false}, Rem2, Err2, War2, Nl} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + Mio2 = update_mio(ifdef, Mio), + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN); {{ifndef, true}, Rem2, Err2, War2, Nl} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], + Out2 = lists:duplicate(Nl,$\n) ++ Out, IfCou2 = {endif, 1, L}, - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN); - {{ifndef, false}, Rem2, Err2, War2, Nl} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN); + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN); + {{ifndef, false}, Macro, Rem2, Err2, War2, Nl} -> + Out2 = lists:duplicate(Nl,$\n) ++ Out, + Mio2 = update_mio({ifndef, Macro}, Mio), + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN); {endif, Rem2, Err2, War2, Nl} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + Mio2 = update_mio(endif, Mio), + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN); {{'if', true}, Rem2, Err2, War2, Nl} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], + Out2 = lists:duplicate(Nl,$\n) ++ Out, IfCou2 = {endif, 1, L}, - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN); + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN); %% {{'if', false}, Removed, Rem2, Nl} -> Not implemented at present {{'if', error}, Rem2, Err2, War2, Nl} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + Mio2 = update_mio('if', Mio), + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN); {'else', {_Removed, Rem2, Nl}} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], + Out2 = lists:duplicate(Nl,$\n) ++ Out, Err2 = {FN, L, "`else' command is not implemented at present"}, - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN); + Mio2 = update_mio('else', Mio), + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN); {'elif', {_Removed, Rem2, Nl}} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], + Out2 = lists:duplicate(Nl,$\n) ++ Out, Err2 = {FN, L, "`elif' command is not implemented at present"}, - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN); + Mio2 = update_mio('elif', Mio), + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN); {warning, {WarningText, Rem2, Nl}} -> [FileName|_More] = IncFile, War2 = {FileName, L, "warning: #warning "++detokenise(WarningText)}, - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, [War2|War], L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, [War2|War], L+Nl, FN); {error, {ErrorText, Rem2, Nl}} -> [FileName|_More] = IncFile, Err2 = {FileName, L, detokenise(ErrorText)}, - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, [Err2|Err], War, L+Nl, FN); {{line, ok}, {_Removed, Rem2, Nl}, L2, FN2, LineText} -> Out2 = lists:duplicate(Nl,$\n)++LineText++Out, [_X|IF] = IncFile, IncFile2 = [FN2|IF], - expand(Rem2, Out2, SelfRef, Defs, IncFile2, IncDir, check_all, Err, War, L2, FN2); + expand(Rem2, Out2, SelfRef, Defs, IncFile2, IncDir, update_mio(Mio), check_all, Err, War, L2, FN2); {{line, error}, {_Removed, Rem2, Nl}, Err2} -> - Out2 = [lists:duplicate(Nl,$\n)|Out], - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN); + Out2 = lists:duplicate(Nl,$\n) ++ Out, + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, [Err2|Err], War, L+Nl, FN); hash_mark -> - expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L, FN); + expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L, FN); {pragma, Rem2, Nl, Text} -> Out2 = lists:duplicate(Nl,$\n)++Text++Out, - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN); + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+Nl, FN); {ident, Rem2, Nl, Text} -> Out2 = lists:duplicate(Nl,$\n)++Text++Out, - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN); + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+Nl, FN); {not_recognised, {Removed, Rem2, Nl}} -> Text = lists:reverse([$#|Command]), RemovedS = lists:reverse([?space|detokenise(Removed)]), Out2 = [$\n|RemovedS]++Text++Out, + Mio2 = update_mio(Mio), case Command of [X|_T] when ?is_upper(X) -> - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN); + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN); [X|_T] when ?is_lower(X) -> - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN); + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN); [X|_T] when ?is_underline(X) -> - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN); + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN); _ -> Err2 = {FN, L, "invalid preprocessing directive name"}, - expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN) + expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN) end; Else -> @@ -859,19 +861,19 @@ expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, check_all end; -expand([{var, "__LINE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> +expand([{var, "__LINE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> LL = io_lib:format("~p",[L]), - expand(Rem, [LL | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); + expand(Rem, [LL | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{var, "__FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> - expand(Rem, [$",FN,$" | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); +expand([{var, "__FILE__"}|Rem], Out, SelfRef, Defs, IncFile, Mio, IncDir, IfCou, Err, War, L, FN) -> + expand(Rem, [$",FN,$" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{var, "__DATE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> +expand([{var, "__DATE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> {{Y,M,D},{_H,_Mi,_S}} = calendar:universal_time(), Date = io_lib:format("\"~s ~p ~p\"",[month(M),D,Y]), - expand(Rem, [Date | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); + expand(Rem, [Date | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> +expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> {{_Y,_M,_D},{H,Mi,S}} = calendar:universal_time(), HS = if H < 10 -> "0"++integer_to_list(H); true -> integer_to_list(H) @@ -883,40 +885,40 @@ expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, true -> integer_to_list(S) end, Time = io_lib:format("\"~s:~s:~s\"",[HS,MiS,SS]), - expand(Rem, [Time | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); + expand(Rem, [Time | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{var, "__INCLUDE_LEVEL__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> +expand([{var, "__INCLUDE_LEVEL__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> IL = io_lib:format("~p",[length(IncFile)-1]), - expand(Rem, [IL | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); + expand(Rem, [IL | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{var, "__BASE_FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> +expand([{var, "__BASE_FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> [BF|_T] = lists:reverse(IncFile), - expand(Rem, [$",BF,$" | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); + expand(Rem, [$",BF,$" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{var, Var} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> +expand([{var, Var} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> {Out2, Err2, War2, Rem2, SelfRef2} = source_line(Var, Rem, SelfRef, Defs, Err, War, L, FN), - expand(Rem2, [Out2 | Out], SelfRef2, Defs, IncFile, IncDir, IfCou, Err2, War2, L, FN); + expand(Rem2, [Out2 | Out], SelfRef2, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err2, War2, L, FN); -expand([{char, Char} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> - expand(Rem, [Char | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); +expand([{char, Char} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> + expand(Rem, [Char | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{number, Number} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> - expand(Rem, [Number | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); +expand([{number, Number} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> + expand(Rem, [Number | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{expanded, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> - expand(Rem, [Str | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); +expand([{expanded, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> + expand(Rem, [Str | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{self_ref, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> +expand([{self_ref, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> SelfRef2 = lists:delete(Str,SelfRef), - expand(Rem, Out, SelfRef2, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); + expand(Rem, Out, SelfRef2, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{string, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> - expand(Rem, [$", Str, $" | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN); +expand([{string, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> + expand(Rem, [$", Str, $" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN); -expand([{string_part, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) -> +expand([{string_part, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) -> {Str2, Rem2, Nl} = expand_string_part([$"|Str], Rem), - expand(Rem2, [Str2| Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L+Nl, FN). + expand(Rem2, [Str2| Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L+Nl, FN). @@ -954,13 +956,14 @@ expand_string_part([{string_part, Str_part} | Rem], Str, Nl) -> get_cmd_line_defs(Flags) -> Adjusted = parse_cmd_line(Flags,[]), - {_Out, _Err, _War, Defs, _IfCou} = + {_Out, _Err, _War, Defs, _IfCou, _Mio} = expand(tokenise(Adjusted,""), [], [], [], [], [], + #mio{}, check_all, [], [], @@ -1030,10 +1033,10 @@ collect_undefine([C|Rest],Found) -> %%====================================================================================== %%====================================================================================== -pp_command(Command, [space|File], Defs, IncDir, Err, War, L, FN) -> - pp_command(Command, File, Defs, IncDir, Err, War, L, FN); +pp_command(Command, [space|File], Defs, IncDir, Mio, Err, War, L, FN) -> + pp_command(Command, File, Defs, IncDir, Mio, Err, War, L, FN); -pp_command(Command, File, Defs, IncDir, Err, War, L, FN) -> +pp_command(Command, File, Defs, IncDir, Mio, Err, War, L, FN) -> case Command of %%---------------------------------------- @@ -1081,14 +1084,16 @@ pp_command(Command, File, Defs, IncDir, Err, War, L, FN) -> %% #include %%---------------------------------------- "include" -> - case include(File, IncDir) of - {error, Rem, Nl, Err2} -> - {{include, error}, Rem, Nl, [{FN, L, Err2}|Err], War}; - {error, Rem, Nl, Err2, NameNl} -> - {{include, error}, Rem, Nl, [{FN, L+ NameNl, Err2}|Err], War}; - {ok, FileName, FileCont, Rem, Nl} -> - {{include, ok}, FileName, FileCont, Rem, Nl, Err, War} - end; + case include(File, IncDir, Mio) of + {error, Rem, Nl, Err2} -> + {{include, error}, Rem, Nl, [{FN, L, Err2}|Err], War}; + {error, Rem, Nl, Err2, NameNl} -> + {{include, error}, Rem, Nl, [{FN, L+ NameNl, Err2}|Err], War}; + {ok, FileNamePath, FileCont, Rem, Nl} -> + {{include, ok}, FileNamePath, FileCont, Rem, Nl, Err, War}; + {skip, Rem} -> + {{include, skip}, Rem} + end; %%---------------------------------------- %% #ifdef @@ -1127,14 +1132,14 @@ pp_command(Command, File, Defs, IncDir, Err, War, L, FN) -> yes -> {{ifndef, true}, Rem, Err2, War2, Nl}; no -> - {{ifndef, false}, Rem, Err2, War2, Nl} + {{ifndef, false}, Name, Rem, Err2, War2, Nl} end; {ok, Rem, Name, No_of_para, _Parameters, _Macro, Err2, War2, Nl} -> case is_defined_before(Name, No_of_para, Defs) of yes -> {{ifndef, true}, Rem, Err2, War2, Nl}; no -> - {{ifndef, false}, Rem, Err2, War2, Nl} + {{ifndef, false}, Name, Rem, Err2, War2, Nl} end end; @@ -1408,29 +1413,32 @@ undef(_Rem) -> %%=============================================================== %%=============================================================== -include(File, IncDir) -> +include(File, IncDir, Mio) -> case include2(File) of - {ok, FileName, Rem, Nl, FileType} -> - %% The error handling is lite strange just to make it compatible to gcc - case {read_inc_file(FileName, IncDir), Nl, FileType} of - {{ok, FileList, FileNamePath}, _, _} -> - {ok, FileNamePath, FileList, Rem, Nl}; - {{error, Text}, _, own_file} -> - NameNl = count_nl(FileName,0), - Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])), - {error, Rem, Nl, Error, NameNl}; - {{error, Text}, 1, sys_file} -> - NameNl = count_nl(FileName,0), - Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])), - {error, Rem, Nl, Error, NameNl}; - {{error, _Text}, _, sys_file} -> - {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"} - end; - - {error, {_Removed, Rem, Nl}} -> - {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"} + {ok, FileName, Rem, Nl, FileType} -> + Result = read_inc_file(FileName, IncDir, Mio), + case {Result, Nl, FileType} of + {{ok, FileNamePath, FileCont}, _, _} -> + {ok, FileNamePath, FileCont, Rem, Nl}; + {skip, _, _} -> + {skip, Rem}; + {{error, Text}, _, own_file} -> + NameNl = count_nl(FileName,0), + Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])), + {error, Rem, Nl, Error, NameNl}; + {{error, Text}, 1, sys_file} -> + NameNl = count_nl(FileName,0), + Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])), + {error, Rem, Nl, Error, NameNl}; + {{error, _Text}, _, sys_file} -> + {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"} + end; + {error, {_Removed, Rem, Nl}} -> + {error, Rem, Nl, "`#include' expects \#FILENAME\" or <FILENAME>"} end. + + count_nl([],Nl) -> Nl; count_nl([$\n|T],Nl) -> @@ -1909,18 +1917,37 @@ include_dir(Flags,IncDir) -> %% Read a included file. Try current dir first then the IncDir list %%=============================================================== -read_inc_file(FileName, IncDir) -> - case catch file:read_file(FileName) of - {ok, Bin} -> - FileList = binary_to_list(Bin), - {ok, FileList, FileName}; +read_inc_file(FileName, IncDir, Mio) -> + case find_inc_file(FileName, IncDir) of + {ok, AbsFile} -> + %% is included before? + case lists:member(FileName, Mio#mio.included) of + false -> + case catch file:read_file(AbsFile) of + {ok, Bin} -> + FileList = binary_to_list(Bin), + {ok, AbsFile, FileList}; + {error, Text} -> + {error, Text} + end; + true -> + skip + end; + {error, Text} -> + {error, Text} + end. + +find_inc_file(FileName, IncDir) -> + case catch file:read_file_info(FileName) of + {ok, _} -> + {ok, FileName}; {error, _} -> - read_inc_file2(FileName, IncDir) + find_inc_file2(FileName, IncDir) end. -read_inc_file2(_FileName, []) -> +find_inc_file2(_FileName, []) -> {error, "No such file or directory"}; -read_inc_file2(FileName, [D|Rem]) -> +find_inc_file2(FileName, [D|Rem]) -> Dir = case lists:last(D) of $/ -> D; @@ -1928,17 +1955,14 @@ read_inc_file2(FileName, [D|Rem]) -> D++"/" end, - case catch file:read_file(Dir++FileName) of - {ok, Bin} -> - FileList = binary_to_list(Bin), - {ok, FileList, Dir++FileName}; + case catch file:read_file_info(Dir++FileName) of + {ok, _} -> + {ok, Dir++FileName}; {error, _} -> - read_inc_file2(FileName, Rem) + find_inc_file2(FileName, Rem) end. - - %%=============================================================== %% Read parameters of a macro or a variable in a source line %%=============================================================== @@ -2135,5 +2159,73 @@ month(11) -> "Nov"; month(12) -> "Dec". +%% Multiple Include Optimization +%% +%% Algorithm described at: +%% http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html +update_mio({include, FileName}, #mio{included=Inc}=Mio) -> + Mio#mio{valid=false, included=[FileName|Inc]}; + +%% valid=false & cmacro=undefined indicates it is already decided this file is +%% not subject to MIO +update_mio(_, #mio{valid=false, depth=0, cmacro=undefined}=Mio) -> + Mio; + +%% if valid=true, there is no non-whitespace tokens before this ifndef +update_mio({'ifndef', Macro}, #mio{valid=true, depth=0, cmacro=undefined}=Mio) -> + Mio#mio{valid=false, cmacro=Macro, depth=1}; + +%% detect any tokens before top level #ifndef +update_mio(_, #mio{valid=true, depth=0, cmacro=undefined}=Mio) -> + Mio#mio{valid=false}; + +%% If cmacro is alreay set, this is after the top level #endif +update_mio({'ifndef', _}, #mio{valid=true, depth=0}=Mio) -> + Mio#mio{valid=false, cmacro=undefined}; + +%% non-top level conditional, just update depth +update_mio({'ifndef', _}, #mio{depth=D}=Mio) when D > 0 -> + Mio#mio{depth=D+1}; +update_mio('ifdef', #mio{depth=D}=Mio) -> + Mio#mio{depth=D+1}; +update_mio('if', #mio{depth=D}=Mio) -> + Mio#mio{depth=D+1}; + +%% top level #else #elif invalidates multiple include optimization +update_mio('else', #mio{depth=1}=Mio) -> + Mio#mio{valid=false, cmacro=undefined}; +update_mio('else', Mio) -> + Mio; +update_mio('elif', #mio{depth=1}=Mio) -> + Mio#mio{valid=false, cmacro=undefined}; +update_mio('elif', Mio) -> + Mio; + +%% AT exit to top level, if the controlling macro is not set, this could be the +%% end of a non-ifndef conditional block, or there were tokens before entering +%% the #ifndef block. In either way, this invalidates the MIO +%% +%% It doesn't matter if `valid` is true at the time of exiting, it is set to +%% true. This will be used to detect if more tokens are following the top +%% level #endif. +update_mio('endif', #mio{depth=1, cmacro=undefined}=Mio) -> + Mio#mio{valid=false, depth=0}; +update_mio('endif', #mio{depth=1}=Mio) -> + Mio#mio{valid=true, depth=0}; +update_mio('endif', #mio{depth=D}=Mio) when D > 1 -> + Mio#mio{valid=true, depth=D-1}; + +%%if more tokens are following the top level #endif. +update_mio('endif', #mio{depth=1, cmacro=undefined}=Mio) -> + Mio#mio{valid=false, depth=0}; +update_mio('endif', #mio{depth=D}=Mio) when D > 0 -> + Mio#mio{valid=true, depth=D-1}; +update_mio(_, Mio) -> + Mio#mio{valid=false}. + +%% clear `valid`, this doesn't matter since #endif will restore it if +%% appropriate +update_mio(Mio) -> + Mio#mio{valid=false}. diff --git a/lib/ic/src/ic_pragma.erl b/lib/ic/src/ic_pragma.erl index 45cb64c9c8..7f2216b9dc 100644 --- a/lib/ic/src/ic_pragma.erl +++ b/lib/ic/src/ic_pragma.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1600,9 +1600,8 @@ remove_inheriters(S,RS,InheriterList) -> [_OneOnly] -> ReducedInhList; _Other -> - EtsList = ets:tab2list(S), CleanList = - [X || X <- EtsList, element(1,X) == inherits], + ets:match(S, {inherits,'_','_'}), % CodeOptList = % [X || X <- EtsList, element(1,X) == codeopt], NoInheriters =remove_inheriters2(S,ReducedInhList,CleanList), @@ -1648,9 +1647,8 @@ remove_inh([X],[Y],List,EtsList) -> %%% from others in the list %%%---------------------------------------------- remove_inherited(S,InheriterList) -> - EtsList = ets:tab2list(S), CleanList = - [X || X <- EtsList, element(1,X) == inherits], + ets:match(S, {inherits, '_', '_'}), remove_inherited(S,InheriterList,CleanList). @@ -1694,11 +1692,8 @@ remove_inhed([X],[Y],List,EtsList) -> %% are inherited from scope in the list %%%---------------------------------------------- get_inherited(S,Scope,OpScopeList) -> - EtsList = ets:tab2list(S), - [[element(3,X)] || X <- EtsList, - element(1,X) == inherits, - element(2,X) == Scope, - member([element(3,X)],OpScopeList)]. + EtsList1 = ets:match(S, {inherits, Scope, '$1'}), + [X || X <- EtsList1, member(X, OpScopeList)]. @@ -1771,9 +1766,7 @@ inherits2(_X,Y,Z,EtsList) -> %% false otherwise %% is_inherited_by(Interface1,Interface2,PragmaTab) -> - FullList = ets:tab2list(PragmaTab), - InheritsList = - [X || X <- FullList, element(1,X) == inherits], + InheritsList = ets:match(PragmaTab, {inherits, '_', '_'}), inherits(Interface2,Interface1,InheritsList). diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk index 6d6c7fa625..6561ccd2a7 100644 --- a/lib/ic/vsn.mk +++ b/lib/ic/vsn.mk @@ -1 +1 @@ -IC_VSN = 4.2.26 +IC_VSN = 4.2.27 diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml index b761b6bd83..cc49090386 100644 --- a/lib/kernel/doc/src/gen_sctp.xml +++ b/lib/kernel/doc/src/gen_sctp.xml @@ -63,14 +63,13 @@ <item><seealso marker="#options">SCTP SOCKET OPTIONS</seealso></item> <item><seealso marker="#examples">SCTP EXAMPLES</seealso></item> <item><seealso marker="#seealso">SEE ALSO</seealso></item> - <item><seealso marker="#authors">AUTHORS</seealso></item> </list> <marker id="types"></marker> </section> <datatypes> <datatype> - <name name="assoc_id"/> + <name><marker id="type-assoc_id">assoc_id()</marker></name> <desc> <p>An opaque term returned in for example #sctp_paddr_change{} that identifies an association for an SCTP socket. The term @@ -80,36 +79,18 @@ </desc> </datatype> <datatype> - <name name="hostname"/> - </datatype> - <datatype> - <name name="ip_address"/> - <desc> - <p>Represents an address of an SCTP socket. - It is a tuple as explained in - <seealso marker="inet">inet(3)</seealso>.</p> - </desc> - </datatype> - <datatype> - <name name="port_number"/> - </datatype> - <datatype> - <name name="posix"/> - <desc> - <p>See <seealso marker="inet#error_codes"> - inet(3); POSIX Error Codes</seealso>.</p> - </desc> - </datatype> - <datatype> - <name name="sctp_option"/> + <name name="option"/> <desc> <p>One of the <seealso marker="#options">SCTP Socket Options.</seealso></p> - <marker id="type-sctp_socket"></marker> </desc> </datatype> <datatype> - <name name="sctp_socket"/> + <name name="option_name"/> + <desc><marker id="type-sctp_socket"></marker></desc> + </datatype> + <datatype> + <name><marker id="type-sctp_socket">sctp_socket()</marker></name> <desc> <p>Socket identifier returned from <c>open/*</c>.</p> <marker id="exports"></marker> @@ -175,8 +156,8 @@ #sctp_assoc_change{ state = atom(), error = atom(), - outbound_streams = int(), - inbound_streams = int(), + outbound_streams = integer(), + inbound_streams = integer(), assoc_id = assoc_id() } </pre> <p>The number of outbound and inbound streams can be set by @@ -300,6 +281,19 @@ The default <c><anno>IP</anno></c> and <c><anno>Port</anno></c> are <c>any</c> and <c>0</c>, meaning bind to all local addresses on any one free port.</p> + + <p>Other options are:</p> + <taglist> + <tag><c>inet6</c></tag> + <item> + <p>Set up the socket for IPv6.</p> + </item> + <tag><c>inet</c></tag> + <item> + <p>Set up the socket for IPv4. This is the default.</p> + </item> + </taglist> + <p>A default set of socket <seealso marker="#options">options</seealso> is used. In particular, the socket is opened in <seealso marker="#option-binary">binary</seealso> and @@ -350,7 +344,7 @@ #sctp_paddr_change{ addr = {ip_address(),port()}, state = atom(), - error = int(), + error = integer(), assoc_id = assoc_id() } </pre> <p>Indicates change of the status of the peer's IP address given by @@ -387,7 +381,7 @@ <pre> #sctp_send_failed{ flags = true | false, - error = int(), + error = integer(), info = #sctp_sndrcvinfo{}, assoc_id = assoc_id() data = binary() @@ -407,7 +401,7 @@ <item> <pre> #sctp_adaptation_event{ - adaptation_ind = int(), + adaptation_ind = integer(), assoc_id = assoc_id() } </pre> <p>Delivered when a peer sends an Adaptation Layer Indication @@ -505,7 +499,7 @@ </list> <marker id="option-buffer"></marker> </item> - <tag><c>{buffer, int()}</c></tag> + <tag><c>{buffer, integer()}</c></tag> <item> <p>Determines the size of the user-level software buffer used by the SCTP driver. Not to be confused with <c>sndbuf</c> @@ -515,7 +509,7 @@ In fact, the <c>val(buffer)</c> is automatically set to the above maximum when <c>sndbuf</c> or <c>recbuf</c> values are set.</p> </item> - <tag><c>{tos, int()}</c></tag> + <tag><c>{tos, integer()}</c></tag> <item> <p>Sets the Type-Of-Service field on the IP datagrams being sent, to the given value, which effectively determines a prioritization @@ -523,7 +517,7 @@ are system-dependent. TODO: we do not provide symbolic names for these values yet.</p> </item> - <tag><c>{priority, int()}</c></tag> + <tag><c>{priority, integer()}</c></tag> <item> <p>A protocol-independent equivalent of <c>tos</c> above. Setting priority implies setting tos as well.</p> @@ -542,7 +536,7 @@ required for high-throughput servers).</p> <marker id="option-linger"></marker> </item> - <tag><c>{linger, {true|false, int()}</c></tag> + <tag><c>{linger, {true|false, integer()}</c></tag> <item> <p>Determines the timeout in seconds for flushing unsent data in the <c>gen_sctp:close/1</c> socket call. If the 1st component of the value @@ -552,14 +546,14 @@ the flushing time-out in seconds.</p> <marker id="option-sndbuf"></marker> </item> - <tag><c>{sndbuf, int()}</c></tag> + <tag><c>{sndbuf, integer()}</c></tag> <item> <p>The size, in bytes, of the *kernel* send buffer for this socket. Sending errors would occur for datagrams larger than <c>val(sndbuf)</c>. Setting this option also adjusts the size of the driver buffer (see <c>buffer</c> above).</p> </item> - <tag><c>{recbuf, int()}</c></tag> + <tag><c>{recbuf, integer()}</c></tag> <item> <p>The size, in bytes, of the *kernel* recv buffer for this socket. Sending errors would occur for datagrams larger than @@ -571,9 +565,9 @@ <pre> #sctp_rtoinfo{ assoc_id = assoc_id(), - initial = int(), - max = int(), - min = int() + initial = integer(), + max = integer(), + min = integer() } </pre> <p>Determines re-transmission time-out parameters, in milliseconds, for the association(s) given by <c>assoc_id</c>. @@ -586,11 +580,11 @@ <pre> #sctp_assocparams{ assoc_id = assoc_id(), - asocmaxrxt = int(), - number_peer_destinations = int(), - peer_rwnd = int(), - local_rwnd = int(), - cookie_life = int() + asocmaxrxt = integer(), + number_peer_destinations = integer(), + peer_rwnd = integer(), + local_rwnd = integer(), + cookie_life = integer() } </pre> <p>Determines association parameters for the association(s) given by <c>assoc_id</c>. <c>assoc_id = 0</c> (default) indicates @@ -601,10 +595,10 @@ <item> <pre> #sctp_initmsg{ - num_ostreams = int(), - max_instreams = int(), - max_attempts = int(), - max_init_timeo = int() + num_ostreams = integer(), + max_instreams = integer(), + max_attempts = integer(), + max_init_timeo = integer() } </pre> <p>Determines the default parameters which this socket attempts to negotiate with its peer while establishing an association with it. @@ -630,10 +624,11 @@ </list> <p></p> </item> - <tag><c>{sctp_autoclose, int()|infinity}</c></tag> + <tag><c>{sctp_autoclose, integer() >= 0}</c></tag> <item> <p>Determines the time (in seconds) after which an idle association is - automatically closed.</p> + automatically closed. <c>0</c> means that the association is + never automatically closed.</p> </item> <tag><c>{sctp_nodelay, true|false}</c></tag> <item> @@ -655,7 +650,7 @@ <p>Turns on|off automatic mapping of IPv4 addresses into IPv6 ones (if the socket address family is AF_INET6).</p> </item> - <tag><c>{sctp_maxseg, int()}</c></tag> + <tag><c>{sctp_maxseg, integer()}</c></tag> <item> <p>Determines the maximum chunk size if message fragmentation is used. If <c>0</c>, the chunk size is limited by the Path MTU only.</p> @@ -693,7 +688,7 @@ <marker id="record-sctp_setadaptation"></marker> <pre> #sctp_setadaptation{ - adaptation_ind = int() + adaptation_ind = integer() } </pre> <p>When set, requests that the local endpoint uses the value given by <c>adaptation_ind</c> as the Adaptation Indication parameter for @@ -707,10 +702,10 @@ #sctp_paddrparams{ assoc_id = assoc_id(), address = {IP, Port}, - hbinterval = int(), - pathmaxrxt = int(), - pathmtu = int(), - sackdelay = int(), + hbinterval = integer(), + pathmaxrxt = integer(), + pathmtu = integer(), + sackdelay = integer(), flags = list() } IP = ip_address() @@ -771,14 +766,14 @@ <marker id="record-sctp_sndrcvinfo"></marker> <pre> #sctp_sndrcvinfo{ - stream = int(), - ssn = int(), + stream = integer(), + ssn = integer(), flags = list(), - ppid = int(), - context = int(), - timetolive = int(), - tsn = int(), - cumtsn = int(), + ppid = integer(), + context = integer(), + timetolive = integer(), + tsn = integer(), + cumtsn = integer(), assoc_id = assoc_id() } </pre> <p><c>#sctp_sndrcvinfo{}</c> is used both in this socket option, and as @@ -853,7 +848,7 @@ <pre> #sctp_assoc_value{ assoc_id = assoc_id(), - assoc_value = int() + assoc_value = integer() } </pre> <p>Rarely used. Determines the ACK time (given by <c>assoc_value</c> in milliseconds) for @@ -866,12 +861,12 @@ #sctp_status{ assoc_id = assoc_id(), state = atom(), - rwnd = int(), - unackdata = int(), - penddata = int(), - instrms = int(), - outstrms = int(), - fragmentation_point = int(), + rwnd = integer(), + unackdata = integer(), + penddata = integer(), + instrms = integer(), + outstrms = integer(), + fragmentation_point = integer(), primary = #sctp_paddrinfo{} } </pre> <p>This option is read-only. It determines the status of @@ -946,10 +941,10 @@ assoc_id = assoc_id(), address = {IP, Port}, state = inactive | active, - cwnd = int(), - srtt = int(), - rto = int(), - mtu = int() + cwnd = integer(), + srtt = integer(), + rto = integer(), + mtu = integer() } IP = ip_address() Port = port_number() </pre> @@ -1119,7 +1114,6 @@ client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) -> <seealso marker="gen_udp">gen_udp(3)</seealso>, <url href="http://www.rfc-archive.org/getrfc.php?rfc=2960">RFC2960</url> (Stream Control Transmission Protocol), <url href="http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13">Sockets API Extensions for SCTP.</url></p> - <marker id="authors"></marker> </section> </erlref> diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index f1d42d9faa..8a5d40bb16 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -37,7 +37,7 @@ binary and closing the connection:</p> <code type="none"> client() -> - SomeHostInNet = "localhost" % to make it runnable on one machine + SomeHostInNet = "localhost", % to make it runnable on one machine {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678, [binary, {packet, 0}]), ok = gen_tcp:send(Sock, "Some Data"), @@ -65,25 +65,16 @@ do_recv(Sock, Bs) -> <datatypes> <datatype> - <name name="hostname"/> + <name name="option"/> </datatype> <datatype> - <name name="ip_address"/> - <desc> - <p>Represents an address of a TCP socket. - It is a tuple as explained in - <seealso marker="inet">inet(3)</seealso>.</p> - </desc> + <name name="option_name"/> </datatype> <datatype> - <name name="port_number"/> + <name name="connect_option"/> </datatype> <datatype> - <name name="posix"/> - <desc> - <p>See <seealso marker="inet#error_codes"> - inet(3); POSIX Error Codes</seealso>.</p> - </desc> + <name name="listen_option"/> </datatype> <datatype> <name><marker id="type-socket">socket()</marker></name> @@ -122,7 +113,7 @@ do_recv(Sock, Bs) -> <item> <p>Specify which local port number to use.</p> </item> - <tag><c>{fd, int()}</c></tag> + <tag><c>{fd, integer() >= 0}</c></tag> <item> <p>If a socket has somehow been connected without using <c>gen_tcp</c>, use this option to pass the file @@ -196,6 +187,10 @@ do_recv(Sock, Bs) -> <p>If the host has several network interfaces, this option specifies which one to listen on.</p> </item> + <tag><c>{port, Port}</c></tag> + <item> + <p>Specify which local port number to use.</p> + </item> <tag><c>{fd, Fd}</c></tag> <item> <p>If a socket has somehow been connected without using diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml index c0e783f508..daa9b7d887 100644 --- a/lib/kernel/doc/src/gen_udp.xml +++ b/lib/kernel/doc/src/gen_udp.xml @@ -36,25 +36,10 @@ <datatypes> <datatype> - <name name="hostname"/> + <name name="option"/> </datatype> <datatype> - <name name="ip_address"/> - <desc> - <p>Represents an address of a TCP socket. - It is a tuple as explained in - <seealso marker="inet">inet(3)</seealso>.</p> - </desc> - </datatype> - <datatype> - <name name="port_number"/> - </datatype> - <datatype> - <name name="posix"/> - <desc> - <p>See <seealso marker="inet#error_codes"> - inet(3); POSIX Error Codes</seealso>.</p> - </desc> + <name name="option_name"/> </datatype> <datatype> <name><marker id="type-socket">socket()</marker></name> @@ -87,7 +72,7 @@ <p>If the host has several network interfaces, this option specifies which one to use.</p> </item> - <tag><c>{fd, int()}</c></tag> + <tag><c>{fd, integer() >= 0}</c></tag> <item> <p>If a socket has somehow been opened without using <c>gen_udp</c>, use this option to pass the file diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index fd843b00d9..b36c28e027 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -105,6 +105,9 @@ fe80::204:acff:fe17:bf38 <name name="ip6_address"/> </datatype> <datatype> + <name name="port_number"/> + </datatype> + <datatype> <name name="posix"/> <desc><p>An atom which is named from the Posix error codes used in Unix, and in the runtime libraries of most @@ -119,7 +122,7 @@ fe80::204:acff:fe17:bf38 </desc> </datatype> <datatype> - <name name="family_option"/> + <name name="address_family"/> </datatype> </datatypes> @@ -250,26 +253,15 @@ fe80::204:acff:fe17:bf38 </func> <func> - <name>getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()}</name> + <name name="getopts" arity="2"/> <fsummary>Get one or more options for a socket</fsummary> - <type> - <v>Socket = term()</v> - <v>Options = [Opt | RawOptReq]</v> - <v>Opt = atom()</v> - <v>RawOptReq = {raw, Protocol, OptionNum, ValueSpec}</v> - <v>Protocol = integer()</v> - <v>OptionNum = integer()</v> - <v>ValueSpec = ValueSize | ValueBin</v> - <v>ValueSize = integer()</v> - <v>ValueBin = binary()</v> - <v>OptionValues = [{Opt, Val} | {raw, Protocol, OptionNum, ValueBin}]</v> - </type> <type name="socket_getopt"/> + <type name="socket_setopt"/> <desc> <p>Gets one or more options for a socket. See <seealso marker="#setopts/2">setopts/2</seealso> for a list of available options.</p> - <p>The number of elements in the returned <c>OptionValues</c> + <p>The number of elements in the returned <c><anno>OptionValues</anno></c> list does not necessarily correspond to the number of options asked for. If the operating system fails to support an option, it is simply left out in the returned list. An error tuple is only @@ -277,12 +269,12 @@ fe80::204:acff:fe17:bf38 (i.e. the socket is closed or the buffer size in a raw request is too large). This behavior is kept for backward compatibility reasons.</p> - <p>A <c>RawOptReq</c> can be used to get information about + <p>A raw option request <c>RawOptReq = {raw, Protocol, OptionNum, ValueSpec}</c> can be used to get information about socket options not (explicitly) supported by the emulator. The use of raw socket options makes the code non portable, but allows the Erlang programmer to take advantage of unusual features present on the current platform.</p> - <p>The <c>RawOptReq</c> consists of the tag <c>raw</c> followed + <p>The <c>RawOptReq</c> consists of the tag <c>raw</c> followed by the protocol level, the option number and either a binary or the size, in bytes, of the buffer in which the option value is to be stored. A binary @@ -325,19 +317,14 @@ fe80::204:acff:fe17:bf38 </func> <func> - <name>getstat(Socket)</name> - <name>getstat(Socket, Options) -> {ok, OptionValues} | {error, posix()}</name> + <name name="getstat" arity="1"/> + <name name="getstat" arity="2"/> <fsummary>Get one or more statistic options for a socket</fsummary> - <type> - <v>Socket = term()</v> - <v>Options = [Opt]</v> - <v>OptionValues = [{Opt, Val}]</v> - <v> Opt, Val -- see below</v> - </type> + <type name="stat_option"/> <desc> <p>Gets one or more statistic options for a socket.</p> - <p><c>getstat(Socket)</c> is equivalent to - <c>getstat(Socket, [recv_avg, recv_cnt, recv_dvi, recv_max, recv_oct, send_avg, send_cnt, send_dvi, send_max, send_oct])</c></p> + <p><c>getstat(<anno>Socket</anno>)</c> is equivalent to + <c>getstat(<anno>Socket</anno>, [recv_avg, recv_cnt, recv_dvi, recv_max, recv_oct, send_avg, send_cnt, send_dvi, send_max, send_oct])</c></p> <p>The following options are available:</p> <taglist> <tag><c>recv_avg</c></tag> @@ -394,12 +381,8 @@ fe80::204:acff:fe17:bf38 </desc> </func> <func> - <name>port(Socket) -> {ok, Port} | {error, any()}</name> + <name name="port" arity="1"/> <fsummary>Return the local port number for a socket</fsummary> - <type> - <v>Socket = socket()</v> - <v>Port = integer()</v> - </type> <desc> <p>Returns the local port number for a socket.</p> </desc> @@ -412,16 +395,9 @@ fe80::204:acff:fe17:bf38 </desc> </func> <func> - <name>setopts(Socket, Options) -> ok | {error, posix()}</name> + <name name="setopts" arity="2"/> <fsummary>Set one or more options for a socket</fsummary> - <type> - <v>Socket = term()</v> - <v>Options = [{Opt, Val} | {raw, Protocol, Option, ValueBin}]</v> - <v>Protocol = integer()</v> - <v>OptionNum = integer()</v> - <v>ValueBin = binary()</v> - <v> Opt, Val -- see below</v> - </type> + <type name="socket_setopt"/> <desc> <p>Sets one or more options for a socket. The following options are available:</p> diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 4a1fc7df34..85bbff9cc3 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1379,8 +1379,12 @@ absname_vr([[X, $:]|Name], _, _AbsBase) -> %% Kill all processes running code from *old* Module, and then purge the %% module. Return true if any processes killed, else false. -do_purge(Mod) -> - do_purge(processes(), to_atom(Mod), false). +do_purge(Mod0) -> + Mod = to_atom(Mod0), + case erlang:check_old_code(Mod) of + false -> false; + true -> do_purge(processes(), Mod, false) + end. do_purge([P|Ps], Mod, Purged) -> case erlang:check_process_code(P, Mod) of @@ -1399,16 +1403,19 @@ do_purge([], Mod, Purged) -> Purged. %% do_soft_purge(Module) -%% Purge old code only if no procs remain that run old code +%% Purge old code only if no procs remain that run old code. %% Return true in that case, false if procs remain (in this %% case old code is not purged) do_soft_purge(Mod) -> - catch do_soft_purge(processes(), Mod). + case erlang:check_old_code(Mod) of + false -> true; + true -> do_soft_purge(processes(), Mod) + end. do_soft_purge([P|Ps], Mod) -> case erlang:check_process_code(P, Mod) of - true -> throw(false); + true -> false; false -> do_soft_purge(Ps, Mod) end; do_soft_purge([], Mod) -> diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl index 004f03f231..6cebb7ab97 100644 --- a/lib/kernel/src/gen_sctp.erl +++ b/lib/kernel/src/gen_sctp.erl @@ -33,55 +33,85 @@ -export([error_string/1]). -export([controlling_process/2]). --opaque assoc_id() :: term(). --type hostname() :: inet:hostname(). --type ip_address() :: inet:ip_address(). --type port_number() :: 0..65535. --type posix() :: inet:posix(). --type sctp_option() :: - {mode, list | binary} | list | binary - | {active, true | false | once} - | {buffer, non_neg_integer()} - | {tos, integer()} - | {priority, integer()} - | {dontroute, boolean()} - | {reuseaddr, boolean()} - | {linger, {boolean(), non_neg_integer()}} - | {sndbuf, non_neg_integer()} - | {recbuf, non_neg_integer()} - | {sctp_rtoinfo, #sctp_rtoinfo{}} - | {sctp_associnfo, #sctp_assocparams{}} - | {sctp_initmsg, #sctp_initmsg{}} - | {sctp_autoclose, timeout()} - | {sctp_nodelay, boolean()} - | {sctp_disable_fragments, boolean()} - | {sctp_i_want_mapped_v4_addr, boolean()} - | {sctp_maxseg, non_neg_integer()} - | {sctp_primary_addr, #sctp_prim{}} - | {sctp_set_peer_primary_addr, #sctp_setpeerprim{}} - | {sctp_adaptation_layer, #sctp_setadaptation{}} - | {sctp_peer_addr_params, #sctp_paddrparams{}} - | {sctp_default_send_param, #sctp_sndrcvinfo{}} - | {sctp_events, #sctp_event_subscribe{}} - | {sctp_delayed_ack_time, #sctp_assoc_value{}} - | {sctp_status, #sctp_status{}} - | {sctp_get_peer_addr_info, #sctp_paddrinfo{}}. --opaque sctp_socket() :: port(). - --spec open() -> {ok, Socket} | {error, posix()} when +-type assoc_id() :: term(). +-type option() :: + {active, true | false | once} | + {buffer, non_neg_integer()} | + {dontroute, boolean()} | + {linger, {boolean(), non_neg_integer()}} | + {mode, list | binary} | list | binary | + {priority, non_neg_integer()} | + {recbuf, non_neg_integer()} | + {reuseaddr, boolean()} | + {sctp_adaptation_layer, #sctp_setadaptation{}} | + {sctp_associnfo, #sctp_assocparams{}} | + {sctp_autoclose, non_neg_integer()} | + {sctp_default_send_param, #sctp_sndrcvinfo{}} | + {sctp_delayed_ack_time, #sctp_assoc_value{}} | + {sctp_disable_fragments, boolean()} | + {sctp_events, #sctp_event_subscribe{}} | + {sctp_get_peer_addr_info, #sctp_paddrinfo{}} | + {sctp_i_want_mapped_v4_addr, boolean()} | + {sctp_initmsg, #sctp_initmsg{}} | + {sctp_maxseg, non_neg_integer()} | + {sctp_nodelay, boolean()} | + {sctp_peer_addr_params, #sctp_paddrparams{}} | + {sctp_primary_addr, #sctp_prim{}} | + {sctp_rtoinfo, #sctp_rtoinfo{}} | + {sctp_set_peer_primary_addr, #sctp_setpeerprim{}} | + {sctp_status, #sctp_status{}} | + {sndbuf, non_neg_integer()} | + {tos, non_neg_integer()}. +-type option_name() :: + active | + buffer | + dontroute | + linger | + mode | + priority | + recbuf | + reuseaddr | + sctp_adaptation_layer | + sctp_associnfo | + sctp_autoclose | + sctp_default_send_param | + sctp_delayed_ack_time | + sctp_disable_fragments | + sctp_events | + sctp_get_peer_addr_info | + sctp_i_want_mapped_v4_addr | + sctp_initmsg | + sctp_maxseg | + sctp_nodelay | + sctp_peer_addr_params | + sctp_primary_addr | + sctp_rtoinfo | + sctp_set_peer_primary_addr | + sctp_status | + sndbuf | + tos. +-type sctp_socket() :: port(). + +-export_type([assoc_id/0, option/0, option_name/0, sctp_socket/0]). + +-spec open() -> {ok, Socket} | {error, inet:posix()} when Socket :: sctp_socket(). open() -> open([]). --spec open(Port) -> {ok, Socket} | {error, posix()} when - Port :: port_number(), +-spec open(Port) -> {ok, Socket} | {error, inet:posix()} when + Port :: inet:port_number(), Socket :: sctp_socket(); - (Opts) -> {ok, Socket} | {error, posix()} when + (Opts) -> {ok, Socket} | {error, inet:posix()} when Opts :: [Opt], - Opt :: {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option(), - IP :: ip_address() | any | loopback, - Port :: port_number(), + Opt :: {ip,IP} + | {ifaddr,IP} + | inet:address_family() + | {port,Port} + | option(), + IP :: inet:ip_address() | any | loopback, + Port :: inet:port_number(), Socket :: sctp_socket(). open(Opts) when is_list(Opts) -> @@ -98,11 +128,15 @@ open(Port) when is_integer(Port) -> open(X) -> erlang:error(badarg, [X]). --spec open(Port, Opts) -> {ok, Socket} | {error, posix()} when +-spec open(Port, Opts) -> {ok, Socket} | {error, inet:posix()} when Opts :: [Opt], - Opt :: {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option(), - IP :: ip_address() | any | loopback, - Port :: port_number(), + Opt :: {ip,IP} + | {ifaddr,IP} + | inet:address_family() + | {port,Port} + | option(), + IP :: inet:ip_address() | any | loopback, + Port :: inet:port_number(), Socket :: sctp_socket(). open(Port, Opts) when is_integer(Port), is_list(Opts) -> @@ -110,7 +144,7 @@ open(Port, Opts) when is_integer(Port), is_list(Opts) -> open(Port, Opts) -> erlang:error(badarg, [Port,Opts]). --spec close(Socket) -> ok | {error, posix()} when +-spec close(Socket) -> ok | {error, inet:posix()} when Socket :: sctp_socket(). close(S) when is_port(S) -> @@ -138,22 +172,22 @@ listen(S, Flag) when is_port(S), is_boolean(Flag) -> listen(S, Flag) -> erlang:error(badarg, [S,Flag]). --spec connect(Socket, Addr, Port, Opts) -> {ok, Assoc} | {error, posix()} when +-spec connect(Socket, Addr, Port, Opts) -> {ok, Assoc} | {error, inet:posix()} when Socket :: sctp_socket(), - Addr :: ip_address() | hostname(), - Port :: port_number(), - Opts :: [Opt :: sctp_option()], + Addr :: inet:ip_address() | inet:hostname(), + Port :: inet:port_number(), + Opts :: [Opt :: option()], Assoc :: #sctp_assoc_change{}. connect(S, Addr, Port, Opts) -> connect(S, Addr, Port, Opts, infinity). -spec connect(Socket, Addr, Port, Opts, Timeout) -> - {ok, Assoc} | {error, posix()} when + {ok, Assoc} | {error, inet:posix()} when Socket :: sctp_socket(), - Addr :: ip_address() | hostname(), - Port :: port_number(), - Opts :: [Opt :: sctp_option()], + Addr :: inet:ip_address() | inet:hostname(), + Port :: inet:port_number(), + Opts :: [Opt :: option()], Timeout :: timeout(), Assoc :: #sctp_assoc_change{}. @@ -166,21 +200,21 @@ connect(S, Addr, Port, Opts, Timeout) -> end. -spec connect_init(Socket, Addr, Port, Opts) -> - ok | {error, posix()} when + ok | {error, inet:posix()} when Socket :: sctp_socket(), - Addr :: ip_address() | hostname(), - Port :: port_number(), - Opts :: [sctp_option()]. + Addr :: inet:ip_address() | inet:hostname(), + Port :: inet:port_number(), + Opts :: [option()]. connect_init(S, Addr, Port, Opts) -> connect_init(S, Addr, Port, Opts, infinity). -spec connect_init(Socket, Addr, Port, Opts, Timeout) -> - ok | {error, posix()} when + ok | {error, inet:posix()} when Socket :: sctp_socket(), - Addr :: ip_address() | hostname(), - Port :: port_number(), - Opts :: [sctp_option()], + Addr :: inet:ip_address() | inet:hostname(), + Port :: inet:port_number(), + Opts :: [option()], Timeout :: timeout(). connect_init(S, Addr, Port, Opts, Timeout) -> @@ -232,7 +266,7 @@ eof(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) -> eof(S, Assoc) -> erlang:error(badarg, [S,Assoc]). --spec abort(Socket, Assoc) -> ok | {error, posix()} when +-spec abort(Socket, Assoc) -> ok | {error, inet:posix()} when Socket :: sctp_socket(), Assoc :: #sctp_assoc_change{}. @@ -294,13 +328,13 @@ send(S, AssocChange, Stream, Data) -> -spec recv(Socket) -> {ok, {FromIP, FromPort, AncData, Data}} | {error, Reason} when Socket :: sctp_socket(), - FromIP :: ip_address(), - FromPort :: port_number(), + FromIP :: inet:ip_address(), + FromPort :: inet:port_number(), AncData :: [#sctp_sndrcvinfo{}], Data :: binary() | string() | #sctp_sndrcvinfo{} | #sctp_assoc_change{} | #sctp_paddr_change{} | #sctp_adaptation_event{}, - Reason :: posix() | #sctp_send_failed{} | #sctp_paddr_change{} + Reason :: inet:posix() | #sctp_send_failed{} | #sctp_paddr_change{} | #sctp_pdapi_event{} | #sctp_remote_error{} | #sctp_shutdown_event{}. @@ -311,13 +345,13 @@ recv(S) -> | {error, Reason} when Socket :: sctp_socket(), Timeout :: timeout(), - FromIP :: ip_address(), - FromPort :: port_number(), + FromIP :: inet:ip_address(), + FromPort :: inet:port_number(), AncData :: [#sctp_sndrcvinfo{}], Data :: binary() | string() | #sctp_sndrcvinfo{} | #sctp_assoc_change{} | #sctp_paddr_change{} | #sctp_adaptation_event{}, - Reason :: posix() | #sctp_send_failed{} | #sctp_paddr_change{} + Reason :: inet:posix() | #sctp_send_failed{} | #sctp_paddr_change{} | #sctp_pdapi_event{} | #sctp_remote_error{} | #sctp_shutdown_event{}. diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl index bee61ca84a..8ab18c01b4 100644 --- a/lib/kernel/src/gen_tcp.erl +++ b/lib/kernel/src/gen_tcp.erl @@ -28,34 +28,108 @@ -include("inet_int.hrl"). --type hostname() :: inet:hostname(). --type ip_address() :: inet:ip_address(). --type port_number() :: 0..65535. --type posix() :: inet:posix(). +-type option() :: + {active, true | false | once} | + {bit8, clear | set | on | off} | + {buffer, non_neg_integer()} | + {delay_send, boolean()} | + {deliver, port | term} | + {dontroute, boolean()} | + {exit_on_close, boolean()} | + {header, non_neg_integer()} | + {high_watermark, non_neg_integer()} | + {keepalive, boolean()} | + {linger, {boolean(), non_neg_integer()}} | + {low_watermark, non_neg_integer()} | + {mode, list | binary} | list | binary | + {nodelay, boolean()} | + {packet, + 0 | 1 | 2 | 4 | raw | sunrm | asn1 | + cdr | fcgi | line | tpkt | http | httph | http_bin | httph_bin } | + {packet_size, non_neg_integer()} | + {priority, non_neg_integer()} | + {raw, + Protocol :: non_neg_integer(), + OptionNum :: non_neg_integer(), + ValueBin :: binary()} | + {recbuf, non_neg_integer()} | + {reuseaddr, boolean()} | + {send_timeout, non_neg_integer() | infinity} | + {send_timeout_close, boolean()} | + {sndbuf, non_neg_integer()} | + {tos, non_neg_integer()}. +-type option_name() :: + active | + bit8 | + buffer | + delay_send | + deliver | + dontroute | + exit_on_close | + header | + high_watermark | + keepalive | + linger | + low_watermark | + mode | + nodelay | + packet | + packet_size | + priority | + {raw, + Protocol :: non_neg_integer(), + OptionNum :: non_neg_integer(), + ValueSpec :: (ValueSize :: non_neg_integer()) | + (ValueBin :: binary())} | + recbuf | + reuseaddr | + send_timeout | + send_timeout_close | + sndbuf | + tos. +-type connect_option() :: + {ip, inet:ip_address()} | + {fd, Fd :: non_neg_integer()} | + {ifaddr, inet:ip_address()} | + inet:address_family() | + {port, inet:port_number()} | + {tcp_module, module()} | + option(). +-type listen_option() :: + {ip, inet:ip_address()} | + {fd, Fd :: non_neg_integer()} | + {ifaddr, inet:ip_address()} | + inet:address_family() | + {port, inet:port_number()} | + {backlog, B :: non_neg_integer()} | + {tcp_module, module()} | + option(). -type socket() :: port(). +-export_type([option/0, option_name/0, connect_option/0, listen_option/0]). + %% %% Connect a socket %% -spec connect(Address, Port, Options) -> {ok, Socket} | {error, Reason} when - Address :: ip_address() | hostname(), - Port :: port_number(), - Options :: [Opt :: term()], + Address :: inet:ip_address() | inet:hostname(), + Port :: inet:port_number(), + Options :: [connect_option()], Socket :: socket(), - Reason :: posix(). + Reason :: inet:posix(). connect(Address, Port, Opts) -> connect(Address,Port,Opts,infinity). -spec connect(Address, Port, Options, Timeout) -> {ok, Socket} | {error, Reason} when - Address :: ip_address() | hostname(), - Port :: port_number(), - Options :: [Opt :: term()], + Address :: inet:ip_address() | inet:hostname(), + Port :: inet:port_number(), + Options :: [connect_option()], Timeout :: timeout(), Socket :: socket(), - Reason :: posix(). + Reason :: inet:posix(). connect(Address, Port, Opts, Time) -> Timer = inet:start_timer(Time), @@ -97,10 +171,10 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) -> %% -spec listen(Port, Options) -> {ok, ListenSocket} | {error, Reason} when - Port :: port_number(), - Options :: [Opt :: term()], + Port :: inet:port_number(), + Options :: [listen_option()], ListenSocket :: socket(), - Reason :: posix(). + Reason :: inet:posix(). listen(Port, Opts) -> Mod = mod(Opts, undefined), @@ -119,7 +193,7 @@ listen(Port, Opts) -> -spec accept(ListenSocket) -> {ok, Socket} | {error, Reason} when ListenSocket :: socket(), Socket :: socket(), - Reason :: closed | timeout | posix(). + Reason :: closed | timeout | inet:posix(). accept(S) -> case inet_db:lookup_socket(S) of @@ -133,7 +207,7 @@ accept(S) -> ListenSocket :: socket(), Timeout :: timeout(), Socket :: socket(), - Reason :: closed | timeout | posix(). + Reason :: closed | timeout | inet:posix(). accept(S, Time) when is_port(S) -> case inet_db:lookup_socket(S) of @@ -150,7 +224,7 @@ accept(S, Time) when is_port(S) -> -spec shutdown(Socket, How) -> ok | {error, Reason} when Socket :: socket(), How :: read | write | read_write, - Reason :: posix(). + Reason :: inet:posix(). shutdown(S, How) when is_port(S) -> case inet_db:lookup_socket(S) of @@ -176,8 +250,8 @@ close(S) -> -spec send(Socket, Packet) -> ok | {error, Reason} when Socket :: socket(), - Packet :: string() | binary(), - Reason :: posix(). + Packet :: iodata(), + Reason :: inet:posix(). send(S, Packet) when is_port(S) -> case inet_db:lookup_socket(S) of @@ -195,7 +269,7 @@ send(S, Packet) when is_port(S) -> Socket :: socket(), Length :: non_neg_integer(), Packet :: string() | binary() | HttpPacket, - Reason :: closed | posix(), + Reason :: closed | inet:posix(), HttpPacket :: term(). recv(S, Length) when is_port(S) -> @@ -211,7 +285,7 @@ recv(S, Length) when is_port(S) -> Length :: non_neg_integer(), Timeout :: timeout(), Packet :: string() | binary() | HttpPacket, - Reason :: closed | posix(), + Reason :: closed | inet:posix(), HttpPacket :: term(). recv(S, Length, Time) when is_port(S) -> @@ -237,7 +311,7 @@ unrecv(S, Data) when is_port(S) -> -spec controlling_process(Socket, Pid) -> ok | {error, Reason} when Socket :: socket(), Pid :: pid(), - Reason :: closed | not_owner | posix(). + Reason :: closed | not_owner | inet:posix(). controlling_process(S, NewOwner) -> case inet_db:lookup_socket(S) of diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl index 7d14615c04..8688799ae9 100644 --- a/lib/kernel/src/gen_udp.erl +++ b/lib/kernel/src/gen_udp.erl @@ -25,25 +25,74 @@ -include("inet_int.hrl"). --type hostname() :: inet:hostname(). --type ip_address() :: inet:ip_address(). --type port_number() :: 0..65535. --type posix() :: inet:posix(). +-type option() :: + {active, true | false | once} | + {add_membership, {inet:ip_address(), inet:ip_address()}} | + {broadcast, boolean()} | + {buffer, non_neg_integer()} | + {deliver, port | term} | + {dontroute, boolean()} | + {drop_membership, {inet:ip_address(), inet:ip_address()}} | + {header, non_neg_integer()} | + {mode, list | binary} | list | binary | + {multicast_if, inet:ip_address()} | + {multicast_loop, boolean()} | + {multicast_ttl, non_neg_integer()} | + {priority, non_neg_integer()} | + {raw, + Protocol :: non_neg_integer(), + OptionNum :: non_neg_integer(), + ValueBin :: binary()} | + {read_packets, non_neg_integer()} | + {recbuf, non_neg_integer()} | + {reuseaddr, boolean()} | + {sndbuf, non_neg_integer()} | + {tos, non_neg_integer()}. +-type option_name() :: + active | + broadcast | + buffer | + deliver | + dontroute | + header | + mode | + multicast_if | + multicast_loop | + multicast_ttl | + priority | + {raw, + Protocol :: non_neg_integer(), + OptionNum :: non_neg_integer(), + ValueSpec :: (ValueSize :: non_neg_integer()) | + (ValueBin :: binary())} | + read_packets | + recbuf | + reuseaddr | + sndbuf | + tos. -type socket() :: port(). +-export_type([option/0, option_name/0]). + -spec open(Port) -> {ok, Socket} | {error, Reason} when - Port :: port_number(), + Port :: inet:port_number(), Socket :: socket(), - Reason :: posix(). + Reason :: inet:posix(). open(Port) -> open(Port, []). -spec open(Port, Opts) -> {ok, Socket} | {error, Reason} when - Port :: port_number(), - Opts :: [Opt :: term()], + Port :: inet:port_number(), + Opts :: [Option], + Option :: {ip, inet:ip_address()} + | {fd, non_neg_integer()} + | {ifaddr, inet:ip_address()} + | inet:address_family() + | {port, inet:port_number()} + | option(), Socket :: socket(), - Reason :: posix(). + Reason :: inet:posix(). open(Port, Opts) -> Mod = mod(Opts, undefined), @@ -58,10 +107,10 @@ close(S) -> -spec send(Socket, Address, Port, Packet) -> ok | {error, Reason} when Socket :: socket(), - Address :: ip_address() | hostname(), - Port :: port_number(), - Packet :: string() | binary(), - Reason :: not_owner | posix(). + Address :: inet:ip_address() | inet:hostname(), + Port :: inet:port_number(), + Packet :: iodata(), + Reason :: not_owner | inet:posix(). send(S, Address, Port, Packet) when is_port(S) -> case inet_db:lookup_socket(S) of @@ -92,10 +141,10 @@ send(S, Packet) when is_port(S) -> {ok, {Address, Port, Packet}} | {error, Reason} when Socket :: socket(), Length :: non_neg_integer(), - Address :: ip_address(), - Port :: port_number(), + Address :: inet:ip_address(), + Port :: inet:port_number(), Packet :: string() | binary(), - Reason :: not_owner | posix(). + Reason :: not_owner | inet:posix(). recv(S,Len) when is_port(S), is_integer(Len) -> case inet_db:lookup_socket(S) of @@ -110,10 +159,10 @@ recv(S,Len) when is_port(S), is_integer(Len) -> Socket :: socket(), Length :: non_neg_integer(), Timeout :: timeout(), - Address :: ip_address(), - Port :: port_number(), + Address :: inet:ip_address(), + Port :: inet:port_number(), Packet :: string() | binary(), - Reason :: not_owner | posix(). + Reason :: not_owner | inet:posix(). recv(S,Len,Time) when is_port(S) -> case inet_db:lookup_socket(S) of diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 5649188c38..48a6f3db65 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -63,8 +63,9 @@ %% timer interface -export([start_timer/1, timeout/1, timeout/2, stop_timer/1]). --export_type([family_option/0, hostent/0, hostname/0, ip4_address/0, - ip6_address/0, ip_address/0, posix/0, socket/0]). +-export_type([address_family/0, hostent/0, hostname/0, ip4_address/0, + ip6_address/0, ip_address/0, posix/0, socket/0, + port_number/0]). %% imports -import(lists, [append/1, duplicate/2, filter/2, foldl/3]). @@ -87,98 +88,15 @@ -type ip6_address() :: {0..65535,0..65535,0..65535,0..65535, 0..65535,0..65535,0..65535,0..65535}. -type ip_address() :: ip4_address() | ip6_address(). --type ip_port() :: 0..65535. +-type port_number() :: 0..65535. -type posix() :: exbadport | exbadseq | file:posix(). -type socket() :: port(). -type socket_setopt() :: - {'raw', non_neg_integer(), non_neg_integer(), binary()} | - %% TCP/UDP options - {'reuseaddr', boolean()} | - {'keepalive', boolean()} | - {'dontroute', boolean()} | - {'linger', {boolean(), non_neg_integer()}} | - {'broadcast', boolean()} | - {'sndbuf', non_neg_integer()} | - {'recbuf', non_neg_integer()} | - {'priority', non_neg_integer()} | - {'tos', non_neg_integer()} | - {'nodelay', boolean()} | - {'multicast_ttl', non_neg_integer()} | - {'multicast_loop', boolean()} | - {'multicast_if', ip_address()} | - {'add_membership', {ip_address(), ip_address()}} | - {'drop_membership', {ip_address(), ip_address()}} | - {'header', non_neg_integer()} | - {'buffer', non_neg_integer()} | - {'active', boolean() | 'once'} | - {'packet', - 0 | 1 | 2 | 4 | 'raw' | 'sunrm' | 'asn1' | - 'cdr' | 'fcgi' | 'line' | 'tpkt' | 'http' | 'httph' | 'http_bin' | 'httph_bin' } | - {'mode', 'list' | 'binary'} | - {'port', 'port', 'term'} | - {'exit_on_close', boolean()} | - {'low_watermark', non_neg_integer()} | - {'high_watermark', non_neg_integer()} | - {'bit8', 'clear' | 'set' | 'on' | 'off'} | - {'send_timeout', non_neg_integer() | 'infinity'} | - {'send_timeout_close', boolean()} | - {'delay_send', boolean()} | - {'packet_size', non_neg_integer()} | - {'read_packets', non_neg_integer()} | - %% SCTP options - {'sctp_rtoinfo', #sctp_rtoinfo{}} | - {'sctp_associnfo', #sctp_assocparams{}} | - {'sctp_initmsg', #sctp_initmsg{}} | - {'sctp_nodelay', boolean()} | - {'sctp_autoclose', non_neg_integer()} | - {'sctp_disable_fragments', boolean()} | - {'sctp_i_want_mapped_v4_addr', boolean()} | - {'sctp_maxseg', non_neg_integer()} | - {'sctp_primary_addr', #sctp_prim{}} | - {'sctp_set_peer_primary_addr', #sctp_setpeerprim{}} | - {'sctp_adaptation_layer', #sctp_setadaptation{}} | - {'sctp_peer_addr_params', #sctp_paddrparams{}} | - {'sctp_default_send_param', #sctp_sndrcvinfo{}} | - {'sctp_events', #sctp_event_subscribe{}} | - {'sctp_delayed_ack_time', #sctp_assoc_value{}}. + gen_sctp:option() | gen_tcp:option() | gen_udp:option(). -type socket_getopt() :: - {'raw', - non_neg_integer(), non_neg_integer(), binary()|non_neg_integer()} | - %% TCP/UDP options - 'reuseaddr' | 'keepalive' | 'dontroute' | 'linger' | - 'broadcast' | 'sndbuf' | 'recbuf' | 'priority' | 'tos' | 'nodelay' | - 'multicast_ttl' | 'multicast_loop' | 'multicast_if' | - 'add_membership' | 'drop_membership' | - 'header' | 'buffer' | 'active' | 'packet' | 'mode' | 'port' | - 'exit_on_close' | 'low_watermark' | 'high_watermark' | 'bit8' | - 'send_timeout' | 'send_timeout_close' | - 'delay_send' | 'packet_size' | 'read_packets' | - %% SCTP options - {'sctp_status', #sctp_status{}} | - 'sctp_get_peer_addr_info' | - {'sctp_get_peer_addr_info', #sctp_status{}} | - 'sctp_rtoinfo' | - {'sctp_rtoinfo', #sctp_rtoinfo{}} | - 'sctp_associnfo' | - {'sctp_associnfo', #sctp_assocparams{}} | - 'sctp_initmsg' | - {'sctp_initmsg', #sctp_initmsg{}} | - 'sctp_nodelay' | 'sctp_autoclose' | 'sctp_disable_fragments' | - 'sctp_i_want_mapped_v4_addr' | 'sctp_maxseg' | - {'sctp_primary_addr', #sctp_prim{}} | - {'sctp_set_peer_primary_addr', #sctp_setpeerprim{}} | - 'sctp_adaptation_layer' | - {'sctp_adaptation_layer', #sctp_setadaptation{}} | - {'sctp_peer_addr_params', #sctp_paddrparams{}} | - 'sctp_default_send_param' | - {'sctp_default_send_param', #sctp_sndrcvinfo{}} | - 'sctp_events' | - {'sctp_events', #sctp_event_subscribe{}} | - 'sctp_delayed_ack_time' | - {'sctp_delayed_ack_time', #sctp_assoc_value{}}. - + gen_sctp:option_name() | gen_tcp:option_name() | gen_udp:option_name(). -type ether_address() :: [0..255]. -type if_setopt() :: @@ -196,7 +114,7 @@ 'addr' | 'broadaddr' | 'dstaddr' | 'mtu' | 'netmask' | 'flags' |'hwaddr'. --type family_option() :: 'inet' | 'inet6'. +-type address_family() :: 'inet' | 'inet6'. -type protocol_option() :: 'tcp' | 'udp' | 'sctp'. -type stat_option() :: 'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' | @@ -229,7 +147,7 @@ close(Socket) -> peername(Socket) -> prim_inet:peername(Socket). --spec setpeername(Socket :: socket(), Address :: {ip_address(), ip_port()}) -> +-spec setpeername(Socket :: socket(), Address :: {ip_address(), port_number()}) -> 'ok' | {'error', any()}. setpeername(Socket, {IP,Port}) -> @@ -246,7 +164,7 @@ setpeername(Socket, undefined) -> sockname(Socket) -> prim_inet:sockname(Socket). --spec setsockname(Socket :: socket(), Address :: {ip_address(), ip_port()}) -> +-spec setsockname(Socket :: socket(), Address :: {ip_address(), port_number()}) -> 'ok' | {'error', any()}. setsockname(Socket, {IP,Port}) -> @@ -254,7 +172,9 @@ setsockname(Socket, {IP,Port}) -> setsockname(Socket, undefined) -> prim_inet:setsockname(Socket, undefined). --spec port(Socket :: socket()) -> {'ok', ip_port()} | {'error', any()}. +-spec port(Socket) -> {'ok', Port} | {'error', any()} when + Socket :: socket(), + Port :: port_number(). port(Socket) -> case prim_inet:sockname(Socket) of @@ -268,16 +188,18 @@ port(Socket) -> send(Socket, Packet) -> prim_inet:send(Socket, Packet). --spec setopts(Socket :: socket(), Opts :: [socket_setopt()]) -> - 'ok' | {'error', posix()}. +-spec setopts(Socket, Options) -> ok | {error, posix()} when + Socket :: socket(), + Options :: [socket_setopt()]. setopts(Socket, Opts) -> prim_inet:setopts(Socket, Opts). -spec getopts(Socket, Options) -> - {'ok', [socket_setopt()]} | {'error', posix()} when + {'ok', OptionValues} | {'error', posix()} when Socket :: socket(), - Options :: [socket_getopt()]. + Options :: [socket_getopt()], + OptionValues :: [socket_setopt()]. getopts(Socket, Opts) -> prim_inet:getopts(Socket, Opts). @@ -419,14 +341,19 @@ gethostname() -> gethostname(Socket) -> prim_inet:gethostname(Socket). --spec getstat(Socket :: socket()) -> - {'ok', [{stat_option(), integer()}]} | {'error', posix()}. +-spec getstat(Socket) -> + {ok, OptionValues} | {error, posix()} when + Socket :: socket(), + OptionValues :: [{stat_option(), integer()}]. getstat(Socket) -> prim_inet:getstat(Socket, stats()). --spec getstat(Socket :: socket(), Statoptions :: [stat_option()]) -> - {'ok', [{stat_option(), integer()}]} | {'error', posix()}. +-spec getstat(Socket, Options) -> + {ok, OptionValues} | {error, posix()} when + Socket :: socket(), + Options :: [stat_option()], + OptionValues :: [{stat_option(), integer()}]. getstat(Socket,What) -> prim_inet:getstat(Socket, What). @@ -441,14 +368,14 @@ gethostbyname(Name) -> -spec gethostbyname(Hostname, Family) -> {ok, Hostent} | {error, posix()} when Hostname :: hostname(), - Family :: family_option(), + Family :: address_family(), Hostent :: hostent(). gethostbyname(Name,Family) -> gethostbyname_tm(Name, Family, false). -spec gethostbyname(Name :: hostname(), - Family :: family_option(), + Family :: address_family(), Timeout :: non_neg_integer() | 'infinity') -> {'ok', #hostent{}} | {'error', posix()}. @@ -527,14 +454,14 @@ getfd(Socket) -> -spec getaddr(Host, Family) -> {ok, Address} | {error, posix()} when Host :: ip_address() | hostname(), - Family :: family_option(), + Family :: address_family(), Address :: ip_address(). getaddr(Address, Family) -> getaddr(Address, Family, infinity). -spec getaddr(Host :: ip_address() | hostname(), - Family :: family_option(), + Family :: address_family(), Timeout :: non_neg_integer() | 'infinity') -> {'ok', ip_address()} | {'error', posix()}. @@ -553,14 +480,14 @@ getaddr_tm(Address, Family, Timer) -> -spec getaddrs(Host, Family) -> {ok, Addresses} | {error, posix()} when Host :: ip_address() | hostname(), - Family :: family_option(), + Family :: address_family(), Addresses :: [ip_address()]. getaddrs(Address, Family) -> getaddrs(Address, Family, infinity). -spec getaddrs(Host :: ip_address() | string() | atom(), - Family :: family_option(), + Family :: address_family(), Timeout :: non_neg_integer() | 'infinity') -> {'ok', [ip_address()]} | {'error', posix()}. @@ -570,7 +497,7 @@ getaddrs(Address, Family, Timeout) -> stop_timer(Timer), Res. --spec getservbyport(Port :: ip_port(), Protocol :: atom() | string()) -> +-spec getservbyport(Port :: port_number(), Protocol :: atom() | string()) -> {'ok', string()} | {'error', posix()}. getservbyport(Port, Proto) -> @@ -584,7 +511,7 @@ getservbyport(Port, Proto) -> -spec getservbyname(Name :: atom() | string(), Protocol :: atom() | string()) -> - {'ok', ip_port()} | {'error', posix()}. + {'ok', port_number()} | {'error', posix()}. getservbyname(Name, Protocol) when is_atom(Name) -> case inet_udp:open(0, []) of @@ -1067,7 +994,7 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) -> -spec open(Fd :: integer(), Addr :: ip_address(), - Port :: ip_port(), + Port :: port_number(), Opts :: [socket_setopt()], Protocol :: protocol_option(), Family :: 'inet' | 'inet6', @@ -1108,7 +1035,7 @@ open(Fd, _Addr, _Port, Opts, Protocol, Family, Module) -> -spec fdopen(Fd :: non_neg_integer(), Opts :: [socket_setopt()], Protocol :: protocol_option(), - Family :: family_option(), + Family :: address_family(), Module :: atom()) -> {'ok', socket()} | {'error', posix()}. diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl index d1f5644ff7..59ba408d7a 100644 --- a/lib/kernel/src/inet_res.erl +++ b/lib/kernel/src/inet_res.erl @@ -407,7 +407,7 @@ gethostbyname(Name) -> -spec gethostbyname(Name, Family) -> {ok, Hostent} | {error, Reason} when Name :: dns_name(), Hostent :: inet:hostent(), - Family :: inet:family_option(), + Family :: inet:address_family(), Reason :: inet:posix() | res_error(). gethostbyname(Name,Family) -> @@ -418,7 +418,7 @@ gethostbyname(Name,Family) -> Name :: dns_name(), Hostent :: inet:hostent(), Timeout :: timeout(), - Family :: inet:family_option(), + Family :: inet:address_family(), Reason :: inet:posix() | res_error(). gethostbyname(Name,Family,Timeout) -> diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl index 4ae4151004..2c5b8ccb66 100644 --- a/lib/kernel/test/application_SUITE.erl +++ b/lib/kernel/test/application_SUITE.erl @@ -967,7 +967,7 @@ otp_1586(doc) -> ["Test recursive load of applications."]; otp_1586(Conf) when is_list(Conf) -> Dir = ?config(priv_dir,Conf), - {ok, Fd} = file:open(filename:join(Dir, "app5.app"), write), + {ok, Fd} = file:open(filename:join(Dir, "app5.app"), [write]), w_app5(Fd), file:close(Fd), ?line code:add_patha(Dir), @@ -1021,10 +1021,10 @@ otp_2012(Conf) when is_list(Conf) -> ?line yes = global:register_name(conf_change, CcPid), % Write a .app file - {ok, Fd} = file:open("app1.app", write), + {ok, Fd} = file:open("app1.app", [write]), w_app1(Fd), file:close(Fd), - {ok, Fd2} = file:open("app2.app", write), + {ok, Fd2} = file:open("app2.app", [write]), w_app1(Fd2), file:close(Fd2), @@ -1096,7 +1096,7 @@ otp_2973(doc) -> ["Test of two processes simultanously starting the same application."]; otp_2973(Conf) when is_list(Conf) -> % Write a .app file - {ok, Fd} = file:open("app0.app", write), + {ok, Fd} = file:open("app0.app", [write]), w_app(Fd, app0()), file:close(Fd), @@ -1138,7 +1138,7 @@ otp_2973(Conf) when is_list(Conf) -> % Write a .app file - ?line {ok, Fda} = file:open("app_start_error.app", write), + ?line {ok, Fda} = file:open("app_start_error.app", [write]), ?line w_app_start_error(Fda), ?line file:close(Fda), @@ -1273,12 +1273,12 @@ otp_4066(Conf) when is_list(Conf) -> App1Nodes = {app1, AllNodes}, Dir = ?config(priv_dir,Conf), - ?line {ok, FdC} = file:open(filename:join(Dir, "otp_4066.config"), write), + ?line {ok, FdC} = file:open(filename:join(Dir, "otp_4066.config"), [write]), ?line write_config(FdC, config_4066(AllNodes, 5000, [App1Nodes])), ?line file:close(FdC), % Write the app1.app file - ?line {ok, FdA12} = file:open(filename:join(Dir, "app1.app"), write), + ?line {ok, FdA12} = file:open(filename:join(Dir, "app1.app"), [write]), ?line w_app1(FdA12), ?line file:close(FdA12), @@ -1441,7 +1441,7 @@ otp_5606(Conf) when is_list(Conf) -> %% Write a config file Dir = ?config(priv_dir, Conf), - {ok, Fd} = file:open(filename:join(Dir, "sys.config"), write), + {ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]), NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf), (config4(NodeNames))(Fd, 10000), file:close(Fd), @@ -2436,7 +2436,7 @@ start_node_config_sf(Name, SysConfigFun, Conf) -> write_config_file(SysConfigFun, Conf) -> Dir = ?config(priv_dir, Conf), - {ok, Fd} = file:open(filename:join(Dir, "sys.config"), write), + {ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]), SysConfigFun(Fd), file:close(Fd), filename:join(Dir,"sys"). @@ -2571,15 +2571,15 @@ cc(List) -> create_app() -> ?line Dir = "./", ?line App1 = Dir ++ "app1", - ?line {ok, Fd1} = file:open(App1++".app",write), + ?line {ok, Fd1} = file:open(App1++".app",[write]), ?line io:format(Fd1, "~p. \n", [app1()]), ?line file:close(Fd1), ?line App2 = Dir ++ "app2", - ?line {ok, Fd2} = file:open(App2++".app",write), + ?line {ok, Fd2} = file:open(App2++".app",[write]), ?line io:format(Fd2, "~p. \n", [app2()]), ?line file:close(Fd2), ?line App3 = Dir ++ "app_sp", - ?line {ok, Fd3} = file:open(App3++".app",write), + ?line {ok, Fd3} = file:open(App3++".app",[write]), ?line io:format(Fd3, "~p. \n", [app_sp()]), ?line file:close(Fd3), ok. @@ -2591,7 +2591,7 @@ create_script(ScriptName) -> ?line Apps = which_applications(), ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), - ?line {ok,Fd} = file:open(Name++".rel",write), + ?line {ok,Fd} = file:open(Name++".rel",[write]), ?line io:format(Fd, "{release, {\"Test release 3\", \"LATEST\"}, \n" " {erts, \"4.4\"}, \n" @@ -2610,7 +2610,7 @@ create_script_dc(ScriptName) -> ?line Apps = which_applications(), ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), - ?line {ok,Fd} = file:open(Name++".rel",write), + ?line {ok,Fd} = file:open(Name++".rel",[write]), ?line io:format(Fd, "{release, {\"Test release 3\", \"LATEST\"}, \n" " {erts, \"4.4\"}, \n" @@ -2630,7 +2630,7 @@ create_script_3002(ScriptName) -> ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), ?line {value,{_,_,SaslVer}} = lists:keysearch(sasl,1,Apps), - ?line {ok,Fd} = file:open(Name++".rel",write), + ?line {ok,Fd} = file:open(Name++".rel",[write]), ?line io:format(Fd, "{release, {\"Test release 3\", \"LATEST\"}, \n" " {erts, \"4.4\"}, \n" @@ -2646,22 +2646,22 @@ create_script_3002(ScriptName) -> distr_changed_prep(Conf) when is_list(Conf) -> % Write .app files - ?line {ok, Fd1} = file:open("app1.app", write), + ?line {ok, Fd1} = file:open("app1.app", [write]), ?line w_app1(Fd1), ?line file:close(Fd1), - ?line {ok, Fd2} = file:open("app2.app", write), + ?line {ok, Fd2} = file:open("app2.app", [write]), ?line w_app2(Fd2), ?line file:close(Fd2), - ?line {ok, Fd3} = file:open("app3.app", write), + ?line {ok, Fd3} = file:open("app3.app", [write]), ?line w_app3(Fd3), ?line file:close(Fd3), - ?line {ok, Fd4} = file:open("app6.app", write), + ?line {ok, Fd4} = file:open("app6.app", [write]), ?line w_app6(Fd4), ?line file:close(Fd4), - ?line {ok, Fd5} = file:open("app7.app", write), + ?line {ok, Fd5} = file:open("app7.app", [write]), ?line w_app7(Fd5), ?line file:close(Fd5), - ?line {ok, Fd6} = file:open("app8.app", write), + ?line {ok, Fd6} = file:open("app8.app", [write]), ?line w_app8(Fd6), ?line file:close(Fd6), @@ -2683,7 +2683,7 @@ distr_changed_prep(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config_dc(NodeNames)), ?line Dir = ?config(priv_dir,Conf), - ?line {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), write), + ?line {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]), ?line (config_dc2(NodeNames))(Fd_dc2), ?line file:close(Fd_dc2), ?line Config2 = filename:join(Dir, "sys2"), diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 3ad49254f1..86cccebc29 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -258,8 +258,8 @@ replace_path(Config) when is_list(Config) -> %% Add a completly new application. - NewAppName = "blurf_blarfer", - ?line NewAppDir = filename:join(Cwd, NewAppName ++ "-6.33.1"), + NewAppName = 'blurf_blarfer', + ?line NewAppDir = filename:join(Cwd, atom_to_list(NewAppName) ++ "-6.33.1"), ?line ok = file:make_dir(NewAppDir), ?line true = code:replace_path(NewAppName, NewAppDir), ?line NewAppDir = code:lib_dir(NewAppName), @@ -410,8 +410,10 @@ all_loaded_1() -> ?line Loaded2 = match_and_remove(Preloaded, Loaded1), ObjExt = code:objfile_extension(), - ?line [] = lists:filter(fun({Mod,AbsName}) when is_atom(Mod), is_list(AbsName) -> - Mod =:= filename:basename(AbsName, ObjExt); + ?line [] = lists:filter(fun({Mod,AbsName}) when is_atom(Mod), + is_list(AbsName) -> + Mod =/= list_to_atom(filename:basename(AbsName, + ObjExt)); (_) -> true end, Loaded2), @@ -1023,8 +1025,8 @@ mult_lib_roots(Config) when is_list(Config) -> "my_dummy_app-c/ebin/code_SUITE_mult_root_module"), %% Set up ERL_LIBS and start a slave node. - ErlLibs = filename:join(DataDir, first_root) ++ mult_lib_sep() ++ - filename:join(DataDir, second_root), + ErlLibs = filename:join(DataDir, "first_root") ++ mult_lib_sep() ++ + filename:join(DataDir, "second_root"), ?line {ok,Node} = ?t:start_node(mult_lib_roots, slave, @@ -1344,7 +1346,7 @@ create_script(Config) -> ?line Apps = application_controller:which_applications(), ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel, 1, Apps), ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib, 1, Apps), - ?line {ok,Fd} = file:open(Name ++ ".rel", write), + ?line {ok,Fd} = file:open(Name ++ ".rel", [write]), ?line io:format(Fd, "{release, {\"Test release 3\", \"P2A\"}, \n" " {erts, \"9.42\"}, \n" @@ -1409,7 +1411,7 @@ create_big_script(Config,Local) -> %% Now we should have only "real" applications... ?line [application:load(list_to_atom(Y)) || {match,[Y]} <- [ re:run(X,code:lib_dir()++"/"++"([^/-]*).*/ebin",[{capture,[1],list}]) || X <- code:get_path()],filter_app(Y,Local)], ?line Apps = [ {N,V} || {N,_,V} <- application:loaded_applications()], - ?line {ok,Fd} = file:open(Name ++ ".rel", write), + ?line {ok,Fd} = file:open(Name ++ ".rel", [write]), ?line io:format(Fd, "{release, {\"Test release 3\", \"P2A\"}, \n" " {erts, \"9.42\"}, \n" diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index 4ae47b4762..ee1e2319b5 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -4917,7 +4917,7 @@ mark(FileName, What) -> ok = file:close(Fd). crash(File, Where) -> - {ok, Fd} = file:open(File, read_write), + {ok, Fd} = file:open(File, [read,write]), file:position(Fd, Where), ok = file:write(Fd, [10]), ok = file:close(Fd). @@ -4933,7 +4933,7 @@ writable(Fname) -> file:write_file_info(Fname, Info#file_info{mode = Mode}). truncate(File, Where) -> - {ok, Fd} = file:open(File, read_write), + {ok, Fd} = file:open(File, [read,write]), file:position(Fd, Where), ok = file:truncate(Fd), ok = file:close(Fd). diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index f47c4603cf..7599a89779 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -547,8 +547,6 @@ host() -> stop_node(Node) -> test_server:stop_node(Node). -get_loader_flag({ose,_}) -> - " -loader ose_inet "; get_loader_flag(_) -> " -loader inet ". diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index fd4685cdad..cbaec2d6dd 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -158,6 +158,10 @@ t_shutdown_error(Config) when is_list(Config) -> t_fdopen(Config) when is_list(Config) -> ?line Question = "Aaaa... Long time ago in a small town in Germany,", + ?line Question1 = list_to_binary(Question), + ?line Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ", + ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]], + ?line Question1 = iolist_to_binary(Question2), ?line Answer = "there was a shoemaker, Schumacher was his name.", ?line {ok, L} = gen_tcp:listen(0, [{active, false}]), ?line {ok, Port} = inet:port(L), @@ -167,6 +171,10 @@ t_fdopen(Config) when is_list(Config) -> ?line {ok, Server} = gen_tcp:fdopen(FD, []), ?line ok = gen_tcp:send(Client, Question), ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), + ?line ok = gen_tcp:send(Client, Question1), + ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), + ?line ok = gen_tcp:send(Client, Question2), + ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), ?line ok = gen_tcp:send(Server, Answer), ?line {ok, Answer} = gen_tcp:recv(Client, length(Answer), 2000), ?line ok = gen_tcp:close(Client), diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl index d8a5519195..514deaf065 100644 --- a/lib/kernel/test/gen_udp_SUITE.erl +++ b/lib/kernel/test/gen_udp_SUITE.erl @@ -201,13 +201,21 @@ binary_passive_recv(suite) -> binary_passive_recv(doc) -> ["OTP-3823 gen_udp:recv does not return address in binary mode"]; binary_passive_recv(Config) when is_list(Config) -> - ?line D = "The quick brown fox jumps over a lazy dog", - ?line B = list_to_binary(D), + ?line D1 = "The quick brown fox jumps over a lazy dog", + ?line D2 = list_to_binary(D1), + ?line D3 = ["The quick", <<" brown ">>, "fox jumps ", <<"over ">>, + <<>>, $a, [[], " lazy ", <<"dog">>]], + ?line D2 = iolist_to_binary(D3), + ?line B = D2, ?line {ok, R} = gen_udp:open(0, [binary, {active, false}]), ?line {ok, RP} = inet:port(R), ?line {ok, S} = gen_udp:open(0), ?line {ok, SP} = inet:port(S), - ?line ok = gen_udp:send(S, localhost, RP, D), + ?line ok = gen_udp:send(S, localhost, RP, D1), + ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1), + ?line ok = gen_udp:send(S, localhost, RP, D2), + ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1), + ?line ok = gen_udp:send(S, localhost, RP, D3), ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1), ?line ok = gen_udp:close(S), ?line ok = gen_udp:close(R), @@ -400,6 +408,7 @@ open_fd(Config) when is_list(Config) -> {ok,S1} = gen_udp:open(0), {ok,P2} = inet:port(S1), {ok,FD} = prim_inet:getfd(S1), + {error,einval} = gen_udp:open(P2, [inet6, {fd,FD}]), {ok,S2} = gen_udp:open(P2, [{fd,FD}]), {ok,S3} = gen_udp:open(0), {ok,P3} = inet:port(S3), diff --git a/lib/kernel/test/global_group_SUITE.erl b/lib/kernel/test/global_group_SUITE.erl index 13b2fd07b5..799b0d9d05 100644 --- a/lib/kernel/test/global_group_SUITE.erl +++ b/lib/kernel/test/global_group_SUITE.erl @@ -100,7 +100,7 @@ start_gg_proc(Config) when is_list(Config) -> ?line Dir = ?config(priv_dir, Config), ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd}=file:open(File, write), + ?line {ok, Fd}=file:open(File, [write]), [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config), ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), @@ -135,7 +135,7 @@ no_gg_proc(Config) when is_list(Config) -> ?line Dir = ?config(priv_dir, Config), ?line File = filename:join(Dir, "no_global_group.config"), - ?line {ok, Fd} = file:open(File, write), + ?line {ok, Fd} = file:open(File, [write]), ?line config_no(Fd), ?line NN = node_name(atom_to_list(node())), @@ -308,7 +308,7 @@ no_gg_proc_sync(Config) when is_list(Config) -> ?line Dir = ?config(priv_dir, Config), ?line File = filename:join(Dir, "no_global_group_sync.config"), - ?line {ok, Fd} = file:open(File, write), + ?line {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] = node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config), @@ -482,7 +482,7 @@ compatible(Config) when is_list(Config) -> ?line Dir = ?config(priv_dir, Config), ?line File = filename:join(Dir, "global_group_comp.config"), - ?line {ok, Fd} = file:open(File, write), + ?line {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] = node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config), @@ -655,7 +655,7 @@ one_grp(Config) when is_list(Config) -> ?line Dir = ?config(priv_dir, Config), ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd} = file:open(File, write), + ?line {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config), ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), @@ -742,7 +742,7 @@ one_grp_x(Config) when is_list(Config) -> ?line Dir = ?config(priv_dir, Config), ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd} = file:open(File, write), + ?line {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config), ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), @@ -804,7 +804,7 @@ two_grp(Config) when is_list(Config) -> ?line Dir = ?config(priv_dir, Config), ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd} = file:open(File, write), + ?line {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] = node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config), @@ -1104,7 +1104,7 @@ hidden_groups(Config) when is_list(Config) -> ?line Dir = ?config(priv_dir, Config), ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd} = file:open(File, write), + ?line {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] = node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config), diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index 2db0f7dcb8..b39fadd65f 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -656,7 +656,7 @@ create_script(Config) -> ?line Apps = application_controller:which_applications(), ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), - ?line {ok,Fd} = file:open(Name ++ ".rel", write), + ?line {ok,Fd} = file:open(Name ++ ".rel", [write]), ?line io:format(Fd, "{release, {\"Test release 3\", \"P2A\"}, \n" " {erts, \"4.4\"}, \n" diff --git a/lib/kernel/test/ram_file_SUITE.erl b/lib/kernel/test/ram_file_SUITE.erl index 9b3fbb91fc..ab95a3ff5f 100644 --- a/lib/kernel/test/ram_file_SUITE.erl +++ b/lib/kernel/test/ram_file_SUITE.erl @@ -552,7 +552,7 @@ large_file_light(Config) when is_list(Config) -> ?line PrivDir = ?config(priv_dir, Config), %% Marker for next test case that is to heavy to run in a suite. ?line ok = ?FILE_MODULE:write_file( - filename:join(PrivDir, large_file_light), + filename:join(PrivDir, "large_file_light"), <<"TAG">>), %% ?line Data = "abcdefghijklmnopqrstuvwzyz", @@ -582,7 +582,7 @@ large_file_heavy(Config) when is_list(Config) -> ?line PrivDir = ?config(priv_dir, Config), %% Check previous test case marker. case ?FILE_MODULE:read_file_info( - filename:join(PrivDir, large_file_light)) of + filename:join(PrivDir, "large_file_light")) of {ok,_} -> {skipped,"Too heavy for casual testing!"}; _ -> diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl index 9eb84c9167..4ad9c6923d 100644 --- a/lib/kernel/test/zlib_SUITE.erl +++ b/lib/kernel/test/zlib_SUITE.erl @@ -412,6 +412,7 @@ api_crc32(Config) when is_list(Config) -> Compressed = list_to_binary(Compressed1 ++ Compressed2), CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)), ?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,Bin)), + ?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,binary_to_list(Bin))), ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,Compressed)), CRC2 = ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,0,Compressed)), ?m(CRC3 when CRC2 /= CRC3, zlib:crc32(Z1,234,Compressed)), @@ -437,6 +438,7 @@ api_adler32(Config) when is_list(Config) -> Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)), Compressed = list_to_binary(Compressed1 ++ Compressed2), ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,Bin)), + ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,binary_to_list(Bin))), ADLER2 = ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,Compressed)), ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,1,Compressed)), ?m(ADLER3 when ADLER2 /= ADLER3, zlib:adler32(Z1,234,Compressed)), @@ -464,6 +466,7 @@ api_un_compress(Config) when is_list(Config) -> ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3>>)), ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3,0>>)), ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<0,156,3,0,0,0,0,1>>)), + ?m(Bin, zlib:uncompress(binary_to_list(Comp))), ?m(Bin, zlib:uncompress(Comp)). api_un_zip(doc) -> "Test zip"; @@ -472,10 +475,12 @@ api_un_zip(Config) when is_list(Config) -> ?m(?BARG,zlib:zip(not_a_binary)), Bin = <<1,11,1,23,45>>, ?line Comp = zlib:zip(Bin), + ?m(Comp, zlib:zip(binary_to_list(Bin))), ?m(?BARG,zlib:unzip(not_a_binary)), ?m({'EXIT',{data_error,_}}, zlib:unzip(<<171,171,171,171,171>>)), ?m({'EXIT',{data_error,_}}, zlib:unzip(<<>>)), ?m(Bin, zlib:unzip(Comp)), + ?m(Bin, zlib:unzip(binary_to_list(Comp))), %% OTP-6396 B = <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97,1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2,10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97,116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101,104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112,114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101,100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100,101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181,107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57,57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4,10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125,248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203,251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0,200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94,13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0,108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,106>>, @@ -504,10 +509,12 @@ api_g_un_zip(Config) when is_list(Config) -> ?m(?BARG,zlib:gzip(not_a_binary)), Bin = <<1,11,1,23,45>>, ?line Comp = zlib:gzip(Bin), + ?m(Comp, zlib:gzip(binary_to_list(Bin))), ?m(?BARG, zlib:gunzip(not_a_binary)), ?m(?DATA_ERROR, zlib:gunzip(<<171,171,171,171,171>>)), ?m(?DATA_ERROR, zlib:gunzip(<<>>)), ?m(Bin, zlib:gunzip(Comp)), + ?m(Bin, zlib:gunzip(binary_to_list(Comp))), %% Bad CRC; bad length. BadCrc = bad_crc_data(), @@ -844,6 +851,7 @@ dictionary_usage({run}) -> ?m(ok, zlib:inflateInit(Z2)), ?line {'EXIT',{{need_dictionary,DictID},_}} = (catch zlib:inflate(Z2, Compressed)), ?m(ok, zlib:inflateSetDictionary(Z2, Dict)), + ?m(ok, zlib:inflateSetDictionary(Z2, binary_to_list(Dict))), ?line Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])), ?m(ok, zlib:inflateEnd(Z2)), ?m(ok, zlib:close(Z2)), diff --git a/lib/observer/src/Makefile b/lib/observer/src/Makefile index 2d06cb6bc4..3875b62101 100644 --- a/lib/observer/src/Makefile +++ b/lib/observer/src/Makefile @@ -56,13 +56,16 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET) PRIVDIR= ../priv WEBTOOLFILES= $(PRIVDIR)/crashdump_viewer.tool BINDIR= $(PRIVDIR)/bin +ifeq ($(findstring win32,$(TARGET)),win32) +WIN32_EXECUTABLES= $(BINDIR)/etop.bat $(BINDIR)/getop.bat $(BINDIR)/cdv.bat +else +WIN32_EXECUTABLES= +endif EXECUTABLES= \ $(BINDIR)/etop \ $(BINDIR)/getop \ $(BINDIR)/cdv \ - $(BINDIR)/etop.bat \ - $(BINDIR)/getop.bat \ - $(BINDIR)/cdv.bat + $(WIN32_EXECUTABLES) CDVDIR= $(PRIVDIR)/crashdump_viewer GIF_FILES= \ $(CDVDIR)/collapsd.gif \ diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c index 11e311d72d..ab2d7fe210 100644 --- a/lib/odbc/c_src/odbcserver.c +++ b/lib/odbc/c_src/odbcserver.c @@ -772,6 +772,7 @@ static db_result_msg db_param_query(byte *buffer, db_state *state) } associated_result_set(state) = FALSE; param_query(state) = TRUE; + out_params(state) = FALSE; msg = encode_empty_message(); diff --git a/lib/odbc/test/mysql.erl b/lib/odbc/test/mysql.erl index 49068c4356..c990793213 100644 --- a/lib/odbc/test/mysql.erl +++ b/lib/odbc/test/mysql.erl @@ -26,7 +26,22 @@ %------------------------------------------------------------------------- connection_string() -> - "DSN=MySQL;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';". + case test_server:os_type() of + {unix, linux} -> + "DSN=MySQL;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';"; + {unix, sunos} -> + solaris_str(); + {unix, darwin} -> + "DSN=MySQLMac;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';" + end. + +solaris_str() -> + case erlang:system_info(system_architecture) of + "sparc" ++ _ -> + "DSN=MySQLSolaris10;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';"; + "i386" ++ _ -> + "DSN=MySQLSolaris10i386;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';" + end. %------------------------------------------------------------------------- insert_result() -> diff --git a/lib/odbc/test/odbc_connect_SUITE.erl b/lib/odbc/test/odbc_connect_SUITE.erl index e59be772e3..a076c4dfff 100644 --- a/lib/odbc/test/odbc_connect_SUITE.erl +++ b/lib/odbc/test/odbc_connect_SUITE.erl @@ -76,20 +76,26 @@ end_per_group(_GroupName, Config) -> %% Note: This function is free to add any key/value pairs to the Config %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- -init_per_suite(Config) -> - case (catch odbc:start()) of - ok -> - case catch odbc:connect(?RDBMS:connection_string(), - [{auto_commit, off}] ++ odbc_test_lib:platform_options()) of - {ok, Ref} -> - odbc:disconnect(Ref), - [{tableName, odbc_test_lib:unique_table_name()} | Config]; - _ -> - {skip, "ODBC is not properly setup"} - end; - _ -> - {skip,"ODBC not startable"} - end. +init_per_suite(Config) when is_list(Config) -> + case odbc_test_lib:skip() of + true -> + {skip, "ODBC not supported"}; + false -> + case (catch odbc:start()) of + ok -> + case catch odbc:connect(?RDBMS:connection_string(), + [{auto_commit, off}] ++ odbc_test_lib:platform_options()) of + {ok, Ref} -> + odbc:disconnect(Ref), + [{tableName, odbc_test_lib:unique_table_name()} | Config]; + _ -> + {skip, "ODBC is not properly setup"} + end; + _ -> + {skip,"ODBC not startable"} + end + end. + %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ %% Config - [tuple()] diff --git a/lib/odbc/test/odbc_data_type_SUITE.erl b/lib/odbc/test/odbc_data_type_SUITE.erl index 099ae0aa7d..d61a91f973 100644 --- a/lib/odbc/test/odbc_data_type_SUITE.erl +++ b/lib/odbc/test/odbc_data_type_SUITE.erl @@ -89,17 +89,15 @@ init_per_group(GroupName, Config) when GroupName == fixed_char; end; init_per_group(unicode, Config) -> - %% Uses parameterized queries - case {os:type(), erlang:system_info(wordsize)} of + case {os:type(), erlang:system_info({wordsize, external})} of {{unix, _}, 4} -> Config; {{unix, _}, _} -> - {skip, "Not supported by driver"}; + {skip, "Postgres drivers pre version psqlODBC 08.04.0200 have utf8-problems"}; _ -> Config end; - init_per_group(_GroupName, Config) -> Config. @@ -115,14 +113,18 @@ end_per_group(_GroupName, Config) -> %% Note: This function is free to add any key/value pairs to the Config %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- -init_per_suite(Config) -> - case (catch odbc:start()) of - ok -> - [{tableName, odbc_test_lib:unique_table_name()} | Config]; - _ -> - {skip, "ODBC not startable"} +init_per_suite(Config) when is_list(Config) -> + case odbc_test_lib:skip() of + true -> + {skip, "ODBC not supported"}; + false -> + case (catch odbc:start()) of + ok -> + [{tableName, odbc_test_lib:unique_table_name()}| Config]; + _ -> + {skip, "ODBC not startable"} + end end. - %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ %% Config - [tuple()] diff --git a/lib/odbc/test/odbc_query_SUITE.erl b/lib/odbc/test/odbc_query_SUITE.erl index 76a214d553..1852678b4b 100644 --- a/lib/odbc/test/odbc_query_SUITE.erl +++ b/lib/odbc/test/odbc_query_SUITE.erl @@ -89,6 +89,7 @@ init_per_group(scrollable_cursors, Config) -> _ -> Config end; + init_per_group(_,Config) -> Config. @@ -105,11 +106,16 @@ end_per_group(_GroupName, Config) -> %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) when is_list(Config) -> - case (catch odbc:start()) of - ok -> - [{tableName, odbc_test_lib:unique_table_name()}| Config]; - _ -> - {skip, "ODBC not startable"} + case odbc_test_lib:skip() of + true -> + {skip, "ODBC not supported"}; + false -> + case (catch odbc:start()) of + ok -> + [{tableName, odbc_test_lib:unique_table_name()}| Config]; + _ -> + {skip, "ODBC not startable"} + end end. %%-------------------------------------------------------------------- diff --git a/lib/odbc/test/odbc_start_SUITE.erl b/lib/odbc/test/odbc_start_SUITE.erl index 440c0ca921..e3a3440559 100644 --- a/lib/odbc/test/odbc_start_SUITE.erl +++ b/lib/odbc/test/odbc_start_SUITE.erl @@ -39,11 +39,18 @@ %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) -> - case code:which(odbc) of - non_existing -> - {skip, "No ODBC built"}; - _ -> - [{tableName, odbc_test_lib:unique_table_name()} | Config] + case odbc_test_lib:skip() of + true -> + {skip, "ODBC not supported"}; + false -> + case code:which(odbc) of + non_existing -> + {skip, "No ODBC built"}; + _ -> + %% Make sure odbc is not already started + odbc:stop(), + [{tableName, odbc_test_lib:unique_table_name()} | Config] + end end. %%-------------------------------------------------------------------- diff --git a/lib/odbc/test/odbc_test.hrl b/lib/odbc/test/odbc_test.hrl index 397d04756b..f7bb338a7f 100644 --- a/lib/odbc/test/odbc_test.hrl +++ b/lib/odbc/test/odbc_test.hrl @@ -25,14 +25,16 @@ -define(RDBMS, case os:type() of {unix, sunos} -> - postgres; + mysql; {unix,linux} -> - case erlang:system_info(wordsize) of + case erlang:system_info({wordsize, external}) of 4 -> mysql; _ -> postgres end; + {unix, darwin} -> + mysql; {win32, _} -> sqlserver end). diff --git a/lib/odbc/test/odbc_test_lib.erl b/lib/odbc/test/odbc_test_lib.erl index 3e78105cf3..4d7d1ae2fa 100644 --- a/lib/odbc/test/odbc_test_lib.erl +++ b/lib/odbc/test/odbc_test_lib.erl @@ -36,7 +36,7 @@ match_float(Float, Match, Delta) -> (Float < Match + Delta) and (Float > Match - Delta). odbc_check() -> - case erlang:system_info(wordsize) of + case erlang:system_info({wordsize, external}) of 4 -> ok; Other -> @@ -71,9 +71,39 @@ strict(_,_) -> ok. platform_options() -> + []. + +skip() -> case os:type() of + {unix, linux} -> + Issue = linux_issue(), + is_sles9(Issue); {unix, sunos} -> - [{scrollable_cursors, off}]; + not supported_solaris(); _ -> - [] + false end. + +supported_solaris() -> + case os:version() of + {_,10,_} -> + true; + _ -> + false + end. + +linux_issue() -> + {ok, Binary} = file:read_file("/etc/issue"), + string:tokens(binary_to_list(Binary), " "). + +is_sles11(IssueTokens) -> + lists:member("11", IssueTokens). + +is_sles10(IssueTokens) -> + lists:member("10", IssueTokens). + +is_sles9(IssueTokens) -> + lists:member("9", IssueTokens). + +is_ubuntu(IssueTokens) -> + lists:member("Ubuntu", IssueTokens). diff --git a/lib/odbc/test/postgres.erl b/lib/odbc/test/postgres.erl index 26a2913d46..d564dbd5ff 100644 --- a/lib/odbc/test/postgres.erl +++ b/lib/odbc/test/postgres.erl @@ -30,7 +30,7 @@ connection_string() -> {unix, sunos} -> "DSN=Postgres;UID=odbctest"; {unix, linux} -> - Size = erlang:system_info(wordsize), + Size = erlang:system_info({wordsize, external}), linux_dist_connection_string(Size) end. @@ -43,7 +43,12 @@ linux_dist_connection_string(4) -> end; linux_dist_connection_string(_) -> - "DSN=PostgresLinux64;UID=odbctest". + case linux_dist() of + "ubuntu" -> + "DSN=PostgresLinux64Ubuntu;UID=odbctest"; + _ -> + "DSN=PostgresLinux64;UID=odbctest" + end. linux_dist() -> case file:read_file("/etc/issue") of diff --git a/lib/parsetools/doc/src/yecc.xml b/lib/parsetools/doc/src/yecc.xml index c712609cf4..1d2a985d7d 100644 --- a/lib/parsetools/doc/src/yecc.xml +++ b/lib/parsetools/doc/src/yecc.xml @@ -425,9 +425,9 @@ myparser:parse_and_scan({Mod, Tokenizer, Args}) </code> Nonterminals E T F. Terminals '+' '*' '(' ')' number. Rootsymbol E. -E -> E '+' T: ['$1', '$2', '$3']. +E -> E '+' T: ['$2', '$1', '$3']. E -> T : '$1'. -T -> T '*' F: ['$1', '$2', '$3']. +T -> T '*' F: ['$2', '$1', '$3']. T -> F : '$1'. F -> '(' E ')' : '$2'. F -> number : '$1'. </code> @@ -438,8 +438,8 @@ Terminals '+' '*' '(' ')' number. Rootsymbol E. Left 100 '+'. Left 200 '*'. -E -> E '+' E : ['$1', '$2', '$3']. -E -> E '*' E : ['$1', '$2', '$3']. +E -> E '+' E : ['$2', '$1', '$3']. +E -> E '*' E : ['$2', '$1', '$3']. E -> '(' E ')' : '$2'. E -> number : '$1'. </code> <p>3. An overloaded minus operator:</p> diff --git a/lib/percept/src/percept_db.erl b/lib/percept/src/percept_db.erl index 52e9afb78f..61b68ce44f 100644 --- a/lib/percept/src/percept_db.erl +++ b/lib/percept/src/percept_db.erl @@ -92,7 +92,7 @@ restart(PerceptDB)-> stop_sync(PerceptDB), do_start(). -%% @spec do_start(pid()) -> pid() +%% @spec do_start() -> pid() %% @private %% @doc starts the percept database. @@ -131,6 +131,7 @@ stop_sync(Pid)-> {'DOWN', MonitorRef, _Type, Pid, _Info}-> true after ?STOP_TIMEOUT-> + erlang:demonitor(MonitorRef, [flush]), exit(Pid, kill) end. @@ -166,14 +167,14 @@ insert(Trace) -> select(Query) -> percept_db ! {select, self(), Query}, - receive Match -> Match end. + receive {result, Match} -> Match end. %% @spec select(atom(), list()) -> Result %% @equiv select({Table,Options}) select(Table, Options) -> percept_db ! {select, self(), {Table, Options}}, - receive Match -> Match end. + receive {result, Match} -> Match end. %% @spec consolidate() -> Result %% @doc Checks timestamp and state-flow inconsistencies in the @@ -213,7 +214,7 @@ loop_percept_db() -> insert_trace(clean_trace(Trace)), loop_percept_db(); {select, Pid, Query} -> - Pid ! select_query(Query), + Pid ! {result, select_query(Query)}, loop_percept_db(); {action, stop} -> stopped; @@ -222,7 +223,7 @@ loop_percept_db() -> loop_percept_db(); {operate, Pid, {Table, {Fun, Start}}} -> Result = ets:foldl(Fun, Start, Table), - Pid ! Result, + Pid ! {result, Result}, loop_percept_db(); Unhandled -> io:format("loop_percept_db, unhandled query: ~p~n", [Unhandled]), diff --git a/lib/public_key/asn1/README b/lib/public_key/asn1/README index 5fb8cf9725..2a880e2d51 100644 --- a/lib/public_key/asn1/README +++ b/lib/public_key/asn1/README @@ -46,6 +46,6 @@ diff -r1.1 PKIXAttributeCertificate.asn1 --- > version AttCertVersion, -- version is v2 -4. Defenitions of publuic keys from PKCS-1.asn1 present in +4. Definitions of public keys from PKCS-1.asn1 present in PKIX1Algorithms88.asn1 where removed as we take them directly from PKCS-1.asn1
\ No newline at end of file diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index d60d91cd83..9a3832c68b 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -63,7 +63,7 @@ <p><code>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| 'RSAPublicKey' 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo'</code></p> - <p><code>pem_entry () = {pki_asn1_type(), binary() %% DER or encrypted DER + <p><code>pem_entry () = {pki_asn1_type(), binary(), %% DER or encrypted DER not_encrypted | {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}}.</code></p> <p><code>rsa_public_key() = #'RSAPublicKey'{}</code></p> @@ -72,8 +72,6 @@ <p><code>dsa_public_key() = {integer(), #'Dss-Parms'{}} </code></p> - <p><code>rsa_private_key() = #'RSAPrivateKey'{} </code></p> - <p><code>dsa_private_key() = #'DSAPrivateKey'{}</code></p> <p><code> public_crypt_options() = [{rsa_pad, rsa_padding()}]. </code></p> @@ -149,7 +147,7 @@ <name>der_decode(Asn1type, Der) -> term()</name> <fsummary> Decodes a public key asn1 der encoded entity.</fsummary> <type> - <v>Asn1Type = atom() -</v> + <v>Asn1Type = atom()</v> <d> ASN.1 type present in the public_key applications asn1 specifications.</d> <v>Der = der_encoded()</v> @@ -166,7 +164,8 @@ <v>Asn1Type = atom()</v> <d> Asn1 type present in the public_key applications ASN.1 specifications.</d> - <v>Entity = term() - The erlang representation of <c> Asn1Type</c></v> + <v>Entity = term()</v> + <d>The erlang representation of <c>Asn1Type</c></d> </type> <desc> <p> Encodes a public key entity with ASN.1 DER encoding.</p> @@ -218,12 +217,13 @@ <fsummary> Creates a pem entry that can be fed to pem_encode/1.</fsummary> <type> <v>Asn1Type = pki_asn1_type()</v> - <v>Entity = term() - The Erlang representation of + <v>Entity = term()</v> + <d>The Erlang representation of <c>Asn1Type</c>. If <c>Asn1Type</c> is 'SubjectPublicKeyInfo' then <c>Entity</c> must be either an rsa_public_key() or a dsa_public_key() and this function will create the appropriate 'SubjectPublicKeyInfo' entry. - </v> + </d> <v>CipherInfo = {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}</v> <v>Password = string()</v> </type> @@ -281,7 +281,7 @@ <desc> <p>Der encodes a pkix x509 certificate or part of such a certificate. This function must be used for encoding certificates or parts of certificates - that are decoded/created on the otp format, whereas for the plain format this + that are decoded/created in the otp format, whereas for the plain format this function will directly call der_encode/2. </p> </desc> </func> diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 2901020e83..33fcce2c44 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -488,9 +488,10 @@ pkix_path_validation(PathErr, [Cert | Chain], Options0) when is_atom(PathErr)-> _:_ -> {error, Reason} end; -pkix_path_validation(TrustedCert, CertChain, Options) when - is_binary(TrustedCert) -> OtpCert = pkix_decode_cert(TrustedCert, - otp), pkix_path_validation(OtpCert, CertChain, Options); +pkix_path_validation(TrustedCert, CertChain, Options) + when is_binary(TrustedCert) -> + OtpCert = pkix_decode_cert(TrustedCert, otp), + pkix_path_validation(OtpCert, CertChain, Options); pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options) when is_list(CertChain), is_list(Options) -> diff --git a/lib/sasl/examples/src/Makefile b/lib/sasl/examples/src/Makefile index 4a4e04a536..c58f651696 100644 --- a/lib/sasl/examples/src/Makefile +++ b/lib/sasl/examples/src/Makefile @@ -66,7 +66,7 @@ release_spec: opt $(INSTALL_DIR) $(RELSYSDIR)/examples/src $(INSTALL_DIR) $(RELSYSDIR)/examples/ebin (cd ..; tar cf - src ebin | (cd $(RELSYSDIR)/examples; tar xf -)) - chmod -f -R ug+w $(RELSYSDIR)/examples + chmod -R ug+w $(RELSYSDIR)/examples release_docs_spec: diff --git a/lib/sasl/test/Makefile b/lib/sasl/test/Makefile index 0bdb79a06a..65be134462 100644 --- a/lib/sasl/test/Makefile +++ b/lib/sasl/test/Makefile @@ -86,7 +86,7 @@ release_tests_spec: make_emakefile $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR) $(INSTALL_DATA) sasl.spec sasl.cover $(EMAKEFILE) $(RELSYSDIR) - chmod -f -R u+w $(RELSYSDIR) + chmod -R u+w $(RELSYSDIR) @tar cfh - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) release_docs_spec: diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 0d59f2e781..9e1a060dee 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -35,7 +35,7 @@ <section> <title>SNMP Development Toolkit 4.21.1</title> <p>Version 4.21.1 supports code replacement in runtime from/to - version 4.21, 4.20.1, 4.20 and 4.19. </p> + version 4.20.1, 4.20 and 4.19. </p> <section> <title>Improvements and new features</title> @@ -44,6 +44,18 @@ --> <list type="bulleted"> <item> + <p>[compiler] Used wrong variable name (for + warnings-as-errors variable), which caused the + compiler to crash when using the snmpc (e)script. </p> + <p>Also added the option + <seealso marker="snmpc(command)#option_werror">--Werror</seealso> + for the SNMP MIB compiler (escript) frontend (to mimic + <seealso marker="erts:erlc">erlc</seealso>), + which specifies whether warnings should be treated as errors. </p> + <p>Own Id: OTP-9447</p> + </item> + + <item> <p>[agent] Some very minor debugging improvements. </p> <p>Own Id: OTP-9446</p> </item> @@ -53,10 +65,9 @@ <section> <title>Fixed Bugs and Malfunctions</title> -<!-- <p>-</p> ---> +<!-- <list type="bulleted"> <item> <p>The snmp config tool could not handle (manager) audit trail config @@ -64,22 +75,8 @@ <p>Own Id: OTP-9354</p> </item> - <item> - <p>[agent] The SNMP ACM cache was not properly updated when - changes where made to the VACM security-to-group, access and - view-tree-family tables. </p> - <p>Own Id: OTP-9367</p> - <p>Aux Id: Seq 11858</p> - </item> - - <item> - <p>Fixed install directory typo for man3. </p> - <p>Peter Lemenkov</p> - <p>Hans Ulrich Niedermann</p> - <p>Own Id: OTP-9442</p> - </item> - </list> +--> </section> diff --git a/lib/snmp/doc/src/snmpc_cmd.xml b/lib/snmp/doc/src/snmpc_cmd.xml index 72116f8981..971f8a3cff 100644 --- a/lib/snmp/doc/src/snmpc_cmd.xml +++ b/lib/snmp/doc/src/snmpc_cmd.xml @@ -79,16 +79,18 @@ <p>Print debug info. </p> <p><c>verbosity</c> = <c>trace</c> | <c>debug</c> | <c>log</c> | <c>info</c> | <c>silence</c></p> <p>Defaults to <c>silence</c>.</p> + <marker id="option_w"></marker> <marker id="option_warnings"></marker> </item> - <tag>--warnings</tag> + <tag>--warnings | --W</tag> <item> <p>Print warning messages. </p> <marker id="option_wae"></marker> + <marker id="option_werror"></marker> </item> - <tag>--wae</tag> + <tag>--wae | --Werror</tag> <item> <p>Warnings as errors. Indicates that warnings shall be treated as errors. </p> @@ -211,7 +213,7 @@ <section> <title>SEE ALSO</title> - <p><seealso marker="erlc">erlc(1)</seealso>, + <p><seealso marker="erts:erlc">erlc(1)</seealso>, <seealso marker="compiler:compile">compile(3)</seealso>, <seealso marker="snmp:snmpc">snmpc(3)</seealso></p> </section> diff --git a/lib/snmp/src/compile/snmpc.src b/lib/snmp/src/compile/snmpc.src index 4e91ae9a03..f993335b89 100644 --- a/lib/snmp/src/compile/snmpc.src +++ b/lib/snmp/src/compile/snmpc.src @@ -46,7 +46,7 @@ agent_capabilities = false, module, no_defaults = false, - relaxed_row_name_assigne_check = false, + relaxed_row_name_assign_check = false, %% The default verbosity (silence) will be filled in %% during argument processing. verbosity, @@ -75,7 +75,7 @@ %% --version %% --verbosity V %% --warnings -%% --wae +%% --Werror | --wae | --warnings_as_errors main(Args) when is_list(Args) -> case (catch process_args(Args)) of ok -> @@ -154,7 +154,7 @@ mk_mib_options(#state{outdir = OutDir, agent_capabilities = AC, module = Mod, no_defaults = ND, - relaxed_row_name_assigne_check = RRNAC, + relaxed_row_name_assign_check = RRNAC, %% The default verbosity (silence) will be filled in %% during argument processing. verbosity = V, @@ -182,7 +182,7 @@ mk_mib_options(#state{outdir = OutDir, maybe_option(MI, module_identity) ++ maybe_option(MC, module_compliance) ++ maybe_option(AC, agent_capabilities) ++ - maybe_option(WE, warnings_as_errors). + maybe_option(WAE, warnings_as_errors). maybe_option(true, Opt) -> [Opt]; maybe_option(_, _) -> []. @@ -234,6 +234,8 @@ process_args(["--verbosity", Verbosity0|Args], #state{verbosity = V} = State) process_args(["--verbosity"|_Args], #state{verbosity = V}) when (V =/= undefined) -> e(lists:flatten(io_lib:format("Verbosity already set to ~w", [V]))); +process_args(["--w"|Args], State) -> + process_args(Args, State#state{warnings = true}); process_args(["--warnings"|Args], State) -> process_args(Args, State#state{warnings = true}); process_args(["--o", Dir|Args], State) -> @@ -295,9 +297,13 @@ process_args(["--mod"|_Args], #state{module = M}) process_args(["--nd"|Args], State) -> process_args(Args, State#state{no_defaults = true}); process_args(["--rrnac"|Args], State) -> - process_args(Args, State#state{relaxed_row_name_assigne_check = true}); + process_args(Args, State#state{relaxed_row_name_assign_check = true}); +process_args(["--Werror"|Args], State) -> + process_args(Args, State#state{warnings_as_errors = true}); process_args(["--wae"|Args], State) -> process_args(Args, State#state{warnings_as_errors = true}); +process_args(["--warnings_as_errors"|Args], State) -> + process_args(Args, State#state{warnings_as_errors = true}); process_args([MIB], State) -> Ext = filename:extension(MIB), if @@ -332,7 +338,7 @@ usage() -> "~n --verbosity <verbosity> - Print debug info." "~n verbosity = trace | debug | log | info | silence" "~n Defaults to silence." - "~n --warnings - Print warning messages." + "~n --warnings | --W - Print warning messages." "~n --o <output dir> - The output dir." "~n Defaults to current working dir." "~n --i <include dir> - Add this dir to the list of dirs that will be" @@ -340,16 +346,19 @@ usage() -> "~n The current workin dir will always be included. " "~n --il <include_lib dir> - Add this dir to the list of dirs that will be" "~n searched for imported (compiled) MIB files." - "~n It assumes that the first element in the dir name" - "~n correspond to an OTP application. For example snmp/mibs/" - "~n The current workin dir and the <snmp-home>/priv/mibs " + "~n It assumes that the first element in the dir " + "~n name correspond to an OTP application. " + "~n For example snmp/mibs/ " + "~n The current workin dir and the " + "~n <snmp-home>/priv/mibs " "~n are always listed last the includ path. " "~n --db <DB> - Database to used for the default instrumentation." "~n Defaults to volatile." - "~n --sgc - This option (skip group check), if present, disables " - "~n the \"group check\" of the mib compiler. " - "~n That is, should the OBJECT-GROUP and the NOTIFICATION-GROUP " - "~n macro(s) be checked for correctness or not. " + "~n --sgc - This option (skip group check), if present, " + "~n disables the \"group check\" of the mib compiler. " + "~n That is, should the OBJECT-GROUP and the " + "~n NOTIFICATION-GROUP macro(s) be checked for " + "~n correctness or not. " "~n By default the check is done. " "~n --dep - Keep deprecated definition(s)." "~n If not specified the compiler will ignore" @@ -360,25 +369,27 @@ usage() -> "~n --mi - The MODULE-IDENTITY field will be included." "~n --mc - The MODULE-COMPLIANCE field will be included." "~n --ac - The AGENT-CAPABILITIES field will be included." - "~n --mod <module> - The module which implements all the instrumentation" - "~n functions. " + "~n --mod <module> - The module which implements all the " + "~n instrumentation functions. " "~n The name of all instrumentation functions must" "~n be the same as the corresponding managed object" "~n it implements." - "~n --nd - The default instrumentation functions will *not* be used" - "~n if a managed object have no instrumentation function. " - "~n Instead this will be reported as an error, and the " - "~n compilation aborts. " - "~n --rrnac - This option, if present, specifies that the row name " - "~n assign check shall not be done strictly according to" - "~n the SMI (which allows only the value 1). " - "~n With this option, all values greater than zero is allowed" - "~n (>= 1). This means that the error will be converted to " + "~n --nd - The default instrumentation functions will *not* " + "~n be used if a managed object have no " + "~n instrumentation function. Instead this will be " + "~n reported as an error, and the compilation aborts. " + "~n --rrnac - This option, if present, specifies that the row " + "~n name assign check shall not be done strictly " + "~n according to the SMI (which allows only the " + "~n value 1). With this option, all values greater " + "~n than zero is allowed (>= 1). " + "~n This means that the error will be converted to " "~n a warning. " - "~n By default it is not included, but if this option is " - "~n present it will be. " - "~n --wae - Warnings as errors. " - "~n Indicates that warnings shall be treated as errors. " + "~n By default it is not included, but if this " + "~n option is present it will be. " + "~n --wae | --Werror - Warnings as errors. " + "~n Indicates that warnings shall be treated as " + "~n errors. " "~n " "~n", []), halt(1). diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl index 4f71c47bfa..a0a35e91c4 100644 --- a/lib/snmp/src/compile/snmpc_lib.erl +++ b/lib/snmp/src/compile/snmpc_lib.erl @@ -1754,12 +1754,12 @@ error(FormatStr, Data, Line) when is_list(FormatStr) -> exit(error). print_error(FormatStr, Data) when is_list(FormatStr) -> - ok = io:format("~s: Error: " ++ FormatStr,[get(filename)|Data]), + ok = io:format("~s: " ++ FormatStr,[get(filename)|Data]), put(errors,yes), io:format("~n"). print_error(FormatStr, Data,Line) when is_list(FormatStr) -> - ok = io:format("~s: ~w: Error: " ++ FormatStr,[get(filename), Line |Data]), + ok = io:format("~s: ~w: " ++ FormatStr,[get(filename), Line |Data]), put(errors,yes), io:format("~n"). diff --git a/lib/snmp/test/test_config/Makefile b/lib/snmp/test/test_config/Makefile index d7bebbc431..d65bb8abe2 100644 --- a/lib/snmp/test/test_config/Makefile +++ b/lib/snmp/test/test_config/Makefile @@ -155,23 +155,23 @@ release_spec: release_tests_spec: clean opt $(INSTALL_DIR) $(RELSYSDIR) - chmod -f -R u+w $(RELSYSDIR) + chmod -R u+w $(RELSYSDIR) $(INSTALL_DIR) $(RELSYSDIR)/agent - chmod -f -R u+w $(RELSYSDIR)/agent + chmod -R u+w $(RELSYSDIR)/agent $(INSTALL_DIR) $(RELSYSDIR)/agent/conf - chmod -f -R u+w $(RELSYSDIR)/agent/conf + chmod -R u+w $(RELSYSDIR)/agent/conf $(INSTALL_DIR) $(RELSYSDIR)/agent/db - chmod -f -R u+w $(RELSYSDIR)/agent/db + chmod -R u+w $(RELSYSDIR)/agent/db $(INSTALL_DIR) $(RELSYSDIR)/agent/log - chmod -f -R u+w $(RELSYSDIR)/agent/log + chmod -R u+w $(RELSYSDIR)/agent/log $(INSTALL_DIR) $(RELSYSDIR)/manager - chmod -f -R u+w $(RELSYSDIR)/manager + chmod -R u+w $(RELSYSDIR)/manager $(INSTALL_DIR) $(RELSYSDIR)/manager/conf - chmod -f -R u+w $(RELSYSDIR)/manager/conf + chmod -R u+w $(RELSYSDIR)/manager/conf $(INSTALL_DIR) $(RELSYSDIR)/manager/db - chmod -f -R u+w $(RELSYSDIR)/manager/db + chmod -R u+w $(RELSYSDIR)/manager/db $(INSTALL_DIR) $(RELSYSDIR)/manager/log - chmod -f -R u+w $(RELSYSDIR)/manager/log + chmod -R u+w $(RELSYSDIR)/manager/log $(INSTALL_DATA) $(SYS_CONFIG_FILES) $(RELSYSDIR) $(INSTALL_DATA) $(AGENT_CONFIG_FILES) $(RELSYSDIR)/agent/conf $(INSTALL_DATA) $(MANAGER_CONFIG_FILES) $(RELSYSDIR)/manager/conf diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 71f3941577..6fc4fdc43d 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -29,6 +29,20 @@ <file>notes.xml</file> </header> +<section><title>Ssh 2.0.8</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Calling ssh_sftp:stop_channel/1 resulted in that the trap_exit flag was + set to true for the invoking process.</p> + <p> + Own Id: OTP-9386 Aux Id: seq11865</p> + </item> + </list> + </section> +</section> + <section><title>Ssh 2.0.7</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src index 974145836c..150b7d86dd 100644 --- a/lib/ssh/src/ssh.appup.src +++ b/lib/ssh/src/ssh.appup.src @@ -19,13 +19,19 @@ {"%VSN%", [ - {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []}]}, + {"2.0.7", [{load_module, ssh_sftp, soft_purge, soft_purge, []}]}, + {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []}, + {load_module, ssh_sftp, soft_purge, soft_purge, []}]}, {"2.0.5", [{load_module, ssh_userreg, soft_purge, soft_purge, []}, + {load_module, ssh_sftp, soft_purge, soft_purge, []}, {load_module, ssh_connection_handler, soft_purge, soft_purge, [ssh_userreg]}]} ], [ - {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []}]}, + {"2.0.7", [{load_module, ssh_sftp, soft_purge, soft_purge, []}]}, + {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []}, + {load_module, ssh_sftp, soft_purge, soft_purge, []}]}, {"2.0.5", [{load_module, ssh_userreg, soft_purge, soft_purge, []}, + {load_module, ssh_sftp, soft_purge, soft_purge, []}, {load_module, ssh_connection_handler, soft_purge, soft_purge, [ssh_userreg]}]} ] }. diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl index 59e09fdd0f..f000558100 100755 --- a/lib/ssh/src/ssh_sftp.erl +++ b/lib/ssh/src/ssh_sftp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -130,9 +130,9 @@ start_channel(Host, Port, Opts) -> end. stop_channel(Pid) -> - case process_info(Pid, [trap_exit]) of - [{trap_exit, Bool}] -> - process_flag(trap_exit, true), + case is_process_alive(Pid) of + true -> + OldValue = process_flag(trap_exit, true), link(Pid), exit(Pid, ssh_sftp_stop_channel), receive @@ -145,9 +145,9 @@ stop_channel(Pid) -> ok end end, - process_flag(trap_exit, Bool), + process_flag(trap_exit, OldValue), ok; - undefined -> + false -> ok end. diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index 5a2a6de24a..1820924ed6 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -115,7 +115,7 @@ release_tests_spec: opt $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR) $(INSTALL_DATA) ssh.spec ssh.cover $(RELSYSDIR) $(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) $(RELSYSDIR) - chmod -f -R u+w $(RELSYSDIR) + chmod -R u+w $(RELSYSDIR) @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) release_docs_spec: diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index d79038df29..fe2b915d17 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,5 +1,5 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 2.0.7 +SSH_VSN = 2.0.8 APP_VSN = "ssh-$(SSH_VSN)" diff --git a/lib/ssl/c_src/esock_openssl.c b/lib/ssl/c_src/esock_openssl.c index 2621c9934e..0bc42958f0 100644 --- a/lib/ssl/c_src/esock_openssl.c +++ b/lib/ssl/c_src/esock_openssl.c @@ -1024,7 +1024,7 @@ static void info_callback(const SSL *ssl, int where, int ret) } } -/* This function is called whenever a SSL_CTX *ctx structure is +/* This function is called whenever an SSL_CTX *ctx structure is * freed. */ static void callback_data_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index b2d17925fd..e090b4e1ef 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -554,7 +554,7 @@ Own Id: OTP-8224</p> </item> <item> - <p>A ssl:ssl_accept/3 could crash a connection if the + <p>An ssl:ssl_accept/3 could crash a connection if the timing was wrong.</p> <p>Removed info message if the socket closed without a proper disconnect from the ssl layer. </p> <p>ssl:send/2 is now blocking until the @@ -770,7 +770,7 @@ <item> <p> The new ssl implementation released as a alfa in this - version supports upgrading of a tcp connection to a ssl + version supports upgrading of a tcp connection to an ssl connection so that http client and servers may implement RFC 2817.</p> <p> @@ -789,7 +789,7 @@ very crippled as the control of the ssl-socket was deep down in openssl making it hard if not impossible to support all inet options, ipv6 and upgrade of a tcp - connection to a ssl connection. The alfa version has a + connection to an ssl connection. The alfa version has a few limitations that will be removed before the ssl-4.0 release. Main differences and limitations in the alfa are listed below.</p> diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 566068beaf..0c4c8796be 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -35,7 +35,7 @@ <title>SSL</title> <list type="bulleted"> - <item>ssl requires the crypto an public_key applications.</item> + <item>ssl requires the crypto and public_key applications.</item> <item>Supported SSL/TLS-versions are SSL-3.0 and TLS-1.0 </item> <item>For security reasons sslv2 is not supported.</item> <item>Ephemeral Diffie-Hellman cipher suites are supported @@ -216,7 +216,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | application is encountered. Additionally it will be called when a certificate is considered valid by the path validation to allow access to each certificate in the path to the user - application. Note that the it will differentiate between the + application. Note that it will differentiate between the peer certificate and CA certificates by using valid_peer or valid as the second argument to the verify fun. See <seealso marker="public_key:cert_records">the public_key User's @@ -326,10 +326,10 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | </item> <tag>{fail_if_no_peer_cert, boolean()}</tag> - <item>Used together with {verify, verify_peer} by a ssl server. + <item>Used together with {verify, verify_peer} by an ssl server. If set to true, the server will fail if the client does not have a certificate to send, i.e. sends a empty certificate, if set to - false it will only fail if the client sends a invalid + false it will only fail if the client sends an invalid certificate (an empty certificate is considered valid). </item> @@ -343,10 +343,10 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | PeerCert, Compression, CipherSuite) -> boolean()}</tag> <item>Enables the ssl server to have a local policy for deciding if a session should be reused or not, - only meaning full if <c>reuse_sessions</c> is set to true. + only meaningful if <c>reuse_sessions</c> is set to true. SuggestedSessionId is a binary(), PeerCert is a DER encoded certificate, Compression is an enumeration integer - and CipherSuite of type ciphersuite(). + and CipherSuite is of type ciphersuite(). </item> </taglist> @@ -355,7 +355,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <section> <title>General</title> - <p>When a ssl socket is in active mode (the default), data from the + <p>When an ssl socket is in active mode (the default), data from the socket is delivered to the owner of the socket in the form of messages: </p> @@ -396,7 +396,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <name>connect(Socket, SslOptions, Timeout) -> {ok, SslSocket} | {error, Reason}</name> <fsummary> Upgrades a gen_tcp, or - equivalent, connected socket to a ssl socket. </fsummary> + equivalent, connected socket to an ssl socket. </fsummary> <type> <v>Socket = socket()</v> <v>SslOptions = [ssloption()]</v> @@ -405,7 +405,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <v>Reason = term()</v> </type> <desc> <p>Upgrades a gen_tcp, or equivalent, - connected socket to a ssl socket i.e. performs the + connected socket to an ssl socket i.e. performs the client-side ssl handshake.</p> </desc> </func> @@ -428,12 +428,12 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <func> <name>close(SslSocket) -> ok | {error, Reason}</name> - <fsummary>Close a ssl connection</fsummary> + <fsummary>Close an ssl connection</fsummary> <type> <v>SslSocket = sslsocket()</v> <v>Reason = term()</v> </type> - <desc><p>Close a ssl connection.</p> + <desc><p>Close an ssl connection.</p> </desc> </func> @@ -450,7 +450,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <v>Reason = term()</v> </type> <desc><p>Assigns a new controlling process to the ssl-socket. A - controlling process is the owner of a ssl-socket, and receives + controlling process is the owner of an ssl-socket, and receives all messages from the socket.</p> </desc> </func> @@ -496,14 +496,14 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <func> <name>listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}</name> - <fsummary>Creates a ssl listen socket.</fsummary> + <fsummary>Creates an ssl listen socket.</fsummary> <type> <v>Port = integer()</v> <v>Options = options()</v> <v>ListenSocket = sslsocket()</v> </type> <desc> - <p>Creates a ssl listen socket.</p> + <p>Creates an ssl listen socket.</p> </desc> </func> @@ -587,6 +587,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | the socket is closed.</p> </desc> </func> + <func> <name>setopts(Socket, Options) -> ok | {error, Reason}</name> <fsummary>Set socket options.</fsummary> @@ -646,7 +647,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | </type> <desc> <p> Upgrades a gen_tcp, or - equivalent, socket to a ssl socket i.e. performs the + equivalent, socket to an ssl socket i.e. performs the ssl server-side handshake.</p> <p><warning>Note that the listen socket should be in {active, false} mode before telling the client that the server is ready to upgrade diff --git a/lib/ssl/doc/src/ssl_protocol.xml b/lib/ssl/doc/src/ssl_protocol.xml index 6936408881..ca5cc8bc7a 100644 --- a/lib/ssl/doc/src/ssl_protocol.xml +++ b/lib/ssl/doc/src/ssl_protocol.xml @@ -31,11 +31,11 @@ </p> <p>By default erlang ssl is run over the TCP/IP protocol even - though you could plug in an other reliable transport protocol + though you could plug in any other reliable transport protocol with the same API as gen_tcp.</p> <p>If a client and server wants to use an upgrade mechanism, such as - defined by RFC2817, to upgrade a regular TCP/IP connection to a ssl + defined by RFC2817, to upgrade a regular TCP/IP connection to an ssl connection the erlang ssl API supports this. This can be useful for things such as supporting HTTP and HTTPS on the same port and implementing virtual hosting. diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml index 605290b6f9..ab837a156a 100644 --- a/lib/ssl/doc/src/using_ssl.xml +++ b/lib/ssl/doc/src/using_ssl.xml @@ -56,7 +56,7 @@ <code type="erl">1 server> ssl:start(). ok</code> - <p>Create a ssl listen socket</p> + <p>Create an ssl listen socket</p> <code type="erl">2 server> {ok, ListenSocket} = ssl:listen(9999, [{certfile, "cert.pem"}, {keyfile, "key.pem"},{reuseaddr, true}]). {ok,{sslsocket, [...]}}</code> @@ -90,7 +90,7 @@ ok</code> <section> <title>Upgrade example</title> - <note><p> To upgrade a TCP/IP connection to a ssl connection the + <note><p> To upgrade a TCP/IP connection to an ssl connection the client and server have to aggre to do so. Agreement may be accompliced by using a protocol such the one used by HTTP specified in RFC 2817.</p> </note> @@ -114,7 +114,7 @@ ok</code> <code type="erl">2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999, [], infinity).</code> <p>Make sure active is set to false before trying - to upgrade a connection to a ssl connection, otherwhise + to upgrade a connection to an ssl connection, otherwhise ssl handshake messages may be deliverd to the wrong process.</p> <code type="erl">4 server> inet:setopts(Socket, [{active, false}]). ok</code> @@ -124,7 +124,7 @@ ok</code> {certfile, "cert.pem"}, {keyfile, "key.pem"}]). {ok,{sslsocket,[...]}}</code> - <p> Upgrade to a ssl connection. Note that the client and server + <p> Upgrade to an ssl connection. Note that the client and server must agree upon the upgrade and the server must call ssl:accept/2 before the client calls ssl:connect/3.</p> <code type="erl">3 client>{ok, SSLSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"}, diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index a0aedbbbee..6074dab3ca 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -49,9 +49,12 @@ inet_ssl, %% inet options for internal ssl socket cb %% Callback info }). --type option() :: socketoption() | ssloption() | transportoption(). --type socketoption() :: term(). %% See gen_tcp and inet, import spec later when there is one to import --type ssloption() :: {verify, verify_type()} | +-type connect_option() :: socket_connect_option() | ssl_option() | transport_option(). +-type socket_connect_option() :: gen_tcp:connect_option(). +-type listen_option() :: socket_listen_option() | ssl_option() | transport_option(). +-type socket_listen_option() :: gen_tcp:listen_option(). + +-type ssl_option() :: {verify, verify_type()} | {verify_fun, {fun(), InitialUserState::term()}} | {fail_if_no_peer_cert, boolean()} | {depth, integer()} | {cert, Der::binary()} | {certfile, path()} | {key, Der::binary()} | @@ -66,7 +69,7 @@ string(). % (according to old API) -type ssl_imp() :: new | old. --type transportoption() :: {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}. +-type transport_option() :: {cb_info, {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}}. %%-------------------------------------------------------------------- @@ -96,15 +99,15 @@ stop() -> application:stop(ssl). %%-------------------------------------------------------------------- --spec connect(host() | port(), [option()]) -> {ok, #sslsocket{}} | +-spec connect(host() | inet:port_number(), [connect_option()]) -> {ok, #sslsocket{}} | {error, reason()}. --spec connect(host() | port(), [option()] | port_num(), timeout() | list()) -> +-spec connect(host() | inet:port_number(), [connect_option()] | inet:port_number(), timeout() | list()) -> {ok, #sslsocket{}} | {error, reason()}. --spec connect(host() | port(), port_num(), list(), timeout()) -> +-spec connect(host() | inet:port_number(), inet:port_number(), list(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Connect to a ssl server. +%% Description: Connect to an ssl server. %%-------------------------------------------------------------------- connect(Socket, SslOptions) when is_port(Socket) -> connect(Socket, SslOptions, infinity). @@ -148,10 +151,10 @@ connect(Host, Port, Options0, Timeout) -> end. %%-------------------------------------------------------------------- --spec listen(port_num(), [option()]) ->{ok, #sslsocket{}} | {error, reason()}. +-spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Creates a ssl listen socket. +%% Description: Creates an ssl listen socket. %%-------------------------------------------------------------------- listen(_Port, []) -> {error, enooptions}; @@ -177,7 +180,7 @@ listen(Port, Options0) -> -spec transport_accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Performs transport accept on a ssl listen socket +%% Description: Performs transport accept on an ssl listen socket %%-------------------------------------------------------------------- transport_accept(ListenSocket) -> transport_accept(ListenSocket, infinity). @@ -214,11 +217,11 @@ transport_accept(#sslsocket{} = ListenSocket, Timeout) -> %%-------------------------------------------------------------------- -spec ssl_accept(#sslsocket{}) -> ok | {error, reason()}. --spec ssl_accept(#sslsocket{} | port(), timeout()| [option()]) -> +-spec ssl_accept(#sslsocket{} | port(), timeout()| [ssl_option() | transport_option()]) -> ok | {ok, #sslsocket{}} | {error, reason()}. --spec ssl_accept(port(), [option()], timeout()) -> {ok, #sslsocket{}} | {error, reason()}. +-spec ssl_accept(port(), [ssl_option()| transport_option()], timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Performs accept on a ssl listen socket. e.i. performs +%% Description: Performs accept on an ssl listen socket. e.i. performs %% ssl handshake. %%-------------------------------------------------------------------- ssl_accept(ListenSocket) -> @@ -252,7 +255,7 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) -> %%-------------------------------------------------------------------- -spec close(#sslsocket{}) -> term(). %% -%% Description: Close a ssl connection +%% Description: Close an ssl connection %%-------------------------------------------------------------------- close(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}, fd = new_ssl}) -> CbMod:close(ListenSocket); @@ -373,7 +376,7 @@ select_part(plain, Cert, Opts) -> end. %%-------------------------------------------------------------------- --spec peername(#sslsocket{}) -> {ok, {tuple(), port_num()}} | {error, reason()}. +-spec peername(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}. %% %% Description: same as inet:peername/1. %%-------------------------------------------------------------------- @@ -402,7 +405,8 @@ cipher_suites(openssl) -> [ssl_cipher:openssl_suite_name(S) || S <- ssl_cipher:suites(Version)]. %%-------------------------------------------------------------------- --spec getopts(#sslsocket{}, [atom()]) -> {ok, [{atom(), term()}]} | {error, reason()}. +-spec getopts(#sslsocket{}, [gen_tcp:option_name()]) -> + {ok, [gen_tcp:option()]} | {error, reason()}. %% %% Description: Gets options %%-------------------------------------------------------------------- @@ -425,7 +429,7 @@ getopts(#sslsocket{} = Socket, OptionTags) -> ssl_broker:getopts(Socket, OptionTags). %%-------------------------------------------------------------------- --spec setopts(#sslsocket{}, [proplists:property()]) -> ok | {error, reason()}. +-spec setopts(#sslsocket{}, [gen_tcp:option()]) -> ok | {error, reason()}. %% %% Description: Sets options %%-------------------------------------------------------------------- @@ -466,7 +470,7 @@ shutdown(#sslsocket{pid = Pid, fd = new_ssl}, How) -> ssl_connection:shutdown(Pid, How). %%-------------------------------------------------------------------- --spec sockname(#sslsocket{}) -> {ok, {tuple(), port_num()}} | {error, reason()}. +-spec sockname(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}. %% %% Description: Same as inet:sockname/1 %%-------------------------------------------------------------------- diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 21b021afb0..5187d0f78f 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -127,11 +127,11 @@ send(Pid, Data) -> recv(Pid, Length, Timeout) -> sync_send_all_state_event(Pid, {recv, Length}, Timeout). %%-------------------------------------------------------------------- --spec connect(host(), port_num(), port(), {#ssl_options{}, #socket_options{}}, +-spec connect(host(), inet:port_number(), port(), {#ssl_options{}, #socket_options{}}, pid(), tuple(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Connect to a ssl server. +%% Description: Connect to an ssl server. %%-------------------------------------------------------------------- connect(Host, Port, Socket, Options, User, CbInfo, Timeout) -> try start_fsm(client, Host, Port, Socket, Options, User, CbInfo, @@ -141,11 +141,11 @@ connect(Host, Port, Socket, Options, User, CbInfo, Timeout) -> {error, ssl_not_started} end. %%-------------------------------------------------------------------- --spec ssl_accept(port_num(), port(), {#ssl_options{}, #socket_options{}}, +-spec ssl_accept(inet:port_number(), port(), {#ssl_options{}, #socket_options{}}, pid(), tuple(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Performs accept on a ssl listen socket. e.i. performs +%% Description: Performs accept on an ssl listen socket. e.i. performs %% ssl handshake. %%-------------------------------------------------------------------- ssl_accept(Port, Socket, Opts, User, CbInfo, Timeout) -> @@ -185,7 +185,7 @@ socket_control(Socket, Pid, CbModule) -> %%-------------------------------------------------------------------- -spec close(pid()) -> ok | {error, reason()}. %% -%% Description: Close a ssl connection +%% Description: Close an ssl connection %%-------------------------------------------------------------------- close(ConnectionPid) -> case sync_send_all_state_event(ConnectionPid, close) of @@ -212,14 +212,14 @@ shutdown(ConnectionPid, How) -> new_user(ConnectionPid, User) -> sync_send_all_state_event(ConnectionPid, {new_user, User}). %%-------------------------------------------------------------------- --spec sockname(pid()) -> {ok, {tuple(), port_num()}} | {error, reason()}. +-spec sockname(pid()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}. %% %% Description: Same as inet:sockname/1 %%-------------------------------------------------------------------- sockname(ConnectionPid) -> sync_send_all_state_event(ConnectionPid, sockname). %%-------------------------------------------------------------------- --spec peername(pid()) -> {ok, {tuple(), port_num()}} | {error, reason()}. +-spec peername(pid()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}. %% %% Description: Same as inet:peername/1 %%-------------------------------------------------------------------- @@ -277,7 +277,7 @@ renegotiation(ConnectionPid) -> %%==================================================================== %%-------------------------------------------------------------------- --spec start_link(atom(), host(), port_num(), port(), list(), pid(), tuple()) -> +-spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) -> {ok, pid()} | ignore | {error, reason()}. %% %% Description: Creates a gen_fsm process which calls Module:init/1 to diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 4e74aec4ac..453ea20f99 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -48,7 +48,7 @@ %% Internal application API %%==================================================================== %%-------------------------------------------------------------------- --spec client_hello(host(), port_num(), #connection_states{}, +-spec client_hello(host(), inet:port_number(), #connection_states{}, #ssl_options{}, boolean(), der_cert()) -> #client_hello{}. %% %% Description: Creates a client hello message. @@ -106,7 +106,7 @@ hello_request() -> %%-------------------------------------------------------------------- -spec hello(#server_hello{} | #client_hello{}, #ssl_options{}, - #connection_states{} | {port_num(), #session{}, db_handle(), + #connection_states{} | {inet:port_number(), #session{}, db_handle(), atom(), #connection_states{}, binary()}, boolean()) -> {tls_version(), session_id(), #connection_states{}}| {tls_version(), {resumed | new, #session{}}, @@ -383,8 +383,9 @@ master_secret(Version, #session{master_secret = Mastersecret}, ConnectionStates, Role) catch exit:Reason -> - error_logger:error_report("Key calculation failed due to ~p", - [Reason]), + Report = io_lib:format("Key calculation failed due to ~p", + [Reason]), + error_logger:error_report(Report), ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE) end; @@ -400,8 +401,9 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) -> SecParams, ConnectionStates, Role) catch exit:Reason -> - error_logger:error_report("Master secret calculation failed" - " due to ~p", [Reason]), + Report = io_lib:format("Master secret calculation failed" + " due to ~p", [Reason]), + error_logger:error_report(Report), ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE) end. diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index cc66246068..6bf1edc452 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -28,8 +28,7 @@ -type reply() :: term(). -type msg() :: term(). -type from() :: term(). --type host() :: string() | tuple(). --type port_num() :: integer(). +-type host() :: inet:ip_address() | inet:hostname(). -type session_id() :: 0 | binary(). -type tls_version() :: {integer(), integer()}. -type tls_atom_version() :: sslv3 | tlsv1. diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index b02815bfd8..725a085d1f 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -113,7 +113,7 @@ lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) -> issuer_candidate(PrevCandidateKey, DbHandle) -> ssl_certificate_db:issuer_candidate(PrevCandidateKey, DbHandle). %%-------------------------------------------------------------------- --spec client_session_id(host(), port_num(), #ssl_options{}, +-spec client_session_id(host(), inet:port_number(), #ssl_options{}, der_cert() | undefined) -> session_id(). %% %% Description: Select a session id for the client. @@ -122,7 +122,7 @@ client_session_id(Host, Port, SslOpts, OwnCert) -> call({client_session_id, Host, Port, SslOpts, OwnCert}). %%-------------------------------------------------------------------- --spec server_session_id(host(), port_num(), #ssl_options{}, +-spec server_session_id(host(), inet:port_number(), #ssl_options{}, der_cert()) -> session_id(). %% %% Description: Select a session id for the server. @@ -131,8 +131,8 @@ server_session_id(Port, SuggestedSessionId, SslOpts, OwnCert) -> call({server_session_id, Port, SuggestedSessionId, SslOpts, OwnCert}). %%-------------------------------------------------------------------- --spec register_session(port_num(), #session{}) -> ok. --spec register_session(host(), port_num(), #session{}) -> ok. +-spec register_session(inet:port_number(), #session{}) -> ok. +-spec register_session(host(), inet:port_number(), #session{}) -> ok. %% %% Description: Make the session available for reuse. %%-------------------------------------------------------------------- @@ -142,8 +142,8 @@ register_session(Host, Port, Session) -> register_session(Port, Session) -> cast({register_session, Port, Session}). %%-------------------------------------------------------------------- --spec invalidate_session(port_num(), #session{}) -> ok. --spec invalidate_session(host(), port_num(), #session{}) -> ok. +-spec invalidate_session(inet:port_number(), #session{}) -> ok. +-spec invalidate_session(host(), inet:port_number(), #session{}) -> ok. %% %% Description: Make the session unavailable for reuse. After %% a the session has been marked "is_resumable = false" for some while diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl index 4c3c0b9c58..72091fdd5f 100644 --- a/lib/ssl/src/ssl_record.erl +++ b/lib/ssl/src/ssl_record.erl @@ -342,7 +342,7 @@ get_tls_records_aux(<<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer), get_tls_records_aux(Rest, [#ssl_tls{type = ?CHANGE_CIPHER_SPEC, version = {MajVer, MinVer}, fragment = Data} | Acc]); -%% Matches a ssl v2 client hello message. +%% Matches an ssl v2 client hello message. %% The server must be able to receive such messages, from clients that %% are willing to use ssl v3 or higher, but have ssl v2 compatibility. get_tls_records_aux(<<1:1, Length0:15, Data0:Length0/binary, Rest/binary>>, diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl index 85c9fcb61c..bf738649f6 100644 --- a/lib/ssl/src/ssl_session.erl +++ b/lib/ssl/src/ssl_session.erl @@ -48,7 +48,7 @@ is_new(_ClientSuggestion, _ServerDecision) -> true. %%-------------------------------------------------------------------- --spec id({host(), port_num(), #ssl_options{}}, db_handle(), atom(), +-spec id({host(), inet:port_number(), #ssl_options{}}, db_handle(), atom(), undefined | binary()) -> binary(). %% %% Description: Should be called by the client side to get an id @@ -63,7 +63,7 @@ id(ClientInfo, Cache, CacheCb, OwnCert) -> end. %%-------------------------------------------------------------------- --spec id(port_num(), binary(), #ssl_options{}, db_handle(), +-spec id(inet:port_number(), binary(), #ssl_options{}, db_handle(), atom(), seconds(), binary()) -> binary(). %% %% Description: Should be called by the server side to get an id diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl index 66610817be..93969f628f 100644 --- a/lib/ssl/src/ssl_session_cache.erl +++ b/lib/ssl/src/ssl_session_cache.erl @@ -28,7 +28,7 @@ -export([init/1, terminate/1, lookup/2, update/3, delete/2, foldl/3, select_session/2]). --type key() :: {{host(), port_num()}, session_id()} | {port_num(), session_id()}. +-type key() :: {{host(), inet:port_number()}, session_id()} | {inet:port_number(), session_id()}. %%-------------------------------------------------------------------- -spec init(list()) -> db_handle(). %% Returns reference to the cache (opaque) @@ -91,7 +91,7 @@ foldl(Fun, Acc0, Cache) -> ets:foldl(Fun, Acc0, Cache). %%-------------------------------------------------------------------- --spec select_session(db_handle(), {host(), port_num()} | port_num()) -> [#session{}]. +-spec select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}]. %% %% Description: Selects a session that could be reused. Should be callable %% from any process. diff --git a/lib/ssl/src/ssl_ssl2.erl b/lib/ssl/src/ssl_ssl2.erl index b1005b1acb..30a3a5fc98 100644 --- a/lib/ssl/src/ssl_ssl2.erl +++ b/lib/ssl/src/ssl_ssl2.erl @@ -20,7 +20,7 @@ %% %%---------------------------------------------------------------------- %% Purpose: Handles sslv2 hello as clients supporting sslv2 and higher -%% will send a sslv2 hello. +%% will send an sslv2 hello. %%---------------------------------------------------------------------- -module(ssl_ssl2). diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml index 2512c84e18..54fefbe2b8 100644 --- a/lib/stdlib/doc/src/dets.xml +++ b/lib/stdlib/doc/src/dets.xml @@ -1105,7 +1105,7 @@ fun(X) -> {continue, X} end. </pre> <p>Terminate the traversal and return <c>[<anno>Value</anno> | Acc]</c>.</p> </item> </taglist> - <p>Any other value returned by <c><anno>Fun</anno></c> terminates the + <p>Any other value <c><anno>OtherValue</anno></c> returned by <c><anno>Fun</anno></c> terminates the traversal and is immediately returned. </p> </desc> diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml index d15383c621..e35b5adace 100644 --- a/lib/stdlib/doc/src/gen_fsm.xml +++ b/lib/stdlib/doc/src/gen_fsm.xml @@ -438,7 +438,7 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <fsummary>Initialize process and internal state name and state data.</fsummary> <type> <v>Args = term()</v> - <v>Return = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v> + <v>Result = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v> <v> | {ok,StateName,StateData,hibernate}</v> <v> | {stop,Reason} | ignore</v> <v> StateName = atom()</v> @@ -639,9 +639,9 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <v>StateName = atom()</v> <v>StateData = term()</v> <v>Result = {next_state,NextStateName,NewStateData}</v> - <v> > | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> > | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> > | {stop,Reason,NewStateData}</v> + <v> | {next_state,NextStateName,NewStateData,Timeout}</v> + <v> | {next_state,NextStateName,NewStateData,hibernate}</v> + <v> | {stop,Reason,NewStateData}</v> <v> NextStateName = atom()</v> <v> NewStateData = term()</v> <v> Timeout = int()>0 | infinity</v> diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index 009aa60faa..edd119d37a 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -150,9 +150,12 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} <p><c>Restart</c> defines when a terminated child process should be restarted. A <c>permanent</c> child process should always be restarted, a <c>temporary</c> child process should - never be restarted and a <c>transient</c> child process - should be restarted only if it terminates abnormally, i.e. - with another exit reason than <c>normal</c>.</p> + never be restarted (even when the supervisor's restart strategy + is <c>rest_for_one</c> or <c>one_for_all</c> and a sibling's + death causes the temporary process to be terminated) and a + <c>transient</c> child process should be restarted only if + it terminates abnormally, i.e. with another exit reason + than <c>normal</c>.</p> </item> <item> <p><c>Shutdown</c> defines how a child process should be diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml index 416df1f02c..b48ad8c1f3 100644 --- a/lib/stdlib/doc/src/unicode_usage.xml +++ b/lib/stdlib/doc/src/unicode_usage.xml @@ -52,7 +52,7 @@ <tag>UCS-4</tag> <item>Basically the same as UTF-32, but without some Unicode semantics, defined by IEEE and has little use as a separate encoding standard. For all normal (and possibly abnormal) usages, UTF-32 and UCS-4 are interchangeable.</item> </taglist> -<p>Certain ranges of characters are left unused and certain ranges are even deemed invalid. The most notable invalid range is 16#D800 - 16#DFFF, as the UTF-16 encoding does not allow for encoding of these numbers. It can be speculated that the UTF-16 encoding standard was, from the beginning, expected to be able to hold all Unicode characters in one 16-bit entity, but then had to be extended, leaving a whole in the Unicode range to cope with backward compatibility.</p> +<p>Certain ranges of characters are left unused and certain ranges are even deemed invalid. The most notable invalid range is 16#D800 - 16#DFFF, as the UTF-16 encoding does not allow for encoding of these numbers. It can be speculated that the UTF-16 encoding standard was, from the beginning, expected to be able to hold all Unicode characters in one 16-bit entity, but then had to be extended, leaving a hole in the Unicode range to cope with backward compatibility.</p> <p>Additionally, the codepoint 16#FEFF is used for byte order marks (BOM's) and use of that character is not encouraged in other contexts than that. It actually is valid though, as the character "ZWNBS" (Zero Width Non Breaking Space). BOM's are used to identify encodings and byte order for programs where such parameters are not known in advance. Byte order marks are more seldom used than one could expect, put their use is becoming more widely spread as they provide the means for programs to make educated guesses about the Unicode format of a certain file.</p> </section> <section> diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl index 671b5a9dd4..fa0641ffd9 100644 --- a/lib/stdlib/src/dets.erl +++ b/lib/stdlib/src/dets.erl @@ -411,7 +411,8 @@ init_table(Tab, InitFun) -> InitFun :: fun((Arg) -> Res), Arg :: read | close, Res :: end_of_input | {[object()], InitFun} | {Data, InitFun} | term(), - Options :: [{min_no_slots,no_slots()} | {format,term | bchunk}], + Options :: Option | [Option], + Option :: {min_no_slots,no_slots()} | {format,term | bchunk}, Reason :: term(), Data :: binary() | tuple(). @@ -871,11 +872,15 @@ to_ets(DTab, ETab) -> -spec traverse(Name, Fun) -> Return | {'error', Reason} when Name :: tab_name(), Fun :: fun((Object) -> FunReturn), - FunReturn :: 'continue' | {'continue', Val} | {'done', Value}, + Object :: object(), + FunReturn :: 'continue' + | {'continue', Val} + | {'done', Value} + | OtherValue, + Return :: [term()] | OtherValue, Val :: term(), Value :: term(), - Object :: object(), - Return :: [term()], + OtherValue :: term(), Reason :: term(). traverse(Tab, Fun) -> diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl index 478f05e792..3073fc0fb5 100644 --- a/lib/stdlib/src/erl_internal.erl +++ b/lib/stdlib/src/erl_internal.erl @@ -262,6 +262,7 @@ bif(bitsize, 1) -> true; bif(bit_size, 1) -> true; bif(bitstring_to_list, 1) -> true; bif(byte_size, 1) -> true; +bif(check_old_code, 1) -> true; bif(check_process_code, 2) -> true; bif(concat_binary, 1) -> true; bif(date, 0) -> true; diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index d67617260e..cd1bacd2f5 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -62,10 +62,10 @@ -type zip_create_option() :: term(). -type section() :: shebang - | {shebang, shebang()} + | {shebang, shebang() | default | undefined} | comment - | {comment, comment()} - | {emu_args, emu_args()} + | {comment, comment() | default | undefined} + | {emu_args, emu_args() | undefined} | {source, file:filename() | binary()} | {beam, file:filename() | binary()} | {archive, file:filename() | binary()} diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl index 2cbd6cdae7..2c7192a7e7 100644 --- a/lib/stdlib/src/eval_bits.erl +++ b/lib/stdlib/src/eval_bits.erl @@ -34,12 +34,12 @@ %% @type matchfun(). A closure which performs a match given a value, a %% pattern and an environment %% -%% @type field() represents a field in a "bin" +%% @type field(). Represents a field in a "bin". %%% Part 1: expression evaluation (binary construction) %% @spec expr_grp(Fields::[field()], Bindings::bindings(), -%% EvalFun::evalfun()) -> +%% EvalFun::evalfun(), term(), term()) -> %% {value, binary(), bindings()} %% %% @doc Returns a tuple with {value,Bin,Bs} where Bin is the binary @@ -192,9 +192,9 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0}, end. %%% Part 3: binary pattern matching -%% @spec match_bits(Fields::[field()], Bin::binary() +%% @spec match_bits(Fields::[field()], Bin::binary(), %% GlobalEnv::bindings(), LocalEnv::bindings(), -%% MatchFun::matchfun(),EvalFun::evalfun()) -> +%% MatchFun::matchfun(),EvalFun::evalfun(), term()) -> %% {match, bindings()} %% @doc Used to perform matching. If the match succeeds a new %% environment is returned. If the match have some syntactic or diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl index 165e03e506..0252cdf742 100644 --- a/lib/stdlib/src/io_lib.erl +++ b/lib/stdlib/src/io_lib.erl @@ -109,9 +109,9 @@ fwrite(Format, Args) -> fread(Chars, Format) -> io_lib_fread:fread(Chars, Format). --spec fread(Continuation, String, Format) -> Return when +-spec fread(Continuation, CharSpec, Format) -> Return when Continuation :: continuation() | [], - String :: string(), + CharSpec :: string() | eof, Format :: string(), Return :: {'more', Continuation1 :: continuation()} | {'done', Result, LeftOverChars :: string()}, diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 39d017d430..5129ba5074 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -461,6 +461,14 @@ obsolete_1(public_key, pem_to_der, 1) -> obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 -> {deprecated,{public_key,pem_entry_decode,1},"R15A"}; +%% Added in R14B03. +obsolete_1(docb_gen, _, _) -> + {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"}; +obsolete_1(docb_transform, _, _) -> + {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"}; +obsolete_1(docb_xml_check, _, _) -> + {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"}; + obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/src/proplists.erl b/lib/stdlib/src/proplists.erl index 68697d0da2..e3eda5d932 100644 --- a/lib/stdlib/src/proplists.erl +++ b/lib/stdlib/src/proplists.erl @@ -49,9 +49,10 @@ %% --------------------------------------------------------------------- --export_type([property/0]). +-export_type([property/0, proplist/0]). -type property() :: atom() | tuple(). +-type proplist() :: [property()]. %% --------------------------------------------------------------------- diff --git a/lib/stdlib/src/sofs.erl b/lib/stdlib/src/sofs.erl index d38b8ab37a..34eb224647 100644 --- a/lib/stdlib/src/sofs.erl +++ b/lib/stdlib/src/sofs.erl @@ -81,7 +81,8 @@ -define(ORDTAG, 'OrdSet'). -record(?TAG, {data = [] :: list(), type = type :: term()}). --record(?ORDTAG, {orddata = {} :: tuple(), ordtype = type :: term()}). +-record(?ORDTAG, {orddata = {} :: tuple() | atom(), + ordtype = type :: term()}). -define(LIST(S), (S)#?TAG.data). -define(TYPE(S), (S)#?TAG.type). @@ -375,7 +376,7 @@ to_sets(S) when ?IS_ORDSET(S) -> -spec(no_elements(ASet) -> NoElements when ASet :: a_set() | ordset(), - NoElements :: pos_integer()). + NoElements :: non_neg_integer()). no_elements(S) when ?IS_SET(S) -> length(?LIST(S)); no_elements(S) when ?IS_ORDSET(S), is_tuple(?ORDTYPE(S)) -> diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index e60706ed05..dc31647eb5 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -735,6 +735,13 @@ restart(one_for_all, Child, State) -> terminate_children(Children, SupName) -> terminate_children(Children, SupName, []). +%% Temporary children should not be restarted and thus should +%% be skipped when building the list of terminated children, although +%% we do want them to be shut down as many functions from this module +%% use this function to just clear everything. +terminate_children([Child = #child{restart_type=temporary} | Children], SupName, Res) -> + do_terminate(Child, SupName), + terminate_children(Children, SupName, Res); terminate_children([Child | Children], SupName, Res) -> NChild = do_terminate(Child, SupName), terminate_children(Children, SupName, [NChild | Res]); diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl index 8ab72c9b50..f34201604c 100644 --- a/lib/stdlib/src/sys.erl +++ b/lib/stdlib/src/sys.erl @@ -154,7 +154,7 @@ log_to_file(Name, FileName, Timeout) -> -spec statistics(Name, Flag) -> 'ok' | {'ok', Statistics} when Name :: name(), Flag :: 'true' | 'false' | 'get', - Statistics :: [StatisticsTuple], + Statistics :: [StatisticsTuple] | no_statistics, StatisticsTuple :: {'start_time', DateTime1} | {'current_time', DateTime2} | {'reductions', non_neg_integer()} @@ -168,7 +168,7 @@ statistics(Name, Flag) -> -spec statistics(Name, Flag, Timeout) -> 'ok' | {'ok', Statistics} when Name :: name(), Flag :: 'true' | 'false' | 'get', - Statistics :: [StatisticsTuple], + Statistics :: [StatisticsTuple] | no_statistics, StatisticsTuple :: {'start_time', DateTime1} | {'current_time', DateTime2} | {'reductions', non_neg_integer()} diff --git a/lib/stdlib/src/timer.erl b/lib/stdlib/src/timer.erl index e3d6c905b6..689e42051f 100644 --- a/lib/stdlib/src/timer.erl +++ b/lib/stdlib/src/timer.erl @@ -199,7 +199,7 @@ tc(M, F, A) -> %% Calculate the time difference (in microseconds) of two %% erlang:now() timestamps, T2-T1. %% --spec now_diff(T1, T2) -> Tdiff when +-spec now_diff(T2, T1) -> Tdiff when T1 :: erlang:timestamp(), T2 :: erlang:timestamp(), Tdiff :: integer(). diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl index 524d709431..c82c8159b6 100644 --- a/lib/stdlib/src/zip.erl +++ b/lib/stdlib/src/zip.erl @@ -223,7 +223,7 @@ openzip_open(F, Options) -> do_openzip_open(F, Options) -> Opts = get_openzip_options(Options), #openzip_opts{output = Output, open_opts = OpO, cwd = CWD} = Opts, - Input = get_zip_input(F), + Input = get_input(F), In0 = Input({open, F, OpO -- [write]}, []), {[#zip_comment{comment = C} | Files], In1} = get_central_dir(In0, fun raw_file_info_etc/5, Input), @@ -489,7 +489,7 @@ do_list_dir(F, Options) -> %% Print zip directory in short form -spec(t(Archive) -> ok when - Archive :: file:name() | binary | ZipHandle, + Archive :: file:name() | binary() | ZipHandle, ZipHandle :: pid()). t(F) when is_pid(F) -> zip_t(F); @@ -513,7 +513,7 @@ do_t(F, RawPrint) -> %% Print zip directory in long form (like ls -l) -spec(tt(Archive) -> ok when - Archive :: file:name() | binary | ZipHandle, + Archive :: file:name() | binary() | ZipHandle, ZipHandle :: pid()). tt(F) when is_pid(F) -> zip_tt(F); @@ -1174,7 +1174,7 @@ zip_get(Pid) when is_pid(Pid) -> zip_close(Pid) when is_pid(Pid) -> request(self(), Pid, close). --spec(zip_get(FileName, ZipHandle) -> {ok, [Result]} | {error, Reason} when +-spec(zip_get(FileName, ZipHandle) -> {ok, Result} | {error, Reason} when FileName :: file:name(), ZipHandle :: pid(), Result :: file:name() | {file:name(), binary()}, @@ -1183,7 +1183,7 @@ zip_close(Pid) when is_pid(Pid) -> zip_get(FileName, Pid) when is_pid(Pid) -> request(self(), Pid, {get, FileName}). --spec(zip_list_dir(ZipHandle) -> Result | {error, Reason} when +-spec(zip_list_dir(ZipHandle) -> {ok, Result} | {error, Reason} when Result :: [zip_comment() | zip_file()], ZipHandle :: pid(), Reason :: term()). diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl index 4ccc863795..91fff3cee4 100644 --- a/lib/stdlib/test/beam_lib_SUITE.erl +++ b/lib/stdlib/test/beam_lib_SUITE.erl @@ -242,8 +242,8 @@ cmp(doc) -> ["Compare contents of BEAM files and directories"]; cmp(Conf) when is_list(Conf) -> ?line PrivDir = ?privdir, - ?line Dir1 = filename:join(PrivDir, dir1), - ?line Dir2 = filename:join(PrivDir, dir2), + ?line Dir1 = filename:join(PrivDir, "dir1"), + ?line Dir2 = filename:join(PrivDir, "dir2"), ok = file:make_dir(Dir1), ok = file:make_dir(Dir2), @@ -292,8 +292,8 @@ cmp_literals(doc) -> ["Compare contents of BEAM files having literals"]; cmp_literals(Conf) when is_list(Conf) -> ?line PrivDir = ?privdir, - ?line Dir1 = filename:join(PrivDir, dir1), - ?line Dir2 = filename:join(PrivDir, dir2), + ?line Dir1 = filename:join(PrivDir, "dir1"), + ?line Dir2 = filename:join(PrivDir, "dir2"), ok = file:make_dir(Dir1), ok = file:make_dir(Dir2), @@ -381,7 +381,7 @@ otp_6711(Conf) when is_list(Conf) -> (catch {a, beam_lib:strip_files([3])}), ?line PrivDir = ?privdir, - ?line Dir = filename:join(PrivDir, dir), + ?line Dir = filename:join(PrivDir, "dir"), ?line Lib = filename:join(Dir, "lib"), ?line App = filename:join(Lib, "app"), ?line EBin = filename:join(App, "ebin"), @@ -417,8 +417,8 @@ building(doc) -> "Testing building of BEAM files."; building(Conf) when is_list(Conf) -> ?line PrivDir = ?privdir, - ?line Dir1 = filename:join(PrivDir, b_dir1), - ?line Dir2 = filename:join(PrivDir, b_dir2), + ?line Dir1 = filename:join(PrivDir, "b_dir1"), + ?line Dir2 = filename:join(PrivDir, "b_dir2"), ok = file:make_dir(Dir1), ok = file:make_dir(Dir2), @@ -688,7 +688,7 @@ chunk_info(File) -> Chunks. make_beam(Dir, Module, F) -> - ?line FileBase = filename:join(Dir, Module), + ?line FileBase = filename:join(Dir, atom_to_list(Module)), ?line Source = FileBase ++ ".erl", ?line BeamFile = FileBase ++ ".beam", ?line simple_file(Source, Module, F), diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl index 698070368f..22a9d4a7ff 100644 --- a/lib/stdlib/test/dets_SUITE.erl +++ b/lib/stdlib/test/dets_SUITE.erl @@ -1516,7 +1516,7 @@ repair(Config, V) -> if V =:= 8 -> %% first estimated number of objects is wrong, repair once more - ?line {ok, Fd} = file:open(Fname, read_write), + ?line {ok, Fd} = file:open(Fname, [read,write]), NoPos = HeadSize - 8, % no_objects ?line file:pwrite(Fd, NoPos, <<0:32>>), % NoItems ok = file:close(Fd), @@ -3247,7 +3247,7 @@ otp_5402(suite) -> []; otp_5402(Config) when is_list(Config) -> Tab = otp_5402, - ?line File = filename:join([cannot, write, this, file]), + ?line File = filename:join(["cannot", "write", "this", "file"]), %% close ?line{ok, T} = dets:open_file(Tab, [{ram_file,true}, @@ -3887,7 +3887,7 @@ crash(File, Where) -> crash(File, Where, 10). crash(File, Where, What) when is_integer(What) -> - ?line {ok, Fd} = file:open(File, read_write), + ?line {ok, Fd} = file:open(File, [read,write]), ?line file:position(Fd, Where), ?line ok = file:write(Fd, [What]), ?line ok = file:close(Fd). @@ -4031,7 +4031,7 @@ writable(Fname) -> ?line file:write_file_info(Fname, Info#file_info{mode = Mode}). truncate(File, Where) -> - ?line {ok, Fd} = file:open(File, read_write), + ?line {ok, Fd} = file:open(File, [read,write]), ?line file:position(Fd, Where), ?line ok = file:truncate(Fd), ?line ok = file:close(Fd). diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index 9b024a5b49..57f3f4eddb 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -1280,7 +1280,7 @@ eval_tests(Config, Fun, Tests) -> check_test(Config, Test) -> - Filename = 'epp_test.erl', + Filename = "epp_test.erl", ?line PrivDir = ?config(priv_dir, Config), ?line File = filename:join(PrivDir, Filename), ?line ok = file:write_file(File, Test), @@ -1293,7 +1293,7 @@ check_test(Config, Test) -> compile_test(Config, Test0) -> Test = [<<"-module(epp_test). -compile(export_all). ">>, Test0], - Filename = 'epp_test.erl', + Filename = "epp_test.erl", ?line PrivDir = ?config(priv_dir, Config), ?line File = filename:join(PrivDir, Filename), ?line ok = file:write_file(File, Test), diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index 0bcf3c5b71..784c7cb86e 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -1189,7 +1189,7 @@ lfh() -> {eval, fun(F, As, Bs) -> local_func(F, As, Bs) end}. local_func(F, As0, Bs0) when is_atom(F) -> - {As,Bs} = erl_eval:expr_list(As0, Bs0, {eval,lfh()}), + {As,Bs} = erl_eval:expr_list(As0, Bs0, lfh()), case erlang:function_exported(?MODULE, F, length(As)) of true -> {value,apply(?MODULE, F, As),Bs}; diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index f980d52e4e..9041adbe5c 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -2981,7 +2981,7 @@ run_test(Conf, Test0, Warnings0) -> run_test2(Conf, Test, Warnings0). run_test2(Conf, Test, Warnings0) -> - Filename = 'lint_test.erl', + Filename = "lint_test.erl", DataDir = ?privdir, File = filename:join(DataDir, Filename), Opts = case Warnings0 of diff --git a/lib/stdlib/test/file_sorter_SUITE.erl b/lib/stdlib/test/file_sorter_SUITE.erl index 80d4ea5fdc..74c08912be 100644 --- a/lib/stdlib/test/file_sorter_SUITE.erl +++ b/lib/stdlib/test/file_sorter_SUITE.erl @@ -89,7 +89,7 @@ basic(suite) -> basic(Config) when is_list(Config) -> Fmt = binary, Arg = {format,Fmt}, - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), P0 = pps(), ?line F1s = [F1] = to_files([[]], Fmt, Config), @@ -455,7 +455,7 @@ inout(suite) -> []; inout(Config) when is_list(Config) -> BTF = {format, binary_term}, - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is fun. End = fun(read) -> end_of_input end, @@ -522,7 +522,7 @@ many(doc) -> many(suite) -> []; many(Config) when is_list(Config) -> - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), PrivDir = ?privdir(Config), P0 = pps(), @@ -587,7 +587,7 @@ misc(suite) -> []; misc(Config) when is_list(Config) -> BTF = {format, binary_term}, - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), FFoo = filename:absname(Foo), P0 = pps(), @@ -704,7 +704,7 @@ misc(Config) when is_list(Config) -> sort(Fmt, XArgs, Config) -> Args = make_args(Fmt, [{size,5} | XArgs]), TmpArgs = [{tmpdir,?privdir(Config)} | Args], - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is a fun. Output is a fun. ?line [] = file_sorter:sort(input([], 2, Fmt), output([], Fmt), Args), @@ -777,7 +777,7 @@ sort(Fmt, XArgs, Config) -> keysort(Fmt, XArgs, Config) -> Args = make_args(Fmt, [{size,50}, {no_files, 2} | XArgs]), TmpArgs = Args ++ [{tmpdir,?privdir(Config)}], - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is files. Output is a file. ?line ok = file_sorter:keysort(2, [], Foo, Args), @@ -836,7 +836,7 @@ keysort(Fmt, XArgs, Config) -> merge(Fmt, XArgs, Config) -> Args = make_args(Fmt, [{size,5} | XArgs]), - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is a file. Output is a fun. ?line [] = file_sorter:merge([], output([], Fmt), Args), @@ -873,7 +873,7 @@ merge(Fmt, XArgs, Config) -> keymerge(Fmt, XArgs, Config) -> Args = make_args(Fmt, [{size,50}, {no_files, 2} | XArgs]), - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is files. Output is a file. ?line ok = file_sorter:keymerge(2, [], Foo, Args), diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl index a355097fe2..3010f5e760 100644 --- a/lib/stdlib/test/filelib_SUITE.erl +++ b/lib/stdlib/test/filelib_SUITE.erl @@ -243,7 +243,7 @@ otp_5960(doc) -> ["Test that filelib:ensure_dir/1 returns ok or {error,Reason}"]; otp_5960(Config) when is_list(Config) -> ?line PrivDir = ?config(priv_dir, Config), - ?line Dir = filename:join(PrivDir, otp_5960_dir), + ?line Dir = filename:join(PrivDir, "otp_5960_dir"), ?line Name1 = filename:join(Dir, name1), ?line Name2 = filename:join(Dir, name2), ?line ok = filelib:ensure_dir(Name1), % parent is created @@ -268,7 +268,7 @@ otp_5960(Config) when is_list(Config) -> ensure_dir_eexist(Config) when is_list(Config) -> ?line PrivDir = ?config(priv_dir, Config), - ?line Dir = filename:join(PrivDir, ensure_dir_eexist), + ?line Dir = filename:join(PrivDir, "ensure_dir_eexist"), ?line Name = filename:join(Dir, "same_name_as_file_and_dir"), ?line ok = filelib:ensure_dir(Name), ?line ok = file:write_file(Name, <<"some string\n">>), diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl index 1dcd4be21e..6969c095a0 100644 --- a/lib/stdlib/test/string_SUITE.erl +++ b/lib/stdlib/test/string_SUITE.erl @@ -273,9 +273,9 @@ words(Config) when is_list(Config) -> ?line 2 = string:words("2.35", $.), ?line 100 = string:words(string:copies(". ", 100)), %% invalid arg type - ?line {'EXIT',_} = (catch string:chars(hej)), + ?line {'EXIT',_} = (catch string:chars(hej, 1)), %% invalid arg type - ?line {'EXIT',_} = (catch string:chars("hej", " ")), + ?line {'EXIT',_} = (catch string:chars("hej", 1, " ")), ok. diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl index ff5e4c629a..b48450c151 100644 --- a/lib/stdlib/test/supervisor_SUITE.erl +++ b/lib/stdlib/test/supervisor_SUITE.erl @@ -42,7 +42,7 @@ -export([ permanent_normal/1, transient_normal/1, temporary_normal/1, permanent_abnormal/1, transient_abnormal/1, - temporary_abnormal/1]). + temporary_abnormal/1, temporary_bystander/1]). %% Restart strategy tests -export([ one_for_one/1, @@ -74,7 +74,7 @@ all() -> {group, abnormal_termination}, child_unlink, tree, count_children_memory, do_not_save_start_parameters_for_temporary_children, do_not_save_child_specs_for_temporary_children, - simple_one_for_one_scale_many_temporary_children]. + simple_one_for_one_scale_many_temporary_children, temporary_bystander]. groups() -> [{sup_start, [], @@ -607,6 +607,37 @@ temporary_abnormal(Config) when is_list(Config) -> [0,0,0,0] = get_child_counts(sup_test). %%------------------------------------------------------------------------- +temporary_bystander(doc) -> + ["A temporary process killed as part of a rest_for_one or one_for_all " + "restart strategy should not be restarted given its args are not " + " saved. Otherwise the supervisor hits its limit and crashes."]; +temporary_bystander(suite) -> []; +temporary_bystander(_Config) -> + Child1 = {child1, {supervisor_1, start_child, []}, permanent, 100, + worker, []}, + Child2 = {child2, {supervisor_1, start_child, []}, temporary, 100, + worker, []}, + {ok, SupPid1} = supervisor:start_link(?MODULE, {ok, {{one_for_all, 2, 300}, []}}), + {ok, SupPid2} = supervisor:start_link(?MODULE, {ok, {{rest_for_one, 2, 300}, []}}), + unlink(SupPid1), % otherwise we crash with it + unlink(SupPid2), % otherwise we crash with it + {ok, CPid1} = supervisor:start_child(SupPid1, Child1), + {ok, _CPid2} = supervisor:start_child(SupPid1, Child2), + {ok, CPid3} = supervisor:start_child(SupPid2, Child1), + {ok, _CPid4} = supervisor:start_child(SupPid2, Child2), + terminate(SupPid1, CPid1, child1, normal), + terminate(SupPid2, CPid3, child1, normal), + timer:sleep(350), + catch link(SupPid1), + catch link(SupPid2), + %% The supervisor would die attempting to restart child2 + true = erlang:is_process_alive(SupPid1), + true = erlang:is_process_alive(SupPid2), + %% Child2 has not been restarted + [{child1, _, _, _}] = supervisor:which_children(SupPid1), + [{child1, _, _, _}] = supervisor:which_children(SupPid2). + +%%------------------------------------------------------------------------- one_for_one(doc) -> ["Test the one_for_one base case."]; one_for_one(suite) -> []; diff --git a/lib/stdlib/test/supervisor_bridge_SUITE.erl b/lib/stdlib/test/supervisor_bridge_SUITE.erl index f2dbad0b3b..c4d696564d 100644 --- a/lib/stdlib/test/supervisor_bridge_SUITE.erl +++ b/lib/stdlib/test/supervisor_bridge_SUITE.erl @@ -158,7 +158,7 @@ internal_loop(State) -> terminate(Reason,{Parent,Worker}) -> %% This func knows about supervisor_bridge io:format("Terminating bridge...\n"), - exit(kill,Worker), + exit(Worker,kill), Parent ! {dying,Reason}, anything. diff --git a/lib/stdlib/test/sys_SUITE.erl b/lib/stdlib/test/sys_SUITE.erl index 72b089aa3f..fe039e8bcc 100644 --- a/lib/stdlib/test/sys_SUITE.erl +++ b/lib/stdlib/test/sys_SUITE.erl @@ -71,7 +71,7 @@ log_to_file(Config) when is_list(Config) -> ?line ok = sys:log_to_file(?server,TempName), ?line {ok,-44} = public_call(44), ?line ok = sys:log_to_file(?server,false), - ?line {ok,Fd} = file:open(TempName,read), + ?line {ok,Fd} = file:open(TempName,[read]), ?line Msg1 = io:get_line(Fd,''), ?line Msg2 = io:get_line(Fd,''), ?line file:close(Fd), diff --git a/lib/stdlib/test/tar_SUITE.erl b/lib/stdlib/test/tar_SUITE.erl index e32704ca65..48f58cd05d 100644 --- a/lib/stdlib/test/tar_SUITE.erl +++ b/lib/stdlib/test/tar_SUITE.erl @@ -65,7 +65,7 @@ borderline(Config) when is_list(Config) -> ?line {ok, Cwd} = file:get_cwd(), ?line RootDir = ?config(priv_dir, Config), - ?line TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, borderline)), + ?line TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, "borderline")), ?line ok = file:make_dir(TempDir), ?line Record = 512, @@ -323,12 +323,12 @@ create_long_names(doc) -> create_long_names(Config) when is_list(Config) -> ?line PrivDir = ?config(priv_dir, Config), ?line ok = file:set_cwd(PrivDir), - Dirs = [aslfjkshjkhliuf, - asdhjfehnbfsky, - sahajfskdfhsz, - asldfkdlfy4y8rchg, - f7nafhjgffagkhsfkhsjk, - dfjasldkfjsdkfjashbv], + Dirs = ["aslfjkshjkhliuf", + "asdhjfehnbfsky", + "sahajfskdfhsz", + "asldfkdlfy4y8rchg", + "f7nafhjgffagkhsfkhsjk", + "dfjasldkfjsdkfjashbv"], ?line DeepDir = make_dirs(Dirs, []), ?line AFile = filename:join(DeepDir, "a_file"), @@ -487,7 +487,7 @@ extract_from_binary_compressed(Config) when is_list(Config) -> %% Trying extracting from a binary. ?line ok = erl_tar:extract({binary,Bin}, [compressed,{cwd,ExtractDir}]), - ?line {ok,List} = file:list_dir(filename:join(ExtractDir, ddll_SUITE_data)), + ?line {ok,List} = file:list_dir(filename:join(ExtractDir, "ddll_SUITE_data")), ?line io:format("~p\n", [List]), ?line 19 = length(List), @@ -676,7 +676,7 @@ cooked_compressed(Config) when is_list(Config) -> end, List), %% Clean up. - ?line delete_files([filename:join(PrivDir, ddll_SUITE_data)]), + ?line delete_files([filename:join(PrivDir, "ddll_SUITE_data")]), ok. memory(doc) -> diff --git a/lib/stdlib/test/zip_SUITE.erl b/lib/stdlib/test/zip_SUITE.erl index d5f2cd52d4..7233c061ef 100644 --- a/lib/stdlib/test/zip_SUITE.erl +++ b/lib/stdlib/test/zip_SUITE.erl @@ -375,7 +375,8 @@ zip_options(Config) when is_list(Config) -> ok = file:set_cwd(?config(data_dir, Config)), %% Create a zip archive - {ok, Zip} = zip:zip("filename_not_used.zip", Names, [memory, {cwd, PrivDir}]), + {ok, {_,Zip}} = + zip:zip("filename_not_used.zip", Names, [memory, {cwd, PrivDir}]), %% Open archive {ok, ZipSrv} = zip:zip_open(Zip, [memory]), diff --git a/lib/test_server/src/ts_install_cth.erl b/lib/test_server/src/ts_install_cth.erl index c5444a342f..a41916fd0a 100644 --- a/lib/test_server/src/ts_install_cth.erl +++ b/lib/test_server/src/ts_install_cth.erl @@ -49,8 +49,7 @@ -include_lib("kernel/include/file.hrl"). --type proplist() :: list({atom(),term()}). --type config() :: proplist(). +-type config() :: proplists:proplist(). -type reason() :: term(). -type skip_or_fail() :: {skip, reason()} | {auto_skip, reason()} | @@ -65,19 +64,19 @@ id(_Opts) -> ?MODULE. %% @doc Always called before any other callback function. --spec init(Id :: term(), Opts :: proplist()) -> - State :: #state{}. +-spec init(Id :: term(), Opts :: proplists:proplist()) -> + {ok, State :: #state{}}. init(_Id, Opts) -> Nodenames = proplists:get_value(nodenames, Opts, 0), Nodes = proplists:get_value(nodes, Opts, 0), TSConfDir = proplists:get_value(ts_conf_dir, Opts), TargetSystem = proplists:get_value(target_system, Opts, install_local), InstallOpts = proplists:get_value(install_opts, Opts, []), - #state{ nodenames = Nodenames, - nodes = Nodes, - ts_conf_dir = TSConfDir, - target_system = TargetSystem, - install_opts = InstallOpts }. + {ok, #state{ nodenames = Nodenames, + nodes = Nodes, + ts_conf_dir = TSConfDir, + target_system = TargetSystem, + install_opts = InstallOpts } }. %% @doc Called before init_per_suite is called. -spec pre_init_per_suite(Suite :: atom(), diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile index ab72a9d579..198440bb17 100644 --- a/lib/test_server/test/Makefile +++ b/lib/test_server/test/Makefile @@ -85,7 +85,7 @@ release_spec: opt release_tests_spec: make_emakefile $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR) - $(INSTALL_DATA) test_server.spec test_server.cover $(RELSYSDIR) + $(INSTALL_DATA) test_server_test_lib.hrl test_server.spec test_server.cover $(RELSYSDIR) chmod -R u+w $(RELSYSDIR) @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el index 6728bef2a4..a8dd3ec3ac 100644 --- a/lib/tools/emacs/erlang.el +++ b/lib/tools/emacs/erlang.el @@ -523,6 +523,32 @@ This is an elisp list of options. Each option can be either: - a string Example: '(bin_opt_info (i . \"/path1/include\") (i . \"/path2/include\"))") +(defvar erlang-compile-command-function-alist + '((".erl\\'" . inferior-erlang-compute-erl-compile-command) + (".xrl\\'" . inferior-erlang-compute-leex-compile-command) + (".yrl\\'" . inferior-erlang-compute-yecc-compile-command) + ("." . inferior-erlang-compute-erl-compile-command)) + "*Alist of filename patterns vs corresponding compilation functions. +Each element looks like (REGEXP . FUNCTION). Compiling a file whose name +matches REGEXP specifies FUNCTION to use to compute the compilation +command. The FUNCTION will be called with two arguments: module name and +default compilation options, like output directory. The FUNCTION +is expected to return a string.") + +(defvar erlang-leex-compile-opts '() + "*Options to pass to leex when compiling xrl files. +This is an elisp list of options. Each option can be either: +- an atom +- a dotted pair +- a string") + +(defvar erlang-yecc-compile-opts '() + "*Options to pass to yecc when compiling yrl files. +This is an elisp list of options. Each option can be either: +- an atom +- a dotted pair +- a string") + (eval-and-compile (defvar erlang-regexp-modern-p (if (> erlang-emacs-major-version 21) t nil) @@ -5276,6 +5302,22 @@ unless the optional NO-DISPLAY is non-nil." (file-name-as-directory buffer-dir)))) (defun inferior-erlang-compute-compile-command (module-name opts) + (let ((ccfn erlang-compile-command-function-alist) + (res (inferior-erlang-compute-erl-compile-command module-name opts)) + ccfn-entry + done) + (if (not (null (buffer-file-name))) + (while (and (not done) (not (null ccfn))) + (setq ccfn-entry (car ccfn)) + (setq ccfn (cdr ccfn)) + (if (string-match (car ccfn-entry) (buffer-file-name)) + (let ((c-fn (cdr ccfn-entry))) + (setq done t) + (if (not (null c-fn)) + (setq result (funcall c-fn module-name opts))))))) + result)) + +(defun inferior-erlang-compute-erl-compile-command (module-name opts) (let* ((out-dir-opt (assoc 'outdir opts)) (out-dir (cdr out-dir-opt))) (if erlang-compile-use-outdir @@ -5299,6 +5341,48 @@ unless the optional NO-DISPLAY is non-nil." (remq out-dir-opt opts)) tmpvar tmpvar tmpvar2))))) +(defun inferior-erlang-compute-leex-compile-command (module-name opts) + (let ((file-name (buffer-file-name)) + (erl-compile-expr (inferior-erlang-remove-any-trailing-dot + (inferior-erlang-compute-erl-compile-command + module-name opts)))) + (format (concat "f(LErr1__), f(LErr2__), " + "case case leex:file(\"%s\", [%s]) of" + " ok -> ok;" + " {ok,_} -> ok;" + " {ok,_,_} -> ok;" + " LErr1__ -> LErr1__ " + "end of" + " ok -> %s;" + " LErr2__ -> LErr2__ " + "end.") + file-name + (inferior-erlang-format-comma-opts erlang-leex-compile-opts) + erl-compile-expr))) + +(defun inferior-erlang-compute-yecc-compile-command (module-name opts) + (let ((file-name (buffer-file-name)) + (erl-compile-expr (inferior-erlang-remove-any-trailing-dot + (inferior-erlang-compute-erl-compile-command + module-name opts)))) + (format (concat "f(YErr1__), f(YErr2__), " + "case case yecc:file(\"%s\", [%s]) of" + " {ok,_} -> ok;" + " {ok,_,_} -> ok;" + " YErr1__ -> YErr1__ " + "end of" + " ok -> %s;" + " YErr2__ -> YErr2__ " + "end.") + file-name + (inferior-erlang-format-comma-opts erlang-yecc-compile-opts) + erl-compile-expr))) + +(defun inferior-erlang-remove-any-trailing-dot (str) + (if (string= (substring str -1) ".") + (substring str 0 (1- (length str))) + str)) + (defun inferior-erlang-format-comma-opts (opts) (if (null opts) "" diff --git a/lib/webtool/priv/Makefile b/lib/webtool/priv/Makefile index 56ab772c45..6e1c6606fe 100644 --- a/lib/webtool/priv/Makefile +++ b/lib/webtool/priv/Makefile @@ -39,8 +39,12 @@ HTDOCS_FILES = root/doc/index.html \ root/doc/tool_management.html \ root/doc/start_info.html -SCRIPTS = bin/start_webtool \ - bin/start_webtool.bat +ifeq ($(findstring win32,$(TARGET)),win32) +WIN32_SCRIPTS= bin/start_webtool.bat +else +WIN32_SCRIPTS= +endif +SCRIPTS = bin/start_webtool $(WIN32_SCRIPTS) # ---------------------------------------------------- # FLAGS diff --git a/lib/wx/test/wxt.erl b/lib/wx/test/wxt.erl index 1f5b1cc3b1..2f52c58f26 100644 --- a/lib/wx/test/wxt.erl +++ b/lib/wx/test/wxt.erl @@ -72,7 +72,7 @@ resolve({Suite0, Case}) when is_atom(Suite0), is_atom(Case) -> {Suite, Case2} -> {Suite, Case2} end; -resolve(List) when list(List) -> +resolve(List) when is_list(List) -> [resolve(Case) || Case <- List]. alias(Suite) when is_atom(Suite) -> @@ -104,7 +104,7 @@ read_config() -> end. %% Write new default config file -write_config(Config) when list(Config) -> +write_config(Config) when is_list(Config) -> Fname = config_fname(), {ok, Fd} = file:open(Fname, write), write_list(Fd, Config), diff --git a/lib/xmerl/include/xmerl_xsd.hrl b/lib/xmerl/include/xmerl_xsd.hrl index b527accc8c..6dad7d8ff0 100644 --- a/lib/xmerl/include/xmerl_xsd.hrl +++ b/lib/xmerl/include/xmerl_xsd.hrl @@ -36,6 +36,7 @@ schema_name, vsn, schema_preprocessed=false, + external_xsd_base=false, xsd_base, xml_options=[], scope=[], diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl index 059c8f21b6..e598c5f56d 100644 --- a/lib/xmerl/src/xmerl_scan.erl +++ b/lib/xmerl/src/xmerl_scan.erl @@ -2276,7 +2276,7 @@ scan_att_chars([H|T], S0, H, Acc, TmpAcc,AttType,IsNorm) -> % End quote true -> normalize(Acc,S,IsNorm) end, - {lists:reverse(Acc2), T, S2,IsNorm2}; + {lists:flatten(lists:reverse(Acc2)), T, S2,IsNorm2}; scan_att_chars("&" ++ T, S0, Delim, Acc, TmpAcc,AT,IsNorm) -> % Reference ?bump_col(1), {ExpRef, T1, S1} = scan_reference(T, S), diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl index e56f1470c0..f003cc74ba 100644 --- a/lib/xmerl/src/xmerl_xsd.erl +++ b/lib/xmerl/src/xmerl_xsd.erl @@ -287,10 +287,19 @@ process_schema(Schema) -> %% error reason. The error reason may be a list of several errors %% or a single error encountered during the processing. process_schema(Schema,Options) when is_list(Options) -> - S = initiate_state(Options,Schema), - process_schema2(xmerl_scan:file(filename:join(S#xsd_state.xsd_base, Schema)),S,Schema); -process_schema(Schema,State) when is_record(State,xsd_state) -> - process_schema2(xmerl_scan:file(filename:join(State#xsd_state.xsd_base, Schema)),State,Schema). + State = initiate_state(Options,Schema), + process_schema(Schema, State); +process_schema(Schema, State=#xsd_state{fetch_fun=Fetch})-> + case Fetch(Schema, State) of + {ok,{file,File},_} -> + process_schema2(xmerl_scan:file(File), State, Schema); + {ok,{string,Str},_} -> + process_schema2(xmerl_scan:string(Str), State, Schema); + {ok,[],_} -> + {error,enoent}; + Err -> + Err + end. process_schema2(Err={error,_},_,_) -> Err; @@ -319,12 +328,9 @@ process_schemas(Schemas) -> %% error reason. The error reason may be a list of several errors %% or a single error encountered during the processing. process_schemas(Schemas=[{_,Schema}|_],Options) when is_list(Options) -> - process_schemas(Schemas,initiate_state(Options,Schema)); + State = initiate_state(Options,Schema), + process_schemas(Schemas, State); process_schemas([{_NS,Schema}|Rest],State=#xsd_state{fetch_fun=Fetch}) -> -%% case process_external_schema_once(Schema,if_list_to_atom(NS),State) of -%% S when is_record(S,xsd_state) -> -%% case process_schema(filename:join([State#xsd_state.xsd_base,Schema]),State) of -%% {ok,S} -> Res= case Fetch(Schema,State) of {ok,{file,File},_} -> @@ -345,20 +351,20 @@ process_schemas([{_NS,Schema}|Rest],State=#xsd_state{fetch_fun=Fetch}) -> process_schemas([],S) when is_record(S,xsd_state) -> {ok,S}. - initiate_state(Opts,Schema) -> XSDBase = filename:dirname(Schema), {{state,S},RestOpts}=new_state(Opts), S2 = create_tables(S), - initiate_state2(S2#xsd_state{schema_name = Schema, - xsd_base = XSDBase, - fetch_fun = fun fetch/2},RestOpts). + S3 = initiate_state2(S2#xsd_state{schema_name = Schema, xsd_base=XSDBase, + fetch_fun = fun fetch/2}, + RestOpts). + initiate_state2(S,[]) -> S; initiate_state2(S,[{tab2file,Bool}|T]) -> initiate_state2(S#xsd_state{tab2file=Bool},T); -initiate_state2(S,[{xsdbase,XSDBase}|T]) -> - initiate_state2(S#xsd_state{xsd_base=XSDBase},T); +initiate_state2(S,[{xsdbase, XSDBase}|T]) -> + initiate_state2(S#xsd_state{xsd_base=XSDBase, external_xsd_base=true},T); initiate_state2(S,[{fetch_fun,FetchFun}|T]) -> initiate_state2(S#xsd_state{fetch_fun=FetchFun},T); initiate_state2(S,[{fetch_path,FetchPath}|T]) -> @@ -5232,7 +5238,12 @@ fetch(URI,S) -> [] -> %% empty systemliteral []; _ -> - filename:join(S#xsd_state.xsd_base, URI) + case S#xsd_state.external_xsd_base of + true -> + filename:join(S#xsd_state.xsd_base, URI); + false -> + filename:join(S#xsd_state.xsd_base, filename:basename(URI)) + end end, Path = path_locate(S#xsd_state.fetch_path, Filename, Fullname), ?dbg("fetch(~p) -> {file, ~p}.~n", [URI, Path]), diff --git a/lib/xmerl/test/Makefile b/lib/xmerl/test/Makefile index 9715aa054a..5a2a585841 100644 --- a/lib/xmerl/test/Makefile +++ b/lib/xmerl/test/Makefile @@ -124,4 +124,4 @@ release_tests_spec: opt @tar cfh - xmerl_xsd_MS2002-01-16_SUITE_data | (cd $(RELSYSDIR); tar xf -) @tar cfh - xmerl_xsd_NIST2002-01-16_SUITE_data | (cd $(RELSYSDIR); tar xf -) @tar cfh - xmerl_xsd_Sun2002-01-16_SUITE_data | (cd $(RELSYSDIR); tar xf -) - chmod -f -R u+w $(RELSYSDIR) + chmod -R u+w $(RELSYSDIR) diff --git a/lib/xmerl/test/xmerl_SUITE.erl b/lib/xmerl/test/xmerl_SUITE.erl index 392b2522e8..0c809dbcb6 100644 --- a/lib/xmerl/test/xmerl_SUITE.erl +++ b/lib/xmerl/test/xmerl_SUITE.erl @@ -57,7 +57,8 @@ groups() -> {eventp_tests, [], [sax_parse_and_export]}, {ticket_tests, [], [ticket_5998, ticket_7211, ticket_7214, ticket_7430, - ticket_6873, ticket_7496, ticket_8156, ticket_8697]}, + ticket_6873, ticket_7496, ticket_8156, ticket_8697, + ticket_9411]}, {app_test, [], [{xmerl_app_test, all}]}, {appup_test, [], [{xmerl_appup_test, all}]}]. @@ -575,7 +576,17 @@ ticket_8697(Config) -> ?line [16#545C] = HexEntityText, ok. +ticket_9411(suite) -> []; +ticket_9411(doc) -> + ["Test that xmerl_scan handles attribute that contains for example ""]; +ticket_9411(Config) -> + DataDir = ?config(data_dir,Config), + ?line {ok, Schema} = xmerl_xsd:process_schema(filename:join([DataDir,"misc/ticket_9411.xsd"])), + ?line {ok, Bin} = file:read_file(filename:join([DataDir,"misc/ticket_9411.xml"])), + ?line Xml = erlang:binary_to_list(Bin), + ?line {E, _} = xmerl_scan:string(Xml), + ?line {E, _} = xmerl_xsd:validate(E, Schema). diff --git a/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz b/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz Binary files differindex c48a6f897b..fef7431845 100644 --- a/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz +++ b/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz diff --git a/lib/xmerl/test/xmerl_xsd_SUITE.erl b/lib/xmerl/test/xmerl_xsd_SUITE.erl index a0d3b1e667..421fa48054 100644 --- a/lib/xmerl/test/xmerl_xsd_SUITE.erl +++ b/lib/xmerl/test/xmerl_xsd_SUITE.erl @@ -62,7 +62,7 @@ groups() -> sis2, state2file_file2state, union]}, {ticket_tests, [], [ticket_6910, ticket_7165, ticket_7190, ticket_7288, - ticket_7736, ticket_8599]}, + ticket_7736, ticket_8599, ticket_9410]}, {facets, [], [length, minLength, maxLength, pattern, enumeration, whiteSpace, maxInclusive, maxExclusive, minExclusive, @@ -1146,3 +1146,8 @@ ticket_8599(Config) -> ?line {{xmlElement,persons,persons,_,_,_,_,_,_,_,_,_},_GlobalState} = xmerl_xsd:validate(E, S). + +ticket_9410(suite) -> []; +ticket_9410(Config) -> + file:set_cwd(filename:join([?config(data_dir,Config),".."])), + ?line {ok, _S} = xmerl_xsd:process_schema("xmerl_xsd_SUITE_data/small.xsd"). |