diff options
Diffstat (limited to 'lib')
386 files changed, 20273 insertions, 12642 deletions
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml index cb89bb298b..11de9ad98f 100644 --- a/lib/asn1/doc/src/notes.xml +++ b/lib/asn1/doc/src/notes.xml @@ -31,6 +31,23 @@ <p>This document describes the changes made to the asn1 application.</p> +<section><title>Asn1 3.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The ASN.1 compiler now generates code that don't trigger + Dialyzer warnings. Along the way, a few minor bugs were + fixed.</p> + <p> + Own Id: OTP-11372 Aux Id: seq12397 </p> + </item> + </list> + </section> + +</section> + <section><title>Asn1 3.0</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile index 500f4a1358..6798da0072 100644 --- a/lib/asn1/src/Makefile +++ b/lib/asn1/src/Makefile @@ -52,6 +52,7 @@ CT_MODULES= \ asn1ct_pretty_format \ asn1ct_func \ asn1ct_gen \ + asn1ct_gen_check \ asn1ct_gen_per \ asn1ct_name \ asn1ct_constructed_per \ diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl index a38da8bcc2..5fadd0495a 100644 --- a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl @@ -962,8 +962,7 @@ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj) WhatKind = asn1ct_gen:type(InnerType), emit(IndDeep), emit(Assign), - gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind, - Element), + gen_optormand_case(OptOrMand, Erules, TopType, Cname, Type, Element), case {Type,asn1ct_gen:get_constraint(Type#type.constraint, componentrelation)} of % #type{constraint=[{tableconstraint_info,RefedFieldName}], @@ -1029,26 +1028,19 @@ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj) emit([nl,indent(7),"end"]) end. -gen_optormand_case(mandatory,_Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind, - _Element) -> +gen_optormand_case(mandatory, _Erules, _TopType, _Cname, _Type, _Element) -> ok; -gen_optormand_case('OPTIONAL',Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind, - Element) -> +gen_optormand_case('OPTIONAL', Erules, _TopType, _Cname, _Type, Element) -> emit([" case ",Element," of",nl]), emit([indent(9),"asn1_NOVALUE -> {", empty_lb(Erules),",0};",nl]), emit([indent(9),"_ ->",nl,indent(12)]); -gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type, - InnerType,WhatKind,Element) -> +gen_optormand_case({'DEFAULT',DefaultValue}, Erules, _TopType, + _Cname, Type, Element) -> CurrMod = get(currmod), case catch lists:member(der,get(encoding_options)) of true -> - emit(" case catch "), - asn1ct_gen:gen_check_call(TopType,Cname,Type,InnerType, - WhatKind,{asis,DefaultValue}, - Element), - emit([" of",nl]), - emit([indent(12),"true -> {[],0};",nl]); + asn1ct_gen_check:emit(Type, DefaultValue, Element); _ -> emit([" case ",Element," of",nl]), emit([indent(9),"asn1_DEFAULT -> {", @@ -1063,10 +1055,9 @@ gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type, emit([indent(9),{asis, DefaultValue}," -> {", empty_lb(Erules),",0};",nl]) - end - end, - emit([indent(9),"_ ->",nl,indent(12)]). - + end, + emit([indent(9),"_ ->",nl,indent(12)]) + end. gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf) -> @@ -1210,11 +1201,11 @@ gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandC (Type#type.def)#'ObjectClassFieldType'.fieldname, [{Cname,RefedFieldName,asn1ct_gen:mk_var(asn1ct_name:curr(term)), asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}]; -gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand, - OptOrMand,DecObjInf,_) -> +gen_dec_call(InnerType, _Erules, TopType, Cname, Type, BytesVar, + Tag, _PrimOptOrMand, _OptOrMand, DecObjInf,_) -> WhatKind = asn1ct_gen:type(InnerType), - gen_dec_call1(WhatKind,InnerType,Erules,TopType,Cname,Type,BytesVar,Tag, - PrimOptOrMand,OptOrMand), + gen_dec_call1(WhatKind, InnerType, TopType, Cname, + Type, BytesVar, Tag), case DecObjInf of {Cname,{_,OSet,_UniqueFName,ValIndex}} -> Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)), @@ -1226,8 +1217,9 @@ gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand, ok end, []. -gen_dec_call1({primitive,bif},InnerType,Erules,TopType,Cname,Type,BytesVar, - Tag,OptOrMand,_) -> + +gen_dec_call1({primitive,bif}, InnerType, TopType, Cname, + Type, BytesVar, Tag) -> case {asn1ct:get_gen_state_field(namelist),InnerType} of {[{Cname,undecoded}|Rest],_} -> asn1ct:add_generated_refed_func({[Cname|TopType],undecoded, @@ -1236,11 +1228,10 @@ gen_dec_call1({primitive,bif},InnerType,Erules,TopType,Cname,Type,BytesVar, emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',", BytesVar,"}"]); _ -> - ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[], - ?PRIMITIVE,OptOrMand) + ?ASN1CT_GEN_BER:gen_dec_prim(Type, BytesVar, Tag) end; -gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,TopType,Cname,Type,BytesVar, - Tag,OptOrMand,_) -> +gen_dec_call1('ASN1_OPEN_TYPE', _InnerType, TopType, Cname, + Type, BytesVar, Tag) -> case {asn1ct:get_gen_state_field(namelist),Type#type.def} of {[{Cname,undecoded}|Rest],_} -> asn1ct:add_generated_refed_func({[Cname|TopType],undecoded, @@ -1249,15 +1240,12 @@ gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,TopType,Cname,Type,BytesVar, emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',", BytesVar,"}"]); {_,#'ObjectClassFieldType'{type=OpenType}} -> - ?ASN1CT_GEN_BER:gen_dec_prim(Erules,#type{def=OpenType}, - BytesVar,Tag,[], - ?PRIMITIVE,OptOrMand); + ?ASN1CT_GEN_BER:gen_dec_prim(#type{def=OpenType}, + BytesVar, Tag); _ -> - ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[], - ?PRIMITIVE,OptOrMand) + ?ASN1CT_GEN_BER:gen_dec_prim(Type, BytesVar, Tag) end; -gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,BytesVar, - Tag,_,_OptOrMand) -> +gen_dec_call1(WhatKind, _, TopType, Cname, Type, BytesVar, Tag) -> case asn1ct:get_gen_state_field(namelist) of [{Cname,undecoded}|Rest] -> asn1ct:add_generated_refed_func({[Cname|TopType],undecoded, diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index ed3f6f886e..a91404ed54 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -426,8 +426,7 @@ gen_dec_open_type(Erule, Val, {Xmod,Xtype}, LeadingAttr, emit([Term," = ",{asis,F},"(",TmpTerm,", ",Val,")"]). dec_objset_optional(N, {'DEFAULT',Val}) -> - dec_objset_optional_1(N, Val), - dec_objset_optional_1(N, asn1_DEFAULT); + dec_objset_optional_1(N, Val); dec_objset_optional(N, 'OPTIONAL') -> dec_objset_optional_1(N, asn1_NOVALUE); dec_objset_optional(_N, mandatory) -> ok. diff --git a/lib/asn1/src/asn1ct_func.erl b/lib/asn1/src/asn1ct_func.erl index 33f998722a..fb94f65b32 100644 --- a/lib/asn1/src/asn1ct_func.erl +++ b/lib/asn1/src/asn1ct_func.erl @@ -19,7 +19,8 @@ %% -module(asn1ct_func). --export([start_link/0,need/1,call/3,call_gen/3,call_gen/4,generate/1]). +-export([start_link/0,need/1,call/3,call_gen/3,call_gen/4, + generate/1,is_used/1]). -export([init/1,handle_call/3,handle_cast/2,terminate/2]). start_link() -> @@ -63,6 +64,10 @@ generate(Fd) -> Funcs = sofs:to_external(Funcs0), ok = file:write(Fd, Funcs). +is_used({_,_,_}=MFA) -> + req({is_used,MFA}). + + req(Req) -> gen_server:call(get(?MODULE), Req, infinity). @@ -103,7 +108,10 @@ handle_call({gen_func,Prefix,Key,GenFun}, _From, #st{gen=G0,gc=Gc0}=St) -> {reply,Name,St#st{gen=G,gc=Gc}}; {value,{Name,_}} -> {reply,Name,St} - end. + end; +handle_call({is_used,MFA}, _From, #st{used=Used}=St) -> + {reply,gb_sets:is_member(MFA, Used),St}. + terminate(_, _) -> ok. diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index 44b050e59d..450d309688 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -29,7 +29,6 @@ list2rname/1, constructed_suffix/2, unify_if_string/1, - gen_check_call/7, get_constraint/2, insert_once/2, ct_gen_module/1, @@ -43,6 +42,8 @@ -export([gen_encode_constructed/4, gen_decode_constructed/4]). +-define(SUPPRESSION_FUNC, 'dialyzer-suppressions'). + %% pgen(Outfile, Erules, Module, TypeOrVal, Options) %% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module %% .hrl file is only generated if necessary @@ -85,12 +86,18 @@ pgen_module(OutFile,Erules,Module, "%%%",nl, "%%% Run-time functions.",nl, "%%%",nl]), + dialyzer_suppressions(Erules), Fd = get(gen_file_out), asn1ct_func:generate(Fd), close_output_file(), _ = erase(outfile), asn1ct:verbose("--~p--~n",[{generated,ErlFile}],Options). +dialyzer_suppressions(Erules) -> + emit([nl, + {asis,?SUPPRESSION_FUNC},"(Arg) ->",nl]), + Rtmod = ct_gen_module(Erules), + Rtmod:dialyzer_suppressions(Erules). pgen_typeorval(Erules,Module,N2nConvEnums,{Types,Values,_Ptypes,_Classes,Objects,ObjectSets}) -> Rtmod = ct_gen_module(Erules), @@ -98,11 +105,6 @@ pgen_typeorval(Erules,Module,N2nConvEnums,{Types,Values,_Ptypes,_Classes,Objects pgen_values(Erules,Module,Values), pgen_objects(Rtmod,Erules,Module,Objects), pgen_objectsets(Rtmod,Erules,Module,ObjectSets), - case catch lists:member(der,get(encoding_options)) of - true -> - pgen_check_defaultval(Erules,Module); - _ -> ok - end, pgen_partial_decode(Rtmod,Erules,Module). pgen_values(_,_,[]) -> @@ -178,23 +180,6 @@ pgen_objectsets(Rtmod,Erules,Module,[H|T]) -> Rtmod:gen_objectset_code(Erules,TypeDef), pgen_objectsets(Rtmod,Erules,Module,T). -pgen_check_defaultval(Erules,Module) -> - CheckObjects = asn1ct_table:to_list(check_functions), - case get(asndebug) of - true -> - FileName = lists:concat([Module,".table"]), - {ok,IoDevice} = file:open(FileName,[write]), - Fun = - fun(X)-> - io:format(IoDevice,"~n~n************~n~n~p~n~n*****" - "********~n~n",[X]) - end, - lists:foreach(Fun,CheckObjects), - ok = file:close(IoDevice); - _ -> ok - end, - gen_check_defaultval(Erules,Module,CheckObjects). - pgen_partial_decode(Rtmod,Erule,Module) when Erule == ber -> pgen_partial_inc_dec(Rtmod,Erule,Module), pgen_partial_dec(Rtmod,Erule,Module); @@ -542,8 +527,7 @@ gen_part_decode_funcs({constructed,bif},TypeName, emit([" 'dec_",TypeName,"'(Data,",{asis,Tag},")"]); gen_part_decode_funcs({primitive,bif},_TypeName, {_Name,undecoded,Tag,Type}) -> - % Argument no 6 is 0, i.e. bit 6 for primitive encoding. - asn1ct_gen_ber_bin_v2:gen_dec_prim(ber_bin_v2,Type,"Data",Tag,[],0,", mandatory, "); + asn1ct_gen_ber_bin_v2:gen_dec_prim(Type, "Data", Tag); gen_part_decode_funcs(WhatKind,_TypeName,{_,Directive,_,_}) -> throw({error,{asn1,{"Not implemented yet",WhatKind," partial incomplete directive:",Directive}}}). @@ -576,131 +560,6 @@ gen_types(Erules,Tname,Type) when is_record(Type,type) -> asn1ct_name:clear(), Rtmod:gen_decode(Erules,Tname,Type). -gen_check_defaultval(Erules,Module,[{Name,Type}|Rest]) -> - gen_check_func(Name,Type), - gen_check_defaultval(Erules,Module,Rest); -gen_check_defaultval(_,_,[]) -> - ok. - -gen_check_func(Name,FType = #type{def=Def}) -> - EncName = ensure_atom(Name), - emit({{asis,EncName},"(_V,asn1_DEFAULT) ->",nl," true;",nl}), - emit({{asis,EncName},"(V,V) ->",nl," true;",nl}), - emit({{asis,EncName},"(V,{_,V}) ->",nl," true;",nl}), - case Def of - {'SEQUENCE OF',Type} -> - gen_check_sof(Name,'SEQOF',Type); - {'SET OF',Type} -> - gen_check_sof(Name,'SETOF',Type); - #'SEQUENCE'{components=Components} -> - gen_check_sequence(Name,Components); - #'SET'{components=Components} -> - gen_check_sequence(Name,Components); - {'CHOICE',Components} -> - gen_check_choice(Name,Components); - #'Externaltypereference'{type=T} -> - emit({{asis,EncName},"(DefaultValue,Value) ->",nl}), - emit({" '",list2name([T,check]),"'(DefaultValue,Value).",nl}); - MaybePrim -> - InnerType = get_inner(MaybePrim), - case type(InnerType) of - {primitive,bif} -> - emit({{asis,EncName},"(DefaultValue,Value) ->",nl," "}), - gen_prim_check_call(get_inner(InnerType),"DefaultValue","Value", - FType), - emit({".",nl,nl}); - _ -> - throw({asn1_error,{unknown,type,MaybePrim}}) - end - end. - -gen_check_sof(Name,SOF,Type) -> - EncName = ensure_atom(Name), - NewName = ensure_atom(list2name([sorted,Name])), - emit({{asis,EncName},"(V1,V2) ->",nl}), - emit({" ",{asis,NewName},"(lists:sort(V1),lists:sort(V2)).",nl,nl}), - emit({{asis,NewName},"([],[]) ->",nl," true;",nl}), - emit({{asis,NewName},"([DV|DVs],[V|Vs]) ->",nl," "}), - InnerType = get_inner(Type#type.def), - case type(InnerType) of - {primitive,bif} -> - gen_prim_check_call(get_inner(InnerType),"DV","V",Type), - emit({",",nl}); - {constructed,bif} -> - emit([{asis,ensure_atom(list2name([SOF,Name]))},"(DV, V),",nl]); - #'Externaltypereference'{type=T} -> - emit([{asis,ensure_atom(list2name([T,check]))},"(DV,V),",nl]); - 'ASN1_OPEN_TYPE' -> - emit(["DV = V,",nl]); - _ -> - emit(["DV = V,",nl]) - end, - emit({" ",{asis,NewName},"(DVs,Vs).",nl,nl}). - -gen_check_sequence(Name, []) -> - emit([{asis,ensure_atom(Name)},"(_,_) ->",nl, - " throw(badval).",nl,nl]); -gen_check_sequence(Name,Components) -> - emit([{asis,ensure_atom(Name)},"(DefaultValue,Value) ->",nl]), - gen_check_sequence(Name,Components,1). - -gen_check_sequence(Name,[#'ComponentType'{name=N,typespec=Type}|Cs],Num) -> - InnerType = get_inner(Type#type.def), - NthDefV = ["element(",Num+1,",DefaultValue)"], - NthV = ["element(",Num+1,",Value)"], - gen_check_func_call(Name,Type,InnerType,NthDefV,NthV,N), - case Cs of - [] -> - emit({".",nl,nl}); - _ -> - emit({",",nl}), - gen_check_sequence(Name,Cs,Num+1) - end. - -gen_check_choice(Name,CList=[#'ComponentType'{}|_Cs]) -> - emit([{asis,ensure_atom(Name)},"({Id,DefaultValue},{Id,Value}) ->",nl]), - emit([" case Id of",nl]), - gen_check_choice_components(Name,CList,1). - -gen_check_choice_components(_,[],_)-> - ok; -gen_check_choice_components(Name,[#'ComponentType'{name=N,typespec=Type}| - Cs],Num) -> - Ind6 = " ", - InnerType = get_inner(Type#type.def), - emit({Ind6,"'",N,"' ->",nl,Ind6}), - gen_check_func_call(Name,Type,InnerType,{var,"defaultValue"}, - {var,"value"},N), - case Cs of - [] -> - emit({nl," end.",nl,nl}); - _ -> - emit({";",nl}), - gen_check_choice_components(Name,Cs,Num+1) - end. - -gen_check_func_call(Name,Type,InnerType,DefVal,Val,N) -> - case type(InnerType) of - {primitive,bif} -> - emit(" "), - gen_prim_check_call(get_inner(InnerType),DefVal,Val,Type); - #'Externaltypereference'{type=T} -> - emit({" ",{asis,ensure_atom(list2name([T,check]))},"(",DefVal,",",Val,")"}); - 'ASN1_OPEN_TYPE' -> - emit([" if",nl, - " ",DefVal," == ",Val," -> true;",nl, - " true -> throw({error,{asn1_open_type}})",nl, - " end",nl]); - {constructed,bif} -> - emit([" ",{asis,ensure_atom(list2name([N,Name]))},"(",DefVal,",",Val,")"]); - _ -> - emit([" if",nl, - " ",DefVal," == ",Val," -> true;",nl, - " true -> throw({error,{asn1_open_type}})",nl, - " end",nl]) - end. - - %% VARIOUS GENERATOR STUFF %% ************************************************* %%************************************************** @@ -790,8 +649,9 @@ gen_decode_constructed(Erules,Typename,InnerType,D) when is_record(D,typedef) -> pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) -> - emit(["-export([encoding_rule/0,bit_string_format/0," + emit(["-export([encoding_rule/0,bit_string_format/0,",nl, " legacy_erlang_types/0]).",nl]), + emit(["-export([",{asis,?SUPPRESSION_FUNC},"/1]).",nl]), case Types of [] -> ok; _ -> @@ -1077,9 +937,10 @@ gen_partial_inc_dispatcher() -> ok; {Data1,Data2} -> % io:format("partial_incomplete_decode: ~p~ninc_type_pattern: ~p~n",[Data,Data2]), - gen_partial_inc_dispatcher(Data1,Data2) + gen_partial_inc_dispatcher(Data1, Data2, "") end. -gen_partial_inc_dispatcher([{FuncName,TopType,_Pattern}|Rest],TypePattern) -> + +gen_partial_inc_dispatcher([{FuncName,TopType,_Pattern}|Rest], TypePattern, Sep) -> TPattern = case lists:keysearch(FuncName,1,TypePattern) of {value,{_,TP}} -> TP; @@ -1093,13 +954,13 @@ gen_partial_inc_dispatcher([{FuncName,TopType,_Pattern}|Rest],TypePattern) -> _ -> atom_to_list(TopType) end, - emit(["decode_partial_inc_disp('",TopTypeName,"',Data) ->",nl, + emit([Sep, + "decode_partial_inc_disp('",TopTypeName,"',Data) ->",nl, " ",{asis,list_to_atom(lists:concat(["dec-inc-",FuncName2]))}, - "(Data);",nl]), - gen_partial_inc_dispatcher(Rest,TypePattern); -gen_partial_inc_dispatcher([],_) -> - emit(["decode_partial_inc_disp(Type,_Data) ->",nl, - " exit({error,{asn1,{undefined_type,Type}}}).",nl]). + "(Data)"]), + gen_partial_inc_dispatcher(Rest, TypePattern, ";\n"); +gen_partial_inc_dispatcher([], _, _) -> + emit([".",nl]). gen_dispatcher([F1,F2|T],FuncName,Prefix,ExtraArg) -> emit([FuncName,"('",F1,"',Data) -> '",Prefix,F1,"'(Data",ExtraArg,")",";",nl]), @@ -1465,171 +1326,6 @@ to_textual_order(Cs=[#'ComponentType'{textual_order=undefined}|_]) -> to_textual_order(Cs) when is_list(Cs) -> lists:keysort(#'ComponentType'.textual_order,Cs). - -gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) -> - case WhatKind of - {primitive,bif} -> - gen_prim_check_call(InnerType,DefaultValue,Element,Type); - #'Externaltypereference'{module=M,type=T} -> - %% generate function call - Name = list2name([T,check]), - emit({"'",Name,"'(",DefaultValue,", ",Element,")"}), - %% insert in ets table and do look ahead check - Typedef = asn1_db:dbget(M,T), - RefType = Typedef#typedef.typespec, - InType = asn1ct_gen:get_inner(RefType#type.def), - case insert_once(check_functions,{Name,RefType}) of - true -> - lookahead_innertype([T],InType,RefType); - _ -> - ok - end; - {constructed,bif} -> - NameList = [Cname|TopType], - Name = list2name(NameList ++ [check]), - emit({"'",Name,"'(",DefaultValue,", ",Element,")"}), - asn1ct_table:insert(check_functions, {Name, Type}), - %% Must look for check functions in InnerType, - %% that may be referenced or internal defined - %% constructed types not used elsewhere. - lookahead_innertype(NameList,InnerType,Type); - _ -> - %% Generate Dummy function call i.e. anything is accepted - emit(["fun() -> true end ()"]) - end. - -gen_prim_check_call(PrimType, Default, Element, Type) -> - case unify_if_string(PrimType) of - 'BOOLEAN' -> - check_call(check_bool, [Default,Element]); - 'INTEGER' -> - NNL = case Type#type.def of - {_,NamedNumberList} -> NamedNumberList; - _ -> [] - end, - check_call(check_int, [Default,Element,{asis,NNL}]); - 'BIT STRING' -> - case Type#type.def of - {_,[]} -> - check_call(check_bitstring, - [Default,Element]); - {_,[_|_]=NBL} -> - check_call(check_named_bitstring, - [Default,Element,{asis,NBL}]) - end; - 'OCTET STRING' -> - check_call(check_octetstring, [Default,Element]); - 'NULL' -> - check_call(check_null, [Default,Element]); - 'OBJECT IDENTIFIER' -> - check_call(check_objectidentifier, [Default,Element]); - 'RELATIVE-OID' -> - check_call(check_objectidentifier, [Default,Element]); - 'ObjectDescriptor' -> - check_call(check_objectdescriptor, [Default,Element]); - 'REAL' -> - check_call(check_real, [Default,Element]); - 'ENUMERATED' -> - {_,Enumerations} = Type#type.def, - check_call(check_enum, [Default,Element,{asis,Enumerations}]); - restrictedstring -> - check_call(check_restrictedstring, [Default,Element]) - end. - -check_call(F, Args) -> - asn1ct_func:call(check, F, Args). - -%% lokahead_innertype/3 traverses Type and checks if check functions -%% have to be generated, i.e. for all constructed or referenced types. -lookahead_innertype(Name,'SEQUENCE',Type) -> - Components = (Type#type.def)#'SEQUENCE'.components, - lookahead_components(Name,Components); -lookahead_innertype(Name,'SET',Type) -> - Components = (Type#type.def)#'SET'.components, - lookahead_components(Name,Components); -lookahead_innertype(Name,'CHOICE',Type) -> - {_,Components} = Type#type.def, - lookahead_components(Name,Components); -lookahead_innertype(Name,'SEQUENCE OF',SeqOf) -> - lookahead_sof(Name,'SEQOF',SeqOf); -lookahead_innertype(Name,'SET OF',SeqOf) -> - lookahead_sof(Name,'SETOF',SeqOf); -lookahead_innertype(_Name,#'Externaltypereference'{module=M,type=T},_) -> - Typedef = asn1_db:dbget(M,T), - RefType = Typedef#typedef.typespec, - insert_once(check_functions,{list2name([T,check]),RefType}), - InType = asn1ct_gen:get_inner(RefType#type.def), - case type(InType) of - {constructed,bif} -> - lookahead_innertype([T],InType,RefType); - Ref = #'Externaltypereference'{} -> - lookahead_reference(Ref); - _ -> - ok - end; -lookahead_innertype(_,_,_) -> - ok. - -lookahead_components(_,[]) -> ok; -lookahead_components(Name,[C|Cs]) -> - #'ComponentType'{name=Cname,typespec=Type} = C, - InType = asn1ct_gen:get_inner(Type#type.def), - case asn1ct_gen:type(InType) of - {constructed,bif} -> - case insert_once(check_functions, - {list2name([Cname|Name] ++ [check]),Type}) of - true -> - lookahead_innertype([Cname|Name],InType,Type); - _ -> - ok - end; - #'Externaltypereference'{module=RefMod,type=RefName} -> - Typedef = asn1_db:dbget(RefMod,RefName), - RefType = Typedef#typedef.typespec, - case insert_once(check_functions,{list2name([RefName,check]), - RefType}) of - true -> - lookahead_innertype([RefName],InType,RefType); - _ -> - ok - end; - _ -> - ok - end, - lookahead_components(Name,Cs). - -lookahead_sof(Name,SOF,SOFType) -> - Type = case SOFType#type.def of - {_,_Type} -> _Type; - _Type -> _Type - end, - InnerType = asn1ct_gen:get_inner(Type#type.def), - case asn1ct_gen:type(InnerType) of - {constructed,bif} -> - %% this is if a constructed type is defined in - %% the SEQUENCE OF type - NameList = [SOF|Name], - insert_once(check_functions, - {list2name(NameList ++ [check]),Type}), - lookahead_innertype(NameList,InnerType,Type); - Ref = #'Externaltypereference'{} -> - lookahead_reference(Ref); - _ -> - ok - end. - -lookahead_reference(#'Externaltypereference'{module=M,type=T}) -> - Typedef = asn1_db:dbget(M,T), - RefType = Typedef#typedef.typespec, - InType = get_inner(RefType#type.def), - case insert_once(check_functions, - {list2name([T,check]),RefType}) of - true -> - lookahead_innertype([T],InType,RefType); - _ -> - ok - end. - insert_once(Table,Object) -> case asn1ct_table:lookup(Table, element(1, Object)) of [] -> @@ -1683,6 +1379,11 @@ conform_value(#type{def={'BIT STRING',[]}}, Bs) -> bitstring when is_bitstring(Bs) -> Bs end; +conform_value(#type{def='OCTET STRING'}, String) -> + case asn1ct:use_legacy_types() of + false -> String; + true -> binary_to_list(String) + end; conform_value(_, Value) -> Value. named_bitstring_value(List, Names) -> @@ -1901,11 +1602,6 @@ get_constraint(C,Key) -> {value,Cnstr} -> Cnstr end. - -ensure_atom(Atom) when is_atom(Atom) -> - Atom; -ensure_atom(List) when is_list(List) -> - list_to_atom(List). get_record_name_prefix() -> case lists:keysearch(record_name_prefix,1,get(encoding_options)) of diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index bea0ec8968..e51b0898be 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -27,11 +27,12 @@ -export([decode_class/1, decode_type/1]). -export([gen_encode/2,gen_encode/3,gen_decode/2,gen_decode/3]). -export([gen_encode_prim/4]). --export([gen_dec_prim/7]). +-export([gen_dec_prim/3]). -export([gen_objectset_code/2, gen_obj_code/3]). -export([encode_tag_val/3]). -export([gen_inc_decode/2,gen_decode_selected/3]). -export([extaddgroup2sequence/1]). +-export([dialyzer_suppressions/1]). -import(asn1ct_gen, [emit/1,demit/1]). @@ -65,6 +66,23 @@ %%=============================================================================== %%=============================================================================== +dialyzer_suppressions(_) -> + case asn1ct:use_legacy_types() of + false -> ok; + true -> suppress({ber,encode_bit_string,4}) + end, + suppress({ber,decode_selective,2}), + emit([" ok.",nl]). + +suppress({M,F,A}=MFA) -> + case asn1ct_func:is_used(MFA) of + false -> + ok; + true -> + Args = [lists:concat(["element(",I,", Arg)"]) || I <- lists:seq(1, A)], + emit([" ",{call,M,F,Args},com,nl]) + end. + %%=============================================================================== %% encode #{typedef, {pos, name, typespec}} %%=============================================================================== @@ -163,6 +181,12 @@ gen_encode_user(Erules, #typedef{}=D, Wrapper) -> gen_encode_prim(_Erules, #type{}=D, DoTag, Value) -> BitStringConstraint = get_size_constraint(D#type.constraint), + MaxBitStrSize = case BitStringConstraint of + [] -> none; + {_,'MAX'} -> none; + {_,Max} -> Max; + Max when is_integer(Max) -> Max + end, asn1ct_name:new(enumval), Type = case D#type.def of 'OCTET STRING' -> restricted_string; @@ -208,11 +232,11 @@ gen_encode_prim(_Erules, #type{}=D, DoTag, Value) -> "end"]); {'BIT STRING',[]} -> case asn1ct:use_legacy_types() of - false when BitStringConstraint =:= [] -> + false when MaxBitStrSize =:= none -> call(encode_unnamed_bit_string, [Value,DoTag]); false -> call(encode_unnamed_bit_string, - [{asis,BitStringConstraint},Value,DoTag]); + [{asis,MaxBitStrSize},Value,DoTag]); true -> call(encode_bit_string, [{asis,BitStringConstraint},Value, @@ -220,12 +244,12 @@ gen_encode_prim(_Erules, #type{}=D, DoTag, Value) -> end; {'BIT STRING',NamedNumberList} -> case asn1ct:use_legacy_types() of - false when BitStringConstraint =:= [] -> + false when MaxBitStrSize =:= none -> call(encode_named_bit_string, [Value,{asis,NamedNumberList},DoTag]); false -> call(encode_named_bit_string, - [{asis,BitStringConstraint},Value, + [{asis,MaxBitStrSize},Value, {asis,NamedNumberList},DoTag]); true -> call(encode_bit_string, @@ -254,14 +278,20 @@ emit_enc_enumerated_cases(L, Tags) -> emit_enc_enumerated_cases(L, Tags, noext). emit_enc_enumerated_cases([{EnumName,EnumVal}|T], Tags, Ext) -> + Bytes = encode_pos_integer(EnumVal, []), + Len = length(Bytes), emit([{asis,EnumName}," -> ", - {call,ber,encode_enumerated,[EnumVal,Tags]},";",nl]), + {call,ber,encode_tags,[Tags,{asis,Bytes},Len]},";",nl]), emit_enc_enumerated_cases(T, Tags, Ext); emit_enc_enumerated_cases([], _Tags, _Ext) -> %% FIXME: Should extension be handled? emit([{curr,enumval}," -> exit({error,{asn1, {enumerated_not_in_range,",{curr, enumval},"}}})"]), emit([nl,"end"]). +encode_pos_integer(0, [B|_Acc] = L) when B < 128 -> + L; +encode_pos_integer(N, Acc) -> + encode_pos_integer(N bsr 8, [N band 255|Acc]). %%=============================================================================== %%=============================================================================== @@ -339,15 +369,11 @@ gen_decode_selected_type(_Erules,TypeDef) -> case asn1ct_gen:type(InnerType) of 'ASN1_OPEN_TYPE' -> asn1ct_name:new(len), - gen_dec_prim(ber, Def#type{def='ASN1_OPEN_TYPE'}, - BytesVar,Tag, [] , - ?PRIMITIVE,"OptOrMand"); -% emit({";",nl}); + gen_dec_prim(Def#type{def='ASN1_OPEN_TYPE'}, + BytesVar, Tag); {primitive,bif} -> asn1ct_name:new(len), - gen_dec_prim(ber, Def, BytesVar,Tag,[] , - ?PRIMITIVE,"OptOrMand"); -% emit([";",nl]); + gen_dec_prim(Def, BytesVar, Tag); {constructed,bif} -> TopType = case TypeDef#typedef.name of A when is_atom(A) -> [A]; @@ -461,14 +487,12 @@ gen_decode_user(Erules,D) when is_record(D,typedef) -> case asn1ct_gen:type(InnerType) of 'ASN1_OPEN_TYPE' -> asn1ct_name:new(len), - gen_dec_prim(ber, Def#type{def='ASN1_OPEN_TYPE'}, - BytesVar,{string,"TagIn"}, [] , - ?PRIMITIVE,"OptOrMand"), + gen_dec_prim(Def#type{def='ASN1_OPEN_TYPE'}, + BytesVar, {string,"TagIn"}), emit({".",nl,nl}); {primitive,bif} -> asn1ct_name:new(len), - gen_dec_prim(ber, Def, BytesVar,{string,"TagIn"},[] , - ?PRIMITIVE,"OptOrMand"), + gen_dec_prim(Def, BytesVar, {string,"TagIn"}), emit([".",nl,nl]); {constructed,bif} -> asn1ct:update_namelist(D#typedef.name), @@ -481,17 +505,10 @@ gen_decode_user(Erules,D) when is_record(D,typedef) -> end. -gen_dec_prim(_Erules, Att, BytesVar, DoTag, _TagIn, _Form, _OptOrMand) -> +gen_dec_prim(Att, BytesVar, DoTag) -> Typename = Att#type.def, -%% Currently not used for BER replaced with [] as place holder -%% Constraint = Att#type.constraint, -%% Constraint = [], Constraint = get_size_constraint(Att#type.constraint), IntConstr = int_constr(Att#type.constraint), - AsBin = case get(binary_strings) of - true -> "_as_bin"; - _ -> "" - end, NewTypeName = case Typename of 'NumericString' -> restricted_string; 'TeletexString' -> restricted_string; @@ -505,107 +522,77 @@ gen_dec_prim(_Erules, Att, BytesVar, DoTag, _TagIn, _Form, _OptOrMand) -> 'ObjectDescriptor'-> restricted_string; 'UTCTime' -> restricted_string; 'GeneralizedTime' -> restricted_string; + 'OCTET STRING' -> + case asn1ct:use_legacy_types() of + true -> restricted_string; + false -> Typename + end; _ -> Typename end, + TagStr = case DoTag of + {string,Tag1} -> Tag1; + _ when is_list(DoTag) -> {asis,DoTag} + end, case NewTypeName of 'BOOLEAN'-> - emit(["decode_boolean(",BytesVar,","]), - need(decode_boolean, 2); + call(decode_boolean, [BytesVar,TagStr]); 'INTEGER' -> - case IntConstr of - [] -> - emit(["decode_integer(",BytesVar,","]), - need(decode_integer, 2); - {_,_} -> - emit(["decode_integer(",BytesVar,",", - {asis,IntConstr},","]), - need(decode_integer, 3) - end; - {'INTEGER',NamedNumberList} -> - case IntConstr of - [] -> - emit(["decode_named_integer(",BytesVar,",", - {asis,NamedNumberList},","]), - need(decode_named_integer, 3); - {_,_} -> - emit(["decode_named_integer(",BytesVar,",", - {asis,IntConstr},",", - {asis,NamedNumberList},","]), - need(decode_named_integer, 4) - end; - {'ENUMERATED',NamedNumberList} -> - emit(["decode_enumerated(",BytesVar,",", - {asis,NamedNumberList},","]), - need(decode_enumerated, 3); + check_constraint(decode_integer, [BytesVar,TagStr], + IntConstr, + identity, + identity); + {'INTEGER',NNL} -> + check_constraint(decode_integer, + [BytesVar,TagStr], + IntConstr, + identity, + fun(Val) -> + asn1ct_name:new(val), + emit([{curr,val}," = "]), + Val(), + emit([com,nl, + {call,ber,number2name, + [{curr,val},{asis,NNL}]}]) + end); + {'ENUMERATED',NNL} -> + gen_dec_enumerated(BytesVar, NNL, TagStr); 'REAL' -> - ok; - {'BIT STRING',_NamedNumberList} -> - ok; + asn1ct_name:new(tmpbuf), + emit(["begin",nl, + {curr,tmpbuf}," = ", + {call,ber,match_tags,[BytesVar,TagStr]},com,nl, + {call,real_common,decode_real,[{curr,tmpbuf}]},nl, + "end",nl]); + {'BIT STRING',NNL} -> + gen_dec_bit_string(BytesVar, Constraint, NNL, TagStr); 'NULL' -> - emit(["decode_null(",BytesVar,","]), - need(decode_null, 2); + call(decode_null, [BytesVar,TagStr]); 'OBJECT IDENTIFIER' -> - emit(["decode_object_identifier(",BytesVar,","]), - need(decode_object_identifier, 2); + call(decode_object_identifier, [BytesVar,TagStr]); 'RELATIVE-OID' -> - emit(["decode_relative_oid(",BytesVar,","]), - need(decode_relative_oid, 2); + call(decode_relative_oid, [BytesVar,TagStr]); 'OCTET STRING' -> - F = case asn1ct:use_legacy_types() of - false -> decode_octet_string; - true -> decode_restricted_string - end, - emit([{asis,F},"(",BytesVar,","]), - case Constraint of - [] -> - need(F, 2); - _ -> - emit([{asis,Constraint},","]), - need(F, 3) - end; + check_constraint(decode_octet_string, [BytesVar,TagStr], + Constraint, {erlang,byte_size}, identity); restricted_string -> - emit(["decode_restricted_string",AsBin,"(",BytesVar,","]), - case Constraint of - [] -> - need(decode_restricted_string, 2); - _ -> - emit([{asis,Constraint},","]), - need(decode_restricted_string, 3) - end; + check_constraint(decode_restricted_string, [BytesVar,TagStr], + Constraint, + {erlang,byte_size}, + fun(Val) -> + emit("binary_to_list("), + Val(), + emit(")") + end); 'UniversalString' -> - emit(["decode_universal_string",AsBin,"(", - BytesVar,",",{asis,Constraint},","]), - need(decode_universal_string, 3); + check_constraint(decode_universal_string, [BytesVar,TagStr], + Constraint, {erlang,length}, identity); 'UTF8String' -> - emit(["decode_UTF8_string",AsBin,"(", - BytesVar,","]), - need(decode_UTF8_string, 2); + call(decode_UTF8_string, [BytesVar,TagStr]); 'BMPString' -> - emit(["decode_BMP_string",AsBin,"(", - BytesVar,",",{asis,Constraint},","]), - need(decode_BMP_string, 3); + check_constraint(decode_BMP_string, [BytesVar,TagStr], + Constraint, {erlang,length}, identity); 'ASN1_OPEN_TYPE' -> - emit(["decode_open_type_as_binary(", - BytesVar,","]), - need(decode_open_type_as_binary, 2) - end, - - TagStr = case DoTag of - {string,Tag1} -> Tag1; - _ when is_list(DoTag) -> {asis,DoTag} - end, - case NewTypeName of - {'BIT STRING',NNL} -> - gen_dec_bit_string(BytesVar, Constraint, NNL, TagStr); - 'REAL' -> - asn1ct_name:new(tmpbuf), - emit(["begin",nl, - {curr,tmpbuf}," = ", - {call,ber,match_tags,[BytesVar,TagStr]},com,nl, - {call,real_common,decode_real,[{curr,tmpbuf}]},nl, - "end",nl]); - _ -> - emit([TagStr,")"]) + call(decode_open_type_as_binary, [BytesVar,TagStr]) end. %% Simplify an integer constraint so that we can efficiently test it. @@ -621,7 +608,7 @@ int_constr(C) -> [{'ValueRange',{_,_}=Range}] -> Range; [{'SingleValue',Sv}] -> - {Sv,Sv}; + Sv; [] -> [] end. @@ -632,16 +619,108 @@ gen_dec_bit_string(BytesVar, _Constraint, [_|_]=NNL, TagStr) -> gen_dec_bit_string(BytesVar, Constraint, [], TagStr) -> case asn1ct:get_bit_string_format() of compact -> - call(decode_compact_bit_string, - [BytesVar,{asis,Constraint},TagStr]); + check_constraint(decode_compact_bit_string, + [BytesVar,TagStr], + Constraint, + {ber,compact_bit_string_size}, + identity); legacy -> - call(decode_legacy_bit_string, - [BytesVar,{asis,Constraint},TagStr]); + check_constraint(decode_native_bit_string, + [BytesVar,TagStr], + Constraint, + {erlang,bit_size}, + fun(Val) -> + asn1ct_name:new(val), + emit([{curr,val}," = "]), + Val(), + emit([com,nl, + {call,ber,native_to_legacy_bit_string, + [{curr,val}]}]) + end); bitstring -> - call(decode_native_bit_string, - [BytesVar,{asis,Constraint},TagStr]) + check_constraint(decode_native_bit_string, + [BytesVar,TagStr], + Constraint, + {erlang,bit_size}, + identity) + end. + +check_constraint(F, Args, Constr, PreConstr0, ReturnVal0) -> + PreConstr = case PreConstr0 of + identity -> + fun(V) -> V end; + {Mod,Name} -> + fun(V) -> + asn1ct_name:new(c), + emit([{curr,c}," = ", + {call,Mod,Name,[V]},com,nl]), + {curr,c} + end + end, + ReturnVal = case ReturnVal0 of + identity -> fun(Val) -> Val() end; + _ -> ReturnVal0 + end, + case Constr of + [] when ReturnVal0 =:= identity -> + %% No constraint, no complications. + call(F, Args); + [] -> + %% No constraint, but the return value could consist + %% of more than one statement. + emit(["begin",nl]), + ReturnVal(fun() -> call(F, Args) end), + emit([nl, + "end",nl]); + _ -> + %% There is a constraint. + asn1ct_name:new(val), + emit(["begin",nl, + {curr,val}," = ",{call,ber,F,Args},com,nl]), + PreVal0 = asn1ct_gen:mk_var(asn1ct_name:curr(val)), + PreVal = PreConstr(PreVal0), + emit("if "), + case Constr of + {Min,Max} -> + emit([{asis,Min}," =< ",PreVal,", ", + PreVal," =< ",{asis,Max}]); + Sv when is_integer(Sv) -> + emit([PreVal," =:= ",{asis,Sv}]) + end, + emit([" ->",nl]), + ReturnVal(fun() -> emit(PreVal0) end), + emit([";",nl, + "true ->",nl, + "exit({error,{asn1,bad_range}})",nl, + "end",nl, + "end"]) end. +gen_dec_enumerated(BytesVar, NNL0, TagStr) -> + asn1ct_name:new(enum), + emit(["case ", + {call,ber,decode_integer,[BytesVar,TagStr]}, + " of",nl]), + NNL = case NNL0 of + {L1,L2} -> + L1 ++ L2 ++ [accept]; + [_|_] -> + NNL0 ++ [error] + end, + gen_dec_enumerated_1(NNL), + emit("end"). + +gen_dec_enumerated_1([accept]) -> + asn1ct_name:new(default), + emit([{curr,default}," -> {asn1_enum,",{curr,default},"}",nl]); +gen_dec_enumerated_1([error]) -> + asn1ct_name:new(default), + emit([{curr,default}," -> exit({error,{asn1,{illegal_enumerated,", + {curr,default},"}}})",nl]); +gen_dec_enumerated_1([{V,K}|T]) -> + emit([{asis,K}," -> ",{asis,V},";",nl]), + gen_dec_enumerated_1(T). + %% Object code generating for encoding and decoding %% ------------------------------------------------ @@ -986,9 +1065,8 @@ gen_decode_field_call(ObjName,FieldName,Bytes,Type) -> Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- OTag], case Type#typedef.name of - {primitive,bif} -> %%tag should be the primitive tag - gen_dec_prim(ber,Def,Bytes,Tag,"TagIn",?PRIMITIVE, - opt_or_default), + {primitive,bif} -> + gen_dec_prim(Def, Bytes, Tag), []; {constructed,bif} -> emit({" 'dec_",ObjName,'_',FieldName, @@ -1016,8 +1094,7 @@ gen_decode_default_call(ClassName,FieldName,Bytes,Type) -> FieldName])), typespec=Type}]; {primitive,bif} -> - gen_dec_prim(ber,Type,Bytes,Tag,"TagIn", - ?PRIMITIVE,opt_or_default), + gen_dec_prim(Type, Bytes, Tag), []; #'Externaltypereference'{module=CurrentMod,type=Etype} -> emit([" 'dec_",Etype,"'(",Bytes, " ,",{asis,Tag},")",nl]), @@ -1386,7 +1463,7 @@ emit_dec_open_type(I) -> end, emit(S). -emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop, +emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type}, _Prop, InternalDefFunName) -> OTag = Type#type.tag, %% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag], @@ -1394,8 +1471,7 @@ emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop, case {ExtName,Name} of {primitive,bif} -> emit(indent(12)), - gen_dec_prim(ber,Type,"Bytes",Tag,"TagIn", - ?PRIMITIVE,Prop), + gen_dec_prim(Type, "Bytes", Tag), 0; {constructed,bif} -> emit([indent(12),"'dec_", @@ -1412,7 +1488,7 @@ emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop, emit_inner_of_decfun(#typedef{name=Name},_Prop,_) -> emit([indent(12),"'dec_",Name,"'(Bytes)"]), 0; -emit_inner_of_decfun(Type,Prop,_) when is_record(Type,type) -> +emit_inner_of_decfun(#type{}=Type, _Prop, _) -> OTag = Type#type.tag, %% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag], Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- OTag], @@ -1423,8 +1499,7 @@ emit_inner_of_decfun(Type,Prop,_) when is_record(Type,type) -> case WhatKind of {primitive,bif} -> emit([indent(9),Def," ->",nl,indent(12)]), - gen_dec_prim(ber,Type,"Bytes",Tag,"TagIn", - ?PRIMITIVE,Prop); + gen_dec_prim(Type, "Bytes", Tag); #'Externaltypereference'{module=CurrMod,type=T} -> emit([indent(9),T," ->",nl,indent(12),"'dec_",T, % "'(Bytes, ",Prop,")"]); @@ -1561,6 +1636,3 @@ extaddgroup2sequence(ExtList) when is_list(ExtList) -> call(F, Args) -> asn1ct_func:call(ber, F, Args). - -need(F, Arity) -> - asn1ct_func:need({ber,F,Arity}). diff --git a/lib/asn1/src/asn1ct_gen_check.erl b/lib/asn1/src/asn1ct_gen_check.erl new file mode 100644 index 0000000000..d80a02dfbf --- /dev/null +++ b/lib/asn1/src/asn1ct_gen_check.erl @@ -0,0 +1,271 @@ +%% vim: tabstop=8:shiftwidth=4 +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. 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(asn1ct_gen_check). +-export([emit/3]). + +-import(asn1ct_gen, [emit/1]). +-include("asn1_records.hrl"). + +emit(Type, Default, Value) -> + Key = {Type,Default}, + Gen = fun(Fd, Name) -> + file:write(Fd, gen(Name, Type, Default)) + end, + emit(" case "), + asn1ct_func:call_gen("is_default_", Key, Gen, [Value]), + emit([" of",nl, + "true -> {[],0};",nl, + "false ->",nl]). + +gen(Name, #type{def=T}, Default) -> + NameStr = atom_to_list(Name), + [NameStr,"(asn1_DEFAULT) ->\n", + "true;\n"|case do_gen(T, Default) of + {literal,Literal} -> + [NameStr,"(",term2str(Literal),") ->\n","true;\n", + NameStr,"(_) ->\n","false.\n\n"]; + {exception,Func,Args} -> + [NameStr,"(Value) ->\n", + "try ",Func,"(Value",arg2str(Args),") of\n", + "_ -> true\n" + "catch throw:false -> false\n" + "end.\n\n"] + end]. + +do_gen(_, asn1_NOVALUE) -> + {literal,asn1_NOVALUE}; +do_gen(#'Externaltypereference'{module=M,type=T}, Default) -> + #typedef{typespec=#type{def=Td}} = asn1_db:dbget(M, T), + do_gen(Td, Default); +do_gen('BOOLEAN', Default) -> + {literal,Default}; +do_gen({'BIT STRING',[]}, Default) -> + true = is_bitstring(Default), %Assertion. + case asn1ct:use_legacy_types() of + false -> + {literal,Default}; + true -> + {exception,need(check_legacy_bitstring, 2),[Default]} + end; +do_gen({'BIT STRING',[_|_]=NBL}, Default) -> + do_named_bitstring(NBL, Default); +do_gen({'ENUMERATED',_}, Default) -> + {literal,Default}; +do_gen('INTEGER', Default) -> + {literal,Default}; +do_gen({'INTEGER',NNL}, Default) -> + {exception,need(check_int, 3),[Default,NNL]}; +do_gen('NULL', Default) -> + {literal,Default}; +do_gen('OCTET STRING', Default) -> + true = is_binary(Default), %Assertion. + case asn1ct:use_legacy_types() of + false -> + {literal,Default}; + true -> + {exception,need(check_octetstring, 2),[Default]} + end; +do_gen('OBJECT IDENTIFIER', Default0) -> + Default = pre_process_oid(Default0), + {exception,need(check_objectidentifier, 2),[Default]}; +do_gen({'CHOICE',Cs}, Default) -> + {Tag,Value} = Default, + [Type] = [Type || #'ComponentType'{name=T,typespec=Type} <- Cs, + T =:= Tag], + case do_gen(Type#type.def, Value) of + {literal,Lit} -> + {literal,{Tag,Lit}}; + {exception,Func0,Args} -> + Key = {Tag,Func0,Args}, + Gen = fun(Fd, Name) -> + S = gen_choice(Name, Tag, Func0, Args), + ok = file:write(Fd, S) + end, + Func = asn1ct_func:call_gen("is_default_choice", Key, Gen), + {exception,atom_to_list(Func),[]} + end; +do_gen(#'SEQUENCE'{components=Cs}, Default) -> + do_seq_set(Cs, Default); +do_gen({'SEQUENCE OF',Type}, Default) -> + do_sof(Type, Default); +do_gen(#'SET'{components=Cs}, Default) -> + do_seq_set(Cs, Default); +do_gen({'SET OF',Type}, Default) -> + do_sof(Type, Default); +do_gen(Type, Default) -> + case asn1ct_gen:unify_if_string(Type) of + restrictedstring -> + {exception,need(check_restrictedstring, 2),[Default]}; + _ -> + %% Open type. Do our best. + {literal,Default} + end. + +do_named_bitstring(NBL, Default0) when is_list(Default0) -> + Default = lists:sort(Default0), + Bs = asn1ct_gen:named_bitstring_value(Default, NBL), + Func = case asn1ct:use_legacy_types() of + false -> check_named_bitstring; + true -> check_legacy_named_bitstring + end, + {exception,need(Func, 4),[Default,Bs,bit_size(Bs)]}; +do_named_bitstring(_, Default) when is_bitstring(Default) -> + Func = case asn1ct:use_legacy_types() of + false -> check_named_bitstring; + true -> check_legacy_named_bitstring + end, + {exception,need(Func, 3),[Default,bit_size(Default)]}. + +do_seq_set(Cs0, Default) -> + Tag = element(1, Default), + Cs1 = [T || #'ComponentType'{typespec=T} <- Cs0], + Cs = components(Cs1, tl(tuple_to_list(Default))), + case are_all_literals(Cs) of + true -> + Literal = list_to_tuple([Tag|[L || {literal,L} <- Cs]]), + {literal,Literal}; + false -> + Key = {Cs,Default}, + Gen = fun(Fd, Name) -> + S = gen_components(Name, Tag, Cs), + ok = file:write(Fd, S) + end, + Func = asn1ct_func:call_gen("is_default_cs_", Key, Gen), + {exception,atom_to_list(Func),[]} + end. + +do_sof(Type, Default0) -> + Default = lists:sort(Default0), + Cs0 = lists:duplicate(length(Default), Type), + Cs = components(Cs0, Default), + case are_all_literals(Cs) of + true -> + Literal = [Lit || {literal,Lit} <- Cs], + {exception,need(check_literal_sof, 2),[Literal]}; + false -> + Key = Cs, + Gen = fun(Fd, Name) -> + S = gen_sof(Name, Cs), + ok = file:write(Fd, S) + end, + Func = asn1ct_func:call_gen("is_default_sof", Key, Gen), + {exception,atom_to_list(Func),[]} + end. + +are_all_literals([{literal,_}|T]) -> + are_all_literals(T); +are_all_literals([_|_]) -> + false; +are_all_literals([]) -> true. + +gen_components(Name, Tag, Cs) -> + [atom_to_list(Name),"(Value) ->\n", + "case Value of\n", + "{",term2str(Tag)|gen_cs_1(Cs, 1, [])]. + +gen_cs_1([{literal,Lit}|T], I, Acc) -> + [",\n",term2str(Lit)|gen_cs_1(T, I, Acc)]; +gen_cs_1([H|T], I, Acc) -> + Var = "E"++integer_to_list(I), + [",\n",Var|gen_cs_1(T, I+1, [{Var,H}|Acc])]; +gen_cs_1([], _, Acc) -> + ["} ->\n"|gen_cs_2(Acc, "")]. + +gen_cs_2([{Var,{exception,Func,Args}}|T], Sep) -> + [Sep,Func,"(",Var,arg2str(Args),")"|gen_cs_2(T, ",\n")]; +gen_cs_2([], _) -> + [";\n", + "_ ->\n" + "throw(false)\n" + "end.\n"]. + +gen_sof(Name, Cs) -> + [atom_to_list(Name),"(Value) ->\n", + "case length(Value) of\n", + integer_to_list(length(Cs))," -> ok;\n" + "_ -> throw(false)\n" + "end,\n" + "T0 = lists:sort(Value)"|gen_sof_1(Cs, 1)]. + +gen_sof_1([{exception,Func,Args}|Cs], I) -> + NumStr = integer_to_list(I), + H = "H" ++ NumStr, + T = "T" ++ NumStr, + Prev = "T" ++ integer_to_list(I-1), + [",\n", + "[",H,case Cs of + [] -> []; + [_|_] -> ["|",T] + end,"] = ",Prev,",\n", + Func,"(",H,arg2str(Args),")"|gen_sof_1(Cs, I+1)]; +gen_sof_1([], _) -> + ".\n". + +components([#type{def=Def}|Ts], [V|Vs]) -> + [do_gen(Def, V)|components(Ts, Vs)]; +components([], []) -> []. + +gen_choice(Name, Tag, Func, Args) -> + NameStr = atom_to_list(Name), + [NameStr,"({",term2str(Tag),",Value}) ->\n" + " ",Func,"(Value",arg2str(Args),");\n", + NameStr,"(_) ->\n" + " throw(false).\n"]. + +pre_process_oid(Oid) -> + Reserved = reserved_oid(), + pre_process_oid(tuple_to_list(Oid), Reserved, []). + +pre_process_oid([H|T]=Tail, Res0, Acc) -> + case lists:keyfind(H, 2, Res0) of + false -> + {lists:reverse(Acc),Tail}; + {Names0,H,Res} -> + Names = case is_list(Names0) of + false -> [Names0]; + true -> Names0 + end, + Keys = [H|Names], + pre_process_oid(T, Res, [Keys|Acc]) + end. + +reserved_oid() -> + [{['itu-t',ccitt],0, + [{recommendation,0,[]}, + {question,1,[]}, + {administration,2,[]}, + {'network-operator',3,[]}, + {'identified-organization',4,[]}]}, + {iso,1,[{standard,0,[]}, + {'member-body',2,[]}, + {'identified-organization',3,[]}]}, + {['joint-iso-itu-t','joint-iso-ccitt'],2,[]}]. + +arg2str(Args) -> + [", "++term2str(Arg) || Arg <- Args]. + +term2str(T) -> + io_lib:format("~w", [T]). + +need(F, A) -> + asn1ct_func:need({check,F,A}), + atom_to_list(F). diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 519ce9f054..39cc0536f8 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -32,6 +32,7 @@ -export([gen_encode/2, gen_encode/3]). -export([gen_dec_external/2]). -export([extaddgroup2sequence/1]). +-export([dialyzer_suppressions/1]). -import(asn1ct_gen, [emit/1,demit/1]). -import(asn1ct_func, [call/3]). @@ -40,6 +41,15 @@ %% Generate ENCODING ****************************** %%****************************************x +dialyzer_suppressions(Erules) -> + case asn1ct_func:is_used({Erules,complete,1}) of + false -> + ok; + true -> + emit([" _ = complete(Arg),",nl]) + end, + emit([" ok.",nl]). + gen_encode(Erules,Type) when is_record(Type,typedef) -> gen_encode_user(Erules,Type). diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl index fde39c674e..bdd14871d1 100644 --- a/lib/asn1/src/asn1ct_imm.erl +++ b/lib/asn1/src/asn1ct_imm.erl @@ -82,15 +82,8 @@ per_dec_enumerated(NamedList0, Aligned) -> Ub = length(NamedList0) - 1, Constraint = [{'ValueRange',{0,Ub}}], Int = per_dec_integer(Constraint, Aligned), - EnumTail = case matched_range(Int) of - {0,Ub} -> - %% The error case can never happen. - []; - _ -> - [enum_error] - end, - NamedList = per_dec_enumerated_fix_list(NamedList0, EnumTail, 0), - {map,Int,NamedList}. + NamedList = per_dec_enumerated_fix_list(NamedList0, [enum_error], 0), + {map,Int,opt_map(NamedList, Int)}. per_dec_enumerated(BaseNamedList, NamedListExt0, Aligned) -> Base = per_dec_enumerated(BaseNamedList, Aligned), @@ -124,7 +117,7 @@ per_dec_length(no, AllowZero, Aligned) -> per_dec_named_integer(Constraint, NamedList0, Aligned) -> Int = per_dec_integer(Constraint, Aligned), NamedList = [{K,V} || {V,K} <- NamedList0] ++ [integer_default], - {map,Int,NamedList}. + {map,Int,opt_map(NamedList, Int)}. per_dec_k_m_string(StringType, Constraint, Aligned) -> SzConstr = effective_constraint(bitstring, Constraint), @@ -175,6 +168,8 @@ per_enc_bit_string(Val0, NNL0, Constraint0, Aligned) -> ToBs = case ExtraArgs of [] -> {call,per_common,bs_drop_trailing_zeroes,[Val]}; + [0] -> + {call,per_common,bs_drop_trailing_zeroes,[Val]}; [Lower] -> {call,per_common,adjust_trailing_zeroes,[Val,Lower]} end, @@ -203,6 +198,7 @@ per_enc_legacy_bit_string(Val0, NNL0, Constraint0, Aligned) -> Constraint = effective_constraint(bitstring, Constraint0), ExtraArgs = case constr_min_size(Constraint) of no -> []; + 0 -> []; Lb -> [Lb] end, B ++ [{'try', @@ -265,10 +261,6 @@ per_enc_k_m_string(Val0, StringType, Constraint, Aligned) -> SzConstraint = effective_constraint(bitstring, Constraint), Unit = string_num_bits(StringType, Constraint, Aligned), Chars0 = char_tab(Constraint, StringType, Unit), - Args = case enc_char_tab(Chars0) of - notab -> [Val,Unit]; - Chars -> [Val,Unit,Chars] - end, Enc = case Unit of 16 -> {call,per_common,encode_chars_16bit,[Val],Bin}; @@ -277,7 +269,15 @@ per_enc_k_m_string(Val0, StringType, Constraint, Aligned) -> 8 -> {call,erlang,list_to_binary,[Val],Bin}; _ -> - {call,per_common,encode_chars,Args,Bin} + case enc_char_tab(Chars0) of + notab -> + {call,per_common,encode_chars,[Val,Unit],Bin}; + {tab,Tab} -> + {call,per_common,encode_chars,[Val,Unit,Tab],Bin}; + {compact_map,Map} -> + {call,per_common,encode_chars_compact_map, + [Val,Unit,Map],Bin} + end end, case Unit of 8 -> @@ -581,14 +581,42 @@ per_num_bits(N) when N =< 64 -> 6; per_num_bits(N) when N =< 128 -> 7; per_num_bits(N) when N =< 255 -> 8. +opt_map(Map, Imm) -> + case matched_range(Imm) of + unknown -> Map; + {Lb,Ub} -> opt_map_1(Map, Lb, Ub) + end. + +opt_map_1([{I,_}=Pair|T], Lb, Ub) -> + if + I =:= Lb, I =< Ub -> + [Pair|opt_map_1(T, Lb+1, Ub)]; + Lb < I, I =< Ub -> + [Pair|opt_map_1(T, Lb, Ub)]; + true -> + opt_map_1(T, Lb, Ub) + end; +opt_map_1(Map, Lb, Ub) -> + if + Lb =< Ub -> + Map; + true -> + [] + end. + matched_range({get_bits,Bits0,[U|Flags]}) when is_integer(U) -> - case lists:member(signed, Flags) of - false -> + case not lists:member(signed, Flags) andalso is_integer(Bits0) of + true -> Bits = U*Bits0, {0,(1 bsl Bits) - 1}; - true -> + false -> unknown end; +matched_range({add,Imm,Add}) -> + case matched_range(Imm) of + unknown -> unknown; + {Lb,Ub} -> {Lb+Add,Ub+Add} + end; matched_range(_Op) -> unknown. string_num_bits(StringType, Constraint, Aligned) -> @@ -1289,6 +1317,8 @@ eval_cond_1({eq,[],[]}) -> true; eval_cond_1({eq,I,N}) when is_integer(I), is_integer(N) -> I =:= N; +eval_cond_1({ge,I,N}) when is_integer(I), is_integer(N) -> + I >= N; eval_cond_1({lt,I,N}) when is_integer(I), is_integer(N) -> I < N; eval_cond_1(_) -> maybe. @@ -1303,9 +1333,15 @@ prepend_to_cond_1([Check|T], Code) -> enc_char_tab(notab) -> notab; enc_char_tab(Tab0) -> - Tab = tuple_to_list(Tab0), - First = hd(Tab), - {First-1,list_to_tuple(enc_char_tab_1(Tab, First, 0))}. + Tab1 = tuple_to_list(Tab0), + First = hd(Tab1), + Tab = enc_char_tab_1(Tab1, First, 0), + case lists:member(ill, Tab) of + false -> + {compact_map,{First,tuple_size(Tab0)}}; + true -> + {tab,{First-1,list_to_tuple(Tab)}} + end. enc_char_tab_1([H|T], H, I) -> [I|enc_char_tab_1(T, H+1, I+1)]; diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl index 4bd814769f..c4cd872368 100644 --- a/lib/asn1/src/asn1rtt_ber.erl +++ b/lib/asn1/src/asn1rtt_ber.erl @@ -26,25 +26,24 @@ skip_ExtensionAdditions/2]). -export([encode_boolean/2,decode_boolean/2, encode_integer/2,encode_integer/3, - decode_integer/2,decode_integer/3, - decode_named_integer/3,decode_named_integer/4, - encode_enumerated/2,decode_enumerated/3, + decode_integer/2, + number2name/2, encode_unnamed_bit_string/2,encode_unnamed_bit_string/3, encode_named_bit_string/3,encode_named_bit_string/4, encode_bit_string/4, decode_named_bit_string/3, - decode_compact_bit_string/3, - decode_legacy_bit_string/3, - decode_native_bit_string/3, + decode_compact_bit_string/2,compact_bit_string_size/1, + decode_native_bit_string/2, + native_to_legacy_bit_string/1, encode_null/2,decode_null/2, encode_relative_oid/2,decode_relative_oid/2, encode_object_identifier/2,decode_object_identifier/2, encode_restricted_string/2, - decode_octet_string/2,decode_octet_string/3, - decode_restricted_string/2,decode_restricted_string/3, - encode_universal_string/2,decode_universal_string/3, + decode_octet_string/2, + decode_restricted_string/2, + encode_universal_string/2,decode_universal_string/2, encode_UTF8_string/2,decode_UTF8_string/2, - encode_BMP_string/2,decode_BMP_string/3]). + encode_BMP_string/2,decode_BMP_string/2]). -export([encode_open_type/2,decode_open_type/2, decode_open_type_as_binary/2]). @@ -591,8 +590,6 @@ encode_tags(TagIn, {BytesSoFar,LenSoFar}) -> encode_open_type(Val, T) when is_list(Val) -> encode_open_type(list_to_binary(Val), T); -encode_open_type(Val, []) -> - {Val,byte_size(Val)}; encode_open_type(Val, Tag) -> encode_tags(Tag, Val, byte_size(Val)). @@ -697,41 +694,14 @@ encode_integer_neg(N, Acc) -> %%=============================================================================== %% decode integer -%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes} -%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes} %%=============================================================================== -decode_named_integer(Tlv, NamedNumberList, TagIn) -> - V = match_tags(Tlv, TagIn), - Int = decode_integer(V), - number2name(Int, NamedNumberList). - -decode_named_integer(Tlv, Range, NamedNumberList, TagIn) -> - V = match_tags(Tlv, TagIn), - Int = range_check_integer(decode_integer(V), Range), - number2name(Int, NamedNumberList). - decode_integer(Tlv, TagIn) -> - V = match_tags(Tlv, TagIn), - decode_integer(V). - -decode_integer(Tlv, Range, TagIn) -> - V = match_tags(Tlv, TagIn), - Int = decode_integer(V), - range_check_integer(Int, Range). - -decode_integer(Bin) -> + Bin = match_tags(Tlv, TagIn), Len = byte_size(Bin), <<Int:Len/signed-unit:8>> = Bin, Int. -range_check_integer(Int, {Lb,Ub}) when Lb =< Int, Int =< Ub -> - Int; -range_check_integer(Int, Range) -> - exit({error,{asn1,{integer_range,Range,Int}}}). - -number2name(Int, []) -> - Int; number2name(Int, NamedNumberList) -> case lists:keyfind(Int, 2, NamedNumberList) of {NamedVal,_} -> @@ -740,49 +710,6 @@ number2name(Int, NamedNumberList) -> Int end. - -%%============================================================================ -%% Enumerated value, ITU_T X.690 Chapter 8.4 - -%% encode enumerated value -%%============================================================================ -encode_enumerated(Val, TagIn) when is_integer(Val) -> - encode_tags(TagIn, encode_integer(Val)). - -%%============================================================================ -%% decode enumerated value -%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> Value -%%=========================================================================== -decode_enumerated(Tlv, NamedNumberList, Tags) -> - Buffer = match_tags(Tlv, Tags), - decode_enumerated_notag(Buffer, NamedNumberList, Tags). - -decode_enumerated_notag(Buffer, {NamedNumberList,ExtList}, _Tags) -> - IVal = decode_integer(Buffer), - case decode_enumerated1(IVal, NamedNumberList) of - {asn1_enum,IVal} -> - decode_enumerated1(IVal,ExtList); - EVal -> - EVal - end; -decode_enumerated_notag(Buffer, NNList, _Tags) -> - IVal = decode_integer(Buffer), - case decode_enumerated1(IVal, NNList) of - {asn1_enum,_} -> - exit({error,{asn1, {illegal_enumerated, IVal}}}); - EVal -> - EVal - end. - -decode_enumerated1(Val, NamedNumberList) -> - %% it must be a named integer - case lists:keyfind(Val, 2, NamedNumberList) of - {NamedVal, _} -> - NamedVal; - _ -> - {asn1_enum,Val} - end. - %%============================================================================ %% Bitstring value, ITU_T X.690 Chapter 8.6 %% @@ -794,45 +721,46 @@ encode_unnamed_bit_string(Bits, TagIn) -> Bin = <<Unused,Bits/bitstring,0:Unused>>, encode_tags(TagIn, Bin, byte_size(Bin)). -encode_unnamed_bit_string(C, Bits, TagIn) -> +encode_unnamed_bit_string(MaxBits, Bits, TagIn) -> NumBits = bit_size(Bits), Unused = (8 - (NumBits band 7)) band 7, Bin = <<Unused,Bits/bitstring,0:Unused>>, - case C of - {_Min,Max} -> - if - NumBits > Max -> - exit({error,{asn1, - {bitstring_length, - {{was,NumBits},{maximum,Max}}}}}); - true -> - ok - end; - Size -> - if NumBits =< Size -> - ok; - true -> - exit({error,{asn1, - {bitstring_length, - {{was,NumBits},{should_be,Size}}}}}) - end - end, - encode_tags(TagIn, Bin, byte_size(Bin)). + if + NumBits > MaxBits -> + exit({error,{asn1, + {bitstring_length, + {{was,NumBits},{maximum,MaxBits}}}}}); + true -> + encode_tags(TagIn, Bin, byte_size(Bin)) + end. encode_named_bit_string([H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> - encode_bit_string_named([], Bits, NamedBitList, TagIn); + do_encode_named_bit_string(Bits, NamedBitList, TagIn); encode_named_bit_string([{bit,_}|_]=Bits, NamedBitList, TagIn) -> - encode_bit_string_named([], Bits, NamedBitList, TagIn); + do_encode_named_bit_string(Bits, NamedBitList, TagIn); encode_named_bit_string(Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> encode_unnamed_bit_string(Bits, TagIn). encode_named_bit_string(C, [H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> - encode_bit_string_named(C, Bits, NamedBitList, TagIn); + do_encode_named_bit_string(C, Bits, NamedBitList, TagIn); encode_named_bit_string(C, [{bit,_}|_]=Bits, NamedBitList, TagIn) -> - encode_bit_string_named(C, Bits, NamedBitList, TagIn); + do_encode_named_bit_string(C, Bits, NamedBitList, TagIn); encode_named_bit_string(C, Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> encode_unnamed_bit_string(C, Bits, TagIn). +do_encode_named_bit_string([FirstVal | RestVal], NamedBitList, TagIn) -> + ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []), + Size = lists:max(ToSetPos) + 1, + BitList = make_and_set_list(Size, ToSetPos, 0), + {Len,Unused,OctetList} = encode_bitstring(BitList), + encode_tags(TagIn, [Unused|OctetList],Len+1). + +do_encode_named_bit_string(Size, [FirstVal | RestVal], NamedBitList, TagIn) -> + ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []), + BitList = make_and_set_list(Size, ToSetPos, 0), + {Len, Unused, OctetList} = encode_bitstring(BitList), + encode_tags(TagIn, [Unused|OctetList], Len+1). + %%============================================================================ %% Bitstring value, ITU_T X.690 Chapter 8.6 %% @@ -932,15 +860,14 @@ remove_unused_then_dotag(TagIn,Unused,BinBits) -> encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn) -> ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []), - Size = - case C of - [] -> - lists:max(ToSetPos)+1; - {_Min,Max} -> - Max; - TSize -> - TSize - end, + Size = case C of + [] -> + lists:max(ToSetPos) + 1; + {_Min,Max} -> + Max; + TSize -> + TSize + end, BitList = make_and_set_list(Size, ToSetPos, 0), {Len, Unused, OctetList} = encode_bitstring(BitList), encode_tags(TagIn, [Unused|OctetList],Len+1). @@ -1098,33 +1025,23 @@ unused_bitlist([Bit | Rest], Trail, Ack) -> %% decode bitstring value %%============================================================================ -decode_compact_bit_string(Buffer, Range, Tags) -> +decode_compact_bit_string(Buffer, Tags) -> case match_and_collect(Buffer, Tags) of - <<0>> -> - check_restricted_string({0,<<>>}, 0, Range); - <<Unused,Bits/binary>> -> - Val = {Unused,Bits}, - Len = bit_size(Bits) - Unused, - check_restricted_string(Val, Len, Range) + <<0>> -> {0,<<>>}; + <<Unused,Bits/binary>> -> {Unused,Bits} end. -decode_legacy_bit_string(Buffer, Range, Tags) -> - Val = case match_and_collect(Buffer, Tags) of - <<0>> -> - []; - <<Unused,Bits/binary>> -> - decode_bitstring2(byte_size(Bits), Unused, Bits) - end, - check_restricted_string(Val, length(Val), Range). +compact_bit_string_size({Unused,Bits}) -> + bit_size(Bits) - Unused. -decode_native_bit_string(Buffer, Range, Tags) -> +decode_native_bit_string(Buffer, Tags) -> case match_and_collect(Buffer, Tags) of <<0>> -> - check_restricted_string(<<>>, 0, Range); + <<>>; <<Unused,Bits/binary>> -> Size = bit_size(Bits) - Unused, <<Val:Size/bitstring,_:Unused/bitstring>> = Bits, - check_restricted_string(Val, Size, Range) + Val end. decode_named_bit_string(Buffer, NamedNumberList, Tags) -> @@ -1147,6 +1064,9 @@ decode_bitstring2(Len, Unused, [B7,B6,B5,B4,B3,B2,B1,B0| decode_bitstring2(Len - 1, Unused, Buffer)]. +native_to_legacy_bit_string(Bits) -> + [B || <<B:1>> <= Bits]. + %%---------------------------------------- %% Decode the bitlist to names %%---------------------------------------- @@ -1310,31 +1230,12 @@ decode_octet_string(Tlv, TagsIn) -> Bin = match_and_collect(Tlv, TagsIn), binary:copy(Bin). -decode_octet_string(Tlv, Range, TagsIn) -> - Bin0 = match_and_collect(Tlv, TagsIn), - Bin = binary:copy(Bin0), - check_restricted_string(Bin, byte_size(Bin), Range). - %%============================================================================ %% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings %%============================================================================ decode_restricted_string(Tlv, TagsIn) -> - Bin = match_and_collect(Tlv, TagsIn), - binary_to_list(Bin). - -decode_restricted_string(Tlv, Range, TagsIn) -> - Bin = match_and_collect(Tlv, TagsIn), - check_restricted_string(binary_to_list(Bin), byte_size(Bin), Range). - -check_restricted_string(Val, _Len, []) -> - Val; -check_restricted_string(Val, Len, {Lb,Ub}) when Lb =< Len, Len =< Ub -> - Val; -check_restricted_string(Val, Len, Len) -> - Val; -check_restricted_string(Val, _Len, Range) -> - exit({error,{asn1,{length,Range,Val}}}). + match_and_collect(Tlv, TagsIn). %%============================================================================ %% encode Universal string @@ -1360,10 +1261,9 @@ mk_uni_list([H|T],List) -> %% {String, Remain, RemovedBytes} %%=========================================================================== -decode_universal_string(Buffer, Range, Tags) -> +decode_universal_string(Buffer, Tags) -> Bin = match_and_collect(Buffer, Tags), - Val = mk_universal_string(binary_to_list(Bin)), - check_restricted_string(Val, length(Val), Range). + mk_universal_string(binary_to_list(Bin)). mk_universal_string(In) -> mk_universal_string(In, []). @@ -1423,10 +1323,9 @@ mk_BMP_list([H|T], List) -> %% (Buffer, Range, StringType, HasTag, TotalLen) -> %% {String, Remain, RemovedBytes} %%============================================================================ -decode_BMP_string(Buffer, Range, Tags) -> +decode_BMP_string(Buffer, Tags) -> Bin = match_and_collect(Buffer, Tags), - Val = mk_BMP_string(binary_to_list(Bin)), - check_restricted_string(Val, length(Val), Range). + mk_BMP_string(binary_to_list(Bin)). mk_BMP_string(In) -> mk_BMP_string(In,[]). diff --git a/lib/asn1/src/asn1rtt_check.erl b/lib/asn1/src/asn1rtt_check.erl index be4f9c8bff..0083867a10 100644 --- a/lib/asn1/src/asn1rtt_check.erl +++ b/lib/asn1/src/asn1rtt_check.erl @@ -18,43 +18,41 @@ %% -module(asn1rtt_check). --export([check_bool/2, +-export([check_fail/1, check_int/3, - check_bitstring/2,check_named_bitstring/3, + check_legacy_bitstring/2, + check_legacy_named_bitstring/3, + check_legacy_named_bitstring/4, + check_named_bitstring/3, + check_named_bitstring/4, + check_literal_sof/2, check_octetstring/2, - check_null/2, check_objectidentifier/2, check_objectdescriptor/2, check_real/2, - check_enum/3, check_restrictedstring/2]). -check_bool(_Bool, asn1_DEFAULT) -> - true; -check_bool(Bool, Bool) when is_boolean(Bool) -> - true; -check_bool(_Bool1, Bool2) -> - throw({error,Bool2}). +check_fail(_) -> + throw(false). -check_int(_, asn1_DEFAULT, _) -> - true; check_int(Value, Value, _) when is_integer(Value) -> true; -check_int(DefValue, Value, NNL) when is_atom(Value) -> +check_int(Value, DefValue, NNL) when is_atom(Value) -> case lists:keyfind(Value, 1, NNL) of {_,DefValue} -> true; _ -> - throw({error,DefValue}) + throw(false) end; -check_int(DefaultValue, _Value, _) -> - throw({error,DefaultValue}). +check_int(_, _, _) -> + throw(false). + +check_legacy_bitstring(Value, Default) -> + check_bitstring(Default, Value). %% check_bitstring(Default, UserBitstring) -> true|false %% Default = bitstring() %% UserBitstring = integeger() | list(0|1) | {Unused,binary()} | bitstring() -check_bitstring(_, asn1_DEFAULT) -> - true; check_bitstring(DefVal, {Unused,Binary}) -> %% User value in compact format. Sz = bit_size(Binary) - Unused, @@ -62,7 +60,7 @@ check_bitstring(DefVal, {Unused,Binary}) -> check_bitstring(DefVal, Val); check_bitstring(DefVal, Val) when is_bitstring(Val) -> case Val =:= DefVal of - false -> throw(error); + false -> throw(false); true -> true end; check_bitstring(Def, Val) when is_list(Val) -> @@ -75,178 +73,95 @@ check_bitstring_list(<<H:1,T1/bitstring>>, [H|T2]) -> check_bitstring_list(<<>>, []) -> true; check_bitstring_list(_, _) -> - throw(error). + throw(false). check_bitstring_integer(<<H:1,T1/bitstring>>, Int) when H =:= Int band 1 -> check_bitstring_integer(T1, Int bsr 1); check_bitstring_integer(<<>>, 0) -> true; check_bitstring_integer(_, _) -> - throw(error). - -check_named_bitstring(_, asn1_DEFAULT, _) -> - true; -check_named_bitstring(V, V, _) -> - true; -%% Default value and user value as lists of ones and zeros -check_named_bitstring(L1=[H1|_T1], L2=[H2|_T2], NBL=[_H|_T]) when is_integer(H1), is_integer(H2) -> - L2new = remove_trailing_zeros(L2), - check_named_bitstring(L1, L2new, NBL); -%% Default value as a list of 1 and 0 and user value as a list of atoms -check_named_bitstring(L1=[H1|_T1], L2=[H2|_T2], NBL) when is_integer(H1), is_atom(H2) -> - L3 = bit_list_to_nbl(L1, NBL, 0, []), - check_named_bitstring(L3, L2, NBL); -%% Both default value and user value as a list of atoms -check_named_bitstring(L1=[H1|T1], L2=[H2|_T2], _) - when is_atom(H1), is_atom(H2), length(L1) =:= length(L2) -> - case lists:member(H1, L2) of - true -> - check_bitstring1(T1, L2); - false -> throw({error,L2}) - end; -%% Default value as a list of atoms and user value as a list of 1 and 0 -check_named_bitstring(L1=[H1|_T1], L2=[H2|_T2], NBL) when is_atom(H1), is_integer(H2) -> - L3 = bit_list_to_nbl(L2, NBL, 0, []), - check_named_bitstring(L1, L3, NBL); -%% User value in compact format -check_named_bitstring(DefVal,CBS={_,_}, NBL) -> - NewVal = cbs_to_bit_list(CBS), - check_named_bitstring(DefVal, NewVal, NBL); -%% User value as a binary -check_named_bitstring(DefVal, CBS, NBL) when is_binary(CBS) -> - NewVal = cbs_to_bit_list({0,CBS}), - check_named_bitstring(DefVal, NewVal, NBL); -%% User value as a bitstring -check_named_bitstring(DefVal, CBS, NBL) when is_bitstring(CBS) -> - BitSize = bit_size(CBS), - Unused = 8 - (BitSize band 7), - NewVal = cbs_to_bit_list({Unused,<<CBS:BitSize/bits,0:Unused>>}), - check_named_bitstring(DefVal, NewVal, NBL); -check_named_bitstring(DV, V, _) -> - throw({error,DV,V}). - -int_to_bit_list(0, Acc, 0) -> - Acc; -int_to_bit_list(Int, Acc, Len) when Len > 0 -> - int_to_bit_list(Int bsr 1, [Int band 1|Acc], Len - 1). - -bit_list_to_nbl([0|T], NBL, Pos, Acc) -> - bit_list_to_nbl(T, NBL, Pos+1, Acc); -bit_list_to_nbl([1|T], NBL, Pos, Acc) -> - case lists:keyfind(Pos, 2, NBL) of - {N,_} -> - bit_list_to_nbl(T, NBL, Pos+1, [N|Acc]); + throw(false). + +check_legacy_named_bitstring([Int|_]=Val, Bs, BsSize) when is_integer(Int) -> + check_named_bitstring(<< <<B:1>> || B <- Val >>, Bs, BsSize); +check_legacy_named_bitstring({Unused,Val0}, Bs, BsSize) -> + Sz = bit_size(Val0) - Unused, + <<Val:Sz/bits,_/bits>> = Val0, + check_named_bitstring(Val, Bs, BsSize); +check_legacy_named_bitstring(Val, Bs, BsSize) when is_integer(Val) -> + L = legacy_int_to_bitlist(Val), + check_named_bitstring(<< <<B:1>> || B <- L >>, Bs, BsSize); +check_legacy_named_bitstring(Val, Bs, BsSize) -> + check_named_bitstring(Val, Bs, BsSize). + +check_legacy_named_bitstring([Int|_]=Val, Names, Bs, BsSize) when is_integer(Int) -> + check_named_bitstring(<< <<B:1>> || B <- Val >>, Names, Bs, BsSize); +check_legacy_named_bitstring({Unused,Val0}, Names, Bs, BsSize) -> + Sz = bit_size(Val0) - Unused, + <<Val:Sz/bits,_/bits>> = Val0, + check_named_bitstring(Val, Names, Bs, BsSize); +check_legacy_named_bitstring(Val, Names, Bs, BsSize) when is_integer(Val) -> + L = legacy_int_to_bitlist(Val), + check_named_bitstring(<< <<B:1>> || B <- L >>, Names, Bs, BsSize); +check_legacy_named_bitstring(Val, Names, Bs, BsSize) -> + check_named_bitstring(Val, Names, Bs, BsSize). + +legacy_int_to_bitlist(0) -> + []; +legacy_int_to_bitlist(Int) -> + [Int band 1|legacy_int_to_bitlist(Int bsr 1)]. + +check_named_bitstring(Bs, Bs, _) -> + true; +check_named_bitstring(Val, Bs, BsSize) -> + Rest = bit_size(Val) - BsSize, + case Val of + <<Bs:BsSize/bits,0:Rest>> -> + true; _ -> - throw({error,{no,named,element,at,pos,Pos}}) - end; -bit_list_to_nbl([], _, _, Acc) -> - Acc. - -remove_trailing_zeros(L2) -> - remove_trailing_zeros1(lists:reverse(L2)). -remove_trailing_zeros1(L) -> - lists:reverse(lists:dropwhile(fun(0)->true; - (_) ->false - end, - L)). - -check_bitstring1([H|T], NBL) -> - case lists:member(H, NBL) of - true -> check_bitstring1(T, NBL); - V -> throw({error,V}) - end; -check_bitstring1([], _) -> - true. - -cbs_to_bit_list({Unused, <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>>}) when byte_size(Rest) >= 1 -> - [B7,B6,B5,B4,B3,B2,B1,B0|cbs_to_bit_list({Unused,Rest})]; -cbs_to_bit_list({0,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1>>}) -> - [B7,B6,B5,B4,B3,B2,B1,B0]; -cbs_to_bit_list({Unused,Bin}) when byte_size(Bin) =:= 1 -> - Used = 8-Unused, - <<Int:Used,_:Unused>> = Bin, - int_to_bit_list(Int, [], Used). - + throw(false) + end. -check_octetstring(_, asn1_DEFAULT) -> - true; -check_octetstring(L, L) -> - true; -check_octetstring(L, Int) when is_list(L), is_integer(Int) -> - case integer_to_octetlist(Int) of - L -> true; - V -> throw({error,V}) +check_named_bitstring([_|_]=Val, Names, _, _) -> + case lists:sort(Val) of + Names -> true; + _ -> throw(false) end; -check_octetstring(_, V) -> - throw({error,V}). - -integer_to_octetlist(Int) -> - integer_to_octetlist(Int, []). -integer_to_octetlist(0, Acc) -> - Acc; -integer_to_octetlist(Int, Acc) -> - integer_to_octetlist(Int bsr 8, [(Int band 255)|Acc]). - -check_null(_, asn1_DEFAULT) -> +check_named_bitstring(Bs, _, Bs, _) -> true; -check_null('NULL', 'NULL') -> - true; -check_null(_, V) -> - throw({error,V}). +check_named_bitstring(Val, _, Bs, BsSize) -> + Rest = bit_size(Val) - BsSize, + case Val of + <<Bs:BsSize/bits,0:Rest>> -> + true; + _ -> + throw(false) + end. -check_objectidentifier(_, asn1_DEFAULT) -> - true; -check_objectidentifier(OI, OI) -> +check_octetstring(V, V) -> true; -check_objectidentifier(DOI, OI) when is_tuple(DOI), is_tuple(OI) -> - check_objectidentifier1(tuple_to_list(DOI), tuple_to_list(OI)); -check_objectidentifier(_, OI) -> - throw({error,OI}). - -check_objectidentifier1([V|Rest1], [V|Rest2]) -> - check_objectidentifier1(Rest1, Rest2, V); -check_objectidentifier1([V1|Rest1], [V2|Rest2]) -> - case reserved_objectid(V2, []) of - V1 -> - check_objectidentifier1(Rest1, Rest2, [V1]); - V -> - throw({error,V}) - end. -check_objectidentifier1([V|Rest1], [V|Rest2], Above) -> - check_objectidentifier1(Rest1, Rest2, [V|Above]); -check_objectidentifier1([V1|Rest1], [V2|Rest2], Above) -> - case reserved_objectid(V2, Above) of - V1 -> - check_objectidentifier1(Rest1, Rest2, [V1|Above]); - V -> - throw({error,V}) +check_octetstring(V, Def) when is_list(V) -> + case list_to_binary(V) of + Def -> true; + _ -> throw(false) + end; +check_octetstring(_, _) -> + throw(false). + +check_objectidentifier(Value, {Prefix,Tail}) when is_tuple(Value) -> + check_oid(tuple_to_list(Value), Prefix, Tail); +check_objectidentifier(_, _) -> + throw(false). + +check_oid([H|T], [K|Ks], Tail) -> + case lists:member(H, K) of + false -> throw(false); + true -> check_oid(T, Ks, Tail) end; -check_objectidentifier1([], [], _) -> +check_oid(Tail, [], Tail) -> true; -check_objectidentifier1(_, V, _) -> - throw({error,object,identifier,V}). - -%% ITU-T Rec. X.680 Annex B - D -reserved_objectid('itu-t', []) -> 0; -reserved_objectid('ccitt', []) -> 0; -%% arcs below "itu-t" -reserved_objectid('recommendation', [0]) -> 0; -reserved_objectid('question', [0]) -> 1; -reserved_objectid('administration', [0]) -> 2; -reserved_objectid('network-operator', [0]) -> 3; -reserved_objectid('identified-organization', [0]) -> 4; - -reserved_objectid(iso, []) -> 1; -%% arcs below "iso", note that number 1 is not used -reserved_objectid('standard', [1]) -> 0; -reserved_objectid('member-body', [1]) -> 2; -reserved_objectid('identified-organization', [1]) -> 3; - -reserved_objectid('joint-iso-itu-t', []) -> 2; -reserved_objectid('joint-iso-ccitt', []) -> 2; - -reserved_objectid(_, _) -> false. - +check_oid(_, _, _) -> + throw(false). check_objectdescriptor(_, asn1_DEFAULT) -> true; @@ -262,21 +177,6 @@ check_real(R, R) -> check_real(_, _) -> throw({error,{not_implemented_yet,check_real}}). -check_enum(_, asn1_DEFAULT, _) -> - true; -check_enum(Val, Val, _) -> - true; -check_enum(Int, Atom, Enumerations) when is_integer(Int), is_atom(Atom) -> - case lists:keyfind(Atom, 1, Enumerations) of - {_,Int} -> true; - _ -> throw({error,{enumerated,Int,Atom}}) - end; -check_enum(DefVal, Val, _) -> - throw({error,{enumerated,DefVal,Val}}). - - -check_restrictedstring(_, asn1_DEFAULT) -> - true; check_restrictedstring(Val, Val) -> true; check_restrictedstring([V|Rest1], [V|Rest2]) -> @@ -295,7 +195,15 @@ check_restrictedstring({V1,V2,V3,V4}, [V1,V2,V3,V4]) -> check_restrictedstring([V1,V2,V3,V4], {V1,V2,V3,V4}) -> true; %% character string list -check_restrictedstring(V1, V2) when is_list(V1), is_tuple(V2) -> - check_restrictedstring(V1, tuple_to_list(V2)); -check_restrictedstring(V1, V2) -> - throw({error,{restricted,string,V1,V2}}). +check_restrictedstring(V1, V2) when is_tuple(V1) -> + check_restrictedstring(tuple_to_list(V1), V2); +check_restrictedstring(_, _) -> + throw(false). + +check_literal_sof(Value, Default) -> + case lists:sort(Value) of + Default -> + true; + _ -> + throw(false) + end. diff --git a/lib/asn1/src/asn1rtt_per_common.erl b/lib/asn1/src/asn1rtt_per_common.erl index 71fec411a0..0290c75a28 100644 --- a/lib/asn1/src/asn1rtt_per_common.erl +++ b/lib/asn1/src/asn1rtt_per_common.erl @@ -30,6 +30,7 @@ decode_big_chars/2, decode_oid/1,decode_relative_oid/1, encode_chars/2,encode_chars/3, + encode_chars_compact_map/3, encode_chars_16bit/1,encode_big_chars/1, encode_fragmented/2, encode_oid/1,encode_relative_oid/1, @@ -108,6 +109,9 @@ encode_chars(Val, NumBits) -> encode_chars(Val, NumBits, {Lb,Tab}) -> << <<(enc_char(C, Lb, Tab)):NumBits>> || C <- Val >>. +encode_chars_compact_map(Val, NumBits, {Lb,Limit}) -> + << <<(enc_char_cm(C, Lb, Limit)):NumBits>> || C <- Val >>. + encode_chars_16bit(Val) -> L = [case C of {0,0,A,B} -> [A,B]; @@ -383,6 +387,15 @@ enc_char(C0, Lb, Tab) -> illegal_char_error() end. +enc_char_cm(C0, Lb, Limit) -> + C = C0 - Lb, + if + 0 =< C, C < Limit -> + C; + true -> + illegal_char_error() + end. + illegal_char_error() -> error({error,{asn1,"value forbidden by FROM constraint"}}). diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl index 782217ed2d..11d1b82fb4 100644 --- a/lib/asn1/test/asn1_SUITE.erl +++ b/lib/asn1/test/asn1_SUITE.erl @@ -50,13 +50,14 @@ all() -> {group, performance}]. groups() -> - [{compile, parallel([]), + Parallel = asn1_test_lib:parallel(), + [{compile, Parallel, [c_syntax, c_string, c_implicit_before_choice, constraint_equivalence]}, - {ber, parallel([]), + {ber, Parallel, [ber_choiceinseq, % Uses 'SOpttest' ber_optional]}, @@ -65,7 +66,7 @@ groups() -> {appup_test, [], [{asn1_appup_test, all}]}, - {parallel, parallel([]), + {parallel, Parallel, [cover, xref, {group, ber}, @@ -173,13 +174,6 @@ groups() -> testTimer_per, testTimer_uper]}]. -parallel(Options) -> - case erlang:system_info(smp_support) andalso - erlang:system_info(schedulers) > 1 of - true -> [parallel|Options]; - false -> Options - end. - %%------------------------------------------------------------------------------ %% Init/end %%------------------------------------------------------------------------------ @@ -428,14 +422,12 @@ testMultipleLevels(Config, Rule, Opts) -> asn1_test_lib:compile("MultipleLevels", Config, [Rule|Opts]), testMultipleLevels:main(Rule). -testDef(Config) -> test(Config, fun testDef/3). -testDef(Config, Rule, Opts) -> - asn1_test_lib:compile("Def", Config, [Rule|Opts]), - testDef:main(Rule). - testDEFAULT(Config) -> test(Config, fun testDEFAULT/3, [ber,{ber,[der]},per,uper]). testDEFAULT(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["Def","Default"], Config, [Rule|Opts]), + testDef:main(Rule), + testSeqSetDefaultVal:main(Rule, Opts), asn1_test_lib:compile_all(["Def","Default"], Config, [legacy_erlang_types,Rule|Opts]), testDef:main(Rule), diff --git a/lib/asn1/test/asn1_SUITE_data/Constraints.py b/lib/asn1/test/asn1_SUITE_data/Constraints.py index c3b3aebd6d..3495cd841b 100644 --- a/lib/asn1/test/asn1_SUITE_data/Constraints.py +++ b/lib/asn1/test/asn1_SUITE_data/Constraints.py @@ -16,6 +16,7 @@ SemiConstrained ::= INTEGER (100..MAX) NegSemiConstrained ::= INTEGER (-128..MAX) SemiConstrainedExt ::= INTEGER (42..MAX, ...) NegSemiConstrainedExt ::= INTEGER (-128..MAX, ...) +SemiNamed ::= INTEGER {a(100), b(200)} (100..MAX) -- Extensions -- LongLongExt ::= INTEGER (0..18446744073709551615, ..., -5000..-1) Range256to65536Ext ::= INTEGER (256..65536, ..., 1000000..9000000) @@ -65,10 +66,12 @@ Wednesday ::= Day(wednesday) Thing ::= INTEGER {fred (0),fred2 (1),fred3 (2)} - - AnotherThing ::= Thing (fred | fred2) +OneMoreThing ::= INTEGER {wilma(0), fred(1), betty(3), barney(2)} +OneMoreThing-1 ::= OneMoreThing (wilma | fred) +OneMoreThing-2 ::= OneMoreThing (fred | barney) + I ::= INTEGER (0|15..269) -- OTP-5457 X1 ::= INTEGER (1..4 | 8 | 10 | 20) -- OTP-9946 diff --git a/lib/asn1/test/asn1_SUITE_data/Default.asn b/lib/asn1/test/asn1_SUITE_data/Default.asn index 168ce50bb2..b91660381a 100644 --- a/lib/asn1/test/asn1_SUITE_data/Default.asn +++ b/lib/asn1/test/asn1_SUITE_data/Default.asn @@ -25,6 +25,10 @@ SeqBS ::= SEQUENCE { e BIT STRING DEFAULT '01011010'B } +SeqBS2 ::= SEQUENCE { + bs BIT STRING {a(0), z(25)} DEFAULT '101'B +} + SetBS ::= SET { a BIT STRING DEFAULT '1010110'B, b BIT STRING DEFAULT 'A8A'H, @@ -156,4 +160,23 @@ four INTEGER ::= 4 cr IA5String ::= {0,13} +SeqNamedInts ::= SEQUENCE { + i1 INTEGER {first(0), last(31)} DEFAULT 15, + i2 INTEGER {first(0), last(31)} DEFAULT 31 +} + +S5 ::= SEQUENCE { + s3 S3 DEFAULT {}, + so SEQUENCE OF OBJECT IDENTIFIER DEFAULT { + {itu-t question 999}, + {itu-t question 555} + }, + soe SEQUENCE OF OBJECT IDENTIFIER DEFAULT { } +} + +SOI ::= SEQUENCE { + soi SEQUENCE OF OBJECT IDENTIFIER + DEFAULT { {iso member-body f(250) 9 55}, {iso member-body f(250) 3 4} } +} + END diff --git a/lib/asn1/test/asn1_SUITE_data/Set.py b/lib/asn1/test/asn1_SUITE_data/Set.py index 4062f6b804..3928004e6b 100644 --- a/lib/asn1/test/asn1_SUITE_data/Set.py +++ b/lib/asn1/test/asn1_SUITE_data/Set.py @@ -80,8 +80,8 @@ SetOpt3 ::= SET SetIn ::= SET { - boolIn BOOLEAN, - intIn INTEGER + boolIn BOOLEAN OPTIONAL, + intIn INTEGER OPTIONAL } diff --git a/lib/asn1/test/asn1_app_test.erl b/lib/asn1/test/asn1_app_test.erl index 1225e36778..d800846b3f 100644 --- a/lib/asn1/test/asn1_app_test.erl +++ b/lib/asn1/test/asn1_app_test.erl @@ -134,13 +134,13 @@ get_ebin_mods(App) -> check_asn1ct_modules(Extra) -> ASN1CTMods = [asn1ct,asn1ct_check,asn1_db,asn1ct_pretty_format, - asn1ct_gen,asn1ct_gen_per,asn1ct_gen_per_rt2ct, + asn1ct_gen,asn1ct_gen_check,asn1ct_gen_per, asn1ct_name,asn1ct_constructed_per,asn1ct_constructed_ber, asn1ct_gen_ber,asn1ct_constructed_ber_bin_v2, asn1ct_gen_ber_bin_v2,asn1ct_value, asn1ct_tok,asn1ct_parser2,asn1ct_table, asn1ct_imm,asn1ct_func,asn1ct_rtt, - asn1ct_eval_ext,asn1ct_eval_per,asn1ct_eval_uper], + asn1ct_eval_ext], case Extra -- ASN1CTMods of [] -> ok; diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl index 417380159e..06e9b2c093 100644 --- a/lib/asn1/test/asn1_test_lib.erl +++ b/lib/asn1/test/asn1_test_lib.erl @@ -21,19 +21,72 @@ -export([compile/3,compile_all/3,compile_erlang/3, hex_to_bin/1, + parallel/0, roundtrip/3,roundtrip/4,roundtrip_enc/3,roundtrip_enc/4]). -include_lib("test_server/include/test_server.hrl"). +run_dialyzer() -> + false. + compile(File, Config, Options) -> compile_all([File], Config, Options). compile_all(Files, Config, Options) -> DataDir = ?config(data_dir, Config), CaseDir = ?config(case_dir, Config), - [compile_file(filename:join(DataDir, F), [{outdir, CaseDir}|Options]) + [compile_file(filename:join(DataDir, F), [{outdir, CaseDir}, + debug_info|Options]) || F <- Files], + dialyze(Files, Options), ok. +parallel() -> + case erlang:system_info(schedulers) > 1 andalso not run_dialyzer() of + true -> [parallel]; + false -> [] + end. + +dialyze(Files, Options) -> + case not run_dialyzer() orelse lists:member(abs, Options) of + true -> ok; + false -> dialyze(Files) + end. + +dialyze(Files) -> + Beams0 = [code:which(module(F)) || F <- Files], + Beams = [code:which(asn1rt_nif)|Beams0], + case dialyzer:run([{files,Beams}, + {warnings,[no_improper_lists]}, + {get_warnings,true}]) of + [] -> + ok; + [_|_]=Ws -> + io:put_chars([[B,$\n] || B <- Beams]), + io:put_chars([dialyzer:format_warning(W) || W <- Ws]), + error(dialyzer_warnings) + end. + +module(F0) -> + F1 = filename:basename(F0), + F2 = case filename:extension(F1) of + ".asn" -> + filename:rootname(F1); + ".asn1" -> + filename:rootname(F1); + ".py" -> + filename:rootname(F1); + "" -> + F1 + end, + F = case filename:extension(F2) of + ".set" -> + filename:rootname(F2); + "" -> + F2 + end, + list_to_atom(F). +%% filename:join(CaseDir, F ++ ".beam"). + compile_file(File, Options) -> try ok = asn1ct:compile(File, [warnings_as_errors|Options]) diff --git a/lib/asn1/test/testNBAPsystem.erl b/lib/asn1/test/testNBAPsystem.erl index 57cb483374..e37e22163a 100644 --- a/lib/asn1/test/testNBAPsystem.erl +++ b/lib/asn1/test/testNBAPsystem.erl @@ -79,13 +79,14 @@ powerRaiseLimit, dLPowerAveragingWindowSize, 'iE-Extensions' = asn1_NOVALUE}). compile(Config, Options) -> - [asn1_test_lib:compile(filename:join([nbapsystem, M]), Config, Options) - || M <- ["NBAP-CommonDataTypes.asn", - "NBAP-IEs.asn", - "NBAP-PDU-Contents.asn", - "NBAP-PDU-Discriptions.asn", - "NBAP-Constants.asn", - "NBAP-Containers.asn"]], + Fs = [filename:join("nbapsystem", M) || + M <- ["NBAP-CommonDataTypes.asn", + "NBAP-IEs.asn", + "NBAP-PDU-Contents.asn", + "NBAP-PDU-Discriptions.asn", + "NBAP-Constants.asn", + "NBAP-Containers.asn"]], + asn1_test_lib:compile_all(Fs, Config, Options), ok. diff --git a/lib/asn1/test/testSeqSetDefaultVal.erl b/lib/asn1/test/testSeqSetDefaultVal.erl index 79992a0a94..c3d9ce33b7 100644 --- a/lib/asn1/test/testSeqSetDefaultVal.erl +++ b/lib/asn1/test/testSeqSetDefaultVal.erl @@ -36,6 +36,7 @@ c = asn1_DEFAULT, d = asn1_DEFAULT, e = asn1_DEFAULT}). +-record('SeqBS2',{bs = asn1_DEFAULT}). -record('SetBS',{a = asn1_DEFAULT, b = asn1_DEFAULT, c = asn1_DEFAULT, @@ -93,6 +94,13 @@ b = asn1_DEFAULT}). -record('S4_b',{ba = asn1_DEFAULT, bb = asn1_DEFAULT}). +-record('SeqNamedInts', + {i1 = asn1_DEFAULT, + i2 = asn1_DEFAULT}). +-record('S5',{s3 = asn1_DEFAULT, + so = asn1_DEFAULT, + soe = asn1_DEFAULT}). +-record('SOI', {soi = asn1_DEFAULT}). main(ber, []) -> %% Nothing to test because plain BER will only use @@ -105,7 +113,11 @@ main(Rule, Opts) -> case {Rule,Opts} of {ber,[der]} -> - der(); + der(), + case 'Default':legacy_erlang_types() of + false -> der_new_types(); + true -> der_legacy() + end; {_,_} -> ok end, @@ -118,45 +130,45 @@ main(Rule, Opts) -> {#'SeqBS'{}, [{#'SeqBS'.a, - [asn1_DEFAULT, - 2#0110101, + [asn1_DEFAULT, %Always. + <<1:1,0:1,1:1,0:1,1:1,1:1,0:1>>], + [2#0110101, %Legacy only. [1,0,1,0,1,1,0], - {1,<<16#AC>>}, - <<1:1,0:1,1:1,0:1,1:1,1:1,0:1>>]}, + {1,<<16#AC>>}]}, {#'SeqBS'.b, [asn1_DEFAULT, - 2#10100010101, + <<16#A8:8,16#A:4>>], + [2#10100010101, [1,0,1,0,1,0,0,0,1,0,1,0], - {4,<<16#A8,16#A0>>}, - <<16#A8:8,16#A:4>>]}, + {4,<<16#A8,16#A0>>}]}, {#'SeqBS'.c, [asn1_DEFAULT, [second], - [0,1], - {6,<<0:1,1:1,0:6>>}, - <<1:2>>]}, + <<1:2>>], + [[0,1], + {6,<<0:1,1:1,0:6>>}]}, {#'SeqBS'.c, %Zeroes on the right [asn1_DEFAULT, [second], - [0,1,0,0,0], - {4,<<0:1,1:1,0:6>>}, - <<1:2,0:17>>]}, + <<1:2,0:17>>], + [[0,1,0,0,0], + {4,<<0:1,1:1,0:6>>}]}, {#'SeqBS'.d, [asn1_DEFAULT, - 2#1001, + <<2#1001:4>>], + [2#1001, [1,0,0,1], - {4,<<2#1001:4,0:4>>}, - <<2#1001:4>>]}, + {4,<<2#1001:4,0:4>>}]}, {#'SeqBS'.e, [asn1_DEFAULT, - [0,1,0,1,1,0,1,0], - {0,<<2#01011010:8>>}, - <<2#01011010:8>>]}, + <<2#01011010:8>>], + [[0,1,0,1,1,0,1,0], + {0,<<2#01011010:8>>}]}, %% Not EQUAL to DEFAULT. {#'SeqBS'.b, + [<<6:3>>], [[1,1,0], %Not equal to DEFAULT - {5,<<6:3,0:5>>}, - <<6:3>>]} + {5,<<6:3,0:5>>}]} ]}, {#'SeqOS'{}, @@ -170,15 +182,14 @@ main(Rule, Opts) -> {1,2,14,15}]}, {#'SeqOI'.b, [asn1_DEFAULT, -%% {iso,'member-body',250,3,4}, + %% {iso,'member-body',250,3,4}, {1,2,250,3,4}]}, {#'SeqOI'.c, [asn1_DEFAULT, -%% {iso,standard,8571,2,250,4}, + %% {iso,standard,8571,2,250,4}, {1,0,8571,2,250,4}]}]} ], - io:format("~p\n", [Ts]), - R0 = [[consistency(Rec, Pos, Vs) || {Pos,Vs} <- Fs] || {Rec,Fs} <- Ts], + R0 = [[consistency(Rec, PosVs) || PosVs <- Fs] || {Rec,Fs} <- Ts], case lists:flatten(R0) of [] -> ok; @@ -187,8 +198,20 @@ main(Rule, Opts) -> ?t:fail() end. -consistency(Rec0, Pos, [V|Vs]) -> +legacy_filter({_,_}=Keep) -> + Keep; +legacy_filter({Rec,Standard,Legacy}) -> + case 'Default':legacy_erlang_types() of + false -> + {Rec,Standard}; + true -> + {Rec,Standard++Legacy} + end. + +consistency(Rec0, PosVs) -> + {Pos,[V|Vs]=AllVs} = legacy_filter(PosVs), T = element(1, Rec0), + io:format("~p: ~p\n", [T,AllVs]), Rec = setelement(Pos, Rec0, V), {ok,Enc} = 'Default':encode(T, Rec), {ok,_SmokeTest} = 'Default':decode(T, Enc), @@ -206,7 +229,7 @@ consistency_1([V|Vs], Rec0, Pos, Enc) -> consistency_1([], _, _, _) -> []. der() -> - io:put_chars("Peforming DER-specific tests..."), + io:put_chars("Performing DER-specific tests..."), roundtrip(<<48,0>>, 'SeqInts', #'SeqInts'{a=asn1_DEFAULT,b=asn1_DEFAULT, @@ -227,98 +250,6 @@ der() -> #'SetInts'{a=1,b=-1,c=three,d=1}, #'SetInts'{a=1,b=-1,c=3,d=1}), - - roundtrip(<<48,0>>, - 'SeqBS', - #'SeqBS'{a=2#0110101, - b=2#010100010101, - c=[second], - d=[1,0,0,1]}, - #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, - c=[second], d = <<2#1001:4>>, - e = <<2#01011010:8>>}), - roundtrip(<<48,0>>, - 'SeqBS', - #'SeqBS'{a=[1,0,1,0,1,1,0], - b=[1,0,1,0,1,0,0,0,1,0,1,0], - c={5,<<64>>}, - d=2#1001}, - #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, - c=[second], d = <<2#1001:4>>, - e = <<2#01011010:8>>}), - roundtrip(<<48,3,131,1,0>>, - 'SeqBS', - #'SeqBS'{a=[1,0,1,0,1,1,0], - b=[1,0,1,0,1,0,0,0,1,0,1,0], - c={5,<<64>>}, - d=0}, - #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, - c=[second], d = <<>>, - e = <<2#01011010:8>>}), - roundtrip(<<48,3,131,1,0>>, - 'SeqBS', - #'SeqBS'{a = <<1:1,0:1,1:1,0:1,1:1,1:1,0:1>>, - b = <<1:1,0:1,1:1,0:1,1:1,0:1,0:1,0:1,1:1,0:1,1:1,0:1>>, - c = <<2:3>>, - d=0, - e = <<16#5A:8>>}, - #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, - c=[second], d = <<>>, - e = <<2#01011010:8>>}), - - %% None of the default values are used. - roundtrip(<<48,19,128,2,7,128,129,2,5,64,130,2,5,32,131,1,0,132,2,5,224>>, - 'SeqBS', - #'SeqBS'{a = <<1:1>>, - b = {5,<<64>>}, - c = [third], - d = 0, - e = <<7:3>>}, - #'SeqBS'{a = <<1:1>>, - b = <<2:3>>, - c = [third], - d = <<>>, - e = <<7:3>>}), - - roundtrip(<<49,0>>, - 'SetBS', - #'SetBS'{a=2#0110101, - b=2#010100010101, - c=[second], - d=[1,0,0,1]}, - #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, - c=[second], d = <<2#1001:4>>}), - roundtrip(<<49,0>>, - 'SetBS', - #'SetBS'{a=[1,0,1,0,1,1,0], - b=[1,0,1,0,1,0,0,0,1,0,1,0], - c={5,<<64>>}, - d=9}, - #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, - c=[second], d = <<2#1001:4>>}), - roundtrip(<<49,3,131,1,0>>, - 'SetBS', - #'SetBS'{a=[1,0,1,0,1,1,0], - b=[1,0,1,0,1,0,0,0,1,0,1,0], - c={5,<<64>>}, - d=0}, - #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, - c=[second], d = <<>>}), - roundtrip(<<49,3,131,1,0>>, - 'SetBS', - #'SetBS'{a = <<1:1,0:1,1:1,0:1,1:1,1:1,0:1>>, - b = <<1:1,0:1,1:1,0:1,1:1,0:1,0:1,0:1,1:1,0:1,1:1,0:1>>, - c = <<2:3>>, - d=0}, - #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, - c=[second], d = <<>>}), - - roundtrip(<<48,0>>, 'SeqOS', - #'SeqOS'{a = <<172>>,b = <<16#A8,16#A0>>,c='NULL'}), - - roundtrip(<<49,0>>, 'SetOS', - #'SetOS'{a = <<172>>,b = <<16#A8,16#A0>>,c='NULL'}), - roundtrip(<<48,0>>, 'SeqOI', #'SeqOI'{a={1,2,14,15}, @@ -443,6 +374,184 @@ der() -> #'S4'{a=#'S2'{a=1,b=asn1_NOVALUE},b=#'S4_b'{ba=true,bb=0}}, #'S4'{a=#'S2'{a=1,b=asn1_NOVALUE},b=#'S4_b'{ba=true,bb=0}}), + roundtrip(<<48,0>>, + 'SeqBS', + #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<2#1001:4>>, + e = <<2#01011010:8>>}), + roundtrip(<<49,0>>, + 'SetBS', + #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<2#1001:4>>}), + + %% None of the default values are used. + roundtrip(<<48,19,128,2,7,128,129,2,5,64,130,2,5,32,131,1,0,132,2,5,224>>, + 'SeqBS', + #'SeqBS'{a = <<1:1>>, + b = <<2:3>>, + c = [third], + d = <<>>, + e = <<7:3>>}), + roundtrip(<<49,3,131,1,0>>, + 'SetBS', + #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<>>}), + + %% SeqNamedInts + roundtrip(<<48,0>>, + 'SeqNamedInts', + #'SeqNamedInts'{i1=15,i2=31}), + roundtrip(<<48,0>>, + 'SeqNamedInts', + #'SeqNamedInts'{}, + #'SeqNamedInts'{i1=15,i2=31}), + roundtrip(<<48,0>>, + 'SeqNamedInts', + #'SeqNamedInts'{i2=last}, + #'SeqNamedInts'{i1=15,i2=31}), + roundtrip(<<48,3,128,1,0>>, + 'SeqNamedInts', + #'SeqNamedInts'{i1=first,i2=31}, + #'SeqNamedInts'{i1=first,i2=31}), + + %% S5 + roundtrip(<<48,0>>, + 'S5', + #'S5'{s3=#'S3'{a=[11,12,13], + b=[{a,11},{b,true},{c,13}], + c=[1,2,3,4], + d=[#'S2'{a=20,b=true},#'S2'{a=30,b=false}]}, + so=[{0,1,999},{0,1,555}], + soe=[]}), + roundtrip(<<48,0>>, + 'S5', + #'S5'{}, + #'S5'{s3=#'S3'{a=[11,12,13], + b=[{a,11},{b,true},{c,13}], + c=[1,2,3,4], + d=[#'S2'{a=20,b=true},#'S2'{a=30,b=false}]}, + so=[{0,1,999},{0,1,555}], + soe=[]}), + + %% SOI + roundtrip(<<48,0>>, + 'SOI', + #'SOI'{}, + #'SOI'{soi=[{1,2,250,9,55},{1,2,250,3,4}]}), + + %% SeqBS2 + roundtrip(<<48,0>>, + 'SeqBS2', + #'SeqBS2'{bs= <<16#5:3>>}), + roundtrip(<<48,0>>, + 'SeqBS2', + #'SeqBS2'{bs= <<16#5:3,0:4>>}, + #'SeqBS2'{bs= <<16#5:3>>}), + + ok. + +der_new_types() -> + io:put_chars("Performing DER-specific tests with new types..."), + + roundtrip(<<48,0>>, 'SeqOS', + #'SeqOS'{a = <<172>>,b = <<16#A8,16#A0>>,c='NULL'}), + + roundtrip(<<49,0>>, 'SetOS', + #'SetOS'{a = <<172>>,b = <<16#A8,16#A0>>,c='NULL'}), + ok. + +der_legacy() -> + io:put_chars("Performing DER-specific tests with legacy types..."), + + roundtrip(<<48,0>>, 'SeqOS', + #'SeqOS'{a=[172],b=[16#A8,16#A0],c='NULL'}), + roundtrip(<<49,0>>, 'SetOS', + #'SetOS'{a=[172],b=[16#A8,16#A0],c='NULL'}), + + roundtrip(<<48,0>>, + 'SeqBS', + #'SeqBS'{a=2#0110101, + b=2#010100010101, + c=[second], + d=[1,0,0,1]}, + #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<2#1001:4>>, + e = <<2#01011010:8>>}), + roundtrip(<<48,0>>, + 'SeqBS', + #'SeqBS'{a=[1,0,1,0,1,1,0], + b=[1,0,1,0,1,0,0,0,1,0,1,0], + c={5,<<64>>}, + d=2#1001}, + #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<2#1001:4>>, + e = <<2#01011010:8>>}), + roundtrip(<<48,3,131,1,0>>, + 'SeqBS', + #'SeqBS'{a=[1,0,1,0,1,1,0], + b=[1,0,1,0,1,0,0,0,1,0,1,0], + c={5,<<64>>}, + d=0}, + #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<>>, + e = <<2#01011010:8>>}), + roundtrip(<<48,3,131,1,0>>, + 'SeqBS', + #'SeqBS'{a = <<1:1,0:1,1:1,0:1,1:1,1:1,0:1>>, + b = <<1:1,0:1,1:1,0:1,1:1,0:1,0:1,0:1,1:1,0:1,1:1,0:1>>, + c = <<2:3>>, + d=0, + e = <<16#5A:8>>}, + #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<>>, + e = <<2#01011010:8>>}), + + %% None of the default values are used. + roundtrip(<<48,19,128,2,7,128,129,2,5,64,130,2,5,32,131,1,0,132,2,5,224>>, + 'SeqBS', + #'SeqBS'{a = <<1:1>>, + b = {5,<<64>>}, + c = [third], + d = 0, + e = <<7:3>>}, + #'SeqBS'{a = <<1:1>>, + b = <<2:3>>, + c = [third], + d = <<>>, + e = <<7:3>>}), + roundtrip(<<49,0>>, + 'SetBS', + #'SetBS'{a=2#0110101, + b=2#010100010101, + c=[second], + d=[1,0,0,1]}, + #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<2#1001:4>>}), + roundtrip(<<49,0>>, + 'SetBS', + #'SetBS'{a=[1,0,1,0,1,1,0], + b=[1,0,1,0,1,0,0,0,1,0,1,0], + c={5,<<64>>}, + d=9}, + #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<2#1001:4>>}), + roundtrip(<<49,3,131,1,0>>, + 'SetBS', + #'SetBS'{a=[1,0,1,0,1,1,0], + b=[1,0,1,0,1,0,0,0,1,0,1,0], + c={5,<<64>>}, + d=0}, + #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<>>}), + roundtrip(<<49,3,131,1,0>>, + 'SetBS', + #'SetBS'{a = <<1:1,0:1,1:1,0:1,1:1,1:1,0:1>>, + b = <<1:1,0:1,1:1,0:1,1:1,0:1,0:1,0:1,1:1,0:1,1:1,0:1>>, + c = <<2:3>>, + d=0}, + #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>, + c=[second], d = <<>>}), + ok. roundtrip(Encoded, Type, Value) -> diff --git a/lib/asn1/test/testTcapsystem.erl b/lib/asn1/test/testTcapsystem.erl index 4979a385b2..fcc9e084e0 100644 --- a/lib/asn1/test/testTcapsystem.erl +++ b/lib/asn1/test/testTcapsystem.erl @@ -21,44 +21,42 @@ -export([compile/2]). --include_lib("test_server/include/test_server.hrl"). - compile(Config, Options) -> - [asn1_test_lib:compile(filename:join([tcapsystem, M]), Config, Options) - || M <- ["DialoguePDUs.asn", - "MAP-ApplicationContexts.asn", - "MAP-BS-Code.asn", - "MAP-CallHandlingOperations.asn", - "MAP-CH-DataTypes.asn", - "MAP-CommonDataTypes.asn", - "MAP-DialogueInformation.asn", - "MAP-ER-DataTypes.asn", - "MAP-Errors.asn", - "MAP-ExtensionDataTypes.asn", - "MAP-GR-DataTypes.asn", - "MAP-Group-Call-Operations.asn", - "MAP-LCS-DataTypes.asn", - "MAP-LocationServiceOperations.asn", - "MAP-MobileServiceOperations.asn", - "MAP-MS-DataTypes.asn", - "MAP-OM-DataTypes.asn", - "MAP-OperationAndMaintenanceOperations.asn", - "MAP-Protocol.asn", - "MAP-SecureTransportOperations.asn", - "MAP-ShortMessageServiceOperations.asn", - "MAP-SM-DataTypes.asn", - "MAP-SS-Code.asn", - "MAP-SS-DataTypes.asn", - "MAP-ST-DataTypes.asn", - "MAP-SupplementaryServiceOperations.asn", - "MAP-TS-Code.asn", - "MobileDomainDefinitions.asn", - "Remote-Operations-Generic-ROS-PDUs.asn", - "Remote-Operations-Information-Objects.asn", - "Remote-Operations-Useful-Definitions.asn", - "TCAP-Examples.asn", - "TCAPMessages.asn", - "TCAP-Tools.asn", - "TC-Notation-Extensions.asn", - "UnidialoguePDUs.asn"]], - ok. + Fs = [filename:join("tcapsystem", M) || + M <- ["DialoguePDUs.asn", + "MAP-ApplicationContexts.asn", + "MAP-BS-Code.asn", + "MAP-CallHandlingOperations.asn", + "MAP-CH-DataTypes.asn", + "MAP-CommonDataTypes.asn", + "MAP-DialogueInformation.asn", + "MAP-ER-DataTypes.asn", + "MAP-Errors.asn", + "MAP-ExtensionDataTypes.asn", + "MAP-GR-DataTypes.asn", + "MAP-Group-Call-Operations.asn", + "MAP-LCS-DataTypes.asn", + "MAP-LocationServiceOperations.asn", + "MAP-MobileServiceOperations.asn", + "MAP-MS-DataTypes.asn", + "MAP-OM-DataTypes.asn", + "MAP-OperationAndMaintenanceOperations.asn", + "MAP-Protocol.asn", + "MAP-SecureTransportOperations.asn", + "MAP-ShortMessageServiceOperations.asn", + "MAP-SM-DataTypes.asn", + "MAP-SS-Code.asn", + "MAP-SS-DataTypes.asn", + "MAP-ST-DataTypes.asn", + "MAP-SupplementaryServiceOperations.asn", + "MAP-TS-Code.asn", + "MobileDomainDefinitions.asn", + "Remote-Operations-Generic-ROS-PDUs.asn", + "Remote-Operations-Information-Objects.asn", + "Remote-Operations-Useful-Definitions.asn", + "TCAP-Examples.asn", + "TCAPMessages.asn", + "TCAP-Tools.asn", + "TC-Notation-Extensions.asn", + "UnidialoguePDUs.asn"]], + asn1_test_lib:compile_all(Fs, Config, Options). diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk index 1f16f31f6b..37c843204a 100644 --- a/lib/asn1/vsn.mk +++ b/lib/asn1/vsn.mk @@ -1,2 +1,2 @@ #next version number to use is 2.0 -ASN1_VSN = 3.0 +ASN1_VSN = 3.0.1 diff --git a/lib/common_test/configure.in b/lib/common_test/configure.in index b2e6ad997a..b2e6ad997a 100755..100644 --- a/lib/common_test/configure.in +++ b/lib/common_test/configure.in diff --git a/lib/common_test/doc/src/cover_chapter.xml b/lib/common_test/doc/src/cover_chapter.xml index a215c8c2f3..accb94e1a9 100644 --- a/lib/common_test/doc/src/cover_chapter.xml +++ b/lib/common_test/doc/src/cover_chapter.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2006</year><year>2013</year> + <year>2006</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -81,10 +81,7 @@ specify that previously exported data should be imported and included in the analysis for a test (you can specify multiple import files). This way it is possible to analyse total code coverage - without necessarily running all tests at once. Note that even if - you run separate tests in one test run, code coverage data will - not be passed on from one test to another unless you specify an - export file for Common Test to use for this purpose.</p> + without necessarily running all tests at once.</p> <p>To activate the code coverage support, you simply specify the name of the cover specification file as you start Common Test. @@ -266,10 +263,20 @@ ct_cover:cross_cover_analyse(Level, [{s1,S1LogDir},{s2,S2LogDir}]).</code> <section> <title>Logging</title> - <p>To view the result of a code coverage test, follow the - "Coverage log" link on the test suite results page. This - takes you to the code coverage overview page. If you have - successfully performed a detailed coverage analysis, you + <p>To view the result of a code coverage test, click the button + labled "COVER LOG" in the top level index page for the test run.</p> + + <p>Prior to Erlang/OTP 17.1, if your test run consisted of + multiple tests, cover would be started and stopped for each test + within the test run. Separate logs would be available via the + "Coverage log" link on the test suite result pages. These links + are still available, but now they all point to the same page as + the button on the top level index page. The log contains the + accumulated results for the complete test run. See the release + notes for more information about this change.</p> + + <p>The buttonc takes you to the code coverage overview page. If you + have successfully performed a detailed coverage analysis, you find links to each individual module coverage page here.</p> <p>If cross cover analysis has been performed, and there are diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml index ddfeb0964b..b53ba32e6c 100644 --- a/lib/common_test/doc/src/notes.xml +++ b/lib/common_test/doc/src/notes.xml @@ -32,6 +32,71 @@ <file>notes.xml</file> </header> +<section><title>Common_Test 1.8.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Substrings in long telnet messages would sometimes get + wrongly reversed. This error has been corrected.</p> + <p> + Own Id: OTP-11871 Aux Id: seq12581 </p> + </item> + <item> + <p> + The basic_html logging mode in Common Test (for + compatibility with old browsers) generated HTML code with + unbalanced tags. This has been fixed.</p> + <p> + Own Id: OTP-11917 Aux Id: seq12598 </p> + </item> + <item> + <p> + The mechanism for running code cover analysis with + common_test has been improved. Earlier, if a test run + consisted of multiple tests, cover would be started and + stopped for each test. This would give "intermediate" + cover logs available from the "Coverage log" link on the + test suite result pages. To accumulate cover data over + all tests, the 'export' option had to be used in the + cover spec file. This was not well documented, and the + functionality was quite confusing.</p> + <p> + Using the 'nodes' option in the cover spec file would + fail when the test run consisted of multiple tests, since + the specified nodes would only be included in the cover + analysis of the first test.</p> + <p> + The repeated compilation and analysis of the same modules + was also very time consuming.</p> + <p> + To overcome these problems, ct will now only cover + compile and analyze modules once per test run, i.e. once + for each cover spec file. The log file is available via a + new button on the top level index page. The old "Coverage + log" links on the test suite result pages still exist, + but they all point to the same log containing the + accumulated result.</p> + <p> + Own Id: OTP-11971</p> + </item> + <item> + <p> + If multiple tests would run simultaneously on different + Erlang nodes, writing their logs to the same directory, + then there would often be entries in the all_runs.html + log file showing incomplete results (all zeroes) upon + completion. This problem was caused by a bug in the + Common Test log cache mechanism, which has been fixed.</p> + <p> + Own Id: OTP-11988 Aux Id: seq12611 </p> + </item> + </list> + </section> + +</section> + <section><title>Common_Test 1.8</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/common_test/priv/run_test.in b/lib/common_test/priv/run_test.in index 1508751e4f..1508751e4f 100755..100644 --- a/lib/common_test/priv/run_test.in +++ b/lib/common_test/priv/run_test.in diff --git a/lib/common_test/src/ct_cover.erl b/lib/common_test/src/ct_cover.erl index ae671c750a..cf2860ae25 100644 --- a/lib/common_test/src/ct_cover.erl +++ b/lib/common_test/src/ct_cover.erl @@ -47,18 +47,21 @@ add_nodes(Nodes) -> undefined -> {error,cover_not_running}; _ -> - {File,Nodes0,Import,Export,AppInfo} = ct_util:get_testdata(cover), + Nodes0 = cover:which_nodes(), Nodes1 = [Node || Node <- Nodes, lists:member(Node,Nodes0) == false], ct_logs:log("COVER INFO", "Adding nodes to cover test: ~w", [Nodes1]), case cover:start(Nodes1) of - Result = {ok,_} -> - ct_util:set_testdata({cover,{File,Nodes1++Nodes0, - Import,Export,AppInfo}}), - + Result = {ok,StartedNodes} -> + ct_logs:log("COVER INFO", + "Successfully added nodes to cover test: ~w", + [StartedNodes]), Result; Error -> + ct_logs:log("COVER INFO", + "Failed to add nodes to cover test: ~tp", + [Error]), Error end end. @@ -81,19 +84,20 @@ remove_nodes(Nodes) -> undefined -> {error,cover_not_running}; _ -> - {File,Nodes0,Import,Export,AppInfo} = ct_util:get_testdata(cover), + Nodes0 = cover:which_nodes(), ToRemove = [Node || Node <- Nodes, lists:member(Node,Nodes0)], ct_logs:log("COVER INFO", - "Removing nodes from cover test: ~w", [ToRemove]), + "Removing nodes from cover test: ~w", [ToRemove]), case cover:stop(ToRemove) of ok -> - Nodes1 = lists:foldl(fun(N,Deleted) -> - lists:delete(N,Deleted) - end, Nodes0, ToRemove), - ct_util:set_testdata({cover,{File,Nodes1, - Import,Export,AppInfo}}), + ct_logs:log("COVER INFO", + "Successfully removed nodes from cover test.", + []), ok; Error -> + ct_logs:log("COVER INFO", + "Failed to remove nodes from cover test: ~tp", + [Error]), Error end end. @@ -149,7 +153,7 @@ get_spec_test(File) -> {value,{_,[Exp]}} -> filename:absname(Exp); _ -> - [] + undefined end, Nodes = case lists:keysearch(nodes, 1, Terms) of diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 20903607dc..e8ea7992b4 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -1244,38 +1244,7 @@ report(What,Data) -> ct_logs:make_all_suites_index({TestName,RunDir}), ok; tests_start -> - case ct_util:get_testdata(cover) of - undefined -> - ok; - {_CovFile,_CovNodes,CovImport,CovExport,_CovAppData} -> - %% Always import cover data from files specified by CovImport - %% if no CovExport defined. If CovExport is defined, only - %% import from CovImport files initially, then use CovExport - %% to pass coverdata between proceeding tests (in the same run). - Imps = - case CovExport of - [] -> % don't export data between tests - CovImport; - _ -> - case filelib:is_file(CovExport) of - true -> - [CovExport]; - false -> - CovImport - end - end, - lists:foreach( - fun(Imp) -> - case cover:import(Imp) of - ok -> - ok; - {error,Reason} -> - ct_logs:log("COVER INFO", - "Importing cover data from: ~ts fails! " - "Reason: ~p", [Imp,Reason]) - end - end, Imps) - end; + ok; tests_done -> ok; severe_error -> diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index a4ad65c0a4..43eabb18d5 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2013. All Rights Reserved. +%% Copyright Ericsson AB 2003-2014. 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 @@ -62,6 +62,7 @@ -define(totals_name, "totals.info"). -define(log_cache_name, "ct_log_cache"). -define(misc_io_log, "misc_io.log.html"). +-define(coverlog_name, "cover.html"). % must be same as in test_server_ctrl -define(table_color1,"#ADD8E6"). -define(table_color2,"#E4F0FE"). @@ -1304,7 +1305,8 @@ total_row(Success, Fail, UserSkip, AutoSkip, NotBuilt, All) -> "<td align=right>",integer_to_list(AllSkip), " (",UserSkipStr,"/",AutoSkipStr,")</td>\n", "<td align=right><b>",integer_to_list(NotBuilt),"<b></td>\n", - AllInfo, "</tr>\n</tfoot>\n"]. + AllInfo, "</tr>\n", + xhtml("","</tfoot>\n")]. not_built(_BaseName,_LogDir,_All,[]) -> 0; @@ -1368,6 +1370,19 @@ index_header(Label, StartTime) -> format_time(StartTime), {[],[1],[2,3,4,5]}) end, + Cover = + case filelib:is_regular(?abs(?coverlog_name)) of + true -> + xhtml(["<p><a href=\"",?coverlog_name, + "\">Cover Log</a></p><br>\n"], + ["<br />" + "<div id=\"button_holder\" class=\"btn\">\n" + "<a href=\"",?coverlog_name, + "\">COVER LOG</a>\n</div><br /><br />"]); + false -> + xhtml("<br>\n", "<br /><br /><br />\n") + end, + [Head | ["<center>\n", xhtml(["<p><a href=\"",?ct_log_name, @@ -1375,8 +1390,8 @@ index_header(Label, StartTime) -> ["<br />" "<div id=\"button_holder\" class=\"btn\">\n" "<a href=\"",?ct_log_name, - "\">COMMON TEST FRAMEWORK LOG</a>\n</div>"]), - xhtml("<br>\n", "<br /><br /><br />\n"), + "\">COMMON TEST FRAMEWORK LOG</a>\n</div><br>\n"]), + Cover, xhtml(["<table border=\"3\" cellpadding=\"5\" " "bgcolor=\"",?table_color3,"\">\n"], ["<table id=\"",?sortable_table_name,"\">\n", @@ -1519,7 +1534,8 @@ all_suites_index_footer() -> xhtml("<br><br>\n", "<br /><br />\n") | footer()]. all_runs_index_footer() -> - ["</tbody>\n</table>\n", + [xhtml("", "</tbody>\n"), + "</table>\n", "</center>\n", xhtml("<br><br>\n", "<br /><br />\n") | footer()]. @@ -1676,7 +1692,7 @@ config_table(Vars) -> config_table_header() -> [ xhtml(["<h2>Configuration</h2>\n" - "<table border=\"3\" cellpadding=\"5\" bgcolor=\"",?table_color1,"\"\n"], + "<table border=\"3\" cellpadding=\"5\" bgcolor=\"",?table_color1,"\">\n"], ["<h4>CONFIGURATION</h4>\n", "<table id=\"",?sortable_table_name,"\">\n", "<thead>\n"]), @@ -1692,7 +1708,7 @@ config_table1([{Key,Value}|Vars]) -> "<td>", io_lib:format("~p",[Value]), "</td>\n</tr>\n"]) | config_table1(Vars)]; config_table1([]) -> - ["</tbody>\n</table>\n"]. + [xhtml("","</tbody>\n"),"</table>\n"]. make_all_runs_index(When) -> @@ -1842,14 +1858,27 @@ dir_diff_all_runs(LogDirs=[Dir|Dirs], Cached=[CElem|CElems], LatestInCache, AllRunsDirs) -> DirDate = datestr_from_dirname(Dir), if DirDate > LatestInCache -> - %% Dir is a new run entry + %% Dir is a new run entry (not cached) dir_diff_all_runs(Dirs, Cached, LatestInCache, [Dir|AllRunsDirs]); DirDate == LatestInCache, CElems /= [] -> - %% Dir is an existing run entry + %% Dir is an existing (cached) run entry + + %% Only add the cached element instead of Dir if the totals + %% are "non-empty" (a test might be executing on a different + %% node and results haven't been saved yet) + ElemToAdd = + case CElem of + {_CDir,{_NodeStr,_Label,_Logs,{0,0,0,0,0}},_IxLink} -> + %% "empty" element in cache - this could be an + %% incomplete test and should be checked again + Dir; + _ -> + CElem + end, dir_diff_all_runs(Dirs, CElems, datestr_from_dirname(element(1,hd(CElems))), - [CElem|AllRunsDirs]); + [ElemToAdd|AllRunsDirs]); DirDate == LatestInCache, CElems == [] -> %% we're done, Dirs must all be new lists:reverse(Dirs)++[CElem|AllRunsDirs]; diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 03cf06abed..00d0aab507 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -1646,7 +1646,7 @@ do_run(Tests, Misc, LogDir, LogOpts) when is_list(Misc), do_run(Tests, [], Opts#opts{logdir = LogDir}, []); do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) -> - #opts{label = Label, profile = Profile, cover = Cover, + #opts{label = Label, profile = Profile, verbosity = VLvls} = Opts, %% label - used by ct_logs TestLabel = @@ -1670,22 +1670,6 @@ do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) -> non_existing -> {error,no_path_to_test_server}; _ -> - Opts1 = if Cover == undefined -> - Opts; - true -> - case ct_cover:get_spec(Cover) of - {error,Reason} -> - exit({error,Reason}); - CoverSpec -> - CoverStop = - case Opts#opts.cover_stop of - undefined -> true; - Stop -> Stop - end, - Opts#opts{coverspec = CoverSpec, - cover_stop = CoverStop} - end - end, %% This env variable is used by test_server to determine %% which framework it runs under. case os:getenv("TEST_SERVER_FRAMEWORK") of @@ -1711,7 +1695,7 @@ do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) -> _Pid -> ct_util:set_testdata({starter,Opts#opts.starter}), compile_and_run(Tests, Skip, - Opts1#opts{verbosity=Verbosity}, Args) + Opts#opts{verbosity=Verbosity}, Args) end end. @@ -2146,67 +2130,11 @@ check_and_add([{TestDir0,M,_} | Tests], Added, PA) -> check_and_add([], _, PA) -> {ok,PA}. -do_run_test(Tests, Skip, Opts) -> +do_run_test(Tests, Skip, Opts0) -> case check_and_add(Tests, [], []) of {ok,AddedToPath} -> ct_util:set_testdata({stats,{0,0,{0,0}}}), - ct_util:set_testdata({cover,undefined}), test_server_ctrl:start_link(local), - case Opts#opts.coverspec of - CovData={CovFile, - CovNodes, - _CovImport, - CovExport, - #cover{app = CovApp, - level = CovLevel, - excl_mods = CovExcl, - incl_mods = CovIncl, - cross = CovCross, - src = _CovSrc}} -> - ct_logs:log("COVER INFO", - "Using cover specification file: ~ts~n" - "App: ~w~n" - "Cross cover: ~w~n" - "Including ~w modules~n" - "Excluding ~w modules", - [CovFile,CovApp,CovCross, - length(CovIncl),length(CovExcl)]), - - %% cover export file will be used for export and import - %% between tests so make sure it doesn't exist initially - case filelib:is_file(CovExport) of - true -> - DelResult = file:delete(CovExport), - ct_logs:log("COVER INFO", - "Warning! " - "Export file ~ts already exists. " - "Deleting with result: ~p", - [CovExport,DelResult]); - false -> - ok - end, - - %% tell test_server which modules should be cover compiled - %% note that actual compilation is done when tests start - test_server_ctrl:cover(CovApp, CovFile, CovExcl, CovIncl, - CovCross, CovExport, CovLevel, - Opts#opts.cover_stop), - %% save cover data (used e.g. to add nodes dynamically) - ct_util:set_testdata({cover,CovData}), - %% start cover on specified nodes - if (CovNodes /= []) and (CovNodes /= undefined) -> - ct_logs:log("COVER INFO", - "Nodes included in cover " - "session: ~w", - [CovNodes]), - cover:start(CovNodes); - true -> - ok - end, - true; - _ -> - false - end, %% let test_server expand the test tuples and count no of cases {Suites,NoOfCases} = count_test_cases(Tests, Skip), @@ -2231,24 +2159,31 @@ do_run_test(Tests, Skip, Opts) -> end, %% if the verbosity level is set lower than ?STD_IMPORTANCE, tell %% test_server to ignore stdout printouts to the test case log file - case proplists:get_value(default, Opts#opts.verbosity) of + case proplists:get_value(default, Opts0#opts.verbosity) of VLvl when is_integer(VLvl), (?STD_IMPORTANCE < (100-VLvl)) -> test_server_ctrl:reject_io_reqs(true); _Lower -> ok end, - test_server_ctrl:multiply_timetraps(Opts#opts.multiply_timetraps), - test_server_ctrl:scale_timetraps(Opts#opts.scale_timetraps), + test_server_ctrl:multiply_timetraps(Opts0#opts.multiply_timetraps), + test_server_ctrl:scale_timetraps(Opts0#opts.scale_timetraps), test_server_ctrl:create_priv_dir(choose_val( - Opts#opts.create_priv_dir, + Opts0#opts.create_priv_dir, auto_per_run)), + + {ok,LogDir} = ct_logs:get_log_dir(true), + {TsCoverInfo,Opts} = maybe_start_cover(Opts0, LogDir), + ct_event:notify(#event{name=start_info, node=node(), data={NoOfTests,NoOfSuites,NoOfCases}}), CleanUp = add_jobs(Tests, Skip, Opts, []), unlink(whereis(test_server_ctrl)), catch test_server_ctrl:wait_finish(), + + maybe_stop_cover(Opts, TsCoverInfo, LogDir), + %% check if last testcase has left a "dead" trace window %% behind, and if so, kill it case ct_util:get_testdata(interpret) of @@ -2281,6 +2216,102 @@ do_run_test(Tests, Skip, Opts) -> exit(Error) end. +maybe_start_cover(Opts=#opts{cover=Cover,cover_stop=CoverStop0},LogDir) -> + if Cover == undefined -> + {undefined,Opts}; + true -> + case ct_cover:get_spec(Cover) of + {error,Reason} -> + exit({error,Reason}); + CoverSpec -> + CoverStop = + case CoverStop0 of + undefined -> true; + Stop -> Stop + end, + start_cover(Opts#opts{coverspec=CoverSpec, + cover_stop=CoverStop}, + LogDir) + end + end. + +start_cover(Opts=#opts{coverspec=CovData,cover_stop=CovStop},LogDir) -> + {CovFile, + CovNodes, + CovImport, + _CovExport, + #cover{app = CovApp, + level = CovLevel, + excl_mods = CovExcl, + incl_mods = CovIncl, + cross = CovCross, + src = _CovSrc}} = CovData, + ct_logs:log("COVER INFO", + "Using cover specification file: ~ts~n" + "App: ~w~n" + "Cross cover: ~w~n" + "Including ~w modules~n" + "Excluding ~w modules", + [CovFile,CovApp,CovCross, + length(CovIncl),length(CovExcl)]), + + %% Tell test_server to print a link in its coverlog + %% pointing to the real coverlog which will be written in + %% maybe_stop_cover/2 + test_server_ctrl:cover({log,LogDir}), + + %% Cover compile all modules + {ok,TsCoverInfo} = test_server_ctrl:cover_compile(CovApp,CovFile, + CovExcl,CovIncl, + CovCross,CovLevel, + CovStop), + ct_logs:log("COVER INFO", + "Compilation completed - test_server cover info: ~tp", + [TsCoverInfo]), + + %% start cover on specified nodes + if (CovNodes /= []) and (CovNodes /= undefined) -> + ct_logs:log("COVER INFO", + "Nodes included in cover " + "session: ~w", + [CovNodes]), + cover:start(CovNodes); + true -> + ok + end, + lists:foreach( + fun(Imp) -> + case cover:import(Imp) of + ok -> + ok; + {error,Reason} -> + ct_logs:log("COVER INFO", + "Importing cover data from: ~ts fails! " + "Reason: ~p", [Imp,Reason]) + end + end, CovImport), + {TsCoverInfo,Opts}. + +maybe_stop_cover(_,undefined,_) -> + ok; +maybe_stop_cover(#opts{coverspec=CovData},TsCoverInfo,LogDir) -> + {_CovFile, + _CovNodes, + _CovImport, + CovExport, + _AppData} = CovData, + case CovExport of + undefined -> ok; + _ -> + ct_logs:log("COVER INFO","Exporting cover data to ~tp",[CovExport]), + cover:export(CovExport) + end, + ct_logs:log("COVER INFO","Analysing cover data to ~tp",[LogDir]), + test_server_ctrl:cover_analyse(TsCoverInfo,LogDir), + ct_logs:log("COVER INFO","Analysis completed.",[]), + ok. + + delete_dups([S | Suites]) -> Suites1 = lists:delete(S, Suites), [S | delete_dups(Suites1)]; diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile index 085f19d023..a0ac47f12a 100644 --- a/lib/common_test/test/Makefile +++ b/lib/common_test/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2008-2013. All Rights Reserved. +# Copyright Ericsson AB 2008-2014. 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 @@ -61,6 +61,7 @@ MODULES= \ ct_snmp_SUITE \ ct_group_leader_SUITE \ ct_cover_SUITE \ + ct_cover_nomerge_SUITE \ ct_groups_search_SUITE \ ct_surefire_SUITE \ ct_telnet_SUITE diff --git a/lib/common_test/test/ct_cover_SUITE.erl b/lib/common_test/test/ct_cover_SUITE.erl index ec2680f664..47080b5577 100644 --- a/lib/common_test/test/ct_cover_SUITE.erl +++ b/lib/common_test/test/ct_cover_SUITE.erl @@ -172,8 +172,8 @@ cross(Config) -> check_calls(Events2,1), %% Get the log dirs for each test and run cross cover analyse - [D11,D12] = lists:sort(get_run_dirs(Events1)), - [D21,D22] = lists:sort(get_run_dirs(Events2)), + [D11,D12] = lists:sort(get_log_dirs(Events1)), + [D21,D22] = lists:sort(get_log_dirs(Events2)), ct_cover:cross_cover_analyse(details,[{cross1,D11},{cross2,D21}]), ct_cover:cross_cover_analyse(details,[{cross1,D12},{cross2,D22}]), @@ -267,18 +267,17 @@ check_cover(Node) when is_atom(Node) -> false end. -%% Get the log dir "run.<timestamp>" for all (both!) tests -get_run_dirs(Events) -> - [filename:dirname(TCLog) || +%% Get the log dir "ct_run.<timestamp>" for all (both!) tests +get_log_dirs(Events) -> + [LogDir || {ct_test_support_eh, - {event,tc_logfile,_Node, - {{?suite,init_per_suite},TCLog}}} <- Events]. + {event,start_logging,_Node,LogDir}} <- Events]. %% Check that each coverlog includes N calls to ?mod:foo/0 check_calls(Events,N) -> check_calls(Events,{?mod,foo,0},N). check_calls(Events,MFA,N) -> - CoverLogs = [filename:join(D,"all.coverdata") || D <- get_run_dirs(Events)], + CoverLogs = [filename:join(D,"all.coverdata") || D <- get_log_dirs(Events)], do_check_logs(CoverLogs,MFA,N). do_check_logs([CoverLog|CoverLogs],{Mod,_,_} = MFA,N) -> diff --git a/lib/common_test/test/ct_cover_nomerge_SUITE.erl b/lib/common_test/test/ct_cover_nomerge_SUITE.erl new file mode 100644 index 0000000000..8e2ee1b500 --- /dev/null +++ b/lib/common_test/test/ct_cover_nomerge_SUITE.erl @@ -0,0 +1,221 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. 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% +%% + +%%%------------------------------------------------------------------- +%%% File: ct_cover_nomerge_SUITE +%%% +%%% Description: +%%% Test code cover analysis support when merge_tests=false +%%% +%%%------------------------------------------------------------------- +-module(ct_cover_nomerge_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-define(eh, ct_test_support_eh). +-define(mod, cover_test_mod). + +%%-------------------------------------------------------------------- +%% TEST SERVER CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Description: Since Common Test starts another Test Server +%% instance, the tests need to be performed on a separate node (or +%% there will be clashes with logging processes etc). +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + case test_server:is_cover() of + true -> + {skip,"Test server is running cover already - skipping"}; + false -> + ct_test_support:init_per_suite(Config) + end. + +end_per_suite(Config) -> + ct_test_support:end_per_suite(Config). + +init_per_testcase(TestCase, Config) -> + ct_test_support:init_per_testcase(TestCase, Config). + +end_per_testcase(TestCase, Config) -> + try apply(?MODULE,TestCase,[cleanup,Config]) + catch error:undef -> ok + end, + ct_test_support:end_per_testcase(TestCase, Config). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [ + local, + remote, + remote_nostop + ]. + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +local(Config) -> + DataDir = ?config(data_dir, Config), + Spec = filename:join(DataDir, "local.spec"), + CoverSpec = [{incl_mods,[?mod]}], + CoverFile = create_cover_file(local,CoverSpec,Config), + {Opts,ERPid} = setup([{spec,Spec},{label,local},{cover,CoverFile}], Config), + {ok,Events} = execute(local, local, Opts, ERPid, Config), + false = check_cover(Config), + check_calls(Events,2), + ok. + +remote(Config) -> + DataDir = ?config(data_dir, Config), + Spec = filename:join(DataDir, "remote.spec"), + %% extending some timers for slow test hosts + {ok,Node} = ct_slave:start(ct_nomerge,[{boot_timeout,15}, + {init_timeout,15}, + {startup_timeout,15}]), + + CoverSpec = [{nodes,[Node]}, + {incl_mods,[?mod]}], + CoverFile = create_cover_file(remote,CoverSpec,Config), + {Opts,ERPid} = setup([{spec,Spec},{label,remote},{cover,CoverFile}], Config), + {ok,Events} = execute(remote, remote, Opts, ERPid, Config), + false = check_cover(Config), + check_calls(Events,2), + ok. +remote(cleanup,_Config) -> + {ok,_} = ct_slave:stop(ct_nomerge), + ok. + +remote_nostop(Config) -> + DataDir = ?config(data_dir, Config), + Spec = filename:join(DataDir, "remote_nostop.spec"), + %% extending some timers for slow test hosts + {ok,Node} = ct_slave:start(ct_nomerge,[{boot_timeout,15}, + {init_timeout,15}, + {startup_timeout,15}]), + + CoverSpec = [{nodes,[Node]}, + {incl_mods,[?mod]}], + CoverFile = create_cover_file(remote_nostop,CoverSpec,Config), + {Opts,ERPid} = setup([{spec,Spec},{label,remote_nostop}, + {cover,CoverFile},{cover_stop,false}], + Config), + {ok,Events} = execute(remote_nostop, remote_nostop, Opts, ERPid, Config), + {true,[Node],[cover_test_mod]} = check_cover(Config), + check_calls(Events,2), + ok. +remote_nostop(cleanup,Config) -> + CtNode = ?config(ct_node,Config), + ok = rpc:call(CtNode,cover,stop,[]), + {ok,_} = ct_slave:stop(ct_nomerge), + ok. + + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- +setup(Test, Config) -> + Opts0 = ct_test_support:get_opts(Config), + Level = ?config(trace_level, Config), + EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], + Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test], + ERPid = ct_test_support:start_event_receiver(Config), + {Opts,ERPid}. + +execute(Name, Testcase, Opts, ERPid, Config) -> + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(Name, + reformat(Events, ?eh), + ?config(priv_dir, Config), + Opts), + TestEvents = events_to_check(Testcase), + R = ct_test_support:verify_events(TestEvents, Events, Config), + {R,Events}. + +reformat(Events, EH) -> + ct_test_support:reformat(Events, EH). + +events_to_check(local) -> + events_to_check1(cover_nomerge_local_SUITE); +events_to_check(remote) -> + events_to_check1(cover_nomerge_remote_SUITE); +events_to_check(remote_nostop) -> + events_to_check1(cover_nomerge_remote_nostop_SUITE). +events_to_check1(Suite) -> + OneTest = + [{?eh,start_logging,{'DEF','RUNDIR'}}] ++ + [{?eh,tc_done,{Suite,t1,ok}}] ++ + [{?eh,tc_done,{Suite,t2,ok}}] ++ + [{?eh,stop_logging,[]}], + + %% 2 tests (ct:run_test + script_start) is default + OneTest ++ OneTest. + +check_cover(Config) when is_list(Config) -> + CTNode = proplists:get_value(ct_node, Config), + check_cover(CTNode); +check_cover(Node) when is_atom(Node) -> + case rpc:call(Node,test_server,is_cover,[]) of + true -> + {true, + rpc:call(Node,cover,which_nodes,[]), + rpc:call(Node,cover,modules,[])}; + false -> + false + end. + +%% Get the log dir "ct_run.<timestamp>" for all (both!) tests +get_log_dirs(Events) -> + [LogDir || + {ct_test_support_eh, + {event,start_logging,_Node,LogDir}} <- Events]. + +%% Check that each coverlog includes N calls to ?mod:foo/0 +check_calls(Events,N) -> + check_calls(Events,{?mod,foo,0},N). +check_calls(Events,MFA,N) -> + CoverLogs = [filename:join(D,"all.coverdata") || D <- get_log_dirs(Events)], + do_check_logs(CoverLogs,MFA,N). + +do_check_logs([CoverLog|CoverLogs],{Mod,_,_} = MFA,N) -> + {ok,_} = cover:start(), + ok = cover:import(CoverLog), + {ok,Calls} = cover:analyse(Mod,calls,function), + ok = cover:stop(), + {MFA,N} = lists:keyfind(MFA,1,Calls), + do_check_logs(CoverLogs,MFA,N); +do_check_logs([],_,_) -> + ok. + +create_cover_file(Filename,Terms,Config) -> + PrivDir = ?config(priv_dir,Config), + File = filename:join(PrivDir,Filename) ++ ".cover", + {ok,Fd} = file:open(File,[write]), + lists:foreach(fun(Term) -> + file:write(Fd,io_lib:format("~p.~n",[Term])) + end,Terms), + ok = file:close(Fd), + File. diff --git a/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_nomerge_local_SUITE.erl b/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_nomerge_local_SUITE.erl new file mode 100644 index 0000000000..e1fe3b5fc9 --- /dev/null +++ b/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_nomerge_local_SUITE.erl @@ -0,0 +1,63 @@ +%%-------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. 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(cover_nomerge_local_SUITE). +-include_lib("common_test/include/ct.hrl"). + +-compile(export_all). + +%% Default timetrap timeout (set in init_per_testcase). +-define(default_timeout, ?t:minutes(1)). + +suite() -> + []. + +all() -> + [t1,t2]. + +init_per_suite(Config) -> + Config. + +end_per_suite(Config) -> + Config. + +init_per_testcase(_Case, Config) -> + Dog = test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + +end_per_testcase(Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +%%%----------------------------------------------------------------- +%%% Test cases +break(_Config) -> + test_server:break(""), + ok. + +t1(_Config) -> + cover_compiled = code:which(cover_test_mod), + ok = cover_test_mod:foo(), + ok. + +t2(_Config) -> + cover_compiled = code:which(cover_test_mod), + ok = cover_test_mod:foo(), + ok. diff --git a/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_nomerge_remote_SUITE.erl b/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_nomerge_remote_SUITE.erl new file mode 100644 index 0000000000..a77ae0c2db --- /dev/null +++ b/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_nomerge_remote_SUITE.erl @@ -0,0 +1,75 @@ +%%-------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. 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(cover_nomerge_remote_SUITE). +-include_lib("common_test/include/ct.hrl"). + +-compile(export_all). + +%% Default timetrap timeout (set in init_per_testcase). +-define(default_timeout, ?t:minutes(1)). + +suite() -> + []. + +all() -> + [t1,t2]. + +init_per_suite(Config) -> + {ok,Host} = inet:gethostname(), + Node = list_to_atom("ct_nomerge@"++Host), + pong = net_adm:ping(Node), + +%% Include this row, and exclude the equivalent row in end_per_suite => +%% fails every now and then with missing data. Why? +%% ct_cover:remove_nodes([Node]), + ct_cover:add_nodes([Node]), + [{node,Node}|Config]. + +end_per_suite(Config) -> + Node = ?config(node,Config), + ct_cover:remove_nodes([Node]), + Config. + +init_per_testcase(_Case, Config) -> + Dog = test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + +end_per_testcase(Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +%%%----------------------------------------------------------------- +%%% Test cases +break(_Config) -> + test_server:break(""), + ok. + +t1(Config) -> + Node = ?config(node,Config), + cover_compiled = rpc:call(Node, code, which, [cover_test_mod]), + ok = rpc:call(Node, cover_test_mod, foo, []), + ok. + +t2(Config) -> + Node = ?config(node,Config), + cover_compiled = rpc:call(Node, code, which, [cover_test_mod]), + ok = rpc:call(Node, cover_test_mod, foo, []), + ok. diff --git a/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_nomerge_remote_nostop_SUITE.erl b/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_nomerge_remote_nostop_SUITE.erl new file mode 100644 index 0000000000..0b3159f2c3 --- /dev/null +++ b/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_nomerge_remote_nostop_SUITE.erl @@ -0,0 +1,68 @@ +%%-------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. 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(cover_nomerge_remote_nostop_SUITE). +-include_lib("common_test/include/ct.hrl"). + +-compile(export_all). + +%% Default timetrap timeout (set in init_per_testcase). +-define(default_timeout, ?t:minutes(1)). + +suite() -> + []. + +all() -> + [t1,t2]. + +init_per_suite(Config) -> + {ok,Host} = inet:gethostname(), + Node = list_to_atom("ct_nomerge@"++Host), + pong = net_adm:ping(Node), + [{node,Node}|Config]. + +end_per_suite(Config) -> + Config. + +init_per_testcase(_Case, Config) -> + Dog = test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + +end_per_testcase(Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +%%%----------------------------------------------------------------- +%%% Test cases +break(_Config) -> + test_server:break(""), + ok. + +t1(Config) -> + Node = ?config(node,Config), + cover_compiled = rpc:call(Node, code, which, [cover_test_mod]), + ok = rpc:call(Node, cover_test_mod, foo, []), + ok. + +t2(Config) -> + Node = ?config(node,Config), + cover_compiled = rpc:call(Node, code, which, [cover_test_mod]), + ok = rpc:call(Node, cover_test_mod, foo, []), + ok. diff --git a/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_test_mod.erl b/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_test_mod.erl new file mode 100644 index 0000000000..d4f69452c3 --- /dev/null +++ b/lib/common_test/test/ct_cover_nomerge_SUITE_data/cover_test_mod.erl @@ -0,0 +1,4 @@ +-module(cover_test_mod). +-compile(export_all). +foo() -> + ok. diff --git a/lib/common_test/test/ct_cover_nomerge_SUITE_data/local.spec b/lib/common_test/test/ct_cover_nomerge_SUITE_data/local.spec new file mode 100644 index 0000000000..893c48b010 --- /dev/null +++ b/lib/common_test/test/ct_cover_nomerge_SUITE_data/local.spec @@ -0,0 +1,6 @@ +{merge_tests,false}. + +{alias,dir,"."}. + +{cases, dir, cover_nomerge_local_SUITE, [t1]}. +{cases, dir, cover_nomerge_local_SUITE, [t2]}. diff --git a/lib/common_test/test/ct_cover_nomerge_SUITE_data/remote.spec b/lib/common_test/test/ct_cover_nomerge_SUITE_data/remote.spec new file mode 100644 index 0000000000..78c4332270 --- /dev/null +++ b/lib/common_test/test/ct_cover_nomerge_SUITE_data/remote.spec @@ -0,0 +1,6 @@ +{merge_tests,false}. + +{alias,dir,"."}. + +{cases, dir, cover_nomerge_remote_SUITE, [t1]}. +{cases, dir, cover_nomerge_remote_SUITE, [t2]}. diff --git a/lib/common_test/test/ct_cover_nomerge_SUITE_data/remote_nostop.spec b/lib/common_test/test/ct_cover_nomerge_SUITE_data/remote_nostop.spec new file mode 100644 index 0000000000..049f586c72 --- /dev/null +++ b/lib/common_test/test/ct_cover_nomerge_SUITE_data/remote_nostop.spec @@ -0,0 +1,6 @@ +{merge_tests,false}. + +{alias,dir,"."}. + +{cases, dir, cover_nomerge_remote_nostop_SUITE, [t1]}. +{cases, dir, cover_nomerge_remote_nostop_SUITE, [t2]}. diff --git a/lib/common_test/test/ct_netconfc_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE.erl index c89a4cdabe..2959f77087 100644 --- a/lib/common_test/test/ct_netconfc_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2012. All Rights Reserved. +%% Copyright Ericsson AB 2009-2014. 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 @@ -63,7 +63,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [ - default + netconfc1_SUITE, + netconfc_remote_SUITE ]. %%-------------------------------------------------------------------- @@ -72,14 +73,21 @@ all() -> %%%----------------------------------------------------------------- %%% -default(Config) when is_list(Config) -> +netconfc1_SUITE(Config) when is_list(Config) -> DataDir = ?config(data_dir, Config), Suite = filename:join(DataDir, "netconfc1_SUITE"), CfgFile = filename:join(DataDir, "netconfc1.cfg"), {Opts,ERPid} = setup([{suite,Suite},{config,CfgFile}, - {label,default}], Config), + {label,netconfc1_SUITE}], Config), - ok = execute(default, Opts, ERPid, Config). + ok = execute(netconfc1_SUITE, Opts, ERPid, Config). + +netconfc_remote_SUITE(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "netconfc_remote_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{label,netconfc_remote_SUITE}], Config), + + ok = execute(netconfc_remote_SUITE, Opts, ERPid, Config). %%%----------------------------------------------------------------- @@ -112,16 +120,15 @@ reformat(Events, EH) -> %%%----------------------------------------------------------------- %%% TEST EVENTS %%%----------------------------------------------------------------- -events_to_check(default,Config) -> - {module,_} = code:load_abs(filename:join(?config(data_dir,Config), - netconfc1_SUITE)), - TCs = netconfc1_SUITE:all(), - code:purge(netconfc1_SUITE), - code:delete(netconfc1_SUITE), +events_to_check(Suite,Config) -> + {module,_} = code:load_abs(filename:join(?config(data_dir,Config),Suite)), + TCs = Suite:all(), + code:purge(Suite), + code:delete(Suite), OneTest = [{?eh,start_logging,{'DEF','RUNDIR'}}] ++ - [{?eh,tc_done,{netconfc1_SUITE,TC,ok}} || TC <- TCs] ++ + [{?eh,tc_done,{Suite,TC,ok}} || TC <- TCs] ++ [{?eh,stop_logging,[]}], %% 2 tests (ct:run_test + script_start) is default diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl index 2bcfeeec0c..f2adeb9065 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013. All Rights Reserved. +%% Copyright Ericsson AB 2013-2014. 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 @@ -30,25 +30,10 @@ -module(netconfc1_SUITE). -include_lib("common_test/include/ct.hrl"). -include_lib("common_test/src/ct_netconfc.hrl"). --include_lib("public_key/include/public_key.hrl"). +-include("netconfc_test_lib.hrl"). -compile(export_all). -%% Default timetrap timeout (set in init_per_testcase). --define(default_timeout, ?t:minutes(1)). - --define(NS,ns). --define(LOCALHOST, "127.0.0.1"). --define(SSH_PORT, 2060). - --define(DEFAULT_SSH_OPTS,[{ssh,?LOCALHOST}, - {port,?SSH_PORT}, - {user,"xxx"}, - {password,"xxx"}]). --define(DEFAULT_SSH_OPTS(Dir), ?DEFAULT_SSH_OPTS++[{user_dir,Dir}]). - --define(ok,ok). - suite() -> [{ct_hooks, [{cth_conn_log, [{ct_netconfc,[{log_type,html}, %will be overwritten by config @@ -136,8 +121,8 @@ end_per_testcase(_Case, Config) -> init_per_suite(Config) -> case catch {crypto:start(), ssh:start()} of {ok, ok} -> - {ok, _} = get_id_keys(Config), - make_dsa_files(Config), + {ok, _} = netconfc_test_lib:get_id_keys(Config), + netconfc_test_lib:make_dsa_files(Config), Server = ?NS:start(?config(data_dir,Config)), [{server,Server}|Config]; _ -> @@ -148,7 +133,7 @@ end_per_suite(Config) -> ?NS:stop(?config(server,Config)), ssh:stop(), crypto:stop(), - remove_id_keys(Config), + netconfc_test_lib:remove_id_keys(Config), Config. hello(Config) -> @@ -1001,165 +986,3 @@ pad(I) when I<10 -> "0"++integer_to_list(I); pad(I) -> integer_to_list(I). - - -%%%----------------------------------------------------------------- -%%% BEGIN SSH key management -%% copy private keys to given dir from ~/.ssh -get_id_keys(Config) -> - DstDir = ?config(priv_dir, Config), - SrcDir = filename:join(os:getenv("HOME"), ".ssh"), - RsaOk = copyfile(SrcDir, DstDir, "id_rsa"), - DsaOk = copyfile(SrcDir, DstDir, "id_dsa"), - case {RsaOk, DsaOk} of - {{ok, _}, {ok, _}} -> {ok, both}; - {{ok, _}, _} -> {ok, rsa}; - {_, {ok, _}} -> {ok, dsa}; - {Error, _} -> Error - end. - -%% Remove later on. Use make_dsa_files instead. -remove_id_keys(Config) -> - Dir = ?config(priv_dir, Config), - file:delete(filename:join(Dir, "id_rsa")), - file:delete(filename:join(Dir, "id_dsa")). - - -make_dsa_files(Config) -> - make_dsa_files(Config, rfc4716_public_key). -make_dsa_files(Config, Type) -> - {DSA, EncodedKey} = gen_dsa(128, 20), - PKey = DSA#'DSAPrivateKey'.y, - P = DSA#'DSAPrivateKey'.p, - Q = DSA#'DSAPrivateKey'.q, - G = DSA#'DSAPrivateKey'.g, - Dss = #'Dss-Parms'{p=P, q=Q, g=G}, - {ok, Hostname} = inet:gethostname(), - {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet), - IP = lists:concat([A, ".", B, ".", C, ".", D]), - Attributes = [], % Could be [{comment,"user@" ++ Hostname}], - HostNames = [{hostnames,[IP, IP]}], - PublicKey = [{{PKey, Dss}, Attributes}], - KnownHosts = [{{PKey, Dss}, HostNames}], - - KnownHostsEnc = public_key:ssh_encode(KnownHosts, known_hosts), - KnownHosts = public_key:ssh_decode(KnownHostsEnc, known_hosts), - - PublicKeyEnc = public_key:ssh_encode(PublicKey, Type), - - SystemTmpDir = ?config(data_dir, Config), - filelib:ensure_dir(SystemTmpDir), - file:make_dir(SystemTmpDir), - - DSAFile = filename:join(SystemTmpDir, "ssh_host_dsa_key.pub"), - file:delete(DSAFile), - - DSAPrivateFile = filename:join(SystemTmpDir, "ssh_host_dsa_key"), - file:delete(DSAPrivateFile), - - KHFile = filename:join(SystemTmpDir, "known_hosts"), - file:delete(KHFile), - - PemBin = public_key:pem_encode([EncodedKey]), - - file:write_file(DSAFile, PublicKeyEnc), - file:write_file(KHFile, KnownHostsEnc), - file:write_file(DSAPrivateFile, PemBin), - ok. - - -%%-------------------------------------------------------------------- -%% @doc Creates a dsa key (OBS: for testing only) -%% the sizes are in bytes -%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()} -%% @end -%%-------------------------------------------------------------------- -gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) -> - Key = gen_dsa2(LSize, NSize), - {Key, encode_key(Key)}. - -encode_key(Key = #'DSAPrivateKey'{}) -> - Der = public_key:der_encode('DSAPrivateKey', Key), - {'DSAPrivateKey', Der, not_encrypted}. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% DSA key generation (OBS: for testing only) -%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm -%% and the fips_186-3.pdf -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -gen_dsa2(LSize, NSize) -> - Q = prime(NSize), %% Choose N-bit prime Q - X0 = prime(LSize), - P0 = prime((LSize div 2) +1), - - %% Choose L-bit prime modulus P such that p-1 is a multiple of q. - case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of - error -> - gen_dsa2(LSize, NSize); - P -> - G = crypto:mod_pow(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q. - %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used. - - X = prime(20), %% Choose x by some random method, where 0 < x < q. - Y = crypto:mod_pow(G, X, P), %% Calculate y = g^x mod p. - - #'DSAPrivateKey'{version=0, p = P, q = Q, - g = crypto:bytes_to_integer(G), y = crypto:bytes_to_integer(Y), x = X} - end. - -%% See fips_186-3.pdf -dsa_search(T, P0, Q, Iter) when Iter > 0 -> - P = 2*T*Q*P0 + 1, - case is_prime(P, 50) of - true -> P; - false -> dsa_search(T+1, P0, Q, Iter-1) - end; -dsa_search(_,_,_,_) -> - error. - - -%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -prime(ByteSize) -> - Rand = odd_rand(ByteSize), - prime_odd(Rand, 0). - -prime_odd(Rand, N) -> - case is_prime(Rand, 50) of - true -> - Rand; - false -> - prime_odd(Rand+2, N+1) - end. - -%% see http://en.wikipedia.org/wiki/Fermat_primality_test -is_prime(_, 0) -> true; -is_prime(Candidate, Test) -> - CoPrime = odd_rand(10000, Candidate), - Result = crypto:mod_pow(CoPrime, Candidate, Candidate) , - is_prime(CoPrime, crypto:bytes_to_integer(Result), Candidate, Test). - -is_prime(CoPrime, CoPrime, Candidate, Test) -> - is_prime(Candidate, Test-1); -is_prime(_,_,_,_) -> - false. - -odd_rand(Size) -> - Min = 1 bsl (Size*8-1), - Max = (1 bsl (Size*8))-1, - odd_rand(Min, Max). - -odd_rand(Min,Max) -> - Rand = crypto:rand_uniform(Min,Max), - case Rand rem 2 of - 0 -> - Rand + 1; - _ -> - Rand - end. - -copyfile(SrcDir, DstDir, Fn) -> - file:copy(filename:join(SrcDir, Fn), - filename:join(DstDir, Fn)). - -%%% END SSH key management -%%%----------------------------------------------------------------- diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl new file mode 100644 index 0000000000..7a44d148dd --- /dev/null +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl @@ -0,0 +1,147 @@ +%%-------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. 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(netconfc_remote_SUITE). +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/src/ct_netconfc.hrl"). +-include("netconfc_test_lib.hrl"). + +-compile(export_all). + +suite() -> + [{ct_hooks, [{cth_conn_log,[{ct_netconfc,[{log_type,html}]}]}]}]. + +all() -> + case os:find_executable("ssh") of + false -> + {skip, "SSH not installed on host"}; + _ -> + [remote_crash + ] + end. + +groups() -> + []. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +init_per_testcase(Case, Config) -> + stop_node(Case), + Dog = test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + +end_per_testcase(Case, Config) -> + stop_node(Case), + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +stop_node(Case) -> + {ok,Host} = inet:gethostname(), + Node = list_to_atom("nc_" ++ atom_to_list(Case)++ "@" ++ Host), + rpc:call(Node,erlang,halt,[]). + + +init_per_suite(Config) -> + case {crypto:start(),ssh:start()} of + {ok,ok} -> + {ok, _} = netconfc_test_lib:get_id_keys(Config), + netconfc_test_lib:make_dsa_files(Config), + Config; + _ -> + {skip, "Crypto and/or SSH could not be started locally!"} + end. + +end_per_suite(Config) -> + ssh:stop(), + crypto:stop(), + netconfc_test_lib:remove_id_keys(Config), + Config. + +%% This test case is related to seq12645 +%% Running the netconf server in a remote node, test that the client +%% process terminates if the remote node goes down. +remote_crash(Config) -> + {ok,Node} = ct_slave:start(nc_remote_crash), + Pa = filename:dirname(code:which(?NS)), + true = rpc:call(Node,code,add_patha,[Pa]), + + case {rpc:call(Node,crypto,start,[]),rpc:call(Node,ssh,start,[])} of + {ok,ok} -> + Server = rpc:call(Node,?NS,start,[?config(data_dir,Config)]), + remote_crash(Node,Config); + _ -> + {skip, "Crypto and/or SSH could not be started remote!"} + end. + +remote_crash(Node,Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(Node,DataDir), + + ns(Node,expect_reply,[{'create-subscription',[stream]},ok]), + ?ok = ct_netconfc:create_subscription(Client), + + true = erlang:is_process_alive(Client), + Ref = erlang:monitor(process,Client), + rpc:call(Node,erlang,halt,[]), % take the node down as brutally as possible + receive {'DOWN',Ref,process,Client,_} -> + ok + after 10000 -> + ct:fail(client_still_alive) + end. + +%%%----------------------------------------------------------------- + +break(_Config) -> + test_server:break("break test case"). + +%%%----------------------------------------------------------------- +%% Open a netconf session which is not specified in a config file +open_success(Node,Dir) -> + open_success(Node,Dir,[]). + +%% Open a netconf session which is not specified in a config file, and +%% give som extra options in addition to the test defaults. +open_success(Node,Dir,ExtraOpts) when is_list(Dir), is_list(ExtraOpts) -> + ns(Node,hello,[1]), % tell server to send hello with session id 1 + ns(Node,expect,[hello]), % tell server to expect a hello message from client + open(Dir,ExtraOpts); + +%% Open a named netconf session which is not specified in a config file +open_success(Node,KeyOrName,Dir) when is_atom(KeyOrName), is_list(Dir) -> + ns(Node,hello,[1]), + ns(Node,expect,[hello]), + ct_netconfc:open(KeyOrName,?DEFAULT_SSH_OPTS(Dir)). + +open(Dir) -> + open(Dir,[]). +open(Dir,ExtraOpts) -> + Opts = lists:ukeymerge(1,lists:keysort(1,ExtraOpts), + lists:keysort(1,?DEFAULT_SSH_OPTS(Dir))), + ct_netconfc:open(Opts). + +%%%----------------------------------------------------------------- +%%% Call server on remote node +ns(Node,Func,Args) -> + rpc:call(Node,?NS,Func,Args). + diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_test_lib.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_test_lib.erl new file mode 100644 index 0000000000..e058bc7600 --- /dev/null +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_test_lib.erl @@ -0,0 +1,166 @@ +-module(netconfc_test_lib). + +-export([get_id_keys/1, remove_id_keys/1, make_dsa_files/1]). +-include_lib("common_test/include/ct.hrl"). +-include_lib("public_key/include/public_key.hrl"). + +%%%----------------------------------------------------------------- +%%% BEGIN SSH key management +%% copy private keys to given dir from ~/.ssh +get_id_keys(Config) -> + DstDir = ?config(priv_dir, Config), + SrcDir = filename:join(os:getenv("HOME"), ".ssh"), + RsaOk = copyfile(SrcDir, DstDir, "id_rsa"), + DsaOk = copyfile(SrcDir, DstDir, "id_dsa"), + case {RsaOk, DsaOk} of + {{ok, _}, {ok, _}} -> {ok, both}; + {{ok, _}, _} -> {ok, rsa}; + {_, {ok, _}} -> {ok, dsa}; + {Error, _} -> Error + end. + +%% Remove later on. Use make_dsa_files instead. +remove_id_keys(Config) -> + Dir = ?config(priv_dir, Config), + file:delete(filename:join(Dir, "id_rsa")), + file:delete(filename:join(Dir, "id_dsa")). + + +make_dsa_files(Config) -> + make_dsa_files(Config, rfc4716_public_key). +make_dsa_files(Config, Type) -> + {DSA, EncodedKey} = gen_dsa(128, 20), + PKey = DSA#'DSAPrivateKey'.y, + P = DSA#'DSAPrivateKey'.p, + Q = DSA#'DSAPrivateKey'.q, + G = DSA#'DSAPrivateKey'.g, + Dss = #'Dss-Parms'{p=P, q=Q, g=G}, + {ok, Hostname} = inet:gethostname(), + {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet), + IP = lists:concat([A, ".", B, ".", C, ".", D]), + Attributes = [], % Could be [{comment,"user@" ++ Hostname}], + HostNames = [{hostnames,[IP, IP]}], + PublicKey = [{{PKey, Dss}, Attributes}], + KnownHosts = [{{PKey, Dss}, HostNames}], + + KnownHostsEnc = public_key:ssh_encode(KnownHosts, known_hosts), + KnownHosts = public_key:ssh_decode(KnownHostsEnc, known_hosts), + + PublicKeyEnc = public_key:ssh_encode(PublicKey, Type), + + SystemTmpDir = ?config(data_dir, Config), + filelib:ensure_dir(SystemTmpDir), + file:make_dir(SystemTmpDir), + + DSAFile = filename:join(SystemTmpDir, "ssh_host_dsa_key.pub"), + file:delete(DSAFile), + + DSAPrivateFile = filename:join(SystemTmpDir, "ssh_host_dsa_key"), + file:delete(DSAPrivateFile), + + KHFile = filename:join(SystemTmpDir, "known_hosts"), + file:delete(KHFile), + + PemBin = public_key:pem_encode([EncodedKey]), + + file:write_file(DSAFile, PublicKeyEnc), + file:write_file(KHFile, KnownHostsEnc), + file:write_file(DSAPrivateFile, PemBin), + ok. + + +%%-------------------------------------------------------------------- +%% @doc Creates a dsa key (OBS: for testing only) +%% the sizes are in bytes +%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()} +%% @end +%%-------------------------------------------------------------------- +gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) -> + Key = gen_dsa2(LSize, NSize), + {Key, encode_key(Key)}. + +encode_key(Key = #'DSAPrivateKey'{}) -> + Der = public_key:der_encode('DSAPrivateKey', Key), + {'DSAPrivateKey', Der, not_encrypted}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% DSA key generation (OBS: for testing only) +%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm +%% and the fips_186-3.pdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +gen_dsa2(LSize, NSize) -> + Q = prime(NSize), %% Choose N-bit prime Q + X0 = prime(LSize), + P0 = prime((LSize div 2) +1), + + %% Choose L-bit prime modulus P such that p-1 is a multiple of q. + case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of + error -> + gen_dsa2(LSize, NSize); + P -> + G = crypto:mod_pow(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q. + %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used. + + X = prime(20), %% Choose x by some random method, where 0 < x < q. + Y = crypto:mod_pow(G, X, P), %% Calculate y = g^x mod p. + + #'DSAPrivateKey'{version=0, p = P, q = Q, + g = crypto:bytes_to_integer(G), y = crypto:bytes_to_integer(Y), x = X} + end. + +%% See fips_186-3.pdf +dsa_search(T, P0, Q, Iter) when Iter > 0 -> + P = 2*T*Q*P0 + 1, + case is_prime(P, 50) of + true -> P; + false -> dsa_search(T+1, P0, Q, Iter-1) + end; +dsa_search(_,_,_,_) -> + error. + + +%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +prime(ByteSize) -> + Rand = odd_rand(ByteSize), + prime_odd(Rand, 0). + +prime_odd(Rand, N) -> + case is_prime(Rand, 50) of + true -> + Rand; + false -> + prime_odd(Rand+2, N+1) + end. + +%% see http://en.wikipedia.org/wiki/Fermat_primality_test +is_prime(_, 0) -> true; +is_prime(Candidate, Test) -> + CoPrime = odd_rand(10000, Candidate), + Result = crypto:mod_pow(CoPrime, Candidate, Candidate) , + is_prime(CoPrime, crypto:bytes_to_integer(Result), Candidate, Test). + +is_prime(CoPrime, CoPrime, Candidate, Test) -> + is_prime(Candidate, Test-1); +is_prime(_,_,_,_) -> + false. + +odd_rand(Size) -> + Min = 1 bsl (Size*8-1), + Max = (1 bsl (Size*8))-1, + odd_rand(Min, Max). + +odd_rand(Min,Max) -> + Rand = crypto:rand_uniform(Min,Max), + case Rand rem 2 of + 0 -> + Rand + 1; + _ -> + Rand + end. + +copyfile(SrcDir, DstDir, Fn) -> + file:copy(filename:join(SrcDir, Fn), + filename:join(DstDir, Fn)). + +%%% END SSH key management +%%%----------------------------------------------------------------- diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_test_lib.hrl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_test_lib.hrl new file mode 100644 index 0000000000..dcaad5ba93 --- /dev/null +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_test_lib.hrl @@ -0,0 +1,14 @@ +%% Default timetrap timeout (set in init_per_testcase). +-define(default_timeout, ?t:minutes(1)). + +-define(NS,ns). % netconf server module +-define(LOCALHOST, "127.0.0.1"). +-define(SSH_PORT, 2060). + +-define(DEFAULT_SSH_OPTS,[{ssh,?LOCALHOST}, + {port,?SSH_PORT}, + {user,"xxx"}, + {password,"xxx"}]). +-define(DEFAULT_SSH_OPTS(Dir), ?DEFAULT_SSH_OPTS++[{user_dir,Dir}]). + +-define(ok,ok). diff --git a/lib/common_test/test/ct_snmp_SUITE_data/snmp.cfg b/lib/common_test/test/ct_snmp_SUITE_data/snmp.cfg index 895e097de6..7ff356e49a 100644 --- a/lib/common_test/test/ct_snmp_SUITE_data/snmp.cfg +++ b/lib/common_test/test/ct_snmp_SUITE_data/snmp.cfg @@ -22,23 +22,23 @@ {agent_target_param_def,{data_dir_file,"target_params.conf"}}, {agent_vacm,{data_dir_file,"vacm.conf"}}]}. {snmp_app1,[{manager, [{config, [{verbosity, silence}]}, - {server,[{verbosity,silence}]}, - {net_if,[{verbosity,silence}]}, + {server,[{verbosity,log}]}, + {net_if,[{verbosity,log}]}, {versions,[v2]} ]}, {agent, [{config, [{verbosity, silence}]}, - {net_if,[{verbosity,silence}]}, + {net_if,[{verbosity,log}]}, {mib_server,[{verbosity,silence}]}, {local_db,[{verbosity,silence}]}, - {agent_verbosity,silence} + {agent_verbosity,log} ]}]}. {snmp_app2,[{manager, [{config, [{verbosity, silence}]}, - {server,[{verbosity,silence}]}, - {net_if,[{verbosity,silence}]} + {server,[{verbosity,log}]}, + {net_if,[{verbosity,log}]} ]}, {agent, [{config, [{verbosity, silence}]}, - {net_if,[{verbosity,silence}]}, + {net_if,[{verbosity,log}]}, {mib_server,[{verbosity,silence}]}, {local_db,[{verbosity,silence}]}, - {agent_verbosity,silence} + {agent_verbosity,log} ]}]}. diff --git a/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl b/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl index 16b2b5690c..e20832e1e7 100644 --- a/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl +++ b/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2014. 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 @@ -288,6 +288,9 @@ override_usm(Config) -> %% Check that usm.conf is overwritten {ok,MyUsm} = snmpa_conf:read_usm_config(DataDir), {ok,UsedUsm} = snmpa_conf:read_usm_config(ConfDir), + ct:pal( + "MyUsm = ~p~nUsedUsm = ~p", + [MyUsm, UsedUsm]), true = (MyUsm == UsedUsm), %% Check that the usm user is actually configured... @@ -304,6 +307,9 @@ override_standard(Config) -> %% Check that standard.conf is overwritten {ok,MyStandard} = snmpa_conf:read_standard_config(DataDir), {ok,UsedStandard} = snmpa_conf:read_standard_config(ConfDir), + ct:pal( + "MyStandard = ~p~nUsedStandard = ~p", + [MyStandard, UsedStandard]), true = (MyStandard == UsedStandard), %% Check that the values from standard.conf is actually configured... @@ -319,6 +325,9 @@ override_context(Config) -> %% Check that context.conf is overwritten {ok,MyContext} = snmpa_conf:read_context_config(DataDir), {ok,UsedContext} = snmpa_conf:read_context_config(ConfDir), + ct:pal( + "MyContext = ~p~nUsedContext = ~p", + [MyContext, UsedContext]), true = (MyContext == UsedContext), ok. @@ -330,6 +339,9 @@ override_community(Config) -> %% Check that community.conf is overwritten {ok,MyCommunity} = snmpa_conf:read_community_config(DataDir), {ok,UsedCommunity} = snmpa_conf:read_community_config(ConfDir), + ct:pal( + "MyCommunity = ~p~nUsedCommunity = ~p", + [MyCommunity, UsedCommunity]), true = (MyCommunity == UsedCommunity), ok. @@ -341,6 +353,9 @@ override_notify(Config) -> %% Check that notify.conf is overwritten {ok,MyNotify} = snmpa_conf:read_notify_config(DataDir), {ok,UsedNotify} = snmpa_conf:read_notify_config(ConfDir), + ct:pal( + "MyNotify = ~p~nUsedNotify = ~p", + [MyNotify, UsedNotify]), true = (MyNotify == UsedNotify), ok. @@ -352,6 +367,9 @@ override_target_addr(Config) -> %% Check that target_addr.conf is overwritten {ok,MyTargetAddr} = snmpa_conf:read_target_addr_config(DataDir), {ok,UsedTargetAddr} = snmpa_conf:read_target_addr_config(ConfDir), + ct:pal( + "MyTargetAddr = ~p~nUsedTargetAddr = ~p", + [MyTargetAddr, UsedTargetAddr]), true = (MyTargetAddr == UsedTargetAddr), ok. @@ -363,6 +381,9 @@ override_target_params(Config) -> %% Check that target_params.conf is overwritten {ok,MyTargetParams} = snmpa_conf:read_target_params_config(DataDir), {ok,UsedTargetParams} = snmpa_conf:read_target_params_config(ConfDir), + ct:pal( + "MyTargetParams = ~p~nUsedTargetParams = ~p", + [MyTargetParams, UsedTargetParams]), true = (MyTargetParams == UsedTargetParams), ok. @@ -374,6 +395,9 @@ override_vacm(Config) -> %% Check that vacm.conf is overwritten {ok,MyVacm} = snmpa_conf:read_vacm_config(DataDir), {ok,UsedVacm} = snmpa_conf:read_vacm_config(ConfDir), + ct:pal( + "MyVacm = ~p~nUsedVacm = ~p", + [MyVacm, UsedVacm]), true = (MyVacm == UsedVacm), ok. diff --git a/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE_data/target_addr.conf b/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE_data/target_addr.conf index d02672a074..d3ce2fa60e 100644 --- a/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE_data/target_addr.conf +++ b/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE_data/target_addr.conf @@ -1,2 +1,2 @@ -{"target1", snmpUDPDomain, [147,214,122,73], 5000, 1500, 3, "std_trap", "target_v3", "", [], 2048}. -{"target2", snmpUDPDomain, [147,214,122,73], 5000, 1500, 3, "std_inform", "target_v3", "", [], 2048}. +{"target1", snmpUDPDomain, {[147,214,122,73], 5000}, 1500, 3, "std_trap", "target_v3", "", [], 2048}. +{"target2", snmpUDPDomain, {[147,214,122,73], 5000}, 1500, 3, "std_inform", "target_v3", "", [], 2048}. diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk index f8a5aab686..def8a6a6f4 100644 --- a/lib/common_test/vsn.mk +++ b/lib/common_test/vsn.mk @@ -1 +1 @@ -COMMON_TEST_VSN = 1.8 +COMMON_TEST_VSN = 1.8.1 diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index a0f2e617cb..55e9661d7d 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -31,6 +31,29 @@ <p>This document describes the changes made to the Compiler application.</p> +<section><title>Compiler 5.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A Dialyzer crash involving analysis of Map types has now + been fixed.</p> + <p> + Own Id: OTP-11947</p> + </item> + <item> + <p>The compiler would fail to compile a file with a + latin-1 character in the false branch of an <c>-ifdef</c> + or <c>-indef</c>.</p> + <p> + Own Id: OTP-11987</p> + </item> + </list> + </section> + +</section> + <section><title>Compiler 5.0</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -211,10 +234,10 @@ "hello"}, % add new associations</c></item> <item><c>#{ "hi" := V1, a := V2, b := V3} = M2. % match keys with values</c></item> </taglist></p> - <p> - For information on how to use Maps please see the - <seealso marker="doc/reference_manual:maps">Reference - Manual</seealso>.</p> + <p> + For information on how to use Maps please see Map Expressions in the + <seealso marker="doc/reference_manual:expressions#map_expressions"> + Reference Manual</seealso>.</p> <p> The current implementation is without the following features: <taglist> <item>No variable keys</item> diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index 761ae8409c..6410b73941 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -33,12 +33,15 @@ -include("../include/erl_bits.hrl"). +-type fa() :: {atom(), arity()}. + -record(expand, {module=[], %Module name exports=[], %Exports imports=[], %Imports compile=[], %Compile flags attributes=[], %Attributes callbacks=[], %Callbacks + optional_callbacks=[] :: [fa()], %Optional callbacks defined, %Defined functions (gb_set) vcount=0, %Variable counter func=[], %Current function @@ -99,7 +102,21 @@ define_functions(Forms, #expand{defined=Predef}=St) -> module_attrs(#expand{attributes=Attributes}=St) -> Attrs = [{attribute,Line,Name,Val} || {Name,Line,Val} <- Attributes], Callbacks = [Callback || {_,_,callback,_}=Callback <- Attrs], - {Attrs,St#expand{callbacks=Callbacks}}. + OptionalCallbacks = get_optional_callbacks(Attrs), + {Attrs,St#expand{callbacks=Callbacks, + optional_callbacks=OptionalCallbacks}}. + +get_optional_callbacks(Attrs) -> + L = [O || + {attribute, _, optional_callbacks, O} <- Attrs, + is_fa_list(O)], + lists:append(L). + +is_fa_list([{FuncName, Arity}|L]) + when is_atom(FuncName), is_integer(Arity), Arity >= 0 -> + is_fa_list(L); +is_fa_list([]) -> true; +is_fa_list(_) -> false. module_predef_funcs(St) -> {Mpf1,St1}=module_predef_func_beh_info(St), @@ -108,19 +125,24 @@ module_predef_funcs(St) -> module_predef_func_beh_info(#expand{callbacks=[]}=St) -> {[], St}; -module_predef_func_beh_info(#expand{callbacks=Callbacks,defined=Defined, +module_predef_func_beh_info(#expand{callbacks=Callbacks, + optional_callbacks=OptionalCallbacks, + defined=Defined, exports=Exports}=St) -> PreDef=[{behaviour_info,1}], PreExp=PreDef, - {[gen_beh_info(Callbacks)], + {[gen_beh_info(Callbacks, OptionalCallbacks)], St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef), Defined), exports=union(from_list(PreExp), Exports)}}. -gen_beh_info(Callbacks) -> +gen_beh_info(Callbacks, OptionalCallbacks) -> List = make_list(Callbacks), + OptionalList = make_optional_list(OptionalCallbacks), {function,0,behaviour_info,1, [{clause,0,[{atom,0,callbacks}],[], - [List]}]}. + [List]}, + {clause,0,[{atom,0,optional_callbacks}],[], + [OptionalList]}]}. make_list([]) -> {nil,0}; make_list([{_,_,_,[{{Name,Arity},_}]}|Rest]) -> @@ -130,6 +152,14 @@ make_list([{_,_,_,[{{Name,Arity},_}]}|Rest]) -> {integer,0,Arity}]}, make_list(Rest)}. +make_optional_list([]) -> {nil,0}; +make_optional_list([{Name,Arity}|Rest]) -> + {cons,0, + {tuple,0, + [{atom,0,Name}, + {integer,0,Arity}]}, + make_optional_list(Rest)}. + module_predef_funcs_mod_info(St) -> PreDef = [{module_info,0},{module_info,1}], PreExp = PreDef, diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 8c18f6a9f7..83cf76f241 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -82,6 +82,8 @@ -include("core_parse.hrl"). +-define(REC_OFFSET, 100000000). % Also in erl_expand_records. + %% Internal core expressions and help functions. %% N.B. annotations fields in place as normal Core expressions. @@ -501,7 +503,7 @@ expr({cons,L,H0,T0}, St0) -> {H1,Hps,St1} = safe(H0, St0), {T1,Tps,St2} = safe(T0, St1), A = lineno_anno(L, St2), - {ann_c_cons(A, H1, T1),Hps ++ Tps,St2}; + {annotate_cons(A, H1, T1, St2),Hps ++ Tps,St2}; expr({lc,L,E,Qs0}, St0) -> {Qs1,St1} = preprocess_quals(L, Qs0, St0), lc_tq(L, E, Qs1, #c_literal{anno=lineno_anno(L, St1),val=[]}, St1); @@ -509,8 +511,8 @@ expr({bc,L,E,Qs}, St) -> bc_tq(L, E, Qs, {nil,L}, St); expr({tuple,L,Es0}, St0) -> {Es1,Eps,St1} = safe_list(Es0, St0), - A = lineno_anno(L, St1), - {ann_c_tuple(A, Es1),Eps,St1}; + A = record_anno(L, St1), + {annotate_tuple(A, Es1, St1),Eps,St1}; expr({map,L,Es0}, St0) -> % erl_lint should make sure only #{ K => V } are allowed % in map construction. @@ -1557,9 +1559,9 @@ pattern({atom,L,A}, St) -> #c_literal{anno=lineno_anno(L, St),val=A}; pattern({string,L,S}, St) -> #c_literal{anno=lineno_anno(L, St),val=S}; pattern({nil,L}, St) -> #c_literal{anno=lineno_anno(L, St),val=[]}; pattern({cons,L,H,T}, St) -> - ann_c_cons(lineno_anno(L, St), pattern(H, St), pattern(T, St)); + annotate_cons(lineno_anno(L, St), pattern(H, St), pattern(T, St), St); pattern({tuple,L,Ps}, St) -> - ann_c_tuple(lineno_anno(L, St), pattern_list(Ps, St)); + annotate_tuple(record_anno(L, St), pattern_list(Ps, St), St); pattern({map,L,Ps}, St) -> #c_map{anno=lineno_anno(L, St), es=pattern_map_pairs(Ps, St)}; pattern({bin,L,Ps}, St) -> @@ -1721,6 +1723,26 @@ fail_clause(Pats, Anno, Arg) -> body=[#iprimop{anno=#a{anno=Anno},name=#c_literal{val=match_fail}, args=[Arg]}]}. +annotate_tuple(A, Es, St) -> + case member(dialyzer, St#core.opts) of + true -> + %% Do not coalesce constant tuple elements. A Hack. + Node = cerl:ann_c_tuple(A, [cerl:c_var(any)]), + cerl:update_c_tuple_skel(Node, Es); + false -> + ann_c_tuple(A, Es) + end. + +annotate_cons(A, H, T, St) -> + case member(dialyzer, St#core.opts) of + true -> + %% Do not coalesce constant conses. A Hack. + Node= cerl:ann_c_cons(A, cerl:c_var(any), cerl:c_var(any)), + cerl:update_c_cons_skel(Node, H, T); + false -> + ann_c_cons(A, H, T) + end. + ubody(B, St) -> uexpr(B, [], St). %% uclauses([Lclause], [KnownVar], State) -> {[Lclause],State}. @@ -2238,6 +2260,23 @@ bitstr_vars(Segs, Vs) -> lit_vars(V, lit_vars(S, Vs0)) end, Vs, Segs). +record_anno(L, St) when L >= ?REC_OFFSET -> + case member(dialyzer, St#core.opts) of + true -> + [record | lineno_anno(L - ?REC_OFFSET, St)]; + false -> + lineno_anno(L, St) + end; +record_anno(L, St) when L < -?REC_OFFSET -> + case member(dialyzer, St#core.opts) of + true -> + [record | lineno_anno(L + ?REC_OFFSET, St)]; + false -> + lineno_anno(L, St) + end; +record_anno(L, St) -> + lineno_anno(L, St). + lineno_anno(L, St) -> {line, Line} = erl_parse:get_attribute(L, line), if diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl index ad4ad91f74..0637041873 100644 --- a/lib/compiler/test/warnings_SUITE.erl +++ b/lib/compiler/test/warnings_SUITE.erl @@ -662,6 +662,20 @@ latin1_fallback(Conf) when is_list(Conf) -> {warnings,[{1,compile,reparsing_invalid_unicode}]} }], [] = run(Conf, Ts2), + + Ts3 = [{latin1_fallback3, + %% Test that the compiler fall backs to latin-1 with + %% a warning if a file has no encoding and does not + %% contain correct UTF-8 sequences. + <<"-ifdef(NOTDEFINED). + t(_) -> \"",246,"\"; + t(x) -> ok. + -endif. + ">>, + [], + {warnings,[{2,compile,reparsing_invalid_unicode}]}}], + [] = run(Conf, Ts3), + ok. %%% diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index c0c3d56472..0a86352f40 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 5.0 +COMPILER_VSN = 5.0.1 diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 948093d69c..e55a03d26a 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -507,6 +507,15 @@ static int init_ose_crypto() { #endif #ifdef HAVE_DYNAMIC_CRYPTO_LIB + +# if defined(DEBUG) +static char crypto_callback_name[] = "crypto_callback.debug"; +# elif defined(VALGRIND) +static char crypto_callback_name[] = "crypto_callback.valgrind"; +# else +static char crypto_callback_name[] = "crypto_callback"; +# endif + static int change_basename(ErlNifBinary* bin, char* buf, int bufsz, const char* newfile) { int i; @@ -613,7 +622,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) #ifdef HAVE_DYNAMIC_CRYPTO_LIB { void* handle; - if (!change_basename(&lib_bin, lib_buf, sizeof(lib_buf), "crypto_callback")) { + if (!change_basename(&lib_bin, lib_buf, sizeof(lib_buf), crypto_callback_name)) { return 0; } if (!(handle = enif_dlopen(lib_buf, &error_handler, NULL))) { @@ -2897,8 +2906,8 @@ static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ /* a + (u * x) */ bn_exp2 = BN_new(); - BN_mod_mul(bn_result, bn_u, bn_exponent, bn_prime, bn_ctx); - BN_mod_add(bn_exp2, bn_a, bn_result, bn_prime, bn_ctx); + BN_mul(bn_result, bn_u, bn_exponent, bn_ctx); + BN_add(bn_exp2, bn_a, bn_result); /* (B - (k * g^x)) ^ (a + (u * x)) % N */ BN_mod_exp(bn_result, bn_base, bn_exp2, bn_prime, bn_ctx); @@ -3244,6 +3253,7 @@ out: if (bn_order) BN_free(bn_order); if (cofactor) BN_free(cofactor); if (group) EC_GROUP_free(group); + if (point) EC_POINT_free(point); return key; } @@ -3406,8 +3416,11 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM EC_KEY_free(key); return enif_make_tuple2(env, pub_key, priv_key); } - else + else { + if (key) + EC_KEY_free(key); return enif_make_badarg(env); + } #else return atom_notsup; #endif diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index a08dcec463..b4c175ae43 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -107,8 +107,6 @@ static INLINE void locking(int mode, ErlNifRWLock* lock) static void locking_function(int mode, int n, const char *file, int line) { - ASSERT(n>=0 && n<CRYPTO_num_locks()); - locking(mode, lock_vec[n]); } diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index 34f2e3c469..1bd2034b93 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -30,6 +30,42 @@ </header> <p>This document describes the changes made to the Crypto application.</p> +<section><title>Crypto 3.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix memory leak in <c>crypto:hmac_init/upgrade/final</c> + functions for all data and in <c>crypto:hmac/3/4</c> for + data larger than 20000 bytes. Bug exists since OTP 17.0.</p> + <p> + Own Id: OTP-11953</p> + </item> + <item> + <p> + Fix memory leak in <c>crypto</c> for elliptic curve.</p> + <p> + Own Id: OTP-11999</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add <c>aes_cfb8</c> cypher to <c>crypto:block_encrypt</c> + and <c>block_decrypt</c>.</p> + <p> + Own Id: OTP-11911</p> + </item> + </list> + </section> + +</section> + <section><title>Crypto 3.3</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 479c947029..03aa3964a5 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -690,7 +690,7 @@ group_config(ecdsa = Type, Config) -> SignVerify = [{Type, sha, Public, Private, Msg}], [{sign_verify, SignVerify} | Config]; group_config(srp, Config) -> - GenerateCompute = [srp3(), srp6(), srp6a()], + GenerateCompute = [srp3(), srp6(), srp6a(), srp6a_smaller_prime()], [{generate_compute, GenerateCompute} | Config]; group_config(ecdh, Config) -> Compute = ecdh(), @@ -1496,6 +1496,32 @@ srp6() -> ClientPublic = crypto:mod_pow(Generator, ClientPrivate, Prime), srp(ClientPrivate, Generator, Prime, Version, Verifier, ServerPublic, ServerPrivate, UserPassHash, Scrambler, SessionKey). + +srp6a_smaller_prime() -> + Username = <<"alice">>, + Password = <<"password123">>, + Salt = <<"mystrongsalt">>, + Prime = hexstr2bin("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"), + Generator = <<7>>, + Version = '6a', + Scrambler = hexstr2bin("18DE4A002AD05EF464B19AE2B6929F9B1319C7AA"), + Verifier = hexstr2bin("867401D5DE10964768184EAF246B322760C847604075FA66A4423907" + "8428BCA5"), + ClientPrivate = hexstr2bin("C49F832EE8D67ECF9E7F2785EB0622D8B3FE2344C00F96E1AEF4103C" + "A44D51F9"), + ServerPrivate = hexstr2bin("6C78CCEAAEC15E69068A87795B2A20ED7B45CFC5A254EBE2F17F144A" + "4D99DB18"), + ClientPublic = hexstr2bin("2452A57166BBBF690DB77539BAF9C57CD1ED99D5AA15ED925AD9B5C3" + "64BBEDFF"), + ServerPublic = hexstr2bin("2C0464DE84B91E4963A3546CAC0EFE55F31F49208C3F0AD7EE55F444" + "8F38BA7F"), + + SessionKey = hexstr2bin("65581B2302580BD26F522A5A421CF969B9CCBCE4051196B034A2A9D22065D848"), + UserPassHash = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, Password])]), + Verifier = crypto:mod_pow(Generator, UserPassHash, Prime), + ClientPublic = crypto:mod_pow(Generator, ClientPrivate, Prime), + srp(ClientPrivate, Generator, Prime, Version, Verifier, ServerPublic, ServerPrivate, UserPassHash, Scrambler, SessionKey). + srp6a() -> Username = <<"alice">>, Password = <<"password123">>, diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index a2bd6f851a..b2bb1d7dfb 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 3.3 +CRYPTO_VSN = 3.4 diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml index 8832f99fc3..c1ba1eec6b 100644 --- a/lib/debugger/doc/src/notes.xml +++ b/lib/debugger/doc/src/notes.xml @@ -32,6 +32,24 @@ <p>This document describes the changes made to the Debugger application.</p> +<section><title>Debugger 4.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix evaluation of map updates in the debugger and + erl_eval</p> + <p> + Reported-by: José Valim</p> + <p> + Own Id: OTP-11922</p> + </item> + </list> + </section> + +</section> + <section><title>Debugger 4.0</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk index cd107599e9..33481a1537 100644 --- a/lib/debugger/vsn.mk +++ b/lib/debugger/vsn.mk @@ -1 +1 @@ -DEBUGGER_VSN = 4.0 +DEBUGGER_VSN = 4.0.1 diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml index 3de60b2f7a..4e26a9e95e 100644 --- a/lib/dialyzer/doc/src/dialyzer.xml +++ b/lib/dialyzer/doc/src/dialyzer.xml @@ -139,12 +139,7 @@ <tag><c><![CDATA[-Wwarn]]></c></tag> <item>A family of options which selectively turn on/off warnings (for help on the names of warnings use - <c><![CDATA[dialyzer -Whelp]]></c>). - Note that the options can also be given in the file with a - <c>-dialyzer({nowarn_tag, WarningTags})</c> attribute. - See <seealso - marker="doc/reference_manual:typespec#suppression">Erlang Reference - Manual</seealso> for details.</item> + <c><![CDATA[dialyzer -Whelp]]></c>).</item> <tag><c><![CDATA[--shell]]></c></tag> <item>Do not disable the Erlang shell while running the GUI.</item> <tag><c><![CDATA[--version]]></c> (or <c><![CDATA[-v]]></c>)</tag> diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index 05baa93557..bdd9c61c5c 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -31,6 +31,44 @@ <p>This document describes the changes made to the Dialyzer application.</p> +<section><title>Dialyzer 2.7.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> Fix a bug concerning opaque types. Thanks to Shayan + Pooya for pointing out the bug.</p> + <p> + Own Id: OTP-11869</p> + </item> + <item> + <p> A bug where Dialyzer failed to handle typed records + with fields containing remote types has been fixed. + Thanks to Erik Søe Sørensen for reporting the bug. </p> + <p> + Own Id: OTP-11918</p> + </item> + <item> + <p> Make sure that only literal records are checked + against the types of record definitions. Until now the + elements of tuples have been checked against record field + types if the tag och size of the tuple matches the record + definition, often with surprising results. </p> + <p> + Own Id: OTP-11935 Aux Id: seq12590 </p> + </item> + <item> + <p> + A Dialyzer crash involving analysis of Map types has now + been fixed.</p> + <p> + Own Id: OTP-11947</p> + </item> + </list> + </section> + +</section> + <section><title>Dialyzer 2.7</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -167,9 +205,9 @@ "hi" := V1, a := V2, b := V3} = M2. % match keys with values</c></item> </taglist></p> <p> - For information on how to use Maps please see the - <seealso marker="doc/reference_manual:maps">Reference - Manual</seealso>.</p> + For information on how to use Maps please see Map Expressions in the + <seealso marker="doc/reference_manual:expressions#map_expressions"> + Reference Manual</seealso>.</p> <p> The current implementation is without the following features: <taglist> <item>No variable keys</item> diff --git a/lib/dialyzer/src/dialyzer_behaviours.erl b/lib/dialyzer/src/dialyzer_behaviours.erl index 1d458b49fc..bbedd3201e 100644 --- a/lib/dialyzer/src/dialyzer_behaviours.erl +++ b/lib/dialyzer/src/dialyzer_behaviours.erl @@ -102,14 +102,18 @@ check_all_callbacks(Module, Behaviour, [Cb|Rest], #state{plt = Plt, codeserver = Codeserver, records = Records} = State, Acc) -> {{Behaviour, Function, Arity}, - {{_BehFile, _BehLine}, Callback}} = Cb, + {{_BehFile, _BehLine}, Callback, Xtra}} = Cb, CbMFA = {Module, Function, Arity}, CbReturnType = dialyzer_contracts:get_contract_return(Callback), CbArgTypes = dialyzer_contracts:get_contract_args(Callback), Acc0 = Acc, Acc1 = case dialyzer_plt:lookup(Plt, CbMFA) of - 'none' -> [{callback_missing, [Behaviour, Function, Arity]}|Acc0]; + 'none' -> + case lists:member(optional_callback, Xtra) of + true -> Acc0; + false -> [{callback_missing, [Behaviour, Function, Arity]}|Acc0] + end; {'value', RetArgTypes} -> Acc00 = Acc0, {ReturnType, ArgTypes} = RetArgTypes, @@ -137,7 +141,7 @@ check_all_callbacks(Module, Behaviour, [Cb|Rest], Acc2 = case dialyzer_codeserver:lookup_mfa_contract(CbMFA, Codeserver) of 'error' -> Acc1; - {ok, {{File, Line}, Contract}} -> + {ok, {{File, Line}, Contract, _Xtra}} -> Acc10 = Acc1, SpecReturnType0 = dialyzer_contracts:get_contract_return(Contract), SpecArgTypes0 = dialyzer_contracts:get_contract_args(Contract), diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl index aab3d6add6..593e71f30b 100644 --- a/lib/dialyzer/src/dialyzer_codeserver.erl +++ b/lib/dialyzer/src/dialyzer_codeserver.erl @@ -278,10 +278,10 @@ lookup_mod_contracts(Mod, #codeserver{contracts = ContDict}) case ets_dict_find(Mod, ContDict) of error -> dict:new(); {ok, Keys} -> - dict:from_list([get_contract_pair(Key, ContDict)|| Key <- Keys]) + dict:from_list([get_file_contract(Key, ContDict)|| Key <- Keys]) end. -get_contract_pair(Key, ContDict) -> +get_file_contract(Key, ContDict) -> {Key, ets:lookup_element(ContDict, Key, 2)}. -spec lookup_mfa_contract(mfa(), codeserver()) -> diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl index 1d2dfc7b2d..3aa5a1779c 100644 --- a/lib/dialyzer/src/dialyzer_contracts.erl +++ b/lib/dialyzer/src/dialyzer_contracts.erl @@ -45,7 +45,7 @@ %% Types used in other parts of the system below %%----------------------------------------------------------------------- --type file_contract() :: {file_line(), #contract{}}. +-type file_contract() :: {file_line(), #contract{}, Extra :: [_]}. -type plt_contracts() :: [{mfa(), #contract{}}]. % actually, an orddict() @@ -148,10 +148,10 @@ process_contract_remote_types(CodeServer) -> ExpTypes = dialyzer_codeserver:get_exported_types(CodeServer), RecordDict = dialyzer_codeserver:get_records(CodeServer), ContractFun = - fun({_M, _F, _A}, {File, #tmp_contract{contract_funs = CFuns, forms = Forms}}) -> + fun({_M, _F, _A}, {File, #tmp_contract{contract_funs = CFuns, forms = Forms}, Xtra}) -> NewCs = [CFun(ExpTypes, RecordDict) || CFun <- CFuns], Args = general_domain(NewCs), - {File, #contract{contracts = NewCs, args = Args, forms = Forms}} + {File, #contract{contracts = NewCs, args = Args, forms = Forms}, Xtra} end, ModuleFun = fun(_ModuleName, ContractDict) -> @@ -177,7 +177,7 @@ check_contracts(Contracts, Callgraph, FunTypes, FindOpaques) -> case dialyzer_callgraph:lookup_name(Label, Callgraph) of {ok, {M,F,A} = MFA} -> case orddict:find(MFA, Contracts) of - {ok, {_FileLine, Contract}} -> + {ok, {_FileLine, Contract, _Xtra}} -> Opaques = FindOpaques(M), case check_contract(Contract, Type, Opaques) of ok -> @@ -364,7 +364,7 @@ contracts_without_fun(Contracts, AllFuns0, Callgraph) -> [warn_spec_missing_fun(MFA, Contracts) || MFA <- ErrorContractMFAs]. warn_spec_missing_fun({M, F, A} = MFA, Contracts) -> - {FileLine, _Contract} = dict:fetch(MFA, Contracts), + {FileLine, _Contract, _Xtra} = dict:fetch(MFA, Contracts), {?WARN_CONTRACT_SYNTAX, FileLine, {spec_missing_fun, [M, F, A]}}. %% This treats the "when" constraints. It will be extended, we hope. @@ -388,14 +388,16 @@ insert_constraints([], Dict) -> Dict. -type types() :: erl_types:type_table(). --spec store_tmp_contract(mfa(), file_line(), [_], contracts(), types()) -> +-type spec_data() :: {TypeSpec :: [_], Xtra:: [_]}. + +-spec store_tmp_contract(mfa(), file_line(), spec_data(), contracts(), types()) -> contracts(). -store_tmp_contract(MFA, FileLine, TypeSpec, SpecDict, RecordsDict) -> +store_tmp_contract(MFA, FileLine, {TypeSpec, Xtra}, SpecDict, RecordsDict) -> %% io:format("contract from form: ~p\n", [TypeSpec]), TmpContract = contract_from_form(TypeSpec, RecordsDict, FileLine), %% io:format("contract: ~p\n", [TmpContract]), - dict:store(MFA, {FileLine, TmpContract}, SpecDict). + dict:store(MFA, {FileLine, TmpContract, Xtra}, SpecDict). contract_from_form(Forms, RecDict, FileLine) -> {CFuns, Forms1} = contract_from_form(Forms, RecDict, FileLine, [], []), @@ -599,7 +601,7 @@ get_invalid_contract_warnings_modules([Mod|Mods], CodeServer, Plt, FindOpaques, get_invalid_contract_warnings_modules([], _CodeServer, _Plt, _FindOpaques, Acc) -> Acc. -get_invalid_contract_warnings_funs([{MFA, {FileLine, Contract}}|Left], +get_invalid_contract_warnings_funs([{MFA, {FileLine, Contract, _Xtra}}|Left], Plt, RecDict, FindOpaques, Acc) -> case dialyzer_plt:lookup(Plt, MFA) of none -> diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index e0873b17f8..9df9aca69f 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -53,7 +53,7 @@ t_bitstr/0, t_bitstr/2, t_bitstr_concat/1, t_bitstr_match/2, t_cons/0, t_cons/2, t_cons_hd/2, t_cons_tl/2, t_contains_opaque/2, - t_find_opaque_mismatch/2, t_float/0, t_from_range/2, t_from_term/1, + t_find_opaque_mismatch/3, t_float/0, t_from_range/2, t_from_term/1, t_fun/0, t_fun/2, t_fun_args/1, t_fun_args/2, t_fun_range/1, t_fun_range/2, t_integer/0, t_integers/1, t_is_any/1, t_is_atom/1, t_is_atom/2, t_is_any_atom/3, @@ -136,11 +136,10 @@ get_warnings(Tree, Plt, Callgraph, Records, NoWarnUnused) -> State1 = analyze_module(Tree, Plt, Callgraph, Records, true), - State2 = find_mismatched_record_patterns(Tree, State1), - State3 = - state__renew_warnings(state__get_warnings(State2, NoWarnUnused), State2), - State4 = state__get_race_warnings(State3), - {State4#state.warnings, state__all_fun_types(State4)}. + State2 = + state__renew_warnings(state__get_warnings(State1, NoWarnUnused), State1), + State3 = state__get_race_warnings(State2), + {State3#state.warnings, state__all_fun_types(State3)}. -spec get_fun_types(cerl:c_module(), dialyzer_plt:plt(), dialyzer_callgraph:callgraph(), @@ -277,13 +276,8 @@ traverse(Tree, Map, State) -> {State1, Map1} = lists:foldl(FoldFun, {State, Map}, Defs), traverse(Body, Map1, State1); literal -> - %% This is needed for finding records - case cerl:unfold_literal(Tree) of - Tree -> - Type = literal_type(Tree), - {State, Map, Type}; - NewTree -> traverse(NewTree, Map, State) - end; + Type = literal_type(Tree), + {State, Map, Type}; module -> handle_module(Tree, Map, State); primop -> @@ -1110,7 +1104,7 @@ handle_tuple(Tree, Map, State) -> %% Let's find out if this is a record case Elements of [Tag|Left] -> - case cerl:is_c_atom(Tag) of + case cerl:is_c_atom(Tag) andalso is_literal_record(Tree) of true -> TagVal = cerl:atom_val(Tag), case state__lookup_record(TagVal, length(Left), State1) of @@ -1240,15 +1234,10 @@ do_clause(C, Arg, ArgType0, OrigArgType, Map, State) -> false -> {State1, Map, t_none(), ArgType0}; true -> - PatString = - case ErrorType of - bind -> format_patterns(Pats); - record -> format_patterns(Pats); - opaque -> format_patterns(NewPats) - end, {Msg, Force} = case t_is_none(ArgType0) of true -> + PatString = format_patterns(Pats), PatTypes = [PatString, format_type(OrigArgType, State1)], %% See if this is covered by an earlier clause or if it %% simply cannot match @@ -1298,6 +1287,12 @@ do_clause(C, Arg, ArgType0, OrigArgType, Map, State) -> false -> true end, + PatString = + case ErrorType of + bind -> format_patterns(Pats); + record -> format_patterns(NewPats); + opaque -> format_patterns(NewPats) + end, PatTypes = case ErrorType of bind -> [PatString, format_type(ArgType0, State1)]; record -> [PatString, format_type(Type, State1)]; @@ -1444,7 +1439,7 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) -> BinType = t_inf(t_bitstr(), Type, Opaques), case t_is_none(BinType) of true -> - case t_find_opaque_mismatch(t_bitstr(), Type) of + case t_find_opaque_mismatch(t_bitstr(), Type, Opaques) of {ok, T1, T2} -> bind_error([Pat], T1, T2, opaque); error -> @@ -1460,7 +1455,7 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) -> Cons = t_inf(Type, t_cons(), Opaques), case t_is_none(Cons) of true -> - bind_opaque_pats(t_cons(), Type, Pat, Map, State, Rev); + bind_opaque_pats(t_cons(), Type, Pat, State); false -> {Map1, [HdType, TlType]} = bind_pat_vars([cerl:cons_hd(Pat), cerl:cons_tl(Pat)], @@ -1473,7 +1468,7 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) -> Literal = literal_type(Pat), case t_is_none(t_inf(Literal, Type, Opaques)) of true -> - bind_opaque_pats(Literal, Type, Pat, Map, State, Rev); + bind_opaque_pats(Literal, Type, Pat, State); false -> {Map, Literal} end; map -> @@ -1484,7 +1479,7 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) -> case Es of [] -> {false, t_tuple([])}; [Tag|Left] -> - case cerl:is_c_atom(Tag) of + case cerl:is_c_atom(Tag) andalso is_literal_record(Pat) of true -> TagAtom = cerl:atom_val(Tag), case state__lookup_record(TagAtom, length(Left), State) of @@ -1500,7 +1495,7 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) -> Tuple = t_inf(Prototype, Type, Opaques), case t_is_none(Tuple) of true -> - bind_opaque_pats(Prototype, Type, Pat, Map, State, Rev); + bind_opaque_pats(Prototype, Type, Pat, State); false -> SubTuples = t_tuple_subtypes(Tuple, Opaques), %% Need to call the top function to get the try-catch wrapper @@ -1549,7 +1544,7 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) -> VarType2 = t_inf(VarType1, Type, Opaques), case t_is_none(VarType2) of true -> - case t_find_opaque_mismatch(VarType1, Type) of + case t_find_opaque_mismatch(VarType1, Type, Opaques) of {ok, T1, T2} -> bind_error([Pat], T1, T2, opaque); error -> @@ -1631,21 +1626,26 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) -> bind_bin_segs([], _BinType, Acc, Map, _State) -> {Map, lists:reverse(Acc)}. -bind_error(Pats, Type, OpaqueType, Error) -> +bind_error(Pats, Type, OpaqueType, Error0) -> + Error = case {Error0, Pats} of + {bind, [Pat]} -> + case is_literal_record(Pat) of + true -> record; + false -> Error0 + end; + _ -> Error0 + end, throw({error, Error, Pats, Type, OpaqueType}). -bind_opaque_pats(GenType, Type, Pat, Map, State, Rev) -> - case t_find_opaque_mismatch(GenType, Type) of +-spec bind_opaque_pats(type(), type(), cerl:c_literal(), state()) -> + no_return(). + +bind_opaque_pats(GenType, Type, Pat, State) -> + case t_find_opaque_mismatch(GenType, Type, State#state.opaques) of {ok, T1, T2} -> - case erl_types:is_opaque_type(T2, State#state.opaques) of - true -> - NewType = erl_types:t_struct_from_opaque(Type, [T2]), - {Map1, _} = - bind_pat_vars([Pat], [NewType], [], Map, State, Rev), - {Map1, T2}; - false -> bind_error([Pat], T1, T2, opaque) - end; - error -> bind_error([Pat], Type, t_none(), bind) + bind_error([Pat], T1, T2, opaque); + error -> + bind_error([Pat], Type, t_none(), bind) end. %%---------------------------------------- @@ -1843,9 +1843,9 @@ handle_guard_comp(Guard, Comp, Map, Env, Eval, State) -> [Type1, Type2] = ArgTypes, IsInt1 = t_is_integer(Type1, Opaques), IsInt2 = t_is_integer(Type2, Opaques), - case {cerl:type(Arg1), cerl:type(Arg2)} of - {literal, literal} -> - case erlang:Comp(cerl:concrete(Arg1), cerl:concrete(Arg2)) of + case {type(Arg1), type(Arg2)} of + {{literal, Lit1}, {literal, Lit2}} -> + case erlang:Comp(cerl:concrete(Lit1), cerl:concrete(Lit2)) of true when Eval =:= pos -> {Map, t_atom(true)}; true when Eval =:= dont_know -> {Map, t_atom(true)}; true when Eval =:= neg -> {Map, t_atom(true)}; @@ -1854,13 +1854,13 @@ handle_guard_comp(Guard, Comp, Map, Env, Eval, State) -> false when Eval =:= dont_know -> {Map, t_atom(false)}; false when Eval =:= neg -> {Map, t_atom(false)} end; - {literal, var} when IsInt1 andalso IsInt2 andalso (Eval =:= pos) -> - case bind_comp_literal_var(Arg1, Arg2, Type2, Comp, Map1, Opaques) of + {{literal, Lit1}, var} when IsInt1 andalso IsInt2 andalso (Eval =:= pos) -> + case bind_comp_literal_var(Lit1, Arg2, Type2, Comp, Map1, Opaques) of error -> signal_guard_fail(Eval, Guard, ArgTypes, State); {ok, NewMap} -> {NewMap, t_atom(true)} end; - {var, literal} when IsInt1 andalso IsInt2 andalso (Eval =:= pos) -> - case bind_comp_literal_var(Arg2, Arg1, Type1, invert_comp(Comp), + {var, {literal, Lit2}} when IsInt1 andalso IsInt2 andalso (Eval =:= pos) -> + case bind_comp_literal_var(Lit2, Arg1, Type1, invert_comp(Comp), Map1, Opaques) of error -> signal_guard_fail(Eval, Guard, ArgTypes, State); {ok, NewMap} -> {NewMap, t_atom(true)} @@ -1980,15 +1980,15 @@ handle_guard_is_record(Guard, Map, Env, Eval, State) -> handle_guard_eq(Guard, Map, Env, Eval, State) -> [Arg1, Arg2] = cerl:call_args(Guard), - case {cerl:type(Arg1), cerl:type(Arg2)} of - {literal, literal} -> - case cerl:concrete(Arg1) =:= cerl:concrete(Arg2) of + case {type(Arg1), type(Arg2)} of + {{literal, Lit1}, {literal, Lit2}} -> + case cerl:concrete(Lit1) =:= cerl:concrete(Lit2) of true -> if Eval =:= pos -> {Map, t_atom(true)}; Eval =:= neg -> - ArgTypes = [t_from_term(cerl:concrete(Arg1)), - t_from_term(cerl:concrete(Arg2))], + ArgTypes = [t_from_term(cerl:concrete(Lit1)), + t_from_term(cerl:concrete(Lit2))], signal_guard_fail(Eval, Guard, ArgTypes, State); Eval =:= dont_know -> {Map, t_atom(true)} end; @@ -1997,28 +1997,28 @@ handle_guard_eq(Guard, Map, Env, Eval, State) -> Eval =:= neg -> {Map, t_atom(false)}; Eval =:= dont_know -> {Map, t_atom(false)}; Eval =:= pos -> - ArgTypes = [t_from_term(cerl:concrete(Arg1)), - t_from_term(cerl:concrete(Arg2))], + ArgTypes = [t_from_term(cerl:concrete(Lit1)), + t_from_term(cerl:concrete(Lit2))], signal_guard_fail(Eval, Guard, ArgTypes, State) end end; - {literal, _} when Eval =:= pos -> - case cerl:concrete(Arg1) of + {{literal, Lit1}, _} when Eval =:= pos -> + case cerl:concrete(Lit1) of Atom when is_atom(Atom) -> - bind_eqeq_guard_lit_other(Guard, Arg1, Arg2, Map, Env, State); + bind_eqeq_guard_lit_other(Guard, Lit1, Arg2, Map, Env, State); [] -> - bind_eqeq_guard_lit_other(Guard, Arg1, Arg2, Map, Env, State); + bind_eqeq_guard_lit_other(Guard, Lit1, Arg2, Map, Env, State); _ -> - bind_eq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) + bind_eq_guard(Guard, Lit1, Arg2, Map, Env, Eval, State) end; - {_, literal} when Eval =:= pos -> - case cerl:concrete(Arg2) of + {_, {literal, Lit2}} when Eval =:= pos -> + case cerl:concrete(Lit2) of Atom when is_atom(Atom) -> - bind_eqeq_guard_lit_other(Guard, Arg2, Arg1, Map, Env, State); + bind_eqeq_guard_lit_other(Guard, Lit2, Arg1, Map, Env, State); [] -> - bind_eqeq_guard_lit_other(Guard, Arg2, Arg1, Map, Env, State); + bind_eqeq_guard_lit_other(Guard, Lit2, Arg1, Map, Env, State); _ -> - bind_eq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) + bind_eq_guard(Guard, Arg1, Lit2, Map, Env, Eval, State) end; {_, _} -> bind_eq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) @@ -2050,13 +2050,14 @@ bind_eq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) -> handle_guard_eqeq(Guard, Map, Env, Eval, State) -> [Arg1, Arg2] = cerl:call_args(Guard), - case {cerl:type(Arg1), cerl:type(Arg2)} of - {literal, literal} -> - case cerl:concrete(Arg1) =:= cerl:concrete(Arg2) of + case {type(Arg1), type(Arg2)} of + {{literal, Lit1}, {literal, Lit2}} -> + + case cerl:concrete(Lit1) =:= cerl:concrete(Lit2) of true -> if Eval =:= neg -> - ArgTypes = [t_from_term(cerl:concrete(Arg1)), - t_from_term(cerl:concrete(Arg2))], + ArgTypes = [t_from_term(cerl:concrete(Lit1)), + t_from_term(cerl:concrete(Lit2))], signal_guard_fail(Eval, Guard, ArgTypes, State); Eval =:= pos -> {Map, t_atom(true)}; Eval =:= dont_know -> {Map, t_atom(true)} @@ -2065,15 +2066,15 @@ handle_guard_eqeq(Guard, Map, Env, Eval, State) -> if Eval =:= neg -> {Map, t_atom(false)}; Eval =:= dont_know -> {Map, t_atom(false)}; Eval =:= pos -> - ArgTypes = [t_from_term(cerl:concrete(Arg1)), - t_from_term(cerl:concrete(Arg2))], + ArgTypes = [t_from_term(cerl:concrete(Lit1)), + t_from_term(cerl:concrete(Lit2))], signal_guard_fail(Eval, Guard, ArgTypes, State) end end; - {literal, _} when Eval =:= pos -> - bind_eqeq_guard_lit_other(Guard, Arg1, Arg2, Map, Env, State); - {_, literal} when Eval =:= pos -> - bind_eqeq_guard_lit_other(Guard, Arg2, Arg1, Map, Env, State); + {{literal, Lit1}, _} when Eval =:= pos -> + bind_eqeq_guard_lit_other(Guard, Lit1, Arg2, Map, Env, State); + {_, {literal, Lit2}} when Eval =:= pos -> + bind_eqeq_guard_lit_other(Guard, Lit2, Arg1, Map, Env, State); {_, _} -> bind_eqeq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) end. @@ -2770,8 +2771,7 @@ filter_match_fail([]) -> %%% =========================================================================== state__new(Callgraph, Tree, Plt, Module, Records) -> - Opaques = erl_types:module_builtin_opaques(Module) ++ - erl_types:t_opaque_from_records(Records), + Opaques = erl_types:t_opaque_from_records(Records), TreeMap = build_tree_map(Tree), Funs = dict:fetch_keys(TreeMap), FunTab = init_fun_tab(Funs, dict:new(), TreeMap, Callgraph, Plt), @@ -3282,12 +3282,17 @@ get_file([_|Tail]) -> get_file(Tail). is_compiler_generated(Ann) -> lists:member(compiler_generated, Ann) orelse (get_line(Ann) < 1). +is_literal_record(Tree) -> + Ann = cerl:get_ann(Tree), + lists:member(record, Ann). + -spec format_args([cerl:cerl()], [type()], state()) -> nonempty_string(). format_args([], [], _State) -> "()"; -format_args(ArgList, TypeList, State) -> +format_args(ArgList0, TypeList, State) -> + ArgList = fold_literals(ArgList0), "(" ++ format_args_1(ArgList, TypeList, State) ++ ")". format_args_1([Arg], [Type], State) -> @@ -3346,7 +3351,8 @@ format_cerl(Tree) -> {ribbon, 100000} %% newlines. ]). -format_patterns(Pats) -> +format_patterns(Pats0) -> + Pats = fold_literals(Pats0), NewPats = map_pats(cerl:c_values(Pats)), String = format_cerl(NewPats), case Pats of @@ -3378,6 +3384,23 @@ map_pats(Pats) -> end, cerl_trees:map(Fun, Pats). +fold_literals(TreeList) -> + [cerl:fold_literal(Tree) || Tree <- TreeList]. + +type(Tree) -> + Folded = cerl:fold_literal(Tree), + case cerl:type(Folded) of + literal -> {literal, Folded}; + Type -> Type + end. + +is_literal(Tree) -> + Folded = cerl:fold_literal(Tree), + case cerl:is_literal(Folded) of + true -> {yes, Folded}; + false -> no + end. + parent_allows_this(FunLbl, #state{callgraph = Callgraph, plt = Plt} =State) -> case state__is_escaping(FunLbl, State) of false -> false; % if it isn't escaping it can't be a return value @@ -3422,18 +3445,18 @@ find_terminals(Tree) -> M0 = cerl:call_module(Tree), F0 = cerl:call_name(Tree), A = length(cerl:call_args(Tree)), - case cerl:is_literal(M0) andalso cerl:is_literal(F0) of - false -> - %% We cannot make assumptions. Say that both are true. - {true, true}; - true -> - M = cerl:concrete(M0), - F = cerl:concrete(F0), + case {is_literal(M0), is_literal(F0)} of + {{yes, LitM}, {yes, LitF}} -> + M = cerl:concrete(LitM), + F = cerl:concrete(LitF), case (erl_bif_types:is_known(M, F, A) andalso t_is_none(erl_bif_types:type(M, F, A))) of true -> {true, false}; false -> {false, true} - end + end; + _ -> + %% We cannot make assumptions. Say that both are true. + {true, true} end; 'case' -> find_terminals_list(cerl:case_clauses(Tree)); 'catch' -> find_terminals(cerl:catch_body(Tree)); @@ -3478,66 +3501,6 @@ find_terminals_list([], Explicit, Normal) -> %%---------------------------------------------------------------------------- -%% If you write a record pattern in a matching that violates the -%% definition it will never match. However, the warning is lost in the -%% regular analysis. This after-pass catches it. - -find_mismatched_record_patterns(Tree, State) -> - cerl_trees:fold( - fun(SubTree, AccState) -> - case cerl:is_c_clause(SubTree) of - true -> lists:foldl(fun(P, AccState1) -> - find_rec_warnings(P, AccState1) - end, AccState, cerl:clause_pats(SubTree)); - false -> AccState - end - end, State, Tree). - -find_rec_warnings(Tree, State) -> - cerl_trees:fold( - fun(SubTree, AccState) -> - case cerl:is_c_tuple(SubTree) of - true -> find_rec_warnings_tuple(SubTree, AccState); - false -> AccState - end - end, State, Tree). - -find_rec_warnings_tuple(Tree, State) -> - Elements = cerl:tuple_es(Tree), - {_, _, EsType} = traverse_list(Elements, map__new(), State), - TupleType = t_tuple(EsType), - case t_is_none(TupleType) of - true -> State; - false -> - %% Let's find out if this is a record construction. - case Elements of - [Tag|Left] -> - case cerl:is_c_atom(Tag) of - true -> - TagVal = cerl:atom_val(Tag), - case state__lookup_record(TagVal, length(Left), State) of - error -> State; - {ok, Prototype} -> - InfTupleType = t_inf(Prototype, TupleType), - case t_is_none(InfTupleType) of - true -> - Msg = {record_matching, - [format_patterns([Tree]), TagVal]}, - state__add_warning(State, ?WARN_MATCHING, Tree, Msg); - false -> - State - end - end; - false -> - State - end; - _ -> - State - end - end. - -%%---------------------------------------------------------------------------- - -ifdef(DEBUG_PP). debug_pp(Tree, true) -> io:put_chars(cerl_prettypr:format(Tree, [{hook, cerl_typean:pp_hook()}])), diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl index 63798f44b1..7c970daf41 100644 --- a/lib/dialyzer/src/dialyzer_plt.erl +++ b/lib/dialyzer/src/dialyzer_plt.erl @@ -158,9 +158,7 @@ lookup_contract(#mini_plt{contracts = ETSContracts}, ets_table_lookup(ETSContracts, MFA). -spec lookup_callbacks(plt(), module()) -> - 'none' | {'value', [{mfa(), {{Filename::string(), - Line::pos_integer()}, - #contract{}}}]}. + 'none' | {'value', [{mfa(), dialyzer_contracts:file_contract()}]}. lookup_callbacks(#mini_plt{callbacks = ETSCallbacks}, Mod) when is_atom(Mod) -> ets_table_lookup(ETSCallbacks, Mod). @@ -618,9 +616,7 @@ table_insert_list(Plt, [{Key, Val}|Left]) -> table_insert_list(Plt, []) -> Plt. -table_insert(Plt, Key, {_Ret, _Arg} = Obj) -> - dict:store(Key, Obj, Plt); -table_insert(Plt, Key, #contract{} = C) -> +table_insert(Plt, Key, {_File, #contract{}, _Xtra} = C) -> dict:store(Key, C, Plt). table_lookup(Plt, Obj) -> diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl index 28c2ad2c0b..2a8aba5d8f 100644 --- a/lib/dialyzer/src/dialyzer_races.erl +++ b/lib/dialyzer/src/dialyzer_races.erl @@ -1848,7 +1848,8 @@ ets_tuple_argtypes1(Str, Tuple, TupleList, NestingLevel) -> end. format_arg(?bypassed) -> ?no_label; -format_arg(Arg) -> +format_arg(Arg0) -> + Arg = cerl:fold_literal(Arg0), case cerl:type(Arg) of var -> cerl_trees:get_label(Arg); tuple -> list_to_tuple([format_arg(A) || A <- cerl:tuple_es(Arg)]); @@ -1878,7 +1879,7 @@ format_args_1([Arg|Args], [Type|Types], CleanState) -> case Arg =:= ?bypassed of true -> [?no_label, format_type(Type, CleanState)]; false -> - case cerl:is_literal(Arg) of + case cerl:is_literal(cerl:fold_literal(Arg)) of true -> [?no_label, format_cerl(Arg)]; false -> [format_arg(Arg), format_type(Type, CleanState)] end @@ -2148,7 +2149,8 @@ race_var_map_guard_helper1(Arg, Pats, RaceVarMap, Op) -> end end. -race_var_map_guard_helper2(Arg, Pat, Bool, RaceVarMap, Op) -> +race_var_map_guard_helper2(Arg, Pat0, Bool, RaceVarMap, Op) -> + Pat = cerl:fold_literal(Pat0), case cerl:type(Pat) of literal -> [Arg1, Arg2] = cerl:call_args(Arg), diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl index ef9b00e203..6dc4285194 100644 --- a/lib/dialyzer/src/dialyzer_succ_typings.erl +++ b/lib/dialyzer/src/dialyzer_succ_typings.erl @@ -201,7 +201,7 @@ postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {CallF, CallL}, Msg}|Rest], Codeserver, WAcc, Acc) -> {contract_range, [Contract, M, F, A, ArgStrings, CRet]} = Msg, case dialyzer_codeserver:lookup_mfa_contract({M,F,A}, Codeserver) of - {ok, {{ContrF, _ContrL} = FileLine, _C}} -> + {ok, {{ContrF, _ContrL} = FileLine, _C, _X}} -> case CallF =:= ContrF of true -> NewMsg = {contract_range, [Contract, M, F, ArgStrings, CallL, CRet]}, @@ -401,7 +401,7 @@ decorate_succ_typings(Contracts, Callgraph, FunTypes, FindOpaques) -> case dialyzer_callgraph:lookup_name(Label, Callgraph) of {ok, MFA} -> case orddict:find(MFA, Contracts) of - {ok, {_FileLine, Contract}} -> + {ok, {_FileLine, Contract, _Xtra}} -> Args = dialyzer_contracts:get_contract_args(Contract), Ret = dialyzer_contracts:get_contract_return(Contract), C = erl_types:t_fun(Args, Ret), @@ -422,10 +422,7 @@ lookup_and_find_opaques_fun(Codeserver) -> end. find_opaques_fun(Records) -> - fun(Module) -> - erl_types:module_builtin_opaques(Module) ++ - erl_types:t_opaque_from_records(Records) - end. + fun(_Module) -> erl_types:t_opaque_from_records(Records) end. get_fun_types_from_plt(FunList, Callgraph, Plt) -> get_fun_types_from_plt(FunList, Callgraph, Plt, dict:new()). diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 31ceaf5ac5..3d03ed3ab3 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -389,13 +389,8 @@ traverse(Tree, DefinedVars, State) -> {State2, _} = traverse_list(Funs, DefinedVars1, State1), traverse(Body, DefinedVars1, State2); literal -> - %% This is needed for finding records - case cerl:unfold_literal(Tree) of - Tree -> - Type = t_from_term(cerl:concrete(Tree)), - {State, Type}; - NewTree -> traverse(NewTree, DefinedVars, State) - end; + Type = t_from_term(cerl:concrete(Tree)), + {State, Type}; module -> Defs = cerl:module_defs(Tree), Funs = [Fun || {_Var, Fun} <- Defs], @@ -462,7 +457,7 @@ traverse(Tree, DefinedVars, State) -> end, case Elements of [Tag|Fields] -> - case cerl:is_c_atom(Tag) of + case cerl:is_c_atom(Tag) andalso is_literal_record(Tree) of true -> %% Check if a record is constructed. Arity = length(Fields), @@ -874,7 +869,8 @@ get_underapprox_from_guard(Tree, Map) -> MFA -> case get_type_test(MFA) of {ok, Type} -> - [Arg] = cerl:call_args(Tree), + [Arg0] = cerl:call_args(Tree), + Arg = cerl:fold_literal(Arg0), {ArgType, Map1} = get_underapprox_from_guard(Arg, Map), Inf = t_inf(Type, ArgType), case t_is_none(Inf) of @@ -891,7 +887,9 @@ get_underapprox_from_guard(Tree, Map) -> {erlang, '=:=', 2} -> throw(dont_know); {erlang, '==', 2} -> throw(dont_know); {erlang, 'and', 2} -> - [Arg1, Arg2] = cerl:call_args(Tree), + [Arg1_0, Arg2_0] = cerl:call_args(Tree), + Arg1 = cerl:fold_literal(Arg1_0), + Arg2 = cerl:fold_literal(Arg2_0), case ((cerl:is_c_var(Arg1) orelse cerl:is_literal(Arg1)) andalso (cerl:is_c_var(Arg2) orelse cerl:is_literal(Arg2))) of @@ -3272,6 +3270,10 @@ lookup_record(Records, Tag, Arity) -> error end. +is_literal_record(Tree) -> + Ann = cerl:get_ann(Tree), + lists:member(record, Ann). + family(L) -> sofs:to_external(sofs:rel2fam(sofs:relation(L))). diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl index 21183e3459..d969ffc4e6 100644 --- a/lib/dialyzer/src/dialyzer_utils.erl +++ b/lib/dialyzer/src/dialyzer_utils.erl @@ -322,8 +322,26 @@ merge_records(NewRecords, OldRecords) -> {'ok', spec_dict(), callback_dict()} | {'error', string()}. get_spec_info(ModName, AbstractCode, RecordsDict) -> + OptionalCallbacks0 = get_optional_callbacks(AbstractCode, ModName), + OptionalCallbacks = gb_sets:from_list(OptionalCallbacks0), get_spec_info(AbstractCode, dict:new(), dict:new(), - RecordsDict, ModName, "nofile"). + RecordsDict, ModName, OptionalCallbacks, "nofile"). + +get_optional_callbacks(Abs, ModName) -> + [{ModName, F, A} || {F, A} <- get_optional_callbacks(Abs)]. + +get_optional_callbacks(Abs) -> + L = [O || + {attribute, _, optional_callbacks, O} <- Abs, + is_fa_list(O)], + lists:append(L). + +is_fa_list([{FuncName, Arity}|L]) + when is_atom(FuncName), is_integer(Arity), Arity >= 0 -> + is_fa_list(L); +is_fa_list([]) -> true; +is_fa_list(_) -> false. + %% TypeSpec is a list of conditional contracts for a function. %% Each contract is of the form {[Argument], Range, [Constraint]} where @@ -332,13 +350,14 @@ get_spec_info(ModName, AbstractCode, RecordsDict) -> %% are erl_types:erl_type() get_spec_info([{attribute, Ln, Contract, {Id, TypeSpec}}|Left], - SpecDict, CallbackDict, RecordsDict, ModName, File) + SpecDict, CallbackDict, RecordsDict, ModName, OptCb, File) when ((Contract =:= 'spec') or (Contract =:= 'callback')), is_list(TypeSpec) -> MFA = case Id of {_, _, _} = T -> T; {F, A} -> {ModName, F, A} end, + Xtra = [optional_callback || gb_sets:is_member(MFA, OptCb)], ActiveDict = case Contract of spec -> SpecDict; @@ -346,8 +365,9 @@ get_spec_info([{attribute, Ln, Contract, {Id, TypeSpec}}|Left], end, try dict:find(MFA, ActiveDict) of error -> + SpecData = {TypeSpec, Xtra}, NewActiveDict = - dialyzer_contracts:store_tmp_contract(MFA, {File, Ln}, TypeSpec, + dialyzer_contracts:store_tmp_contract(MFA, {File, Ln}, SpecData, ActiveDict, RecordsDict), {NewSpecDict, NewCallbackDict} = case Contract of @@ -355,8 +375,8 @@ get_spec_info([{attribute, Ln, Contract, {Id, TypeSpec}}|Left], callback -> {SpecDict, NewActiveDict} end, get_spec_info(Left, NewSpecDict, NewCallbackDict, - RecordsDict, ModName,File); - {ok, {{OtherFile, L},_C}} -> + RecordsDict, ModName, OptCb, File); + {ok, {{OtherFile, L}, _D}} -> {Mod, Fun, Arity} = MFA, Msg = flat_format(" Contract/callback for function ~w:~w/~w " "already defined in ~s:~w\n", @@ -368,13 +388,15 @@ get_spec_info([{attribute, Ln, Contract, {Id, TypeSpec}}|Left], [Ln, Error])} end; get_spec_info([{attribute, _, file, {IncludeFile, _}}|Left], - SpecDict, CallbackDict, RecordsDict, ModName, _File) -> + SpecDict, CallbackDict, RecordsDict, ModName, OptCb, _File) -> get_spec_info(Left, SpecDict, CallbackDict, - RecordsDict, ModName, IncludeFile); + RecordsDict, ModName, OptCb, IncludeFile); get_spec_info([_Other|Left], SpecDict, CallbackDict, - RecordsDict, ModName, File) -> - get_spec_info(Left, SpecDict, CallbackDict, RecordsDict, ModName, File); -get_spec_info([], SpecDict, CallbackDict, _RecordsDict, _ModName, _File) -> + RecordsDict, ModName, OptCb, File) -> + get_spec_info(Left, SpecDict, CallbackDict, + RecordsDict, ModName, OptCb, File); +get_spec_info([], SpecDict, CallbackDict, + _RecordsDict, _ModName, _OptCb, _File) -> {ok, SpecDict, CallbackDict}. %% ============================================================================ @@ -402,7 +424,7 @@ sets_filter([Mod|Mods], ExpTypes) -> src_compiler_opts() -> [no_copt, to_core, binary, return_errors, no_inline, strict_record_tests, strict_record_updates, - no_is_record_optimization]. + dialyzer]. -spec get_module(abstract_code()) -> module(). diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/simple b/lib/dialyzer/test/opaque_SUITE_data/results/simple index 072ac9be8f..29864d6065 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/simple +++ b/lib/dialyzer/test/opaque_SUITE_data/results/simple @@ -14,12 +14,17 @@ is_rec.erl:53: The call erlang:is_record(A::simple1_adt:d1(),A::simple1_adt:d1() is_rec.erl:57: Guard test is_record(A::simple1_adt:d1(),'r',2) breaks the opaqueness of its argument is_rec.erl:61: The record #r{f1::simple1_adt:d1()} violates the declared type for #r{} is_rec.erl:65: The call erlang:is_record({simple1_adt:d1(),1},'r',2) contains an opaque term as 1st argument when terms of different types are expected in these positions -rec_api.erl:22: Record construction #r1{f1::10} violates the declared type of field f1::'undefined' | rec_api:a() -rec_api.erl:23: The pattern {'r1', 10} violates the declared type for #r1{} -rec_api.erl:27: The attempt to match a term of type rec_adt:r1() against the pattern {'r1', 'a'} breaks the opaqueness of the term -rec_api.erl:29: Invalid type specification for function rec_api:adt_t1/1. The success typing is (#r1{f1::'a'}) -> #r1{f1::'a'} -rec_api.erl:34: Invalid type specification for function rec_api:adt_r1/0. The success typing is () -> #r1{f1::'a'} -rec_api.erl:77: The attempt to match a term of type rec_api:f() against the variable _ breaks the opaqueness of the term +rec_api.erl:104: Matching of pattern {'r2', 10} tagged with a record name violates the declared type of #r2{f1::10} +rec_api.erl:113: The attempt to match a term of type #r3{f1::queue:queue(_)} against the pattern {'r3', 'a'} breaks the opaqueness of queue:queue(_) +rec_api.erl:118: Record construction #r3{f1::10} violates the declared type of field f1::queue:queue(_) +rec_api.erl:123: The attempt to match a term of type #r3{f1::10} against the pattern {'r3', 10} breaks the opaqueness of queue:queue(_) +rec_api.erl:24: Record construction #r1{f1::10} violates the declared type of field f1::'undefined' | rec_api:a() +rec_api.erl:29: Matching of pattern {'r1', 10} tagged with a record name violates the declared type of #r1{f1::10} +rec_api.erl:33: The attempt to match a term of type rec_adt:r1() against the pattern {'r1', 'a'} breaks the opaqueness of the term +rec_api.erl:35: Invalid type specification for function rec_api:adt_t1/1. The success typing is (#r1{f1::'a'}) -> #r1{f1::'a'} +rec_api.erl:40: Invalid type specification for function rec_api:adt_r1/0. The success typing is () -> #r1{f1::'a'} +rec_api.erl:85: The attempt to match a term of type rec_api:f() against the variable _ breaks the opaqueness of rec_adt:f() +rec_api.erl:99: Record construction #r2{f1::10} violates the declared type of field f1::rec_api:a() simple1_api.erl:113: The test simple1_api:d1() =:= simple1_api:d2() can never evaluate to 'true' simple1_api.erl:118: Guard test simple1_api:d2() =:= A::simple1_api:d1() can never succeed simple1_api.erl:142: Attempt to test for equality between a term of type simple1_adt:o2() and a term of opaque type simple1_adt:o1() @@ -58,7 +63,7 @@ simple1_api.erl:381: Invalid type specification for function simple1_api:bool_ad simple1_api.erl:407: The size simple1_adt:i1() breaks the opaqueness of A simple1_api.erl:418: The attempt to match a term of type non_neg_integer() against the variable A breaks the opaqueness of simple1_adt:i1() simple1_api.erl:425: The attempt to match a term of type non_neg_integer() against the variable B breaks the opaqueness of simple1_adt:i1() -simple1_api.erl:432: The attempt to match a term of type non_neg_integer() against the variable B breaks the opaqueness of simple1_api:o1() +simple1_api.erl:432: The pattern <<_:B/integer-unit:1>> can never match the type any() simple1_api.erl:448: The attempt to match a term of type non_neg_integer() against the variable Sz breaks the opaqueness of simple1_adt:i1() simple1_api.erl:460: The attempt to match a term of type simple1_adt:bit1() against the pattern <<_/binary-unit:8>> breaks the opaqueness of the term simple1_api.erl:478: The call 'foo':A(A::simple1_adt:a()) breaks the opaqueness of the term A :: simple1_adt:a() diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/timer b/lib/dialyzer/test/opaque_SUITE_data/results/timer index e917b76b08..b1cfcd4e9f 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/timer +++ b/lib/dialyzer/test/opaque_SUITE_data/results/timer @@ -1,4 +1,4 @@ timer_use.erl:16: The pattern 'gazonk' can never match the type {'error',_} | {'ok',timer:tref()} -timer_use.erl:17: The attempt to match a term of type {'ok',timer:tref()} against the pattern {'ok', 42} breaks the opaqueness of timer:tref() +timer_use.erl:17: The attempt to match a term of type {'error',_} | {'ok',timer:tref()} against the pattern {'ok', 42} breaks the opaqueness of timer:tref() timer_use.erl:18: The attempt to match a term of type {'error',_} | {'ok',timer:tref()} against the pattern {Tag, 'gazonk'} breaks the opaqueness of timer:tref() diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/simple/rec_api.erl b/lib/dialyzer/test/opaque_SUITE_data/src/simple/rec_api.erl index d9b1d59f0c..fb6d59d263 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/simple/rec_api.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/simple/rec_api.erl @@ -1,9 +1,9 @@ -module(rec_api). --export([t1/0, t2/0, adt_t1/0, adt_t1/1, adt_r1/0, - t/1, t_adt/0, r/0, r_adt/0]). +-export([t1/0, t2/0, t3/0, adt_t1/0, adt_t1/1, adt_r1/0, + t/1, t_adt/0, r/0, r_adt/0, u1/0, u2/0, u3/0, v1/0, v2/0, v3/0]). --export_type([{a,0},{r1,0}]). +-export_type([{a,0},{r1,0}, r2/0, r3/0]). -export_type([f/0, op_t/0, r/0, tup/0]). @@ -19,8 +19,14 @@ t1() -> {r1, a} = A. t2() -> - A = {r1, 10}, % violates the type of #r1{} - {r1, 10} = A. % violates the type of #r1{} + A = {r1, 10}, + {r1, 10} = A, + A = #r1{f1 = 10}, % violates the type of field f1 + #r1{f1 = 10} = A. + +t3() -> + A = {r1, 10}, + #r1{f1 = 10} = A. % violates the type of #r1{} adt_t1() -> R = rec_adt:r1(), @@ -66,7 +72,8 @@ t_adt() -> -spec r() -> _. r() -> - {r, f(), 2}. % OK, f() is a local opaque type + {{r, f(), 2}, + #r{f = f(), o = 2}}. % OK, f() is a local opaque type -spec f() -> f(). @@ -74,4 +81,43 @@ f() -> fun(_) -> 3 end. r_adt() -> - {r, rec_adt:f(), 2}. % breaks the opaqueness + {{r, rec_adt:f(), 2}, + #r{f = rec_adt:f(), o = 2}}. % breaks the opaqueness + +-record(r2, % like #r1{}, but with initial value + {f1 = a :: a()}). + +-opaque r2() :: #r2{}. + +u1() -> + A = #r2{f1 = a}, + {r2, a} = A. + +u2() -> + A = {r2, 10}, + {r2, 10} = A, + A = #r2{f1 = 10}, % violates the type of field f1 + #r2{f1 = 10} = A. + +u3() -> + A = {r2, 10}, + #r2{f1 = 10} = A. % violates the type of #r2{} + +-record(r3, % like #r1{}, but an opaque type + {f1 = queue:new():: queue:queue()}). + +-opaque r3() :: #r3{}. + +v1() -> + A = #r3{f1 = queue:new()}, + {r3, a} = A. % breaks the opaqueness + +v2() -> + A = {r3, 10}, + {r3, 10} = A, + A = #r3{f1 = 10}, % violates the type of field f1 + #r3{f1 = 10} = A. + +v3() -> + A = {r3, 10}, + #r3{f1 = 10} = A. % breaks the opaqueness diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/simple/simple1_api.erl b/lib/dialyzer/test/opaque_SUITE_data/src/simple/simple1_api.erl index 5135eb8e59..eef2074e0c 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/simple/simple1_api.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/simple/simple1_api.erl @@ -428,8 +428,8 @@ bit_adt_t3(A) -> bit_t5(A) -> B = o1(), - case none:none() of - <<A:B>> -> 1 % breaks the opaqueness + case none:none() of % the type is any(); should fix that XXX + <<A:B>> -> 1 % can never match (local opaque type is OK) end. -spec bit_t4(<<_:1>>) -> integer(). diff --git a/lib/dialyzer/test/options1_SUITE_data/results/compiler b/lib/dialyzer/test/options1_SUITE_data/results/compiler index 6399e3e36b..30b6f4814a 100644 --- a/lib/dialyzer/test/options1_SUITE_data/results/compiler +++ b/lib/dialyzer/test/options1_SUITE_data/results/compiler @@ -4,7 +4,7 @@ beam_bool.erl:193: The pattern {[], _} can never match the type {[{_,_,_,_},...] beam_bool.erl:510: The pattern [{'set', [Dst], _, _}, {'%live', _}] can never match the type [{_,_,_,_}] beam_disasm.erl:537: The variable X can never match since previous clauses completely covered the type 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 beam_type.erl:284: The pattern <'pi', 0> can never match the type <_,1 | 2> -beam_validator.erl:396: The pattern <{'jump', {'f', _}}, Vst = {'vst', 'none', _}> can never match the type <_,#vst{current::#st{ct::[]}}> +beam_validator.erl:396: Matching of pattern {'vst', 'none', _} tagged with a record name violates the declared type of #vst{current::#st{ct::[]}} beam_validator.erl:690: The pattern <'term', OldT> can never match the type <{'tuple',[any(),...]},_> beam_validator.erl:693: Guard test 'or'('false','false') can never succeed beam_validator.erl:700: Guard test 'or'('false','false') can never succeed @@ -33,4 +33,4 @@ core_lint.erl:473: The pattern <{'c_atom', _, 'all'}, 'binary', _Def, St> can ne core_lint.erl:505: The pattern <_Req, 'unknown', St> can never match the type <non_neg_integer(),non_neg_integer(),_> v3_codegen.erl:1569: The call v3_codegen:load_reg_1(V::any(),I::0,Rs::any(),pos_integer()) will never return since it differs in the 4th argument from the success typing arguments: (any(),0,maybe_improper_list(),0) v3_codegen.erl:1571: The call v3_codegen:load_reg_1(V::any(),I::0,[],pos_integer()) will never return since it differs in the 4th argument from the success typing arguments: (any(),0,maybe_improper_list(),0) -v3_core.erl:646: The pattern <Prim = {'iprimop', _, _, _}, St> can never match the type <#c_nil{anno::[any(),...]} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple' | 'c_var' | 'ibinary' | 'icatch' | 'ireceive1',[any(),...] | {_,_,_,_},_} | #c_cons{anno::[any(),...]} | #c_fname{anno::[any(),...]} | #iletrec{anno::{_,_,_,_},defs::[any(),...],body::[any(),...]} | #icase{anno::{_,_,_,_},args::[any()],clauses::[any()],fc::{_,_,_,_,_,_}} | #ireceive2{anno::{_,_,_,_},clauses::[any()],action::[any()]} | #ifun{anno::{_,_,_,_},id::[any(),...],vars::[any()],clauses::[any(),...],fc::{_,_,_,_,_,_}} | #imatch{anno::{_,_,_,_},guard::[],fc::{_,_,_,_,_,_}} | #itry{anno::{_,_,_,_},args::[any()],vars::[any(),...],body::[any(),...],evars::[any(),...],handler::[any(),...]},_> +v3_core.erl:646: Matching of pattern {'iprimop', _, _, _} tagged with a record name violates the declared type of #c_nil{anno::[any(),...]} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple' | 'c_var' | 'ibinary' | 'icatch' | 'ireceive1',[any(),...] | {_,_,_,_},_} | #c_cons{anno::[any(),...]} | #c_fname{anno::[any(),...]} | #iletrec{anno::{_,_,_,_},defs::[any(),...],body::[any(),...]} | #icase{anno::{_,_,_,_},args::[any()],clauses::[any()],fc::{_,_,_,_,_,_}} | #ireceive2{anno::{_,_,_,_},clauses::[any()],action::[any()]} | #ifun{anno::{_,_,_,_},id::[any(),...],vars::[any()],clauses::[any(),...],fc::{_,_,_,_,_,_}} | #imatch{anno::{_,_,_,_},guard::[],fc::{_,_,_,_,_,_}} | #itry{anno::{_,_,_,_},args::[any()],vars::[any(),...],body::[any(),...],evars::[any(),...],handler::[any(),...]} diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 b/lib/dialyzer/test/r9c_SUITE_data/results/asn1 index c11105b76d..1cf03346ee 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 +++ b/lib/dialyzer/test/r9c_SUITE_data/results/asn1 @@ -5,7 +5,7 @@ asn1ct.erl:1673: The pattern 'all' can never match the type 'asn1_module' | 'exc 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',_,_} +asn1ct_check.erl:2733: Matching of pattern {'type', Tag, _, _, _, _} tagged with a record name violates the declared type of 'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_} asn1ct_check.erl:2738: The pattern <_S, _> can never match since previous clauses completely covered the type <#state{},#'ObjectClassFieldType'{class::#objectclass{fields::maybe_improper_list() | {_,_,_,_}},fieldname::{_,maybe_improper_list()},type::'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_}}> asn1ct_check.erl:2887: The variable Other can never match since previous clauses completely covered the type any() asn1ct_check.erl:3188: The pattern <_S, [], B> can never match the type <#state{},{'SingleValue',_},{'ValueRange',_}> diff --git a/lib/dialyzer/test/small_SUITE_data/results/behaviour_info b/lib/dialyzer/test/small_SUITE_data/results/behaviour_info new file mode 100644 index 0000000000..2da4d26acb --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/behaviour_info @@ -0,0 +1,2 @@ + +with_bad_format_status.erl:12: The inferred type for the 1st argument of format_status/2 ('bad_arg') is not a supertype of 'normal' | 'terminate', which is expected type for this argument in the callback of the gen_server behaviour diff --git a/lib/dialyzer/test/small_SUITE_data/results/confusing_record_warning b/lib/dialyzer/test/small_SUITE_data/results/confusing_record_warning deleted file mode 100644 index ac3d89b02b..0000000000 --- a/lib/dialyzer/test/small_SUITE_data/results/confusing_record_warning +++ /dev/null @@ -1,3 +0,0 @@ - -confusing_record_warning.erl:18: Function test/1 has no local return -confusing_record_warning.erl:18: Matching of pattern {'r', [_]} tagged with a record name violates the declared type of #r{field::'binary' | 'undefined'} diff --git a/lib/dialyzer/test/small_SUITE_data/results/literals b/lib/dialyzer/test/small_SUITE_data/results/literals new file mode 100644 index 0000000000..03e161ca71 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/literals @@ -0,0 +1,14 @@ + +literals.erl:11: Function t1/0 has no local return +literals.erl:12: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:14: Function t2/0 has no local return +literals.erl:15: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:17: Function t3/0 has no local return +literals.erl:18: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:21: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:23: Function m1/1 has no local return +literals.erl:23: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer' | 'undefined'} +literals.erl:26: Function m2/1 has no local return +literals.erl:26: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer' | 'undefined'} +literals.erl:29: Function m3/1 has no local return +literals.erl:29: The pattern {{'r', 'a'}} can never match the type any() diff --git a/lib/dialyzer/test/small_SUITE_data/results/my_sofs b/lib/dialyzer/test/small_SUITE_data/results/my_sofs index bc97c08d62..0b933e6cd7 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/my_sofs +++ b/lib/dialyzer/test/small_SUITE_data/results/my_sofs @@ -1,3 +1,3 @@ -my_sofs.erl:34: The pattern {'Set', _, _} can never match the type #'OrdSet'{} -my_sofs.erl:54: The pattern {'Set', _, _} can never match the type #'OrdSet'{} +my_sofs.erl:34: Matching of pattern {'Set', _, _} tagged with a record name violates the declared type of #'OrdSet'{} +my_sofs.erl:54: Matching of pattern {'Set', _, _} tagged with a record name violates the declared type of #'OrdSet'{} diff --git a/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring b/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring new file mode 100644 index 0000000000..0ad6eee766 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring @@ -0,0 +1,3 @@ + +pretty_bitstring.erl:7: Function t/0 has no local return +pretty_bitstring.erl:8: The call binary:copy(#{#<1>(8, 1, 'integer', ['unsigned', 'big']), #<2>(8, 1, 'integer', ['unsigned', 'big']), #<3>(3, 1, 'integer', ['unsigned', 'big'])}#,2) breaks the contract (Subject,N) -> binary() when is_subtype(Subject,binary()), is_subtype(N,non_neg_integer()) diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_pat b/lib/dialyzer/test/small_SUITE_data/results/record_pat index 9a3f925e42..a46be6c451 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/record_pat +++ b/lib/dialyzer/test/small_SUITE_data/results/record_pat @@ -1,2 +1,2 @@ -record_pat.erl:14: The pattern {'foo', 'baz'} violates the declared type for #foo{} +record_pat.erl:14: Matching of pattern {'foo', 'baz'} tagged with a record name violates the declared type of #foo{bar::'undefined' | integer()} diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_test b/lib/dialyzer/test/small_SUITE_data/results/record_test index 9715f0dcfb..7060bfa200 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/record_test +++ b/lib/dialyzer/test/small_SUITE_data/results/record_test @@ -1,3 +1,3 @@ -record_test.erl:19: The pattern {'foo', _} can never match the type 'foo' +record_test.erl:19: Matching of pattern {'foo', _} tagged with a record name violates the declared type of 'foo' record_test.erl:21: The variable _ can never match since previous clauses completely covered the type 'foo' diff --git a/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning b/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning new file mode 100644 index 0000000000..2e417e1b2a --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning @@ -0,0 +1,3 @@ + +relevant_record_warning.erl:22: Function test/1 has no local return +relevant_record_warning.erl:23: Record construction #r{field::<<_:8>>} violates the declared type of field field::'binary' | 'undefined' diff --git a/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_bad_format_status.erl b/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_bad_format_status.erl new file mode 100644 index 0000000000..24591e08fa --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_bad_format_status.erl @@ -0,0 +1,12 @@ +-module(with_bad_format_status). + +-behaviour(gen_server). +-export([handle_call/3,handle_cast/2,handle_info/2, + code_change/3, init/1, terminate/2, format_status/2]). +handle_call(_, _, S) -> {noreply, S}. +handle_cast(_, S) -> {noreply, S}. +handle_info(_, S) -> {noreply, S}. +code_change(_, _, _) -> {error, not_implemented}. +init(_) -> {ok, state}. +terminate(_, _) -> ok. +format_status(bad_arg, _) -> ok. % optional callback diff --git a/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_format_status.erl b/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_format_status.erl new file mode 100644 index 0000000000..a56ff63d1d --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_format_status.erl @@ -0,0 +1,13 @@ +-module(with_format_status). + +-behaviour(gen_server). +-export([handle_call/3,handle_cast/2,handle_info/2, + code_change/3, init/1, terminate/2, format_status/2]). +-export([handle_call/3,handle_cast/2,handle_info/2]). +handle_call(_, _, S) -> {noreply, S}. +handle_cast(_, S) -> {noreply, S}. +handle_info(_, S) -> {noreply, S}. +code_change(_, _, _) -> {error, not_implemented}. +init(_) -> {ok, state}. +terminate(_, _) -> ok. +format_status(normal, _) -> ok. % optional callback diff --git a/lib/dialyzer/test/small_SUITE_data/src/fun2ms.erl b/lib/dialyzer/test/small_SUITE_data/src/fun2ms.erl new file mode 100644 index 0000000000..9e7df85e4c --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/fun2ms.erl @@ -0,0 +1,21 @@ +-module(fun2ms). +-export([return/0]). +-include_lib("stdlib/include/ms_transform.hrl"). + +-record(snapshot, {id :: integer(), arg1 :: atom(), arg2 :: tuple()}). + +return() -> + TableId = ets:new(table, [public, {keypos, #snapshot.id}]), + + ets:insert(TableId, [#snapshot{id = 1, arg1 = hard, arg2 = {1,2}}, + #snapshot{id = 2, arg1 = rock, arg2 = {1,2}}, + #snapshot{id = 3, arg1 = hallelujah, arg2 = + {1,2}}]), + + + Example = ets:fun2ms( + fun(#snapshot{id = Arg1, arg1 = Arg2}) -> + {Arg1, Arg2} + end), + + ets:select(TableId, Example). diff --git a/lib/dialyzer/test/small_SUITE_data/src/literals.erl b/lib/dialyzer/test/small_SUITE_data/src/literals.erl new file mode 100644 index 0000000000..abd7033712 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/literals.erl @@ -0,0 +1,33 @@ +-module(literals). + +%% Bad records inside structures used to be ignored. The reason: +%% v3_core:unfold() does not annotate the parts of a literal. +%% This example does not work perfectly yet, in particular Maps. + +-export([t1/0, t2/0, t3/0, t4/0, m1/1, m2/1, m3/1, m4/1]). + +-record(r, {id :: integer}). + +t1() -> + #r{id = a}. % violation + +t2() -> + [#r{id = a}]. % violation + +t3() -> + {#r{id = a}}. % violation + +t4() -> + #{a => #r{id = a}}. % violation found, but t4() returns... (bug) + +m1(#r{id = a}) -> % violation + ok. + +m2([#r{id = a}]) -> % violation + ok. + +m3({#r{id = a}}) -> % can never match; not so good + ok. + +m4(#{a := #r{id = a}}) -> % violation not found + ok. diff --git a/lib/dialyzer/test/small_SUITE_data/src/predef2.erl b/lib/dialyzer/test/small_SUITE_data/src/predef2.erl deleted file mode 100644 index b1d941a49a..0000000000 --- a/lib/dialyzer/test/small_SUITE_data/src/predef2.erl +++ /dev/null @@ -1,56 +0,0 @@ --module(predef2). - --export([array/1, dict/1, digraph/1, digraph2/1, gb_set/1, gb_tree/1, - queue/1, set/1, tid/0, tid2/0]). - --export_type([array/0, digraph/0, gb_set/0]). - --spec array(array()) -> array:array(). - -array(A) -> - array:relax(A). - --spec dict(dict()) -> dict:dict(). - -dict(D) -> - dict:store(1, a, D). - --spec digraph(digraph()) -> [digraph:edge()]. - -digraph(G) -> - digraph:edges(G). - --spec digraph2(digraph:graph()) -> [digraph:edge()]. - -digraph2(G) -> - digraph:edges(G). - --spec gb_set(gb_set()) -> gb_sets:set(). - -gb_set(S) -> - gb_sets:balance(S). - --spec gb_tree(gb_tree()) -> gb_trees:tree(). - -gb_tree(S) -> - gb_trees:balance(S). - --spec queue(queue()) -> queue:queue(). - -queue(Q) -> - queue:reverse(Q). - --spec set(set()) -> sets:set(). - -set(S) -> - sets:union([S]). - --spec tid() -> tid(). - -tid() -> - ets:new(tid, []). - --spec tid2() -> ets:tid(). - -tid2() -> - ets:new(tid, []). diff --git a/lib/dialyzer/test/small_SUITE_data/src/pretty_bitstring.erl b/lib/dialyzer/test/small_SUITE_data/src/pretty_bitstring.erl new file mode 100644 index 0000000000..3dbf5ab7a7 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/pretty_bitstring.erl @@ -0,0 +1,8 @@ +%% Prettyprint bitstrings. + +-module(pretty_bitstring). + +-export([t/0]). + +t() -> + binary:copy(<<1,2,3:3>>,2). diff --git a/lib/dialyzer/test/small_SUITE_data/src/confusing_record_warning.erl b/lib/dialyzer/test/small_SUITE_data/src/relevant_record_warning.erl index 8af74e0914..3ff65458df 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/confusing_record_warning.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/relevant_record_warning.erl @@ -1,3 +1,7 @@ +%% Formerly confusing_record_warning.erl. +%% The warning output is relevant as of Erlang/OTP 17.1. +%% The original comment kept below. + %%--------------------------------------------------------------------- %% A user complained that dialyzer produces a weird warning for the %% following program. I explained to him that there is an implicit @@ -9,7 +13,7 @@ %% The pattern {'r', [_]} can never match the type any() %% We should clearly give some less confusing warning in this case. %%--------------------------------------------------------------------- --module(confusing_record_warning). +-module(relevant_record_warning). -export([test/1]). diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 95d2464e1d..b0cb3ec4f9 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 2.7 +DIALYZER_VSN = 2.7.1 diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index 68e69dbfeb..d89e1dfd26 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -42,6 +42,135 @@ first.</p> <!-- ===================================================================== --> +<section><title>diameter 1.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Improve robustness.</p> + <p> + Counters returned by diameter:service_info/2 now only + count messages known to the dictionary in question, so + that an attacker cannot cause arbitrarily many counters + to be created.</p> + <p> + Messages to the Erlang log have been minimized, and those + related to traffic have been removed entirely since an + attacker could cause a node to be logged to death. + Consequently, the default answer_errors configuration has + been changed from report to discard. A service needs to + be restarted for the change in default to take effect.</p> + <p> + Own Id: OTP-11721</p> + </item> + <item> + <p> + Fix request table leak.</p> + <p> + Outgoing Diameter requests are stored in a table until an + answer is received or times out. Calling + diameter:stop_service/1 before this took place would + orphan the entries, resulting in a memory leak.</p> + <p> + Own Id: OTP-11893</p> + </item> + <item> + <p> + Fix broken SCTP transport.</p> + <p> + OTP-11593 caused the sending of answer messages over SCTP + to fail.</p> + <p> + Own Id: OTP-11901 Aux Id: OTP-11593 </p> + </item> + <item> + <p> + Fix watchdog process leak.</p> + <p> + A failed capabilities exchange on a listening transport + would orphan a process, causing a memory leak.</p> + <p> + Own Id: OTP-11934</p> + </item> + <item> + <p> + Fix incorrect handling of incoming DPR.</p> + <p> + In the case of a listening transport, a reconnection by a + peer following DPR could transition the watchdog state to + REOPEN instead of OKAY.</p> + <p> + Own Id: OTP-11938</p> + </item> + <item> + <p> + Fix handling of AVP length errors on unknown AVPs.</p> + <p> + An AVP (Header) length that pointed past the end of the + message was not flagged as a 5014 error in this case. + Moreover, encoding such an AVP in the Failed-AVP of an + answer message as a consequence of other errors (eg. + M-bit, resulting in 5001) failed if the AVP contained a + complete header.</p> + <p> + Own Id: OTP-11946</p> + </item> + <item> + <p> + Fix broken check in dictionary compilation.</p> + <p> + That an AVP specified in the content of a @codecs or + @custom_types section was undefined went undetected, + causing compilation to fail when attempting to lookup the + AVP's type.</p> + <p> + Own Id: OTP-11958</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add result code counters for CEA, DWA, and DPA.</p> + <p> + In addition to the existing result code counters on other + answer messages.</p> + <p> + Own Id: OTP-11891</p> + </item> + <item> + <p> + Add best-effort decode of AVPs within Failed-AVP.</p> + <p> + OTP-11007 disabled the decode of AVPs in Failed-AVP since + errors could cause the decode of Failed-AVP itself to + fail. Component AVPs are now decoded if possible, + otherwise not. AVPs of type Grouped are decoded as much + as possible, as deeply as possible.</p> + <p> + Own Id: OTP-11936 Aux Id: OTP-11007 </p> + </item> + <item> + <p> + Add counters for encode errors in outgoing Diameter + messages.</p> + <p> + In addition to the existing counters on decode errors. + The latter now count independently of result codes in + answer messages since decode errors do not preclude the + presence of a result code.</p> + <p> + Own Id: OTP-11937</p> + </item> + </list> + </section> + +</section> + <section><title>diameter 1.6</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src index b7b9662383..3b6e259f5a 100644 --- a/lib/diameter/src/diameter.appup.src +++ b/lib/diameter/src/diameter.appup.src @@ -43,7 +43,7 @@ {load_module, diameter_gen_base_rfc6733}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc3588}, - {load_module, diameter_gen_accounting}, + {load_module, diameter_gen_base_accounting}, {load_module, diameter_gen_relay}, {load_module, diameter_codec}, {load_module, diameter_sctp}]} @@ -67,7 +67,7 @@ {"1.6", [{load_module, diameter_sctp}, {load_module, diameter_codec}, {load_module, diameter_gen_relay}, - {load_module, diameter_gen_accounting}, + {load_module, diameter_gen_base_accounting}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc6733}, diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml index d7cbfa1fdc..b3440ce6e1 100644 --- a/lib/edoc/doc/src/notes.xml +++ b/lib/edoc/doc/src/notes.xml @@ -31,6 +31,25 @@ <p>This document describes the changes made to the EDoc application.</p> +<section><title>Edoc 0.7.14</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> The default encoding for Erlang source files is now + UTF-8. As a temporary measure to ease the transition from + the old default of Latin-1, if EDoc encounters byte + sequences that are not valid UTF-8 sequences, EDoc will + re-try in Latin-1 mode. This workaround will be removed + in a future release. </p> + <p> + Own Id: OTP-12008</p> + </item> + </list> + </section> + +</section> + <section><title>Edoc 0.7.13</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl index a87a8471e3..983f04e8b6 100644 --- a/lib/edoc/src/edoc.erl +++ b/lib/edoc/src/edoc.erl @@ -696,15 +696,44 @@ read_source_2(Name, Opts) -> %% The line of the dot token will be copied to the integer token. parse_file(Name, Includes, Macros) -> - case epp:open(Name, Includes, Macros) of - {ok, Epp} -> - try {ok, parse_file(Epp)} + case parse_file(utf8, Name, Includes, Macros) of + invalid_unicode -> + parse_file(latin1, Name, Includes, Macros); + Ret -> + Ret + end. + +parse_file(DefEncoding, Name, Includes, Macros) -> + Options = [{name, Name}, + {includes, Includes}, + {macros, Macros}, + {default_encoding, DefEncoding}], + case epp:open([extra | Options]) of + {ok, Epp, Extra} -> + try parse_file(Epp) of + Forms -> + Encoding = proplists:get_value(encoding, Extra), + case find_invalid_unicode(Forms) of + invalid_unicode when Encoding =/= utf8 -> + invalid_unicode; + _ -> + {ok, Forms} + end after _ = epp:close(Epp) end; Error -> Error end. +find_invalid_unicode([H|T]) -> + case H of + {error,{_Line,file_io_server,invalid_unicode}} -> + invalid_unicode; + _Other -> + find_invalid_unicode(T) + end; +find_invalid_unicode([]) -> none. + parse_file(Epp) -> case scan_and_parse(Epp) of {ok, Form} -> diff --git a/lib/edoc/src/edoc_data.erl b/lib/edoc/src/edoc_data.erl index f88ba05f4b..eceb5cb1bd 100644 --- a/lib/edoc/src/edoc_data.erl +++ b/lib/edoc/src/edoc_data.erl @@ -173,21 +173,34 @@ callbacks(Es, Module, Env, Opts) -> lists:keymember(callback, 1, Module#module.attributes) of true -> - try (Module#module.name):behaviour_info(callbacks) of - Fs -> - Fs1 = [{F,A} || {F,A} <- Fs, is_atom(F), is_integer(A)], - if Fs1 =:= [] -> - []; - true -> - [{callbacks, - [callback(F, Env, Opts) || F <- Fs1]}] - end - catch - _:_ -> [] - end; + M = Module#module.name, + Fs = get_callback_functions(M, callbacks), + Os1 = get_callback_functions(M, optional_callbacks), + Fs1 = [FA || FA <- Fs, not lists:member(FA, Os1)], + Req = if Fs1 =:= [] -> + []; + true -> + [{callbacks, + [callback(FA, Env, Opts) || FA <- Fs1]}] + end, + Opt = if Os1 =:= [] -> + []; + true -> + [{optional_callbacks, + [callback(FA, Env, Opts) || FA <- Os1]}] + end, + Req ++ Opt; false -> [] end. +get_callback_functions(M, Callbacks) -> + try + [FA || {F, A} = FA <- M:behaviour_info(Callbacks), + is_atom(F), is_integer(A), A >= 0] + catch + _:_ -> [] + end. + %% <!ELEMENT callback EMPTY> %% <!ATTLIST callback %% name CDATA #REQUIRED diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl index e164ff060f..c9761dc2a6 100644 --- a/lib/edoc/src/edoc_layout.erl +++ b/lib/edoc/src/edoc_layout.erl @@ -701,6 +701,8 @@ deprecated(Es, S) -> end. behaviours(Es, Name) -> + CBs = get_content(callbacks, Es), + OCBs = get_content(optional_callbacks, Es), (case get_elem(behaviour, Es) of [] -> []; Es1 -> @@ -709,13 +711,24 @@ behaviours(Es, Name) -> ?NL] end ++ - case get_content(callbacks, Es) of - [] -> []; - Es1 -> + if CBs =:= [], OCBs =:= [] -> + []; + true -> + Req = if CBs =:= [] -> + []; + true -> + [br, " Required callback functions: "] + ++ seq(fun callback/1, CBs, ["."]) + end, + Opt = if OCBs =:= [] -> + []; + true -> + [br, " Optional callback functions: "] + ++ seq(fun callback/1, OCBs, ["."]) + end, [{p, ([{b, ["This module defines the ", {tt, [Name]}, - " behaviour."]}, - br, " Required callback functions: "] - ++ seq(fun callback/1, Es1, ["."]))}, + " behaviour."]}] + ++ Req ++ Opt)}, ?NL] end). @@ -885,7 +898,7 @@ t_map(Es) -> ["#{"] ++ seq(fun t_utype_elem/1, Es, ["}"]). t_map_field([K,V]) -> - [t_utype_elem(K) ++ " => " ++ t_utype_elem(V)]. + t_utype_elem(K) ++ [" => "] ++ t_utype_elem(V). t_record(E, Es) -> Name = ["#"] ++ t_type(get_elem(atom, Es)), @@ -1082,6 +1095,10 @@ ot_type([#xmlElement{name = nonempty_list, content = Es}]) -> ot_nonempty_list(Es); ot_type([#xmlElement{name = tuple, content = Es}]) -> ot_tuple(Es); +ot_type([#xmlElement{name = map, content = Es}]) -> + ot_map(Es); +ot_type([#xmlElement{name = map_field, content = Es}]) -> + ot_map_field(Es); ot_type([#xmlElement{name = 'fun', content = Es}]) -> ot_fun(Es); ot_type([#xmlElement{name = record, content = Es}]) -> @@ -1138,6 +1155,12 @@ ot_nonempty_list(Es) -> ot_tuple(Es) -> {type,0,tuple,[ot_utype_elem(E) || E <- Es]}. +ot_map(Es) -> + {type,0,map,[ot_utype_elem(E) || E <- Es]}. + +ot_map_field(Es) -> + {type,0,map_field_assoc,[ot_utype_elem(E) || E <- Es]}. + ot_fun(Es) -> Range = ot_utype(get_elem(type, Es)), Args = [ot_utype_elem(A) || A <- get_content(argtypes, Es)], diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl index 211a354c74..3bf81c6503 100644 --- a/lib/edoc/src/edoc_specs.erl +++ b/lib/edoc/src/edoc_specs.erl @@ -362,7 +362,7 @@ d2e({type,_,map,any}) -> #t_map{ types = []}; d2e({type,_,map,Es}) -> #t_map{ types = d2e(Es) }; -d2e({type,_,map_field_assoc,K,V}) -> +d2e({type,_,map_field_assoc,[K,V]}) -> #t_map_field{ k_type = d2e(K), v_type=d2e(V) }; d2e({type,_,map_field_exact,K,V}) -> #t_map_field{ k_type = d2e(K), v_type=d2e(V) }; @@ -388,6 +388,9 @@ d2e({record_field,L,_Name}=F) -> d2e({type,_,Name,Types0}) -> Types = d2e(Types0), typevar_anno(#t_type{name = #t_name{name = Name}, args = Types}, Types); +d2e({user_type,_,Name,Types0}) -> + Types = d2e(Types0), + typevar_anno(#t_type{name = #t_name{name = Name}, args = Types}, Types); d2e({var,_,'_'}) -> #t_type{name = #t_name{name = ?TOP_TYPE}}; d2e({var,_,TypeName}) -> diff --git a/lib/edoc/src/edoc_tags.erl b/lib/edoc/src/edoc_tags.erl index 264a533a52..82a1b72d84 100644 --- a/lib/edoc/src/edoc_tags.erl +++ b/lib/edoc/src/edoc_tags.erl @@ -329,10 +329,7 @@ parse_typedef(Data, Line, _Env, Where) -> NAs = length(As), case edoc_types:is_predefined(T, NAs) of true -> - case - edoc_types:is_new_predefined(T, NAs) - orelse edoc_types:is_predefined_otp_type(T, NAs) - of + case edoc_types:is_new_predefined(T, NAs) of false -> throw_error(Line, {"redefining built-in type '~w'.", [T]}); @@ -499,7 +496,6 @@ check_used_type(#t_name{name = N, module = Mod}=Name, Args, P, LocalTypes) -> Mod =/= [] orelse lists:member(TypeName, ets:lookup(DT, Name)) orelse edoc_types:is_predefined(N, NArgs) - orelse edoc_types:is_predefined_otp_type(N, NArgs) orelse lists:member(TypeName, LocalTypes) of true -> diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl index d4e00d3ecd..2f21eb24b6 100644 --- a/lib/edoc/src/edoc_types.erl +++ b/lib/edoc/src/edoc_types.erl @@ -25,7 +25,7 @@ -module(edoc_types). --export([is_predefined/2, is_new_predefined/2, is_predefined_otp_type/2, +-export([is_predefined/2, is_new_predefined/2, to_ref/1, to_xml/2, to_label/1, arg_names/1, set_arg_names/2, arg_descs/1, range_desc/1]). @@ -34,67 +34,13 @@ -include("edoc_types.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; % kept for backwards compatibility -is_predefined(char, 0) -> true; is_predefined(cons, 2) -> true; is_predefined(deep_string, 0) -> true; -is_predefined(float, 0) -> true; -is_predefined(function, 0) -> true; -is_predefined(integer, 0) -> true; -is_predefined(list, 0) -> true; -is_predefined(list, 1) -> true; -is_predefined(nil, 0) -> true; -is_predefined(none, 0) -> true; -is_predefined(no_return, 0) -> true; -is_predefined(number, 0) -> true; -is_predefined(pid, 0) -> true; -is_predefined(port, 0) -> true; -is_predefined(reference, 0) -> true; -is_predefined(string, 0) -> true; -is_predefined(term, 0) -> true; -is_predefined(tuple, 0) -> true; -is_predefined(F, A) -> is_new_predefined(F, A). +is_predefined(F, A) -> erl_internal:is_type(F, A). -%% Should eventually be coalesced with is_predefined/2. -is_new_predefined(arity, 0) -> true; -is_new_predefined(bitstring, 0) -> true; -is_new_predefined(boolean, 0) -> true; -is_new_predefined(byte, 0) -> true; -is_new_predefined(iodata, 0) -> true; -is_new_predefined(iolist, 0) -> true; is_new_predefined(map, 0) -> true; -is_new_predefined(maybe_improper_list, 0) -> true; -is_new_predefined(maybe_improper_list, 2) -> true; -is_new_predefined(mfa, 0) -> true; -is_new_predefined(module, 0) -> true; -is_new_predefined(neg_integer, 0) -> true; -is_new_predefined(node, 0) -> true; -is_new_predefined(non_neg_integer, 0) -> true; -is_new_predefined(nonempty_improper_list, 2) -> true; -is_new_predefined(nonempty_list, 0) -> true; -is_new_predefined(nonempty_list, 1) -> true; -is_new_predefined(nonempty_maybe_improper_list, 0) -> true; -is_new_predefined(nonempty_maybe_improper_list, 2) -> true; -is_new_predefined(nonempty_string, 0) -> true; -is_new_predefined(pos_integer, 0) -> true; -is_new_predefined(timeout, 0) -> true; is_new_predefined(_, _) -> false. -%% The following types will be removed later, but they are currently -%% kind of built-in. -is_predefined_otp_type(array, 0) -> true; -is_predefined_otp_type(dict, 0) -> true; -is_predefined_otp_type(digraph, 0) -> true; -is_predefined_otp_type(gb_set, 0) -> true; -is_predefined_otp_type(gb_tree, 0) -> true; -is_predefined_otp_type(queue, 0) -> true; -is_predefined_otp_type(set, 0) -> true; -is_predefined_otp_type(_, _) -> false. - to_ref(#t_typedef{name = N}) -> to_ref(N); to_ref(#t_def{name = N}) -> @@ -129,8 +75,7 @@ to_xml(#t_type{name = N, args = As}, Env) -> Predef = case N of #t_name{module = [], name = T} -> NArgs = length(As), - (is_predefined(T, NArgs) - orelse is_predefined_otp_type(T, NArgs)); + is_predefined(T, NArgs); _ -> false end, diff --git a/lib/edoc/test/edoc_SUITE.erl b/lib/edoc/test/edoc_SUITE.erl index c9c7811afb..c63660c8c0 100644 --- a/lib/edoc/test/edoc_SUITE.erl +++ b/lib/edoc/test/edoc_SUITE.erl @@ -22,12 +22,12 @@ init_per_group/2,end_per_group/2]). %% Test cases --export([app/1,appup/1,build_std/1,build_map_module/1]). +-export([app/1,appup/1,build_std/1,build_map_module/1,otp_12008/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [app,appup,build_std,build_map_module]. + [app,appup,build_std,build_map_module,otp_12008]. groups() -> []. @@ -77,3 +77,21 @@ build_map_module(Config) when is_list(Config) -> Filename = filename:join(DataDir, "map_module.erl"), ok = edoc:file(Filename, [{dir, PrivDir}]), ok. + +otp_12008(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + Un1 = filename:join(DataDir, "un1.erl"), + Un2 = filename:join(DataDir, "un2.erl"), + Un3 = filename:join(DataDir, "un3.erl"), + %% epp_dodger + Opts1 = [{dir, PrivDir}], + ok = edoc:files([Un1], Opts1), + ok = edoc:files([Un2], Opts1), + {'EXIT', error} = (catch edoc:files([Un3], Opts1)), + %% epp + Opts2 = [{preprocess, true}, {dir, PrivDir}], + ok = edoc:files([Un1], Opts2), + ok = edoc:files([Un2], Opts2), + {'EXIT', error} = (catch edoc:files([Un3], Opts2)), + ok. diff --git a/lib/edoc/test/edoc_SUITE_data/map_module.erl b/lib/edoc/test/edoc_SUITE_data/map_module.erl index 94ee7e6f26..f242721637 100644 --- a/lib/edoc/test/edoc_SUITE_data/map_module.erl +++ b/lib/edoc/test/edoc_SUITE_data/map_module.erl @@ -1,6 +1,6 @@ -module(map_module). --export([foo1/1,foo2/3]). +-export([foo1/1,foo2/3,start_child/2]). %% @type wazzup() = integer() %% @type some_type() = map() @@ -25,3 +25,43 @@ foo1(#{ a:= 1, b := V}) -> V. Map :: #{ get => 'value', 'value' => binary()}) -> binary(). foo2(Type1, {a,#{ "a" := _}}, #{get := value, value := B}) when is_map(Type1) -> B. + +%% from supervisor 18.0 + +-type child() :: 'undefined' | pid(). +-type child_id() :: term(). +-type mfargs() :: {M :: module(), F :: atom(), A :: [term()] | undefined}. +-type modules() :: [module()] | 'dynamic'. +-type restart() :: 'permanent' | 'transient' | 'temporary'. +-type shutdown() :: 'brutal_kill' | timeout(). +-type worker() :: 'worker' | 'supervisor'. +-type sup_ref() :: (Name :: atom()) + | {Name :: atom(), Node :: node()} + | {'global', Name :: atom()} + | {'via', Module :: module(), Name :: any()} + | pid(). +-type child_spec() :: #{name => child_id(), % mandatory + start => mfargs(), % mandatory + restart => restart(), % optional + shutdown => shutdown(), % optional + type => worker(), % optional + modules => modules()} % optional + | {Id :: child_id(), + StartFunc :: mfargs(), + Restart :: restart(), + Shutdown :: shutdown(), + Type :: worker(), + Modules :: modules()}. + +-type startchild_err() :: 'already_present' + | {'already_started', Child :: child()} | term(). +-type startchild_ret() :: {'ok', Child :: child()} + | {'ok', Child :: child(), Info :: term()} + | {'error', startchild_err()}. + + +-spec start_child(SupRef, ChildSpec) -> startchild_ret() when + SupRef :: sup_ref(), + ChildSpec :: child_spec() | (List :: [term()]). +start_child(Supervisor, ChildSpec) -> + {Supervisor,ChildSpec}. diff --git a/lib/edoc/test/edoc_SUITE_data/un1.erl b/lib/edoc/test/edoc_SUITE_data/un1.erl new file mode 100644 index 0000000000..0c48e7f940 --- /dev/null +++ b/lib/edoc/test/edoc_SUITE_data/un1.erl @@ -0,0 +1,7 @@ +-module(un1). + +-export([t/0]). + +%% @doc F�pp +t() -> + �rlig. diff --git a/lib/edoc/test/edoc_SUITE_data/un2.erl b/lib/edoc/test/edoc_SUITE_data/un2.erl new file mode 100644 index 0000000000..a6d13f4723 --- /dev/null +++ b/lib/edoc/test/edoc_SUITE_data/un2.erl @@ -0,0 +1,8 @@ +-module(un2). +%% coding: latin-1 + +-export([t/0]). + +%% @doc F�pp +t() -> + �rlig. diff --git a/lib/edoc/test/edoc_SUITE_data/un3.erl b/lib/edoc/test/edoc_SUITE_data/un3.erl new file mode 100644 index 0000000000..fbe9591dce --- /dev/null +++ b/lib/edoc/test/edoc_SUITE_data/un3.erl @@ -0,0 +1,8 @@ +-module(un3). +%% coding: utf-8 + +-export([t/0]). + +%% @doc F�pp +t() -> + �rlig. diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk index 0172aac48b..281a792118 100644 --- a/lib/edoc/vsn.mk +++ b/lib/edoc/vsn.mk @@ -1 +1 @@ -EDOC_VSN = 0.7.13 +EDOC_VSN = 0.7.14 diff --git a/lib/erl_docgen/src/docgen_otp_specs.erl b/lib/erl_docgen/src/docgen_otp_specs.erl index 886194598f..cbdbbbee80 100644 --- a/lib/erl_docgen/src/docgen_otp_specs.erl +++ b/lib/erl_docgen/src/docgen_otp_specs.erl @@ -388,8 +388,10 @@ t_type([#xmlElement{name = nonempty_list, content = Es}]) -> t_nonempty_list(Es); t_type([#xmlElement{name = tuple, content = Es}]) -> t_tuple(Es); -t_type([#xmlElement{name = map}]) -> - t_map(); +t_type([#xmlElement{name = map, content = Es}]) -> + t_map(Es); +t_type([#xmlElement{name = map_field, content = Es}]) -> + t_map_field(Es); t_type([#xmlElement{name = 'fun', content = Es}]) -> ["fun("] ++ t_fun(Es) ++ [")"]; t_type([E = #xmlElement{name = record, content = Es}]) -> @@ -432,8 +434,11 @@ t_nonempty_list(Es) -> t_tuple(Es) -> ["{"] ++ seq(fun t_utype_elem/1, Es, ["}"]). -t_map() -> - ["map()"]. +t_map(Es) -> + ["#{"] ++ seq(fun t_utype_elem/1, Es, ["}"]). + +t_map_field([K,V]) -> + [t_utype_elem(K) ++ " => " ++ t_utype_elem(V)]. t_fun(Es) -> ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es), @@ -550,6 +555,10 @@ ot_type([#xmlElement{name = nonempty_list, content = Es}]) -> ot_nonempty_list(Es); ot_type([#xmlElement{name = tuple, content = Es}]) -> ot_tuple(Es); +ot_type([#xmlElement{name = map, content = Es}]) -> + ot_map(Es); +ot_type([#xmlElement{name = map_field, content = Es}]) -> + ot_map_field(Es); ot_type([#xmlElement{name = 'fun', content = Es}]) -> ot_fun(Es); ot_type([#xmlElement{name = record, content = Es}]) -> @@ -606,6 +615,12 @@ ot_nonempty_list(Es) -> ot_tuple(Es) -> {type,0,tuple,[ot_utype_elem(E) || E <- Es]}. +ot_map(Es) -> + {type,0,map,[ot_utype_elem(E) || E <- Es]}. + +ot_map_field(Es) -> + {type,0,map_field_assoc,[ot_utype_elem(E) || E <- Es]}. + ot_fun(Es) -> Range = ot_utype(get_elem(type, Es)), Args = [ot_utype_elem(A) || A <- get_content(argtypes, Es)], diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in index d511f2e240..ef78f0f87b 100644 --- a/lib/erl_interface/configure.in +++ b/lib/erl_interface/configure.in @@ -311,6 +311,26 @@ else fi fi +dnl ---------------------------------------------------------------------- +dnl Enable -fsanitize= flags. +dnl ---------------------------------------------------------------------- + +m4_define(DEFAULT_SANITIZERS, [address,undefined]) +AC_ARG_ENABLE( + sanitizers, + AS_HELP_STRING( + [--enable-sanitizers@<:@=comma-separated list of sanitizers@:>@], + [Default=DEFAULT_SANITIZERS]), +[ +case "$enableval" in + no) sanitizers= ;; + yes) sanitizers="-fsanitize=DEFAULT_SANITIZERS" ;; + *) sanitizers="-fsanitize=$enableval" ;; +esac +CFLAGS="$CFLAGS $sanitizers" +LDFLAGS="$LDFLAGS $sanitizers" +]) + # --------------------------------------------------------------------------- # XXX # --------------------------------------------------------------------------- diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml index ab6f4179d6..3f85af8956 100644 --- a/lib/erl_interface/doc/src/notes.xml +++ b/lib/erl_interface/doc/src/notes.xml @@ -30,6 +30,21 @@ </header> <p>This document describes the changes made to the Erl_interface application.</p> +<section><title>Erl_Interface 3.7.17</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Now works with Visual Studio.</p> + <p> + Own Id: OTP-11984</p> + </item> + </list> + </section> + +</section> + <section><title>Erl_Interface 3.7.16</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk index 8731283265..b1e612a9eb 100644 --- a/lib/erl_interface/vsn.mk +++ b/lib/erl_interface/vsn.mk @@ -1,2 +1,2 @@ -EI_VSN = 3.7.16 +EI_VSN = 3.7.17 ERL_INTERFACE_VSN = $(EI_VSN) diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl index 0350f9bf6e..cbbc6fbc15 100644 --- a/lib/eunit/src/eunit_data.erl +++ b/lib/eunit/src/eunit_data.erl @@ -440,13 +440,8 @@ parse_function({M, F}) when is_atom(M), is_atom(F) -> parse_function(F) -> bad_test(F). -check_arity(F, N, T) when is_function(F) -> - case erlang:fun_info(F, arity) of - {arity, N} -> - ok; - _ -> - bad_test(T) - end; +check_arity(F, N, _) when is_function(F, N) -> + ok; check_arity(_, _, T) -> bad_test(T). diff --git a/lib/hipe/cerl/cerl_prettypr.erl b/lib/hipe/cerl/cerl_prettypr.erl index 9a3873f46d..f4a67439d6 100644 --- a/lib/hipe/cerl/cerl_prettypr.erl +++ b/lib/hipe/cerl/cerl_prettypr.erl @@ -1,7 +1,7 @@ %% ===================================================================== %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -476,13 +476,20 @@ lay_literal(Node, Ctxt) -> %% that could represent printable characters - we %% always print an integer. text(int_lit(Node)); - V when is_binary(V) -> - lay_binary(c_binary([c_bitstr(abstract(B), - abstract(8), + V when is_bitstring(V) -> + Val = fun(I) when is_integer(I) -> I; + (B) when is_bitstring(B) -> + BZ = bit_size(B), <<BV:BZ>> = B, BV + end, + Sz = fun(I) when is_integer(I) -> 8; + (B) when is_bitstring(B) -> bit_size(B) + end, + lay_binary(c_binary([c_bitstr(abstract(Val(B)), + abstract(Sz(B)), abstract(1), abstract(integer), abstract([unsigned, big])) - || B <- binary_to_list(V)]), + || B <- bitstring_to_list(V)]), Ctxt); [] -> text("[]"); diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 67661130a5..b8ae31b622 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -40,7 +40,6 @@ any_none_or_unit/1, lookup_record/3, max/2, - module_builtin_opaques/1, min/2, number_max/1, number_max/2, number_min/1, number_min/2, @@ -72,7 +71,7 @@ t_contains_opaque/1, t_contains_opaque/2, t_decorate_with_opaque/3, t_elements/1, - t_find_opaque_mismatch/2, + t_find_opaque_mismatch/3, t_find_unknown_opaque/3, t_fixnum/0, t_map/2, @@ -188,7 +187,6 @@ t_subtract_list/2, t_sup/1, t_sup/2, - t_tid/0, t_timeout/0, t_to_string/1, t_to_string/2, @@ -464,16 +462,6 @@ has_opaque_subtype(T) -> t_opaque_structure(?opaque(Elements)) -> t_sup([Struct || #opaque{struct = Struct} <- ordsets:to_list(Elements)]). --spec t_opaque_modules(erl_type()) -> [module()]. - -t_opaque_modules(?opaque(Elements)) -> - case ordsets:size(Elements) of - 1 -> - [#opaque{mod = Mod}] = set_to_list(Elements), - [Mod]; - _ -> throw({error, "Unexpected multiple opaque types"}) - end. - -spec t_contains_opaque(erl_type()) -> boolean(). t_contains_opaque(Type) -> @@ -530,39 +518,51 @@ list_contains_opaque(List, Opaques) -> %% The first argument of the function is the pattern and its second %% argument the type we are matching against the pattern. --spec t_find_opaque_mismatch(erl_type(), erl_type()) -> 'error' | {'ok', erl_type(), erl_type()}. +-spec t_find_opaque_mismatch(erl_type(), erl_type(), [erl_type()]) -> + 'error' | {'ok', erl_type(), erl_type()}. -t_find_opaque_mismatch(T1, T2) -> - t_find_opaque_mismatch(T1, T2, T2). +t_find_opaque_mismatch(T1, T2, Opaques) -> + t_find_opaque_mismatch(T1, T2, T2, Opaques). -t_find_opaque_mismatch(?any, _Type, _TopType) -> error; -t_find_opaque_mismatch(?none, _Type, _TopType) -> error; -t_find_opaque_mismatch(?list(T1, Tl1, _), ?list(T2, Tl2, _), TopType) -> - t_find_opaque_mismatch_ordlists([T1, Tl1], [T2, Tl2], TopType); -t_find_opaque_mismatch(_T1, ?opaque(_) = T2, TopType) -> {ok, TopType, T2}; -t_find_opaque_mismatch(?opaque(_) = T1, _T2, TopType) -> +t_find_opaque_mismatch(?any, _Type, _TopType, _Opaques) -> error; +t_find_opaque_mismatch(?none, _Type, _TopType, _Opaques) -> error; +t_find_opaque_mismatch(?list(T1, Tl1, _), ?list(T2, Tl2, _), TopType, Opaques) -> + t_find_opaque_mismatch_ordlists([T1, Tl1], [T2, Tl2], TopType, Opaques); +t_find_opaque_mismatch(T1, ?opaque(_) = T2, TopType, Opaques) -> + case is_opaque_type(T2, Opaques) of + false -> {ok, TopType, T2}; + true -> + t_find_opaque_mismatch(T1, t_opaque_structure(T2), TopType, Opaques) + end; +t_find_opaque_mismatch(?opaque(_) = T1, T2, TopType, Opaques) -> %% The generated message is somewhat misleading: - {ok, TopType, T1}; -t_find_opaque_mismatch(?product(T1), ?product(T2), TopType) -> - t_find_opaque_mismatch_ordlists(T1, T2, TopType); -t_find_opaque_mismatch(?tuple(T1, Arity, _), ?tuple(T2, Arity, _), TopType) -> - t_find_opaque_mismatch_ordlists(T1, T2, TopType); -t_find_opaque_mismatch(?tuple(_, _, _) = T1, ?tuple_set(_) = T2, TopType) -> + case is_opaque_type(T1, Opaques) of + false -> {ok, TopType, T1}; + true -> + t_find_opaque_mismatch(t_opaque_structure(T1), T2, TopType, Opaques) + end; +t_find_opaque_mismatch(?product(T1), ?product(T2), TopType, Opaques) -> + t_find_opaque_mismatch_ordlists(T1, T2, TopType, Opaques); +t_find_opaque_mismatch(?tuple(T1, Arity, _), ?tuple(T2, Arity, _), + TopType, Opaques) -> + t_find_opaque_mismatch_ordlists(T1, T2, TopType, Opaques); +t_find_opaque_mismatch(?tuple(_, _, _) = T1, ?tuple_set(_) = T2, + TopType, Opaques) -> Tuples1 = t_tuple_subtypes(T1), Tuples2 = t_tuple_subtypes(T2), - t_find_opaque_mismatch_lists(Tuples1, Tuples2, TopType); -t_find_opaque_mismatch(T1, ?union(U2), TopType) -> - t_find_opaque_mismatch_lists([T1], U2, TopType); -t_find_opaque_mismatch(_T1, _T2, _TopType) -> error. + t_find_opaque_mismatch_lists(Tuples1, Tuples2, TopType, Opaques); +t_find_opaque_mismatch(T1, ?union(U2), TopType, Opaques) -> + t_find_opaque_mismatch_lists([T1], U2, TopType, Opaques); +t_find_opaque_mismatch(_T1, _T2, _TopType, _Opaques) -> error. -t_find_opaque_mismatch_ordlists(L1, L2, TopType) -> +t_find_opaque_mismatch_ordlists(L1, L2, TopType, Opaques) -> List = lists:zipwith(fun(T1, T2) -> - t_find_opaque_mismatch(T1, T2, TopType) + t_find_opaque_mismatch(T1, T2, TopType, Opaques) end, L1, L2), t_find_opaque_mismatch_list(List). -t_find_opaque_mismatch_lists(L1, L2, _TopType) -> - List = [t_find_opaque_mismatch(T1, T2, T2) || T1 <- L1, T2 <- L2], +t_find_opaque_mismatch_lists(L1, L2, _TopType, Opaques) -> + List = [t_find_opaque_mismatch(T1, T2, T2, Opaques) || T1 <- L1, T2 <- L2], t_find_opaque_mismatch_list(List). t_find_opaque_mismatch_list([]) -> error; @@ -787,11 +787,6 @@ t_struct_from_opaque(Type, _Opaques) -> Type. list_struct_from_opaque(Types, Opaques) -> [t_struct_from_opaque(Type, Opaques) || Type <- Types]. --spec module_builtin_opaques(module()) -> [erl_type()]. - -module_builtin_opaques(Module) -> - [O || O <- all_opaque_builtins(), lists:member(Module, t_opaque_modules(O))]. - %%----------------------------------------------------------------------------- %% Remote types: these types are used for preprocessing; %% they should never reach the analysis stage. @@ -1423,7 +1418,6 @@ t_number_vals(Type) -> t_number_vals(Type, Opaques) -> do_opaque(Type, Opaques, fun number_vals/1). -number_vals(?int_set(?any)) -> unknown; number_vals(?int_set(Set)) -> set_to_list(Set); number_vals(?number(_, _)) -> unknown; number_vals(?opaque(_)) -> unknown; @@ -1972,82 +1966,6 @@ t_parameterized_module() -> t_timeout() -> t_sup(t_non_neg_integer(), t_atom('infinity')). -%%----------------------------------------------------------------------------- -%% Some built-in opaque types -%% - --spec t_array() -> erl_type(). - -t_array() -> - t_opaque(array, array, [t_any()], - t_tuple([t_atom('array'), - t_sup([t_atom('undefined'), t_non_neg_integer()]), - t_sup([t_atom('undefined'), t_non_neg_integer()]), - t_any(), - t_any()])). - --spec t_dict() -> erl_type(). - -t_dict() -> - t_opaque(dict, dict, [t_any(), t_any()], - t_tuple([t_atom('dict'), - t_sup([t_atom('undefined'), t_non_neg_integer()]), - t_sup([t_atom('undefined'), t_non_neg_integer()]), - t_sup([t_atom('undefined'), t_non_neg_integer()]), - t_sup([t_atom('undefined'), t_non_neg_integer()]), - t_sup([t_atom('undefined'), t_non_neg_integer()]), - t_sup([t_atom('undefined'), t_non_neg_integer()]), - t_sup([t_atom('undefined'), t_tuple()]), - t_sup([t_atom('undefined'), t_tuple()])])). - --spec t_digraph() -> erl_type(). - -t_digraph() -> - t_opaque(digraph, digraph, [], - t_tuple([t_atom('digraph'), - t_sup(t_atom(), t_tid()), - t_sup(t_atom(), t_tid()), - t_sup(t_atom(), t_tid()), - t_boolean()])). - --spec t_gb_set() -> erl_type(). - -t_gb_set() -> - t_opaque(gb_sets, gb_set, [], - t_tuple([t_non_neg_integer(), t_sup(t_atom('nil'), t_tuple(3))])). - --spec t_gb_tree() -> erl_type(). - -t_gb_tree() -> - t_opaque(gb_trees, gb_tree, [], - t_tuple([t_non_neg_integer(), t_sup(t_atom('nil'), t_tuple(4))])). - --spec t_queue() -> erl_type(). - -t_queue() -> - t_opaque(queue, queue, [t_any()], t_tuple([t_list(), t_list()])). - --spec t_set() -> erl_type(). - -t_set() -> - t_opaque(sets, set, [t_any()], - t_tuple([t_atom('set'), t_non_neg_integer(), t_non_neg_integer(), - t_pos_integer(), t_non_neg_integer(), t_non_neg_integer(), - t_non_neg_integer(), - t_sup([t_atom('undefined'), t_tuple()]), - t_sup([t_atom('undefined'), t_tuple()])])). - --spec t_tid() -> erl_type(). - -t_tid() -> - t_opaque(ets, tid, [], t_integer()). - --spec all_opaque_builtins() -> [erl_type(),...]. - -all_opaque_builtins() -> - [t_array(), t_dict(), t_digraph(), t_gb_set(), - t_gb_tree(), t_queue(), t_set(), t_tid()]. - %%------------------------------------ %% ?none is allowed in products. A product of size 1 is not a product. @@ -3302,8 +3220,8 @@ is_opaque_type2(#opaque{mod = Mod1, name = Name1, args = Args1}, Opaques) -> is_type_name(Mod, Name, Args1, Mod, Name, Args2) -> length(Args1) =:= length(Args2); -is_type_name(Mod1, Name1, Args1, Mod2, Name2, Args2) -> - is_same_type_name2(Mod1, Name1, Args1, Mod2, Name2, Args2). +is_type_name(_Mod1, _Name1, _Args1, _Mod2, _Name2, _Args2) -> + false. %% Two functions since t_unify is not symmetric. unify_tuple_set_and_tuple1(?tuple_set([{Arity, List}]), @@ -4141,15 +4059,7 @@ opaque_name(Mod, Name, Extra) -> flat_format("~s(~s)", [S, Extra]). mod_name(Mod, Name) -> - case is_obsolete_opaque_builtin(Mod, Name) of - true -> flat_format("~w", [Name]); - false -> flat_format("~w:~w", [Mod, Name]) - end. - -is_obsolete_opaque_builtin(digraph, digraph) -> true; -is_obsolete_opaque_builtin(gb_sets, gb_set) -> true; -is_obsolete_opaque_builtin(gb_trees, gb_tree) -> true; -is_obsolete_opaque_builtin(_, _) -> false. + flat_format("~w:~w", [Mod, Name]). %%============================================================================= %% @@ -4214,8 +4124,6 @@ t_from_form({type, _L, any, []}, _TypeNames, _RecDict, _VarDict) -> {t_any(), []}; t_from_form({type, _L, arity, []}, _TypeNames, _RecDict, _VarDict) -> {t_arity(), []}; -t_from_form({type, _L, array, []}, TypeNames, RecDict, VarDict) -> - builtin_type(array, t_array(), TypeNames, RecDict, VarDict); t_from_form({type, _L, atom, []}, _TypeNames, _RecDict, _VarDict) -> {t_atom(), []}; t_from_form({type, _L, binary, []}, _TypeNames, _RecDict, _VarDict) -> @@ -4237,10 +4145,6 @@ t_from_form({type, _L, byte, []}, _TypeNames, _RecDict, _VarDict) -> {t_byte(), []}; t_from_form({type, _L, char, []}, _TypeNames, _RecDict, _VarDict) -> {t_char(), []}; -t_from_form({type, _L, dict, []}, TypeNames, RecDict, VarDict) -> - builtin_type(dict, t_dict(), TypeNames, RecDict, VarDict); -t_from_form({type, _L, digraph, []}, TypeNames, RecDict, VarDict) -> - builtin_type(digraph, t_digraph(), TypeNames, RecDict, VarDict); t_from_form({type, _L, float, []}, _TypeNames, _RecDict, _VarDict) -> {t_float(), []}; t_from_form({type, _L, function, []}, _TypeNames, _RecDict, _VarDict) -> @@ -4256,10 +4160,6 @@ t_from_form({type, _L, 'fun', [{type, _, product, Domain}, Range]}, {L, R1} = list_from_form(Domain, TypeNames, RecDict, VarDict), {T, R2} = t_from_form(Range, TypeNames, RecDict, VarDict), {t_fun(L, T), R1 ++ R2}; -t_from_form({type, _L, gb_set, []}, TypeNames, RecDict, VarDict) -> - builtin_type(gb_set, t_gb_set(), TypeNames, RecDict, VarDict); -t_from_form({type, _L, gb_tree, []}, TypeNames, RecDict, VarDict) -> - builtin_type(gb_tree, t_gb_tree(), TypeNames, RecDict, VarDict); t_from_form({type, _L, identifier, []}, _TypeNames, _RecDict, _VarDict) -> {t_identifier(), []}; t_from_form({type, _L, integer, []}, _TypeNames, _RecDict, _VarDict) -> @@ -4332,8 +4232,6 @@ t_from_form({type, _L, maybe_improper_list, [Content, Termination]}, t_from_form({type, _L, product, Elements}, TypeNames, RecDict, VarDict) -> {L, R} = list_from_form(Elements, TypeNames, RecDict, VarDict), {t_product(L), R}; -t_from_form({type, _L, queue, []}, TypeNames, RecDict, VarDict) -> - builtin_type(queue, t_queue(), TypeNames, RecDict, VarDict); t_from_form({type, _L, range, [From, To]} = Type, _TypeNames, _RecDict, _VarDict) -> case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of @@ -4345,14 +4243,10 @@ t_from_form({type, _L, record, [Name|Fields]}, TypeNames, RecDict, VarDict) -> record_from_form(Name, Fields, TypeNames, RecDict, VarDict); t_from_form({type, _L, reference, []}, _TypeNames, _RecDict, _VarDict) -> {t_reference(), []}; -t_from_form({type, _L, set, []}, TypeNames, RecDict, VarDict) -> - builtin_type(set, t_set(), TypeNames, RecDict, VarDict); t_from_form({type, _L, string, []}, _TypeNames, _RecDict, _VarDict) -> {t_string(), []}; t_from_form({type, _L, term, []}, _TypeNames, _RecDict, _VarDict) -> {t_any(), []}; -t_from_form({type, _L, tid, []}, TypeNames, RecDict, VarDict) -> - builtin_type(tid, t_tid(), TypeNames, RecDict, VarDict); t_from_form({type, _L, timeout, []}, _TypeNames, _RecDict, _VarDict) -> {t_timeout(), []}; t_from_form({type, _L, tuple, any}, _TypeNames, _RecDict, _VarDict) -> @@ -4363,7 +4257,10 @@ t_from_form({type, _L, tuple, Args}, TypeNames, RecDict, VarDict) -> t_from_form({type, _L, union, Args}, TypeNames, RecDict, VarDict) -> {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict), {t_sup(L), R}; +t_from_form({user_type, _L, Name, Args}, TypeNames, RecDict, VarDict) -> + type_from_form(Name, Args, TypeNames, RecDict, VarDict); t_from_form({type, _L, Name, Args}, TypeNames, RecDict, VarDict) -> + %% Compatibility: modules compiled before Erlang/OTP 18.0. type_from_form(Name, Args, TypeNames, RecDict, VarDict); t_from_form({opaque, _L, Name, {Mod, Args, Rep}}, _TypeNames, _RecDict, _VarDict) -> @@ -4607,9 +4504,12 @@ t_form_to_string({type, _L, Name, []} = T) -> try t_to_string(t_from_form(T)) catch throw:{error, _} -> atom_to_string(Name) ++ "()" end; -t_form_to_string({type, _L, Name, List}) -> +t_form_to_string({user_type, _L, Name, List}) -> flat_format("~w(~s)", - [Name, string:join(t_form_to_string_list(List), ",")]). + [Name, string:join(t_form_to_string_list(List), ",")]); +t_form_to_string({type, L, Name, List}) -> + %% Compatibility: modules compiled before Erlang/OTP 18.0. + t_form_to_string({user_type, L, Name, List}). t_form_to_string_list(List) -> t_form_to_string_list(List, []). @@ -4722,27 +4622,14 @@ do_opaque(Type, _Opaques, Pred) -> is_same_type_name(ModNameArgs, ModNameArgs) -> true; is_same_type_name({Mod, Name, Args1}, {Mod, Name, Args2}) -> all_any(Args1) orelse all_any(Args2); -is_same_type_name({Mod1, Name1, Args1}, {Mod2, Name2, Args2}) -> - is_same_type_name2(Mod1, Name1, Args1, Mod2, Name2, Args2). +is_same_type_name(_ModNameArgs1, _ModNameArgs2) -> + false. all_any([]) -> true; all_any([T|L]) -> t_is_any(T) andalso all_any(L); all_any(_) -> false. -%% Compatibility. In Erlang/OTP 17 the pre-defined opaque types -%% digraph() and so on can be used, but there are also new types such -%% as digraph:graph() with the exact same meaning. In Erlang/OTP R18.0 -%% all but the last clause can be removed. - -is_same_type_name2(digraph, digraph, [], digraph, graph, []) -> true; -is_same_type_name2(digraph, graph, [], digraph, digraph, []) -> true; -is_same_type_name2(gb_sets, gb_set, [], gb_sets, set, [_]) -> true; -is_same_type_name2(gb_sets, set, [_], gb_sets, gb_set, []) -> true; -is_same_type_name2(gb_trees, gb_tree, [], gb_trees, tree, [_, _]) -> true; -is_same_type_name2(gb_trees, tree, [_, _], gb_trees, gb_tree, []) -> true; -is_same_type_name2(_, _, _, _, _, _) -> false. - map_keys(?map(Pairs)) -> [K || {K, _} <- Pairs]. diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index c7faf733c7..e8552eabcc 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -30,6 +30,35 @@ </header> <p>This document describes the changes made to HiPE.</p> +<section><title>Hipe 3.11</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A Dialyzer crash involving analysis of Map types has now + been fixed.</p> + <p> + Own Id: OTP-11947</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Handle Maps instructions get_map_elements, put_map_assoc, + put_map_exact in HiPE compiler.</p> + <p> + Own Id: OTP-11900</p> + </item> + </list> + </section> + +</section> + <section><title>Hipe 3.10.3</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -118,9 +147,9 @@ "hi" := V1, a := V2, b := V3} = M2. % match keys with values</c></item> </taglist></p> <p> - For information on how to use Maps please see the - <seealso marker="doc/reference_manual:maps">Reference - Manual</seealso>.</p> + For information on how to use Maps please see Map Expressions in the + <seealso marker="doc/reference_manual:expressions#map_expressions"> + Reference Manual</seealso>.</p> <p> The current implementation is without the following features: <taglist> <item>No variable keys</item> diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index fb7e4b91a0..c30695d4f0 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.10.3 +HIPE_VSN = 3.11 diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 596c0d77f4..d586536b0a 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -32,7 +32,22 @@ <file>notes.xml</file> </header> - <section><title>Inets 5.10.1</title> + <section><title>Inets 5.10.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + httpc: Fix streaming bugs when handling small responses</p> + <p> + Own Id: OTP-11992</p> + </item> + </list> + </section> + +</section> + +<section><title>Inets 5.10.1</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl index b3c9cbc46a..9bea58cc9e 100644 --- a/lib/inets/src/http_server/httpd_request_handler.erl +++ b/lib/inets/src/http_server/httpd_request_handler.erl @@ -35,6 +35,7 @@ -include("http_internal.hrl"). -include("httpd_internal.hrl"). +-define(HANDSHAKE_TIMEOUT, 5000). -record(state, {mod, %% #mod{} manager, %% pid() status, %% accept | busy | blocked @@ -96,15 +97,13 @@ init([Manager, ConfigDB, AcceptTimeout]) -> {SocketType, Socket} = await_socket_ownership_transfer(AcceptTimeout), - TimeOut = httpd_util:lookup(ConfigDB, keep_alive_timeout, 150000), - Then = erlang:now(), + KeepAliveTimeOut = httpd_util:lookup(ConfigDB, keep_alive_timeout, 150000), - case http_transport:negotiate(SocketType, Socket, TimeOut) of + case http_transport:negotiate(SocketType, Socket, ?HANDSHAKE_TIMEOUT) of {error, _Error} -> exit(shutdown); %% Can be 'normal'. ok -> - NewTimeout = TimeOut - timer:now_diff(now(),Then) div 1000, - continue_init(Manager, ConfigDB, SocketType, Socket, NewTimeout) + continue_init(Manager, ConfigDB, SocketType, Socket, KeepAliveTimeOut) end. continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) -> diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index 5499596bbd..6991fb6d04 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -17,8 +17,16 @@ %% %CopyrightEnd% {"%VSN%", [ + {"5.10.1", + [{load_module, httpc_handler, soft_purge, soft_purge, []}, + {load_module, httpd, soft_purge, soft_purge, []}, + {load_module, httpd_manager, soft_purge, soft_purge, []}, + {load_module, httpd_request, soft_purge, soft_purge, []}, + {load_module, httpd_request_handler, soft_purge, soft_purge, + []}]}, {"5.10", - [{load_module, httpd, soft_purge, soft_purge, []}, + [{load_module, httpc_handler, soft_purge, soft_purge, []}, + {load_module, httpd, soft_purge, soft_purge, []}, {load_module, httpd_manager, soft_purge, soft_purge, []}, {load_module, httpd_request, soft_purge, soft_purge, []}, {load_module, httpd_request_handler, soft_purge, soft_purge, @@ -26,8 +34,16 @@ {<<"5\\..*">>,[{restart_application, inets}]} ], [ + {"5.10.1", + [{load_module, httpc_handler, soft_purge, soft_purge, []}, + {load_module, httpd, soft_purge, soft_purge, []}, + {load_module, httpd_manager, soft_purge, soft_purge, []}, + {load_module, httpd_request, soft_purge, soft_purge, []}, + {load_module, httpd_request_handler, soft_purge, soft_purge, + []}]}, {"5.10", - [{load_module, httpd, soft_purge, soft_purge, []}, + [{load_module, httpc_handler, soft_purge, soft_purge, []}, + {load_module, httpd, soft_purge, soft_purge, []}, {load_module, httpd_manager, soft_purge, soft_purge, []}, {load_module, httpd_request, soft_purge, soft_purge, []}, {load_module, httpd_request_handler, soft_purge, soft_purge, []}]}, diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index 4be20d3a69..de47760e6e 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -39,6 +39,7 @@ -define(FAIL_EXPIRE_TIME,1). %% Seconds before successful auths timeout. -define(AUTH_TIMEOUT,5). +-define(URL_START, "http://"). %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- @@ -63,7 +64,9 @@ all() -> {group, http_htaccess}, {group, https_htaccess}, {group, http_security}, - {group, https_security} + {group, https_security}, + {group, http_reload}, + {group, https_reload} ]. groups() -> @@ -84,7 +87,18 @@ groups() -> {https_htaccess, [], [{group, htaccess}]}, {http_security, [], [{group, security}]}, {https_security, [], [{group, security}]}, + {http_reload, [], [{group, reload}]}, + {https_reload, [], [{group, reload}]}, {limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]}, + {reload, [], [non_disturbing_reconfiger_dies, + disturbing_reconfiger_dies, + non_disturbing_1_1, + non_disturbing_1_0, + non_disturbing_0_9, + disturbing_1_1, + disturbing_1_0, + disturbing_0_9 + ]}, {basic_auth, [], [basic_auth_1_1, basic_auth_1_0, basic_auth_0_9]}, {auth_api, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9 ]}, @@ -150,7 +164,8 @@ init_per_group(Group, Config0) when Group == https_basic; Group == https_auth_api; Group == https_auth_api_dets; Group == https_auth_api_mnesia; - Group == https_security + Group == https_security; + Group == https_reload -> init_ssl(Group, Config0); init_per_group(Group, Config0) when Group == http_basic; @@ -159,7 +174,8 @@ init_per_group(Group, Config0) when Group == http_basic; Group == http_auth_api; Group == http_auth_api_dets; Group == http_auth_api_mnesia; - Group == http_security + Group == http_security; + Group == http_reload -> ok = start_apps(Group), init_httpd(Group, [{type, ip_comm} | Config0]); @@ -202,17 +218,19 @@ end_per_group(Group, _Config) when Group == http_basic; Group == http_auth_api_dets; Group == http_auth_api_mnesia; Group == http_htaccess; - Group == http_security + Group == http_security; + Group == http_reload -> inets:stop(); end_per_group(Group, _Config) when Group == https_basic; Group == https_limit; Group == https_basic_auth; Group == https_auth_api; - Group == http_auth_api_dets; - Group == http_auth_api_mnesia; + Group == https_auth_api_dets; + Group == https_auth_api_mnesia; Group == https_htaccess; - Group == http_security + Group == https_security; + Group == https_reload -> ssl:stop(), inets:stop(); @@ -1088,12 +1106,114 @@ security(Config) -> [{statuscode, 401}]), true = unblock_user(Node, "two", Port, OpenDir). + +%%------------------------------------------------------------------------- +non_disturbing_reconfiger_dies(Config) when is_list(Config) -> + do_reconfiger_dies([{http_version, "HTTP/1.1"} | Config], non_disturbing). +disturbing_reconfiger_dies(Config) when is_list(Config) -> + do_reconfiger_dies([{http_version, "HTTP/1.1"} | Config], disturbing). + +do_reconfiger_dies(Config, DisturbingType) -> + Server = ?config(server_pid, Config), + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Port = ?config(port, Config), + Type = ?config(type, Config), + + HttpdConfig = httpd:info(Server), + BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host), + {ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)), + inets_test_lib:send(Type, Socket, BlockRequest), + ct:sleep(100), %% Avoid possible timing issues + Pid = spawn(fun() -> httpd:reload_config([{server_name, "httpd_kill_" ++ Version}, + {port, Port}| + proplists:delete(server_name, HttpdConfig)], DisturbingType) + end), + monitor(process, Pid), + exit(Pid, kill), + receive + {'DOWN', _, _, _, _} -> + ok + end, + inets_test_lib:close(Type, Socket), + [{server_name, "httpd_test"}] = httpd:info(Server, [server_name]). +%%------------------------------------------------------------------------- +disturbing_1_1(Config) when is_list(Config) -> + disturbing([{http_version, "HTTP/1.1"} | Config]). + +disturbing_1_0(Config) when is_list(Config) -> + disturbing([{http_version, "HTTP/1.0"} | Config]). + +disturbing_0_9(Config) when is_list(Config) -> + disturbing([{http_version, "HTTP/0.9"} | Config]). + +disturbing(Config) when is_list(Config)-> + Server = ?config(server_pid, Config), + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Port = ?config(port, Config), + Type = ?config(type, Config), + HttpdConfig = httpd:info(Server), + BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host), + {ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)), + inets_test_lib:send(Type, Socket, BlockRequest), + ct:sleep(100), %% Avoid possible timing issues + ok = httpd:reload_config([{server_name, "httpd_disturbing_" ++ Version}, {port, Port}| + proplists:delete(server_name, HttpdConfig)], disturbing), + Close = list_to_atom((typestr(Type)) ++ "_closed"), + receive + {Close, Socket} -> + ok; + Msg -> + ct:fail({{expected, {Close, Socket}}, {got, Msg}}) + end, + inets_test_lib:close(Type, Socket), + [{server_name, "httpd_disturbing_" ++ Version}] = httpd:info(Server, [server_name]). +%%------------------------------------------------------------------------- +non_disturbing_1_1(Config) when is_list(Config) -> + non_disturbing([{http_version, "HTTP/1.1"} | Config]). + +non_disturbing_1_0(Config) when is_list(Config) -> + non_disturbing([{http_version, "HTTP/1.0"} | Config]). + +non_disturbing_0_9(Config) when is_list(Config) -> + non_disturbing([{http_version, "HTTP/0.9"} | Config]). + +non_disturbing(Config) when is_list(Config)-> + Server = ?config(server_pid, Config), + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Port = ?config(port, Config), + Type = ?config(type, Config), + + HttpdConfig = httpd:info(Server), + BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host), + {ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)), + inets_test_lib:send(Type, Socket, BlockRequest), + ct:sleep(100), %% Avoid possible timing issues + ok = httpd:reload_config([{server_name, "httpd_non_disturbing_" ++ Version}, {port, Port}| + proplists:delete(server_name, HttpdConfig)], non_disturbing), + Transport = type(Type), + receive + {Transport, Socket, Msg} -> + ct:pal("Received message ~p~n", [Msg]), + ok + after 2000 -> + ct:fail(timeout) + end, + inets_test_lib:close(Type, Socket), + [{server_name, "httpd_non_disturbing_" ++ Version}] = httpd:info(Server, [server_name]). %%-------------------------------------------------------------------- %% Internal functions ----------------------------------- %%-------------------------------------------------------------------- +url(http, End, Config) -> + Port = ?config(port, Config), + {ok,Host} = inet:gethostname(), + ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End. + do_max_clients(Config) -> Version = ?config(http_version, Config), Host = ?config(host, Config), @@ -1171,7 +1291,9 @@ start_apps(Group) when Group == https_basic; Group == https_auth_api_dets; Group == https_auth_api_mnesia; Group == http_htaccess; - Group == http_security -> + Group == http_security; + Group == http_reload + -> inets_test_lib:start_apps([inets, asn1, crypto, public_key, ssl]); start_apps(Group) when Group == http_basic; Group == http_limit; @@ -1180,7 +1302,8 @@ start_apps(Group) when Group == http_basic; Group == http_auth_api_dets; Group == http_auth_api_mnesia; Group == https_htaccess; - Group == https_security -> + Group == https_security; + Group == https_reload-> inets_test_lib:start_apps([inets]). server_start(_, HttpdConfig) -> @@ -1224,6 +1347,10 @@ server_config(http_basic, Config) -> basic_conf() ++ server_config(http, Config); server_config(https_basic, Config) -> basic_conf() ++ server_config(https, Config); +server_config(http_reload, Config) -> + [{keep_alive_timeout, 2}] ++ server_config(http, Config); +server_config(https_reload, Config) -> + [{keep_alive_timeout, 2}] ++ server_config(https, Config); server_config(http_limit, Config) -> [{max_clients, 1}] ++ server_config(http, Config); server_config(https_limit, Config) -> @@ -1792,3 +1919,12 @@ event(What, Port, Dir, Data) -> global:send(mod_security_test, Msg) end. +type(ip_comm) -> + tcp; +type(_) -> + ssl. + +typestr(ip_comm) -> + "tcp"; +typestr(_) -> + "ssl". diff --git a/lib/inets/test/httpd_basic_SUITE.erl b/lib/inets/test/httpd_basic_SUITE.erl index 1fcc5f257e..baef699629 100644 --- a/lib/inets/test/httpd_basic_SUITE.erl +++ b/lib/inets/test/httpd_basic_SUITE.erl @@ -129,7 +129,7 @@ end_per_suite(_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_testcase(Case, Config) -> +init_per_testcase(_Case, Config) -> Config. diff --git a/lib/inets/test/old_httpd_SUITE.erl b/lib/inets/test/old_httpd_SUITE.erl index 19c2bc129e..74c11f71ba 100644 --- a/lib/inets/test/old_httpd_SUITE.erl +++ b/lib/inets/test/old_httpd_SUITE.erl @@ -186,20 +186,23 @@ groups() -> %% Only used through load_config %% but we still need these tests %% should be cleaned up and moved to new test suite - ip_restart_no_block, - ip_restart_disturbing_block, - ip_restart_non_disturbing_block, - ip_block_disturbing_idle, - ip_block_non_disturbing_idle, - ip_block_503, - ip_block_disturbing_active, - ip_block_non_disturbing_active, - ip_block_disturbing_active_timeout_not_released, - ip_block_disturbing_active_timeout_released, - ip_block_non_disturbing_active_timeout_not_released, - ip_block_non_disturbing_active_timeout_released, - ip_block_disturbing_blocker_dies, - ip_block_non_disturbing_blocker_dies + %%ip_restart_no_block, + %%ip_restart_disturbing_block, + %%ip_restart_non_disturbing_block, + %% Tested in inets_SUITE + %%ip_block_disturbing_idle, + %%ip_block_non_disturbing_idle, + ip_block_503 + %% Tested in new httpd_SUITE + %%ip_block_disturbing_active, + %%ip_block_non_disturbing_active, + %%ip_block_disturbing_blocker_dies, + %%ip_block_non_disturbing_blocker_dies + %% No longer relevant + %%ip_block_disturbing_active_timeout_not_released, + %%ip_block_disturbing_active_timeout_released, + %%ip_block_non_disturbing_active_timeout_not_released, + %%ip_block_non_disturbing_active_timeout_released, ]}, {ssl, [], [{group, essl}]}, {essl, [], diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index bbd86c3eb3..79081f371c 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 5.10.1 +INETS_VSN = 5.10.2 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java index 9ba6a4a0ab..85d303689f 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java @@ -266,7 +266,7 @@ public abstract class AbstractConnection extends Thread { * * @param dest * the Erlang PID of the remote process. - * @param msg + * @param payload * the encoded message to send. * * @exception java.io.IOException @@ -959,7 +959,9 @@ public abstract class AbstractConnection extends Thread { } catch (final Exception e) { final String nn = peer.node(); close(); - throw new IOException("Error accepting connection from " + nn); + IOException ioe = new IOException("Error accepting connection from " + nn); + ioe.initCause(e); + throw ioe; } if (traceLevel >= handshakeThreshold) { System.out.println("<- MD5 ACCEPTED " + peer.host()); @@ -990,7 +992,9 @@ public abstract class AbstractConnection extends Thread { throw ae; } catch (final Exception e) { close(); - throw new IOException("Cannot connect to peer node"); + IOException ioe = new IOException("Cannot connect to peer node"); + ioe.initCause(e); + throw ioe; } } diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java index 8e8bd473c8..e7a9d1092c 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java @@ -404,7 +404,7 @@ public class OtpConnection extends AbstractConnection { * * @param dest * the Erlang PID of the remote process. - * @param msg + * @param payload * the encoded message to send. * * @exception java.io.IOException diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java index 7e3e2a7296..84b1355c54 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java @@ -51,8 +51,8 @@ public class OtpErlangLong extends OtpErlangObject implements Serializable, /** * Create an Erlang integer from the given value. * - * @param val - * the long value to use. + * @param v + * the big integer value to use. */ public OtpErlangLong(final BigInteger v) { if (v == null) { diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java index 03c18e55a2..0254edd5da 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java @@ -58,15 +58,23 @@ public class OtpErlangMap extends OtpErlangObject implements Serializable, /** * Create a map from an array of terms. * - * @param elems + * @param keys * the array of terms to create the map from. - * @param start - * the offset of the first term to insert. + * @param kstart + * the offset of the first key to insert. + * @param kcount + * the number of keys to insert. + * @param values + * the array of values to create the map from. + * @param vstart + * the offset of the first value to insert. * @param vcount - * the number of terms to insert. + * the number of values to insert. * * @exception java.lang.IllegalArgumentException * if any array is empty (null) or contains null elements. + * @exception java.lang.IllegalArgumentException + * if kcount and vcount differ. */ public OtpErlangMap(final OtpErlangObject[] keys, final int kstart, final int kcount, final OtpErlangObject[] values, final int vstart, diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java index fe81ce302d..f75e4353d0 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java @@ -162,7 +162,7 @@ public class OtpErlangPid extends OtpErlangObject implements Serializable, * Determine if two PIDs are equal. PIDs are equal if their components are * equal. * - * @param port + * @param o * the other PID to compare to. * * @return true if the PIDs are equal, false otherwise. diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java index 6766b52ce5..a5e202c473 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java @@ -41,8 +41,6 @@ public class OtpErlangString extends OtpErlangObject implements Serializable, /** * Create an Erlang string from a list of integers. - * - * @return an Erlang string with Unicode code units. * * @throws OtpErlangException * for non-proper and non-integer lists. diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java index 0d1342d796..f813594541 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java @@ -21,6 +21,7 @@ package com.ericsson.otp.erlang; import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigDecimal; +import java.util.Arrays; /** * Provides a stream for decoding Erlang terms from external format. @@ -819,7 +820,7 @@ public class OtpInputStream extends ByteArrayInputStream { if (unsigned) { if (c < 0) { throw new OtpErlangDecodeException("Value not unsigned: " - + b); + + Arrays.toString(b)); } while (b[i] == 0) { i++; // Skip leading zero sign bytes @@ -844,7 +845,7 @@ public class OtpInputStream extends ByteArrayInputStream { if (b.length - i > 8) { // More than 64 bits of value throw new OtpErlangDecodeException( - "Value does not fit in long: " + b); + "Value does not fit in long: " + Arrays.toString(b)); } // Convert the necessary bytes for (v = c < 0 ? -1 : 0; i < b.length; i++) { diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java index 0fd93b09f4..4a4a1e7f8f 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java @@ -69,6 +69,7 @@ package com.ericsson.otp.erlang; * notify other parties in a timely manner. * </p> * + * <p> * When retrieving messages from a mailbox that has received an exit signal, an * {@link OtpErlangExit OtpErlangExit} exception will be raised. Note that the * exception is queued in the mailbox along with other messages, and will not be @@ -420,7 +421,6 @@ public class OtpMbox { /** * Equivalent to <code>exit(new OtpErlangAtom(reason))</code>. - * </p> * * @see #exit(OtpErlangObject) */ diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java index 6f507bf4bb..31a5d0fb8f 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java @@ -30,14 +30,14 @@ package com.ericsson.otp.erlang; * </p> * * <p> - * The header information that is available is as follows: <lu> + * The header information that is available is as follows: <ul> * <li> a tag indicating the type of message * <li> the intended recipient of the message, either as a * {@link OtpErlangPid pid} or as a String, but never both. * <li> (sometimes) the sender of the message. Due to some eccentric * characteristics of the Erlang distribution protocol, not all messages have * information about the sending process. In particular, only messages whose tag - * is {@link OtpMsg#regSendTag regSendTag} contain sender information. </lu> + * is {@link OtpMsg#regSendTag regSendTag} contain sender information. </ul> * * <p> * Message are sent using the Erlang external format (see separate diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java index a78423db44..c98790bbd4 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java @@ -202,7 +202,7 @@ public class OtpOutputStream extends ByteArrayOutputStream { /** * Write an array of bytes to the stream. * - * @param buf + * @param bytes * the array of bytes to write. * */ @@ -637,7 +637,7 @@ public class OtpOutputStream extends ByteArrayOutputStream { * Write a positive short to the stream. The short is interpreted as a two's * complement unsigned short even if it is negative. * - * @param s + * @param us * the short to use. */ public void write_ushort(final short us) { diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 8dae34431b..1c03efe7fd 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -428,14 +428,6 @@ </desc> </func> <func> - <name name="file_info" arity="1"/> - <fsummary>Get information about a file (deprecated)</fsummary> - <desc> - <p>This function is obsolete. Use <c>read_file_info/1,2</c> - instead.</p> - </desc> - </func> - <func> <name name="format_error" arity="1"/> <fsummary>Return a descriptive string for an error reason</fsummary> <desc> diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index dbd0d3c815..820ecd1e30 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -112,7 +112,12 @@ do_recv(Sock, Bs) -> <item> <p>If a socket has somehow been connected without using <c>gen_tcp</c>, use this option to pass the file - descriptor for it.</p> + descriptor for it. If <c>{ip, ip_address()}</c> + and/or <c>{port, port_number()}</c> is combined with + this option the fd will be bound to the given interface + and port before connecting. If these options are not given + it is assumed that the fd is already bound appropriately. + </p> </item> <tag><c>inet</c></tag> diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml index 503725fe18..291d1b0da7 100644 --- a/lib/kernel/doc/src/gen_udp.xml +++ b/lib/kernel/doc/src/gen_udp.xml @@ -84,7 +84,12 @@ <item> <p>If a socket has somehow been opened without using <c>gen_udp</c>, use this option to pass the file - descriptor for it.</p> + descriptor for it. If <c><anno>Port</anno></c> is not set to 0 + and/or <c>{ip, ip_address()}</c> is combined with this option + the fd will be bound to the given interface and port after being + opened. If these options are not given it is assumed that the fd + is already bound appropriately. + </p> </item> <tag><c>inet6</c></tag> <item> diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index c6538b7d05..f92770603a 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -30,6 +30,77 @@ </header> <p>This document describes the changes made to the Kernel application.</p> +<section><title>Kernel 3.0.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + OTP-11850 fixed filelib:wildcard/1 to work with broken + symlinks. This correction, however, introduced problems + since symlinks were no longer followed for functions like + filelib:ensure_dir/1, filelib:is_dir/1, + filelib:file_size/1, etc. This is now corrected.</p> + <p> + Own Id: OTP-12054 Aux Id: seq12660 </p> + </item> + </list> + </section> + +</section> + +<section><title>Kernel 3.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + If the Config given to + application_controller:change_application_data included + other config files, it was only expanded for already + existing (loaded) applications. If an upgrade added a new + application which had config data in an included config + file, the new application did not get correct config + data.</p> + <p> + This is now changed so config data will be expanded for + all applications.</p> + <p> + Own Id: OTP-11864</p> + </item> + <item> + <p>It was allowed to re-load pre-loaded modules such as + <c>erlang</c>, but that could cause strange and unwanted + things to happen, such as call <c>apply/3</c> to loop. + Pre-loaded modules are now sticky by default. (Thanks to + Loïc Hoguin for reporting this bug.)</p> + <p><c>code:add_path("/ending/in/slash/")</c> removes the + trailing slash, adding <c>/ending/in/slash</c> to the + code path. However, + <c>code:del_path("/ending/in/slash/")</c> would fail to + remove the path since it did not remove the trailing + slash. This has been fixed.</p> + <p> + Own Id: OTP-11913</p> + </item> + <item> + <p> + Fix erts_debug:size/1 to handle Map sizes</p> + <p> + Own Id: OTP-11923</p> + </item> + <item> + <p>The documentation for <c>file:file_info/1</c> has been + removed. The function itself was removed a long time + ago.</p> + <p> + Own Id: OTP-11982</p> + </item> + </list> + </section> + +</section> + <section><title>Kernel 3.0</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -80,7 +151,6 @@ </list> </section> - <section><title>Improvements and New Features</title> <list> <item> @@ -224,7 +294,26 @@ </item> </list> </section> +</section> +<section><title>Kernel 2.16.4.1</title> + + <section><title>Known Bugs and Problems</title> + <list> + <item> + <p> + When using gen_tcp:connect and the <c>fd</c> option with + <c>port</c> and/or <c>ip</c>, the <c>port</c> and + <c>ip</c> options were ignored. This has been fixed so + that if <c>port</c> and/or <c>ip</c> is specified + together with <c>fd</c> a bind is requested for that + <c>fd</c>. If <c>port</c> and/or <c>ip</c> is not + specified bind will not be called.</p> + <p> + Own Id: OTP-12061</p> + </item> + </list> + </section> </section> <section><title>Kernel 2.16.4</title> diff --git a/lib/kernel/doc/src/pg2.xml b/lib/kernel/doc/src/pg2.xml index 5eb63c1ef6..35cf85470a 100644 --- a/lib/kernel/doc/src/pg2.xml +++ b/lib/kernel/doc/src/pg2.xml @@ -34,11 +34,8 @@ <module>pg2</module> <modulesummary>Distributed Named Process Groups</modulesummary> <description> - <p>This module implements process groups. The groups in this - module differ from the groups in the module <c>pg</c> in several - ways. In <c>pg</c>, each message is sent to all members in the - group. In this module, each message may be sent to one, some, or - all members. + <p>This module implements process groups. Each message may be sent + to one, some, or all members of the group. </p> <p>A group of processes can be accessed by a common name. For example, if there is a group named <c>foobar</c>, there can be a @@ -160,8 +157,7 @@ <section> <title>See Also</title> - <p><seealso marker="kernel_app">kernel(6)</seealso>, - <seealso marker="stdlib:pg">pg(3)</seealso></p> + <p><seealso marker="kernel_app">kernel(6)</seealso></p> </section> </erlref> diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index fc7ac08699..819554ce74 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -63,7 +63,10 @@ init(Ref, Parent, [Root,Mode0]) -> process_flag(trap_exit, true), Db = ets:new(code, [private]), - foreach(fun (M) -> ets:insert(Db, {M,preloaded}) end, erlang:pre_loaded()), + foreach(fun (M) -> + %% Pre-loaded modules are always sticky. + ets:insert(Db, [{M,preloaded},{{sticky,M},true}]) + end, erlang:pre_loaded()), ets:insert(Db, init:fetch_loaded()), Mode = @@ -988,7 +991,7 @@ try_archive_subdirs(_Archive, Base, []) -> %% the complete directory name. %% del_path(Name0,Path,NameDb) -> - case catch to_list(Name0)of + case catch filename:join([to_list(Name0)]) of {'EXIT',_} -> {{error,bad_name},Path}; Name -> diff --git a/lib/kernel/src/erl_boot_server.erl b/lib/kernel/src/erl_boot_server.erl index 9a49655a9f..ef09d86ca4 100644 --- a/lib/kernel/src/erl_boot_server.erl +++ b/lib/kernel/src/erl_boot_server.erl @@ -341,9 +341,13 @@ handle_command(S, PS, Msg) -> send_file_result(S, list_dir, Res), PS2; {read_file_info,File} -> - {Res, PS2} = erl_prim_loader:prim_read_file_info(PS, File), + {Res, PS2} = erl_prim_loader:prim_read_file_info(PS, File, true), send_file_result(S, read_file_info, Res), PS2; + {read_link_info,File} -> + {Res, PS2} = erl_prim_loader:prim_read_file_info(PS, File, false), + send_file_result(S, read_link_info, Res), + PS2; get_cwd -> {Res, PS2} = erl_prim_loader:prim_get_cwd(PS, []), send_file_result(S, get_cwd, Res), diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 20b703e084..ee2fb85de2 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -117,15 +117,7 @@ | {'time', 'posix'}. %%% BIFs --export([file_info/1, native_name_encoding/0]). - --spec file_info(Filename) -> {ok, FileInfo} | {error, Reason} when - Filename :: name_all(), - FileInfo :: file_info(), - Reason :: posix() | badarg. - -file_info(_) -> - erlang:nif_error(undef). +-export([native_name_encoding/0]). -spec native_name_encoding() -> latin1 | utf8. diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 41d422d7d4..d17da2d329 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -1257,9 +1257,9 @@ open(FdO, Addr, Port, Opts, Protocol, Family, Type, Module) Error -> Error end; -open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module) +open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when is_integer(Fd) -> - fdopen(Fd, Opts, Protocol, Family, Type, Module). + fdopen(Fd, Addr, Port, Opts, Protocol, Family, Type, Module). bindx(S, [Addr], Port0) -> {IP, Port} = set_bindx_port(Addr, Port0), @@ -1298,12 +1298,35 @@ change_bindx_0_port({_IP, _Port}=Addr, _AssignedPort) -> {'ok', socket()} | {'error', posix()}. fdopen(Fd, Opts, Protocol, Family, Type, Module) -> - case prim_inet:fdopen(Protocol, Family, Type, Fd) of + fdopen(Fd, any, 0, Opts, Protocol, Family, Type, Module). + +fdopen(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) -> + IsAnyAddr = (Addr == {0,0,0,0} orelse Addr == {0,0,0,0,0,0,0,0} + orelse Addr == any), + Bound = Port == 0 andalso IsAnyAddr, + case prim_inet:fdopen(Protocol, Family, Type, Fd, Bound) of {ok, S} -> case prim_inet:setopts(S, Opts) of ok -> - inet_db:register_socket(S, Module), - {ok, S}; + case if + Bound -> + %% We do not do any binding if default + %% port+addr options where given in order + %% to keep backwards compatability with + %% pre Erlang/TOP 17 + {ok, ok}; + is_list(Addr) -> + bindx(S, Addr, Port); + true -> + prim_inet:bind(S, Addr, Port) + end of + {ok, _} -> + inet_db:register_socket(S, Module), + {ok, S}; + Error -> + prim_inet:close(S), + Error + end; Error -> prim_inet:close(S), Error end; diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 5658c6b6cf..9f6c0f4624 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -115,6 +115,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-6.0", "stdlib-2.0", "sasl-2.4"]} + {runtime_dependencies, ["erts-6.1.2", "stdlib-2.0", "sasl-2.4"]} ] }. diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index f8f4cc1ec2..1bae762bed 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -17,9 +17,7 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 - {<<"2\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R16 + [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 %% Down to - max one major revision back - [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 - {<<"2\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R16 + [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 }. diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl index 036e238c85..4901206c8e 100644 --- a/lib/kernel/test/application_SUITE.erl +++ b/lib/kernel/test/application_SUITE.erl @@ -1076,10 +1076,13 @@ otp_1586(Conf) when is_list(Conf) -> {ok, Fd} = file:open(filename:join(Dir, "app5.app"), [write]), w_app5(Fd), file:close(Fd), - code:add_patha(Dir), - ok = application:load(app4()), - ok = application:unload(app4), - ok. + try + true = code:add_patha(Dir), + ok = application:load(app4()), + ok = application:unload(app4) + after + _ = code:del_path(Dir) + end. %%----------------------------------------------------------------- %% Ticket: OTP-2078 diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 42b81d16b3..afedc17e57 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -37,8 +37,7 @@ native_early_modules/1, get_mode/1]). -export([init_per_testcase/2, end_per_testcase/2, - init_per_suite/1, end_per_suite/1, - sticky_compiler/1]). + init_per_suite/1, end_per_suite/1]). %% error_logger -export([init/1, @@ -55,7 +54,7 @@ all() -> delete, purge, purge_many_exits, soft_purge, is_loaded, all_loaded, load_binary, dir_req, object_code, set_path_file, upgrade, - pa_pz_option, add_del_path, dir_disappeared, + sticky_dir, pa_pz_option, add_del_path, dir_disappeared, ext_mod_dep, clash, load_cached, start_node_with_cache, add_and_rehash, where_is_file_no_cache, where_is_file_cached, purge_stacktrace, mult_lib_roots, @@ -219,6 +218,13 @@ del_path(suite) -> []; del_path(doc) -> []; del_path(Config) when is_list(Config) -> P = code:get_path(), + try + del_path_1(P) + after + code:set_path(P) + end. + +del_path_1(P) -> test_server:format("Initial code:get_path()=~p~n",[P]), {'EXIT',_} = (catch code:del_path(3)), false = code:del_path(my_dummy_name), @@ -226,19 +232,22 @@ del_path(Config) when is_list(Config) -> Dir = filename:join([code:lib_dir(kernel),"ebin"]), test_server:format("kernel dir: ~p~n",[Dir]), - true = code:del_path(kernel), NewP = code:get_path(), test_server:format("Path after removing 'kernel':~p~n",[NewP]), ReferenceP = lists:delete(Dir,P), test_server:format("Reference path:~p~n",[ReferenceP]), NewP = ReferenceP, % check that dir is deleted + code:set_path(P), + %% An superfluous "/" should also work. + true = code:del_path("kernel/"), + NewP = ReferenceP, % check that dir is deleted code:set_path(P), + true = code:del_path(Dir), NewP1 = code:get_path(), NewP1 = lists:delete(Dir,P), % check that dir is deleted - code:set_path(P), ok. replace_path(suite) -> []; @@ -577,35 +586,42 @@ sticky_dir(suite) -> []; sticky_dir(doc) -> ["Test that a module with the same name as a module in ", "a sticky directory cannot be loaded."]; sticky_dir(Config) when is_list(Config) -> - MyDir=filename:dirname(code:which(?MODULE)), - {ok, Node}=?t:start_node(sticky_dir, slave,[{args, "-pa \""++MyDir++"\""}]), - File=filename:join([?config(data_dir, Config), "calendar"]), - Ret=rpc:call(Node, ?MODULE, sticky_compiler, [File]), + Pa = filename:dirname(code:which(?MODULE)), + {ok,Node} = ?t:start_node(sticky_dir, slave, [{args,"-pa "++Pa}]), + Mods = [code,lists,erlang,init], + OutDir = filename:join(?config(priv_dir, Config), sticky_dir), + _ = file:make_dir(OutDir), + Ret = rpc:call(Node, erlang, apply, + [fun sticky_compiler/2,[Mods,OutDir]]), case Ret of - fail -> - ?t:fail("c:c allowed a sticky module to be compiled and loaded."); - ok -> + [] -> ok; Other -> - test_server:format("Other: ~p",[Other]) + io:format("~p\n", [Other]), + ?t:fail() end, - ?t:stop_node(Node). + ?t:stop_node(Node), + ok. -sticky_compiler(File) -> - Compiled=File++code:objfile_extension(), - Dir=filename:dirname(File), - code:add_patha(Dir), - file:delete(Compiled), - case c:c(File, [{outdir, Dir}]) of - {ok, Module} -> - case catch Module:test(apa) of - {error, _} -> - fail; - {'EXIT', _} -> - ok - end; - Other -> - test_server:format("c:c(~p) returned: ~p",[File, Other]), +sticky_compiler(Files, PrivDir) -> + code:add_patha(PrivDir), + Rets = [do_sticky_compile(F, PrivDir) || F <- Files], + [R || R <- Rets, R =/= ok]. + +do_sticky_compile(Mod, Dir) -> + %% Make sure that the module is loaded. A module being sticky + %% only prevents it from begin reloaded, not from being loaded + %% from the wrong place to begin with. + Mod = Mod:module_info(module), + File = filename:append(Dir, atom_to_list(Mod)), + Src = io_lib:format("-module(~s).\n" + "-export([test/1]).\n" + "test(me) -> fail.\n", [Mod]), + ok = file:write_file(File++".erl", Src), + case c:c(File, [{outdir,Dir}]) of + {ok,Module} -> + Module:test(me); + {error,sticky_directory} -> ok end. diff --git a/lib/kernel/test/code_SUITE_data/calendar.erl b/lib/kernel/test/code_SUITE_data/calendar.erl deleted file mode 100644 index c1a4a1c12a..0000000000 --- a/lib/kernel/test/code_SUITE_data/calendar.erl +++ /dev/null @@ -1,23 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. 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(calendar). --export([test/1]). - -test(apa) -> - {error, this_function_should_not_be_called}. diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index b2ca3bdbc2..658c31c14d 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -328,6 +328,30 @@ file_requests(Config) when is_list(Config) -> {ok,Info} = file:read_file_info(code:which(test_server)), ?line {ok,Info} = rpc:call(Node, erl_prim_loader, read_file_info, [code:which(test_server)]), + + PrivDir = ?config(priv_dir,Config), + Dir = filename:join(PrivDir,?MODULE_STRING++"_file_requests"), + ok = file:make_dir(Dir), + Alias = filename:join(Dir,"symlink"), + case file:make_symlink(code:which(test_server), Alias) of + {error, enotsup} -> + %% Links not supported on this platform + ok; + {error, eperm} -> + {win32,_} = os:type(), + %% Windows user not privileged to create symlinks" + ok; + ok -> + %% Reading file info for link should return file info for + %% link target + {ok,Info} = rpc:call(Node, erl_prim_loader, read_file_info, + [Alias]), + #file_info{type=regular} = Info, + {ok,#file_info{type=symlink}} = + rpc:call(Node, erl_prim_loader, read_link_info, + [Alias]) + end, + {ok,Cwd} = file:get_cwd(), ?line {ok,Cwd} = rpc:call(Node, erl_prim_loader, get_cwd, []), case file:get_cwd("C:") of diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index a7af00c12a..c27d265550 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -32,14 +32,16 @@ t_connect_bad/1, t_recv_timeout/1, t_recv_eof/1, t_shutdown_write/1, t_shutdown_both/1, t_shutdown_error/1, - t_fdopen/1, t_implicit_inet6/1]). + t_fdopen/1, t_fdconnect/1, t_implicit_inet6/1]). + +-export([getsockfd/0,closesockfd/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [{group, t_accept}, {group, t_connect}, {group, t_recv}, t_shutdown_write, t_shutdown_both, t_shutdown_error, - t_fdopen, t_implicit_inet6]. + t_fdopen, t_fdconnect, t_implicit_inet6]. groups() -> [{t_accept, [], [t_accept_timeout]}, @@ -185,6 +187,37 @@ t_fdopen(Config) when is_list(Config) -> ?line ok = gen_tcp:close(L), ok. +t_fdconnect(Config) when is_list(Config) -> + Question = "Aaaa... Long time ago in a small town in Germany,", + Question1 = list_to_binary(Question), + Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ", + ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]], + Question1 = iolist_to_binary(Question2), + Answer = "there was a shoemaker, Schumacher was his name.", + Path = ?config(data_dir, Config), + Lib = "gen_tcp_api_SUITE", + ok = erlang:load_nif(filename:join(Path,Lib), []), + {ok, L} = gen_tcp:listen(0, [{active, false}]), + {ok, Port} = inet:port(L), + FD = gen_tcp_api_SUITE:getsockfd(), + {ok, Client} = gen_tcp:connect(localhost, Port, [{fd,FD},{port,20002}, + {active,false}]), + {ok, Server} = gen_tcp:accept(L), + ok = gen_tcp:send(Client, Question), + {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), + ok = gen_tcp:send(Client, Question1), + {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), + ok = gen_tcp:send(Client, Question2), + {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), + ok = gen_tcp:send(Server, Answer), + {ok, Answer} = gen_tcp:recv(Client, length(Answer), 2000), + ok = gen_tcp:close(Client), + FD = gen_tcp_api_SUITE:closesockfd(FD), + {error,closed} = gen_tcp:recv(Server, 1, 2000), + ok = gen_tcp:close(Server), + ok = gen_tcp:close(L), + ok. + %%% implicit inet6 option to api functions @@ -300,3 +333,7 @@ unused_ip(A, B, C, D) -> end. ok({ok,V}) -> V. + + +getsockfd() -> undefined. +closesockfd(_FD) -> undefined. diff --git a/lib/kernel/test/gen_tcp_api_SUITE_data/Makefile.src b/lib/kernel/test/gen_tcp_api_SUITE_data/Makefile.src new file mode 100644 index 0000000000..5477598160 --- /dev/null +++ b/lib/kernel/test/gen_tcp_api_SUITE_data/Makefile.src @@ -0,0 +1,9 @@ + +NIF_LIBS = gen_tcp_api_SUITE@dll@ +SHLIB_EXTRA_LDLIBS = @LIBS@ + +all: $(NIF_LIBS) + +@SHLIB_RULES@ + +$(NIF_LIBS): gen_tcp_api_SUITE.c diff --git a/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c new file mode 100644 index 0000000000..73a6568b30 --- /dev/null +++ b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c @@ -0,0 +1,60 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009-2013. 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% + */ +#include "erl_nif.h" + +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <limits.h> +#include <sys/types.h> + +#ifdef __WIN32__ +#include <winsock2.h> +#else +#include <sys/socket.h> +#endif + +#define sock_open(af, type, proto) socket((af), (type), (proto)) + +static ERL_NIF_TERM getsockfd(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int fd; + + fd = sock_open(AF_INET, SOCK_STREAM, 0); + return enif_make_int(env, fd); +} + +static ERL_NIF_TERM closesockfd(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int fd; + + enif_get_int(env, argv[0], &fd); + + close(fd); + + return enif_make_int(env, fd); +} + +static ErlNifFunc nif_funcs[] = +{ + {"getsockfd", 0, getsockfd}, + {"closesockfd", 1, closesockfd} +}; + +ERL_NIF_INIT(gen_tcp_api_SUITE,nif_funcs,NULL,NULL,NULL,NULL) diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl index 6bb41999c5..8177123332 100644 --- a/lib/kernel/test/gen_udp_SUITE.erl +++ b/lib/kernel/test/gen_udp_SUITE.erl @@ -447,8 +447,8 @@ 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}]), + {error,einval} = gen_udp:open(0, [inet6, {fd,FD}]), + {ok,S2} = gen_udp:open(0, [{fd,FD}]), {ok,S3} = gen_udp:open(0), {ok,P3} = inet:port(S3), ok = gen_udp:send(S3, Addr, P2, Msg), diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index dd5316b825..1ecfde190e 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 3.0 +KERNEL_VSN = 3.0.2 diff --git a/lib/megaco/configure.in b/lib/megaco/configure.in index 64daa959b5..e3c24a58b8 100644 --- a/lib/megaco/configure.in +++ b/lib/megaco/configure.in @@ -167,6 +167,26 @@ if test "x$GCC" = xyes; then LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS]) fi +dnl ---------------------------------------------------------------------- +dnl Enable -fsanitize= flags. +dnl ---------------------------------------------------------------------- + +m4_define(DEFAULT_SANITIZERS, [address,undefined]) +AC_ARG_ENABLE( + sanitizers, + AS_HELP_STRING( + [--enable-sanitizers@<:@=comma-separated list of sanitizers@:>@], + [Default=DEFAULT_SANITIZERS]), +[ +case "$enableval" in + no) sanitizers= ;; + yes) sanitizers="-fsanitize=DEFAULT_SANITIZERS" ;; + *) sanitizers="-fsanitize=$enableval" ;; +esac +CFLAGS="$CFLAGS $sanitizers" +LDFLAGS="$LDFLAGS $sanitizers" +]) + dnl dnl If ${ERL_TOP}/make/otp_ded.mk.in exists and contains DED_MK_VSN > 0, dnl every thing releted to compiling Dynamic Erlang Drivers can be found diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index 213c2b6d21..08212dfede 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -38,7 +38,30 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.</p> - <section><title>Mnesia 4.12</title> + <section><title>Mnesia 4.12.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Force load table could hang when a node went away during + start up.</p> + <p> + Own Id: OTP-11948 Aux Id: seq12585 </p> + </item> + <item> + <p> + The time for inserting locks for a transaction with large + number of locks is reduced significantly.</p> + <p> + Own Id: OTP-11981</p> + </item> + </list> + </section> + +</section> + +<section><title>Mnesia 4.12</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl index c3846b00c0..e27396731f 100644 --- a/lib/mnesia/src/mnesia_locker.erl +++ b/lib/mnesia/src/mnesia_locker.erl @@ -84,7 +84,7 @@ init(Parent) -> register(?MODULE, self()), process_flag(trap_exit, true), ?ets_new_table(mnesia_held_locks, [ordered_set, private, named_table]), - ?ets_new_table(mnesia_tid_locks, [bag, private, named_table]), + ?ets_new_table(mnesia_tid_locks, [ordered_set, private, named_table]), ?ets_new_table(mnesia_sticky_locks, [set, private, named_table]), ?ets_new_table(mnesia_lock_queue, [bag, private, named_table, {keypos, 2}]), @@ -253,13 +253,13 @@ loop(State) -> end. set_lock(Tid, Oid, Op, []) -> - ?ets_insert(mnesia_tid_locks, {Tid, Oid, Op}), + ?ets_insert(mnesia_tid_locks, {{Tid, Oid, Op}}), ?ets_insert(mnesia_held_locks, {Oid, Op, [{Op, Tid}]}); set_lock(Tid, Oid, read, [{Oid, Prev, Items}]) -> - ?ets_insert(mnesia_tid_locks, {Tid, Oid, read}), + ?ets_insert(mnesia_tid_locks, {{Tid, Oid, read}}), ?ets_insert(mnesia_held_locks, {Oid, Prev, [{read, Tid}|Items]}); set_lock(Tid, Oid, write, [{Oid, _Prev, Items}]) -> - ?ets_insert(mnesia_tid_locks, {Tid, Oid, write}), + ?ets_insert(mnesia_tid_locks, {{Tid, Oid, write}}), ?ets_insert(mnesia_held_locks, {Oid, write, [{write, Tid}|Items]}); set_lock(Tid, Oid, Op, undefined) -> set_lock(Tid, Oid, Op, ?ets_lookup(mnesia_held_locks, Oid)). @@ -299,7 +299,7 @@ try_lock(Tid, Op, SimpleOp, Lock, Pid, Oid) -> ?ets_insert(mnesia_lock_queue, #queue{oid = Oid, tid = Tid, op = Op, pid = Pid, lucky = Lucky}), - ?ets_insert(mnesia_tid_locks, {Tid, Oid, {queued, Op}}) + ?ets_insert(mnesia_tid_locks, {{Tid, Oid, {queued, Op}}}) end. grant_lock(Tid, read, Lock, Oid = {Tab, Key}, Default) @@ -498,7 +498,7 @@ set_read_lock_on_all_keys(Tid, From, Tab, IxKey, Pos) -> ?ets_insert(mnesia_lock_queue, #queue{oid = Oid, tid = Tid, op = Op, pid = From, lucky = Lucky}), - ?ets_insert(mnesia_tid_locks, {Tid, Oid, {queued, Op}}) + ?ets_insert(mnesia_tid_locks, {{Tid, Oid, {queued, Op}}}) end. %%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -514,7 +514,8 @@ release_remote_non_pending(Node, Pending) -> %% running at the failed node and also simply remove all %% queue'd requests back to the failed node - AllTids = ?ets_match(mnesia_tid_locks, {'$1', '_', '_'}), + AllTids0 = ?ets_match(mnesia_tid_locks, {{'$1', '_', '_'}}), + AllTids = lists:usort(AllTids0), Tids = [T || [T] <- AllTids, Node == node(T#tid.pid), not lists:member(T, Pending)], do_release_tids(Tids). @@ -525,9 +526,10 @@ do_release_tids([]) -> ok. do_release_tid(Tid) -> - Locks = ?ets_lookup(mnesia_tid_locks, Tid), + Objects = ets:select(mnesia_tid_locks, [{{{Tid, '_', '_'}}, [], ['$_']}]), + Locks = lists:map(fun({L}) -> L end, Objects), ?dbg("Release ~p ~p ~n", [Tid, Locks]), - ?ets_delete(mnesia_tid_locks, Tid), + [?ets_delete(mnesia_tid_locks, L) || L <- Locks], release_locks(Locks), %% Removed queued locks which has had locks UniqueLocks = keyunique(lists:sort(Locks),[]), diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index c596f98c81..173c46898b 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1 +1 @@ -MNESIA_VSN = 4.12 +MNESIA_VSN = 4.12.1 diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml index a2c5eda9d7..c135e29520 100644 --- a/lib/observer/doc/src/notes.xml +++ b/lib/observer/doc/src/notes.xml @@ -31,6 +31,29 @@ <p>This document describes the changes made to the Observer application.</p> +<section><title>Observer 2.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + crashdump_viewer would crash if the owner of a timer was + specified as the process' registered name. This has been + corrected.</p> + <p> + Own Id: OTP-11919</p> + </item> + <item> + <p> + Fix crash and minor updates.</p> + <p> + Own Id: OTP-11949</p> + </item> + </list> + </section> + +</section> + <section><title>Observer 2.0</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl index 03ca1bf9c1..c86f5ea916 100644 --- a/lib/observer/src/observer_wx.erl +++ b/lib/observer/src/observer_wx.erl @@ -112,10 +112,6 @@ setup(#state{frame = Frame} = State) -> observer_lib:create_menus(DefMenus, MenuBar, default), wxFrame:setMenuBar(Frame, MenuBar), - StatusBar = wxStatusBar:new(Frame), - wxFrame:setStatusBar(Frame, StatusBar), - wxFrame:setTitle(Frame, atom_to_list(node())), - wxStatusBar:setStatusText(StatusBar, atom_to_list(node())), %% Setup panels Panel = wxPanel:new(Frame, []), @@ -131,6 +127,11 @@ setup(#state{frame = Frame} = State) -> wxSizer:add(MainSizer, Notebook, [{proportion, 1}, {flag, ?wxEXPAND}]), wxPanel:setSizer(Panel, MainSizer), + StatusBar = wxStatusBar:new(Frame), + wxFrame:setStatusBar(Frame, StatusBar), + wxFrame:setTitle(Frame, atom_to_list(node())), + wxStatusBar:setStatusText(StatusBar, atom_to_list(node())), + wxNotebook:connect(Notebook, command_notebook_page_changing), wxFrame:connect(Frame, close_window, [{skip, true}]), wxMenu:connect(Frame, command_menu_selected), diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl index 03ab0c20e1..1266b1f9b9 100644 --- a/lib/observer/test/crashdump_viewer_SUITE.erl +++ b/lib/observer/test/crashdump_viewer_SUITE.erl @@ -101,7 +101,7 @@ end_per_group(_GroupName, Config) -> init_per_suite(Config) when is_list(Config) -> delete_saved(Config), DataDir = ?config(data_dir,Config), - Rels = [R || R <- [r15b,r16b], ?t:is_release_available(R)] ++ [current], + Rels = [R || R <- [r16b,'17'], ?t:is_release_available(R)] ++ [current], io:format("Creating crash dumps for the following releases: ~p", [Rels]), AllDumps = create_dumps(DataDir,Rels), [{dumps,AllDumps}|Config]. @@ -563,12 +563,6 @@ dump_with_strange_module_name(DataDir,Rel,DumpName) -> CD. dump(Node,DataDir,Rel,DumpName) -> - case Rel of - _ when Rel<r15b, Rel=/=current -> - rpc:call(Node,os,putenv,["ERL_CRASH_DUMP_SECONDS","600"]); - _ -> - ok - end, rpc:call(Node,erlang,halt,[DumpName]), Crashdump0 = filename:join(filename:dirname(code:which(?t)), "erl_crash_dump.n1"), @@ -623,42 +617,21 @@ dos_dump(DataDir,Rel,Dump) -> rel_opt(Rel) -> case Rel of - r9b -> [{erl,[{release,"r9b_patched"}]}]; - r9c -> [{erl,[{release,"r9c_patched"}]}]; - r10b -> [{erl,[{release,"r10b_patched"}]}]; - r11b -> [{erl,[{release,"r11b_patched"}]}]; - r12b -> [{erl,[{release,"r12b_patched"}]}]; - r13b -> [{erl,[{release,"r13b_patched"}]}]; - r14b -> [{erl,[{release,"r14b_latest"}]}]; %naming convention changed - r15b -> [{erl,[{release,"r15b_latest"}]}]; r16b -> [{erl,[{release,"r16b_latest"}]}]; + '17' -> [{erl,[{release,"17_latest"}]}]; current -> [] end. dump_prefix(Rel) -> case Rel of - r9b -> "r9b_dump."; - r9c -> "r9c_dump."; - r10b -> "r10b_dump."; - r11b -> "r11b_dump."; - r12b -> "r12b_dump."; - r13b -> "r13b_dump."; - r14b -> "r14b_dump."; - r15b -> "r15b_dump."; r16b -> "r16b_dump."; - current -> "r17b_dump." + '17' -> "r17_dump."; + current -> "r18_dump." end. compat_rel(Rel) -> case Rel of - r9b -> "+R9 "; - r9c -> "+R9 "; - r10b -> "+R10 "; - r11b -> "+R11 "; - r12b -> "+R12 "; - r13b -> "+R13 "; - r14b -> "+R14 "; - r15b -> "+R15 "; r16b -> "+R16 "; + '17' -> "+R17 "; current -> "" end. diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk index a6300eeb18..b55cff7332 100644 --- a/lib/observer/vsn.mk +++ b/lib/observer/vsn.mk @@ -1 +1 @@ -OBSERVER_VSN = 2.0 +OBSERVER_VSN = 2.0.1 diff --git a/lib/odbc/configure.in b/lib/odbc/configure.in index f86146759c..ea5c51965f 100644 --- a/lib/odbc/configure.in +++ b/lib/odbc/configure.in @@ -228,4 +228,24 @@ if test "x$GCC" = xyes; then LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS]) fi +dnl ---------------------------------------------------------------------- +dnl Enable -fsanitize= flags. +dnl ---------------------------------------------------------------------- + +m4_define(DEFAULT_SANITIZERS, [address,undefined]) +AC_ARG_ENABLE( + sanitizers, + AS_HELP_STRING( + [--enable-sanitizers@<:@=comma-separated list of sanitizers@:>@], + [Default=DEFAULT_SANITIZERS]), +[ +case "$enableval" in + no) sanitizers= ;; + yes) sanitizers="-fsanitize=DEFAULT_SANITIZERS" ;; + *) sanitizers="-fsanitize=$enableval" ;; +esac +CFLAGS="$CFLAGS $sanitizers" +LDFLAGS="$LDFLAGS $sanitizers" +]) + AC_OUTPUT(c_src/$host/Makefile:c_src/Makefile.in) diff --git a/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl b/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl index 5ec0c084e3..c665e1fbc8 100644 --- a/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl +++ b/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl @@ -176,7 +176,6 @@ addresses({false, Adr, Rest}, Addresses) -> {lists:reverse([Adr|Addresses]), Rest}; addresses({true, Adr, Rest}, Addresses) -> addresses(address(protocol, Rest, [], []), [Adr|Addresses]). - %% Which protocol. address(protocol, [$:|T], [], []) -> address(version, T, [], [iiop]); @@ -192,6 +191,7 @@ address(protocol, What, _, _) -> [?LINE, What], ?DEBUG_LEVEL), corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{}); + %% Parsed one address, no version found or port found. address(version, [$,|T], Acc, Previous) -> {true, lists:reverse([?DEF_PORT, lists:reverse(Acc), ?DEF_VERS|Previous]), T}; @@ -208,15 +208,26 @@ address(version, [$@|T], Acc, Previous) -> [?LINE, What], ?DEBUG_LEVEL), corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{}) end; + +%% Found no iiop version, switch to ipv6. +address(version, [$[|T], [], Previous) -> + address(ipv6, T, [], [?DEF_VERS|Previous]); + %% Found no iiop version, switch to port. In this case Acc contains the %% Host. address(version, [$:|T], Acc, Previous) -> - case check_ip_version(T, [$:|Acc]) of - false -> - address(port, T, [], [lists:reverse(Acc), ?DEF_VERS|Previous]); - {ok, NewAcc, NewT, Type} -> - address(Type, NewT, [], [lists:reverse(NewAcc), ?DEF_VERS|Previous]) - end; + address(port, T, [], [lists:reverse(Acc), ?DEF_VERS|Previous]); + +%% Found IPv6 +address(address, [$[|T], [], Previous) -> + address(ipv6, T, [], Previous); + +%% Found port +address(address, [$:|T], Acc, Previous) -> + address(port, T, [], [lists:reverse(Acc)|Previous]); + +address(ipv6, [$]|T], Acc, Previous) -> + address(address, T, Acc, Previous); %% Parsed one address, port not found. address(address, [$,|T], [], Previous) -> @@ -267,68 +278,9 @@ address(address, [], [], Previous) -> address(address, [], Acc, Previous) -> {false, lists:reverse([?DEF_PORT, lists:reverse(Acc)|Previous]), []}; -%% Found port -address(address, [$:|T], Acc, Previous) -> - case check_ip_version(T, [$:|Acc]) of - false -> - address(port, T, [], [lists:reverse(Acc)|Previous]); - {ok, NewAcc, NewT, Type} -> - address(Type, NewT, [], [lists:reverse(NewAcc)|Previous]) - end; - address(Type, [H|T], Acc, Previous) -> address(Type, T, [H|Acc], Previous). - -check_ip_version(T, Acc) -> - case orber_env:ip_version() of - inet -> - false; - inet6 -> - case search_for_delimiter(1, T, Acc, $:) of - {ok, NewAcc, NewT, Type} -> - {ok, NewAcc, NewT, Type}; - _ -> - false - end - end. - -%% An IPv6 address may look like (x == hex, d == dec): -%% * "0:0:0:0:0:0:10.1.1.1" - x:x:x:x:x:x:d.d.d.d -%% * "0:0:0:0:8:800:200C:417A" - x:x:x:x:x:x:x:x -%% We cannot allow compressed addresses (::10.1.1.1) since we it is not -%% possible to know if the last part is a port number or part of the address. -search_for_delimiter(7, [], Acc, $:) -> - {ok, Acc, [], address}; -search_for_delimiter(9, [], Acc, $.) -> - {ok, Acc, [], address}; -search_for_delimiter(_, [], _, _) -> - false; -search_for_delimiter(7, [$/|T], Acc, $:) -> - {ok, Acc, [$/|T], address}; -search_for_delimiter(9, [$/|T], Acc, $.) -> - {ok, Acc, [$/|T], address}; -search_for_delimiter(_, [$/|_T], _Acc, _) -> - false; -search_for_delimiter(7, [$,|T], Acc, $:) -> - {ok, Acc, [$,|T], address}; -search_for_delimiter(9, [$,|T], Acc, $.) -> - {ok, Acc, [$,|T], address}; -search_for_delimiter(_, [$,|_T], _Acc, _) -> - false; -search_for_delimiter(7, [$:|T], Acc, $:) -> - {ok, Acc, T, port}; -search_for_delimiter(9, [$:|T], Acc, $.) -> - {ok, Acc, T, port}; -search_for_delimiter(N, [$:|T], Acc, $:) -> - search_for_delimiter(N+1, T, [$:|Acc], $:); -search_for_delimiter(N, [$.|T], Acc, $.) when N > 6, N < 9 -> - search_for_delimiter(N+1, T, [$.|Acc], $.); -search_for_delimiter(6, [$.|T], Acc, $:) -> - search_for_delimiter(7, T, [$.|Acc], $.); -search_for_delimiter(N, [H|T], Acc, LookingFor) -> - search_for_delimiter(N, T, [H|Acc], LookingFor). - %%---------------------------------------------------------------------- %% Function : key %% Arguments : A string which contain a Key we want to use and, if defined, diff --git a/lib/orber/doc/src/ch_naming_service.xml b/lib/orber/doc/src/ch_naming_service.xml index b735629a14..e355db2edb 100644 --- a/lib/orber/doc/src/ch_naming_service.xml +++ b/lib/orber/doc/src/ch_naming_service.xml @@ -273,25 +273,28 @@ lists:foreach(fun({{Id, Kind},BindingType}) -> case BindingType of <p>The notation of this scheme is similar to the more well known URL <c>HTTP</c>, and the full <c>corbaloc</c> BNF is:</p> <code type="none"><![CDATA[ -<corbaloc> = "corbaloc:"<obj_addr_list>["/"<key_string>] -<obj_addr_list> = [<obj_addr>","]*<obj_addr> -<obj_addr> = <prot_addr> | <future_prot_addr> -<prot_addr> = <rir_prot_addr> | <iiop_prot_addr> -<rir_prot_addr> = <rir_prot_token>":" -<rir_prot_token> = rir -<future_prot_addr> = <future_prot_id><future_prot_addr> -<future_prot_id> = <future_prot_token>":" -<iiop_prot_addr> = <iiop_id><iiop_addr> -<iiop_id> = <iiop_default> | <iiop_prot_token>":" -<iiop_default> = ":" -<iiop_prot_token> = "iiop" -<iiop_addr> = <version><host>[":"<port>] -<host> = DNS-style Host Name | ip_address -<version> = <major>"."<minor>"@" | empty_string -<port> = number -<major> = number -<minor> = number -<key_string> = for example NameService +<corbaloc> = "corbaloc:"<obj_addr_list>["/"<key_string>] +<obj_addr_list> = [<obj_addr>","]*<obj_addr> +<obj_addr> = <prot_addr> | <future_prot_addr> +<prot_addr> = <rir_prot_addr> | <iiop_prot_addr> +<rir_prot_addr> = <rir_prot_token>":" +<rir_prot_token> = rir +<future_prot_addr> = <future_prot_id><future_prot_addr> +<future_prot_id> = <future_prot_token>":" +<iiop_prot_addr> = <iiop_id><iiop_addr> +<iiop_id> = <iiop_default> | <iiop_prot_token>":" +<iiop_default> = ":" +<iiop_prot_token> = "iiop" +<iiop_addr> = <version><host>[":"<port>] +<host> = <DNS-style Host Name> | <ip_v4_address> | "["<ip_v6_address>"]" +<version> = <major>"."<minor>"@" | empty_string +<port> = number +<major> = number +<minor> = number +<DNS-style Host Name> = string +<ip_v4_address> = string +<ip_v6_address> = string +<key_string> = for example NameService ]]></code> <p>The <c>corbaloc</c> scheme consists of 3 parts:</p> <list type="bulleted"> diff --git a/lib/orber/doc/src/corba.xml b/lib/orber/doc/src/corba.xml index 004c7fb9b0..4a11b271b4 100644 --- a/lib/orber/doc/src/corba.xml +++ b/lib/orber/doc/src/corba.xml @@ -294,7 +294,9 @@ Example: <p>This function returns the object reference for the object id asked for. The remote modifier string has the following format: - <c>"iiop://host:port"</c>.</p> + <c>"iiop://"<host>":"<port></c> where <c><host> = <DNS hostname> | + <IPv4 address> | "["<IPv6 address>"]"</c>. + </p> <p>The <em>configuration</em> context is used to override the global SSL client side <seealso marker="ch_install#config">configuration</seealso>.</p> @@ -322,8 +324,11 @@ Example: <v>ObjectId = string()</v> </type> <desc> - <p>This function returns a list of allowed object id's. The remote modifier - string has the following format: <c>"iiop://host:port"</c>.</p> + <p>This function returns a list of allowed object id's. + The remote modifier string has the following format: + <c>"iiop://"<host>":"<port></c> where <c><host> = <DNS hostname> | + <IPv4 address> | "["<IPv6 address>"]"</c>. + </p> <p>The <em>configuration</em> context is used to override the global SSL client side <seealso marker="ch_install#config">configuration</seealso>.</p> @@ -365,9 +370,11 @@ Example: <p>This function takes a <c>corbaname</c>, <c>corbaloc</c> or an IOR on the external string representation and returns the object reference.</p> <p>To lookup the NameService reference, simply use - <c>"corbaloc:iiop:[email protected]:4001/NameService"</c></p> + <c>"corbaloc:iiop:[email protected]:4001/NameService"</c></p> <p>We can also resolve an object from the NameService by using - <c>"corbaname:iiop:[email protected]:4001/NameService#org/Erlang/MyObj"</c></p> + <c>"corbaname:iiop:[email protected]:4001/NameService#org/Erlang/MyObj"</c></p> + <p>To lookup the NameService reference with an IPv6 address, simply use + <c>"corbaloc:iiop:1.2@[FEC1:0:3:0:0312:44AF:FAB1:3D01]:4001/NameService"</c></p> <p>For more information about <c>corbaname</c> and <c>corbaloc</c>, see the User's Guide (Interoperable Naming Service).</p> <p>The <em>configuration</em> context is used to override the global diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml index 93dc403c47..141d306740 100644 --- a/lib/orber/doc/src/notes.xml +++ b/lib/orber/doc/src/notes.xml @@ -33,7 +33,46 @@ </header> - <section><title>Orber 3.6.27</title> + <section><title>Orber 3.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> The following functions have been corrected so they + work properly with IPv6 addresses. </p> <list> + <item><c>corba:resolve_initial_references_remote/2/3</c></item> + <item><c>corba:list_initial_references_remote/1/2</c></item> + <item><c>corba:string_to_object/1/2</c></item> </list> + <p> + Own Id: OTP-12016</p> + </item> + <item> + <p> A couple of macros were malformed, missing commas: + PROFILEBODY_1_1_TYPEDEF and PROFILEBODY_1_2_TYPEDEF. + Thanks to Vlad Dumitrescu. </p> + <p> + Own Id: OTP-12062</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> It is now possible to add listen interfaces for IPv6 + when orber is default configured for IPv4 and the other + way around. For more information, consult the User's + Guide and the orber module Reference Manual. </p> + <p> + Own Id: OTP-12007</p> + </item> + </list> + </section> + +</section> + +<section><title>Orber 3.6.27</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/orber/doc/src/orber.xml b/lib/orber/doc/src/orber.xml index 16781059c7..a182a56972 100644 --- a/lib/orber/doc/src/orber.xml +++ b/lib/orber/doc/src/orber.xml @@ -356,8 +356,8 @@ <v>Type = normal | ssl</v> <v>Port = integer() > 0</v> <v>ConfigurationParameters = [{Key, Value}]</v> - <v>Key = flags | iiop_in_connection_timeout | iiop_max_fragments | iiop_max_in_requests | interceptors | iiop_port | iiop_ssl_port | ssl_server_options</v> - <v>Value = as described in the User's Guide</v> + <v>Key = flags | ip_family | iiop_in_connection_timeout | iiop_max_fragments | iiop_max_in_requests | interceptors | iiop_port | iiop_ssl_port | ssl_server_options</v> + <v>Value = as described in the User's Guide or below</v> <v>Result = {ok, Ref} | {error, Reason} | {'EXCEPTION', #'BAD_PARAM'{}}</v> <v>Ref = #Ref</v> <v>Reason = string()</v> @@ -383,6 +383,9 @@ <item><em>flags</em> - currently it is only possible to override the global setting for the <c>Use Current Interface in IOR</c> and <c>Exclude CodeSet Component</c> flags.</item> + <item><em>ip_family</em> - can be set to <c>inet</c> or <c>inet6</c> and is + used to get a listen interface that uses another IP version than the default + set with flags at startup.</item> <item><em>iiop_port</em> - requires that <c>Use Current Interface in IOR</c> is activated and the supplied <c>Type</c> is <c>normal</c>. If so, exported IOR:s will contain the IIOP port defined by this configuration @@ -390,7 +393,7 @@ <item><em>iiop_ssl_port</em> - almost equivalent to <c>iiop_port</c>. The difference is that <c>Type</c> shall be <c>ssl</c> and that exported IOR:s will contain the IIOP via SSL port defined by this configuration - parameter.</item> + parameter.</item> </list> <p>If it is not possible to add a listener based on the supplied interface and port, the error message is one of the ones described in <c>inet</c> diff --git a/lib/orber/src/Makefile b/lib/orber/src/Makefile index d96350f4d5..398e481138 100644 --- a/lib/orber/src/Makefile +++ b/lib/orber/src/Makefile @@ -194,8 +194,7 @@ ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin ERL_COMPILE_FLAGS += $(ERL_IDL_FLAGS) \ -I$(ERL_TOP)/lib/orber/include \ +'{parse_transform,sys_pre_attributes}' \ - +'{attribute,insert,app_vsn,"orber_$(ORBER_VSN)"}' \ - -D'ORBVSN="$(ORBER_VSN)"' + +'{attribute,insert,app_vsn,"orber_$(ORBER_VSN)"}' ASN_FLAGS = -bber +der +compact_bit_string +nowarn_unused_record diff --git a/lib/orber/src/corba.erl b/lib/orber/src/corba.erl index 989e84f581..586a02d540 100644 --- a/lib/orber/src/corba.erl +++ b/lib/orber/src/corba.erl @@ -311,19 +311,18 @@ resolve_initial_references_remote(_ObjectId, [], _Ctx) -> raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}); resolve_initial_references_remote(ObjectId, [RemoteModifier| Rest], Ctx) when is_list(RemoteModifier) -> - case lists:prefix("iiop://", RemoteModifier) of - true -> - [_, Host, Port] = string:tokens(RemoteModifier, ":/"), + case parse_remote_modifier(RemoteModifier) of + {error, _} -> + resolve_initial_references_remote(ObjectId, Rest, Ctx); + {ok, Host, Port} -> IOR = iop_ior:create_external(orber:giop_version(), "", - Host, list_to_integer(Port), "INIT"), + Host, list_to_integer(Port), "INIT"), %% We know it's an external referens. Hence, no need to check. {_, Key} = iop_ior:get_key(IOR), orber_iiop:request(Key, 'get', [ObjectId], {{'tk_objref', 12, "object"}, [{'tk_string', 0}], - []}, 'true', infinity, IOR, Ctx); - false -> - resolve_initial_references_remote(ObjectId, Rest, Ctx) + []}, 'true', infinity, IOR, Ctx) end. list_initial_services_remote(Address) -> @@ -332,24 +331,44 @@ list_initial_services_remote(Address) -> list_initial_services_remote([], _Ctx) -> raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}); list_initial_services_remote([RemoteModifier| Rest], Ctx) when is_list(RemoteModifier) -> - case lists:prefix("iiop://", RemoteModifier) of - true -> - [_, Host, Port] = string:tokens(RemoteModifier, ":/"), + case parse_remote_modifier(RemoteModifier) of + {error, _} -> + resolve_initial_references_remote(Rest, Ctx); + {ok, Host, Port} -> IOR = iop_ior:create_external(orber:giop_version(), "", Host, list_to_integer(Port), "INIT"), %% We know it's an external referens. Hence, no need to check. {_, Key} = iop_ior:get_key(IOR), orber_iiop:request(Key, 'list', [], {{'tk_sequence', {'tk_string',0},0}, - [], []}, 'true', infinity, IOR, Ctx); - false -> - list_initial_services_remote(Rest, Ctx) + [], []}, 'true', infinity, IOR, Ctx) end; list_initial_services_remote(_, _) -> raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}). +parse_remote_modifier("iiop://" ++ Rest) -> + parse_host_version(Rest); +parse_remote_modifier(_RemoteModifier) -> + {error, not_supported}. + +parse_host_version("[" ++ Rest) -> + parse_ipv6(Rest, []); +parse_host_version(Rest) -> + parse_ipv4_or_dnsname(Rest, []). + + +parse_ipv4_or_dnsname([$: |Rest], Acc) -> + {ok, lists:reverse(Acc), Rest}; +parse_ipv4_or_dnsname([C |Rest], Acc) -> + parse_ipv4_or_dnsname(Rest, [C |Acc]). + +parse_ipv6("]:" ++ Rest, Acc) -> + {ok, lists:reverse(Acc), Rest}; +parse_ipv6([C |Rest], Acc) -> + parse_ipv6(Rest, [C |Acc]). + %%----------------------------------------------------------------- %% Objectreference convertions %%----------------------------------------------------------------- diff --git a/lib/orber/src/corba_request.erl b/lib/orber/src/corba_request.erl deleted file mode 100644 index c4226739a9..0000000000 --- a/lib/orber/src/corba_request.erl +++ /dev/null @@ -1,384 +0,0 @@ -%%-------------------------------------------------------------------- -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1998-2009. 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% -%% -%% -%%----------------------------------------------------------------- -%% File: corba_request.erl -%% Description: -%% This file contains an corba request server for Orber -%% -%%----------------------------------------------------------------- --module(corba_request). - --behaviour(gen_server). - --include_lib("orber/include/corba.hrl"). - -%%----------------------------------------------------------------- -%% External exports -%%----------------------------------------------------------------- --export([start/1, stop/0, stop_all/0, create/1, - create_schema/1]). - -%%----------------------------------------------------------------- -%% Internal exports -%%----------------------------------------------------------------- --export([init/1, terminate/2, install/2, handle_call/3, handle_info/2]). --export([handle_cast/2, dump/0, get_key_from_pid/1]). - -%%----------------------------------------------------------------- -%% Standard interface CORBA::Request -%%----------------------------------------------------------------- --export([add_arg/6, - invoke/2, - delete/1, - send/2, - get_response/2]). - -%%----------------------------------------------------------------- -%% Mnesia table definition -%%----------------------------------------------------------------- --record('corba_request', {reqid, ctx, operation, arg_list, result, req_flags, pid}). - - -%%----------------------------------------------------------------- -%% Macros -%%----------------------------------------------------------------- --define(dirty_query_context, true). - -%% This macro returns a read fun suitable for evaluation in a transaction --define(read_function(ReqId), - fun() -> - mnesia:dirty_read(ReqId) - end). - -%% This macro returns a write fun suitable for evaluation in a transaction --define(write_function(R), - fun() -> - mnesia:dirty_write(R) - end). - -%% This macro returns a write fun suitable for evaluation in a transaction --define(update(R), - fun() -> - mnesia:dirty_write(R) - end). - -%% This macro returns a delete fun suitable for evaluation in a transaction --define(delete_function(R), - fun() -> - mnesia:delete(R) - end). - --ifdef(dirty_query_context). --define(query_check(Q_res), Q_res). --else. --define(query_check(Q_res), {atomic, Q_res}). --endif. - - --define(CHECK_EXCEPTION(Res), case Res of - {'EXCEPTION', E} -> - corba:raise(E); - R -> - R - end). - -%%----------------------------------------------------------------- -%% Debugging function -%%----------------------------------------------------------------- -dump() -> - case catch mnesia:dirty_first('orber_request') of - {'EXIT', R} -> - io:format("Exited with ~p\n",[R]); - Key -> - dump_print(Key), - dump_loop(Key) - end. - -dump_loop(PreviousKey) -> - case catch mnesia:dirty_next('orber_request', PreviousKey) of - {'EXIT', R} -> - io:format("Exited with ~p\n",[R]); - '$end_of_table' -> - ok; - Key -> - dump_print(Key), - dump_loop(Key) - end. - -dump_print(Key) -> - case catch mnesia:dirty_read({'orber_request', Key}) of - {'EXIT', R} -> - io:format("Exited with ~p\n",[R]); - [X] -> - io:format("Req Id: ~p, op: ~p\n",[binary_to_term(X#orber_request.object_key), - X#orber_request.pid]); - _ -> - ok - end. - - -%%----------------------------------------------------------------- -%% External interface functions -%%----------------------------------------------------------------- -start(Opts) -> - gen_server:start_link({local, orber_requestserver}, orber_request, Opts, []). - -stop() -> - gen_server:call(orber_requestserver, stop, infinity). - - -stop_all() -> - Fun = fun() -> - mnesia:match_object({orber_request, '_', '_', '_', '_', '_', '_', '_'}) - end, - case catch mnesia:transaction(Fun) of - {atomic, Objects} -> - lists:foreach(fun({orber_request, _, _, _, _, _, _, _ }) -> - ok %gen_server:call(Pid, stop, infinity) - end, - Objects); - R -> - R - end. - -create() -> - ?CHECK_EXCEPTION(gen_server:call(orber_requestserver, - create, infinity)). - -create(Ctx, OP, Args, Flags) -> - ?CHECK_EXCEPTION(gen_server:call(orber_requestserver, - {create, Ctx, OP, Args, Flags}, infinity)). - -delete(ReqId) -> - ?CHECK_EXCEPTION(gen_server:call(orber_requestserver, - {delete, ReqId}, infinity)). - -%%------------------------------------------------------------ -%% Implementation of standard interface -%%------------------------------------------------------------ -add_arg(ReqId, ArgumentName, TC, Value, Len, ArgFlags) -> - Request = ets:lookup_element(orber_request, ReqId), - case Request of - [] -> - ok; - R -> - Args = Request#orber_request.arg_list, - NewArgs = lists:append(Args, []), - ets:insert(orber_request, NewArgs), - ok - end. - -invoke(ReqId, InvokeFlags) -> - ok. - - - -send(ReqId, InvokeFlags) -> - ok. - -get_response(ReqId, ResponseFlags) -> - [{_, Val}] = ets:lookup_element(orber_request, ReqId), - Val#'orber_request'.result. - -%%----------------------------------------------------------------- -%% Server functions -%%----------------------------------------------------------------- -init(Env) -> - case mnesia:wait_for_tables(['orber_request'], infinity) of - ok -> - process_flag(trap_exit, true), - {ok, []}; - StopReason -> - {stop, StopReason} - end. - -terminate(From, Reason) -> - ok. - - - -install(Timeout, Options) -> - %% check if there already exists a database. If not, create one. - %% DB_initialized = perhaps_create_schema(Nodelist), - %% check if mnesia is running. If not, start mnesia. - DB_started = perhaps_start_mnesia(), - - %% Do we have a complete set of IFR tables? If not, create them. - AllTabs = mnesia:system_info(tables), - - DB_Result = case lists:member(orber_request, AllTabs) of - true -> - case lists:member({local_content, true}, - Options) of - true-> - mnesia:add_table_copy(orber_request, - node(), - ram_copies); - _ -> - mnesia:create_table(orber_request, - [{attributes, - record_info(fields, - orber_objkeys)} - |Options]) - end; - _ -> - mnesia:create_table(orber_request, - [{attributes, - record_info(fields, - orber_objkeys)} - |Options]) - end, - - Wait = mnesia:wait_for_tables([orber_request], Timeout), - %% Check if any error has occured yet. If there are errors, return them. - if - DB_Result == {atomic, ok}, - Wait == ok -> - ok; - true -> - {error, {DB_Result, Wait}} - end. - -%%----------------------------------------------------------------- -%% Func: handle_call/3 -%% -%% Comment: -%% In objectkey gen_server all exceptions are tupples and corba:raise -%% may not be used. It is too time consuming to add catches in every -%% function before returning. On the client side there is a case which -%% maps every tupple on the format {'exception', E} to corba:raise(E). -%%----------------------------------------------------------------- -handle_call(stop, From, State) -> - {stop, normal, [], State}; -handle_call(create, From, State) -> - ReqId = term_to_binary({node(), now()}), - _F = ?write_function(#'corba_request'{reqid=ReqId}), - R = write_result(mnesia:transaction(_F)), - - ReqId - - ?query_check(Qres) = mnesia:dirty_read({orber_request, Objkey}), - case Qres of - [] -> - _F = ?write_function(#orber_requests{object_key=Objkey, pid=Pid}), - R = write_result(mnesia:transaction(_F)), - if - R == ok, pid(Pid) -> - link(Pid); - true -> - true - end, - {reply, R, State}; - X -> - {reply, {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}, - State} - end; -handle_call({delete, ReqId}, From, State) -> - ?query_check(Qres) = mnesia:dirty_read({orber_request, ReqId}), - case Qres of - [] -> - true; - [X] when pid(X#orber_request.pid) -> - unlink(X#orber_request.pid); - _ -> - true - end, - _F = ?delete_function({orber_request, ReqId}), - R = write_result(mnesia:transaction(_F)), - {reply, R, State}. - -handle_info({'EXIT', Pid, Reason}, State) when pid(Pid) -> - _MF = fun() -> - mnesia:match_object({orber_request, '_', '_', '_', '_', '_', '_', Pid}) - end, - ?query_check(Qres) = mnesia:ets(_MF), - case Qres of - [] -> - true; - X -> - remove_requests(X), - unlink(Pid); - _ -> - true - end, - {noreply, State}. - -%%----------------------------------------------------------------- -%% Internal Functions -%%----------------------------------------------------------------- -get_reqids_from_pid(Pid) -> - case mnesia:dirty_match_object({orber_request, '_', '_', '_', '_', '_', '_', Pid}) of - Keys -> - [Keys] - _ -> - corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO}) - end. - -remove_requests([]) -> - ok; -remove_requests([H|T]) -> - _F = ?delete_function({orber_request, H#orber_request.reqid}), - write_result(mnesia:transaction(_F)), - remove_requests(T). - -%%----------------------------------------------------------------- -%% Check a read transaction -query_result(?query_check(Qres)) -> - case Qres of - [Hres] -> - Hres#orber_request.pid; - [] -> - {'excpetion', #'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO}}; - Other -> - {'excpetion', #'INTERNAL'{completion_status=?COMPLETED_NO}} - end. - -%%----------------------------------------------------------------- -%% Check a write transaction -write_result({atomic,ok}) -> ok; -write_result(Foo) -> - {'excpetion', #'INTERNAL'{completion_status=?COMPLETED_NO}}. - - -create_schema(Nodes) -> - case mnesia:system_info(use_dir) of - false -> - mnesia:create_schema(Nodes); - _ -> - ok - end. - -perhaps_start_mnesia() -> - case mnesia:system_info(is_running) of - no -> - mnesia:start(); - _ -> - ok - end. - - -%%------------------------------------------------------------ -%% Standard gen_server cast handle -%% -handle_cast(_, State) -> - {noreply, State}. - - diff --git a/lib/orber/src/orber_env.erl b/lib/orber/src/orber_env.erl index 1c8a90bc81..16dbb74253 100644 --- a/lib/orber/src/orber_env.erl +++ b/lib/orber/src/orber_env.erl @@ -204,9 +204,9 @@ info(IoDevice) -> _ -> lists:flatten( io_lib:format("======= Orber Execution Environment ======~n" - " *** Orber-~s is not running ***~n" + " *** Orber is not running ***~n" "==========================================~n", - [?ORBVSN])) + [])) end, case IoDevice of info_msg -> @@ -223,6 +223,7 @@ info(IoDevice) -> create_main_info() -> {Major, Minor} = giop_version(), + {orber, _, OrberVsn} = lists:keyfind(orber, 1, application:loaded_applications()), [io_lib:format("======= Orber Execution Environment ======~n" "Orber version.................: ~s~n" "Orber domain..................: ~s~n" @@ -257,7 +258,7 @@ create_main_info() -> "Debug Level...................: ~p~n" "orbInitRef....................: ~p~n" "orbDefaultInitRef.............: ~p~n", - [?ORBVSN, domain(), iiop_port(), nat_iiop_port(), host(), + [OrberVsn, domain(), iiop_port(), nat_iiop_port(), host(), nat_host(), ip_address_local(), orber:orber_nodes(), Major, Minor, iiop_timeout(), iiop_connection_timeout(), diff --git a/lib/orber/src/orber_iiop.hrl b/lib/orber/src/orber_iiop.hrl index 7a30af63e4..b2e970b30d 100644 --- a/lib/orber/src/orber_iiop.hrl +++ b/lib/orber/src/orber_iiop.hrl @@ -467,14 +467,14 @@ [{"iiop_version",?IIOP_VERSION }, {"host", {'tk_string', 0}}, {"port", 'tk_ushort'}, - {"object_key", {'tk_sequence', 'tk_octet', 0}} + {"object_key", {'tk_sequence', 'tk_octet', 0}}, {"components", ?IOP_TAGGEDCOMPONENT_SEQ}]}). -define(PROFILEBODY_1_2_TYPEDEF, {'tk_struct', ?SYSTEM_TYPE, 'IIOP_ProfileBody_1_1', [{"iiop_version",?IIOP_VERSION }, {"host", {'tk_string', 0}}, {"port", 'tk_ushort'}, - {"object_key", {'tk_sequence', 'tk_octet', 0}} + {"object_key", {'tk_sequence', 'tk_octet', 0}}, {"components", ?IOP_TAGGEDCOMPONENT_SEQ}]}). -define(SSLIOP_SSL, {'tk_struct', ?SYSTEM_TYPE, 'SSLIOP_SSL', diff --git a/lib/orber/src/orber_iiop_net.erl b/lib/orber/src/orber_iiop_net.erl index 33e02e3c04..1bfc6b7d58 100644 --- a/lib/orber/src/orber_iiop_net.erl +++ b/lib/orber/src/orber_iiop_net.erl @@ -157,7 +157,7 @@ terminate(_Reason, _State) -> ok. %%----------------------------------------------------------------- -%% Func: parse_options/2 +%% Func: get_options/2 %%----------------------------------------------------------------- get_options(normal, _Options) -> []; @@ -212,14 +212,21 @@ get_options(ssl, Options) -> %%----------------------------------------------------------------- parse_options([{port, Type, Port} | Rest], State) -> Options = get_options(Type, []), - Options2 = case orber_env:ip_address_variable_defined() of - false -> - Options; - Host -> - IPVersion = orber:ip_version(), - {ok, IP} = inet:getaddr(Host, IPVersion), - [{ip, IP} | Options] - end, + Family = orber_env:ip_version(), + IPFamilyOptions = + case Family of + inet -> [inet]; + inet6 -> [inet6, {ipv6_v6only, true}] + end, + Options2 = + case orber_env:ip_address_variable_defined() of + false -> + IPFamilyOptions ++ Options; + Host -> + {ok, IP} = inet:getaddr(Host, Family), + IPFamilyOptions ++ [{ip, IP} |Options] + end, + {ok, Listen, NewPort} = orber_socket:listen(Type, Port, Options2, true), {ok, Pid} = orber_iiop_socketsup:start_accept(Type, Listen, 0), link(Pid), @@ -283,28 +290,33 @@ handle_call({remove, Ref}, _From, State) -> {reply, ok, State} end; handle_call({add, IP, Type, Port, AllOptions}, _From, State) -> - Family = orber_env:ip_version(), + Family = orber_tb:keysearch(ip_family, AllOptions, orber_env:ip_version()), + IPFamilyOptions = + case Family of + inet -> [inet]; + inet6 -> [inet6, {ipv6_v6only, true}] + end, case inet:getaddr(IP, Family) of {ok, IPTuple} -> - try [{ip, IPTuple} |get_options(Type, AllOptions)] of - Options -> - Ref = make_ref(), - ProxyOptions = filter_options(AllOptions, []), - case orber_socket:listen(Type, Port, Options, false) of - {ok, Listen, NewPort} -> - {ok, Pid} = orber_iiop_socketsup:start_accept(Type, Listen, Ref, - ProxyOptions), - link(Pid), - ets:insert(?CONNECTION_DB, #listen{pid = Pid, - socket = Listen, - port = NewPort, - type = Type, ref = Ref, - options = Options, - proxy_options = ProxyOptions}), - {reply, {ok, Ref}, State}; - Error -> - {reply, Error, State} - end + try + Options = IPFamilyOptions ++ [{ip, IPTuple} |get_options(Type, AllOptions)], + Ref = make_ref(), + ProxyOptions = filter_options(AllOptions, []), + case orber_socket:listen(Type, Port, Options, false) of + {ok, Listen, NewPort} -> + {ok, Pid} = orber_iiop_socketsup:start_accept(Type, Listen, Ref, + ProxyOptions), + link(Pid), + ets:insert(?CONNECTION_DB, #listen{pid = Pid, + socket = Listen, + port = NewPort, + type = Type, ref = Ref, + options = Options, + proxy_options = ProxyOptions}), + {reply, {ok, Ref}, State}; + Error -> + {reply, Error, State} + end catch error:Reason -> {reply, {error, Reason}, State} diff --git a/lib/orber/src/orber_iiop_outproxy.erl b/lib/orber/src/orber_iiop_outproxy.erl index 8319d89088..4ba5b05995 100644 --- a/lib/orber/src/orber_iiop_outproxy.erl +++ b/lib/orber/src/orber_iiop_outproxy.erl @@ -112,7 +112,8 @@ stop(Pid) -> %%----------------------------------------------------------------- init({connect, Host, Port, SocketType, SocketOptions, Parent, Key, NewKey}) -> process_flag(trap_exit, true), - case catch orber_socket:connect(SocketType, Host, Port, SocketOptions) of + case catch orber_socket:connect(SocketType, Host, Port, + get_ip_family_opts(Host) ++ SocketOptions) of {'EXCEPTION', _E} -> ignore; %% We used to reply the below but since this would generate a CRASH REPORT @@ -507,3 +508,38 @@ clear_queue(Proxy, RequestId, MRef) -> end end. +get_ip_family_opts(Host) -> + case inet:parse_address(Host) of + {ok, {_,_,_,_}} -> + [inet]; + {ok, {_,_,_,_,_,_,_,_}} -> + [inet6]; + {error, einval} -> + check_family_for_name(Host, orber_env:ip_version()) + end. + +check_family_for_name(Host, inet) -> + case inet:getaddr(Host, inet) of + {ok, _Address} -> + [inet]; + {error, _} -> + case inet:getaddrs(Host, inet6) of + {ok, _Address} -> + [inet6]; + {error, _} -> + [inet] + end + end; +check_family_for_name(Host, inet6) -> + case inet:getaddr(Host, inet6) of + {ok, _Address} -> + [inet6]; + {error, _} -> + case inet:getaddr(Host, inet) of + {ok, _Address} -> + [inet]; + {error, _} -> + [inet6] + end + end. + diff --git a/lib/orber/src/orber_socket.erl b/lib/orber/src/orber_socket.erl index 07a0e09ccc..c8d2f0636b 100644 --- a/lib/orber/src/orber_socket.erl +++ b/lib/orber/src/orber_socket.erl @@ -205,29 +205,27 @@ listen(normal, Port, Options, Exception) -> MaxSize -> [{packet_size, MaxSize}|Options2] end, - case catch gen_tcp:listen(Port, [binary, {packet,cdr}, {keepalive, Keepalive}, + Options4 = [binary, {packet,cdr}, {keepalive, Keepalive}, {reuseaddr,true}, {backlog, Backlog} | - Options3]) of + Options3], + + case catch gen_tcp:listen(Port, Options4) of {ok, ListenSocket} -> {ok, ListenSocket, check_port(Port, normal, ListenSocket)}; {error, Reason} when Exception == false -> {error, Reason}; {error, eaddrinuse} -> - AllOpts = [binary, {packet,cdr}, - {reuseaddr,true} | Options3], orber:dbg("[~p] orber_socket:listen(normal, ~p, ~p);~n" "Looks like the listen port is already in use.~n" "Check if another Orber is started~n" "on the same node and uses the same listen port (iiop_port). But it may also~n" "be used by any other application; confirm with 'netstat'.", - [?LINE, Port, AllOpts], ?DEBUG_LEVEL), + [?LINE, Port, Options4], ?DEBUG_LEVEL), corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}); Error -> - AllOpts = [binary, {packet,cdr}, - {reuseaddr,true} | Options3], orber:dbg("[~p] orber_socket:listen(normal, ~p, ~p);~n" "Failed with reason: ~p", - [?LINE, Port, AllOpts, Error], ?DEBUG_LEVEL), + [?LINE, Port, Options4, Error], ?DEBUG_LEVEL), corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) end; listen(ssl, Port, Options, Exception) -> @@ -252,26 +250,24 @@ listen(ssl, Port, Options, Exception) -> true -> Options3 end, - case catch ssl:listen(Port, [binary, {packet,cdr}, - {backlog, Backlog} | Options4]) of + Options5 = [binary, {packet,cdr}, {backlog, Backlog} | Options4], + case catch ssl:listen(Port, Options5) of {ok, ListenSocket} -> {ok, ListenSocket, check_port(Port, ssl, ListenSocket)}; {error, Reason} when Exception == false -> {error, Reason}; {error, eaddrinuse} -> - AllOpts = [binary, {packet,cdr} | Options4], orber:dbg("[~p] orber_socket:listen(ssl, ~p, ~p);~n" "Looks like the listen port is already in use. Check if~n" "another Orber is started on the same node and uses the~n" "same listen port (iiop_port). But it may also~n" "be used by any other application; confirm with 'netstat'.", - [?LINE, Port, AllOpts], ?DEBUG_LEVEL), + [?LINE, Port, Options5], ?DEBUG_LEVEL), corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}); Error -> - AllOpts = [binary, {packet,cdr} | Options4], orber:dbg("[~p] orber_socket:listen(ssl, ~p, ~p);~n" "Failed with reason: ~p", - [?LINE, Port, AllOpts, Error], ?DEBUG_LEVEL), + [?LINE, Port, Options5, Error], ?DEBUG_LEVEL), corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) end. @@ -485,16 +481,14 @@ check_port(Port, _, _) -> %%----------------------------------------------------------------- %% Check Options. check_options(normal, Options, _Generation) -> - [orber:ip_version()|Options]; + Options; check_options(ssl, Options, Generation) -> - case orber:ip_version() of - inet when Generation > 2 -> + if + Generation > 2 -> [{ssl_imp, new}|Options]; - inet -> - [{ssl_imp, old}|Options]; - inet6 when Generation > 2 -> - [{ssl_imp, new}, inet6|Options]; - inet6 -> - [{ssl_imp, old}, inet6|Options] + true -> + [{ssl_imp, old}|Options] end. + + diff --git a/lib/orber/test/Makefile b/lib/orber/test/Makefile index 2f8777c773..50be14c24a 100644 --- a/lib/orber/test/Makefile +++ b/lib/orber/test/Makefile @@ -73,7 +73,8 @@ MODULES = \ orber_firewall_ipv6_in_SUITE \ orber_firewall_ipv4_out_SUITE \ orber_firewall_ipv6_out_SUITE \ - orber_nat_SUITE + orber_nat_SUITE \ + ip_v4v6_interop_SUITE GEN_MOD_ORBER = \ oe_orber_test \ diff --git a/lib/orber/test/ip_v4v6_interop_SUITE.erl b/lib/orber/test/ip_v4v6_interop_SUITE.erl new file mode 100644 index 0000000000..5eee5a29c2 --- /dev/null +++ b/lib/orber/test/ip_v4v6_interop_SUITE.erl @@ -0,0 +1,199 @@ +%%---------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-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% +%% +%%---------------------------------------------------------------------- +%% File : ip_v4v6_interop_SUITE.erl +%% Description : +%% +%%---------------------------------------------------------------------- +-module(ip_v4v6_interop_SUITE). + +-compile(export_all). +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + all/0, + init_per_suite/1, + end_per_suite/1, + init_per_testcase/2, + end_per_testcase/2, + groups/0, + init_per_group/2, + end_per_group/2 + ]). +%%----------------------------------------------------------------- +%% Internal exports +%%----------------------------------------------------------------- +-export([]). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include_lib("test_server/include/test_server.hrl"). +-include_lib("orber/include/corba.hrl"). +-include_lib("orber/COSS/CosNaming/CosNaming.hrl"). +-include_lib("orber/src/orber_iiop.hrl"). +-include_lib("orber/src/ifr_objects.hrl"). +-include("idl_output/orber_test_server.hrl"). +-include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl"). +-include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl"). + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- +-define(default_timeout, ?t:minutes(15)). + +-define(match(ExpectedRes,Expr), + fun() -> + AcTuAlReS = (catch (Expr)), + case AcTuAlReS of + ExpectedRes -> + io:format("------ CORRECT RESULT ------~n~p~n", + [AcTuAlReS]), + AcTuAlReS; + _ -> + io:format("###### ERROR ERROR ######~nRESULT: ~p~n", + [AcTuAlReS]), + ?line exit(AcTuAlReS) + end + end()). +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +%%====================================================================== +%% Initialization functions. +%%====================================================================== + +init_per_testcase(_Case, Config) -> + %% Starting dual configured ORB + orber:jump_start([{iiop_port, 10001}, {flags, 16#1000}]), + orber:info(), + Dog=test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + + +end_per_testcase(_Case, Config) -> + orber:jump_stop(), + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +init_per_suite(Config) -> + Config. + +end_per_suite(Config) -> + Config. + +%%==================================================================== +%% SUITE specification +%%==================================================================== +all() -> + [ + dual_ipv4v6 + ]. + +suite() -> [{ct_hooks,[ts_install_cth]}]. + + +groups() -> + []. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +%%==================================================================== +%% Test Cases +%%==================================================================== +dual_ipv4v6(doc) -> + ["ORB configured for supporting both IPv4 and IPv6"]; +dual_ipv4v6(_Config) -> + + %% Starting slave node with ipv4 configured ORB + {ok, Ipv4Node, _Ipv4Host} = + ?match({ok,_,_}, orber_test_lib:js_node([{iiop_port, 4001}])), + Ipv4NS = orber_test_lib:remote_apply(Ipv4Node, corba, resolve_initial_references, ["NameService"]), + + %% Starting slave node with ipv6 configured ORB + {ok, Ipv6Node, _Ipv6Host} = + ?match({ok,_,_}, orber_test_lib:js_node([{iiop_port, 6001}, {flags, 16#0100}])), + Ipv6NS = orber_test_lib:remote_apply(Ipv6Node, corba, resolve_initial_references, ["NameService"]), + + %% Add the ipv6 interface in the dual configured ORB + ?match({ok, _}, orber:add_listen_interface("::1", normal, + [{ip_family, inet6}, {iiop_port, 10002}])), + DualNS = corba:resolve_initial_references("NameService"), + + %% Bind IPv4 NameServer to a name in the dual stack orbs NameServer + NSDual4 = orber_test_lib:remote_apply(Ipv4Node, corba, resolve_initial_references_remote, + ["NameService", ["iiop://127.0.0.1:10001"]]), + ?match(ok, orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', bind, + [NSDual4, lname:new(["ns4"]), Ipv4NS])), + 'CosNaming_NamingContext':resolve(DualNS, lname:new(["ns4"])), + + %% Bind IPv6 NameServer to a name in the dual stack orbs NameServer + NSDual6 = orber_test_lib:remote_apply(Ipv6Node, corba, resolve_initial_references_remote, + ["NameService", ["iiop://[::1]:10002"]]), + ?match(ok, orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', bind, + [NSDual6, lname:new(["ns6"]), Ipv6NS])), + 'CosNaming_NamingContext':resolve(DualNS, lname:new(["ns6"])), + + %% IPv4: Fetch IPv6 NS reference from dual stack orber and register own NameServer in that + Ipv4NSO = orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', resolve, + [NSDual4, lname:new(["ns6"])]), + ?match(ok, orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', bind, + [Ipv4NSO, lname:new(["nso"]), Ipv4NS])), + + %% IPv6: Fetch IPv4 NS reference from dual stack orber and register own NameServer in that + Ipv6NSO = orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', resolve, + [NSDual6, lname:new(["ns4"])]), + ?match(ok, orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', bind, + [Ipv6NSO, lname:new(["nso"]), Ipv6NS])), + + + %% IPv4: Fetch own NS reference from IPv6 NameServer and add a context then check that everything went well + Ipv4NSFromIpv6 = orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', resolve, + [Ipv6NS, lname:new(["nso"])]), + _Ipv4NC = orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', bind_new_context, + [Ipv4NSFromIpv6, lname:new(["test_context4"])]), + + %% IPv6: Fetch own NS reference from IPv4 NameServer and add a context then check that everything went well + Ipv6NSFromIpv4 = orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', resolve, + [Ipv4NS, lname:new(["nso"])]), + _Ipv6NC = orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', bind_new_context, + [Ipv6NSFromIpv4, lname:new(["test_context6"])]), + + %% Check that all the names are register correctly + {ok,DualNames,_} = 'CosNaming_NamingContext':list(DualNS, 100), + {ok,Ipv4Names,_} = orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', list, [Ipv4NS, 100]), + {ok,Ipv6Names,_} = orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', list, [Ipv6NS, 100]), + + io:format("\nNames in Dual NS: ~p\n", [DualNames]), + ?match(2, length(DualNames)), + io:format("\nNames in IPv4 NS: ~p\n", [Ipv4Names]), + ?match(2, length(Ipv4Names)), + io:format("\nNames in IPv6 NS: ~p\n", [Ipv6Names]), + ?match(2, length(Ipv6Names)), + + ok. + diff --git a/lib/orber/test/multi_ORB_SUITE.erl b/lib/orber/test/multi_ORB_SUITE.erl index 41a309ff16..40d8846e0f 100644 --- a/lib/orber/test/multi_ORB_SUITE.erl +++ b/lib/orber/test/multi_ORB_SUITE.erl @@ -582,12 +582,12 @@ proxy_interface_ipv6_api2() -> IOR1 = ?match(#'IOP_IOR'{}, orber_test_lib:remote_apply(ClientNode, corba, string_to_object, - ["corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService"])), + ["corbaloc::1.2@["++IP++"]:"++integer_to_list(ServerPort)++"/NameService"])), ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}}, orber_test_lib:remote_apply(ClientNode, iop_ior, get_key, [IOR1])), IOR2 = ?match(#'IOP_IOR'{}, orber_test_lib:remote_apply(ClientNode, corba, string_to_object, - ["corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService"])), + ["corbaloc::1.2@["++Loopback++"]:"++integer_to_list(ServerPort)++"/NameService"])), ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}}, orber_test_lib:remote_apply(ClientNode, iop_ior, get_key, [IOR2])), ok. diff --git a/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl b/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl index 10827b6ef5..2853949a49 100644 --- a/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl +++ b/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl @@ -188,6 +188,7 @@ allow_port_range_api(_Config) -> ?ORB_ENV_USE_ACL_INCOMING)}, {iiop_acl, [{tcp_in, IP++"/128#5980/6000"}]}])), ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []), + io:format("ServerNode: ~p\nServerHost: ~p\n", [ServerNode, ServerHost]), IOR = ?match({'IOP_IOR',_,_}, corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")), @@ -243,34 +244,34 @@ check_address_api(doc) -> ["Test corbaloc strings"]; check_address_api(suite) -> []; check_address_api(_Config) -> ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]],"NameService"}, - orber_cosnaming_utils:addresses(":0:0:0:0:0:FFFF:C02A:2A2A/NameService")), + orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:C02A:2A2A]/NameService")), ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]],[]}, - orber_cosnaming_utils:addresses(":0:0:0:0:0:FFFF:C02A:2A2A")), + orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:C02A:2A2A]")), ?match({[[iiop,{1,2},"0:0:0:0:0:FFFF:C02A:2A2A",2809]],"NameService"}, - orber_cosnaming_utils:addresses(":1.2@0:0:0:0:0:FFFF:C02A:2A2A/NameService")), + orber_cosnaming_utils:addresses(":1.2@[0:0:0:0:0:FFFF:C02A:2A2A]/NameService")), ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",4001]],"NameService"}, - orber_cosnaming_utils:addresses(":0:0:0:0:0:FFFF:C02A:2A2A:4001/NameService")), + orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]],"NameService"}, - orber_cosnaming_utils:addresses(":1.1@0:0:0:0:0:FFFF:C02A:2A2A:4001/NameService")), + orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]],[]}, - orber_cosnaming_utils:addresses(":1.1@0:0:0:0:0:FFFF:C02A:2A2A:4001")), + orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]],[]}, - orber_cosnaming_utils:addresses("iiop:1.1@0:0:0:0:0:FFFF:C02A:2A2A:4001")), + orber_cosnaming_utils:addresses("iiop:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001")), ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809]],"NameService"}, - orber_cosnaming_utils:addresses(":0:0:0:0:0:FFFF:10.11.11.11/NameService")), + orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11]/NameService")), ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809]],[]}, - orber_cosnaming_utils:addresses(":0:0:0:0:0:FFFF:10.11.11.11")), + orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11]")), ?match({[[iiop,{1,2},"0:0:0:0:0:FFFF:10.11.11.11",2809]],"NameService"}, - orber_cosnaming_utils:addresses(":1.2@0:0:0:0:0:FFFF:10.11.11.11/NameService")), + orber_cosnaming_utils:addresses(":1.2@[0:0:0:0:0:FFFF:10.11.11.11]/NameService")), ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",4001]],"NameService"}, - orber_cosnaming_utils:addresses(":0:0:0:0:0:FFFF:10.11.11.11:4001/NameService")), + orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11]:4001/NameService")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001]],"NameService"}, - orber_cosnaming_utils:addresses(":1.1@0:0:0:0:0:FFFF:10.11.11.11:4001/NameService")), + orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001/NameService")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001]],[]}, - orber_cosnaming_utils:addresses(":1.1@0:0:0:0:0:FFFF:10.11.11.11:4001/")), + orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001/")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001]],[]}, - orber_cosnaming_utils:addresses("iiop:1.1@0:0:0:0:0:FFFF:10.11.11.11:4001/")), + orber_cosnaming_utils:addresses("iiop:1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001/")), ?match({[[iiop,{1,1},"myhost",4001]],[]}, orber_cosnaming_utils:addresses("iiop:1.1@myhost:4001")), @@ -282,31 +283,31 @@ check_address_api(_Config) -> ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001], [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], "NameService"}, - orber_cosnaming_utils:addresses(":1.1@0:0:0:0:0:FFFF:10.11.11.11:4001,:1.1@0:0:0:0:0:FFFF:C02A:2A2A:4001/NameService")), + orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001,:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001], [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], []}, - orber_cosnaming_utils:addresses(":1.1@0:0:0:0:0:FFFF:10.11.11.11:4001,:1.1@0:0:0:0:0:FFFF:C02A:2A2A:4001")), + orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001,:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001")), ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",4001], [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], "NameService"}, - orber_cosnaming_utils:addresses(":0:0:0:0:0:FFFF:10.11.11.11:4001,:1.1@0:0:0:0:0:FFFF:C02A:2A2A:4001/NameService")), + orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11]:4001,:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001], [iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], "NameService"}, - orber_cosnaming_utils:addresses(":1.1@0:0:0:0:0:FFFF:10.11.11.11:4001,:0:0:0:0:0:FFFF:C02A:2A2A:4001/NameService")), + orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001,:[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",2809], [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], "NameService"}, - orber_cosnaming_utils:addresses(":1.1@0:0:0:0:0:FFFF:10.11.11.11,:1.1@0:0:0:0:0:FFFF:C02A:2A2A:4001/NameService")), + orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11],:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")), ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001], [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",2809]], "NameService"}, - orber_cosnaming_utils:addresses(":1.1@0:0:0:0:0:FFFF:10.11.11.11:4001,:1.1@0:0:0:0:0:FFFF:C02A:2A2A/NameService")), + orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001,:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]/NameService")), ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809], [iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]], "NameService"}, - orber_cosnaming_utils:addresses(":0:0:0:0:0:FFFF:10.11.11.11,:0:0:0:0:0:FFFF:C02A:2A2A/NameService")), + orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11],:[0:0:0:0:0:FFFF:C02A:2A2A]/NameService")), ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809], [iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]], []}, - orber_cosnaming_utils:addresses(":0:0:0:0:0:FFFF:10.11.11.11,:0:0:0:0:0:FFFF:C02A:2A2A/")), + orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11],:[0:0:0:0:0:FFFF:C02A:2A2A]/")), ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809], [iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]], []}, - orber_cosnaming_utils:addresses("iiop:0:0:0:0:0:FFFF:10.11.11.11,:0:0:0:0:0:FFFF:C02A:2A2A/")), + orber_cosnaming_utils:addresses("iiop:[0:0:0:0:0:FFFF:10.11.11.11],:[0:0:0:0:0:FFFF:C02A:2A2A]/")), [IP] = ?match([_], orber:host()), {ok, ServerNode, _ServerHost} = @@ -315,7 +316,7 @@ check_address_api(_Config) -> {iiop_acl, [{tcp_in, IP++"/128"}]}])), ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []), ?match({'IOP_IOR',_,_}, - corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")), + corba:string_to_object("corbaloc::1.2@["++IP++"]:"++integer_to_list(ServerPort)++"/NameService")), % ?line catch orber_test_lib:destroy_node(ServerNode, timeout), ok. diff --git a/lib/orber/test/orber_test_lib.erl b/lib/orber/test/orber_test_lib.erl index 6824d25aef..46ed26f210 100644 --- a/lib/orber/test/orber_test_lib.erl +++ b/lib/orber/test/orber_test_lib.erl @@ -166,7 +166,7 @@ get_host(Family) -> {6, _, _} when Family == inet -> "127.0.0.1"; {6, _, _} -> - "0:0:0:0:0:FFFF:7F00:0001"; + "0:0:0:0:0:0:0:0001"; _ -> [IP] = ?match([_], orber:host()), IP @@ -192,16 +192,16 @@ get_loopback_interface(Family) -> {6, _, _} when Family == inet -> "127.0.0.2"; {6, _, _} -> - "0:0:0:0:0:FFFF:7F00:0002"; + "0:0:0:0:0:0:0:0002"; _ when Family == inet -> "127.0.0.1"; _ -> - "0:0:0:0:0:FFFF:7F00:0001" + "0:0:0:0:0:0:0:0001" end; _ when Family == inet -> "127.0.0.1"; _ -> - "0:0:0:0:0:FFFF:7F00:0001" + "0:0:0:0:0:0:0:0001" end. %%------------------------------------------------------------ diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk index 3ea64b1ff6..13bdf55c07 100644 --- a/lib/orber/vsn.mk +++ b/lib/orber/vsn.mk @@ -1,2 +1,2 @@ -ORBER_VSN = 3.6.27 +ORBER_VSN = 3.7 diff --git a/lib/os_mon/doc/src/disksup.xml b/lib/os_mon/doc/src/disksup.xml index dbcfd65095..0e76178edb 100644 --- a/lib/os_mon/doc/src/disksup.xml +++ b/lib/os_mon/doc/src/disksup.xml @@ -73,6 +73,17 @@ much disk can be utilized before the <c>disk_almost_full</c> alarm is set. The default is 0.80 (80%).</p> </item> + <tag><c>disksup_posix_only = bool()</c></tag> + <item> + <p>Specifies whether the <c>disksup</c> helper process should only + use POSIX conformant commands (<c>true</c>) or not. The default is + <c>false</c>. Setting this parameter to <c>true</c> can be + necessary on embedded systems with stripped-down versions + of Unix tools like <c>df</c>. The returned disk data and alarms + can be different when using this option.</p> + <p>The parameter is ignored on platforms that are known to not be + posix compatible (Windows and SunOS).</p> + </item> </taglist> <p>See <seealso marker="kernel:config">config(4)</seealso> for information about how to change the value of configuration diff --git a/lib/os_mon/src/disksup.erl b/lib/os_mon/src/disksup.erl index 278da26a20..af5bcc6fe8 100644 --- a/lib/os_mon/src/disksup.erl +++ b/lib/os_mon/src/disksup.erl @@ -81,10 +81,12 @@ param_type(disk_space_check_interval, Val) when is_integer(Val), param_type(disk_almost_full_threshold, Val) when is_number(Val), 0=<Val, Val=<1 -> true; +param_type(disksup_posix_only, Val) when Val==true; Val==false -> true; param_type(_Param, _Val) -> false. param_default(disk_space_check_interval) -> 30; -param_default(disk_almost_full_threshold) -> 0.80. +param_default(disk_almost_full_threshold) -> 0.80; +param_default(disksup_posix_only) -> false. %%---------------------------------------------------------------------- %% gen_server callbacks @@ -94,7 +96,8 @@ init([]) -> process_flag(trap_exit, true), process_flag(priority, low), - OS = get_os(), + PosixOnly = os_mon:get_env(disksup, disksup_posix_only), + OS = get_os(PosixOnly), Port = case OS of {unix, Flavor} when Flavor==sunos4; Flavor==solaris; @@ -102,6 +105,7 @@ init([]) -> Flavor==dragonfly; Flavor==darwin; Flavor==linux; + Flavor==posix; Flavor==openbsd; Flavor==netbsd; Flavor==irix64; @@ -205,14 +209,16 @@ format_status(_Opt, [_PDict, #state{os = OS, threshold = Threshold, %% Internal functions %%---------------------------------------------------------------------- -get_os() -> +get_os(PosixOnly) -> case os:type() of {unix, sunos} -> - case os:version() of + case os:version() of {5,_,_} -> {unix, solaris}; {4,_,_} -> {unix, sunos4}; V -> exit({unknown_os_version, V}) - end; + end; + {unix, _} when PosixOnly -> + {unix, posix}; {unix, irix64} -> {unix, irix}; OS -> OS @@ -259,6 +265,9 @@ check_disk_space({unix, irix}, Port, Threshold) -> check_disk_space({unix, linux}, Port, Threshold) -> Result = my_cmd("/bin/df -lk", Port), check_disks_solaris(skip_to_eol(Result), Threshold); +check_disk_space({unix, posix}, Port, Threshold) -> + Result = my_cmd("df -k -P", Port), + check_disks_solaris(skip_to_eol(Result), Threshold); check_disk_space({unix, dragonfly}, Port, Threshold) -> Result = my_cmd("/bin/df -k -t ufs,hammer", Port), check_disks_solaris(skip_to_eol(Result), Threshold); diff --git a/lib/os_mon/test/disksup_SUITE.erl b/lib/os_mon/test/disksup_SUITE.erl index 94661cfa77..f9addd96cf 100644 --- a/lib/os_mon/test/disksup_SUITE.erl +++ b/lib/os_mon/test/disksup_SUITE.erl @@ -29,6 +29,7 @@ -export([port/1]). -export([terminate/1, unavailable/1, restart/1]). -export([otp_5910/1]). +-export([posix_only/1]). %% Default timetrap timeout (set in init_per_testcase) -define(default_timeout, ?t:minutes(1)). @@ -48,7 +49,8 @@ init_per_testcase(_Case, Config) -> Dog = ?t:timetrap(?default_timeout), [{watchdog,Dog} | Config]. -end_per_testcase(unavailable, Config) -> +end_per_testcase(TC, Config) when TC =:= unavailable; + TC =:= posix_only -> restart(Config), end_per_testcase(dummy, Config); end_per_testcase(_Case, Config) -> @@ -60,11 +62,10 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> Bugs = [otp_5910], + Always = [api, config, alarm, port, posix_only, unavailable] ++ Bugs, case test_server:os_type() of - {unix, sunos} -> - [api, config, alarm, port, unavailable] ++ Bugs; - {unix, _OSname} -> [api, alarm] ++ Bugs; - {win32, _OSname} -> [api, alarm] ++ Bugs; + {unix, _OSname} -> Always; + {win32, _OSname} -> Always; _OS -> [unavailable] end. @@ -83,12 +84,7 @@ api(doc) -> ["Test of API functions"]; api(Config) when is_list(Config) -> %% get_disk_data() - [{Id,KByte,Capacity}|_] = get_disk_data(), - true = io_lib:printable_list(Id), - true = is_integer(KByte), - true = is_integer(Capacity), - true = Capacity>0, - true = KByte>0, + ok = check_get_disk_data(), %% get_check_interval() 1800000 = disksup:get_check_interval(), @@ -340,6 +336,7 @@ restart(suite) -> []; restart(Config) when is_list(Config) -> ok = application:set_env(os_mon, start_disksup, true), + ok = application:set_env(os_mon, disksup_posix_only, false), {ok, _Pid} = supervisor:restart_child(os_mon_sup, disksup), ok. @@ -405,9 +402,28 @@ otp_5910(Config) when is_list(Config) -> ok = application:start(os_mon), ok. +posix_only(suite) -> []; +posix_only(doc) -> ["Test disksup_posix_only option"]; +posix_only(Config) when is_list(Config) -> + %% Set option and restart disksup + ok = application:set_env(os_mon, disksup_posix_only, true), + ok = supervisor:terminate_child(os_mon_sup, disksup), + {ok, _Child1} = supervisor:restart_child(os_mon_sup, disksup), + + ok = check_get_disk_data(). + dump_info() -> io:format("Status: ~p~n", [sys:get_status(disksup)]). +check_get_disk_data() -> + [{Id,KByte,Capacity}|_] = get_disk_data(), + true = io_lib:printable_list(Id), + true = is_integer(KByte), + true = is_integer(Capacity), + true = Capacity>0, + true = KByte>0, + ok. + % filter get_disk_data and remove entriew with zero capacity % "non-normal" filesystems report zero capacity % - Perhaps errorneous 'df -k -l'? diff --git a/lib/public_key/asn1/OTP-PKIX.asn1 b/lib/public_key/asn1/OTP-PKIX.asn1 index 8d3c76adf5..37196bb9bf 100644 --- a/lib/public_key/asn1/OTP-PKIX.asn1 +++ b/lib/public_key/asn1/OTP-PKIX.asn1 @@ -452,23 +452,23 @@ SupportedPublicKeyAlgorithms PUBLIC-KEY-ALGORITHM-CLASS ::= { ecdsa-with-sha1 SIGNATURE-ALGORITHM-CLASS ::= { ID ecdsa-with-SHA1 - TYPE NULL } -- XXX Must be empty and not NULL + TYPE EcpkParameters } -- XXX Must be empty and not NULL ecdsa-with-sha224 SIGNATURE-ALGORITHM-CLASS ::= { ID ecdsa-with-SHA224 - TYPE NULL } -- XXX Must be empty and not NULL + TYPE EcpkParameters } -- XXX Must be empty and not NULL ecdsa-with-sha256 SIGNATURE-ALGORITHM-CLASS ::= { ID ecdsa-with-SHA256 - TYPE NULL } -- XXX Must be empty and not NULL + TYPE EcpkParameters } -- XXX Must be empty and not NULL ecdsa-with-sha384 SIGNATURE-ALGORITHM-CLASS ::= { ID ecdsa-with-SHA384 - TYPE NULL } -- XXX Must be empty and not NULL + TYPE EcpkParameters } -- XXX Must be empty and not NULL ecdsa-with-sha512 SIGNATURE-ALGORITHM-CLASS ::= { ID ecdsa-with-SHA512 - TYPE NULL } -- XXX Must be empty and not NULL + TYPE EcpkParameters } -- XXX Must be empty and not NULL FIELD-ID-CLASS ::= CLASS { &id OBJECT IDENTIFIER UNIQUE, diff --git a/lib/public_key/doc/src/cert_records.xml b/lib/public_key/doc/src/cert_records.xml index 397c13b463..d1293d12b8 100644 --- a/lib/public_key/doc/src/cert_records.xml +++ b/lib/public_key/doc/src/cert_records.xml @@ -36,8 +36,9 @@ <p>This chapter briefly describes erlang records derived from ASN1 specifications used to handle <c> X509 certificates</c> and <c>CertificationRequest</c>. - The intent is to describe the data types and not to specify the meaning of each - component for this we refer you to <url + The intent is to describe the data types +and not to specify the semantics of each component. For information on the +semantics, please see <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280</url> and <url href="http://www.ietf.org/rfc/rfc5967.txt">PKCS-10</url>. </p> diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 8e93f562d4..f8011cd5c0 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -75,7 +75,7 @@ <p><em>Data Types </em></p> - <p><code>oid() - a tuple of integers as generated by the ASN1 compiler.</code></p> + <p><code>oid() - Object Identifier, a tuple of integers as generated by the ASN1 compiler.</code></p> <p><code>boolean() = true | false</code></p> diff --git a/lib/public_key/doc/src/public_key_records.xml b/lib/public_key/doc/src/public_key_records.xml index 13bb996f7f..d3534846fa 100644 --- a/lib/public_key/doc/src/public_key_records.xml +++ b/lib/public_key/doc/src/public_key_records.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2008</year> - <year>2013</year> + <year>2014</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -35,17 +35,27 @@ </header> <p>This chapter briefly describes Erlang records derived from ASN1 - specifications used to handle public and private keys. The intent - is to describe the data types and not to specify the meaning of - each component for this we refer you to the relevant standards and RFCs.</p> + specifications used to handle public and private keys. + The intent is to describe the data types + and not to specify the semantics of each component. For information on the + semantics, please see the relevant standards and RFCs.</p> <p>Use the following include directive to get access to the - records and constant macros used in the following sections.</p> + records and constant macros described in the following sections.</p> <code> -include_lib("public_key/include/public_key.hrl"). </code> + <section> + <title>Common Data Types</title> + + <p>Common non-standard Erlang + data types used to described the record fields in the + below sections are defined in <seealso + marker="public_key">public key reference manual </seealso></p> + </section> + <section> - <title>RSA as defined by the PKCS-1 standard and RFC 3447.</title> + <title>RSA as defined by the PKCS-1 standard and <url href="http://www.ietf.org/rfc/rfc3447.txt"> RFC 3447 </url></title> <code> #'RSAPublicKey'{ @@ -76,7 +86,8 @@ </section> <section> - <title>DSA as defined by Digital Signature Standard (NIST FIPS PUB 186-2) + <title>DSA as defined by + <url href="http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf"> Digital Signature Standard (NIST FIPS PUB 186-2) </url> </title> <code> @@ -96,4 +107,47 @@ }. </code> </section> + + <section> + <title>ECC (Elliptic Curve) <url href="http://www.ietf.org/rfc/rfc3447.txt"> RFC 5480 </url> + </title> + + <code> +#'ECPrivateKey'{ + version, % integer() + privateKey, % octet_string() + parameters, % der_encoded() - {'EcpkParameters', #'ECParameters'{}} | + {'EcpkParameters', {namedCurve, oid()}} | + {'EcpkParameters', 'NULL'} % Inherited by CA + publicKey % bitstring() + }. + +#'ECParameters'{ + version, % integer() + fieldID, % #'FieldID'{} + curve, % #'Curve'{} + base, % octet_string() + order, % integer() + cofactor % integer() + }. + +#'Curve'{ + a, % octet_string() + b, % octet_string() + seed % bitstring() - optional + + }. + +#'FieldID'{ + fieldType, % oid() + parameters % Depending on fieldType + }. + +#'ECPoint'{ + point % octet_string() - the public key + }. + + </code> + </section> + </chapter> diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl index 3a1653d989..bee57a223d 100644 --- a/lib/public_key/src/pubkey_pem.erl +++ b/lib/public_key/src/pubkey_pem.erl @@ -203,7 +203,7 @@ pem_start('ContentInfo') -> <<"-----BEGIN PKCS7-----">>; pem_start('CertificateList') -> <<"-----BEGIN X509 CRL-----">>; -pem_start('OTPEcpkParameters') -> +pem_start('EcpkParameters') -> <<"-----BEGIN EC PARAMETERS-----">>; pem_start('ECPrivateKey') -> <<"-----BEGIN EC PRIVATE KEY-----">>. @@ -260,7 +260,7 @@ asn1_type(<<"-----BEGIN PKCS7-----">>) -> asn1_type(<<"-----BEGIN X509 CRL-----">>) -> 'CertificateList'; asn1_type(<<"-----BEGIN EC PARAMETERS-----">>) -> - 'OTPEcpkParameters'; + 'EcpkParameters'; asn1_type(<<"-----BEGIN EC PRIVATE KEY-----">>) -> 'ECPrivateKey'. diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml index 969af2d745..18b36ff953 100644 --- a/lib/reltool/doc/src/notes.xml +++ b/lib/reltool/doc/src/notes.xml @@ -37,7 +37,23 @@ thus constitutes one section in this document. The title of each section is the version number of Reltool.</p> - <section><title>Reltool 0.6.5</title> + <section><title>Reltool 0.6.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a minor typo in an error message from + reltool_server.</p> + <p> + Own Id: OTP-11977</p> + </item> + </list> + </section> + +</section> + +<section><title>Reltool 0.6.5</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index 98eeed5c27..e7af4bd3f7 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2013. All Rights Reserved. +%% Copyright Ericsson AB 2009-2014. 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 @@ -2030,7 +2030,7 @@ ensure_app_info(#app{name = Name, [BadVsn | _] -> reltool_utils:throw_error( "~w: Application version clash. " - "Multiple directories contains version ~tp.", + "Multiple directories contain version ~tp.", [Name,BadVsn]) end, FirstInfo = hd(AllInfo), diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk index 163b77dfa0..4fc1534250 100644 --- a/lib/reltool/vsn.mk +++ b/lib/reltool/vsn.mk @@ -1 +1 @@ -RELTOOL_VSN = 0.6.5 +RELTOOL_VSN = 0.6.6 diff --git a/lib/sasl/doc/src/alarm_handler.xml b/lib/sasl/doc/src/alarm_handler.xml index ab3041137e..e4def7c7f5 100644 --- a/lib/sasl/doc/src/alarm_handler.xml +++ b/lib/sasl/doc/src/alarm_handler.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1996</year> - <year>2013</year> + <year>2014</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -87,7 +87,9 @@ <v>AlarmId = term()</v> </type> <desc> - <p>Clears all alarms with id <c>AlarmId</c>. + <p>Sends the <c>clear_alarm</c> event to all event handlers.</p> + <p>When receiving this event, the default simple handler + clears the latest received alarm with id <c>AlarmId</c>. </p> </desc> </func> @@ -109,8 +111,10 @@ <v>AlarmDescription = term()</v> </type> <desc> - <p>Sets an alarm with id <c>AlarmId</c>. This id is used at a - later stage when the alarm is cleared. + <p>Sends the <c>set_alarm</c> event to all event handlers.</p> + <p>When receiving this event, the default simple handler + stores the alarm. The <c>AlarmId</c> identifies the alarm + and is used when the alarm is cleared. </p> </desc> </func> diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src index e789853eea..af04d007ac 100644 --- a/lib/sasl/src/sasl.appup.src +++ b/lib/sasl/src/sasl.appup.src @@ -17,9 +17,7 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 - {<<"2\\.3(\\.[0-9]+)*">>,[restart_new_emulator]}], %% R16 + [{<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 %% Down to - max one major revision back - [{<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 - {<<"2\\.3(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R16 + [{<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 }. diff --git a/lib/sasl/test/test_lib.hrl b/lib/sasl/test/test_lib.hrl index c8a4e92f24..b16c4ac34c 100644 --- a/lib/sasl/test/test_lib.hrl +++ b/lib/sasl/test/test_lib.hrl @@ -1,3 +1,3 @@ -define(ertsvsn,"4.4"). --define(kernelvsn,"2.16.4"). --define(stdlibvsn,"1.19.4"). +-define(kernelvsn,"3.0"). +-define(stdlibvsn,"2.0"). diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 06674095f2..15efd47a1c 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -33,7 +33,29 @@ </header> - <section><title>SNMP 4.25.1</title> + <section><title>SNMP 5.0</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + SNMP has been improved to handle IPv6. The agent can + handle dual stack IPv4 + IPv6, but not yet the manager. + The documentation also still lags behind... If you do + such advanced stuff like writing a custom net_if module, + the interface for it has changed, but other than that + SNMP is backwards compatible.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-12020 Aux Id: OTP-11518 </p> + </item> + </list> + </section> + +</section> + +<section><title>SNMP 4.25.1</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/snmp/src/agent/snmp_community_mib.erl b/lib/snmp/src/agent/snmp_community_mib.erl index 7bdd500727..4546c343b7 100644 --- a/lib/snmp/src/agent/snmp_community_mib.erl +++ b/lib/snmp/src/agent/snmp_community_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2012. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -31,6 +31,7 @@ -include("snmpa_internal.hrl"). -include("SNMP-COMMUNITY-MIB.hrl"). -include("SNMP-TARGET-MIB.hrl"). +-include("SNMPv2-TM.hrl"). -include("SNMPv2-TC.hrl"). -include("snmp_types.hrl"). @@ -129,10 +130,11 @@ read_community_config_files(Dir) -> [FileName, D, Reason]), ok end, - Filter = fun(Comms) -> Comms end, - Check = fun(Entry) -> check_community(Entry) end, + Order = fun snmp_conf:no_order/2, + Filter = fun snmp_conf:no_filter/1, + Check = fun(Entry, State) -> {check_community(Entry), State} end, [Comms] = - snmp_conf:read_files(Dir, [{Gen, Filter, Check, "community.conf"}]), + snmp_conf:read_files(Dir, [{FileName, Gen, Order, Check, Filter}]), Comms. check_community({Index, CommunityName, SecName, CtxName, TransportTag}) -> @@ -192,7 +194,7 @@ add_community(Idx, CommName, SecName, EngineId, CtxName, TransportTag) -> do_add_community(Community). do_add_community(Community) -> - case (catch check_community(Community)) of + try check_community(Community) of {ok, Row} -> Key = element(1, Row), case table_cre_row(snmpCommunityTable, Key, Row) of @@ -201,11 +203,12 @@ do_add_community(Community) -> {ok, Key}; false -> {error, create_failed} - end; + end + catch {error, Reason} -> {error, Reason}; - Error -> - {error, Error} + Class:Reason -> + {error, {Class, Reason, erlang:get_stacktrace()}} end. %% FIXME: does not work with mnesia @@ -243,6 +246,10 @@ gc_tabs() -> %%----------------------------------------------------------------- community2vacm(Community, Addr) -> Idxs = ets:lookup(snmp_community_cache, Community), + ?vtrace("community2vacm ->~n" + " Community: ~p~n" + " Addr: ~p~n" + " Idxs: ~p", [Community, Addr, Idxs]), loop_c2v_rows(lists:keysort(2, Idxs), Addr). loop_c2v_rows([{_, CommunityIndex} | T], Addr) -> @@ -250,6 +257,9 @@ loop_c2v_rows([{_, CommunityIndex} | T], Addr) -> "~n CommunityIndex: ~p", [CommunityIndex]), case get_row(CommunityIndex) of {_Community, VacmParams, Tag} -> + ?vtrace("loop_c2v_rows ->~n" + " VacmParams: ~p~n" + " Tag: ~p", [VacmParams, Tag]), {TDomain, TAddr} = Addr, case snmp_target_mib:is_valid_tag(Tag, TDomain, TAddr) of true -> @@ -506,7 +516,12 @@ snmpTargetAddrExtTable(get_next, RowIndex, Cols) -> NCols = conv1(Cols), conv2(next(snmpTargetAddrExtTable, RowIndex, NCols)); snmpTargetAddrExtTable(set, RowIndex, Cols0) -> - case (catch verify_snmpTargetAddrExtTable_cols(Cols0, [])) of + case + (catch verify_snmpTargetAddrExtTable_cols( + Cols0, + get_snmpTargetAddrTDomain(RowIndex, Cols0), + [])) + of {ok, Cols} -> NCols = conv3(Cols), snmp_generic:table_func(set, RowIndex, NCols, @@ -515,7 +530,11 @@ snmpTargetAddrExtTable(set, RowIndex, Cols0) -> Error end; snmpTargetAddrExtTable(is_set_ok, RowIndex, Cols0) -> - case (catch verify_snmpTargetAddrExtTable_cols(Cols0, [])) of + case (catch verify_snmpTargetAddrExtTable_cols( + Cols0, + get_snmpTargetAddrTDomain(RowIndex, Cols0), + [])) + of {ok, Cols} -> NCols = conv3(Cols), snmp_generic:table_func(is_set_ok, RowIndex, NCols, @@ -525,29 +544,49 @@ snmpTargetAddrExtTable(is_set_ok, RowIndex, Cols0) -> end. -verify_snmpTargetAddrExtTable_cols([], Cols) -> + +get_snmpTargetAddrTDomain(RowIndex, Col) -> + case + get( + snmpTargetAddrTable, RowIndex, + [?snmpTargetAddrRowStatus,?snmpTargetAddrTDomain]) + of + [{value,?snmpTargetAddrRowStatus_active},ValueTDomain] -> + case ValueTDomain of + {value,TDomain} -> + TDomain; + _ -> + ?snmpUDPDomain + end; + _ -> + wrongValue(Col) + end. + + + +verify_snmpTargetAddrExtTable_cols([], _TDomain, Cols) -> {ok, lists:reverse(Cols)}; -verify_snmpTargetAddrExtTable_cols([{Col, Val0}|Cols], Acc) -> - Val = verify_snmpTargetAddrExtTable_col(Col, Val0), - verify_snmpTargetAddrExtTable_cols(Cols, [{Col, Val}|Acc]). +verify_snmpTargetAddrExtTable_cols([{Col, Val0}|Cols], TDomain, Acc) -> + Val = verify_snmpTargetAddrExtTable_col(Col, TDomain, Val0), + verify_snmpTargetAddrExtTable_cols(Cols, TDomain, [{Col, Val}|Acc]). -verify_snmpTargetAddrExtTable_col(?snmpTargetAddrTMask, []) -> +verify_snmpTargetAddrExtTable_col(?snmpTargetAddrTMask, _TDomain, []) -> []; -verify_snmpTargetAddrExtTable_col(?snmpTargetAddrTMask, TMask) -> - case (catch snmp_conf:check_taddress(TMask)) of +verify_snmpTargetAddrExtTable_col(?snmpTargetAddrTMask, TDomain, TMask) -> + case (catch snmp_conf:check_taddress(TDomain, TMask)) of ok -> TMask; _ -> wrongValue(?snmpTargetAddrTMask) end; -verify_snmpTargetAddrExtTable_col(?snmpTargetAddrMMS, MMS) -> +verify_snmpTargetAddrExtTable_col(?snmpTargetAddrMMS, _TDomain, MMS) -> case (catch snmp_conf:check_packet_size(MMS)) of ok -> MMS; _ -> wrongValue(?snmpTargetAddrMMS) end; -verify_snmpTargetAddrExtTable_col(_, Val) -> +verify_snmpTargetAddrExtTable_col(_, _TDomain, Val) -> Val. db(snmpTargetAddrExtTable) -> db(snmpTargetAddrTable); @@ -583,6 +622,7 @@ conv3([{Idx, Val}|T]) -> [{Idx+10, Val} | conv3(T)]; conv3([]) -> []. + get(Name, RowIndex, Cols) -> snmp_generic:handle_table_get(db(Name), RowIndex, Cols, foi(Name)). diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl index cc191bd956..9d3f7ef5e7 100644 --- a/lib/snmp/src/agent/snmp_framework_mib.erl +++ b/lib/snmp/src/agent/snmp_framework_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2012. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -41,6 +41,7 @@ -compile({no_auto_import,[error/1]}). -export([init/0, configure/1]). -export([intContextTable/1, intContextTable/3, + intAgentTransportDomain/1, intAgentTransports/1, intAgentUDPPort/1, intAgentIpAddress/1, snmpEngineID/1, snmpEngineBoots/1, @@ -51,7 +52,7 @@ set_engine_boots/1, set_engine_time/1, table_next/2, check_status/3]). -export([add_context/1, delete_context/1]). --export([check_agent/1, check_context/1]). +-export([check_agent/2, check_context/1, order_agent/2]). %%----------------------------------------------------------------- @@ -115,54 +116,46 @@ do_configure(Dir) -> read_internal_config_files(Dir) -> ?vdebug("read context config file",[]), - Gen = fun(D, Reason) -> - convert_context(D, Reason) - end, - Filter = fun(Contexts) -> Contexts end, - Check = fun(Entry) -> check_context(Entry) end, - [Ctxs] = snmp_conf:read_files(Dir, [{Gen, Filter, Check, "context.conf"}]), + Gen = fun gen_context/2, + Order = fun snmp_conf:no_order/2, + Filter = fun snmp_conf:no_filter/1, + Check = fun(Entry, State) -> {check_context(Entry), State} end, + [Ctxs] = + snmp_conf:read_files + (Dir, [{"context.conf", Gen, Order, Check, Filter}]), Ctxs. - read_agent(Dir) -> ?vdebug("read agent config file", []), - FileName = "agent.conf", - Check = fun(Entry) -> check_agent(Entry) end, + FileName = "agent.conf", File = filename:join(Dir, FileName), - Agent = + Conf0 = try - snmp_conf:read(File, Check) + snmp_conf:read(File, fun order_agent/2, fun check_agent/2) catch throw:{error, Reason} -> error({failed_reading_config_file, Dir, FileName, Reason}) end, - sort_agent(Agent). - - -%%----------------------------------------------------------------- -%% Make sure that each mandatory agent attribute is present, and -%% provide default values for the other non-present attributes. -%%----------------------------------------------------------------- -sort_agent(L) -> - Mand = [{intAgentIpAddress, mandatory}, - {intAgentUDPPort, mandatory}, - {snmpEngineMaxMessageSize, mandatory}, - {snmpEngineID, mandatory}], - {ok, L2} = snmp_conf:check_mandatory(L, Mand), - lists:keysort(1, L2). + Mand = + [{intAgentTransports, mandatory}, + {snmpEngineMaxMessageSize, mandatory}, + {snmpEngineID, mandatory}], + {ok, Conf} = snmp_conf:check_mandatory(Conf0, Mand), + Conf. %%----------------------------------------------------------------- %% Generate a context.conf file. %%----------------------------------------------------------------- -convert_context(Dir, _Reason) -> +gen_context(Dir, _Reason) -> config_err("missing context.conf file => generating a default file", []), File = filename:join(Dir, "context.conf"), case file:open(File, [write]) of {ok, Fid} -> ok = io:format(Fid, "~s\n", [context_header()]), ok = io:format(Fid, "%% The default context\n\"\".\n", []), - file:close(Fid); + file:close(Fid), + []; {error, Reason} -> file:delete(File), error({failed_creating_file, File, Reason}) @@ -196,10 +189,44 @@ check_context(Context) -> %% Agent %% {Name, Value}. %%----------------------------------------------------------------- -check_agent({intAgentIpAddress, Value}) -> - snmp_conf:check_ip(Value); -check_agent({intAgentUDPPort, Value}) -> - snmp_conf:check_integer(Value); +check_agent(Entry, undefined) -> + check_agent(Entry, {snmp_target_mib:default_domain(), undefined}); +check_agent({intAgentTransportDomain, Domain}, {_, Port}) -> + {snmp_conf:check_domain(Domain), {Domain, Port}}; +check_agent({intAgentUDPPort, Port}, {Domain, _}) -> + ok = snmp_conf:check_port(Port), + {ok, {Domain, Port}}; +check_agent({intAgentIpAddress, _}, {_, undefined}) -> + error({missing_mandatory, intAgentUDPPort}); +check_agent({intAgentIpAddress = Tag, Ip} = Entry, {Domain, Port} = State) -> + {case snmp_conf:check_ip(Domain, Ip) of + ok -> + [Entry, + {intAgentTransports, [{Domain, {Ip, Port}}]}]; + {ok, FixedIp} -> + [{Tag, FixedIp}, + {intAgentTransports, [{Domain, {FixedIp, Port}}]}] + end, State}; +check_agent({intAgentTransports = Tag, Transports}, {_, Port} = State) -> + CheckedTransports = + [case + case Port of + undefined -> + snmp_conf:check_address(Domain, Address); + _ -> + snmp_conf:check_address(Domain, Address, Port) + end + of + ok -> + Transport; + {ok, FixedAddress} -> + {Domain, FixedAddress} + end + || {Domain, Address} = Transport <- Transports], + {{ok, {Tag, CheckedTransports}}, State}; +check_agent(Entry, State) -> + {check_agent(Entry), State}. + %% This one is kept for backwards compatibility check_agent({intAgentMaxPacketSize, Value}) -> snmp_conf:check_packet_size(Value); @@ -210,6 +237,14 @@ check_agent({snmpEngineID, Value}) -> check_agent(X) -> error({invalid_agent_attribute, X}). +%% Ordering function to sort intAgentTransportDomain first +%% hence before intAgentIpAddress. Sort other entries on the key. +order_agent(EntryA, EntryB) -> + snmp_conf:keyorder( + 1, EntryA, EntryB, + [intAgentTransportDomain, intAgentUDPPort | sort]). + + maybe_create_table(Name) -> case snmpa_local_db:table_exists(db(Name)) of @@ -382,6 +417,14 @@ intAgentUDPPort(Op) -> intAgentIpAddress(Op) -> snmp_generic:variable_func(Op, db(intAgentIpAddress)). +intAgentTransportDomain(Op) -> + snmp_generic:variable_func(Op, db(intAgentTransportDomain)). + +intAgentTransports(Op) -> + snmp_generic:variable_func(Op, db(intAgentTransports)). + + + snmpEngineID(print) -> VarAndValue = [{snmpEngineID, snmpEngineID(get)}], snmpa_mib_lib:print_variables(VarAndValue); diff --git a/lib/snmp/src/agent/snmp_generic.erl b/lib/snmp/src/agent/snmp_generic.erl index 06afa68d96..3195ca2500 100644 --- a/lib/snmp/src/agent/snmp_generic.erl +++ b/lib/snmp/src/agent/snmp_generic.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -414,7 +414,12 @@ table_check_status(NameDb, Col, ?'RowStatus_createAndGo', RowIndex, Cols) -> % side effect free and we only use the result temporary. case catch snmpa_local_db:table_construct_row( NameDb, RowIndex, ?'RowStatus_createAndGo', Cols) of - {'EXIT', _} -> + {'EXIT', _Reason} -> + ?vtrace( + "failed construct row (createAndGo): " + " n Reason: ~p" + " n Stack: ~p", + [_Reason, erlang:get_stacktrace()]), {noCreation, Col}; % Bad RowIndex Row -> case lists:member(noinit, tuple_to_list(Row)) of @@ -431,7 +436,12 @@ table_check_status(NameDb, Col, ?'RowStatus_createAndWait', RowIndex, Cols) -> false -> case catch snmpa_local_db:table_construct_row( NameDb, RowIndex, ?'RowStatus_createAndGo', Cols) of - {'EXIT', _} -> + {'EXIT', _Reason} -> + ?vtrace( + "failed construct row (createAndWait): " + " n Reason: ~p" + " n Stack: ~p", + [_Reason, erlang:get_stacktrace()]), {noCreation, Col}; % Bad RowIndex _Row -> {noError, 0} @@ -711,7 +721,19 @@ find_col(Col, [_H | T]) -> find_col(Col, T). try_apply(nofunc, _) -> {noError, 0}; -try_apply(F, Args) -> apply(F, Args). +try_apply(F, Args) -> maybe_verbose_apply(F, Args). + +maybe_verbose_apply(M, Args) -> + case get(verbosity) of + false -> + apply(M, Args); + _ -> + ?vlog("~n apply: ~w,~p~n", [M,Args]), + Res = apply(M,Args), + ?vlog("~n returned: ~p", [Res]), + Res + end. + table_info({Name, _Db}) -> case snmpa_symbolic_store:table_info(Name) of diff --git a/lib/snmp/src/agent/snmp_notification_mib.erl b/lib/snmp/src/agent/snmp_notification_mib.erl index 37e09f5d3e..31c7735226 100644 --- a/lib/snmp/src/agent/snmp_notification_mib.erl +++ b/lib/snmp/src/agent/snmp_notification_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2012. All Rights Reserved. +%% Copyright Ericsson AB 1998-2014. 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 @@ -106,17 +106,19 @@ do_reconfigure(Dir) -> read_notify_config_files(Dir) -> ?vdebug("read notify config file",[]), FileName = "notify.conf", - Gen = fun(D, Reason) -> - info_msg("failed reading config file ~s" - "~n Config Dir: ~s" - "~n Reason: ~p", - [FileName, D, Reason]), - ok - end, - Filter = fun(Notifs) -> Notifs end, - Check = fun(Entry) -> check_notify(Entry) end, + Gen = + fun (D, Reason) -> + info_msg("failed reading config file ~s" + "~n Config Dir: ~s" + "~n Reason: ~p", + [FileName, D, Reason]), + ok + end, + Order = fun snmp_conf:no_order/2, + Filter = fun snmp_conf:no_filter/1, + Check = fun (Entry, State) -> {check_notify(Entry), State} end, [Notifs] = - snmp_conf:read_files(Dir, [{Gen, Filter, Check, "notify.conf"}]), + snmp_conf:read_files(Dir, [{FileName, Gen, Order, Check, Filter}]), Notifs. check_notify({Name, Tag, Type}) -> diff --git a/lib/snmp/src/agent/snmp_standard_mib.erl b/lib/snmp/src/agent/snmp_standard_mib.erl index 766b75022b..aace3fd413 100644 --- a/lib/snmp/src/agent/snmp_standard_mib.erl +++ b/lib/snmp/src/agent/snmp_standard_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -152,16 +152,19 @@ do_reconfigure(Dir) -> %%----------------------------------------------------------------- read_standard(Dir) -> ?vdebug("check standard config file",[]), - FileName = "standard.conf", - Gen = fun(D, Reason) -> - throw({error, {failed_reading_config_file, - D, FileName, - list_dir(Dir), Reason}}) - end, - Filter = fun(Standard) -> sort_standard(Standard) end, - Check = fun(Entry) -> check_standard(Entry) end, + FileName = "standard.conf", + Gen = + fun (D, Reason) -> + throw( + {error, + {failed_reading_config_file, + D, FileName, list_dir(Dir), Reason}}) + end, + Order = fun snmp_conf:no_order/2, + Check = fun (Entry, State) -> {check_standard(Entry), State} end, + Filter = fun sort_standard/1, [Standard] = - snmp_conf:read_files(Dir, [{Gen, Filter, Check, FileName}]), + snmp_conf:read_files(Dir, [{FileName, Gen, Order, Check, Filter}]), Standard. list_dir(Dir) -> diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl index b01d536caa..e916f17d6a 100644 --- a/lib/snmp/src/agent/snmp_target_mib.erl +++ b/lib/snmp/src/agent/snmp_target_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2012. All Rights Reserved. +%% Copyright Ericsson AB 1998-2014. 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 @@ -133,18 +133,22 @@ do_reconfigure(Dir) -> read_target_config_files(Dir) -> ?vdebug("check target address and parameter config file(s)",[]), - TAGen = fun(_D, _Reason) -> ok end, - TAFilter = fun(Addr) -> Addr end, - TACheck = fun(Entry) -> check_target_addr(Entry) end, - TPGen = fun(_D, _Reason) -> ok end, - TPFilter = fun(Params) -> Params end, - TPCheck = fun(Entry) -> check_target_params(Entry) end, + TAName = "target_addr.conf", + TACheck = fun (Entry, State) -> {check_target_addr(Entry), State} end, + + TPName = "target_params.conf", + TPCheck = fun (Entry, State) -> {check_target_params(Entry), State} end, + + NoGen = fun snmp_conf:no_gen/2, + NoOrder = fun snmp_conf:no_order/2, + NoFilter = fun snmp_conf:no_filter/1, [Addrs, Params] = - snmp_conf:read_files(Dir, - [{TAGen, TAFilter, TACheck, "target_addr.conf"}, - {TPGen, TPFilter, TPCheck, "target_params.conf"}]), + snmp_conf:read_files( + Dir, + [{TAName, NoGen, NoOrder, TACheck, NoFilter}, + {TPName, NoGen, NoOrder, TPCheck, NoFilter}]), {Addrs, Params}. @@ -154,79 +158,154 @@ read_target_config_files(Dir) -> %% TMask, MMS} %%----------------------------------------------------------------- -check_target_addr({Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, - Params, EngineId, TMask, MMS}) -> +check_target_addr( + {Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS}) -> % Arity 11 + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS); +check_target_addr( + {Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS}) % Arity 10 + when is_atom(Domain) -> + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS); +check_target_addr( + {Name, Ip, Udp, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS}) + when is_integer(Udp) -> % Arity 10 + Domain = default_domain(), + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS); +check_target_addr( + {Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId}) % Arity 8 + when is_atom(Domain) -> + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId); +check_target_addr( + {Name, Ip, Udp, Timeout, RetryCount, TagList, Params, + EngineId}) % Arity 8 + when is_integer(Udp) -> + Domain = default_domain(), + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId); +%% Use dummy engine id if the old style is found +check_target_addr( + {Name, Domain, Address, Timeout, RetryCount, TagList, Params}) % Arity 7 + when is_atom(Domain) -> + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params); +check_target_addr( + {Name, Ip, Udp, Timeout, RetryCount, TagList, Params}) % Arity 7 + when is_integer(Udp) -> + Domain = default_domain(), + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params); +%% Use dummy engine id if the old style is found +check_target_addr( + {Name, Domain, Address, Timeout, RetryCount, TagList, Params, + TMask, MMS}) % Arity 9 + when is_atom(Domain) -> + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, TMask, MMS); +check_target_addr( + {Name, Ip, Udp, Timeout, RetryCount, TagList, Params, + TMask, MMS}) % Arity 9 + when is_integer(Udp) -> + Domain = default_domain(), + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, TMask, MMS); +check_target_addr(X) -> + error({invalid_target_addr, X}). + +check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params) -> % Arity 7 + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + "dummy"). +%% +check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId) -> % Arity 8 + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, [], 2048). +%% +check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + TMask, MMS) -> % Arity 9 + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + "dummy", TMask, MMS). +%% +check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, Mask, MMS) -> % Arity 10 ?vtrace("check target address with:" "~n Name: ~s" "~n Domain: ~p" - "~n Ip: ~p" - "~n Udp: ~p" + "~n Address: ~p" "~n Timeout: ~p" "~n RetryCount: ~p" "~n TagList: ~p" "~n Params: ~p" "~n EngineId: ~p" - "~n TMask: ~p" + "~n Mask: ~p" "~n MMS: ~p", - [Name, - Domain, Ip, Udp, + [Name, Domain, Address, Timeout, RetryCount, - TagList, Params, EngineId, TMask, MMS]), + TagList, Params, EngineId, Mask, MMS]), snmp_conf:check_string(Name,{gt,0}), snmp_conf:check_domain(Domain), - snmp_conf:check_ip(Domain, Ip), - snmp_conf:check_integer(Udp, {gt, 0}), + NAddress = check_address(Domain, Address), snmp_conf:check_integer(Timeout, {gte, 0}), snmp_conf:check_integer(RetryCount, {gte,0}), snmp_conf:check_string(TagList), snmp_conf:check_string(Params), check_engine_id(EngineId), - TAddress = snmp_conf:mk_taddress(Domain, Ip, Udp), + NMask = check_mask(Domain, Mask), TDomain = snmp_conf:mk_tdomain(Domain), - check_tmask(TDomain, TMask, TAddress), + TAddress = snmp_conf:mk_taddress(Domain, NAddress), + TMask = snmp_conf:mk_taddress(Domain, NMask), snmp_conf:check_packet_size(MMS), ?vtrace("check target address done",[]), Addr = {Name, TDomain, TAddress, Timeout, RetryCount, TagList, Params, ?'StorageType_nonVolatile', ?'RowStatus_active', EngineId, TMask, MMS}, % Values for Augmenting table in SNMP-COMMUNITY-MIB - {ok, Addr}; -check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, - Params, EngineId, TMask, MMS}) -> - Domain = default_domain(), - check_target_addr({Name, - Domain, Ip, Udp, - Timeout, RetryCount, TagList, - Params, EngineId, TMask, MMS}); -check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, Params, - EngineId}) -> - check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, - Params, EngineId, [], 2048}); -%% Use dummy engine id if the old style is found -check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, Params}) -> - check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, - Params, "dummy", [], 2048}); -%% Use dummy engine id if the old style is found -check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, Params, - TMask, MMS}) -> - check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, - Params, "dummy", TMask, MMS}); -check_target_addr(X) -> - error({invalid_target_addr, X}). - + {ok, Addr}. check_engine_id(discovery) -> ok; check_engine_id(EngineId) -> snmp_conf:check_string(EngineId). +check_address(Domain, Address) -> + case snmp_conf:check_address(Domain, Address) of + ok -> + Address; + {ok, NAddress} -> + NAddress + end. -check_tmask(_TDomain, [], _TAddress) -> - ok; -check_tmask(TDomain, TMask, TAddress) when length(TMask) =:= length(TAddress) -> - snmp_conf:check_taddress(TDomain, TMask); -check_tmask(_TDomain, TMask, _TAddr) -> - throw({error, {invalid_tmask, TMask}}). +check_mask(_Domain, [] = Mask) -> + Mask; +check_mask(Domain, Mask) -> + try check_address(Domain, Mask) + catch + {error, {bad_address, Info}} -> + error({bad_mask, Info}) + end. %%----------------------------------------------------------------- @@ -604,6 +683,20 @@ snmpTargetAddrTable(print) -> FOI = foi(Table), PrintRow = fun(Prefix, Row) -> + TDomain = element(?snmpTargetAddrTDomain, Row), + Domain = + try snmp_conf:tdomain_to_domain(TDomain) + catch + {error, {bad_tdomain, _}} -> + undefined + end, + TAddress = element(?snmpTargetAddrTAddress, Row), + AddrString = + try snmp_conf:mk_addr_string({Domain, TAddress}) + catch + {error, {bad_address, _}} -> + "-" + end, lists:flatten( io_lib:format("~sName: ~p" "~n~sTDomain: ~p (~w)" @@ -618,21 +711,8 @@ snmpTargetAddrTable(print) -> "~n~s[Ext] TMask: ~p" "~n~s[Ext] MMS: ~p", [Prefix, element(?snmpTargetAddrName, Row), - Prefix, element(?snmpTargetAddrTDomain, Row), - case element(?snmpTargetAddrTDomain, Row) of - ?snmpUDPDomain -> snmpUDPDomain; - ?transportDomainUdpIpv4 -> transportDomainUdpIpv4; - ?transportDomainUdpIpv6 -> transportDomainUdpIpv6; - _ -> undefined - end, - Prefix, element(?snmpTargetAddrTAddress, Row), - case element(?snmpTargetAddrTAddress, Row) of - [A,B,C,D,U1,U2] -> - lists:flatten( - io_lib:format("~w.~w.~w.~w:~w", - [A, B, C, D, U1 bsl 8 + U2])); - _ -> "-" - end, + Prefix, TDomain, Domain, + Prefix, TAddress, AddrString, Prefix, element(?snmpTargetAddrTimeout, Row), Prefix, element(?snmpTargetAddrRetryCount, Row), Prefix, element(?snmpTargetAddrTagList, Row), diff --git a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl index 223d3f7218..69dce337ba 100644 --- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl +++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -137,18 +137,20 @@ do_reconfigure(Dir) -> read_usm_config_files(Dir) -> ?vdebug("read usm config file",[]), - Gen = fun(D, Reason) -> generate_usm(D, Reason) end, - Filter = fun(Usms) -> Usms end, - Check = fun(Entry) -> check_usm(Entry) end, + Gen = fun (D, Reason) -> generate_usm(D, Reason) end, + Order = fun snmp_conf:no_order/2, + Check = fun (Entry, State) -> {check_usm(Entry), State} end, + Filter = fun snmp_conf:no_filter/1, [Usms] = - snmp_conf:read_files(Dir, [{Gen, Filter, Check, "usm.conf"}]), + snmp_conf:read_files(Dir, [{"usm.conf", Gen, Order, Check, Filter}]), Usms. generate_usm(Dir, _Reason) -> info_msg("Incomplete configuration. Generating empty usm.conf.", []), USMFile = filename:join(Dir, "usm.conf"), - ok = file:write_file(USMFile, list_to_binary([])). + ok = file:write_file(USMFile, list_to_binary([])), + []. check_usm({EngineID, Name, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl index c0177b1cea..722bd7ac5b 100644 --- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl +++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -123,15 +123,18 @@ do_reconfigure(Dir) -> read_vacm_config_files(Dir) -> ?vdebug("read vacm config file",[]), - Gen = fun(_D, _Reason) -> ok end, - Filter = fun(Vacms) -> - Sec2Group = [X || {vacmSecurityToGroup, X} <- Vacms], - Access = [X || {vacmAccess, X} <- Vacms], - View = [X || {vacmViewTreeFamily, X} <- Vacms], - {Sec2Group, Access, View} - end, - Check = fun(Entry) -> check_vacm(Entry) end, - [Vacms] = snmp_conf:read_files(Dir, [{Gen, Filter, Check, "vacm.conf"}]), + Gen = fun snmp_conf:no_gen/2, + Order = fun snmp_conf:no_order/2, + Check = fun (Entry, State) -> {check_vacm(Entry), State} end, + Filter = + fun (Vacms) -> + Sec2Group = [X || {vacmSecurityToGroup, X} <- Vacms], + Access = [X || {vacmAccess, X} <- Vacms], + View = [X || {vacmViewTreeFamily, X} <- Vacms], + {Sec2Group, Access, View} + end, + [Vacms] = + snmp_conf:read_files(Dir, [{"vacm.conf", Gen, Order, Check, Filter}]), Vacms. %%----------------------------------------------------------------- diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index 9bed6e554e..6d3f1cca4a 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -2512,10 +2512,19 @@ handle_mib_of(MibServer, Oid) -> %% Func: process_msg/7 %% Returns: RePdu %%----------------------------------------------------------------- -process_msg(MibView, Vsn, Pdu, PduMS, Community, {Ip, Udp}, ContextName, - GbMaxVBs) -> +process_msg( + MibView, Vsn, Pdu, PduMS, Community, + SourceAddress, ContextName, GbMaxVBs) -> #pdu{request_id = ReqId} = Pdu, - put(snmp_address, {tuple_to_list(Ip), Udp}), + put( + snmp_address, + case SourceAddress of + {Domain, _} when is_atom(Domain) -> + SourceAddress; + {Ip, Port} when is_integer(Port) -> + %% Legacy transport domain + {tuple_to_list(Ip), Port} + end), put(snmp_request_id, ReqId), put(snmp_community, Community), put(snmp_context, ContextName), diff --git a/lib/snmp/src/agent/snmpa_conf.erl b/lib/snmp/src/agent/snmpa_conf.erl index c17a6abbd7..b4d32dc928 100644 --- a/lib/snmp/src/agent/snmpa_conf.erl +++ b/lib/snmp/src/agent/snmpa_conf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2011. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. 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 @@ -108,36 +108,25 @@ write_agent_config(Dir, Conf) -> Hdr = header() ++ Comment, write_agent_config(Dir, Hdr, Conf). -write_agent_config(Dir, Hdr, Conf) +write_agent_config(Dir, Hdr, Conf) when is_list(Dir) and is_list(Hdr) and is_list(Conf) -> - Verify = fun() -> verify_agent_conf(Conf) end, - Write = fun(Fd) -> write_agent_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, "agent.conf", Verify, Write). - + Order = fun snmp_framework_mib:order_agent/2, + Check = fun snmp_framework_mib:check_agent/2, + Write = fun (Fd, Entries) -> write_agent_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, "agent.conf", Order, Check, Write, Conf). -append_agent_config(Dir, Conf) +append_agent_config(Dir, Conf) when is_list(Dir) and is_list(Conf) -> - Verify = fun() -> verify_agent_conf(Conf) end, - Write = fun(Fd) -> write_agent_conf(Fd, Conf) end, - append_config_file(Dir, "agent.conf", Verify, Write). - + Order = fun snmp_framework_mib:order_agent/2, + Check = fun snmp_framework_mib:check_agent/2, + Write = fun write_agent_conf/2, + append_config_file(Dir, "agent.conf", Order, Check, Write, Conf). read_agent_config(Dir) -> - Verify = fun(Entry) -> verify_agent_conf_entry(Entry) end, - read_config_file(Dir, "agent.conf", Verify). + Order = fun snmp_framework_mib:order_agent/2, + Check = fun snmp_framework_mib:check_agent/2, + read_config_file(Dir, "agent.conf", Order, Check). - -verify_agent_conf([]) -> - ok; -verify_agent_conf([H|T]) -> - verify_agent_conf_entry(H), - verify_agent_conf(T); -verify_agent_conf(X) -> - error({bad_agent_config, X}). - -verify_agent_conf_entry(Entry) -> - ok = snmp_framework_mib:check_agent(Entry), - ok. write_agent_conf(Fd, "", Conf) -> write_agent_conf(Fd, Conf); @@ -151,6 +140,10 @@ write_agent_conf(Fd, [H|T]) -> do_write_agent_conf(Fd, H), write_agent_conf(Fd, T). +do_write_agent_conf(Fd, {intAgentTransports = Tag, Val}) -> + io:format(Fd, "{~w, ~w}.~n", [Tag, Val]); +do_write_agent_conf(Fd, {intAgentTransportDomain = Tag, Val}) -> + io:format(Fd, "{~w, ~w}.~n", [Tag, Val]); do_write_agent_conf(Fd, {intAgentIpAddress = Tag, Val}) -> io:format(Fd, "{~w, ~w}.~n", [Tag, Val]); do_write_agent_conf(Fd, {intAgentUDPPort = Tag, Val} ) -> @@ -191,34 +184,27 @@ write_context_config(Dir, Conf) -> write_context_config(Dir, Hdr, Conf) when is_list(Dir) and is_list(Hdr) and is_list(Conf) -> - Verify = fun() -> verify_context_conf(Conf) end, - Write = fun(Fd) -> write_context_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, "context.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_context/2, + Write = fun (Fd, Entries) -> write_context_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, "context.conf", Order, Check, Write, Conf). -append_context_config(Dir, Conf) +append_context_config(Dir, Conf) when is_list(Dir) and is_list(Conf) -> - Verify = fun() -> verify_context_conf(Conf) end, - Write = fun(Fd) -> write_context_conf(Fd, Conf) end, - append_config_file(Dir, "context.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_context/2, + Write = fun write_context_conf/2, + append_config_file(Dir, "context.conf", Order, Check, Write, Conf). read_context_config(Dir) -> - Verify = fun(Entry) -> verify_context_conf_entry(Entry) end, - read_config_file(Dir, "context.conf", Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_context/2, + read_config_file(Dir, "context.conf", Order, Check). - -verify_context_conf([]) -> - ok; -verify_context_conf([H|T]) -> - verify_context_conf_entry(H), - verify_context_conf(T); -verify_context_conf(X) -> - error({error_context_config, X}). - -verify_context_conf_entry(Context) -> - {ok, _} = snmp_framework_mib:check_context(Context), - ok. + +check_context(Entry, State) -> + {check_ok(snmp_framework_mib:check_context(Entry)), + State}. write_context_conf(Fd, "", Conf) -> write_context_conf(Fd, Conf); @@ -271,36 +257,29 @@ write_community_config(Dir, Conf) -> Hdr = header() ++ Comment, write_community_config(Dir, Hdr, Conf). -write_community_config(Dir, Hdr, Conf) +write_community_config(Dir, Hdr, Conf) when is_list(Dir) and is_list(Hdr) and is_list(Conf) -> - Verify = fun() -> verify_community_conf(Conf) end, - Write = fun(Fd) -> write_community_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, "community.conf", Verify, Write). + Order = fun snmp_conf:no_order/2, + Check = fun check_community/2, + Write = fun (Fd, Entries) -> write_community_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, "community.conf", Order, Check, Write, Conf). - -append_community_config(Dir, Conf) +append_community_config(Dir, Conf) when is_list(Dir) and is_list(Conf) -> - Verify = fun() -> verify_community_conf(Conf) end, - Write = fun(Fd) -> write_community_conf(Fd, Conf) end, - append_config_file(Dir, "community.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_community/2, + Write = fun write_community_conf/2, + append_config_file(Dir, "community.conf", Order, Check, Write, Conf). read_community_config(Dir) -> - Verify = fun(Entry) -> verify_community_conf_entry(Entry) end, - read_config_file(Dir, "community.conf", Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_community/2, + read_config_file(Dir, "community.conf", Order, Check). - -verify_community_conf([]) -> - ok; -verify_community_conf([H|T]) -> - verify_community_conf_entry(H), - verify_community_conf(T); -verify_community_conf(X) -> - error({invalid_community_config, X}). - -verify_community_conf_entry(Context) -> - {ok, _} = snmp_community_mib:check_community(Context), - ok. + +check_community(Entry, State) -> + {check_ok(snmp_community_mib:check_community(Entry)), + State}. write_community_conf(Fd, "", Conf) -> write_community_conf(Fd, Conf); @@ -309,14 +288,17 @@ write_community_conf(Fd, Hdr, Conf) -> write_community_conf(Fd, Conf). write_community_conf(Fd, Conf) -> - Fun = fun({Idx, Name, SecName, CtxName, TranspTag}) -> - io:format(Fd, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n", - [Idx, Name, SecName, CtxName, TranspTag]); + Fun = + fun({Idx, Name, SecName, CtxName, TranspTag}) -> + io:format( + Fd, + "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n", + [Idx, Name, SecName, CtxName, TranspTag]); (Crap) -> - error({bad_community_config, Crap}) + error({bad_community_config, Crap}) end, lists:foreach(Fun, Conf). - + %% %% ------ standard.conf ------ @@ -343,40 +325,29 @@ write_standard_config(Dir, Conf) -> Hdr = header() ++ Comment, write_standard_config(Dir, Hdr, Conf). -write_standard_config(Dir, Hdr, Conf) +write_standard_config(Dir, Hdr, Conf) when is_list(Dir) and is_list(Hdr) and is_list(Conf) -> - Verify = fun() -> verify_standard_conf(Conf) end, - Write = fun(Fd) -> write_standard_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, "standard.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_standard/2, + Write = fun (Fd, Entries) -> write_standard_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, "standard.conf", Order, Check, Write, Conf). -append_standard_config(Dir, Conf) +append_standard_config(Dir, Conf) when is_list(Dir) and is_list(Conf) -> - Verify = fun() -> verify_standard_conf(Conf) end, - Write = fun(Fd) -> write_standard_conf(Fd, Conf) end, - append_config_file(Dir, "standard.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_standard/2, + Write = fun write_standard_conf/2, + append_config_file(Dir, "standard.conf", Order, Check, Write, Conf). read_standard_config(Dir) -> - Verify = fun(Entry) -> verify_standard_conf_entry(Entry) end, - read_config_file(Dir, "standard.conf", Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_standard/2, + read_config_file(Dir, "standard.conf", Order, Check). - -verify_standard_conf([]) -> - ok; -verify_standard_conf([H|T]) -> - verify_standard_conf_entry(H), - verify_standard_conf(T); -verify_standard_conf(X) -> - error({bad_standard_config, X}). - -verify_standard_conf_entry(Std) -> - case snmp_standard_mib:check_standard(Std) of - ok -> - ok; - {ok, _} -> - ok - end. + +check_standard(Entry, State) -> + {check_ok(snmp_standard_mib:check_standard(Entry)), + State}. write_standard_conf(Fd, "", Conf) -> write_standard_conf(Fd, Conf); @@ -410,72 +381,35 @@ do_write_standard_conf(_Fd, Tag, Val) -> %% ------ target_addr.conf ------ %% -target_addr_entry(Name, - Ip, - TagList, - ParamsName, - EngineId) -> +target_addr_entry( + Name, Ip, TagList, ParamsName, EngineId) -> target_addr_entry(Name, Ip, TagList, ParamsName, EngineId, []). -target_addr_entry(Name, - Ip, - TagList, - ParamsName, - EngineId, - TMask) -> - target_addr_entry(Name, Ip, 162, TagList, - ParamsName, EngineId, - TMask, 2048). - -target_addr_entry(Name, - Ip, - Udp, - TagList, - ParamsName, - EngineId, - TMask, - MaxMessageSize) -> - target_addr_entry(Name, Ip, Udp, 1500, 3, TagList, - ParamsName, EngineId, - TMask, MaxMessageSize). - -target_addr_entry(Name, - Ip, - Udp, - Timeout, - RetryCount, - TagList, - ParamsName, - EngineId, - TMask, - MaxMessageSize) -> - target_addr_entry(Name, snmp_target_mib:default_domain(), Ip, Udp, - Timeout, RetryCount, TagList, - ParamsName, EngineId, - TMask, MaxMessageSize). - -target_addr_entry(Name, - Domain, - Ip, - Udp, - Timeout, - RetryCount, - TagList, - ParamsName, - EngineId, - TMask, - MaxMessageSize) -> - {Name, - Domain, - Ip, - Udp, - Timeout, - RetryCount, - TagList, - ParamsName, - EngineId, - TMask, - MaxMessageSize}. +target_addr_entry( + Name, Ip, TagList, ParamsName, + EngineId, TMask) -> + target_addr_entry( + Name, Ip, 162, TagList, ParamsName, + EngineId, TMask, 2048). + +target_addr_entry( + Name, Domain_or_Ip, Addr_or_Port, TagList, + ParamsName, EngineId, TMask, MaxMessageSize) -> + target_addr_entry( + Name, Domain_or_Ip, Addr_or_Port, 1500, 3, TagList, + ParamsName, EngineId, TMask, MaxMessageSize). + +target_addr_entry( + Name, Domain_or_Ip, Addr_or_Port, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize) -> + {Name, Domain_or_Ip, Addr_or_Port, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize}. + +target_addr_entry( + Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, + ParamsName, EngineId,TMask, MaxMessageSize) -> + {Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize}. write_target_addr_config(Dir, Conf) -> @@ -504,37 +438,29 @@ write_target_addr_config(Dir, Conf) -> Hdr = header() ++ Comment, write_target_addr_config(Dir, Hdr, Conf). -write_target_addr_config(Dir, Hdr, Conf) +write_target_addr_config(Dir, Hdr, Conf) when is_list(Dir) and is_list(Hdr) and is_list(Conf) -> - Verify = fun() -> verify_target_addr_conf(Conf) end, - Write = fun(Fd) -> write_target_addr_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, "target_addr.conf", Verify, Write). + Order = fun snmp_conf:no_order/2, + Check = fun check_target_addr/2, + Write = fun (Fd, Entries) -> write_target_addr_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, "target_addr.conf", Order, Check, Write, Conf). - - -append_target_addr_config(Dir, Conf) +append_target_addr_config(Dir, Conf) when is_list(Dir) and is_list(Conf) -> - Verify = fun() -> verify_target_addr_conf(Conf) end, - Write = fun(Fd) -> write_target_addr_conf(Fd, Conf) end, - append_config_file(Dir, "target_addr.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_target_addr/2, + Write = fun write_target_addr_conf/2, + append_config_file(Dir, "target_addr.conf", Order, Check, Write, Conf). read_target_addr_config(Dir) -> - Verify = fun(Entry) -> verify_target_addr_conf_entry(Entry) end, - read_config_file(Dir, "target_addr.conf", Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_target_addr/2, + read_config_file(Dir, "target_addr.conf", Order, Check). - -verify_target_addr_conf([]) -> - ok; -verify_target_addr_conf([H|T]) -> - verify_target_addr_conf_entry(H), - verify_target_addr_conf(T); -verify_target_addr_conf(X) -> - error({bad_target_addr_config, X}). - -verify_target_addr_conf_entry(Entry) -> - {ok, _} = snmp_target_mib:check_target_addr(Entry), - ok. + +check_target_addr(Entry, State) -> + {check_ok(snmp_target_mib:check_target_addr(Entry)), + State}. write_target_addr_conf(Fd, "", Conf) -> write_target_addr_conf(Fd, Conf); @@ -547,29 +473,36 @@ write_target_addr_conf(Fd, Conf) -> lists:foreach(Fun, Conf), ok. -do_write_target_addr_conf(Fd, - {Name, - Ip, Udp, - Timeout, RetryCount, TagList, - ParamsName, EngineId, - TMask, MaxMessageSize}) -> - Domain = snmp_target_mib:default_domain(), - do_write_target_addr_conf(Fd, - {Name, - Domain, Ip, Udp, - Timeout, RetryCount, TagList, - ParamsName, EngineId, - TMask, MaxMessageSize}); -do_write_target_addr_conf(Fd, - {Name, - Domain, Ip, Udp, - Timeout, RetryCount, TagList, - ParamsName, EngineId, - TMask, MaxMessageSize}) -> - io:format(Fd, - "{\"~s\", ~w, ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", - [Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, - ParamsName, EngineId, TMask, MaxMessageSize]); +do_write_target_addr_conf( + Fd, + {Name, Ip, Udp, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize}) + when is_integer(Udp) -> + Domain = snmp_target_mib:default_domain(), + Address = {Ip, Udp}, + do_write_target_addr_conf( + Fd, + {Name, Domain, Address, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize}); +do_write_target_addr_conf( + Fd, + {Name, Domain, Address, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize}) + when is_atom(Domain) -> + io:format( + Fd, + "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", + [Name, Domain, Address, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize]); +do_write_target_addr_conf( + Fd, + {Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize}) -> + Address = {Ip, Udp}, + do_write_target_addr_conf( + Fd, + {Name, Domain, Address, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize}); do_write_target_addr_conf(_Fd, Crap) -> error({bad_target_addr_config, Crap}). @@ -613,34 +546,27 @@ write_target_params_config(Dir, Conf) -> write_target_params_config(Dir, Hdr, Conf) when is_list(Dir) and is_list(Hdr) and is_list(Conf) -> - Verify = fun() -> verify_target_params_conf(Conf) end, - Write = fun(Fd) -> write_target_params_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, "target_params.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_target_params/2, + Write = fun (Fd, Entries) -> write_target_params_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, "target_params.conf", Order, Check, Write, Conf). append_target_params_config(Dir, Conf) when is_list(Dir) and is_list(Conf) -> - Verify = fun() -> verify_target_params_conf(Conf) end, - Write = fun(Fd) -> write_target_params_conf(Fd, Conf) end, - append_config_file(Dir, "target_params.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_target_params/2, + Write = fun write_target_params_conf/2, + append_config_file(Dir, "target_params.conf", Order, Check, Write, Conf). read_target_params_config(Dir) -> - Verify = fun(Entry) -> verify_target_params_conf_entry(Entry) end, - read_config_file(Dir, "target_params.conf", Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_target_params/2, + read_config_file(Dir, "target_params.conf", Order, Check). -verify_target_params_conf([]) -> - ok; -verify_target_params_conf([H|T]) -> - verify_target_params_conf_entry(H), - verify_target_params_conf(T); -verify_target_params_conf(X) -> - error({bad_target_params_config, X}). - -verify_target_params_conf_entry(Entry) -> - {ok, _} = snmp_target_mib:check_target_params(Entry), - ok. +check_target_params(Entry, State) -> + {check_ok(snmp_target_mib:check_target_params(Entry)), + State}. write_target_params_conf(Fd, "", Conf) -> write_target_params_conf(Fd, Conf); @@ -685,34 +611,27 @@ write_notify_config(Dir, Conf) -> write_notify_config(Dir, Hdr, Conf) when is_list(Dir) and is_list(Hdr) and is_list(Conf) -> - Verify = fun() -> verify_notify_conf(Conf) end, - Write = fun(Fd) -> write_notify_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, "notify.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_notify/2, + Write = fun (Fd, Entries) -> write_notify_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, "notify.conf", Order, Check, Write, Conf). append_notify_config(Dir, Conf) when is_list(Dir) and is_list(Conf) -> - Verify = fun() -> verify_notify_conf(Conf) end, - Write = fun(Fd) -> write_notify_conf(Fd, Conf) end, - append_config_file(Dir, "notify.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_notify/2, + Write = fun write_notify_conf/2, + append_config_file(Dir, "notify.conf", Order, Check, Write, Conf). read_notify_config(Dir) -> - Verify = fun(Entry) -> verify_notify_conf_entry(Entry) end, - read_config_file(Dir, "notify.conf", Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_notify/2, + read_config_file(Dir, "notify.conf", Order, Check). -verify_notify_conf([]) -> - ok; -verify_notify_conf([H|T]) -> - verify_notify_conf_entry(H), - verify_notify_conf(T); -verify_notify_conf(X) -> - error({bad_notify_config, X}). - -verify_notify_conf_entry(Entry) -> - {ok, _} = snmp_notification_mib:check_notify(Entry), - ok. +check_notify(Entry, State) -> + {check_ok(snmp_notification_mib:check_notify(Entry)), + State}. write_notify_conf(Fd, "", Conf) -> write_notify_conf(Fd, Conf); @@ -781,34 +700,27 @@ write_usm_config(Dir, Conf) -> write_usm_config(Dir, Hdr, Conf) when is_list(Dir) and is_list(Hdr) and is_list(Conf) -> - Verify = fun() -> verify_usm_conf(Conf) end, - Write = fun(Fd) -> write_usm_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, "usm.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_usm/2, + Write = fun (Fd, Entries) -> write_usm_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, "usm.conf", Order, Check, Write, Conf). append_usm_config(Dir, Conf) when is_list(Dir) and is_list(Conf) -> - Verify = fun() -> verify_usm_conf(Conf) end, - Write = fun(Fd) -> write_usm_conf(Fd, Conf) end, - append_config_file(Dir, "usm.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_usm/2, + Write = fun write_usm_conf/2, + append_config_file(Dir, "usm.conf", Order, Check, Write, Conf). read_usm_config(Dir) -> - Verify = fun(Entry) -> verify_usm_conf_entry(Entry) end, - read_config_file(Dir, "usm.conf", Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_usm/2, + read_config_file(Dir, "usm.conf", Order, Check). -verify_usm_conf([]) -> - ok; -verify_usm_conf([H|T]) -> - verify_usm_conf_entry(H), - verify_usm_conf(T); -verify_usm_conf(X) -> - error({bad_usm_conf, X}). - -verify_usm_conf_entry(Entry) -> - {ok, _} = snmp_user_based_sm_mib:check_usm(Entry), - ok. +check_usm(Entry, State) -> + {check_ok(snmp_user_based_sm_mib:check_usm(Entry)), + State}. write_usm_conf(Fd, "", Conf) -> write_usm_conf(Fd, Conf); @@ -820,11 +732,12 @@ write_usm_conf(Fd, Conf) -> Fun = fun(Entry) -> do_write_usm_conf(Fd, Entry) end, lists:foreach(Fun, Conf). -do_write_usm_conf(Fd, - {EngineID, UserName, SecName, Clone, - AuthP, AuthKeyC, OwnAuthKeyC, - PrivP, PrivKeyC, OwnPrivKeyC, - Public, AuthKey, PrivKey}) -> +do_write_usm_conf( + Fd, + {EngineID, UserName, SecName, Clone, + AuthP, AuthKeyC, OwnAuthKeyC, + PrivP, PrivKeyC, OwnPrivKeyC, + Public, AuthKey, PrivKey}) -> io:format(Fd, "{", []), io:format(Fd, "\"~s\", ", [EngineID]), io:format(Fd, "\"~s\", ", [UserName]), @@ -890,34 +803,27 @@ write_vacm_config(Dir, Conf) -> write_vacm_config(Dir, Hdr, Conf) when is_list(Dir) and is_list(Hdr) and is_list(Conf) -> - Verify = fun() -> verify_vacm_conf(Conf) end, - Write = fun(Fd) -> write_vacm_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, "vacm.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_vacm/2, + Write = fun (Fd, Entries) -> write_vacm_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, "vacm.conf", Order, Check, Write, Conf). append_vacm_config(Dir, Conf) when is_list(Dir) and is_list(Conf) -> - Verify = fun() -> verify_vacm_conf(Conf) end, - Write = fun(Fd) -> write_vacm_conf(Fd, Conf) end, - append_config_file(Dir, "vacm.conf", Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_vacm/2, + Write = fun write_vacm_conf/2, + append_config_file(Dir, "vacm.conf", Order, Check, Write, Conf). read_vacm_config(Dir) -> - Verify = fun(Entry) -> verify_vacm_conf_entry(Entry) end, - read_config_file(Dir, "vacm.conf", Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_vacm/2, + read_config_file(Dir, "vacm.conf", Order, Check). -verify_vacm_conf([]) -> - ok; -verify_vacm_conf([H|T]) -> - verify_vacm_conf_entry(H), - verify_vacm_conf(T); -verify_vacm_conf(X) -> - error({bad_vacm_conf, X}). - -verify_vacm_conf_entry(Entry) -> - {ok, _} = snmp_view_based_acm_mib:check_vacm(Entry), - ok. +check_vacm(Entry, State) -> + {check_ok(snmp_view_based_acm_mib:check_vacm(Entry)), + State}. write_vacm_conf(Fd, "", Conf) -> write_vacm_conf(Fd, Conf); @@ -929,49 +835,60 @@ write_vacm_conf(Fd, Conf) -> Fun = fun(Entry) -> do_write_vacm_conf(Fd, Entry) end, lists:foreach(Fun, Conf). -do_write_vacm_conf(Fd, - {vacmSecurityToGroup, - SecModel, SecName, GroupName}) -> - io:format(Fd, "{vacmSecurityToGroup, ~w, \"~s\", \"~s\"}.~n", - [SecModel, SecName, GroupName]); -do_write_vacm_conf(Fd, - {vacmAccess, - GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV}) -> - io:format(Fd, "{vacmAccess, \"~s\", \"~s\", ~w, ~w, ~w, " - "\"~s\", \"~s\", \"~s\"}.~n", - [GroupName, Prefix, SecModel, SecLevel, - Match, RV, WV, NV]); -do_write_vacm_conf(Fd, - {vacmViewTreeFamily, - ViewIndex, ViewSubtree, ViewStatus, ViewMask}) -> - io:format(Fd, "{vacmViewTreeFamily, \"~s\", ~w, ~w, ~w}.~n", - [ViewIndex, ViewSubtree, ViewStatus, ViewMask]); +do_write_vacm_conf( + Fd, + {vacmSecurityToGroup, + SecModel, SecName, GroupName}) -> + io:format( + Fd, "{vacmSecurityToGroup, ~w, \"~s\", \"~s\"}.~n", + [SecModel, SecName, GroupName]); +do_write_vacm_conf( + Fd, + {vacmAccess, + GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV}) -> + io:format( + Fd, "{vacmAccess, \"~s\", \"~s\", ~w, ~w, ~w, " + "\"~s\", \"~s\", \"~s\"}.~n", + [GroupName, Prefix, SecModel, SecLevel, + Match, RV, WV, NV]); +do_write_vacm_conf( + Fd, + {vacmViewTreeFamily, + ViewIndex, ViewSubtree, ViewStatus, ViewMask}) -> + io:format( + Fd, "{vacmViewTreeFamily, \"~s\", ~w, ~w, ~w}.~n", + [ViewIndex, ViewSubtree, ViewStatus, ViewMask]); do_write_vacm_conf(_Fd, Crap) -> error({bad_vacm_config, Crap}). %% ---- config file wrapper functions ---- -write_config_file(Dir, File, Verify, Write) -> - snmp_config:write_config_file(Dir, File, Verify, Write). +write_config_file(Dir, File, Order, Check, Write, Conf) -> + snmp_config:write_config_file(Dir, File, Order, Check, Write, Conf). -append_config_file(Dir, File, Verify, Write) -> - snmp_config:append_config_file(Dir, File, Verify, Write). +append_config_file(Dir, File, Order, Check, Write, Conf) -> + snmp_config:append_config_file(Dir, File, Order, Check, Write, Conf). -read_config_file(Dir, File, Verify) -> - snmp_config:read_config_file(Dir, File, Verify). +read_config_file(Dir, File, Order, Check) -> + snmp_config:read_config_file(Dir, File, Order, Check). %% ---- config file utility functions ---- +check_ok(ok) -> + ok; +check_ok({ok, _}) -> + ok. + header() -> {Y,Mo,D} = date(), {H,Mi,S} = time(), - io_lib:format("%% This file was generated by " - "~w (version-~s) ~w-~2.2.0w-~2.2.0w " - "~2.2.0w:~2.2.0w:~2.2.0w\n", - [?MODULE, ?version, Y, Mo, D, H, Mi, S]). - + io_lib:format( + "%% This file was generated by " + "~w (version-~s) ~w-~2.2.0w-~2.2.0w " + "~2.2.0w:~2.2.0w:~2.2.0w\n", + [?MODULE, ?version, Y, Mo, D, H, Mi, S]). error(R) -> throw({error, R}). diff --git a/lib/snmp/src/agent/snmpa_local_db.erl b/lib/snmp/src/agent/snmpa_local_db.erl index f991244287..292c370d51 100644 --- a/lib/snmp/src/agent/snmpa_local_db.erl +++ b/lib/snmp/src/agent/snmpa_local_db.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -1011,6 +1011,10 @@ table_construct_row(Name, RowIndex, Status, Cols) -> defvals = Defs, status_col = StatusCol, first_own_index = FirstOwnIndex, not_accessible = NoAccs} = snmp_generic:table_info(Name), + ?vtrace( + "table_construct_row Indexes: ~p~n" + " RowIndex: ~p", + [Indexes, RowIndex]), Keys = snmp_generic:split_index_to_keys(Indexes, RowIndex), OwnKeys = snmp_generic:get_own_indexes(FirstOwnIndex, Keys), Row = OwnKeys ++ snmp_generic:table_create_rest(length(OwnKeys) + 1, diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl index 11ae806866..642b1f7fc5 100644 --- a/lib/snmp/src/agent/snmpa_mpd.erl +++ b/lib/snmp/src/agent/snmpa_mpd.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. 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 @@ -20,7 +20,7 @@ -export([init/1, reset/0, inc/1, counters/0, discarded_pdu/1, - process_packet/6, process_packet/7, + process_packet/5, process_packet/6, process_packet/7, generate_response_msg/5, generate_response_msg/6, generate_msg/5, generate_msg/6, generate_discovery_msg/4, @@ -113,22 +113,30 @@ reset() -> % length(snmp_pdus:enc_message(M)) + 4. %%----------------------------------------------------------------- -%% Func: process_packet(Packet, TDomain, TAddress, State, Log) -> +%% Func: process_packet(Packet, Domain, Address, State, Log) -> %% {ok, SnmpVsn, Pdu, PduMS, ACMData} | {discarded, Reason} %% Types: Packet = binary() -%% TDomain = snmpUDPDomain | transportDomain() -%% TAddress = {Ip, Udp} (*but* depends on TDomain) +%% Domain = snmpUDPDomain | transportDomain() +%% Address = {Ip, Udp} (*but* depends on Domain) %% State = #state %% Purpose: This is the main Message Dispatching function. (see %% section 4.2.1 in rfc2272) %%----------------------------------------------------------------- -process_packet(Packet, TDomain, TAddress, State, NoteStore, Log) -> +process_packet(Packet, From, State, NoteStore, Log) -> LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, - process_packet(Packet, TDomain, TAddress, LocalEngineID, - State, NoteStore, Log). - -process_packet(Packet, TDomain, TAddress, LocalEngineID, - State, NoteStore, Log) -> + process_packet(Packet, From, LocalEngineID, State, NoteStore, Log). + +process_packet( + Packet, Domain, Address, LocalEngineID, State, NoteStore, Log) -> + From = {Domain, Address}, + process_packet(Packet, From, LocalEngineID, State, NoteStore, Log). + +process_packet(Packet, Domain, Address, State, NoteStore, Log) + when is_atom(Domain) -> + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + From = {Domain, Address}, + process_packet(Packet, From, LocalEngineID, State, NoteStore, Log); +process_packet(Packet, From, LocalEngineID, State, NoteStore, Log) -> inc(snmpInPkts), case catch snmp_pdus:dec_message_only(binary_to_list(Packet)) of @@ -136,17 +144,17 @@ process_packet(Packet, TDomain, TAddress, LocalEngineID, when State#state.v1 =:= true -> ?vlog("v1, community: ~s", [Community]), HS = ?empty_msg_size + length(Community), - v1_v2c_proc('version-1', NoteStore, Community, - TDomain, TAddress, - LocalEngineID, Data, HS, Log, Packet); + v1_v2c_proc( + 'version-1', NoteStore, Community, From, + LocalEngineID, Data, HS, Log, Packet); #message{version = 'version-2', vsn_hdr = Community, data = Data} when State#state.v2c =:= true -> ?vlog("v2c, community: ~s", [Community]), HS = ?empty_msg_size + length(Community), - v1_v2c_proc('version-2', NoteStore, Community, - TDomain, TAddress, - LocalEngineID, Data, HS, Log, Packet); + v1_v2c_proc( + 'version-2', NoteStore, Community, From, + LocalEngineID, Data, HS, Log, Packet); #message{version = 'version-3', vsn_hdr = V3Hdr, data = Data} when State#state.v3 =:= true -> @@ -154,9 +162,9 @@ process_packet(Packet, TDomain, TAddress, LocalEngineID, [V3Hdr#v3_hdr.msgID, V3Hdr#v3_hdr.msgFlags, V3Hdr#v3_hdr.msgSecurityModel]), - v3_proc(NoteStore, Packet, - TDomain, TAddress, - LocalEngineID, V3Hdr, Data, Log); + v3_proc( + NoteStore, Packet, From, + LocalEngineID, V3Hdr, Data, Log); {'EXIT', {bad_version, Vsn}} -> ?vtrace("exit: bad version: ~p",[Vsn]), @@ -183,11 +191,32 @@ discarded_pdu(Variable) -> inc(Variable). %%----------------------------------------------------------------- %% Handles a Community based message (v1 or v2c). %%----------------------------------------------------------------- -v1_v2c_proc(Vsn, NoteStore, Community, Domain, - {Ip, Udp}, LocalEngineID, - Data, HS, Log, Packet) -> - TDomain = snmp_conf:mk_tdomain(Domain), - TAddress = snmp_conf:mk_taddress(Domain, Ip, Udp), +v1_v2c_proc( + Vsn, NoteStore, Community, From, + LocalEngineID, Data, HS, Log, Packet) -> + try + case From of + {D, A} when is_atom(D) -> + {snmp_conf:mk_tdomain(D), + snmp_conf:mk_taddress(D, A)}; + {_, P} = A when is_integer(P) -> + {snmp_conf:mk_tdomain(), + snmp_conf:mk_taddress(A)} + end + of + {TDomain, TAddress} -> + v1_v2c_proc_dec( + Vsn, NoteStore, Community, TDomain, TAddress, + LocalEngineID, Data, HS, Log, Packet) + catch + _ -> + {discarded, {badarg, From}} + end. + + +v1_v2c_proc_dec( + Vsn, NoteStore, Community, TDomain, TAddress, + LocalEngineID, Data, HS, Log, Packet) -> AgentMS = get_engine_max_message_size(LocalEngineID), MgrMS = snmp_community_mib:get_target_addr_ext_mms(TDomain, TAddress), PduMS = case MgrMS of @@ -214,7 +243,7 @@ v1_v2c_proc(Vsn, NoteStore, Community, Domain, case Pdu#pdu.type of 'set-request' -> %% Check if this message has already been processed - Key = {agent, Ip, ReqId}, + Key = {agent, {TDomain, TAddress}, ReqId}, case snmp_note_store:get_note(NoteStore, Key) of undefined -> %% Set the processed note _after_ pdu processing. @@ -236,13 +265,7 @@ v1_v2c_proc(Vsn, NoteStore, Community, Domain, {discarded, Reason}; _TrapPdu -> {discarded, trap_pdu} - end; -v1_v2c_proc(_Vsn, _NoteStore, _Community, snmpUDPDomain, TAddress, - _LocalEngineID, _Data, _HS, _Log, _Packet) -> - {discarded, {badarg, TAddress}}; -v1_v2c_proc(_Vsn, _NoteStore, _Community, TDomain, _TAddress, - _LocalEngineID, _Data, _HS, _Log, _Packet) -> - {discarded, {badarg, TDomain}}. + end. sec_model('version-1') -> ?SEC_V1; sec_model('version-2') -> ?SEC_V2C. @@ -252,8 +275,7 @@ sec_model('version-2') -> ?SEC_V2C. %% Handles a SNMPv3 Message, following the procedures in rfc2272, %% section 4.2 and 7.2 %%----------------------------------------------------------------- -v3_proc(NoteStore, Packet, _TDomain, _TAddress, LocalEngineID, - V3Hdr, Data, Log) -> +v3_proc(NoteStore, Packet, _From, LocalEngineID, V3Hdr, Data, Log) -> case (catch v3_proc(NoteStore, Packet, LocalEngineID, V3Hdr, Data, Log)) of {'EXIT', Reason} -> exit(Reason); @@ -999,7 +1021,7 @@ generate_discovery_msg(NoteStore, {TDomain, TAddress}, InitialUserName, ContextName, Timeout) -> - {ok, {_Domain, Address}} = transform_taddr(TDomain, TAddress), + {ok, {Domain, Address}} = transform_taddr(TDomain, TAddress), %% 7.1.7 ?vdebug("generate_discovery_msg -> 7.1.7 (~w)", [ManagerEngineID]), @@ -1041,7 +1063,7 @@ generate_discovery_msg(NoteStore, {TDomain, TAddress}, %% Log(Packet), inc_snmp_out_vars(Pdu), ?vdebug("generate_discovery_msg -> done", []), - {Packet, Address}; + {Domain, Address, Packet}; Error -> throw(Error) @@ -1081,8 +1103,22 @@ transform_taddr(?transportDomainUdpIpv4, [A, B, C, D, P1, P2]) -> {ok, {Domain, Address}}; transform_taddr(?transportDomainUdpIpv4, BadAddr) -> {error, {bad_transportDomainUdpIpv4_address, BadAddr}}; -transform_taddr(?transportDomainUdpIpv6, - [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]) -> +transform_taddr( + ?transportDomainUdpIpv6, + [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, + P1, P2]) -> + Domain = transportDomainUdpIpv6, + Addr = + {(A1 bsl 8) bor A2, (A3 bsl 8) bor A4, + (A5 bsl 8) bor A6, (A7 bsl 8) bor A8, + (A9 bsl 8) bor A10, (A11 bsl 8) bor A12, + (A13 bsl 8) bor A14, (A15 bsl 8) bor A16}, + Port = P1 bsl 8 + P2, + Address = {Addr, Port}, + {ok, {Domain, Address}}; +transform_taddr( + ?transportDomainUdpIpv6, + [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]) -> Domain = transportDomainUdpIpv6, Addr = {A1, A2, A3, A4, A5, A6, A7, A8}, Port = P1 bsl 8 + P2, @@ -1171,6 +1207,9 @@ mk_v1_v2_packet_list([{Domain, Addr} | T], %% Sending from default UDP port inc_snmp_out_vars(Pdu), Entry = {Domain, Addr, Packet}, + %% It would be cleaner to return {To, Packet} to not + %% break the abstraction for an address on the + %% {Domain, Address} format. mk_v1_v2_packet_list(T, Packet, Len, Pdu, [Entry | Acc]). @@ -1277,6 +1316,9 @@ mk_v3_packet_entry(NoteStore, Domain, Addr, req_id = Pdu#pdu.request_id}, snmp_note_store:set_note(NoteStore, 1500, CacheKey, CacheVal), inc_snmp_out_vars(Pdu), + %% It would be cleaner to return {To, Packet} to not + %% break the abstraction for an address on the + %% {Domain, Address} format. {ok, {Domain, Addr, Data}} end. diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl index 79c85a6e4e..840d56d563 100644 --- a/lib/snmp/src/agent/snmpa_net_if.erl +++ b/lib/snmp/src/agent/snmpa_net_if.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -35,18 +35,27 @@ -include("snmp_debug.hrl"). -include("snmp_verbosity.hrl"). --record(state, {parent, - note_store, - master_agent, - usock, - usock_opts, - mpd_state, - log, - reqs = [], - debug = false, - limit = infinity, - rcnt = [], - filter}). +-record(state, + {parent, + note_store, + master_agent, + transports = [], +%% usock, +%% usock_opts, + mpd_state, + log, + reqs = [], + debug = false, + limit = infinity, +%% rcnt = [], + filter}). +%% domain = snmpUDPDomain}). + +-record(transport, + {socket, + domain = snmpUDPDomain, + opts = [], + req_refs = []}). -ifndef(default_verbosity). -define(default_verbosity,silence). @@ -104,13 +113,9 @@ get_request_limit(Pid) -> set_request_limit(Pid, NewLimit) -> call(Pid, {set_request_limit, NewLimit}). -get_port() -> - {value, UDPPort} = snmp_framework_mib:intAgentUDPPort(get), - UDPPort. - -get_address() -> - {value, IPAddress} = snmp_framework_mib:intAgentIpAddress(get), - IPAddress. +get_transports() -> + {value, Transports} = snmp_framework_mib:intAgentTransports(get), + Transports. filter_reset(Pid) -> Pid ! filter_reset. @@ -129,7 +134,22 @@ init(Prio, NoteStore, MasterAgent, Parent, Opts) -> case (catch do_init(Prio, NoteStore, MasterAgent, Parent, Opts)) of {ok, State} -> proc_lib:init_ack({ok, self()}), - loop(State); + try loop(State) + catch + C:E when C =/= exit, E =/= shutdown -> + Fmt = + "loop/1 EXCEPTION ~w:~w~n" + " ~p", + S = erlang:get_stacktrace(), + case C of + exit -> + %% Externally killed, root cause is elsewhere + info_msg(Fmt, [C, E, S]); + _ -> + error_msg(Fmt, [C, E, S]) + end, + erlang:raise(C, E, S) + end; {error, Reason} -> config_err("failed starting net-if: ~n~p", [Reason]), proc_lib:init_ack({error, Reason}); @@ -147,12 +167,6 @@ do_init(Prio, NoteStore, MasterAgent, Parent, Opts) -> put(verbosity,get_verbosity(Opts)), ?vlog("starting",[]), - %% -- Port and address -- - UDPPort = get_port(), - ?vdebug("port: ~w",[UDPPort]), - IPAddress = get_address(), - ?vdebug("addr: ~w",[IPAddress]), - %% -- Versions -- Vsns = get_vsns(Opts), ?vdebug("vsns: ~w",[Vsns]), @@ -162,39 +176,45 @@ do_init(Prio, NoteStore, MasterAgent, Parent, Opts) -> ?vdebug("Limit: ~w", [Limit]), FilterOpts = get_filter_opts(Opts), FilterMod = create_filter(FilterOpts), - ?vdebug("FilterMod: ~w", [FilterMod]), + ?vdebug("FilterMod: ~w FilterOpts: ~p", [FilterMod,FilterOpts]), %% -- Audit trail log Log = create_log(), ?vdebug("Log: ~w",[Log]), - - %% -- Socket -- - IPOpts1 = ip_opt_bind_to_ip_address(Opts, IPAddress), - IPOpts2 = ip_opt_no_reuse_address(Opts), - IPOpts3 = ip_opt_recbuf(Opts), - IPOpts4 = ip_opt_sndbuf(Opts), - IPOpts = [binary | IPOpts1 ++ IPOpts2 ++ IPOpts3 ++ IPOpts4], - ?vdebug("open socket with options: ~w",[IPOpts]), - case gen_udp_open(UDPPort, IPOpts) of - {ok, Sock} -> + DomainAddresses = get_transports(), + ?vdebug("DomainAddresses: ~w",[DomainAddresses]), + try + [begin + SocketOpts = socket_opts(Domain, Address, Opts), + Socket = socket_open(Domain, SocketOpts), + active_once(Socket), + #transport{ + socket = Socket, + domain = Domain, + opts = SocketOpts} + end || {Domain, Address} <- DomainAddresses] + of + [] -> + ?vinfo("No transports configured: ~p", [DomainAddresses]), + {error, {no_transports,DomainAddresses}}; + Transports -> MpdState = snmpa_mpd:init(Vsns), - init_counters(), - active_once(Sock), + init_counters(), S = #state{parent = Parent, note_store = NoteStore, master_agent = MasterAgent, mpd_state = MpdState, - usock = Sock, - usock_opts = IPOpts, + transports = Transports, log = Log, limit = Limit, filter = FilterMod}, ?vdebug("started with MpdState: ~p", [MpdState]), - {ok, S}; - {error, Reason} -> - ?vinfo("Failed to open UDP socket: ~p", [Reason]), - {error, {udp_open, UDPPort, Reason}} + {ok, S} + catch + Error -> + ?vinfo("Failed to initialize socket(s): ~p", [Error]), + {error, Error} end. @@ -250,48 +270,84 @@ create_filter(BadOpts) -> throw({error, {bad_filter_opts, BadOpts}}). -log({_, []}, _, _, _, _) -> +log({_, []}, _, _, _) -> ok; -log({Log, Types}, 'set-request', Packet, Addr, Port) -> +log({Log, Types}, 'set-request', Packet, Address) -> case lists:member(write, Types) of true -> - snmp_log:log(Log, Packet, Addr, Port); + snmp_log:log(Log, Packet, format_address(Address)); false -> ok end; -log({Log, Types}, _, Packet, Addr, Port) -> +log({Log, Types}, _, Packet, Address) -> case lists:member(read, Types) of true -> - snmp_log:log(Log, Packet, Addr, Port); + snmp_log:log(Log, Packet, format_address(Address)); false -> ok - end; -log(_, _, _, _, _) -> - ok. - - -gen_udp_open(Port, Opts) -> + end. + +format_address(Address) -> + iolist_to_binary(snmp_conf:mk_addr_string(Address)). + + +socket_open(snmpUDPDomain = Domain, [IpPort | Opts]) -> case init:get_argument(snmp_fd) of {ok, [[FdStr]]} -> Fd = list_to_integer(FdStr), - gen_udp:open(0, [{fd, Fd}|Opts]); + ?vdebug("socket_open(~p, [~p | ~p]) Fd: ~p", + [Domain, IpPort, Opts, Fd]), + gen_udp_open(IpPort, [{fd, Fd} | Opts]); error -> case init:get_argument(snmpa_fd) of {ok, [[FdStr]]} -> Fd = list_to_integer(FdStr), - gen_udp:open(0, [{fd, Fd}|Opts]); + ?vdebug("socket_open(~p, [~p | ~p]) Fd: ~p", + [Domain, IpPort, Opts, Fd]), + gen_udp_open(IpPort, [{fd, Fd} | Opts]); error -> - gen_udp:open(Port, Opts) + ?vdebug("socket_open(~p, [~p | ~p])", + [Domain, IpPort, Opts]), + gen_udp_open(IpPort, Opts) end + end; +socket_open(Domain, [IpPort | Opts]) + when Domain =:= transportDomainUdpIpv4; + Domain =:= transportDomainUdpIpv6 -> + ?vdebug("socket_open(~p, [~p | ~p])", [Domain, IpPort, Opts]), + gen_udp_open(IpPort, Opts); +socket_open(Domain, Opts) -> + throw({socket_open, Domain, Opts}). + +gen_udp_open(IpPort, Opts) -> + case gen_udp:open(IpPort, Opts) of + {ok, Socket} -> + Socket; + {error, Reason} -> + throw({udp_open, IpPort, Reason}) end. -loop(S) -> + +loop(#state{transports = Transports, limit = Limit, parent = Parent} = S) -> + ?vdebug("loop(~p)", [S]), receive - {udp, _UdpId, Ip, Port, Packet} -> - ?vlog("got paket from ~w:~w",[Ip,Port]), - NewS = maybe_handle_recv(S, Ip, Port, Packet), - loop(NewS); + {udp, Socket, IpAddr, IpPort, Packet} = Msg when is_port(Socket) -> + ?vlog("got paket from ~w:~w on ~w", [IpAddr, IpPort, Socket]), + case lists:keyfind(Socket, #transport.socket, Transports) of + #transport{socket = Socket, domain = Domain} = Transport -> + From = + case Domain of + snmpUDPDomain -> + {IpAddr, IpPort}; + _ -> + {Domain, {IpAddr, IpPort}} + end, + loop(maybe_handle_recv(S, Transport, From, Packet)); + false -> + error_msg("Packet on unknown port: ~p", [Msg]), + loop(S) + end; {info, ReplyRef, Pid} -> Info = get_info(S), @@ -299,47 +355,78 @@ loop(S) -> loop(S); %% response (to get/get_next/get_bulk/set requests) - {snmp_response, Vsn, RePdu, Type, ACMData, Dest, []} -> + {snmp_response, Vsn, RePdu, Type, ACMData, To, Extra} -> ?vlog("reply pdu: " "~n ~s", [?vapply(snmp_misc, format, [256, "~w", [RePdu]])]), - NewS = maybe_handle_reply_pdu(S, Vsn, RePdu, Type, ACMData, Dest), - loop(NewS); + {_, ReqRef} = lists:keyfind(request_ref, 1, Extra), + case + case + (Limit =/= infinity) andalso + select_transport_from_req_ref(ReqRef, Transports) + of + false -> + select_transport_from_domain( + address_to_domain(To), + Transports); + T -> + T + end + of + false -> + error_msg( + "Can not find transport for response PDU to: ~s", + [format_address(To)]), + loop(S); + Transport -> + NewS = update_req_counter_outgoing(S, Transport, ReqRef), + maybe_handle_reply_pdu( + NewS, Transport, Vsn, RePdu, Type, ACMData, To), + loop(NewS) + end; %% Traps/notification - {send_pdu, Vsn, Pdu, MsgData, To} -> - ?vdebug("send pdu: " - "~n Pdu: ~p" - "~n To: ~p", [Pdu, To]), - NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, undefined), + {send_pdu, Vsn, Pdu, MsgData, TDomAddrs} -> + ?vdebug("send pdu:~n" + " Pdu: ~p~n" + " TDomAddrs: ~p", [Pdu, TDomAddrs]), + NewS = + maybe_handle_send_pdu( + S, Vsn, Pdu, MsgData, TDomAddrs, undefined), loop(NewS); %% We dont use the extra-info at this time, ... - {send_pdu, Vsn, Pdu, MsgData, To, _ExtraInfo} -> - ?vdebug("send pdu: " - "~n Pdu: ~p" - "~n To: ~p", [Pdu, To]), - NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, undefined), + {send_pdu, Vsn, Pdu, MsgData, TDomAddrs, _ExtraInfo} -> + ?vdebug("send pdu:~n" + " Pdu: ~p~n" + " TDomAddrs: ~p", [Pdu, TDomAddrs]), + NewS = + maybe_handle_send_pdu( + S, Vsn, Pdu, MsgData, TDomAddrs, undefined), loop(NewS); %% Informs - {send_pdu_req, Vsn, Pdu, MsgData, To, From} -> - ?vdebug("send pdu request: " - "~n Pdu: ~p" - "~n To: ~p" - "~n From: ~p", - [Pdu, To, toname(From)]), - NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, From), + {send_pdu_req, Vsn, Pdu, MsgData, TDomAddrs, From} -> + ?vdebug("send pdu request:~n" + " Pdu: ~p~n" + " TDomAddrs: ~p~n" + " From: ~p", + [Pdu, TDomAddrs, toname(From)]), + NewS = + maybe_handle_send_pdu( + S, Vsn, Pdu, MsgData, TDomAddrs, From), loop(NewS); %% We dont use the extra-info at this time, ... - {send_pdu_req, Vsn, Pdu, MsgData, To, From, _ExtraInfo} -> - ?vdebug("send pdu request: " - "~n Pdu: ~p" - "~n To: ~p" - "~n From: ~p", - [Pdu, To, toname(From)]), - NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, From), + {send_pdu_req, Vsn, Pdu, MsgData, TDomAddrs, From, _ExtraInfo} -> + ?vdebug("send pdu request:~n" + " Pdu: ~p~n" + " TDomAddrs: ~p~n" + " From: ~p", + [Pdu, TDomAddrs, toname(From)]), + NewS = + maybe_handle_send_pdu( + S, Vsn, Pdu, MsgData, TDomAddrs, From), loop(NewS); %% Discovery Inform @@ -365,15 +452,34 @@ loop(S) -> NewS = handle_send_discovery(S, Pdu, MsgData, To, From), loop(NewS); - {discarded_pdu, _Vsn, ReqId, _ACMData, Variable, _Extra} -> - ?vdebug("discard PDU: ~p", [Variable]), + {discarded_pdu, _Vsn, ReqId, _ACMData, Variable, Extra} -> + ?vdebug("discard PDU: ~p - ~p - ~p", + [Variable, Extra, Transports]), snmpa_mpd:discarded_pdu(Variable), - NewS = update_req_counter_outgoing(S, ReqId), - loop(NewS); + {_, ReqRef} = lists:keyfind(request_ref, 1, Extra), + if + Limit =:= infinity -> + %% The incoming PDU was not registered + loop(update_req_counter_outgoing(S, false, ReqRef)); + true -> + case + select_transport_from_req_ref(ReqRef, Transports) + of + false -> + error_msg( + "Can not find transport for discarded PDU: ~p", + [ReqId]), + loop(S); + Transport -> + loop( + update_req_counter_outgoing( + S, Transport, ReqRef)) + end + end; {get_log_type, ReplyRef, Pid} -> ?vdebug("get log type: ~p", []), - #state{log = {_, LogType}} = S, + {_, LogType} = S#state.log, Pid ! {ReplyRef, {ok, LogType}, self()}, loop(S); @@ -385,7 +491,6 @@ loop(S) -> {get_request_limit, ReplyRef, Pid} -> ?vdebug("get request limit: ~p", []), - #state{limit = Limit} = S, Pid ! {ReplyRef, {ok, Limit}, self()}, loop(S); @@ -409,36 +514,50 @@ loop(S) -> reset_counters(), loop(S); - {'EXIT', Parent, Reason} when Parent == S#state.parent -> + {'EXIT', Parent, Reason} -> ?vlog("parent (~p) exited: " "~n ~p", [Parent, Reason]), exit(Reason); - {'EXIT', Port, Reason} when Port == S#state.usock -> - UDPPort = get_port(), - NewS = - case gen_udp_open(UDPPort, S#state.usock_opts) of - {ok, Id} -> - error_msg("Port ~p exited for reason" - "~n ~p" - "~n Re-opened (~p)", [Port, Reason, Id]), - S#state{usock = Id}; - {error, ReopenReason} -> - error_msg("Port ~p exited for reason" - "~n ~p" - "~n Re-open failed with reason" - "~n ~p", - [Port, Reason, ReopenReason]), - ok - end, - loop(NewS); - - {'EXIT', Port, Reason} when is_port(Port) -> - error_msg("Exit message from port ~p for reason ~p~n", - [Port, Reason]), - loop(S); - - {'EXIT', Pid, Reason} -> + {'EXIT', Socket, Reason} when is_port(Socket) -> + case lists:keyfind(Socket, #transport.socket, Transports) of + #transport{ + socket = Socket, + domain = Domain, + opts = SocketOpts, + req_refs = ReqRefs} = Transport -> + try socket_open(Domain, SocketOpts) of + NewSocket -> + error_msg( + "Socket ~p exited for reason" + "~n ~p" + "~n Re-opened (~p)", + [Socket, Reason, NewSocket]), + (length(ReqRefs) < Limit) andalso + active_once(NewSocket), + S#state{ + transports = + lists:keyreplace( + Socket, #transport.socket, Transports, + Transport#transport{socket = NewSocket})} + catch + ReopenReason -> + error_msg( + "Socket ~p exited for reason" + "~n ~p" + "~n Re-open failed with reason" + "~n ~p", + [Socket, Reason, ReopenReason]), + exit(ReopenReason) + end; + false -> + error_msg( + "Exit message from port ~p for reason ~p~n", + [Socket, Reason]), + loop(S) + end; + + {'EXIT', Pid, Reason} when is_pid(Pid) -> ?vlog("~p exited: " "~n ~p", [Pid, Reason]), NewS = clear_reqs(Pid, S), @@ -446,205 +565,321 @@ loop(S) -> {system, From, Msg} -> ?vdebug("system event ~p from ~p", [Msg, From]), - sys:handle_system_msg(Msg, From, S#state.parent, ?MODULE, [], S); + sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], S); _ -> loop(S) end. -update_req_counter_incomming(#state{limit = infinity, usock = Sock} = S, _) -> - active_once(Sock), %% No limit so activate directly +update_req_counter_incoming( + #state{limit = infinity} = S, + #transport{socket = Socket}, + _ReqRef) -> + active_once(Socket), %% No limit so activate directly S; -update_req_counter_incomming(#state{limit = Limit, - rcnt = RCnt, - usock = Sock} = S, Rid) - when length(RCnt) + 1 == Limit -> +update_req_counter_incoming( + #state{limit = Limit} = S, + #transport{socket = Socket, req_refs = ReqRefs} = T, + ReqRef) when length(ReqRefs) + 1 >= Limit -> %% Ok, one more and we are at the limit. %% Just make sure we are not already processing this one... - case lists:member(Rid, RCnt) of + case lists:member(ReqRef, ReqRefs) of false -> %% We are at the limit, do _not_ activate socket - S#state{rcnt = [Rid|RCnt]}; + update_transport_req_refs(S, T, [ReqRef | ReqRefs]); true -> - active_once(Sock), + active_once(Socket), S end; -update_req_counter_incomming(#state{rcnt = RCnt, - usock = Sock} = S, Rid) -> - active_once(Sock), - case lists:member(Rid, RCnt) of +update_req_counter_incoming( + #state{} = S, + #transport{socket = Socket, req_refs = ReqRefs} = T, + ReqRef) -> + active_once(Socket), + case lists:member(ReqRef, ReqRefs) of false -> - S#state{rcnt = [Rid|RCnt]}; + update_transport_req_refs(S, T, [ReqRef | ReqRefs]); true -> S end. - -update_req_counter_outgoing(#state{limit = infinity} = S, _Rid) -> +update_req_counter_outgoing( + #state{limit = infinity} = S, + _Transport, _ReqRef) -> %% Already activated (in the incoming function) S; -update_req_counter_outgoing(#state{limit = Limit, - rcnt = RCnt, - usock = Sock} = S, Rid) - when length(RCnt) == Limit -> - ?vtrace("handle_req_counter_outgoing(~w) -> entry with" - "~n Rid: ~w" - "~n length(RCnt): ~w", [Limit, Rid, length(RCnt)]), - case lists:delete(Rid, RCnt) of - NewRCnt when length(NewRCnt) < Limit -> +update_req_counter_outgoing( + #state{limit = Limit} = S, + #transport{socket = Socket, req_refs = ReqRefs} = Transport, + ReqRef) -> + LengthReqRefs = length(ReqRefs), + ?vtrace("update_req_counter_outgoing() -> entry with~n" + " Limit: ~w~n" + " ReqRef: ~w~n" + " length(ReqRefs): ~w", [Limit, ReqRef, LengthReqRefs]), + NewReqRefs = lists:delete(ReqRef, ReqRefs), + (LengthReqRefs >= Limit) andalso (length(NewReqRefs) < Limit) andalso + begin ?vtrace("update_req_counter_outgoing -> " - "passed below limit: activate", []), - active_once(Sock), - S#state{rcnt = NewRCnt}; - _ -> - S - end; -update_req_counter_outgoing(#state{limit = Limit, rcnt = RCnt} = S, - Rid) -> - ?vtrace("handle_req_counter_outgoing(~w) -> entry with" - "~n Rid: ~w" - "~n length(RCnt): ~w", [Limit, Rid, length(RCnt)]), - NewRCnt = lists:delete(Rid, RCnt), - S#state{rcnt = NewRCnt}. - - -maybe_handle_recv(#state{usock = Sock, filter = FilterMod} = S, - Ip, Port, Packet) -> - case (catch FilterMod:accept_recv(Ip, Port)) of + "passed below limit: activate", []), + active_once(Socket) + end, + update_transport_req_refs(S, Transport, NewReqRefs). + +update_transport_req_refs( + #state{transports = Transports} = S, + #transport{socket = Socket} = T, + ReqRefs) -> + S#state{ + transports = + lists:keyreplace( + Socket, #transport.socket, Transports, + T#transport{req_refs = ReqRefs})}. + + +maybe_handle_recv( + #state{filter = FilterMod} = S, + #transport{socket = Socket} = Transport, + From, Packet) -> + {From_1, From_2} = From, + case + try FilterMod:accept_recv(From_1, From_2) + catch + Class:Exception -> + error_msg( + "FilterMod:accept_recv(~p, ~p) crashed: ~w:~w~n ~p", + [From_1,From_2,Class,Exception,erlang:get_stacktrace()]), + true + end + of false -> %% Drop the received packet inc(netIfMsgInDrops), - active_once(Sock), + active_once(Socket), S; - _ -> - handle_recv(S, Ip, Port, Packet) + Other -> + case Other of + true -> + ok; + _ -> + error_msg( + "FilterMod:accept_recv(~p, ~p) returned: ~p", + [From_1,From_2,Other]) + end, + handle_recv(S, Transport, From, Packet) end. -handle_discovery_response(_Ip, _Port, #pdu{request_id = ReqId} = Pdu, - ManagerEngineId, - #state{usock = Sock, reqs = Reqs} = S) -> - case lists:keysearch(ReqId, 1, S#state.reqs) of - {value, {_, Pid}} -> - active_once(Sock), - Pid ! {snmp_discovery_response_received, Pdu, ManagerEngineId}, - NReqs = lists:keydelete(ReqId, 1, Reqs), - S#state{reqs = NReqs}; - _ -> - %% Ouch, timeout? resend? - S - end. - -handle_recv(#state{usock = Sock, - mpd_state = MpdState, - note_store = NS, - log = Log} = S, Ip, Port, Packet) -> +handle_recv( + #state{mpd_state = MpdState, note_store = NS, log = Log} = S, + #transport{socket = Socket} = Transport, + From, Packet) -> put(n1, erlang:now()), - LogF = fun(Type, Data) -> - log(Log, Type, Data, Ip, Port) - end, - Domain = snmp_conf:which_domain(Ip), % What the ****... - case (catch snmpa_mpd:process_packet(Packet, - Domain, {Ip, Port}, - MpdState, NS, LogF)) of + LogF = + fun(Type, Data) -> + log(Log, Type, Data, From) + end, + case (catch snmpa_mpd:process_packet( + Packet, From, MpdState, NS, LogF)) of {ok, _Vsn, Pdu, _PduMS, {discovery, ManagerEngineId}} -> - handle_discovery_response(Ip, Port, Pdu, ManagerEngineId, S); + handle_discovery_response( + S, Transport, From, Pdu, ManagerEngineId); {ok, _Vsn, Pdu, _PduMS, discovery} -> - handle_discovery_response(Ip, Port, Pdu, undefined, S); + handle_discovery_response( + S, Transport, From, Pdu, undefined); {ok, Vsn, Pdu, PduMS, ACMData} -> ?vlog("got pdu ~s", [?vapply(snmp_misc, format, [256, "~w", [Pdu]])]), - %% handle_recv_pdu(Ip, Port, Vsn, Pdu, PduMS, ACMData, S); - maybe_handle_recv_pdu(Ip, Port, Vsn, Pdu, PduMS, ACMData, S); + %% handle_recv_pdu(S, Transport, From, Vsn, Pdu, PduMS, ACMData); + maybe_handle_recv_pdu( + S, Transport, From, Vsn, Pdu, PduMS, ACMData); {discarded, Reason} -> ?vlog("packet discarded for reason: ~s", [?vapply(snmp_misc, format, [256, "~w", [Reason]])]), - active_once(Sock), + active_once(Socket), S; {discarded, Reason, ReportPacket} -> ?vlog("sending report for reason: " "~n ~s", [?vapply(snmp_misc, format, [256, "~w", [Reason]])]), - (catch udp_send(S#state.usock, Ip, Port, ReportPacket)), - active_once(Sock), + (catch udp_send(Socket, From, ReportPacket)), + active_once(Socket), S; {discovery, ReportPacket} -> ?vlog("sending discovery report", []), - (catch udp_send(S#state.usock, Ip, Port, ReportPacket)), - active_once(Sock), + (catch udp_send(Socket, From, ReportPacket)), + active_once(Socket), S; Error -> error_msg("processing of received message failed: " "~n ~p", [Error]), - active_once(Sock), + active_once(Socket), S end. - -maybe_handle_recv_pdu(Ip, Port, Vsn, #pdu{type = Type} = Pdu, PduMS, ACMData, - #state{usock = Sock, filter = FilterMod} = S) -> - case (catch FilterMod:accept_recv_pdu(Ip, Port, Type)) of + +handle_discovery_response( + #state{reqs = Reqs} = S, + #transport{socket = Socket}, + _From, + #pdu{request_id = ReqId} = Pdu, + ManagerEngineId) -> + case lists:keyfind(ReqId, 1, S#state.reqs) of + {ReqId, Pid} -> + active_once(Socket), + Pid ! {snmp_discovery_response_received, Pdu, ManagerEngineId}, + %% XXX Strange... Reqs from this Pid should be reaped + %% at process exit by clear_reqs/2 so the following + %% should be redundant. + NReqs = lists:keydelete(ReqId, 1, Reqs), + S#state{reqs = NReqs}; + false -> + %% Ouch, timeout? resend? + S + end. + +maybe_handle_recv_pdu( + #state{filter = FilterMod} = S, + #transport{socket = Socket} = Transport, + From, Vsn, + #pdu{type = Type} = Pdu, PduMS, ACMData) -> + {From_1, From_2} = From, + case + try FilterMod:accept_recv_pdu(From_1, From_2, Type) + catch + Class:Exception -> + error_msg( + "FilterMod:accept_recv_pdu(~p, ~p, ~p) crashed: ~w:~w~n" + " ~p", + [From_1,From_2,Type,Class,Exception, + erlang:get_stacktrace()]), + true + end + of false -> inc(netIfPduInDrops), - active_once(Sock), - ok; - _ -> - handle_recv_pdu(Ip, Port, Vsn, Pdu, PduMS, ACMData, S) - end; -maybe_handle_recv_pdu(Ip, Port, Vsn, Pdu, PduMS, ACMData, S) -> - handle_recv_pdu(Ip, Port, Vsn, Pdu, PduMS, ACMData, S). + active_once(Socket), + S; + Other -> + case Other of + true -> + ok; + _ -> + error_msg( + "FilterMod:accept_recv_pdu(~p, ~p, ~p) returned: ~p", + [From_1,From_2,Type,Other]) + end, + handle_recv_pdu(S, Transport, From, Vsn, Pdu, PduMS, ACMData) + end. -handle_recv_pdu(Ip, Port, Vsn, #pdu{type = 'get-response'} = Pdu, - _PduMS, _ACMData, #state{usock = Sock} = S) -> - active_once(Sock), - handle_response(Vsn, Pdu, {Ip, Port}, S), +handle_recv_pdu( + #state{reqs = Reqs} = S, + #transport{socket = Socket}, + From, Vsn, + #pdu{type = 'get-response', request_id = ReqId} = Pdu, + _PduMS, _ACMData) -> + active_once(Socket), + case lists:keyfind(ReqId, 1, Reqs) of + {ReqId, Pid} -> + ?vdebug("handle_recv_pdu -> " + "~n send response to receiver ~p", [Pid]), + Pid ! {snmp_response_received, Vsn, Pdu, From}; + false -> + ?vdebug("handle_recv_pdu -> " + "~n No receiver available for response pdu", []) + end, S; -handle_recv_pdu(Ip, Port, Vsn, #pdu{request_id = Rid, type = Type} = Pdu, - PduMS, ACMData, #state{master_agent = Pid} = S) - when ((Type =:= 'get-request') orelse - (Type =:= 'get-next-request') orelse - (Type =:= 'get-bulk-request')) -> - ?vtrace("handle_recv_pdu -> received get (~w)", [Type]), - Pid ! {snmp_pdu, Vsn, Pdu, PduMS, ACMData, {Ip, Port}, []}, - update_req_counter_incomming(S, Rid); -handle_recv_pdu(Ip, Port, Vsn, Pdu, PduMS, ACMData, - #state{usock = Sock, master_agent = Pid} = S) -> +handle_recv_pdu( + #state{master_agent = Pid} = S, + #transport{} = Transport, + From, Vsn, + #pdu{type = Type} = Pdu, + PduMS, ACMData) + when Type =:= 'set-request'; + Type =:= 'get-request'; + Type =:= 'get-next-request'; + Type =:= 'get-bulk-request' -> + ?vtrace("handle_recv_pdu -> received request (~w)", [Type]), + ReqRef = make_ref(), + Extra = [{request_ref, ReqRef}], + Pid ! {snmp_pdu, Vsn, Pdu, PduMS, ACMData, From, Extra}, + NewS = update_req_counter_incoming(S, Transport, ReqRef), + ?vdebug("handle_recv_pdu -> ~p", [NewS]), + NewS; +handle_recv_pdu( + #state{master_agent = Pid} = S, + #transport{socket = Socket}, + From, Vsn, Pdu, PduMS, ACMData) -> ?vtrace("handle_recv_pdu -> received other request", []), - active_once(Sock), - Pid ! {snmp_pdu, Vsn, Pdu, PduMS, ACMData, {Ip, Port}, []}, + active_once(Socket), + Pid ! {snmp_pdu, Vsn, Pdu, PduMS, ACMData, From, []}, S. -maybe_handle_reply_pdu(#state{filter = FilterMod} = S, Vsn, - #pdu{request_id = Rid} = Pdu, - Type, ACMData, {Ip, Port} = Dest) -> - S1 = update_req_counter_outgoing(S, Rid), - case (catch FilterMod:accept_send_pdu([{Ip, Port}], Type)) of +maybe_handle_reply_pdu( + #state{filter = FilterMod, transports = Transports} = S, + #transport{} = Transport, + Vsn, + #pdu{} = Pdu, + Type, ACMData, To) -> + %% + Addresses = [fix_filter_address(Transports, To)], + case + try + FilterMod:accept_send_pdu(Addresses, Type) + catch + Class:Exception -> + error_msg( + "FilterMod:accept_send_pdu(~p, ~p) crashed: ~w:~w~n ~p", + [Addresses, Type, Class, Exception, + erlang:get_stacktrace()]), + true + end + of false -> inc(netIfPduOutDrops), ok; - _ -> - handle_reply_pdu(S1, Vsn, Pdu, Type, ACMData, Dest) - end, - S1. - -handle_reply_pdu(#state{log = Log, - usock = Sock, - filter = FilterMod}, - Vsn, Pdu, Type, ACMData, {Ip, Port}) -> - LogF = fun(Type2, Data) -> - log(Log, Type2, Data, Ip, Port) - end, + Other -> + case Other of + true -> + ok; + _ -> + error_msg( + "FilterMod:accept_send_pdu(~p, ~p) returned: ~p", + [Addresses,Type,Other]) + end, + handle_reply_pdu(S, Transport, Vsn, Pdu, Type, ACMData, To) + end. + +handle_reply_pdu( + #state{log = Log} = S, + #transport{} = Transport, + Vsn, + #pdu{} = Pdu, + Type, ACMData, To) -> + %% + LogF = + fun(Type2, Data) -> + log(Log, Type2, Data, To) + end, case (catch snmpa_mpd:generate_response_msg(Vsn, Pdu, Type, ACMData, LogF)) of {ok, Packet} -> ?vinfo("time in agent: ~w mysec", [time_in_agent()]), - maybe_udp_send(FilterMod, Sock, Ip, Port, Packet); + try maybe_udp_send(S, Transport, To, Packet) + catch + {Reason, Sz} -> + error_msg("Cannot send message " + "~n size: ~p" + "~n reason: ~p" + "~n pdu: ~p", + [Sz, Reason, Pdu]) + end; {discarded, Reason} -> ?vlog("handle_reply_pdu -> " "~n reply discarded for reason: ~s", @@ -652,105 +887,116 @@ handle_reply_pdu(#state{log = Log, ok; {'EXIT', Reason} -> user_err("failed generating response message: " - "~nPDU: ~w~n~w", [Pdu, Reason]) + "~nPDU: ~p~n~p", [Pdu, Reason]) end. - -process_taddrs(To) -> - process_taddrs(To, []). -process_taddrs([], Acc) -> - lists:reverse(Acc); -%% v3 -process_taddrs([{{_Domain, AddrAndPort}, _SecData}|T], Acc) -> - process_taddrs(T, [AddrAndPort|Acc]); -%% v1 & v2 -process_taddrs([{_Domain, AddrAndPort}|T], Acc) -> - process_taddrs(T, [AddrAndPort|Acc]). -merge_taddrs(To1, To2) -> - merge_taddrs(To1, To2, []). +maybe_handle_send_pdu( + #state{filter = FilterMod, transports = Transports} = S, + Vsn, Pdu, MsgData, TDomAddrSecs, From) -> -merge_taddrs([], _To2, Acc) -> - lists:reverse(Acc); -%% v3 -merge_taddrs([{{_, AddrAndPort}, _} = H|To1], To2, Acc) -> - case lists:member(AddrAndPort, To2) of - true -> - merge_taddrs(To1, To2, [H|Acc]); - false -> - merge_taddrs(To1, To2, Acc) - end; -%% v1 & v2 -merge_taddrs([{_, AddrAndPort} = H|To1], To2, Acc) -> - case lists:member(AddrAndPort, To2) of - true -> - merge_taddrs(To1, To2, [H|Acc]); - false -> - merge_taddrs(To1, To2, Acc) - end; -merge_taddrs([_Crap|To1], To2, Acc) -> - merge_taddrs(To1, To2, Acc). - - -maybe_handle_send_pdu(#state{filter = FilterMod} = S, - Vsn, Pdu, MsgData, To0, From) -> + ?vtrace("maybe_handle_send_pdu -> entry with~n" + " FilterMod: ~p~n" + " TDomAddrSecs: ~p", [FilterMod, TDomAddrSecs]), - ?vtrace("maybe_handle_send_pdu -> entry with" - "~n FilterMod: ~p" - "~n To0: ~p", [FilterMod, To0]), - - To1 = snmpa_mpd:process_taddrs(To0), - To2 = process_taddrs(To1), + DomAddrSecs = snmpa_mpd:process_taddrs(TDomAddrSecs), + AddressesToFilter = + case is_legacy_transports(Transports) of + true -> + [fix_filter_legacy_mpd_address(DAS) + || DAS <- DomAddrSecs]; + false -> + [fix_filter_mpd_address(DAS) + || DAS <- DomAddrSecs] + end, - case (catch FilterMod:accept_send_pdu(To2, pdu_type_of(Pdu))) of + Type = pdu_type_of(Pdu), + + case + try FilterMod:accept_send_pdu(AddressesToFilter, Type) + catch + Class:Exception -> + error_msg( + "FilterMod:accept_send_pdu(~p, ~p) crashed: ~w:~w~n ~p", + [AddressesToFilter,Type, + Class,Exception,erlang:get_stacktrace()]), + true + end + of false -> inc(netIfPduOutDrops), ok; true -> - handle_send_pdu(S, Vsn, Pdu, MsgData, To1, From); - To3 when is_list(To3) -> - To4 = merge_taddrs(To1, To3), - ?vtrace("maybe_handle_send_pdu -> To4: " - "~n ~p", [To4]), - handle_send_pdu(S, Vsn, Pdu, MsgData, To4, From); - _ -> - handle_send_pdu(S, Vsn, Pdu, MsgData, To1, From) + handle_send_pdu(S, Vsn, Pdu, MsgData, DomAddrSecs, From); + FilteredAddresses when is_list(FilteredAddresses) -> + FilteredDomAddrSecs = + case is_legacy_transports(Transports) of + true -> + [DAS || + DAS <- DomAddrSecs, + lists:member( + fix_filter_legacy_mpd_address(DAS), + FilteredAddresses)]; + false -> + [DAS || + DAS <- DomAddrSecs, + lists:member( + fix_filter_mpd_address(DAS), + FilteredAddresses)] + end, + ?vtrace("maybe_handle_send_pdu -> FilteredDomAddrSecs:~n" + " ~p", [FilteredDomAddrSecs]), + handle_send_pdu(S, Vsn, Pdu, MsgData, FilteredDomAddrSecs, From); + Other -> + error_msg( + "FilterMod:accept_send_pdu(~p, ~p) returned: ~p", + [AddressesToFilter,Type,Other]), + handle_send_pdu(S, Vsn, Pdu, MsgData, DomAddrSecs, From) end. -handle_send_pdu(#state{note_store = NS} = S, Vsn, Pdu, MsgData, To, From) -> - - ?vtrace("handle_send_pdu -> entry with" - "~n Pdu: ~p" - "~n To: ~p", [Pdu, To]), +handle_send_pdu( + #state{note_store = NS} = S, + Vsn, Pdu, MsgData, DomAddrSecs, From) -> + %% + ?vtrace("handle_send_pdu -> entry with~n" + " Pdu: ~p~n" + " DomAddrSecs: ~p", [Pdu, DomAddrSecs]), - case (catch snmpa_mpd:generate_msg(Vsn, NS, Pdu, MsgData, To)) of + case (catch snmpa_mpd:generate_msg( + Vsn, NS, Pdu, MsgData, DomAddrSecs)) of {ok, Addresses} -> - handle_send_pdu(S, Pdu, Addresses); + do_handle_send_pdu(S, Pdu, Addresses); {discarded, Reason} -> ?vlog("handle_send_pdu -> " "~n PDU ~p not sent due to ~p", [Pdu, Reason]), ok; {'EXIT', Reason} -> user_err("failed generating message: " - "~nPDU: ~w~n~w", [Pdu, Reason]), + "~nPDU: ~p~n~p", [Pdu, Reason]), ok end, case From of undefined -> S; - Pid -> + Pid when is_pid(Pid) -> ?vtrace("link to ~p and add to request list", [Pid]), link(Pid), - NReqs = snmp_misc:keyreplaceadd(Pid, 2, S#state.reqs, - {Pdu#pdu.request_id, From}), + NReqs = + snmp_misc:keyreplaceadd( + Pid, 2, S#state.reqs, {Pdu#pdu.request_id, From}), S#state{reqs = NReqs} end. -handle_send_discovery(#state{note_store = NS} = S, - Pdu, MsgData, - To, From) -> +handle_send_discovery( + #state{ + note_store = NS, + log = Log, + reqs = Reqs, + transports = Transports} = S, + #pdu{type = Type, request_id = ReqId} = Pdu, + MsgData, To, From) when is_pid(From) -> ?vtrace("handle_send_discovery -> entry with" "~n Pdu: ~p" @@ -759,155 +1005,173 @@ handle_send_discovery(#state{note_store = NS} = S, "~n From: ~p", [Pdu, MsgData, To, From]), case (catch snmpa_mpd:generate_discovery_msg(NS, Pdu, MsgData, To)) of - {ok, {Packet, {Ip, Port}}} -> - handle_send_discovery(S, Pdu, Packet, Ip, Port, From); + {ok, {Domain, Address, Packet}} -> + case select_transport_from_domain(Domain, Transports) of + false -> + error_msg( + "Can not find transport to: ~s", + [format_address(To)]), + S; + #transport{socket = Socket} -> + log(Log, Type, Packet, {Domain, Address}), + udp_send(Socket, {Domain, Address}, Packet), + ?vtrace("handle_send_discovery -> sent (~w)", [ReqId]), + NReqs = snmp_misc:keyreplaceadd(From, 2, Reqs, {ReqId, From}), + S#state{reqs = NReqs} + end; {discarded, Reason} -> ?vlog("handle_send_discovery -> " "~n Discovery PDU ~p not sent due to ~p", [Pdu, Reason]), - ok; + S; {'EXIT', Reason} -> user_err("failed generating discovery message: " - "~n PDU: ~w" - "~n Reason: ~w", [Pdu, Reason]), - ok + "~n PDU: ~p" + "~n Reason: ~p", [Pdu, Reason]), + S end. -handle_send_discovery(#state{log = Log, - usock = Sock, - reqs = Reqs} = S, - #pdu{type = Type, - request_id = ReqId}, - Packet, Ip, Port, From) - when is_binary(Packet) -> - log(Log, Type, Packet, Ip, Port), - udp_send(Sock, Ip, Port, Packet), - ?vtrace("handle_send_discovery -> sent (~w)", [ReqId]), - NReqs = snmp_misc:keyreplaceadd(From, 2, Reqs, {ReqId, From}), - S#state{reqs = NReqs}. +do_handle_send_pdu(S, #pdu{type = Type} = Pdu, Addresses) -> + do_handle_send_pdu(S, Type, Pdu, Addresses); +do_handle_send_pdu(S, Trap, Addresses) -> + do_handle_send_pdu(S, trappdu, Trap, Addresses). -handle_send_pdu(S, #pdu{type = Type} = Pdu, Addresses) -> - handle_send_pdu(S, Type, Pdu, Addresses); -handle_send_pdu(S, Trap, Addresses) -> - handle_send_pdu(S, trappdu, Trap, Addresses). - -handle_send_pdu(S, Type, Pdu, Addresses) -> - case (catch handle_send_pdu1(S, Type, Addresses)) of +do_handle_send_pdu(S, Type, Pdu, Addresses) -> + try do_handle_send_pdu1(S, Type, Addresses) + catch {Reason, Sz} -> - error_msg("Cannot send message " - "~n size: ~p" - "~n reason: ~p" - "~n pdu: ~p", - [Sz, Reason, Pdu]); - _ -> - ok - end. - -handle_send_pdu1(#state{log = Log, - usock = Sock, - filter = FilterMod}, Type, Addresses) -> - SendFun = - fun({snmpUDPDomain, {Ip, Port}, Packet}) - when is_binary(Packet) -> - ?vdebug("[snmpUDPDomain] sending packet:" - "~n size: ~p" - "~n to: ~p:~p", - [sz(Packet), Ip, Port]), - maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); - - ({snmpUDPDomain, {Ip, Port}, {Packet, _LogData}}) - when is_binary(Packet) -> - ?vdebug("[snmpUDPDomain] sending encrypted packet:" - "~n size: ~p" - "~n to: ~p:~p", - [sz(Packet), Ip, Port]), - maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); - - ({transportDomainUdpIpv4, {Ip, Port}, Packet}) - when is_binary(Packet) -> - ?vdebug("[transportDomainUdpIpv4] sending packet:" - "~n size: ~p" - "~n to: ~p:~p", - [sz(Packet), Ip, Port]), - maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); - - ({transportDomainUdpIpv4, {Ip, Port}, {Packet, _LogData}}) - when is_binary(Packet) -> - ?vdebug("[transportDomainUdpIpv4] sending encrypted packet:" - "~n size: ~p" - "~n to: ~p:~p", - [sz(Packet), Ip, Port]), - maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); - - ({transportDomainUdpIpv6, {Ip, Port}, Packet}) - when is_binary(Packet) -> - ?vdebug("[transportDomainUdpIpv6] sending packet:" - "~n size: ~p" - "~n to: ~p:~p", - [sz(Packet), Ip, Port]), - maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); - - ({transportDomainUdpIpv6, {Ip, Port}, {Packet, _LogData}}) - when is_binary(Packet) -> - ?vdebug("[transportDomainUdpIpv6] sending encrypted packet:" - "~n size: ~p" - "~n to: ~p:~p", - [sz(Packet), Ip, Port]), - maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); - - (_X) -> - ?vlog("** bad res: ~p", [_X]), - ok - end, - lists:foreach(SendFun, Addresses). - - -handle_response(Vsn, Pdu, From, S) -> - case lists:keysearch(Pdu#pdu.request_id, 1, S#state.reqs) of - {value, {_, Pid}} -> - ?vdebug("handle_response -> " - "~n send response to receiver ~p", [Pid]), - Pid ! {snmp_response_received, Vsn, Pdu, From}; - _ -> - ?vdebug("handle_response -> " - "~n No receiver available for response pdu", []) + error_msg( + "Can not send message~n" + " size: ~p~n" + " reason: ~p~n" + " pdu: ~p", + [Sz, Reason, Pdu]) end. -maybe_udp_send(FilterMod, Sock, Ip, Port, Packet) -> - case (catch FilterMod:accept_send(Ip, Port)) of +do_handle_send_pdu1( + #state{transports = Transports} = S, + Type, Addresses) -> + lists:foreach( + fun ({Domain, Address, Packet}) when is_binary(Packet) -> + ?vdebug( + "[~w] sending packet:~n" + " size: ~p~n" + " to: ~p", [Domain, sz(Packet), Address]), + To = {Domain, Address}, + case select_transport_from_domain(Domain, Transports) of + false -> + error_msg( + "Can not find transport~n" + " size: ~p~n" + " to: ~s", + [sz(Packet), format_address(To)]); + Transport -> + maybe_udp_send(S, Transport, To, Packet) + end; + ({Domain, Address, {Packet, LogData}}) when is_binary(Packet) -> + ?vdebug( + "[~w] sending encrypted packet:~n" + " size: ~p~n" + " to: ~p", [Domain, sz(Packet), Address]), + To = {Domain, Address}, + case select_transport_from_domain(Domain, Transports) of + false -> + error_msg( + "Can not find transport~n" + " size: ~p~n" + " to: ~s", + [sz(Packet), format_address(To)]); + Transport -> + maybe_udp_send(S, Transport, To, Packet, Type, LogData) + end + end, + Addresses). + +maybe_udp_send( + #state{filter = FilterMod, transports = Transports}, + #transport{socket = Socket}, + To, Packet) -> + {To_1, To_2} = fix_filter_address(Transports, To), + case + try FilterMod:accept_send(To_1, To_2) + catch + Class:Exception -> + error_msg( + "FilterMod:accept_send(~p, ~p) crashed: ~w:~w~n ~p", + [To_1,To_2,Class,Exception,erlang:get_stacktrace()]), + true + end + of false -> inc(netIfMsgOutDrops), ok; - _ -> - (catch udp_send(Sock, Ip, Port, Packet)) + Other -> + case Other of + true -> + ok; + _ -> + error_msg( + "FilterMod:accept_send(~p, ~p) returned: ~p", + [To_1,To_2,Other]) + end, + udp_send(Socket, To, Packet) end. -maybe_udp_send(FilterMod, AtLog, Type, Sock, Ip, Port, Packet) -> - case (catch FilterMod:accept_send(Ip, Port)) of +maybe_udp_send( + #state{log = Log, filter = FilterMod, transports = Transports}, + #transport{socket = Socket}, + To, Packet, Type, _LogData) -> + {To_1, To_2} = fix_filter_address(Transports, To), + case + try FilterMod:accept_send(To_1, To_2) + catch + Class:Exception -> + error_msg( + "FilterMod:accept_send(~p, ~p) crashed for: ~w:~w~n ~p", + [To_1, To_2, Class, Exception, erlang:get_stacktrace()]), + true + end + of false -> inc(netIfMsgOutDrops), ok; - _ -> - log(AtLog, Type, Packet, Ip, Port), - (catch udp_send(Sock, Ip, Port, Packet)) + Other -> + case Other of + true -> + ok; + _ -> + error_msg( + "FilterMod:accept_send(~p, ~p) returned: ~p", + [To_1,To_2,Other]) + end, + log(Log, Type, Packet, To), + udp_send(Socket, To, Packet) end. - -udp_send(UdpId, AgentIp, UdpPort, B) -> - case (catch gen_udp:send(UdpId, AgentIp, UdpPort, B)) of +udp_send(Socket, To, B) -> + {IpAddr, IpPort} = + case To of + {Domain, Addr} when is_atom(Domain) -> + Addr; + {_, P} = Addr when is_integer(P) -> + Addr + end, + try gen_udp:send(Socket, IpAddr, IpPort, B) of {error, emsgsize} -> %% From this message we cannot recover, so exit sending loop throw({emsgsize, sz(B)}); {error, ErrorReason} -> error_msg("[error] cannot send message " "(destination: ~p:~p, size: ~p, reason: ~p)", - [AgentIp, UdpPort, sz(B), ErrorReason]); - {'EXIT', ExitReason} -> - error_msg("[exit] cannot send message " - "(destination: ~p:~p, size: ~p, reason: ~p)", - [AgentIp, UdpPort, sz(B), ExitReason]); - _ -> + [IpAddr, IpPort, sz(B), ErrorReason]); + ok -> ok + catch + error:ExitReason -> + error_msg("[exit] cannot send message " + "(destination: ~p:~p, size: ~p, reason: ~p, at: ~p)", + [IpAddr, IpPort, sz(B), ExitReason, + erlang:get_stacktrace()]) end. sz(L) when is_list(L) -> length(L); @@ -957,6 +1221,75 @@ active_once(Sock) -> inet:setopts(Sock, [{active, once}]). +select_transport_from_req_ref(_, []) -> + false; +select_transport_from_req_ref( + ReqRef, + [#transport{req_refs = ReqRefs} = Transport | Transports]) -> + case lists:member(ReqRef, ReqRefs) of + true -> + Transport; + false -> + select_transport_from_req_ref(ReqRef, Transports) + end. + +select_transport_from_domain(Domain, Transports) when is_atom(Domain) -> + Pos = #transport.domain, + case lists:keyfind(Domain, Pos, Transports) of + #transport{domain = Domain} = Transport -> + Transport; + false when Domain == snmpUDPDomain -> + lists:keyfind(transportDomainUdpIpv4, Pos, Transports); + false when Domain == transportDomainUdpIpv4 -> + lists:keyfind(snmpUDPDomain, Pos, Transports); + false -> + false + end. + +address_to_domain({Domain, _Addr}) when is_atom(Domain) -> + Domain; +address_to_domain({_Ip, Port}) when is_integer(Port) -> + snmpUDPDomain. + +%% If the agent uses legacy snmpUDPDomain e.g has not set +%% intAgentTransportDomain, then make sure +%% snmpa_network_interface_filter gets legacy arguments +%% to not break backwards compatibility. +%% +fix_filter_address(Transports, Address) -> + case is_legacy_transports(Transports) of + true -> + case Address of + {Domain, Addr} when is_atom(Domain) -> + Addr; + {_, IpPort} = Addr when is_integer(IpPort) -> + Addr + end; + false -> + Address + end. + +is_legacy_transports([#transport{domain = snmpUDPDomain}]) -> + true; +is_legacy_transports([#transport{} | _]) -> + false. + +fix_filter_legacy_mpd_address(Domain_Address_SecData) -> + case Domain_Address_SecData of + {{Domain, Addr}, _SecData} when is_atom(Domain) -> % v3 + Addr; + {Domain, Addr} when is_atom(Domain) -> % v1 & v2 + Addr + end. + +fix_filter_mpd_address(Domain_Address_SecData) -> + case Domain_Address_SecData of + {{Domain, _Addr} = Address, _SecData} when is_atom(Domain) -> % v3 + Address; + {Domain, _Addr} = Address when is_atom(Domain) -> % v1 & v2 + Address + end. + %%%----------------------------------------------------------------- handle_set_log_type(#state{log = {Log, OldValue}} = State, NewType) @@ -1113,37 +1446,39 @@ get_counters([Counter|Counters], Acc) -> %% ---------------------------------------------------------------- -ip_opt_bind_to_ip_address(Opts, Ip) -> - case get_bind_to_ip_address(Opts) of - true -> - [{ip, list_to_tuple(Ip)}]; - _ -> - [] - end. - -ip_opt_no_reuse_address(Opts) -> - case get_no_reuse_address(Opts) of - false -> - [{reuseaddr, true}]; - _ -> - [] - end. - -ip_opt_recbuf(Opts) -> - case get_recbuf(Opts) of - use_default -> - []; - Sz -> - [{recbuf, Sz}] - end. - -ip_opt_sndbuf(Opts) -> - case get_sndbuf(Opts) of - use_default -> - []; - Sz -> - [{sndbuf, Sz}] - end. +socket_opts(Domain, {IpAddr, IpPort}, Opts) -> + [IpPort, % Picked off at socket open, separate argument + binary + | case snmp_conf:tdomain_to_family(Domain) of + inet6 = Family -> + [Family, {ipv6_v6only, true}]; + Family -> + [Family] + end ++ + case get_bind_to_ip_address(Opts) of + true -> + [{ip, IpAddr}]; + _ -> + [] + end ++ + case get_no_reuse_address(Opts) of + false -> + [{reuseaddr, true}]; + _ -> + [] + end ++ + case get_recbuf(Opts) of + use_default -> + []; + Sz -> + [{recbuf, Sz}] + end ++ + case get_sndbuf(Opts) of + use_default -> + []; + Sz -> + [{sndbuf, Sz}] + end]. %% ---------------------------------------------------------------- @@ -1203,6 +1538,9 @@ get_bind_to_ip_address(Opts) -> error_msg(F,A) -> ?snmpa_error("NET-IF server: " ++ F, A). +info_msg(F,A) -> + ?snmpa_info("NET-IF server: " ++ F, A). + %% --- user_err(F, A) -> @@ -1227,14 +1565,14 @@ call(Pid, Req) -> %% ---------------------------------------------------------------- -get_info(#state{usock = Id, reqs = Reqs}) -> +get_info(#state{transports = Transports, reqs = Reqs}) -> ProcSize = proc_mem(self()), - PortInfo = get_port_info(Id), Counters = get_counters(), - [{reqs, Reqs}, - {counters, Counters}, - {process_memory, ProcSize}, - {port_info, PortInfo}]. + [{reqs, Reqs}, + {counters, Counters}, + {process_memory, ProcSize} + | [{port_info, get_port_info(Socket)} + || #transport{socket = Socket} <- Transports]]. proc_mem(P) when is_pid(P) -> case (catch erlang:process_info(P, memory)) of diff --git a/lib/snmp/src/agent/snmpa_net_if_filter.erl b/lib/snmp/src/agent/snmpa_net_if_filter.erl index 989f7c95b3..dd77b143d0 100644 --- a/lib/snmp/src/agent/snmpa_net_if_filter.erl +++ b/lib/snmp/src/agent/snmpa_net_if_filter.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. 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 @@ -18,35 +18,49 @@ %% -module(snmpa_net_if_filter). --export([accept_recv/2, - accept_send/2, - accept_recv_pdu/3, - accept_send_pdu/2]). +%% Behaviour +-export([accept_recv/2, accept_send/2, accept_recv_pdu/3, accept_send_pdu/2]). -include("snmp_debug.hrl"). -accept_recv(_Addr, _Port) -> - ?d("accept_recv -> entry with" - "~n Addr: ~p" - "~n Port: ~p", [_Addr, _Port]), +accept_recv(Domain, _Address) when is_atom(Domain) -> + ?d("accept_recv -> entry with~n" + " Domain: ~p~n" + " Address: ~p", [Domain, _Address]), + true; +accept_recv(_Addr, Port) when is_integer(Port) -> + ?d("accept_recv -> entry with~n" + " Addr: ~p~n" + " Port: ~p", [_Addr, Port]), true. -accept_send(_Addr, _Port) -> - ?d("accept_send -> entry with" - "~n Addr: ~p" - "~n Port: ~p", [_Addr, _Port]), +accept_send(Domain, _Address) when is_atom(Domain) -> + ?d("accept_send -> entry with~n" + " Domain: ~p~n" + " Address: ~p", [Domain, _Address]), + true; +accept_send(_Addr, Port) when is_integer(Port) -> + ?d("accept_send -> entry with~n" + " Addr: ~p~n" + " Port: ~p", [_Addr, Port]), true. -accept_recv_pdu(_Addr, _Port, _PduType) -> - ?d("accept_recv_pdu -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n PduType: ~p", [_Addr, _Port, _PduType]), +accept_recv_pdu(Domain, _Address, _PduType) when is_atom(Domain) -> + ?d("accept_recv -> entry with~n" + " Domain: ~p~n" + " Address: ~p~n" + " PduType: ~p", [Domain, _Address, _PduType]), + true; +accept_recv_pdu(_Addr, Port, _PduType) when is_integer(Port) -> + ?d("accept_recv_pdu -> entry with~n" + " Addr: ~p~n" + " Port: ~p~n" + " PduType: ~p", [_Addr, Port, _PduType]), true. accept_send_pdu(_Targets, _PduType) -> - ?d("accept_send_pdu -> entry with" - "~n Targets: ~p" - "~n PduType: ~p", [_Targets, _PduType]), + ?d("accept_send_pdu -> entry with~n" + " Targets: ~p~n" + " PduType: ~p", [_Targets, _PduType]), true. diff --git a/lib/snmp/src/agent/snmpa_network_interface_filter.erl b/lib/snmp/src/agent/snmpa_network_interface_filter.erl index 6fa131beee..90aa54a271 100644 --- a/lib/snmp/src/agent/snmpa_network_interface_filter.erl +++ b/lib/snmp/src/agent/snmpa_network_interface_filter.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. 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 @@ -23,7 +23,7 @@ behaviour_info(callbacks) -> - [{accept_recv, 2}, + [{accept_recv, 2}, {accept_send, 2}, {accept_recv_pdu, 3}, {accept_send_pdu, 2}]; @@ -31,20 +31,21 @@ behaviour_info(_) -> undefined. -%% accept_recv(address(), port()) -> boolean() +%% accept_recv({domain(), address()}) -> boolean() %% Called at the receiption of a message %% (before *any* processing has been done). %% -%% accept_send(address(), port()) -> boolean() +%% accept_send({domain(), address()}) -> boolean() %% Called before the sending of a message %% (after *all* processing has been done). %% -%% accept_recv_pdu(Addr, Port, pdu_type()) -> boolean() +%% accept_recv_pdu({domain(), address()}, pdu_type()) -> boolean() %% Called after the basic message processing (MPD) has been done, %% but before the pdu is handed over to the master-agent for %% primary processing. %% -%% accept_send_pdu(Targets, pdu_type()) -> boolean() | NewTargets +%% accept_send_pdu([{domain(), address()}, ...] = Targets, pdu_type()) -> +%% boolean() | NewTargets %% Called before the basic message processing (MPD) is done, %% when a pdu has been received from the master-agent. %% diff --git a/lib/snmp/src/agent/snmpa_trap.erl b/lib/snmp/src/agent/snmpa_trap.erl index b9a2496341..a79b150f57 100644 --- a/lib/snmp/src/agent/snmpa_trap.erl +++ b/lib/snmp/src/agent/snmpa_trap.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -270,12 +270,13 @@ localise_type({VariableOid, Value}, Mib) when is_list(VariableOid) -> localise_type(X, _) -> X. %%----------------------------------------------------------------- -%% Func: make_v1_trap_pdu/4 +%% Func: make_v1_trap_pdu/5 %% Args: Enterprise = oid() %% Specific = integer() %% Varbinds is as returned from initiate_vars %% (but only {Oid, Type[, Value} permitted) %% SysUpTime = integer() +%% AgentIp = {A, B, C, D} %% Purpose: Make a #trappdu %% Checks the Varbinds to see that no symbolic names are %% present, and that each var has a type. Performs a get @@ -284,7 +285,7 @@ localise_type(X, _) -> X. %% Fails: yes %% NOTE: Executed at the MA %%----------------------------------------------------------------- -make_v1_trap_pdu(Enterprise, Specific, VarbindList, SysUpTime) -> +make_v1_trap_pdu(Enterprise, Specific, VarbindList, SysUpTime, AgentIp) -> {Enterp,Generic,Spec} = case Enterprise of ?snmp -> @@ -292,7 +293,6 @@ make_v1_trap_pdu(Enterprise, Specific, VarbindList, SysUpTime) -> _ -> {Enterprise,?enterpriseSpecific,Specific} end, - {value, AgentIp} = snmp_framework_mib:intAgentIpAddress(get), #trappdu{enterprise = Enterp, agent_addr = AgentIp, generic_trap = Generic, @@ -369,6 +369,7 @@ send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, {tag, T}, {err, E}, {stacktrace, erlang:get_stacktrace()}], + ?vlog("snmpa_trap:send_trap exception: ~p", [Info]), {error, {failed_sending_trap, Info}} end. @@ -789,23 +790,19 @@ send_trap_pdus([], ContextName, {TrapRec, Vbs}, send_v1_trap(_TrapRec, [], _Vbs, _ExtraInfo, _NetIf, _SysUpTime) -> ok; -send_v1_trap(#trap{enterpriseoid = Enter, specificcode = Spec}, - V1Res, Vbs, ExtraInfo, NetIf, SysUpTime) -> +send_v1_trap( + #trap{enterpriseoid = Enter, specificcode = Spec}, + V1Res, Vbs, ExtraInfo, NetIf, SysUpTime) -> ?vdebug("prepare to send v1 trap " "~n '~p'" "~n with" "~n ~p" "~n to" "~n ~p", [Enter, Spec, V1Res]), - TrapPdu = make_v1_trap_pdu(Enter, Spec, Vbs, SysUpTime), - AddrCommunities = mk_addr_communities(V1Res), - lists:foreach(fun({Community, Addrs}) -> - ?vtrace("send v1 trap pdu to ~p",[Addrs]), - NetIf ! {send_pdu, 'version-1', TrapPdu, - {community, Community}, Addrs, ExtraInfo} - end, AddrCommunities); -send_v1_trap(#notification{oid = Oid}, V1Res, Vbs, ExtraInfo, NetIf, - SysUpTime) -> + do_send_v1_trap(Enter, Spec, V1Res, Vbs, ExtraInfo, NetIf, SysUpTime); +send_v1_trap( + #notification{oid = Oid}, + V1Res, Vbs, ExtraInfo, NetIf, SysUpTime) -> %% Use alg. in rfc2089 to map a v2 trap to a v1 trap % delete Counter64 objects from vbs ?vdebug("prepare to send v1 trap '~p'",[Oid]), @@ -822,14 +819,38 @@ send_v1_trap(#notification{oid = Oid}, V1Res, Vbs, ExtraInfo, NetIf, {lists:reverse(First),Last} end end, - TrapPdu = make_v1_trap_pdu(Enter, Spec, NVbs, SysUpTime), + do_send_v1_trap(Enter, Spec, V1Res, NVbs, ExtraInfo, NetIf, SysUpTime). + +do_send_v1_trap(Enter, Spec, V1Res, NVbs, ExtraInfo, NetIf, SysUpTime) -> + {value, Transports} = snmp_framework_mib:intAgentTransports(get), + {_Domain, {AgentIp, _AgentPort}} = + case lists:keyfind(snmpUDPDomain, 1, Transports) of + false -> + case lists:keyfind(transportDomainUdpIpv4, 1, Transports) of + false -> + ?vtrace( + "snmpa_trap: can not send v1 trap " + "without IPv4 domain: ~p", + [Transports]), + user_err( + "snmpa_trap: can not send v1 trap " + "without IPv4 domain: ~p", + [Transports]); + DomainAddr -> + DomainAddr + end; + DomainAddr -> + DomainAddr + end, + TrapPdu = make_v1_trap_pdu(Enter, Spec, NVbs, SysUpTime, AgentIp), AddrCommunities = mk_addr_communities(V1Res), - lists:foreach(fun({Community, Addrs}) -> - ?vtrace("send v1 trap to ~p",[Addrs]), - NetIf ! {send_pdu, 'version-1', TrapPdu, - {community, Community}, Addrs, ExtraInfo} - end, AddrCommunities). - + lists:foreach( + fun ({Community, Addrs}) -> + ?vtrace("send v1 trap to ~p",[Addrs]), + NetIf ! {send_pdu, 'version-1', TrapPdu, + {community, Community}, Addrs, ExtraInfo} + end, AddrCommunities). + send_v2_trap(_TrapRec, [], _Vbs, _Recv, _ExtraInfo, _NetIf, _SysUpTime) -> ok; send_v2_trap(TrapRec, V2Res, Vbs, Recv, ExtraInfo, NetIf, SysUpTime) -> @@ -1045,7 +1066,7 @@ deliver_recv(#snmpa_notification_delivery_info{tag = Tag, "~n DeliveryResult: ~p" "~n TAddr: ~p" "", [Tag, Mod, Extra, DeliveryResult, TAddr]), - Addr = transform_taddr(TAddr), + [Addr] = transform_taddrs([TAddr]), (catch Mod:delivery_info(Tag, Addr, DeliveryResult, Extra)); deliver_recv({Tag, Receiver}, MsgId, Result) -> ?vtrace("deliver_recv -> entry with" @@ -1072,35 +1093,90 @@ deliver_recv(Else, _MsgId, _Result) -> [Else]), user_err("snmpa: bad receiver, ~w\n", [Else]). -transform_taddrs(Addrs) -> - [transform_taddr(Addr) || Addr <- Addrs]. +transform_taddrs(TAddrs) -> + UseTDomain = + case snmp_framework_mib:intAgentTransportDomain(get) of + {value,snmpUDPDomain} -> + false; + {value,_} -> + true; + genErr -> + false + end, + DomAddrs = [transform_taddr(TAddr) || TAddr <- TAddrs], + case UseTDomain of + true -> + DomAddrs; + false -> + [Addr || {_Domain, Addr} <- DomAddrs] + end. -transform_taddr({?snmpUDPDomain, [A1, A2, A3, A4, P1, P2]}) -> % v2 - Addr = {A1, A2, A3, A4}, - Port = P1 bsl 8 + P2, - {Addr, Port}; -transform_taddr({?transportDomainUdpIpv4, [A1, A2, A3, A4, P1, P2]}) -> % v2 - Addr = {A1, A2, A3, A4}, +%% v2 +transform_taddr({?snmpUDPDomain, Addr}) -> + transform_taddr(transportDomainIdpIpv4, Addr); +transform_taddr({?transportDomainUdpIpv4, Addr}) -> + transform_taddr(transportDomainUdpIpv4, Addr); +transform_taddr({?transportDomainUdpIpv6, Addr}) -> + transform_taddr(transportDomainUdpIpv6, Addr); +%% v3 +transform_taddr({{?snmpUDPDomain, Addr}, _MsgData}) -> + transform_taddr(transportDomainUdpIpv4, Addr); +transform_taddr({{?transportDomainUdpIpv4, Addr}, _MsgData}) -> + transform_taddr(transportDomainUdpIpv4, Addr); +transform_taddr({{?transportDomainUdpIpv6, Addr}, _MsgData}) -> + transform_taddr(transportDomainUdpIpv6, Addr). + +transform_taddr( + transportDomainUdpIpv4 = Domain, + [A1,A2,A3,A4,P1,P2]) -> + Ip = {A1, A2, A3, A4}, Port = P1 bsl 8 + P2, - {Addr, Port}; -transform_taddr({?transportDomainUdpIpv6, - [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]}) -> % v2 - Addr = {A1, A2, A3, A4, A5, A6, A7, A8}, + {Domain, {Ip, Port}}; +transform_taddr( + transportDomainUdpIpv6 = Domain, + [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]) -> + Ip = {A1, A2, A3, A4, A5, A6, A7, A8}, Port = P1 bsl 8 + P2, - {Addr, Port}; -transform_taddr({{?snmpUDPDomain, [A1, A2, A3, A4, P1, P2]}, _MsgData}) -> % v3 - Addr = {A1, A2, A3, A4}, + {Domain, {Ip, Port}}; +transform_taddr( + transportDomainUdpIpv6 = Domain, + [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, + P1, P2]) -> + Ip = + {(A1 bsl 8) bor A2, (A3 bsl 8) bor A4, + (A5 bsl 8) bor A6, (A7 bsl 8) bor A8, + (A9 bsl 8) bor A10, (A11 bsl 8) bor A12, + (A13 bsl 8) bor A14, (A15 bsl 8) bor A16}, Port = P1 bsl 8 + P2, - {Addr, Port}; -transform_taddr({{?transportDomainUdpIpv4, [A1, A2, A3, A4, P1, P2]}, _MsgData}) -> % v3 - Addr = {A1, A2, A3, A4}, - Port = P1 bsl 8 + P2, - {Addr, Port}; -transform_taddr({{?transportDomainUdpIpv6, - [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]}, _MsgData}) -> % v3 - Addr = {A1, A2, A3, A4, A5, A6, A7, A8}, - Port = P1 bsl 8 + P2, - {Addr, Port}. + {Domain, {Ip, Port}}. + +%% transform_taddr({?snmpUDPDomain, [A1, A2, A3, A4, P1, P2]}) -> % v2 +%% Addr = {A1, A2, A3, A4}, +%% Port = P1 bsl 8 + P2, +%% {Addr, Port}; +%% transform_taddr({?transportDomainUdpIpv4, [A1, A2, A3, A4, P1, P2]}) -> % v2 +%% Addr = {A1, A2, A3, A4}, +%% Port = P1 bsl 8 + P2, +%% {Addr, Port}; +%% transform_taddr({?transportDomainUdpIpv6, +%% [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]}) -> % v2 +%% Addr = {A1, A2, A3, A4, A5, A6, A7, A8}, +%% Port = P1 bsl 8 + P2, +%% {Addr, Port}; +%% transform_taddr({{?snmpUDPDomain, [A1, A2, A3, A4, P1, P2]}, _MsgData}) -> % v3 +%% Addr = {A1, A2, A3, A4}, +%% Port = P1 bsl 8 + P2, +%% {Addr, Port}; +%% transform_taddr({{?transportDomainUdpIpv4, [A1, A2, A3, A4, P1, P2]}, _MsgData}) -> % v3 +%% Addr = {A1, A2, A3, A4}, +%% Port = P1 bsl 8 + P2, +%% {Addr, Port}; +%% transform_taddr({{?transportDomainUdpIpv6, +%% [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]}, _MsgData}) -> % v3 +%% Addr = {A1, A2, A3, A4, A5, A6, A7, A8}, +%% Port = P1 bsl 8 + P2, +%% {Addr, Port}. + check_all_varbinds(#notification{oid = Oid}, Vbs, MibView) -> diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index babc33e6a5..ae79e3c1d1 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -28,6 +28,8 @@ %% {update, snmpa_local_db, soft, soft_purge, soft_purge, []} %% {add_module, snmpm_net_if_mt} [ + {"4.25.1", [{restart_application, snmp}]}, + {"4.25.0.1", [{restart_application, snmp}]}, {"4.25", [{restart_application, snmp}]}, {"4.24.2", [{restart_application, snmp}]}, {"4.24.1", [{restart_application, snmp}]}, @@ -40,6 +42,8 @@ %% {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} [ + {"4.25.1", [{restart_application, snmp}]}, + {"4.25.0.1", [{restart_application, snmp}]}, {"4.25", [{restart_application, snmp}]}, {"4.24.2", [{restart_application, snmp}]}, {"4.24.1", [{restart_application, snmp}]}, diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl index c97b635fc6..8976322c4e 100644 --- a/lib/snmp/src/manager/snmpm.erl +++ b/lib/snmp/src/manager/snmpm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -379,21 +379,33 @@ register_agent(UserId, Addr) -> register_agent(UserId, Addr, ?DEFAULT_AGENT_PORT, []). %% Backward compatibility -register_agent(UserId, Addr, Port, Config0) -> +register_agent(UserId, Domain, Addr, Config0) when is_atom(Domain) -> case lists:keymember(target_name, 1, Config0) of false -> - TargetName = mk_target_name(Addr, Port, Config0), - Config = [{reg_type, addr_port}, - {address, Addr}, {port, Port} | Config0], + TargetName = mk_target_name(Domain, Addr, Config0), + Config = + [{reg_type, addr_port}, + {tdomain, Domain}, {taddress, Addr} | Config0], do_register_agent(UserId, TargetName, ensure_engine_id(Config)); true -> {value, {_, TargetName}} = lists:keysearch(target_name, 1, Config0), Config1 = lists:keydelete(target_name, 1, Config0), - Config2 = [{reg_type, addr_port}, - {address, Addr}, {port, Port} | Config1], + Config2 = + [{reg_type, addr_port}, + {tdomain, Domain}, {taddress, Addr} | Config1], register_agent(UserId, TargetName, ensure_engine_id(Config2)) - end. + end; +register_agent(UserId, Ip, Port, Config) when is_integer(Port) -> + Domain = snmpm_config:default_transport_domain(), + Addr = + case snmp_conf:check_address(Domain, {Ip, Port}) of + ok -> + {Ip, Port}; + {ok, FixedAddr} -> + FixedAddr + end, + register_agent(UserId, Domain, Addr, Config). unregister_agent(UserId, TargetName) when is_list(TargetName) -> snmpm_config:unregister_agent(UserId, TargetName); @@ -402,8 +414,8 @@ unregister_agent(UserId, TargetName) when is_list(TargetName) -> unregister_agent(UserId, Addr) -> unregister_agent(UserId, Addr, ?DEFAULT_AGENT_PORT). -unregister_agent(UserId, Addr, Port) -> - case target_name(Addr, Port) of +unregister_agent(UserId, DomainIp, AddressPort) -> + case target_name(DomainIp, AddressPort) of {ok, TargetName} -> unregister_agent(UserId, TargetName); Error -> @@ -1264,14 +1276,17 @@ format_vb_value(Prefix, _Type, Val) -> %% --- Internal utility functions --- %% -target_name(Addr) -> - target_name(Addr, ?DEFAULT_AGENT_PORT). +target_name(Ip) -> + target_name(Ip, ?DEFAULT_AGENT_PORT). -target_name(Addr, Port) -> - snmpm_config:agent_info(Addr, Port, target_name). +target_name(DomainIp, AddressPort) -> + snmpm_config:agent_info(DomainIp, AddressPort, target_name). mk_target_name(Addr, Port, Config) -> - snmpm_config:mk_target_name(Addr, Port, Config). + R = snmpm_config:mk_target_name(Addr, Port, Config), + p(?MODULE_STRING":mk_target_name(~p, ~p, ~p) -> ~p.~n", + [Addr, Port, Config, R]), + R. ensure_engine_id(Config) -> case lists:keymember(engine_id, 1, Config) of @@ -1287,5 +1302,5 @@ ensure_engine_id(Config) -> %% p(F) -> %% p(F, []). -%% p(F, A) -> -%% io:format("~w:" ++ F ++ "~n", [?MODULE | A]). +p(F, A) -> + io:format("~w:" ++ F ++ "~n", [?MODULE | A]). diff --git a/lib/snmp/src/manager/snmpm_conf.erl b/lib/snmp/src/manager/snmpm_conf.erl index 5e2d9fdbf6..888f19aec6 100644 --- a/lib/snmp/src/manager/snmpm_conf.erl +++ b/lib/snmp/src/manager/snmpm_conf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2013. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. 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 @@ -78,43 +78,26 @@ write_manager_config(Dir, Conf) -> Hdr = header() ++ Comment, write_manager_config(Dir, Hdr, Conf). -write_manager_config(Dir, Hdr, Conf) - when is_list(Dir) andalso is_list(Hdr) andalso is_list(Conf) -> - Verify = fun() -> verify_manager_conf(Conf) end, - Write = fun(Fid) -> write_manager_conf(Fid, Hdr, Conf) end, - write_config_file(Dir, ?MANAGER_CONF_FILE, Verify, Write). - +write_manager_config(Dir, Hdr, Conf) + when is_list(Dir), is_list(Hdr), is_list(Conf) -> + Order = fun snmpm_config:order_manager_config/2, + Check = fun snmpm_config:check_manager_config/2, + Write = fun (Fd, Entries) -> write_manager_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, ?MANAGER_CONF_FILE, Order, Check, Write, Conf). append_manager_config(Dir, Conf) - when is_list(Dir) andalso is_list(Conf) -> - Verify = fun() -> verify_manager_conf(Conf) end, - Write = fun(Fid) -> write_manager_conf(Fid, Conf) end, - append_config_file(Dir, ?MANAGER_CONF_FILE, Verify, Write). - + when is_list(Dir), is_list(Conf) -> + Order = fun snmpm_config:order_manager_config/2, + Check = fun snmpm_config:check_manager_config/2, + Write = fun write_manager_conf/2, + append_config_file(Dir, ?MANAGER_CONF_FILE, Order, Check, Write, Conf). -read_manager_config(Dir) -> - Verify = fun(Entry) -> verify_manager_conf_entry(Entry) end, - read_config_file(Dir, ?MANAGER_CONF_FILE, Verify). +read_manager_config(Dir) when is_list(Dir) -> + Order = fun snmpm_config:order_manager_config/2, + Check = fun snmpm_config:check_manager_config/2, + read_config_file(Dir, ?MANAGER_CONF_FILE, Order, Check). -verify_manager_conf([]) -> - ok; -verify_manager_conf([H|T]) -> - verify_manager_conf_entry(H), - verify_manager_conf(T); -verify_manager_conf(X) -> - error({bad_manager_config, X}). - -verify_manager_conf_entry(Entry) -> - case snmpm_config:check_manager_config(Entry) of - ok -> - ok; -%% {ok, _} -> -%% ok; - Error -> - throw(Error) - end. - write_manager_conf(Fd, "", Conf) -> write_manager_conf(Fd, Conf); write_manager_conf(Fd, Hdr, Conf) -> @@ -127,14 +110,15 @@ write_manager_conf(Fd, [H|T]) -> do_write_manager_conf(Fd, H), write_manager_conf(Fd, T). -do_write_manager_conf(Fd, {address = Tag, Val}) -> - io:format(Fd, "{~w, ~w}.~n", [Tag, Val]); -do_write_manager_conf(Fd, {port = Tag, Val} ) -> +do_write_manager_conf(Fd, {Tag, Val}) + when Tag =:= domain; + Tag =:= address; + Tag =:= port; + Tag =:= max_message_size -> io:format(Fd, "{~w, ~w}.~n", [Tag, Val]); -do_write_manager_conf(Fd, {engine_id = Tag, Val} ) -> +do_write_manager_conf(Fd, {Tag, Val}) + when Tag =:= engine_id -> io:format(Fd, "{~w, \"~s\"}.~n", [Tag, Val]); -do_write_manager_conf(Fd, {max_message_size = Tag, Val} ) -> - io:format(Fd, "{~w, ~w}.~n", [Tag, Val]); do_write_manager_conf(_Fd, Crap) -> error({bad_manager_config, Crap}). @@ -167,36 +151,29 @@ write_users_config(Dir, Conf) -> Hdr = header() ++ Comment, write_users_config(Dir, Hdr, Conf). -write_users_config(Dir, Hdr, Conf) +write_users_config(Dir, Hdr, Conf) when is_list(Dir) andalso is_list(Hdr) andalso is_list(Conf) -> - Verify = fun() -> verify_users_conf(Conf) end, - Write = fun(Fd) -> write_users_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, ?USERS_CONF_FILE, Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_user_config/2, + Write = fun (Fd, Entries) -> write_users_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, ?USERS_CONF_FILE, Order, Check, Write, Conf). -append_users_config(Dir, Conf) +append_users_config(Dir, Conf) when is_list(Dir) andalso is_list(Conf) -> - Verify = fun() -> verify_users_conf(Conf) end, - Write = fun(Fd) -> write_users_conf(Fd, Conf) end, - append_config_file(Dir, ?USERS_CONF_FILE, Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_user_config/2, + Write = fun write_users_conf/2, + append_config_file(Dir, ?USERS_CONF_FILE, Order, Check, Write, Conf). read_users_config(Dir) when is_list(Dir) -> - Verify = fun(Entry) -> verify_users_conf_entry(Entry) end, - read_config_file(Dir, ?USERS_CONF_FILE, Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_user_config/2, + read_config_file(Dir, ?USERS_CONF_FILE, Order, Check). - -verify_users_conf([]) -> - ok; -verify_users_conf([H|T]) -> - verify_users_conf_entry(H), - verify_users_conf(T); -verify_users_conf(X) -> - error({bad_users_conf, X}). - -verify_users_conf_entry(Entry) -> - {ok, _} = snmpm_config:check_user_config(Entry), - ok. + +check_user_config(Entry, State) -> + {check_ok(snmpm_config:check_user_config(Entry)), + State}. write_users_conf(Fd, "", Conf) -> write_users_conf(Fd, Conf); @@ -239,36 +216,29 @@ write_agents_config(Dir, Conf) -> Hdr = header() ++ Comment, write_agents_config(Dir, Hdr, Conf). -write_agents_config(Dir, Hdr, Conf) +write_agents_config(Dir, Hdr, Conf) when is_list(Dir) andalso is_list(Hdr) andalso is_list(Conf) -> - Verify = fun() -> verify_agents_conf(Conf) end, - Write = fun(Fd) -> write_agents_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, ?AGENTS_CONF_FILE, Verify, Write). + Order = fun snmp_conf:no_order/2, + Check = fun check_agent_config/2, + Write = fun (Fd, Entries) -> write_agents_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, ?AGENTS_CONF_FILE, Order, Check, Write, Conf). - -append_agents_config(Dir, Conf) +append_agents_config(Dir, Conf) when is_list(Dir) andalso is_list(Conf) -> - Verify = fun() -> verify_agents_conf(Conf) end, - Write = fun(Fd) -> write_agents_conf(Fd, Conf) end, - append_config_file(Dir, ?AGENTS_CONF_FILE, Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_agent_config/2, + Write = fun write_agents_conf/2, + append_config_file(Dir, ?AGENTS_CONF_FILE, Order, Check, Write, Conf). read_agents_config(Dir) -> - Verify = fun(Entry) -> verify_agents_conf_entry(Entry) end, - read_config_file(Dir, ?AGENTS_CONF_FILE, Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_agent_config/2, + read_config_file(Dir, ?AGENTS_CONF_FILE, Order, Check). -verify_agents_conf([]) -> - ok; -verify_agents_conf([H|T]) -> - verify_agents_conf_entry(H), - verify_agents_conf(T); -verify_agents_conf(X) -> - error({bad_agents_config, X}). - -verify_agents_conf_entry(Entry) -> - {ok, _} = snmpm_config:check_agent_config(Entry), - ok. +check_agent_config(Entry, State) -> + {check_ok(snmpm_config:check_agent_config(Entry)), + State}. write_agents_conf(Fd, "", Conf) -> write_agents_conf(Fd, Conf); @@ -282,13 +252,15 @@ write_agents_conf(Fd, [H|T]) -> do_write_agents_conf(Fd, H), write_agents_conf(Fd, T). -do_write_agents_conf(Fd, - {UserId, - TargetName, Comm, Ip, Port, EngineID, - Timeout, MaxMessageSize, Version, - SecModel, SecName, SecLevel} = _A) -> - io:format(Fd, - "{~w, \"~s\", \"~s\", ~w, ~w, \"~s\", ~w, ~w, ~w, ~w, \"~s\", ~w}.~n", [UserId, TargetName, Comm, Ip, Port, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel]); +do_write_agents_conf( + Fd, + {UserId, TargetName, Comm, Ip, Port, EngineID, + Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel} = _A) -> + io:format( + Fd, + "{~w, \"~s\", \"~s\", ~w, ~w, \"~s\", ~w, ~w, ~w, ~w, \"~s\", ~w}.~n", + [UserId, TargetName, Comm, Ip, Port, EngineID, + Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel]); do_write_agents_conf(_Fd, Crap) -> error({bad_agents_config, Crap}). @@ -314,37 +286,30 @@ write_usm_config(Dir, Conf) -> Hdr = header() ++ Comment, write_usm_config(Dir, Hdr, Conf). -write_usm_config(Dir, Hdr, Conf) +write_usm_config(Dir, Hdr, Conf) when is_list(Dir) andalso is_list(Hdr) andalso is_list(Conf) -> - Verify = fun() -> verify_usm_conf(Conf) end, - Write = fun(Fd) -> write_usm_conf(Fd, Hdr, Conf) end, - write_config_file(Dir, ?USM_USERS_CONF_FILE, Verify, Write). + Order = fun snmp_conf:no_order/2, + Check = fun check_usm_user_config/2, + Write = fun (Fd, Entries) -> write_usm_conf(Fd, Hdr, Entries) end, + write_config_file(Dir, ?USM_USERS_CONF_FILE, Order, Check, Write, Conf). - -append_usm_config(Dir, Conf) +append_usm_config(Dir, Conf) when is_list(Dir) andalso is_list(Conf) -> - Verify = fun() -> verify_usm_conf(Conf) end, - Write = fun(Fd) -> write_usm_conf(Fd, Conf) end, - append_config_file(Dir, ?USM_USERS_CONF_FILE, Verify, Write). - + Order = fun snmp_conf:no_order/2, + Check = fun check_usm_user_config/2, + Write = fun write_usm_conf/2, + append_config_file(Dir, ?USM_USERS_CONF_FILE, Order, Check, Write, Conf). read_usm_config(Dir) when is_list(Dir) -> - Verify = fun(Entry) -> verify_usm_conf_entry(Entry) end, - read_config_file(Dir, ?USM_USERS_CONF_FILE, Verify). + Order = fun snmp_conf:no_order/2, + Check = fun check_usm_user_config/2, + read_config_file(Dir, ?USM_USERS_CONF_FILE, Order, Check). -verify_usm_conf([]) -> - ok; -verify_usm_conf([H|T]) -> - verify_usm_conf_entry(H), - verify_usm_conf(T); -verify_usm_conf(X) -> - error({bad_usm_conf, X}). - -verify_usm_conf_entry(Entry) -> - {ok, _} = snmpm_config:check_usm_user_config(Entry), - ok. +check_usm_user_config(Entry, State) -> + {check_ok(snmpm_config:check_usm_user_config(Entry)), + State}. write_usm_conf(Fd, "", Conf) -> write_usm_conf(Fd, Conf); @@ -358,41 +323,49 @@ write_usm_conf(Fd, [H|T]) -> do_write_usm_conf(Fd, H), write_usm_conf(Fd, T). -do_write_usm_conf(Fd, - {EngineID, UserName, AuthP, AuthKey, PrivP, PrivKey}) -> - io:format(Fd, "{\"~s\", \"~s\", ~w, ~w, ~w, ~w}.~n", - [EngineID, UserName, AuthP, AuthKey, PrivP, PrivKey]); -do_write_usm_conf(Fd, - {EngineID, UserName, SecName, - AuthP, AuthKey, PrivP, PrivKey}) -> - io:format(Fd, "{\"~s\", \"~s\", \"~s\", Ã~w, ~w, ~w, ~w}.~n", - [EngineID, UserName, SecName, AuthP, AuthKey, PrivP, PrivKey]); +do_write_usm_conf( + Fd, + {EngineID, UserName, AuthP, AuthKey, PrivP, PrivKey}) -> + io:format( + Fd, "{\"~s\", \"~s\", ~w, ~w, ~w, ~w}.~n", + [EngineID, UserName, AuthP, AuthKey, PrivP, PrivKey]); +do_write_usm_conf( + Fd, + {EngineID, UserName, SecName, + AuthP, AuthKey, PrivP, PrivKey}) -> + io:format( + Fd, "{\"~s\", \"~s\", \"~s\", Ã~w, ~w, ~w, ~w}.~n", + [EngineID, UserName, SecName, AuthP, AuthKey, PrivP, PrivKey]); do_write_usm_conf(_Fd, Crap) -> error({bad_usm_conf, Crap}). %% ---- config file wrapper functions ---- -write_config_file(Dir, File, Verify, Write) -> - snmp_config:write_config_file(Dir, File, Verify, Write). - -append_config_file(Dir, File, Verify, Write) -> - snmp_config:append_config_file(Dir, File, Verify, Write). +write_config_file(Dir, File, Order, Check, Write, Conf) -> + snmp_config:write_config_file(Dir, File, Order, Check, Write, Conf). -read_config_file(Dir, File, Verify) -> - snmp_config:read_config_file(Dir, File, Verify). +append_config_file(Dir, File, Order, Check, Write, Conf) -> + snmp_config:append_config_file(Dir, File, Order, Check, Write, Conf). +read_config_file(Dir, File, Order, Check) -> + snmp_config:read_config_file(Dir, File, Order, Check). %% ---- config file utility functions ---- +check_ok(ok) -> + ok; +check_ok({ok, _}) -> + ok. + header() -> {Y,Mo,D} = date(), {H,Mi,S} = time(), - io_lib:format("%% This file was generated by " - "~w (version-~s) ~w-~2.2.0w-~2.2.0w " - "~2.2.0w:~2.2.0w:~2.2.0w\n", - [?MODULE, ?version, Y, Mo, D, H, Mi, S]). - + io_lib:format( + "%% This file was generated by " + "~w (version-~s) ~w-~2.2.0w-~2.2.0w " + "~2.2.0w:~2.2.0w:~2.2.0w\n", + [?MODULE, ?version, Y, Mo, D, H, Mi, S]). error(R) -> throw({error, R}). diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 2101ad46e1..013fefa4e2 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -103,8 +103,10 @@ get_agent_mp_model/2 ]). --export([check_manager_config/1, - check_user_config/1, +-export([ + order_manager_config/2, + check_manager_config/2, + check_user_config/1, check_agent_config/1, check_usm_user_config/1]). @@ -165,7 +167,7 @@ %%%------------------------------------------------------------------- default_transport_domain() -> - transportDomainUdpIpv4. + snmpUDPDomain. start_link(Opts) -> @@ -190,7 +192,11 @@ register_user(UserId, UserMod, UserData, DefaultAgentConfig) when (UserId =/= ?DEFAULT_USER) andalso is_list(DefaultAgentConfig) -> case (catch verify_user_behaviour(UserMod)) of ok -> - Config = default_agent_config(DefaultAgentConfig), + {ok, SystemDefaultAgentConfig} = agent_info(), + Config = + ensure_config(SystemDefaultAgentConfig, + DefaultAgentConfig), +%% Config = default_agent_config(DefaultAgentConfig), call({register_user, UserId, UserMod, UserData, Config}); Error -> Error @@ -201,19 +207,19 @@ register_user(UserId, _UserMod, _UserData, DefaultAgentConfig) register_user(UserId, _, _, _) -> {error, {bad_user_id, UserId}}. -default_agent_config(DefaultAgentConfig) -> - {ok, SystemDefaultAgentConfig} = agent_info(), - default_agent_config(SystemDefaultAgentConfig, DefaultAgentConfig). +%% default_agent_config(DefaultAgentConfig) -> +%% {ok, SystemDefaultAgentConfig} = agent_info(), +%% default_agent_config(SystemDefaultAgentConfig, DefaultAgentConfig). -default_agent_config([], DefaultAgentConfig) -> - DefaultAgentConfig; -default_agent_config([{Key, _} = Entry|T], DefaultAgentConfig) -> - case lists:keysearch(Key, 1, DefaultAgentConfig) of - {value, _} -> - default_agent_config(T, DefaultAgentConfig); - false -> - default_agent_config(T, [Entry|DefaultAgentConfig]) - end. +%% default_agent_config([], DefaultAgentConfig) -> +%% DefaultAgentConfig; +%% default_agent_config([{Key, _} = Entry|T], DefaultAgentConfig) -> +%% case lists:keymember(Key, 1, DefaultAgentConfig) of +%% true -> +%% default_agent_config(T, DefaultAgentConfig); +%% false -> +%% default_agent_config(T, [Entry|DefaultAgentConfig]) +%% end. verify_user_behaviour(UserMod) -> @@ -280,9 +286,10 @@ do_user_info(_UserId, BadItem) -> %% A target-name constructed in this way is a string with the following: %% <IP-address>:<Port>-<Version> -%% This is intended for backward compatibility and therefor has +%% This is intended for backward compatibility and therefore has %% only support for IPv4 addresses and *no* other transport domain. -mk_target_name(Addr0, Port, Config) when is_list(Config) -> +mk_target_name(Domain, Addr, Config) + when is_atom(Domain), is_list(Config) -> Version = case lists:keysearch(version, 1, Config) of {value, {_, V}} -> @@ -290,18 +297,35 @@ mk_target_name(Addr0, Port, Config) when is_list(Config) -> false -> select_lowest_supported_version() end, - case normalize_address(Addr0) of - {A, B, C, D} -> - lists:flatten( - io_lib:format("~w.~w.~w.~w:~w-~w", [A, B, C, D, Port, Version])); - [A, B, C, D] -> + try + lists:flatten( + io_lib:format( + "~s-~w", [snmp_conf:mk_addr_string({Domain, Addr}), Version])) + catch + _ -> lists:flatten( - io_lib:format("~w.~w.~w.~w:~w-~w", [A, B, C, D, Port, Version])); - _ -> + io_lib:format("~p-~w", [Addr, Version])) + end; +mk_target_name(Ip, Port, Config) + when is_integer(Port), is_list(Config) -> + Domain = default_transport_domain(), + try fix_address(Domain, {Ip, Port}) of + Address -> + mk_target_name(Domain, Address, Config) + catch + _ -> + Version = + case lists:keysearch(version, 1, Config) of + {value, {_, V}} -> + V; + false -> + select_lowest_supported_version() + end, lists:flatten( - io_lib:format("~p:~w-~w", [Addr0, Port, Version])) + io_lib:format("~p:~w-~w", [Ip, Port, Version])) end. - + + select_lowest_supported_version() -> {ok, Versions} = system_info(versions), select_lowest_supported_version([v1, v2, v3], Versions). @@ -335,27 +359,17 @@ register_agent(UserId, TargetName, Config0) %% is not present %% 3) Check that there are no invalid or erroneous configs %% 4) Check that the manager is capable of using the selected version - case verify_agent_config(Config0) of - {ok, Config} -> - call({register_agent, UserId, TargetName, Config}); - Error -> - Error - end. - - -verify_agent_config(Conf0) -> try - begin - verify_mandatory(Conf0, [engine_id, address, reg_type]), - verify_invalid(Conf0, [user_id]), - Conf = verify_agent_config3(Conf0), - Vsns = versions(), - Vsn = which_version(Conf), - verify_version(Vsn, Vsns), - {ok, Conf} - end + verify_mandatory(Config0, [engine_id, reg_type]), + verify_someof(Config0, [address, taddress]), + verify_illegal(Config0, [user_id]), + Config = verify_agent_config(Config0), + Vsns = versions(), + Vsn = which_version(Config), + verify_version(Vsn, Vsns), + call({register_agent, UserId, TargetName, Config}) catch - throw:Error -> + Error -> Error end. @@ -381,52 +395,43 @@ verify_version(Vsn, Vsns) -> ok; false -> Reason = {version_not_supported_by_manager, Vsn, Vsns}, - throw({error, Reason}) - end. - -verify_agent_config3(Conf0) -> - %% Fix (transport) address and domain - {TDomain, Conf1} = - case lists:keysearch(tdomain, 1, Conf0) of - {value, {tdomain, Dom}} -> - {Dom, Conf0}; - false -> - Dom = default_transport_domain(), - {Dom, [{tdomain, Dom} | Conf0]} - end, - Conf2 = case lists:keysearch(address, 1, Conf1) of - {value, {address, Address}} -> - lists:keyreplace(address, 1, Conf1, - {address, {TDomain, Address}}); - false -> - %% This is a mandatory config option, - %% a later test will detect this - Conf1 - end, - case verify_agent2(Conf2) of - {ok, Conf} -> - Conf; - {error, _} = ERROR -> - throw(ERROR) + error(Reason) end. -verify_agent_config2(Conf) -> - verify_agent2(Conf). unregister_agent(UserId, TargetName) -> call({unregister_agent, UserId, TargetName}). %% This is the old style agent unregistration (using Addr and Port). -unregister_agent(UserId, Addr0, Port) -> - Addr = normalize_address(Addr0), - case do_agent_info(Addr, Port, target_name) of +unregister_agent(UserId, Domain, Address) when is_atom(Domain) -> + try fix_address(Domain, Address) of + NAddress -> + do_unregister_agent(UserId, Domain, NAddress) + catch + _ -> + {error, not_found} + end; +unregister_agent(UserId, Ip, Port) when is_integer(Port) -> + Domain = default_transport_domain(), + try fix_address(Domain, {Ip, Port}) of + Address -> + do_unregister_agent(UserId, Domain, Address) + catch + _ -> + {error, not_found} + end. + +do_unregister_agent(UserId, Domain, Address) -> + case do_agent_info(Domain, Address, target_name) of {ok, TargetName} -> unregister_agent(UserId, TargetName); Error -> Error end. + + agent_info() -> agent_info(?DEFAULT_TARGETNAME, all). @@ -444,20 +449,46 @@ agent_info(TargetName, Item) -> [] -> {error, not_found} end. - -agent_info(Addr0, Port, Item) -> - Addr = normalize_address(Addr0), - do_agent_info(Addr, Port, Item). -do_agent_info(Addr, Port, target_name = Item) -> - case ets:lookup(snmpm_agent_table, {Addr, Port, Item}) of +agent_info(Domain, Address, Item) when is_atom(Domain) -> + try fix_address(Domain, Address) of + NAddress -> + do_agent_info(Domain, NAddress, Item) + catch + _Thrown -> + p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n" + " ~p", + [Domain, Address, Item, _Thrown, erlang:get_stacktrace()]), + {error, not_found} + end; +agent_info(Ip, Port, Item) -> + p(?MODULE_STRING":agent_info(~p, ~p, ~p) entry~n", + [Ip, Port, Item]), + Domain = default_transport_domain(), + try fix_address(Domain, {Ip, Port}) of + Address -> + do_agent_info(Domain, Address, Item) + catch + _Thrown -> + p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n" + " ~p", + [Ip, Port, Item, _Thrown, erlang:get_stacktrace()]), + {error, not_found} + end. + +do_agent_info(Domain, Address, target_name = Item) -> + p(?MODULE_STRING":do_agent_info(~p, ~p, ~p) entry~n", + [Domain, Address, Item]), + case ets:lookup(snmpm_agent_table, {Domain, Address, Item}) of [{_, Val}] -> {ok, Val}; [] -> {error, not_found} end; -do_agent_info(Addr, Port, Item) -> - case do_agent_info(Addr, Port, target_name) of +do_agent_info(Domain, Address, Item) -> + p(?MODULE_STRING":do_agent_info(~p, ~p, ~p) entry~n", + [Domain, Address, Item]), + case do_agent_info(Domain, Address, target_name) of {ok, TargetName} -> agent_info(TargetName, Item); Error -> @@ -465,6 +496,19 @@ do_agent_info(Addr, Port, Item) -> end. +ensure_agent_info(_, [], Info) -> + Info; +ensure_agent_info(TargetName, [Item|Items], Info) -> + case lists:keymember(Item, 1, Info) of + true -> + ensure_agent_info(TargetName, Items, Info); + false -> + {ok, Value} = agent_info(TargetName, Item), + ensure_agent_info(TargetName, Items, [{Item, Value}|Info]) + end. + + + which_agents() -> which_agents('_'). @@ -474,38 +518,6 @@ which_agents(UserId) -> [TargetName || [TargetName] <- Agents]. -verify_agent_info(TargetName, Info0) -> - try - begin - verify_invalid(Info0, [user_id]), - %% Check if address is part of the list and - %% if so update it with the domain info. - Info = - case lists:keysearch(address, 1, Info0) of - {value, {address, Addr}} -> - %% If domain is part of the info, then use it. - %% If not, lookup what is already stored for - %% this agent and use that. - Domain = - case lists:keysearch(tdomain, 1, Info0) of - {value, {tdomain, Dom}} -> - Dom; - false -> - {ok, Dom} = - agent_info(TargetName, tdomain), - Dom - end, - Addr2 = {Domain, Addr}, - lists:keyreplace(address, 1, Info0, {address, Addr2}); - false -> - Info0 - end, - verify_agent2(Info) - end - catch - throw:Error -> - Error - end. update_agent_info(UserId, TargetName, Info) -> call({update_agent_info, UserId, TargetName, Info}). @@ -740,7 +752,7 @@ verify_usm_user_config(EngineID, Name, Config) -> try begin verify_mandatory(Config, []), - verify_invalid(Config, [engine_id, name]), + verify_illegal(Config, [engine_id, name]), verify_usm_user_config2(EngineID, Name, Config) end catch @@ -1073,7 +1085,11 @@ do_init(Opts) -> %% -- Prio (optional) -- Prio = get_opt(priority, Opts, normal), ets:insert(snmpm_config_table, {prio, Prio}), - process_flag(priority, Prio), + try process_flag(priority, Prio) + catch + error:badarg -> + error({invalid_priority,Prio}) + end, %% -- Server (optional) -- ServerOpts = get_opt(server, Opts, []), @@ -1506,7 +1522,9 @@ verify_versions([]) -> ok; verify_versions([Vsn|Vsns]) -> verify_version(Vsn), - verify_versions(Vsns). + verify_versions(Vsns); +verify_versions(Vsns) -> + error({invalid_versions, Vsns}). verify_version(v1) -> ok; @@ -1629,181 +1647,136 @@ init_agent_default() -> %% The purpose of the default_agent is only to have a place %% to store system wide default values related to agents. %% - - %% Port - init_agent_default(port, ?DEFAULT_AGENT_PORT), - - %% Timeout - init_agent_default(timeout, 10000), - - %% Max message (packet) size - init_agent_default(max_message_size, 484), - - %% MPModel - init_agent_default(version, v2), - - %% SecModel - init_agent_default(sec_model, v2c), - - %% SecName - init_agent_default(sec_name, "initial"), - - %% SecLevel - init_agent_default(sec_level, noAuthNoPriv), - - %% Community - init_agent_default(community, "all-rights"), - ok. - - -init_agent_default(Item, Val) when Item =/= user_id -> - case do_update_agent_info(default_agent, Item, Val) of - ok -> - ok; - {error, Reason} -> - error(Reason) - end. - + AgentDefaultConfig = + [{port, ?DEFAULT_AGENT_PORT}, % Port + {timeout, 10000}, % Timeout + {max_message_size, 484}, % Max message (packet) size + {version, v2}, % MPModel + {sec_model, v2c}, % SecModel + {sec_name, "initial"}, % SecName + {sec_level, noAuthPriv}, % SecLevel + {community, "all-rights"}], % Community + do_update_agent_info(default_agent, AgentDefaultConfig). + +%% %% Port +%% init_agent_default(port, ?DEFAULT_AGENT_PORT), + +%% %% Timeout +%% init_agent_default(timeout, 10000), + +%% %% Max message (packet) size +%% init_agent_default(max_message_size, 484), + +%% %% MPModel +%% init_agent_default(version, v2), + +%% %% SecModel +%% init_agent_default(sec_model, v2c), + +%% %% SecName +%% init_agent_default(sec_name, "initial"), + +%% %% SecLevel +%% init_agent_default(sec_level, noAuthNoPriv), + +%% %% Community +%% init_agent_default(community, "all-rights"), +%% ok. + + +%% init_agent_default(Item, Val) when Item =/= user_id -> +%% case do_update_agent_info(default_agent, Item, Val) of +%% ok -> +%% ok; +%% {error, Reason} -> +%% error(Reason) +%% end. + +%% read_agents_config_file(Dir) -> +%% Verify = fun check_agent_config2/1, +%% case read_file(Dir, "agents.conf", Verify, []) of +%% {ok, Conf} -> +%% Conf; +%% Error -> +%% ?vlog("agent config error: ~p", [Error]), +%% throw(Error) +%% end. + +%% check_agent_config2(Agent) -> +%% case (catch check_agent_config(Agent)) of +%% {ok, {UserId, TargetName, Conf, Version}} -> +%% {ok, Vsns} = system_info(versions), +%% case lists:member(Version, Vsns) of +%% true -> +%% {ok, {UserId, TargetName, Conf}}; +%% false -> +%% error({version_not_supported_by_manager, +%% Version, Vsns}) +%% end; +%% Err -> +%% throw(Err) +%% end. read_agents_config_file(Dir) -> - Check = fun(C) -> check_agent_config2(C) end, - case read_file(Dir, "agents.conf", Check, []) of - {ok, Conf} -> - Conf; - Error -> + Order = fun snmp_conf:no_order/2, + Check = fun check_agent_config/2, + try read_file(Dir, "agents.conf", Order, Check, []) + catch + throw:Error -> ?vlog("agent config error: ~p", [Error]), - throw(Error) + erlang:raise(throw, Error, erlang:get_stacktrace()) end. -check_agent_config2(Agent) -> - case (catch check_agent_config(Agent)) of - {ok, {UserId, TargetName, Conf, Version}} -> - {ok, Vsns} = system_info(versions), - case lists:member(Version, Vsns) of - true -> - {ok, {UserId, TargetName, Conf}}; - false -> - error({version_not_supported_by_manager, - Version, Vsns}) - end; - Err -> - throw(Err) +check_agent_config(Agent, State) -> + {ok, {UserId, TargetName, Conf, Version}} = check_agent_config(Agent), + {ok, Vsns} = system_info(versions), + case lists:member(Version, Vsns) of + true -> + {{ok, {UserId, TargetName, Conf}}, State}; + false -> + error({version_not_supported_by_manager, Version, Vsns}) end. %% For backward compatibility -check_agent_config({UserId, - TargetName, - Community, - Ip, Port, - EngineId, - Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel}) -> - TDomain = default_transport_domain(), - check_agent_config({UserId, - TargetName, - Community, - TDomain, Ip, Port, - EngineId, - Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel}); - -check_agent_config({UserId, - TargetName, - Community, - TDomain, Ip, Port, - EngineId, - Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel}) -> - ?vtrace("check_agent_config -> entry with" - "~n UserId: ~p" - "~n TargetName: ~p" - "~n Community: ~p" - "~n TDomain: ~p" - "~n Ip: ~p" - "~n Port: ~p" - "~n EngineId: ~p" - "~n Timeout: ~p" - "~n MaxMessageSize: ~p" - "~n Version: ~p" - "~n SecModel: ~p" - "~n SecName: ~p" - "~n SecLevel: ~p", - [UserId, TargetName, Community, - TDomain, Ip, Port, - EngineId, Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel]), - Addr = normalize_address(TDomain, Ip), - ?vtrace("check_agent_config -> Addr: ~p", [Addr]), - Agent = {UserId, - TargetName, - Community, - TDomain, Addr, Port, - EngineId, - Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel}, - {ok, verify_agent(Agent)}; +check_agent_config( + {UserId, TargetName, Community, Ip, Port, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel}) -> + Domain = default_transport_domain(), + Addr = fix_address(Domain, {Ip, Port}), + check_agent_config( + UserId, TargetName, Community, Domain, Addr, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel); +check_agent_config( + {UserId, TargetName, Community, Domain, Ip, Port, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel}) -> + check_agent_config( + UserId, TargetName, Community, Domain, {Ip, Port}, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel); check_agent_config(Agent) -> error({bad_agent_config, Agent}). - -init_agents_config([]) -> - ok; -init_agents_config([Agent|Agents]) -> - init_agent_config(Agent), - init_agents_config(Agents). - -init_agent_config({_UserId, ?DEFAULT_TARGETNAME = TargetName, _Config}) -> - throw({error, {invalid_target_name, TargetName}}); -init_agent_config({UserId, TargetName, Config}) -> - case handle_register_agent(UserId, TargetName, Config) of - ok -> - ok; - Error -> - throw(Error) - end. - - -%% For backward compatibility -verify_agent({UserId, - TargetName, - Comm, - Ip, Port, - EngineId, - Timeout, MMS, - Version, SecModel, SecName, SecLevel}) -> - TDomain = default_transport_domain(), - verify_agent({UserId, - TargetName, - Comm, - TDomain, Ip, Port, - EngineId, - Timeout, MMS, - Version, SecModel, SecName, SecLevel}); - -verify_agent({UserId, - TargetName, - Comm, - TDomain, Ip, Port, - EngineId, - Timeout, MMS, - Version, SecModel, SecName, SecLevel}) -> - ?vdebug("verify_agent -> entry with" +check_agent_config( + UserId, TargetName, Comm, Domain, Addr, + EngineId, Timeout, MMS, + Version, SecModel, SecName, SecLevel) -> + ?vdebug("check_agent_config -> entry with" "~n UserId: ~p" "~n TargetName: ~p", [UserId, TargetName]), snmp_conf:check_string(TargetName, {gt, 0}), - snmp_conf:check_integer(Port, {gt, 0}), %% Note that the order of Conf *is* important. %% Some properties may depend on others, so that %% in order to verify one property, another must %% be already verified (and present). An example - %% of this is the property 'address', for which + %% of this is the property 'taddress', for which %% the property tdomain is needed. - Conf0 = + Conf = [{reg_type, target_name}, - {tdomain, TDomain}, - %% This should be taddress, but what the*... - {address, {TDomain, Ip}}, - {port, Port}, + {tdomain, Domain}, + {taddress, Addr}, {community, Comm}, {engine_id, EngineId}, {timeout, Timeout}, @@ -1813,40 +1786,186 @@ verify_agent({UserId, {sec_name, SecName}, {sec_level, SecLevel} ], - case verify_agent2(Conf0) of - {ok, Conf} -> - {UserId, TargetName, Conf, Version}; - Err -> - throw(Err) + {ok, {UserId, TargetName, verify_agent_config(Conf), Version}}. + + + +init_agents_config([]) -> + ok; +init_agents_config([Agent|Agents]) -> + init_agent_config(Agent), + init_agents_config(Agents). + +init_agent_config({_UserId, ?DEFAULT_TARGETNAME = TargetName, _Config}) -> + error({invalid_target_name, TargetName}); +init_agent_config({UserId, TargetName, Config}) -> + case handle_register_agent(UserId, TargetName, Config) of + ok -> + ok; + Error -> + throw(Error) end. -verify_agent2(Conf) -> - verify_agent2(Conf, []). -verify_agent2([], VerifiedConf) -> - {ok, VerifiedConf}; -verify_agent2([{Item, Val0}|Items], VerifiedConf) -> - case verify_val(Item, Val0) of - {ok, Val} -> - verify_agent2(Items, [{Item, Val} | VerifiedConf]); - Err -> - Err + +%% Sort 'tdomain' first then 'port' to ensure both +%% sorts before 'taddress'. Keep the order of other items. +order_agent(ItemA, ItemB) -> + snmp_conf:keyorder(1, ItemA, ItemB, [tdomain, port]). + +fix_agent_config(Conf) -> + ?vdebug("fix_agent_config -> entry with~n~n" + " Conf: ~p", [Conf]), + fix_agent_config(lists:sort(fun order_agent/2, Conf), []). + +fix_agent_config([], FixedConf) -> + Ret = lists:reverse(FixedConf), + ?vdebug("fix_agent_config -> returns:~n" + " ~p", [Ret]), + Ret; +fix_agent_config([{taddress = Item, Address} = Entry|Conf], FixedConf) -> + {value, {tdomain, TDomain}} = lists:keysearch(tdomain, 1, FixedConf), + {value, {port, DefaultPort}} = lists:keysearch(port, 1, FixedConf), + case snmp_conf:check_address(TDomain, Address, DefaultPort) of + ok -> + fix_agent_config(Conf, [Entry|FixedConf]); + {ok, NAddress} -> + fix_agent_config(Conf, [{Item, NAddress}|FixedConf]) end; -verify_agent2([Bad|_], _VerifiedConf) -> - {error, {bad_agent_config, Bad}}. +fix_agent_config([Entry|Conf], FixedConf) -> + fix_agent_config(Conf, [Entry|FixedConf]). + + + +verify_agent_config(Conf) -> + verify_agent_config(lists:sort(fun order_agent/2, Conf), []). + +verify_agent_config([], VerifiedConf) -> + Ret = lists:reverse(VerifiedConf), + ?vdebug("verify_agent_config -> returns:~n" + " ~p", [Ret]), + Ret; +verify_agent_config([{Item, _} = Entry|Conf], VerifiedConf) -> + verify_illegal(VerifiedConf, [Item]), % Duplicates are hereby illegal + verify_agent_config(Conf, VerifiedConf, Entry); +verify_agent_config([Bad|_], _VerifiedConf) -> + error({bad_agent_config, Bad}). + +verify_agent_config( + Conf, VerifiedConf, {taddress = Item, Address} = Entry) -> + verify_illegal(VerifiedConf, [address]), + {TDomain, VC} = + case lists:keysearch(tdomain, 1, VerifiedConf) of + {value, {tdomain,TD}} -> + {TD, VerifiedConf}; + _ -> + %% Insert tdomain since it is missing + TD = default_transport_domain(), + {TD, [{tdomain, TD}|VerifiedConf]} + end, + case snmp_conf:check_address(TDomain, Address, 0) of + ok -> + verify_agent_config(Conf, [Entry|VC]); + {ok, NAddress} -> + verify_agent_config(Conf, [{Item, NAddress}|VC]) + end; +verify_agent_config(Conf, VerifiedConf, {address, Address}) -> + Item = taddress, + verify_illegal(VerifiedConf, [Item]), + {TDomain, VC} = + case lists:keysearch(tdomain, 1, VerifiedConf) of + {value, {tdomain, TD}} -> + {TD, VerifiedConf}; + _ -> + %% Insert tdomain since it is missing + TD = default_transport_domain(), + {TD, [{tdomain, TD}|VerifiedConf]} + end, + case snmp_conf:check_address(TDomain, Address, 0) of + ok -> + verify_agent_config(Conf, [{Item, Address}|VC]); + {ok, NAddress} -> + verify_agent_config(Conf, [{Item, NAddress}|VC]) + end; +verify_agent_config(Conf, VerifiedConf, {Item, Val} = Entry) -> + case verify_agent_entry(Item, Val) of + ok -> + verify_agent_config(Conf, [Entry|VerifiedConf]); + {ok, NewVal} -> + verify_agent_config(Conf, [{Item, NewVal}|VerifiedConf]) + end. + +verify_agent_entry(user_id, _UserId) -> + ok; +verify_agent_entry(reg_type, RegType) -> + if + RegType =:= addr_port; + RegType =:= target_name -> + ok; + true -> + error({bad_reg_type, RegType}) + end; +verify_agent_entry(tdomain, TDomain) -> + snmp_conf:check_domain(TDomain); +verify_agent_entry(port, Port) -> + snmp_conf:check_port(Port); +verify_agent_entry(community, Comm) -> + snmp_conf:check_string(Comm); +verify_agent_entry(engine_id, EngineId) -> + case EngineId of + discovery -> + ok; + _ -> + snmp_conf:check_string(EngineId) + end; +verify_agent_entry(timeout, Timeout) -> + snmp_conf:check_timer(Timeout); +verify_agent_entry(max_message_size, MMS) -> + snmp_conf:check_packet_size(MMS); +verify_agent_entry(version, V) -> + if + V =:= v1; + V =:= v2; + V =:= v3 -> + ok; + true -> + error({bad_version, V}) + end; +verify_agent_entry(sec_model, Model) -> + snmp_conf:check_sec_model(Model); +verify_agent_entry(sec_name, Name) -> + try snmp_conf:check_string(Name) + catch + _ -> + error({bad_sec_name, Name}) + end; +verify_agent_entry(sec_level, Level) -> + snmp_conf:check_sec_level(Level); +verify_agent_entry(Item, _) -> + error({unknown_item, Item}). + +%% read_users_config_file(Dir) -> +%% Verify = fun check_user_config/1, +%% case read_file(Dir, "users.conf", Verify, []) of +%% {ok, Conf} -> +%% Conf; +%% Error -> +%% ?vlog("failure reading users config file: ~n ~p", [Error]), +%% throw(Error) +%% end. + read_users_config_file(Dir) -> - Check = fun(C) -> check_user_config(C) end, - case read_file(Dir, "users.conf", Check, []) of - {ok, Conf} -> - Conf; - Error -> + Order = fun snmp_conf:no_order/2, + Check = fun (User, State) -> {check_user_config(User), State} end, + try read_file(Dir, "users.conf", Order, Check, []) + catch + throw:Error -> ?vlog("failure reading users config file: ~n ~p", [Error]), - throw(Error) + erlang:raise(throw, Error, erlang:get_stacktrace()) end. - check_user_config({Id, Mod, Data}) -> ?vtrace("check_user_config -> entry with" "~n Id: ~p" @@ -1864,21 +1983,18 @@ check_user_config({Id, Mod, Data, DefaultAgentConfig} = _User) case (catch verify_user_behaviour(Mod)) of ok -> ?vtrace("check_user_config -> user behaviour verified", []), - case verify_user_agent_config(DefaultAgentConfig) of - {ok, DefAgentConf} -> - ?vtrace("check_user_config -> " - "user agent (default) config verified", []), - User2 = {Id, Mod, Data, DefAgentConf}, - {ok, User2}; - {error, Reason} -> - error({bad_default_agent_config, Reason}) - end; + DefAgentConf = + verify_default_agent_config(DefaultAgentConfig), + ?vtrace("check_user_config -> " + "user agent (default) config verified", []), + User2 = {Id, Mod, Data, DefAgentConf}, + {ok, User2}; Error -> throw(Error) end; check_user_config({Id, _Mod, _Data, DefaultAgentConfig}) when (Id =/= ?DEFAULT_USER) -> - {error, {bad_default_agent_config, DefaultAgentConfig}}; + error({bad_default_agent_config, DefaultAgentConfig}); check_user_config({Id, _Mod, _Data, _DefaultAgentConfig}) -> error({bad_user_id, Id}); check_user_config(User) -> @@ -1904,7 +2020,7 @@ init_user_config(User) -> error_msg("user config check failed: " "~n~w~n~w", [User, Reason]) end. - + verify_user({Id, UserMod, UserData}) -> verify_user({Id, UserMod, UserData, []}); verify_user({Id, UserMod, UserData, DefaultAgentConfig}) @@ -1917,15 +2033,24 @@ verify_user({Id, UserMod, UserData, DefaultAgentConfig}) [Id, UserMod, UserData, DefaultAgentConfig]), case (catch verify_user_behaviour(UserMod)) of ok -> - case verify_user_agent_config(DefaultAgentConfig) of - {ok, DefAgentConf} -> - Config = default_agent_config(DefAgentConf), - {ok, #user{id = Id, - mod = UserMod, - data = UserData, - default_agent_config = Config}}; - {error, Reason} -> - error({bad_default_agent_config, Reason}) + try + {ok, SystemDefaultAgentConfig} = agent_info(), + Config = + ensure_config( + SystemDefaultAgentConfig, + verify_default_agent_config(DefaultAgentConfig)), +%% Config = +%% default_agent_config( +%% verify_default_agent_config(DefaultAgentConfig)), + {ok, #user{id = Id, + mod = UserMod, + data = UserData, + default_agent_config = Config}} + catch + Error -> + ?vdebug("verify_user default_agent_config -> throw" + "~n Error: ~p", [Error]), + error({bad_default_agent_config, Error}) end; Error -> throw(Error) @@ -1936,27 +2061,32 @@ verify_user({Id, _UserMod, _UserData, DefaultAgentConfig}) verify_user({Id, _, _, _}) -> {error, {bad_user_id, Id}}. -verify_user_agent_config(Conf) -> +verify_default_agent_config(Conf) -> try - begin - verify_invalid(Conf, [user_id, engine_id, address]), - verify_agent_config2(Conf) - end + verify_illegal( + Conf, + [user_id, engine_id, address, tdomain, taddress]), + verify_agent_config(Conf) catch - throw:Error -> - ?vdebug("verify_user_agent_config -> throw" + Error -> + ?vdebug("verify_default_agent_config -> throw" "~n Error: ~p", [Error]), - Error + error({bad_default_agent_config, Error}) end. +%% read_usm_config_file(Dir) -> +%% Verify = fun check_usm_user_config/1, +%% case read_file(Dir, "usm.conf", Verify, []) of +%% {ok, Conf} -> +%% Conf; +%% Error -> +%% throw(Error) +%% end. + read_usm_config_file(Dir) -> - Check = fun(C) -> check_usm_user_config(C) end, - case read_file(Dir, "usm.conf", Check, []) of - {ok, Conf} -> - Conf; - Error -> - throw(Error) - end. + Order = fun snmp_conf:no_order/2, + Check = fun (User, State) -> {check_usm_user_config(User), State} end, + read_file(Dir, "usm.conf", Order, Check, []). %% Identity-function check_usm_user_config({EngineId, Name, @@ -2138,20 +2268,61 @@ is_crypto_supported(Func) -> snmp_misc:is_crypto_supported(Func). +%% read_manager_config_file(Dir) -> +%% Verify = fun check_manager_config/1, +%% case read_file(Dir, "manager.conf", Verify) of +%% {ok, Conf} -> +%% ?d("read_manager_config_file -> ok: " +%% "~n Conf: ~p", [Conf]), +%% %% If the address is not specified, then we assume +%% %% it should be the local host. +%% %% If the address is not possible to determine +%% %% that way, then we give up... +%% verify_mandatory(Conf, [port,engine_id,max_message_size]), +%% ensure_config(default_manager_config(), Conf); +%% %% check_mandatory_manager_config(Conf), +%% %% ensure_manager_config(Conf); +%% Error -> +%% throw(Error) +%% end. + read_manager_config_file(Dir) -> - Check = fun(Conf) -> check_manager_config(Conf) end, - case read_file(Dir, "manager.conf", Check) of - {ok, Conf} -> - ?d("read_manager_config_file -> ok: " - "~n Conf: ~p", [Conf]), - %% If the address is not specified, then we assume - %% it should be the local host. - %% If the address is not possible to determine - %% that way, then we give up... - check_mandatory_manager_config(Conf), - ensure_manager_config(Conf); - Error -> - throw(Error) + Order = fun order_manager_config/2, + Check = fun check_manager_config/2, + Conf = read_file(Dir, "manager.conf", Order, Check), + ?d("read_manager_config_file -> ok: " + "~n Conf: ~p", [Conf]), + %% If the address is not specified, then we assume + %% it should be the local host. + %% If the address is not possible to determine + %% that way, then we give up... + verify_mandatory(Conf, [port,engine_id,max_message_size]), + default_manager_config(Conf). + +default_manager_config(Conf) -> + %% Ensure address of right family + case lists:keyfind(address, 1, Conf) of + false -> + Domain = + case lists:keyfind(domain, 1, Conf) of + false -> + default_transport_domain(); + {_, D} -> + D + end, + Family = snmp_conf:tdomain_to_family(Domain), + {ok, HostName} = inet:gethostname(), + case inet:getaddr(HostName, Family) of + {ok, Address} -> + [{address, Address} | Conf]; + {error, _Reason} -> + ?d("default_manager_config -> " + "failed getting ~w address for ~s:~n" + " _Reason: ~p", [Family, HostName, _Reason]), + Conf + end; + _ -> + Conf end. default_manager_config() -> @@ -2164,46 +2335,66 @@ default_manager_config() -> "~n _Reason: ~p", [_Reason]), [] end. - -check_manager_config({address, Addr}) -> - snmp_conf:check_ip(Addr); + +order_manager_config(EntryA, EntryB) -> + snmp_conf:keyorder(1, EntryA, EntryB, [domain]). + +check_manager_config({domain, D}, _Domain) -> + {snmp_conf:check_domain(D), D}; +check_manager_config({address = Tag, Ip}, D) -> + Domain = + case D of + undefined -> + default_transport_domain(); + _ -> + D + end, + {case snmp_conf:check_ip(Domain, Ip) of + ok -> + ok; + {ok, FixedIp} -> + {ok, {Tag, FixedIp}} + end, Domain}; +check_manager_config(Entry, Domain) -> + {check_manager_config(Entry), Domain}. + check_manager_config({port, Port}) -> - snmp_conf:check_integer(Port, {gt, 0}); + snmp_conf:check_port(Port); check_manager_config({engine_id, EngineID}) -> snmp_conf:check_string(EngineID); check_manager_config({max_message_size, Max}) -> snmp_conf:check_integer(Max, {gte, 484}); check_manager_config(Conf) -> - {error, {unknown_config, Conf}}. + error({unknown_config, Conf}). -check_mandatory_manager_config(Conf) -> - Mand = [port, engine_id, max_message_size], - check_mandatory_manager_config(Mand, Conf). +%% check_mandatory_manager_config(Conf) -> +%% Mand = [port, engine_id, max_message_size], +%% check_mandatory_manager_config(Mand, Conf). -check_mandatory_manager_config([], _Conf) -> - ok; -check_mandatory_manager_config([Item|Mand], Conf) -> - case lists:keysearch(Item, 1, Conf) of - false -> - error({missing_mandatory_manager_config, Item}); - _ -> - check_mandatory_manager_config(Mand, Conf) - end. +%% check_mandatory_manager_config([], _Conf) -> +%% ok; +%% check_mandatory_manager_config([Item|Mand], Conf) -> +%% case lists:keysearch(Item, 1, Conf) of +%% false -> +%% error({missing_mandatory_manager_config, Item}); +%% _ -> +%% check_mandatory_manager_config(Mand, Conf) +%% end. -ensure_manager_config(Confs) -> - ensure_manager_config(Confs, default_manager_config()). +%% ensure_manager_config(Confs) -> +%% ensure_manager_config(Confs, default_manager_config()). -ensure_manager_config(Confs, []) -> - Confs; -ensure_manager_config(Confs, [{Key,_} = DefKeyVal|Defs]) -> - case lists:keysearch(Key, 1, Confs) of - false -> - ensure_manager_config([DefKeyVal|Confs], Defs); - {value, _Conf} -> - ensure_manager_config(Confs, Defs) - end. +%% ensure_manager_config(Confs, []) -> +%% Confs; +%% ensure_manager_config(Confs, [{Key,_} = DefKeyVal|Defs]) -> +%% case lists:keysearch(Key, 1, Confs) of +%% false -> +%% ensure_manager_config([DefKeyVal|Confs], Defs); +%% {value, _Conf} -> +%% ensure_manager_config(Confs, Defs) +%% end. % ensure_manager_config([], Defs, Confs) -> % Confs ++ Defs; @@ -2216,46 +2407,102 @@ ensure_manager_config(Confs, [{Key,_} = DefKeyVal|Defs]) -> % ensure_manager_config(Confs, Defs, [Conf|Acc]) % end. - - -read_file(Dir, FileName, Check, Default) -> - File = filename:join(Dir, FileName), - case file:read_file_info(File) of - {ok, _} -> - case (catch do_read(File, Check)) of - {ok, Conf} -> - {ok, Conf}; - Error -> - ?vtrace("read_file -> read failed:" - "~n Error: ~p", [Error]), - Error - end; - {error, Reason} -> +read_file(Dir, FileName, Order, Check, Default) -> + try snmp_conf:read(filename:join(Dir, FileName), Order, Check) + catch + {error, Reason} when element(1, Reason) =:= failed_open -> ?vlog("failed reading config from ~s: ~p", [FileName, Reason]), - {ok, Default} + Default end. -read_file(Dir, FileName, Check) -> - File = filename:join(Dir, FileName), - case file:read_file_info(File) of - {ok, _} -> - case (catch do_read(File, Check)) of - {ok, Conf} -> - ?vtrace("read_file -> read ok" - "~n Conf: ~p", [Conf]), - {ok, Conf}; - Error -> - ?vtrace("read_file -> read failed:" - "~n Error: ~p", [Error]), - Error - end; - {error, Reason} -> +read_file(Dir, FileName, Order, Check) -> + try snmp_conf:read(filename:join(Dir, FileName), Order, Check) + catch + throw:{error, Reason} = Error + when element(1, Reason) =:= failed_open -> error_msg("failed reading config from ~s: ~p", [FileName, Reason]), - {error, {failed_reading, FileName, Reason}} - end. + erlang:raise(throw, Error, erlang:get_stacktrace()) + end. + + + + + + +%% read_file(Dir, FileName, Verify, Default) -> +%% File = filename:join(Dir, FileName), +%% case file:read_file_info(File) of +%% {ok, _} -> +%% read_file(File, Verify); +%% {error, Reason} -> +%% ?vlog("failed reading config from ~s: ~p", [FileName, Reason]), +%% {ok, Default} +%% end. + +%% read_file(Dir, FileName, Verify) -> +%% File = filename:join(Dir, FileName), +%% case file:read_file_info(File) of +%% {ok, _} -> +%% read_file(File, Verify); +%% {error, Reason} -> +%% error_msg("failed reading config from ~s: ~p", [FileName, Reason]), +%% {error, {failed_reading, FileName, Reason}} +%% end. + +%% read_file(File, Verify) -> +%% Check = fun (Config, State) -> {Verify(Config), State} end, +%% try snmp_conf:read(File, Check) of +%% Conf -> +%% ?vtrace("read_file -> read ok" +%% "~n Conf: ~p", [Conf]), +%% {ok, Conf} +%% catch +%% Error -> +%% ?vtrace("read_file -> read failed:" +%% "~n Error: ~p", [Error]), +%% Error +%% end. + +%% XXX remove + +%% read_file(Dir, FileName, Check, Default) -> +%% File = filename:join(Dir, FileName), +%% case file:read_file_info(File) of +%% {ok, _} -> +%% case (catch do_read(File, Check)) of +%% {ok, Conf} -> +%% {ok, Conf}; +%% Error -> +%% ?vtrace("read_file -> read failed:" +%% "~n Error: ~p", [Error]), +%% Error +%% end; +%% {error, Reason} -> +%% ?vlog("failed reading config from ~s: ~p", [FileName, Reason]), +%% {ok, Default} +%% end. + +%% read_file(Dir, FileName, Check) -> +%% File = filename:join(Dir, FileName), +%% case file:read_file_info(File) of +%% {ok, _} -> +%% case (catch do_read(File, Check)) of +%% {ok, Conf} -> +%% ?vtrace("read_file -> read ok" +%% "~n Conf: ~p", [Conf]), +%% {ok, Conf}; +%% Error -> +%% ?vtrace("read_file -> read failed:" +%% "~n Error: ~p", [Error]), +%% Error +%% end; +%% {error, Reason} -> +%% error_msg("failed reading config from ~s: ~p", [FileName, Reason]), +%% {error, {failed_reading, FileName, Reason}} +%% end. -do_read(File, Check) -> - {ok, snmp_conf:read(File, Check)}. +%% do_read(File, Check) -> +%% {ok, snmp_conf:read(File, Check)}. %%-------------------------------------------------------------------- @@ -2684,30 +2931,50 @@ handle_register_agent(UserId, TargetName, Config) -> "~n Config: ~p", [UserId, TargetName, Config]), case (catch agent_info(TargetName, user_id)) of {error, _} -> - ?vtrace("handle_register_agent -> user_id not found in config", []), + ?vtrace( + "handle_register_agent -> user_id not found in config", []), case ets:lookup(snmpm_user_table, UserId) of [#user{default_agent_config = DefConfig}] -> - ?vtrace("handle_register_agent -> " - "~n DefConfig: ~p", [DefConfig]), - %% First, insert this users default config - ?vtrace("handle_register_agent -> store default config", []), - do_handle_register_agent(TargetName, DefConfig), - %% Second, insert the config for this agent - ?vtrace("handle_register_agent -> store config", []), - do_handle_register_agent(TargetName, - [{user_id, UserId}|Config]), + ?vtrace("handle_register_agent ->~n" + " DefConfig: ~p", [DefConfig]), + FixedConfig = + fix_agent_config(ensure_config(DefConfig, Config)), + ?vtrace("handle_register_agent ->~n" + " FixedConfig: ~p", [FixedConfig]), + do_handle_register_agent( + TargetName, [{user_id, UserId}|FixedConfig]), %% <DIRTY-BACKWARD-COMPATIBILLITY> - %% And now for some (backward compatibillity) + %% And now for some (backward compatibillity) %% dirty crossref stuff - ?vtrace("handle_register_agent -> lookup address", []), - {ok, Addr} = agent_info(TargetName, address), - ?vtrace("handle_register_agent -> Addr: ~p, lookup Port", - [Addr]), - {ok, Port} = agent_info(TargetName, port), - ?vtrace("handle_register_agent -> register cross-ref fix", []), - ets:insert(snmpm_agent_table, - {{Addr, Port, target_name}, TargetName}), + {value, {_, Domain}} = + lists:keysearch(tdomain, 1, FixedConfig), + {value, {_, Address}} = + lists:keysearch(taddress, 1, FixedConfig), + ?vtrace( + "handle_register_agent -> register cross-ref fix", []), + ets:insert(snmpm_agent_table, + {{Domain, Address, target_name}, TargetName}), %% </DIRTY-BACKWARD-COMPATIBILLITY> + +%% %% First, insert this users default config +%% ?vtrace("handle_register_agent -> store default config", []), +%% do_handle_register_agent(TargetName, DefConfig), +%% %% Second, insert the config for this agent +%% ?vtrace("handle_register_agent -> store config", []), +%% do_handle_register_agent(TargetName, +%% [{user_id, UserId}|Config]), +%% %% <DIRTY-BACKWARD-COMPATIBILLITY> +%% %% And now for some (backward compatibillity) +%% %% dirty crossref stuff +%% ?vtrace("handle_register_agent -> lookup taddress", []), +%% {ok, {Addr, Port} = TAddress} = +%% agent_info(TargetName, taddress), +%% ?vtrace("handle_register_agent -> taddress: ~p", +%% [TAddress]), +%% ?vtrace("handle_register_agent -> register cross-ref fix", []), +%% ets:insert(snmpm_agent_table, +%% {{Addr, Port, target_name}, TargetName}), +%% %% </DIRTY-BACKWARD-COMPATIBILLITY> ok; _ -> {error, {not_found, UserId}} @@ -2729,7 +2996,7 @@ handle_register_agent(UserId, TargetName, Config) -> do_handle_register_agent(_TargetName, []) -> ok; do_handle_register_agent(TargetName, [{Item, Val}|Rest]) -> - ?vtrace("handle_register_agent -> entry with" + ?vtrace("do_handle_register_agent -> entry with" "~n TargetName: ~p" "~n Item: ~p" "~n Val: ~p" @@ -2738,7 +3005,7 @@ do_handle_register_agent(TargetName, [{Item, Val}|Rest]) -> ok -> do_handle_register_agent(TargetName, Rest); {error, Reason} -> - ?vtrace("handle_register_agent -> failed updating ~p" + ?vtrace("do_handle_register_agent -> failed updating ~p" "~n Item: ~p" "~n Reason: ~p", [Item, Reason]), ets:match_delete(snmpm_agent_table, {TargetName, '_'}), @@ -2762,9 +3029,9 @@ handle_unregister_agent(UserId, TargetName) -> %% <DIRTY-BACKWARD-COMPATIBILLITY> %% And now for some (backward compatibillity) %% dirty crossref stuff - {ok, Addr} = agent_info(TargetName, address), - {ok, Port} = agent_info(TargetName, port), - ets:delete(snmpm_agent_table, {Addr, Port, target_name}), + {ok, Domain} = agent_info(TargetName, tdomain), + {ok, Address} = agent_info(TargetName, taddress), + ets:delete(snmpm_agent_table, {Domain, Address, target_name}), %% </DIRTY-BACKWARD-COMPATIBILLITY> ets:match_delete(snmpm_agent_table, {{TargetName, '_'}, '_'}), ok; @@ -2790,21 +3057,26 @@ handle_update_agent_info(UserId, TargetName, Info) -> Error end. -handle_update_agent_info(TargetName, Info0) -> +handle_update_agent_info(TargetName, Info) -> ?vtrace("handle_update_agent_info -> entry with" "~n TargetName: ~p" - "~n Info0: ~p", [TargetName, Info0]), + "~n Info: ~p", [TargetName, Info]), %% Verify info - try verify_agent_info(TargetName, Info0) of - {ok, Info} -> - do_update_agent_info(TargetName, Info); + try + verify_illegal(Info, [user_id]), + %% If port or domain is part of the info, then use it. + %% If not, lookup what is already stored for + %% this agent and use that. + do_update_agent_info( + TargetName, + fix_agent_config( + verify_agent_config( + ensure_agent_info(TargetName, [port,tdomain], Info)))) + catch Error -> - Error - catch - throw:Error -> Error; T:E -> - {error, {failed_info_verification, Info0, T, E}} + {error, {failed_info_verification, Info, T, E}} end. handle_update_agent_info(UserId, TargetName, Item, Val) -> @@ -2816,6 +3088,9 @@ handle_update_agent_info(UserId, TargetName, Item, Val) -> handle_update_agent_info(TargetName, [{Item, Val}]). do_update_agent_info(TargetName, Info) -> + ?vtrace("do_update_agent_info -> entry with~n" + " TargetName: ~p~n" + " Info: ~p", [TargetName,Info]), InsertItem = fun({Item, Val}) -> ets:insert(snmpm_agent_table, {{TargetName, Item}, Val}) @@ -2997,109 +3272,42 @@ verify_mandatory(Conf, [Mand|Mands]) -> true -> verify_mandatory(Conf, Mands); false -> - throw({error, {missing_mandatory_config, Mand}}) + error({missing_mandatory_config, Mand}) end. -verify_invalid(_, []) -> +verify_illegal(_, []) -> ok; -verify_invalid(Conf, [Inv|Invs]) -> +verify_illegal(Conf, [Inv|Invs]) -> case lists:member(Inv, Conf) of false -> - verify_invalid(Conf, Invs); + verify_illegal(Conf, Invs); true -> - throw({error, {illegal_config, Inv}}) + error({illegal_config, Inv}) end. - -verify_val(user_id, UserId) -> - {ok, UserId}; -verify_val(reg_type, RegType) - when (RegType =:= addr_port) orelse (RegType =:= target_name) -> - {ok, RegType}; -verify_val(tdomain = Item, snmpUDPDomain = _Domain) -> - verify_val(Item, transportDomainUdpIpv4); -verify_val(tdomain, Domain) -> - case lists:member(Domain, ?SUPPORTED_DOMAINS) of +verify_someof(Conf, [Mand|Mands]) -> + case lists:keymember(Mand, 1, Conf) of true -> - {ok, Domain}; + ok; false -> - case lists:member(Domain, snmp_conf:all_domains()) of - true -> - error({unsupported_domain, Domain}); - false -> - error({unknown_domain, Domain}) + case Mands of + [] -> + error({missing_mandatory_config, Mand}); + _ -> + verify_someof(Conf, Mands) end - end; -verify_val(address, {Domain, Addr0}) -> - case normalize_address(Domain, Addr0) of - {_A1, _A2, _A3, _A4} = Addr -> - {ok, Addr}; - {_A1, _A2, _A3, _A4, _A5, _A6, _A7, _A8} = Addr -> - {ok, Addr}; - _ when is_list(Addr0) -> - case (catch snmp_conf:check_ip(Addr0)) of - ok -> - {ok, list_to_tuple(Addr0)}; - Err -> - Err - end; - _ -> - error({bad_address, Addr0}) - end; -verify_val(address, BadAddress) -> - error({bad_address, BadAddress}); -verify_val(port, Port) -> - case (catch snmp_conf:check_integer(Port, {gt, 0})) of - ok -> - {ok, Port}; - Err -> - Err - end; -verify_val(community, Comm) -> - case (catch snmp_conf:check_string(Comm)) of - ok -> - {ok, Comm}; - Err -> - Err - end; -verify_val(engine_id, discovery = EngineId) -> - {ok, EngineId}; -verify_val(engine_id, EngineId) -> - case (catch snmp_conf:check_string(EngineId)) of - ok -> - {ok, EngineId}; - Err -> - Err - end; -verify_val(timeout, Timeout) -> - (catch snmp_conf:check_timer(Timeout)); -verify_val(max_message_size, MMS) -> - case (catch snmp_conf:check_packet_size(MMS)) of - ok -> - {ok, MMS}; - Err -> - Err - end; -verify_val(version, V) - when (V =:= v1) orelse (V =:= v2) orelse (V =:= v3) -> - {ok, V}; -verify_val(version, BadVersion) -> - error({bad_version, BadVersion}); -verify_val(sec_model, Model) -> - (catch snmp_conf:check_sec_model(Model)); -verify_val(sec_name, Name) when is_list(Name) -> - case (catch snmp_conf:check_string(Name)) of - ok -> - {ok, Name}; - Err -> - Err - end; -verify_val(sec_name, BadName) -> - error({bad_sec_name, BadName}); -verify_val(sec_level, Level) -> - (catch snmp_conf:check_sec_level(Level)); -verify_val(Item, _) -> - {error, {unknown_item, Item}}. + end. + +ensure_config([], Config) -> + Config; +ensure_config([Default|Defaults], Config) -> + case lists:keymember(element(1, Default), 1, Config) of + true -> + ensure_config(Defaults, Config); + false -> + ensure_config(Defaults, [Default|Config]) + end. + %%%------------------------------------------------------------------- @@ -3257,31 +3465,14 @@ init_mini_mib_elems(MibName, [_|T], Res) -> %%---------------------------------------------------------------------- -normalize_address(Addr) -> - normalize_address(snmpUDPDomain, Addr). - -normalize_address(snmpUDPDomain, Addr) -> - normalize_address(transportDomainUdpIpv4, Addr); - -normalize_address(Domain, Addr) -> - case inet:getaddr(Addr, td2fam(Domain)) of - {ok, Addr2} -> - Addr2; - _ when is_list(Addr) -> - case (catch snmp_conf:check_ip(Domain, Addr)) of - ok -> - list_to_tuple(Addr); - _ -> - Addr - end; - _ -> - Addr +fix_address(Domain, Address) -> + case snmp_conf:check_address(Domain, Address) of + ok -> + Address; + {ok, NAddress} -> + NAddress end. -td2fam(transportDomainUdpIpv4) -> inet; -td2fam(transportDomainUdpIpv6) -> inet6. - - %%---------------------------------------------------------------------- call(Req) -> @@ -3389,6 +3580,6 @@ error_msg(F, A) -> %% p(F) -> %% p(F, []). -%% p(F, A) -> -%% io:format("~w:" ++ F ++ "~n", [?MODULE | A]). +p(F, A) -> + io:format("~w:" ++ F ++ "~n", [?MODULE | A]). diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl index 953c94ab54..f8a7441c0a 100644 --- a/lib/snmp/src/manager/snmpm_mpd.erl +++ b/lib/snmp/src/manager/snmpm_mpd.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -21,7 +21,7 @@ -export([init/1, - process_msg/7, + process_msg/7, process_msg/6, generate_msg/5, generate_response_msg/4, next_msg_id/0, @@ -92,8 +92,10 @@ reset(#state{v3 = V3}) -> %% Purpose: This is the main Message Dispatching function. (see %% section 4.2.1 in rfc2272) %%----------------------------------------------------------------- -process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) -> +process_msg(Msg, Domain, Ip, Port, State, NoteStore, Logger) -> + process_msg(Msg, Domain, {Ip, Port}, State, NoteStore, Logger). +process_msg(Msg, Domain, Addr, State, NoteStore, Logger) -> inc(snmpInPkts), case (catch snmp_pdus:dec_message_only(binary_to_list(Msg))) of @@ -102,17 +104,17 @@ process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) -> #message{version = 'version-1', vsn_hdr = Community, data = Data} when State#state.v1 =:= true -> HS = ?empty_msg_size + length(Community), - process_v1_v2c_msg('version-1', NoteStore, Msg, - Domain, Addr, Port, - Community, Data, HS, Logger); + process_v1_v2c_msg( + 'version-1', NoteStore, Msg, Domain, Addr, + Community, Data, HS, Logger); %% Version 2 #message{version = 'version-2', vsn_hdr = Community, data = Data} when State#state.v2c =:= true -> HS = ?empty_msg_size + length(Community), - process_v1_v2c_msg('version-2', NoteStore, Msg, - Domain, Addr, Port, - Community, Data, HS, Logger); + process_v1_v2c_msg( + 'version-2', NoteStore, Msg, Domain, Addr, + Community, Data, HS, Logger); %% Version 3 #message{version = 'version-3', vsn_hdr = H, data = Data} @@ -122,7 +124,7 @@ process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) -> "~n msgFlags: ~p" "~n msgSecModel: ~p", [H#v3_hdr.msgID,H#v3_hdr.msgFlags,H#v3_hdr.msgSecurityModel]), - process_v3_msg(NoteStore, Msg, H, Data, Addr, Port, Logger); + process_v3_msg(NoteStore, Msg, H, Data, Addr, Logger); %% Crap {'EXIT', {bad_version, Vsn}} -> @@ -148,32 +150,27 @@ process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) -> %%----------------------------------------------------------------- %% Handles a Community based message (v1 or v2c). %%----------------------------------------------------------------- -process_v1_v2c_msg(Vsn, _NoteStore, Msg, Domain, - Addr, Port, - Community, Data, HS, Log) -> +process_v1_v2c_msg( + Vsn, _NoteStore, Msg, Domain, Addr, Community, Data, HS, Log) -> ?vdebug("process_v1_v2c_msg -> entry with" "~n Vsn: ~p" "~n Domain: ~p" "~n Addr: ~p" - "~n Port: ~p" "~n Community: ~p" - "~n HS: ~p", [Vsn, Domain, Addr, Port, Community, HS]), - + "~n HS: ~p", [Vsn, Domain, Addr, Community, HS]), + {TDomain, TAddress} = try - begin - TD = snmp_conf:mk_tdomain(Domain), - TA = snmp_conf:mk_taddress(Domain, Addr, Port), - {TD, TA} - end + {snmp_conf:mk_tdomain(Domain), + snmp_conf:mk_taddress(Domain, Addr)} catch throw:{error, TReason} -> throw({discarded, {badarg, Domain, TReason}}) end, Max = get_max_message_size(), - AgentMax = get_agent_max_message_size(Addr, Port), + AgentMax = get_agent_max_message_size(Domain, Addr), PduMS = pdu_ms(Max, AgentMax, HS), ?vtrace("process_v1_v2c_msg -> PduMS: ~p", [PduMS]), @@ -213,13 +210,12 @@ sec_model('version-2') -> ?SEC_V2C. %% Handles a SNMPv3 Message, following the procedures in rfc2272, %% section 4.2 and 7.2 %%----------------------------------------------------------------- -process_v3_msg(NoteStore, Msg, Hdr, Data, Addr, Port, Log) -> +process_v3_msg(NoteStore, Msg, Hdr, Data, Address, Log) -> + ?vdebug( + "process_v3_msg -> entry with~n" + " Hdr: ~p~n" + " Address: ~p", [Hdr, Address]), - ?vdebug("process_v3_msg -> entry with" - "~n Hdr: ~p" - "~n Addr: ~p" - "~n Port: ~p", [Hdr, Addr, Port]), - %% 7.2.3 #v3_hdr{msgID = MsgID, msgMaxSize = MMS, @@ -352,8 +348,8 @@ process_v3_msg(NoteStore, Msg, Hdr, Data, Addr, Port, Log) -> %% 4.2.2.1.1 - we don't handle proxys yet => we only %% handle CtxEngineID to ourselves %% Check that we actually know of an agent with this - %% CtxEngineID and Addr/Port - case is_known_engine_id(CtxEngineID, Addr, Port) of + %% CtxEngineID and Address + case is_known_engine_id(CtxEngineID, Address) of true -> ?vtrace("and the agent EngineID (~p) " "is know to us", [CtxEngineID]), @@ -866,14 +862,23 @@ get_max_message_size() -> end. %% The the MMS of the agent -get_agent_max_message_size(Addr, Port) -> - case snmpm_config:get_agent_engine_max_message_size(Addr, Port) of +get_agent_max_message_size(Domain, Addr) -> + case snmpm_config:get_agent_engine_max_message_size(Domain, Addr) of {ok, MMS} -> MMS; _Error -> - ?vlog("unknown agent: ~w:~w", [Addr, Port]), + ?vlog("unknown agent: ~s", + [snmp_conf:mk_addr_string({Domain, Addr})]), get_max_message_size() end. +%% get_agent_max_message_size(Addr, Port) -> +%% case snmpm_config:get_agent_engine_max_message_size(Addr, Port) of +%% {ok, MMS} -> +%% MMS; +%% _Error -> +%% ?vlog("unknown agent: ~w:~w", [Addr, Port]), +%% get_max_message_size() +%% end. %% Get "our" (manager) engine id get_engine_id() -> @@ -888,9 +893,12 @@ get_engine_id() -> get_agent_engine_id(Name) -> snmpm_config:get_agent_engine_id(Name). -is_known_engine_id(EngineID, Addr, Port) -> +is_known_engine_id(EngineID, {Addr, Port}) -> snmpm_config:is_known_engine_id(EngineID, Addr, Port). +%% is_known_engine_id(EngineID, Addr, Port) -> +%% snmpm_config:is_known_engine_id(EngineID, Addr, Port). + % get_agent_engine_id(Addr, Port) -> % case snmpm_config:get_agent_engine_id(Addr, Port) of % {ok, Id} -> diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl index 4d6bd9aa33..860b0b83dd 100644 --- a/lib/snmp/src/manager/snmpm_net_if.erl +++ b/lib/snmp/src/manager/snmpm_net_if.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -27,9 +27,9 @@ -export([ start_link/2, stop/1, - send_pdu/6, % Backward compatibillity - send_pdu/7, % Backward compatibillity - send_pdu/8, + send_pdu/6, % Backward compatibility + send_pdu/7, % Partly backward compatibility + send_pdu/8, % Backward compatibility inform_response/4, @@ -55,11 +55,12 @@ %% -define(VMODULE,"NET_IF"). -include("snmp_verbosity.hrl"). --record(state, +-record(state, { server, note_store, - sock, + domain, + sock, mpd_state, log, irb = auto, % auto | {user, integer()} @@ -99,30 +100,32 @@ start_link(Server, NoteStore) -> stop(Pid) -> call(Pid, stop). -send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port) -> - send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ?DEFAULT_EXTRA_INFO). +send_pdu(Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port) -> + send_pdu( + Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port, ?DEFAULT_EXTRA_INFO). -send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo) -> - Domain = snmpm_config:default_transport_domain(), - send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo). - -send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo) +send_pdu(Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port, ExtraInfo) when is_record(Pdu, pdu) -> - ?d("send_pdu -> entry with" - "~n Pid: ~p" - "~n Pdu: ~p" - "~n Vsn: ~p" - "~n MsgData: ~p" - "~n Domain: ~p" - "~n Addr: ~p" - "~n Port: ~p", [Pid, Pdu, Vsn, MsgData, Domain, Addr, Port]), - cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}). + ?d("send_pdu -> entry with~n" + " Pid: ~p~n" + " Pdu: ~p~n" + " Vsn: ~p~n" + " MsgData: ~p~n" + " Domain/IP: ~p~n" + " Addr/Port: ~p", + [Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port]), + {Domain, Addr} = address(Domain_or_Ip, Addr_or_Port), + cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo}). + +send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Ip, Port, ExtraInfo) -> + send_pdu(Pid, Pdu, Vsn, MsgData, Domain, {Ip, Port}, ExtraInfo). note_store(Pid, NoteStore) -> call(Pid, {note_store, NoteStore}). -inform_response(Pid, Ref, Addr, Port) -> - cast(Pid, {inform_response, Ref, Addr, Port}). +inform_response(Pid, Ref, Domain_or_Ip, Addr_or_Port) -> + {Domain, Addr} = address(Domain_or_Ip, Addr_or_Port), + cast(Pid, {inform_response, Ref, Domain, Addr}). info(Pid) -> call(Pid, info). @@ -199,7 +202,14 @@ do_init(Server, NoteStore) -> BindTo = get_opt(Opts, bind_to, false), NoReuse = get_opt(Opts, no_reuse, false), {ok, Port} = snmpm_config:system_info(port), - {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, BindTo, NoReuse), + Domain = + case snmpm_config:system_info(domain) of + {ok, D} -> + D; + _ -> + snmpm_config:default_transport_domain() + end, + {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, Domain, BindTo, NoReuse), %% Flow control -- FilterOpts = get_opt(Opts, filter, []), @@ -217,6 +227,7 @@ do_init(Server, NoteStore) -> State = #state{server = Server, note_store = NoteStore, mpd_state = MpdState, + domain = Domain, sock = Sock, log = Log, irb = IRB, @@ -227,18 +238,23 @@ do_init(Server, NoteStore) -> %% Open port -do_open_port(Port, SendSz, RecvSz, BindTo, NoReuse) -> - ?vtrace("do_open_port -> entry with" - "~n Port: ~p" - "~n SendSz: ~p" - "~n RecvSz: ~p" - "~n BindTo: ~p" - "~n NoReuse: ~p", [Port, SendSz, RecvSz, BindTo, NoReuse]), +do_open_port(Port, SendSz, RecvSz, Domain, BindTo, NoReuse) -> + ?vtrace("do_open_port -> entry with~n" + " Port: ~p~n" + " SendSz: ~p~n" + " RecvSz: ~p~n" + " Domain: ~p~n" + " BindTo: ~p~n" + " NoReuse: ~p", + [Port, SendSz, RecvSz, Domain, BindTo, NoReuse]), IpOpts1 = bind_to(BindTo), IpOpts2 = no_reuse(NoReuse), IpOpts3 = recbuf(RecvSz), IpOpts4 = sndbuf(SendSz), - IpOpts = [binary | IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], + IpOpts = + [binary, + snmp_conf:tdomain_to_family(Domain) | + IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], OpenRes = case init:get_argument(snmpm_fd) of {ok, [[FdStr]]} -> @@ -386,25 +402,24 @@ handle_call(Req, From, State) -> %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- -handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}, +handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo}, State) -> - ?vlog("received send_pdu message with" - "~n Pdu: ~p" - "~n Vsn: ~p" - "~n MsgData: ~p" - "~n Domain: ~p" - "~n Addr: ~p" - "~n Port: ~p", [Pdu, Vsn, MsgData, Domain, Addr, Port]), - maybe_process_extra_info(ExtraInfo), - maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State), + ?vlog("received send_pdu message with~n" + " Pdu: ~p~n" + " Vsn: ~p~n" + " MsgData: ~p~n" + " Domain: ~p~n" + " Addr : ~p", [Pdu, Vsn, MsgData, Domain, Addr]), + maybe_process_extra_info(ExtraInfo), + maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State), {noreply, State}; -handle_cast({inform_response, Ref, Addr, Port}, State) -> - ?vlog("received inform_response message with" - "~n Ref: ~p" - "~n Addr: ~p" - "~n Port: ~p", [Ref, Addr, Port]), - handle_inform_response(Ref, Addr, Port, State), +handle_cast({inform_response, Ref, Domain, Addr}, State) -> + ?vlog("received inform_response message with~n" + " Ref: ~p~n" + " Domain: ~p~n" + " Addr: ~p", [Ref, Domain, Addr]), + handle_inform_response(Ref, Domain, Addr, State), {noreply, State}; handle_cast(filter_reset, State) -> @@ -423,9 +438,11 @@ handle_cast(Msg, State) -> %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- -handle_info({udp, Sock, Ip, Port, Bytes}, #state{sock = Sock} = State) -> +handle_info( + {udp, Sock, Ip, Port, Bytes}, + #state{sock = Sock, domain = Domain} = State) -> ?vlog("received ~w bytes from ~p:~p [~w]", [size(Bytes), Ip, Port, Sock]), - maybe_handle_recv_msg(Ip, Port, Bytes, State), + maybe_handle_recv_msg(Domain, {Ip, Port}, Bytes, State), {noreply, State}; handle_info(inform_response_gc, State) -> @@ -531,48 +548,50 @@ code_change(_Vsn, State, _Extra) -> %%% Internal functions %%%------------------------------------------------------------------- -maybe_handle_recv_msg(Addr, Port, Bytes, #state{filter = FilterMod} = State) -> - case (catch FilterMod:accept_recv(Addr, Port)) of +maybe_handle_recv_msg( + Domain, Addr, Bytes, + #state{filter = FilterMod, domain = ManagerDomain} = State) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_recv(Arg1, Arg2)) of false -> %% Drop the received packet inc(netIfMsgInDrops), ok; _ -> - handle_recv_msg(Addr, Port, Bytes, State) + handle_recv_msg(Domain, Addr, Bytes, State) end. -handle_recv_msg(Addr, Port, Bytes, #state{server = Pid}) +handle_recv_msg(Domain, Addr, Bytes, #state{server = Pid}) when is_binary(Bytes) andalso (size(Bytes) =:= 0) -> - Pid ! {snmp_error, {empty_message, Addr, Port}, Addr, Port}, + Pid ! {snmp_error, {empty_message, Domain, Addr}, Domain, Addr}, ok; -handle_recv_msg(Addr, Port, Bytes, - #state{server = Pid, - note_store = NoteStore, - mpd_state = MpdState, - sock = Sock, - log = Log} = State) -> - Domain = snmp_conf:which_domain(Addr), % What the ****... - Logger = logger(Log, read, Addr, Port), - case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, Port, +handle_recv_msg( + Domain, Addr, Bytes, + #state{server = Pid, + note_store = NoteStore, + mpd_state = MpdState, + log = Log} = State) -> + Logger = logger(Log, read, Domain, Addr), + case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, MpdState, NoteStore, Logger)) of {ok, Vsn, Pdu, MS, ACM} -> - maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, MS, ACM, + maybe_handle_recv_pdu(Domain, Addr, Vsn, Pdu, MS, ACM, Logger, State); {discarded, Reason, Report} -> ?vdebug("discarded: ~p", [Reason]), ErrorInfo = {failed_processing_message, Reason}, - Pid ! {snmp_error, ErrorInfo, Addr, Port}, - maybe_udp_send(State#state.filter, Sock, Addr, Port, Report), + Pid ! {snmp_error, ErrorInfo, Domain, Addr}, + maybe_udp_send(Domain, Addr, Report, State), ok; {discarded, Reason} -> ?vdebug("discarded: ~p", [Reason]), ErrorInfo = {failed_processing_message, Reason}, - Pid ! {snmp_error, ErrorInfo, Addr, Port}, + Pid ! {snmp_error, ErrorInfo, Domain, Addr}, ok; Error -> @@ -582,88 +601,94 @@ handle_recv_msg(Addr, Port, Bytes, end. -maybe_handle_recv_pdu(Addr, Port, - Vsn, #pdu{type = Type} = Pdu, PduMS, ACM, - Logger, - #state{filter = FilterMod} = State) -> - case (catch FilterMod:accept_recv_pdu(Addr, Port, Type)) of +maybe_handle_recv_pdu( + Domain, Addr, Vsn, #pdu{type = Type} = Pdu, PduMS, ACM, Logger, + #state{filter = FilterMod, domain = ManagerDomain} = State) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, Type)) of false -> inc(netIfPduInDrops), ok; _ -> - handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State) + handle_recv_pdu( + Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State) end; -maybe_handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger, - #state{filter = FilterMod} = State) +maybe_handle_recv_pdu( + Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, + #state{filter = FilterMod, domain = ManagerDomain} = State) when is_record(Trap, trappdu) -> - case (catch FilterMod:accept_recv_pdu(Addr, Port, trappdu)) of + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, trappdu)) of false -> inc(netIfPduInDrops), ok; _ -> - handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger, State) + handle_recv_pdu( + Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, State) end; -maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State) -> - handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State). - - -handle_recv_pdu(Addr, Port, - Vsn, #pdu{type = 'inform-request'} = Pdu, _PduMS, ACM, - Logger, #state{server = Pid, irb = IRB} = State) -> - handle_inform_request(IRB, Pid, Vsn, Pdu, ACM, - Addr, Port, Logger, State); -handle_recv_pdu(Addr, Port, - _Vsn, #pdu{type = report} = Pdu, _PduMS, ok, - _Logger, - #state{server = Pid} = _State) -> +maybe_handle_recv_pdu( + Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State) -> + handle_recv_pdu(Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State). + + +handle_recv_pdu( + Domain, Addr, Vsn, + #pdu{type = 'inform-request'} = Pdu, _PduMS, ACM, Logger, + #state{server = Pid, irb = IRB} = State) -> + handle_inform_request( + IRB, Pid, Vsn, Pdu, ACM, Domain, Addr, Logger, State); +handle_recv_pdu( + Domain, Addr, _Vsn, + #pdu{type = report} = Pdu, _PduMS, ok, _Logger, + #state{server = Pid} = _State) -> ?vtrace("received report - ok", []), - Pid ! {snmp_report, {ok, Pdu}, Addr, Port}; -handle_recv_pdu(Addr, Port, - _Vsn, #pdu{type = report} = Pdu, _PduMS, - {error, ReqId, Reason}, - _Logger, - #state{server = Pid} = _State) -> + Pid ! {snmp_report, {ok, Pdu}, Domain, Addr}; +handle_recv_pdu( + Domain, Addr, _Vsn, + #pdu{type = report} = Pdu, _PduMS, {error, ReqId, Reason}, _Logger, + #state{server = Pid} = _State) -> ?vtrace("received report - error", []), - Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Addr, Port}; -handle_recv_pdu(Addr, Port, - _Vsn, #pdu{type = 'snmpv2-trap'} = Pdu, _PduMS, _ACM, - _Logger, - #state{server = Pid} = _State) -> + Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Domain, Addr}; +handle_recv_pdu( + Domain, Addr, _Vsn, + #pdu{type = 'snmpv2-trap'} = Pdu, _PduMS, _ACM, _Logger, + #state{server = Pid} = _State) -> ?vtrace("received snmpv2-trap", []), - Pid ! {snmp_trap, Pdu, Addr, Port}; -handle_recv_pdu(Addr, Port, - _Vsn, Trap, _PduMS, _ACM, - _Logger, - #state{server = Pid} = _State) when is_record(Trap, trappdu) -> + Pid ! {snmp_trap, Pdu, Domain, Addr}; +handle_recv_pdu( + Domain, Addr, _Vsn, Trap, _PduMS, _ACM, _Logger, + #state{server = Pid} = _State) when is_record(Trap, trappdu) -> ?vtrace("received trappdu", []), - Pid ! {snmp_trap, Trap, Addr, Port}; -handle_recv_pdu(Addr, Port, - _Vsn, Pdu, _PduMS, _ACM, - _Logger, - #state{server = Pid} = _State) when is_record(Pdu, pdu) -> + Pid ! {snmp_trap, Trap, Domain, Addr}; +handle_recv_pdu( + Domain, Addr, _Vsn, Pdu, _PduMS, _ACM, _Logger, + #state{server = Pid} = _State) when is_record(Pdu, pdu) -> ?vtrace("received pdu", []), - Pid ! {snmp_pdu, Pdu, Addr, Port}; -handle_recv_pdu(_Addr, _Port, _Vsn, Pdu, _PduMS, ACM, _Logger, _State) -> + Pid ! {snmp_pdu, Pdu, Domain, Addr}; +handle_recv_pdu( + _Domain, _Addr, _Vsn, Pdu, _PduMS, ACM, _Logger, _State) -> ?vlog("received unexpected pdu: " - "~n Pdu: ~p" - "~n ACM: ~p", [Pdu, ACM]). + "~n Pdu: ~p" + "~n ACM: ~p", [Pdu, ACM]). -handle_inform_request(auto, Pid, Vsn, Pdu, ACM, Addr, Port, Logger, State) -> +handle_inform_request( + auto, Pid, Vsn, Pdu, ACM, Domain, Addr, Logger, State) -> ?vtrace("received inform-request (true)", []), - Pid ! {snmp_inform, ignore, Pdu, Addr, Port}, + Pid ! {snmp_inform, ignore, Pdu, Domain, Addr}, RePdu = make_response_pdu(Pdu), - maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger, State); -handle_inform_request({user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu, - ACM, Addr, Port, _Logger, _State) -> + maybe_send_inform_response(RePdu, Vsn, ACM, Domain, Addr, Logger, State); +handle_inform_request( + {user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu, + ACM, Domain, Addr, _Logger, _State) -> ?vtrace("received inform-request (false)", []), - Pid ! {snmp_inform, ReqId, Pdu, Addr, Port}, + Pid ! {snmp_inform, ReqId, Pdu, Domain, Addr}, %% Before we go any further, we need to check that we have not %% already received this message (possible resend). - Key = {ReqId, Addr, Port}, + Key = {ReqId, Domain, Addr}, case ets:lookup(snmpm_inform_request_table, Key) of [_] -> %% OK, we already know about this. We assume this @@ -676,39 +701,43 @@ handle_inform_request({user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu, Rec = {Key, Expire, {Vsn, ACM, RePdu}}, ets:insert(snmpm_inform_request_table, Rec) end. - -handle_inform_response(Ref, Addr, Port, State) -> - Key = {Ref, Addr, Port}, + +handle_inform_response(Ref, Domain, Addr, State) -> + Key = {Ref, Domain, Addr}, case ets:lookup(snmpm_inform_request_table, Key) of [{Key, _, {Vsn, ACM, RePdu}}] -> - Logger = logger(State#state.log, read, Addr, Port), + Logger = logger(State#state.log, read, Domain, Addr), ets:delete(snmpm_inform_request_table, Key), - maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, - Logger, State); + maybe_send_inform_response( + RePdu, Vsn, ACM, Domain, Addr, Logger, State); [] -> %% Already acknowledged, or the user was to slow to reply... ok end, ok. -maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger, - #state{server = Pid, - sock = Sock, - filter = FilterMod}) -> - case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(RePdu))) of +maybe_send_inform_response( + RePdu, Vsn, ACM, Domain, Addr, Logger, + #state{server = Pid, + filter = FilterMod, + domain = ManagerDomain} = State) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_send_pdu( + Arg1, Arg2, pdu_type_of(RePdu))) + of false -> inc(netIfPduOutDrops), ok; _ -> case snmpm_mpd:generate_response_msg(Vsn, RePdu, ACM, Logger) of {ok, Msg} -> - maybe_udp_send(FilterMod, Sock, Addr, Port, Msg); + maybe_udp_send(Domain, Addr, Msg, State); {discarded, Reason} -> ?vlog("failed generating response message:" "~n Reason: ~p", [Reason]), ReqId = RePdu#pdu.request_id, ErrorInfo = {failed_generating_response, {RePdu, Reason}}, - Pid ! {snmp_error, ReqId, ErrorInfo, Addr, Port}, + Pid ! {snmp_error, ReqId, ErrorInfo, Domain, Addr}, ok end end. @@ -743,28 +772,29 @@ irgc_stop(Ref) -> (catch erlang:cancel_timer(Ref)). -maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, - #state{filter = FilterMod} = State) -> - case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(Pdu))) of +maybe_handle_send_pdu( + Pdu, Vsn, MsgData, Domain, Addr, + #state{filter = FilterMod, domain = ManagerDomain} = State) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_send_pdu(Arg1, Arg2, pdu_type_of(Pdu))) of false -> inc(netIfPduOutDrops), ok; _ -> - handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State) + handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State) end. -handle_send_pdu(Pdu, Vsn, MsgData, _Domain, Addr, Port, - #state{server = Pid, - note_store = NoteStore, - sock = Sock, - log = Log, - filter = FilterMod}) -> - Logger = logger(Log, write, Addr, Port), - case (catch snmpm_mpd:generate_msg(Vsn, NoteStore, - Pdu, MsgData, Logger)) of +handle_send_pdu( + Pdu, Vsn, MsgData, Domain, Addr, + #state{server = Pid, + note_store = NoteStore, + log = Log} = State) -> + Logger = logger(Log, write, Domain, Addr), + case (catch snmpm_mpd:generate_msg( + Vsn, NoteStore, Pdu, MsgData, Logger)) of {ok, Msg} -> ?vtrace("handle_send_pdu -> message generated", []), - maybe_udp_send(FilterMod, Sock, Addr, Port, Msg); + maybe_udp_send(Domain, Addr, Msg, State); {discarded, Reason} -> ?vlog("PDU not sent: " "~n PDU: ~p" @@ -774,28 +804,34 @@ handle_send_pdu(Pdu, Vsn, MsgData, _Domain, Addr, Port, end. -maybe_udp_send(FilterMod, Sock, Addr, Port, Msg) -> - case (catch FilterMod:accept_send(Addr, Port)) of +maybe_udp_send( + Domain, Addr, Msg, + #state{sock = Sock, filter = FilterMod, domain = ManagerDomain}) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_send(Arg1, Arg2)) of false -> inc(netIfMsgOutDrops), ok; _ -> - udp_send(Sock, Addr, Port, Msg) + %% XXX There should be some kind of lookup of socket + %% from transport domain here + {Ip, Port} = Addr, + udp_send(Sock, Ip, Port, Msg) end. -udp_send(Sock, Addr, Port, Msg) -> - case (catch gen_udp:send(Sock, Addr, Port, Msg)) of +udp_send(Sock, Ip, Port, Msg) -> + case (catch gen_udp:send(Sock, Ip, Port, Msg)) of ok -> ?vdebug("sent ~w bytes to ~w:~w [~w]", - [sz(Msg), Addr, Port, Sock]), + [sz(Msg), Ip, Port, Sock]), ok; {error, Reason} -> error_msg("failed sending message to ~p:~p: " - "~n ~p",[Addr, Port, Reason]); + "~n ~p",[Ip, Port, Reason]); Error -> error_msg("failed sending message to ~p:~p: " - "~n ~p",[Addr, Port, Error]) + "~n ~p",[Ip, Port, Error]) end. sz(B) when is_binary(B) -> @@ -989,6 +1025,26 @@ handle_set_log_type(State, _NewType) -> {State, {error, not_enabled}}. +%% If the manager uses legacy snmpUDPDomain e.g has not set +%% {domain, _}, then make sure snmpm_network_interface_filter +%% gets legacy arguments to not break backwards compatibility. +%% +fix_filter_address(snmpUDPDomain, {Domain, Addr}) + when Domain =:= snmpUDPDomain; + Domain =:= transportDomainUdpIpv4 -> + Addr; +fix_filter_address(_ManagerDomain, {Domain, _} = Address) + when is_atom(Domain) -> + Address; +fix_filter_address(snmpUDPDomain, {_, Port} = Addr) + when is_integer(Port) -> + Addr. + +address(Domain, Addr) when is_atom(Domain) -> + {Domain, Addr}; +address(Ip, Port) when is_integer(Port) -> + {snmpm_config:default_transport_domain(), {Ip, Port}}. + %% ------------------------------------------------------------------- make_response_pdu(#pdu{request_id = ReqId, varbinds = Vbs}) -> @@ -1029,15 +1085,17 @@ t() -> %% ------------------------------------------------------------------- -logger(undefined, _Type, _Addr, _Port) -> +logger(undefined, _Type, _Domain, _Addr) -> fun(_) -> ok end; -logger({Log, Types}, Type, Addr, Port) -> +logger({Log, Types}, Type, Domain, Addr) -> case lists:member(Type, Types) of true -> + AddrString = + iolist_to_binary(snmp_conf:mk_addr_string({Domain, Addr})), fun(Msg) -> - snmp_log:log(Log, Msg, Addr, Port) + snmp_log:log(Log, Msg, AddrString) end; false -> fun(_) -> diff --git a/lib/snmp/src/manager/snmpm_net_if_filter.erl b/lib/snmp/src/manager/snmpm_net_if_filter.erl index eb0c6efb11..d96ae5c145 100644 --- a/lib/snmp/src/manager/snmpm_net_if_filter.erl +++ b/lib/snmp/src/manager/snmpm_net_if_filter.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009. All Rights Reserved. +%% Copyright Ericsson AB 2009-2014. 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 @@ -25,29 +25,51 @@ -include("snmp_debug.hrl"). -accept_recv(_Addr, _Port) -> - ?d("accept_recv -> entry with" - "~n Addr: ~p" - "~n Port: ~p", [_Addr, _Port]), +accept_recv(Domain, _Address) when is_atom(Domain) -> + ?d("accept_recv -> entry with~n" + " Domain: ~p~n" + " Address: ~p", [Domain, _Address]), + true; +accept_recv(_Addr, Port) when is_integer(Port) -> + ?d("accept_recv -> entry with~n" + " Addr: ~p~n" + " Port: ~p", [_Addr, Port]), true. -accept_send(_Addr, _Port) -> - ?d("accept_send -> entry with" - "~n Addr: ~p" - "~n Port: ~p", [_Addr, _Port]), +accept_send(Domain, _Address) when is_atom(Domain) -> + ?d("accept_send -> entry with~n" + " Domain: ~p~n" + " Address: ~p", [Domain, _Address]), + true; +accept_send(_Addr, Port) when is_integer(Port) -> + ?d("accept_send -> entry with~n" + " Addr: ~p~n" + " Port: ~p", [_Addr, Port]), true. -accept_recv_pdu(_Addr, _Port, _PduType) -> - ?d("accept_recv_pdu -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n PduType: ~p", [_Addr, _Port, _PduType]), +accept_recv_pdu(Domain, _Address, _PduType) when is_atom(Domain) -> + ?d("accept_recv_pdu -> entry with~n" + " Domain: ~p~n" + " Address: ~p~n" + " PduType: ~p", [Domain, _Address, _PduType]), + true; +accept_recv_pdu(_Addr, Port, _PduType) when is_integer(Port) -> + ?d("accept_recv_pdu -> entry with~n" + " Addr: ~p~n" + " Port: ~p~n" + " PduType: ~p", [_Addr, Port, _PduType]), true. -accept_send_pdu(_Addr, _Port, _PduType) -> - ?d("accept_send_pdu -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n PduType: ~p", [_Addr, _Port, _PduType]), +accept_send_pdu(Domain, _Address, _PduType) when is_atom(Domain) -> + ?d("accept_send_pdu -> entry with~n" + " Domain: ~p~n" + " Address: ~p~n" + " PduType: ~p", [Domain, _Address, _PduType]), + true; +accept_send_pdu(_Addr, Port, _PduType) when is_integer(Port) -> + ?d("accept_send_pdu -> entry with~n" + " Addr: ~p~n" + " Port: ~p~n" + " PduType: ~p", [_Addr, Port, _PduType]), true. diff --git a/lib/snmp/src/manager/snmpm_net_if_mt.erl b/lib/snmp/src/manager/snmpm_net_if_mt.erl index 3e87f6a7fb..2937f5cc87 100644 --- a/lib/snmp/src/manager/snmpm_net_if_mt.erl +++ b/lib/snmp/src/manager/snmpm_net_if_mt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -27,9 +27,9 @@ -export([ start_link/2, stop/1, - send_pdu/6, % Backward compatibillity - send_pdu/7, % Backward compatibillity - send_pdu/8, + send_pdu/6, % Backward compatibility + send_pdu/7, % Partly backward compatibility + send_pdu/8, % Backward compatibility inform_response/4, @@ -55,13 +55,14 @@ %% -define(VMODULE,"NET_IF"). -include("snmp_verbosity.hrl"). --record(state, +-record(state, { server, note_store, - sock, + domain, + sock, mpd_state, - log, + log, irb = auto, % auto | {user, integer()} irgc, filter @@ -99,30 +100,32 @@ start_link(Server, NoteStore) -> stop(Pid) -> call(Pid, stop). -send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port) -> - send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ?DEFAULT_EXTRA_INFO). +send_pdu(Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port) -> + send_pdu( + Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port, ?DEFAULT_EXTRA_INFO). -send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo) -> - Domain = snmpm_config:default_transport_domain(), - send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo). - -send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo) +send_pdu(Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port, ExtraInfo) when is_record(Pdu, pdu) -> - ?d("send_pdu -> entry with" - "~n Pid: ~p" - "~n Pdu: ~p" - "~n Vsn: ~p" - "~n MsgData: ~p" - "~n Domain: ~p" - "~n Addr: ~p" - "~n Port: ~p", [Pid, Pdu, Vsn, MsgData, Domain, Addr, Port]), - cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}). + ?d("send_pdu -> entry with~n" + " Pid: ~p~n" + " Pdu: ~p~n" + " Vsn: ~p~n" + " MsgData: ~p~n" + " Domain/IP: ~p~n" + " Addr/Port : ~p", + [Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port]), + {Domain, Addr} = address(Domain_or_Ip, Addr_or_Port), + cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo}). + +send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Ip, Port, ExtraInfo) -> + send_pdu(Pid, Pdu, Vsn, MsgData, Domain, {Ip, Port}, ExtraInfo). note_store(Pid, NoteStore) -> call(Pid, {note_store, NoteStore}). -inform_response(Pid, Ref, Addr, Port) -> - cast(Pid, {inform_response, Ref, Addr, Port}). +inform_response(Pid, Ref, Domain_or_Ip, Addr_or_Port) -> + {Domain, Addr} = address(Domain_or_Ip, Addr_or_Port), + cast(Pid, {inform_response, Ref, Domain, Addr}). info(Pid) -> call(Pid, info). @@ -202,7 +205,14 @@ do_init(Server, NoteStore) -> BindTo = get_opt(Opts, bind_to, false), NoReuse = get_opt(Opts, no_reuse, false), {ok, Port} = snmpm_config:system_info(port), - {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, BindTo, NoReuse), + Domain = + case snmpm_config:system_info(domain) of + {ok, D} -> + D; + _ -> + snmpm_config:default_transport_domain() + end, + {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, Domain, BindTo, NoReuse), %% Flow control -- FilterOpts = get_opt(Opts, filter, []), @@ -218,10 +228,11 @@ do_init(Server, NoteStore) -> init_counters(), %% -- We are done --- - State = #state{server = Server, - note_store = NoteStore, + State = #state{server = Server, + note_store = NoteStore, mpd_state = MpdState, - sock = Sock, + domain = Domain, + sock = Sock, log = Log, irb = IRB, irgc = IrGcRef, @@ -231,19 +242,24 @@ do_init(Server, NoteStore) -> %% Open port -do_open_port(Port, SendSz, RecvSz, BindTo, NoReuse) -> - ?vtrace("do_open_port -> entry with" - "~n Port: ~p" - "~n SendSz: ~p" - "~n RecvSz: ~p" - "~n BindTo: ~p" - "~n NoReuse: ~p", [Port, SendSz, RecvSz, BindTo, NoReuse]), +do_open_port(Port, SendSz, RecvSz, Domain, BindTo, NoReuse) -> + ?vtrace("do_open_port -> entry with~n" + " Port: ~p~n" + " SendSz: ~p~n" + " RecvSz: ~p~n" + " Domain: ~p~n" + " BindTo: ~p~n" + " NoReuse: ~p", + [Port, SendSz, RecvSz, Domain, BindTo, NoReuse]), IpOpts1 = bind_to(BindTo), IpOpts2 = no_reuse(NoReuse), IpOpts3 = recbuf(RecvSz), IpOpts4 = sndbuf(SendSz), - IpOpts = [binary | IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], - OpenRes = + IpOpts = + [binary, + snmp_conf:tdomain_to_family(Domain) | + IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], + OpenRes = case init:get_argument(snmpm_fd) of {ok, [[FdStr]]} -> Fd = list_to_integer(FdStr), @@ -396,25 +412,24 @@ handle_call(Req, From, State) -> %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- -handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}, +handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo}, State) -> - ?vlog("received send_pdu message with" - "~n Pdu: ~p" - "~n Vsn: ~p" - "~n MsgData: ~p" - "~n Domain: ~p" - "~n Addr: ~p" - "~n Port: ~p", [Pdu, Vsn, MsgData, Domain, Addr, Port]), - maybe_process_extra_info(ExtraInfo), - handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State), + ?vlog("received send_pdu message with~n" + " Pdu: ~p~n" + " Vsn: ~p~n" + " MsgData: ~p~n" + " Domain: ~p~n" + " Addr: ~p", [Pdu, Vsn, MsgData, Domain, Addr]), + maybe_process_extra_info(ExtraInfo), + handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State), {noreply, State}; -handle_cast({inform_response, Ref, Addr, Port}, State) -> - ?vlog("received inform_response message with" - "~n Ref: ~p" - "~n Addr: ~p" - "~n Port: ~p", [Ref, Addr, Port]), - handle_inform_response(Ref, Addr, Port, State), +handle_cast({inform_response, Ref, Domain, Addr}, State) -> + ?vlog("received inform_response message with~n" + " Ref: ~p~n" + " Domain: ~p~n" + " Addr: ~p", [Ref, Domain, Addr]), + handle_inform_response(Ref, Domain, Addr, State), {noreply, State}; handle_cast(filter_reset, State) -> @@ -433,9 +448,11 @@ handle_cast(Msg, State) -> %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- -handle_info({udp, Sock, Ip, Port, Bytes}, #state{sock = Sock} = State) -> +handle_info( + {udp, Sock, Ip, Port, Bytes}, + #state{sock = Sock, domain = Domain} = State) -> ?vlog("received ~w bytes from ~p:~p", [size(Bytes), Ip, Port]), - handle_udp(Ip, Port, Bytes, State), + handle_udp(Domain, {Ip, Port}, Bytes, State), {noreply, State}; handle_info(inform_response_gc, State) -> @@ -500,60 +517,64 @@ code_change(_Vsn, State, _Extra) -> %%% Internal functions %%%------------------------------------------------------------------- -handle_udp(Addr, Port, Bytes, State) -> - Verbosity = get(verbosity), - spawn_opt(fun() -> - Log = worker_init(State, Verbosity), - Res = (catch maybe_handle_recv_msg( - Addr, Port, Bytes, - State#state{log = Log})), - worker_exit(udp, {Addr, Port}, Res) - end, - [monitor]). - - -maybe_handle_recv_msg(Addr, Port, Bytes, #state{filter = FilterMod} = State) -> - case (catch FilterMod:accept_recv(Addr, Port)) of +handle_udp(Domain, Addr, Bytes, State) -> + Verbosity = get(verbosity), + spawn_opt( + fun() -> + Log = worker_init(State, Verbosity), + Res = + (catch maybe_handle_recv_msg( + Domain, Addr, Bytes, + State#state{log = Log})), + worker_exit(udp, {Domain, Addr}, Res) + end, + [monitor]). + + +maybe_handle_recv_msg( + Domain, Addr, Bytes, + #state{filter = FilterMod, domain = ManagerDomain} = State) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_recv(Arg1, Arg2)) of false -> - %% Drop the received packet + %% Drop the received packet inc(netIfMsgInDrops), ok; _ -> - handle_recv_msg(Addr, Port, Bytes, State) + handle_recv_msg(Domain, Addr, Bytes, State) end. -handle_recv_msg(Addr, Port, Bytes, #state{server = Pid}) +handle_recv_msg(Domain, Addr, Bytes, #state{server = Pid}) when is_binary(Bytes) andalso (size(Bytes) =:= 0) -> - Pid ! {snmp_error, {empty_message, Addr, Port}, Addr, Port}, + Pid ! {snmp_error, {empty_message, Domain, Addr}, Domain, Addr}, ok; -handle_recv_msg(Addr, Port, Bytes, - #state{server = Pid, - note_store = NoteStore, - mpd_state = MpdState, - sock = Sock, - log = Log} = State) -> - Domain = snmp_conf:which_domain(Addr), % What the ****... - Logger = logger(Log, read, Addr, Port), - case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, Port, +handle_recv_msg( + Domain, Addr, Bytes, + #state{server = Pid, + note_store = NoteStore, + mpd_state = MpdState, + log = Log} = State) -> + Logger = logger(Log, read, Domain, Addr), + case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, MpdState, NoteStore, Logger)) of {ok, Vsn, Pdu, MS, ACM} -> - maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, MS, ACM, + maybe_handle_recv_pdu(Domain, Addr, Vsn, Pdu, MS, ACM, Logger, State); {discarded, Reason, Report} -> ?vdebug("discarded: ~p", [Reason]), ErrorInfo = {failed_processing_message, Reason}, - Pid ! {snmp_error, ErrorInfo, Addr, Port}, - maybe_udp_send(State#state.filter, Sock, Addr, Port, Report), + Pid ! {snmp_error, ErrorInfo, Domain, Addr}, + maybe_udp_send(Domain, Addr, Report, State), ok; {discarded, Reason} -> ?vdebug("discarded: ~p", [Reason]), ErrorInfo = {failed_processing_message, Reason}, - Pid ! {snmp_error, ErrorInfo, Addr, Port}, + Pid ! {snmp_error, ErrorInfo, Domain, Addr}, ok; Error -> @@ -563,94 +584,100 @@ handle_recv_msg(Addr, Port, Bytes, end. -maybe_handle_recv_pdu(Addr, Port, - Vsn, #pdu{type = Type} = Pdu, PduMS, ACM, - Logger, - #state{filter = FilterMod} = State) -> - case (catch FilterMod:accept_recv_pdu(Addr, Port, Type)) of +maybe_handle_recv_pdu( + Domain, Addr, Vsn, #pdu{type = Type} = Pdu, PduMS, ACM, Logger, + #state{filter = FilterMod, domain = ManagerDomain} = State) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, Type)) of false -> inc(netIfPduInDrops), ok; _ -> - handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State) + handle_recv_pdu( + Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State) end; -maybe_handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger, - #state{filter = FilterMod} = State) +maybe_handle_recv_pdu( + Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, + #state{filter = FilterMod, domain = ManagerDomain} = State) when is_record(Trap, trappdu) -> - case (catch FilterMod:accept_recv_pdu(Addr, Port, trappdu)) of + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, trappdu)) of false -> inc(netIfPduInDrops), ok; _ -> - handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger, State) + handle_recv_pdu( + Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, State) end; -maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State) -> - handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State). - - -handle_recv_pdu(Addr, Port, - Vsn, #pdu{type = 'inform-request'} = Pdu, _PduMS, ACM, - Logger, #state{server = Pid, irb = IRB} = State) -> - handle_inform_request(IRB, Pid, Vsn, Pdu, ACM, - Addr, Port, Logger, State); -handle_recv_pdu(Addr, Port, - _Vsn, #pdu{type = report} = Pdu, _PduMS, ok, - _Logger, - #state{server = Pid} = _State) -> +maybe_handle_recv_pdu( + Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State) -> + handle_recv_pdu(Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State). + + +handle_recv_pdu( + Domain, Addr, Vsn, + #pdu{type = 'inform-request'} = Pdu, _PduMS, ACM, Logger, + #state{server = Pid, irb = IRB} = State) -> + handle_inform_request( + IRB, Pid, Vsn, Pdu, ACM, Domain, Addr, Logger, State); +handle_recv_pdu( + Domain, Addr, _Vsn, + #pdu{type = report} = Pdu, _PduMS, ok, _Logger, + #state{server = Pid} = _State) -> ?vtrace("received report - ok", []), - Pid ! {snmp_report, {ok, Pdu}, Addr, Port}, + Pid ! {snmp_report, {ok, Pdu}, Domain, Addr}, ok; -handle_recv_pdu(Addr, Port, - _Vsn, #pdu{type = report} = Pdu, _PduMS, - {error, ReqId, Reason}, - _Logger, - #state{server = Pid} = _State) -> +handle_recv_pdu( + Domain, Addr, _Vsn, + #pdu{type = report} = Pdu, _PduMS, {error, ReqId, Reason}, _Logger, + #state{server = Pid} = _State) -> ?vtrace("received report - error", []), - Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Addr, Port}, + Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Domain, Addr}, ok; -handle_recv_pdu(Addr, Port, - _Vsn, #pdu{type = 'snmpv2-trap'} = Pdu, _PduMS, _ACM, - _Logger, - #state{server = Pid} = _State) -> +handle_recv_pdu( + Domain, Addr, _Vsn, + #pdu{type = 'snmpv2-trap'} = Pdu, _PduMS, _ACM, _Logger, + #state{server = Pid} = _State) -> ?vtrace("received snmpv2-trap", []), - Pid ! {snmp_trap, Pdu, Addr, Port}, + Pid ! {snmp_trap, Pdu, Domain, Addr}, ok; -handle_recv_pdu(Addr, Port, - _Vsn, Trap, _PduMS, _ACM, - _Logger, - #state{server = Pid} = _State) when is_record(Trap, trappdu) -> +handle_recv_pdu( + Domain, Addr, _Vsn, Trap, _PduMS, _ACM, _Logger, + #state{server = Pid} = _State) when is_record(Trap, trappdu) -> ?vtrace("received trappdu", []), - Pid ! {snmp_trap, Trap, Addr, Port}, + Pid ! {snmp_trap, Trap, Domain, Addr}, ok; -handle_recv_pdu(Addr, Port, - _Vsn, Pdu, _PduMS, _ACM, - _Logger, - #state{server = Pid} = _State) when is_record(Pdu, pdu) -> +handle_recv_pdu( + Domain, Addr, _Vsn, Pdu, _PduMS, _ACM, _Logger, + #state{server = Pid} = _State) when is_record(Pdu, pdu) -> ?vtrace("received pdu", []), - Pid ! {snmp_pdu, Pdu, Addr, Port}, + Pid ! {snmp_pdu, Pdu, Domain, Addr}, ok; -handle_recv_pdu(_Addr, _Port, _Vsn, Pdu, _PduMS, ACM, _Logger, _State) -> +handle_recv_pdu( + _Domain, _Addr, _Vsn, Pdu, _PduMS, ACM, _Logger, _State) -> ?vlog("received unexpected pdu: " "~n Pdu: ~p" "~n ACM: ~p", [Pdu, ACM]), ok. -handle_inform_request(auto, Pid, Vsn, Pdu, ACM, Addr, Port, Logger, State) -> +handle_inform_request( + auto, Pid, Vsn, Pdu, ACM, Domain, Addr, Logger, State) -> ?vtrace("received inform-request (true)", []), - Pid ! {snmp_inform, ignore, Pdu, Addr, Port}, + Pid ! {snmp_inform, ignore, Pdu, Domain, Addr}, RePdu = make_response_pdu(Pdu), - maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger, State); -handle_inform_request({user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu, - ACM, Addr, Port, _Logger, _State) -> + maybe_send_inform_response(RePdu, Vsn, ACM, Domain, Addr, Logger, State); +handle_inform_request( + {user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu, + ACM, Domain, Addr, _Logger, _State) -> ?vtrace("received inform-request (false)", []), - Pid ! {snmp_inform, ReqId, Pdu, Addr, Port}, + Pid ! {snmp_inform, ReqId, Pdu, Domain, Addr}, %% Before we go any further, we need to check that we have not %% already received this message (possible resend). - Key = {ReqId, Addr, Port}, + Key = {ReqId, Domain, Addr}, case ets:lookup(snmpm_inform_request_table, Key) of [_] -> %% OK, we already know about this. We assume this @@ -664,53 +691,58 @@ handle_inform_request({user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu, ets:insert(snmpm_inform_request_table, Rec) end, ok. - -handle_inform_response(Ref, Addr, Port, State) -> - Verbosity = get(verbosity), - spawn_opt(fun() -> - Log = worker_init(State, Verbosity), - Res = (catch do_handle_inform_response( - Ref, - Addr, Port, - State#state{log = Log})), - worker_exit(inform_reponse, {Addr, Port}, Res) - end, - [monitor]). - + +handle_inform_response(Ref, Domain, Addr, State) -> + Verbosity = get(verbosity), + spawn_opt( + fun() -> + Log = worker_init(State, Verbosity), + Res = (catch do_handle_inform_response( + Ref, Domain, Addr, State#state{log = Log})), + worker_exit(inform_response, {Domain, Addr}, Res) + end, + [monitor]). + -do_handle_inform_response(Ref, Addr, Port, State) -> - Key = {Ref, Addr, Port}, +do_handle_inform_response(Ref, Domain, Addr, State) -> + Key = {Ref, Domain, Addr}, case ets:lookup(snmpm_inform_request_table, Key) of [{Key, _, {Vsn, ACM, RePdu}}] -> - Logger = logger(State#state.log, read, Addr, Port), + Logger = logger(State#state.log, read, Domain, Addr), ets:delete(snmpm_inform_request_table, Key), - maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, - Logger, State); + maybe_send_inform_response( + RePdu, Vsn, ACM, Domain, Addr, Logger, State); [] -> %% Already acknowledged, or the user was to slow to reply... ok end, ok. -maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger, - #state{server = Pid, - sock = Sock, - filter = FilterMod}) -> - case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(RePdu))) of +maybe_send_inform_response( + RePdu, Vsn, ACM, Domain, Addr, Logger, + #state{server = Pid, + sock = Sock, + domain = ManagerDomain, + filter = FilterMod}) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_send_pdu( + Arg1, Arg2, pdu_type_of(RePdu))) + of false -> inc(netIfPduOutDrops), ok; _ -> case snmpm_mpd:generate_response_msg(Vsn, RePdu, ACM, Logger) of {ok, Msg} -> - maybe_udp_send(FilterMod, Sock, Addr, Port, Msg); + maybe_udp_send( + Domain, Addr, Msg, Sock, FilterMod, ManagerDomain); {discarded, Reason} -> ?vlog("failed generating response message:" "~n Reason: ~p", [Reason]), ReqId = RePdu#pdu.request_id, ErrorInfo = {failed_generating_response, {RePdu, Reason}}, - Pid ! {snmp_error, ReqId, ErrorInfo, Addr, Port}, + Pid ! {snmp_error, ReqId, ErrorInfo, Domain, Addr}, ok end end. @@ -745,40 +777,42 @@ irgc_stop(Ref) -> (catch erlang:cancel_timer(Ref)). -handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State) -> - Verbosity = get(verbosity), - spawn_opt(fun() -> - Log = worker_init(State, Verbosity), - Res = (catch maybe_handle_send_pdu( - Pdu, Vsn, MsgData, - Domain, Addr, Port, - State#state{log = Log})), - worker_exit(send_pdu, {Domain, Addr, Port}, Res) - end, - [monitor]). - -maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, - #state{filter = FilterMod} = State) -> - case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(Pdu))) of +handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State) -> + Verbosity = get(verbosity), + spawn_opt( + fun() -> + Log = worker_init(State, Verbosity), + Res = (catch maybe_handle_send_pdu( + Pdu, Vsn, MsgData, + Domain, Addr, + State#state{log = Log})), + worker_exit(send_pdu, {Domain, Addr}, Res) + end, + [monitor]). + +maybe_handle_send_pdu( + Pdu, Vsn, MsgData, Domain, Addr, + #state{filter = FilterMod, domain = ManagerDomain} = State) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_send_pdu(Arg1, Arg2, pdu_type_of(Pdu))) of false -> inc(netIfPduOutDrops), ok; _ -> - do_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State) + do_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State) end. -do_handle_send_pdu(Pdu, Vsn, MsgData, _Domain, Addr, Port, - #state{server = Pid, - note_store = NoteStore, - sock = Sock, - log = Log, - filter = FilterMod}) -> - Logger = logger(Log, write, Addr, Port), - case (catch snmpm_mpd:generate_msg(Vsn, NoteStore, - Pdu, MsgData, Logger)) of +do_handle_send_pdu( + Pdu, Vsn, MsgData, Domain, Addr, + #state{server = Pid, + note_store = NoteStore, + log = Log} = State) -> + Logger = logger(Log, write, Domain, Addr), + case (catch snmpm_mpd:generate_msg( + Vsn, NoteStore, Pdu, MsgData, Logger)) of {ok, Msg} -> ?vtrace("do_handle_send_pdu -> message generated", []), - maybe_udp_send(FilterMod, Sock, Addr, Port, Msg); + maybe_udp_send(Domain, Addr, Msg, State); {discarded, Reason} -> ?vlog("PDU not sent: " "~n PDU: ~p" @@ -787,30 +821,38 @@ do_handle_send_pdu(Pdu, Vsn, MsgData, _Domain, Addr, Port, ok end. +maybe_udp_send( + Domain, Addr, Msg, + #state{sock = Sock, filter = FilterMod, domain = ManagerDomain}) -> + maybe_udp_send(Domain, Addr, Msg, Sock, FilterMod, ManagerDomain). -maybe_udp_send(FilterMod, Sock, Addr, Port, Msg) -> - case (catch FilterMod:accept_send(Addr, Port)) of +maybe_udp_send(Domain, Addr, Msg, Sock, FilterMod, ManagerDomain) -> + {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + case (catch FilterMod:accept_send(Arg1, Arg2)) of false -> inc(netIfMsgOutDrops), ok; _ -> - udp_send(Sock, Addr, Port, Msg) + %% XXX There should be some kind of lookup of socket + %% from transport domain here + {Ip, Port} = Addr, + udp_send(Sock, Ip, Port, Msg) end. -udp_send(Sock, Addr, Port, Msg) -> - case (catch gen_udp:send(Sock, Addr, Port, Msg)) of +udp_send(Sock, Ip, Port, Msg) -> + case (catch gen_udp:send(Sock, Ip, Port, Msg)) of ok -> ?vdebug("sent ~w bytes to ~w:~w [~w]", - [sz(Msg), Addr, Port, Sock]), + [sz(Msg), Ip, Port, Sock]), ok; {error, Reason} -> error_msg("failed sending message to ~p:~p: " - "~n ~p",[Addr, Port, Reason]), + "~n ~p", [Ip, Port, Reason]), ok; Error -> error_msg("failed sending message to ~p:~p: " - "~n ~p",[Addr, Port, Error]), + "~n ~p", [Ip, Port, Error]), ok end. @@ -1036,25 +1078,48 @@ worker_exit(Tag, Info, Result) -> handle_worker_exit(_, {_, _, ok}) -> ok; -handle_worker_exit(Pid, {udp, {Addr, Port}, ExitStatus}) -> - warning_msg("Worker process (~p) terminated " - "while processing (incomming) message from ~w:~w: " - "~n~p", [Pid, Addr, Port, ExitStatus]), +handle_worker_exit(Pid, {udp, {Domain, Addr}, ExitStatus}) -> + warning_msg( + "Worker process (~p) terminated " + "while processing (incomming) message from %s:~n" + "~p", [Pid, snmp_conf:mk_addr_string({Domain, Addr}), ExitStatus]), ok; -handle_worker_exit(Pid, {send_pdu, {Domain, Addr, Port}, ExitStatus}) -> - warning_msg("Worker process (~p) terminated " - "while processing (outgoing) pdu for [~w] ~w:~w: " - "~n~p", [Pid, Domain, Addr, Port, ExitStatus]), +handle_worker_exit(Pid, {send_pdu, {Domain, Addr}, ExitStatus}) -> + warning_msg( + "Worker process (~p) terminated " + "while processing (outgoing) pdu for %s:~n" + "~p", [Pid, snmp_conf:mk_addr_string({Domain, Addr}), ExitStatus]), ok; -handle_worker_exit(Pid, {inform_response, {Addr, Port}, ExitStatus}) -> - warning_msg("Worker process (~p) terminated " - "while processing (outgoing) inform response for ~w:~w: " - "~n~p", [Pid, Addr, Port, ExitStatus]), +handle_worker_exit(Pid, {inform_response, {Domain, Addr}, ExitStatus}) -> + warning_msg( + "Worker process (~p) terminated " + "while processing (outgoing) inform response for %s:~n" + "~p", [Pid, snmp_conf:mk_addr_string({Domain, Addr}), ExitStatus]), ok; handle_worker_exit(_, _) -> ok. +%% If the manager uses legacy snmpUDPDomain e.g has not set +%% {domain, _}, then make sure snmpm_network_interface_filter +%% gets legacy arguments to not break backwards compatibility. +%% +fix_filter_address(snmpUDPDomain, {Domain, Addr}) + when Domain =:= snmpUDPDomain; + Domain =:= transportDomainUdpIpv4 -> + Addr; +fix_filter_address(_ManagerDomain, {Domain, _} = Address) + when is_atom(Domain) -> + Address; +fix_filter_address(snmpUDPDomain, {_, Port} = Addr) + when is_integer(Port) -> + Addr. + +address(Domain, Addr) when is_atom(Domain) -> + {Domain, Addr}; +address(Ip, Port) when is_integer(Port) -> + {snmpm_config:default_transport_domain(), {Ip, Port}}. + %% ------------------------------------------------------------------- make_response_pdu(#pdu{request_id = ReqId, varbinds = Vbs}) -> @@ -1095,15 +1160,17 @@ t() -> %% ------------------------------------------------------------------- -logger(undefined, _Type, _Addr, _Port) -> +logger(undefined, _Type, _Domain, _Addr) -> fun(_) -> ok end; -logger({_Name, Log, Types}, Type, Addr, Port) -> +logger({_Name, Log, Types}, Type, Domain, Addr) -> case lists:member(Type, Types) of true -> + AddrString = + iolist_to_binary(snmp_conf:mk_addr_string({Domain, Addr})), fun(Msg) -> - snmp_log:log(Log, Msg, Addr, Port) + snmp_log:log(Log, Msg, Domain, AddrString) end; false -> fun(_) -> @@ -1256,4 +1323,3 @@ call(Pid, Req, Timeout) -> cast(Pid, Msg) -> gen_server:cast(Pid, Msg). - diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl index 9c79df2748..ece5dad082 100644 --- a/lib/snmp/src/manager/snmpm_server.erl +++ b/lib/snmp/src/manager/snmpm_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -163,8 +163,7 @@ reg_type, target, domain, - addr, - port, + address, type, data, ref, @@ -1033,14 +1032,14 @@ handle_info({snmp_error, Pdu, Reason}, State) -> handle_snmp_error(Pdu, Reason, State), {noreply, State}; -handle_info({snmp_error, Reason, Addr, Port}, State) -> +handle_info({snmp_error, Reason, Domain, Addr}, State) -> ?vlog("received snmp_error message", []), - handle_snmp_error(Addr, Port, -1, Reason, State), + handle_snmp_error(Domain, Addr, -1, Reason, State), {noreply, State}; -handle_info({snmp_error, ReqId, Reason, Addr, Port}, State) -> +handle_info({snmp_error, ReqId, Reason, Domain, Addr}, State) -> ?vlog("received snmp_error message", []), - handle_snmp_error(Addr, Port, ReqId, Reason, State), + handle_snmp_error(Domain, Addr, ReqId, Reason, State), {noreply, State}; %% handle_info({snmp_error, ReqId, Pdu, Reason, Addr, Port}, State) -> @@ -1049,30 +1048,30 @@ handle_info({snmp_error, ReqId, Reason, Addr, Port}, State) -> %% {noreply, State}; -handle_info({snmp_pdu, Pdu, Addr, Port}, State) -> +handle_info({snmp_pdu, Pdu, Domain, Addr}, State) -> ?vlog("received snmp_pdu message", []), - handle_snmp_pdu(Pdu, Addr, Port, State), + handle_snmp_pdu(Pdu, Domain, Addr, State), {noreply, State}; -handle_info({snmp_trap, Trap, Addr, Port}, State) -> +handle_info({snmp_trap, Trap, Domain, Addr}, State) -> ?vlog("received snmp_trap message", []), - handle_snmp_trap(Trap, Addr, Port, State), + handle_snmp_trap(Trap, Domain, Addr, State), {noreply, State}; -handle_info({snmp_inform, Ref, Pdu, Addr, Port}, State) -> +handle_info({snmp_inform, Ref, Pdu, Domain, Addr}, State) -> ?vlog("received snmp_inform message", []), - handle_snmp_inform(Ref, Pdu, Addr, Port, State), + handle_snmp_inform(Ref, Pdu, Domain, Addr, State), {noreply, State}; -handle_info({snmp_report, {ok, Pdu}, Addr, Port}, State) -> - handle_snmp_report(Pdu, Addr, Port, State), +handle_info({snmp_report, {ok, Pdu}, Domain, Addr}, State) -> + handle_snmp_report(Pdu, Domain, Addr, State), {noreply, State}; -handle_info({snmp_report, {error, ReqId, Info, Pdu}, Addr, Port}, State) -> - handle_snmp_report(ReqId, Pdu, Info, Addr, Port, State), +handle_info({snmp_report, {error, ReqId, Info, Pdu}, Domain, Addr}, State) -> + handle_snmp_report(ReqId, Pdu, Info, Domain, Addr, State), {noreply, State}; @@ -1176,11 +1175,11 @@ handle_sync_get(Pid, UserId, TargetName, Oids, SendOpts, From, State) -> "~n From: ~p", [Pid, UserId, TargetName, Oids, SendOpts, From]), case agent_data(TargetName, SendOpts) of - {ok, RegType, Domain, Addr, Port, Vsn, MsgData} -> + {ok, RegType, Domain, Addr, Vsn, MsgData} -> ?vtrace("handle_sync_get -> send a ~p message", [Vsn]), Extra = ?GET_EXTRA(SendOpts), ReqId = send_get_request(Oids, Vsn, MsgData, - Domain, Addr, Port, + Domain, Addr, Extra, State), ?vdebug("handle_sync_get -> ReqId: ~p", [ReqId]), Msg = {sync_timeout, ReqId, From}, @@ -1193,8 +1192,7 @@ handle_sync_get(Pid, UserId, TargetName, Oids, SendOpts, From, State) -> reg_type = RegType, target = TargetName, domain = Domain, - addr = Addr, - port = Port, + address = Addr, type = get, data = MsgData, ref = Ref, @@ -1230,11 +1228,11 @@ handle_sync_get_next(Pid, UserId, TargetName, Oids, SendOpts, "~n From: ~p", [Pid, UserId, TargetName, Oids, SendOpts, From]), case agent_data(TargetName, SendOpts) of - {ok, RegType, Domain, Addr, Port, Vsn, MsgData} -> + {ok, RegType, Domain, Addr, Vsn, MsgData} -> ?vtrace("handle_sync_get_next -> send a ~p message", [Vsn]), Extra = ?GET_EXTRA(SendOpts), ReqId = send_get_next_request(Oids, Vsn, MsgData, - Domain, Addr, Port, + Domain, Addr, Extra, State), ?vdebug("handle_sync_get_next -> ReqId: ~p", [ReqId]), Msg = {sync_timeout, ReqId, From}, @@ -1247,12 +1245,11 @@ handle_sync_get_next(Pid, UserId, TargetName, Oids, SendOpts, reg_type = RegType, target = TargetName, domain = Domain, - addr = Addr, - port = Port, + address = Addr, type = get_next, data = MsgData, ref = Ref, - mon = MonRef, + mon = MonRef, from = From}, ets:insert(snmpm_request_table, Req), ok; @@ -1290,11 +1287,11 @@ handle_sync_get_bulk(Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts, "~n From: ~p", [Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts, From]), case agent_data(TargetName, SendOpts) of - {ok, RegType, Domain, Addr, Port, Vsn, MsgData} -> + {ok, RegType, Domain, Addr, Vsn, MsgData} -> ?vtrace("handle_sync_get_bulk -> send a ~p message", [Vsn]), Extra = ?GET_EXTRA(SendOpts), ReqId = send_get_bulk_request(Oids, Vsn, MsgData, - Domain, Addr, Port, + Domain, Addr, NonRep, MaxRep, Extra, State), ?vdebug("handle_sync_get_bulk -> ReqId: ~p", [ReqId]), Msg = {sync_timeout, ReqId, From}, @@ -1307,8 +1304,7 @@ handle_sync_get_bulk(Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts, reg_type = RegType, target = TargetName, domain = Domain, - addr = Addr, - port = Port, + address = Addr, type = get_bulk, data = MsgData, ref = Ref, @@ -1346,11 +1342,11 @@ handle_sync_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, From, State) -> "~n From: ~p", [Pid, UserId, TargetName, VarsAndVals, From]), case agent_data(TargetName, SendOpts) of - {ok, RegType, Domain, Addr, Port, Vsn, MsgData} -> + {ok, RegType, Domain, Addr, Vsn, MsgData} -> ?vtrace("handle_sync_set -> send a ~p message", [Vsn]), Extra = ?GET_EXTRA(SendOpts), ReqId = send_set_request(VarsAndVals, Vsn, MsgData, - Domain, Addr, Port, + Domain, Addr, Extra, State), ?vdebug("handle_sync_set -> ReqId: ~p", [ReqId]), Msg = {sync_timeout, ReqId, From}, @@ -1363,8 +1359,7 @@ handle_sync_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, From, State) -> reg_type = RegType, target = TargetName, domain = Domain, - addr = Addr, - port = Port, + address = Addr, type = set, data = MsgData, ref = Ref, @@ -1400,11 +1395,11 @@ handle_async_get(Pid, UserId, TargetName, Oids, SendOpts, State) -> "~n SendOpts: ~p", [Pid, UserId, TargetName, Oids, SendOpts]), case agent_data(TargetName, SendOpts) of - {ok, RegType, Domain, Addr, Port, Vsn, MsgData} -> + {ok, RegType, Domain, Addr, Vsn, MsgData} -> ?vtrace("handle_async_get -> send a ~p message", [Vsn]), Extra = ?GET_EXTRA(SendOpts), ReqId = send_get_request(Oids, Vsn, MsgData, - Domain, Addr, Port, + Domain, Addr, Extra, State), ?vdebug("handle_async_get -> ReqId: ~p", [ReqId]), Expire = ?ASYNC_GET_TIMEOUT(SendOpts), @@ -1413,8 +1408,7 @@ handle_async_get(Pid, UserId, TargetName, Oids, SendOpts, State) -> reg_type = RegType, target = TargetName, domain = Domain, - addr = Addr, - port = Port, + address = Addr, type = get, data = MsgData, expire = t() + Expire}, @@ -1450,11 +1444,11 @@ handle_async_get_next(Pid, UserId, TargetName, Oids, SendOpts, State) -> "~n SendOpts: ~p", [Pid, UserId, TargetName, Oids, SendOpts]), case agent_data(TargetName, SendOpts) of - {ok, RegType, Domain, Addr, Port, Vsn, MsgData} -> + {ok, RegType, Domain, Addr, Vsn, MsgData} -> ?vtrace("handle_async_get_next -> send a ~p message", [Vsn]), Extra = ?GET_EXTRA(SendOpts), ReqId = send_get_next_request(Oids, Vsn, MsgData, - Domain, Addr, Port, + Domain, Addr, Extra, State), ?vdebug("handle_async_get_next -> ReqId: ~p", [ReqId]), Expire = ?ASYNC_GET_NEXT_TIMEOUT(SendOpts), @@ -1463,8 +1457,7 @@ handle_async_get_next(Pid, UserId, TargetName, Oids, SendOpts, State) -> reg_type = RegType, target = TargetName, domain = Domain, - addr = Addr, - port = Port, + address = Addr, type = get_next, data = MsgData, expire = t() + Expire}, @@ -1507,11 +1500,11 @@ handle_async_get_bulk(Pid, "~n SendOpts: ~p", [Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts]), case agent_data(TargetName, SendOpts) of - {ok, RegType, Domain, Addr, Port, Vsn, MsgData} -> + {ok, RegType, Domain, Addr, Vsn, MsgData} -> ?vtrace("handle_async_get_bulk -> send a ~p message", [Vsn]), Extra = ?GET_EXTRA(SendOpts), ReqId = send_get_bulk_request(Oids, Vsn, MsgData, - Domain, Addr, Port, + Domain, Addr, NonRep, MaxRep, Extra, State), ?vdebug("handle_async_get_bulk -> ReqId: ~p", [ReqId]), Expire = ?ASYNC_GET_BULK_TIMEOUT(SendOpts), @@ -1520,8 +1513,7 @@ handle_async_get_bulk(Pid, reg_type = RegType, target = TargetName, domain = Domain, - addr = Addr, - port = Port, + address = Addr, type = get_bulk, data = MsgData, expire = t() + Expire}, @@ -1556,11 +1548,11 @@ handle_async_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, State) -> "~n SendOpts: ~p", [Pid, UserId, TargetName, VarsAndVals, SendOpts]), case agent_data(TargetName, SendOpts) of - {ok, RegType, Domain, Addr, Port, Vsn, MsgData} -> + {ok, RegType, Domain, Addr, Vsn, MsgData} -> ?vtrace("handle_async_set -> send a ~p message", [Vsn]), Extra = ?GET_EXTRA(SendOpts), ReqId = send_set_request(VarsAndVals, Vsn, MsgData, - Domain, Addr, Port, + Domain, Addr, Extra, State), ?vdebug("handle_async_set -> ReqId: ~p", [ReqId]), Expire = ?ASYNC_SET_TIMEOUT(SendOpts), @@ -1569,8 +1561,7 @@ handle_async_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, State) -> reg_type = RegType, target = TargetName, domain = Domain, - addr = Addr, - port = Port, + address = Addr, type = set, data = MsgData, expire = t() + Expire}, @@ -1808,15 +1799,15 @@ handle_snmp_error(CrapError, Reason, _State) -> "~n~p~n~p", [CrapError, Reason]), ok. -handle_snmp_error(Addr, Port, ReqId, Reason, State) -> +handle_snmp_error(Domain, Addr, ReqId, Reason, State) -> - ?vtrace("handle_snmp_error -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n ReqId: ~p" - "~n Reason: ~p", [Addr, Port, ReqId, Reason]), + ?vtrace("handle_snmp_error -> entry with~n" + " Domain: ~p~n" + " Addr: ~p~n" + " ReqId: ~p~n" + " Reason: ~p", [Domain, Addr, ReqId, Reason]), - case snmpm_config:get_agent_user_id(Addr, Port) of + case snmpm_config:get_agent_user_id(Domain, Addr) of {ok, UserId} -> case snmpm_config:user_info(UserId) of {ok, UserMod, UserData} -> @@ -1831,7 +1822,7 @@ handle_snmp_error(Addr, Port, ReqId, Reason, State) -> error_msg("failed retreiving the default user " "info handling snmp error " "<~p,~p>: ~n~w~n~w", - [Addr, Port, ReqId, Reason]) + [Domain, Addr, ReqId, Reason]) end end; _Error -> @@ -1843,7 +1834,7 @@ handle_snmp_error(Addr, Port, ReqId, Reason, State) -> error_msg("failed retreiving the default user " "info handling snmp error " "<~p,~p>: ~n~w~n~w", - [Addr, Port, ReqId, Reason]) + [Domain, Addr, ReqId, Reason]) end end. @@ -1867,12 +1858,12 @@ handle_error(_UserId, Mod, Reason, ReqId, Data, _State) -> handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu, - Addr, Port, State) -> + Domain, Addr, State) -> - ?vtrace("handle_snmp_pdu(get-response) -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n Pdu: ~p", [Addr, Port, Pdu]), + ?vtrace("handle_snmp_pdu(get-response) -> entry with~n" + " Domain: ~p~n" + " Addr: ~p~n" + " Pdu: ~p", [Domain, Addr, Pdu]), case ets:lookup(snmpm_request_table, ReqId) of @@ -1902,9 +1893,10 @@ handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu, SnmpResponse = {EStatus, EIndex, Varbinds2}, case snmpm_config:user_info(UserId) of {ok, UserMod, UserData} -> - handle_pdu(UserId, UserMod, - RegType, Target, Addr, Port, - ReqId, SnmpResponse, UserData, State), + handle_pdu( + UserId, UserMod, + RegType, Target, Domain, Addr, + ReqId, SnmpResponse, UserData, State), maybe_delete(Disco, ReqId); _Error -> %% reply to outstanding request, for which there is no @@ -1912,15 +1904,16 @@ handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu, %% Therefor send it to the default user case snmpm_config:user_info() of {ok, DefUserId, DefMod, DefData} -> - handle_pdu(DefUserId, DefMod, - RegType, Target, Addr, Port, - ReqId, SnmpResponse, DefData, State), + handle_pdu( + DefUserId, DefMod, + RegType, Target, Domain, Addr, + ReqId, SnmpResponse, DefData, State), maybe_delete(Disco, ReqId); Error -> error_msg("failed retreiving the default user " "info handling pdu from " "~p <~p,~p>: ~n~w~n~w", - [Target, Addr, Port, Error, Pdu]) + [Target, Domain, Addr, Error, Pdu]) end end; @@ -1974,7 +1967,7 @@ handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu, varbinds = Varbinds} = Pdu, Varbinds2 = fix_vbs_BITS(Varbinds), SnmpInfo = {EStatus, EIndex, Varbinds2}, - case snmpm_config:get_agent_user_id(Addr, Port) of + case snmpm_config:get_agent_user_id(Domain, Addr) of {ok, UserId} -> %% A very late reply or a reply to a request %% that has been cancelled. @@ -1999,7 +1992,7 @@ handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu, "user info handling (old) " "pdu from " "<~p,~p>: ~n~w~n~w", - [Addr, Port, Error, Pdu]) + [Domain, Addr, Error, Pdu]) end end; @@ -2016,28 +2009,30 @@ handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu, "no agent info found", []), case snmpm_config:user_info() of {ok, DefUserId, DefMod, DefData} -> - handle_agent(DefUserId, DefMod, - Addr, Port, - pdu, ignore, - SnmpInfo, DefData, State); + handle_agent( + DefUserId, DefMod, + Domain, Addr, + pdu, ignore, + SnmpInfo, DefData, State); Error -> error_msg("failed retreiving the default user " "info handling (old) pdu when no user " "found from " "<~p,~p>: ~n~w~n~w", - [Addr, Port, Error, Pdu]) + [Domain, Addr, Error, Pdu]) end end end; -handle_snmp_pdu(CrapPdu, Addr, Port, _State) -> +handle_snmp_pdu(CrapPdu, Domain, Addr, _State) -> error_msg("received crap (snmp) Pdu from ~w:~w =>" - "~p", [Addr, Port, CrapPdu]), + "~p", [Domain, Addr, CrapPdu]), ok. -handle_pdu(_UserId, Mod, target_name = _RegType, TargetName, _Addr, _Port, - ReqId, SnmpResponse, Data, _State) -> +handle_pdu( + _UserId, Mod, target_name = _RegType, TargetName, _Domain, _Addr, + ReqId, SnmpResponse, Data, _State) -> ?vtrace("handle_pdu(target_name) -> entry when" "~n Mod: ~p", [Mod]), F = fun() -> @@ -2053,43 +2048,47 @@ handle_pdu(_UserId, Mod, target_name = _RegType, TargetName, _Addr, _Port, end, handle_callback(F), ok; -handle_pdu(_UserId, Mod, addr_port = _RegType, _TargetName, Addr, Port, - ReqId, SnmpResponse, Data, _State) -> +handle_pdu( + _UserId, Mod, addr_port = _RegType, _TargetName, _Domain, Addr, + ReqId, SnmpResponse, Data, _State) -> ?vtrace("handle_pdu(addr_port) -> entry when" "~n Mod: ~p", [Mod]), F = fun() -> - (catch Mod:handle_pdu(Addr, Port, ReqId, SnmpResponse, Data)) + {Ip, Port} = Addr, + (catch Mod:handle_pdu(Ip, Port, ReqId, SnmpResponse, Data)) end, handle_callback(F), ok. -handle_agent(UserId, Mod, Addr, Port, Type, Ref, SnmpInfo, Data, State) -> +handle_agent(UserId, Mod, Domain, Addr, Type, Ref, SnmpInfo, Data, State) -> ?vtrace("handle_agent -> entry when" "~n UserId: ~p" "~n Type: ~p" "~n Mod: ~p", [UserId, Type, Mod]), F = fun() -> - do_handle_agent(UserId, Mod, Addr, Port, + do_handle_agent(UserId, Mod, Domain, Addr, Type, Ref, SnmpInfo, Data, State) end, handle_callback(F), ok. do_handle_agent(DefUserId, DefMod, - Addr, Port, + Domain, Addr, Type, Ref, SnmpInfo, DefData, State) -> ?vdebug("do_handle_agent -> entry when" "~n DefUserId: ~p", [DefUserId]), - try DefMod:handle_agent(Addr, Port, Type, SnmpInfo, DefData) of + try DefMod:handle_agent(Domain, Addr, Type, SnmpInfo, DefData) of {register, UserId2, TargetName, Config} -> ?vtrace("do_handle_agent -> register: " "~n UserId2: ~p" "~n TargetName: ~p" "~n Config: ~p", [UserId2, TargetName, Config]), - Config2 = ensure_present([{address, Addr}, {port, Port}], Config), + Config2 = + ensure_present( + [{tdomain, Domain}, {taddress, Addr}], Config), Config3 = [{reg_type, target_name} | Config2], case snmpm_config:register_agent(UserId2, TargetName, Config3) of @@ -2099,7 +2098,7 @@ do_handle_agent(DefUserId, DefMod, error_msg("failed registering agent - " "handling agent " "~p <~p,~p>: ~n~w", - [TargetName, Addr, Port, Reason]), + [TargetName, Domain, Addr, Reason]), ok end; @@ -2108,31 +2107,33 @@ do_handle_agent(DefUserId, DefMod, ok; InvalidResult -> - CallbackArgs = [Addr, Port, Type, SnmpInfo, DefData], + CallbackArgs = [Domain, Addr, Type, SnmpInfo, DefData], handle_invalid_result(handle_agent, CallbackArgs, InvalidResult) catch error:{undef, _} when Type =:= pdu -> %% Maybe, still on the old API ?vdebug("do_handle_agent -> maybe still on the old api", []), - case (catch DefMod:handle_agent(Addr, Port, SnmpInfo, DefData)) of + {Ip, Port} = Addr, + case (catch DefMod:handle_agent(Ip, Port, SnmpInfo, DefData)) of {register, UserId2, Config} -> ?vtrace("do_handle_agent -> register: " "~n UserId2: ~p" "~n Config: ~p", [UserId2, Config]), - TargetName = mk_target_name(Addr, Port, Config), - Config2 = [{reg_type, addr_port}, - {address, Addr}, - {port, Port} | Config], - case snmpm_config:register_agent(UserId2, - TargetName, Config2) of + TargetName = mk_target_name(Domain, Addr, Config), + Config2 = + ensure_present( + [{tdomain, Domain}, {taddress, Addr}], Config), + Config3 = [{reg_type, addr_port} | Config2], + case snmpm_config:register_agent( + UserId2, TargetName, Config3) of ok -> ok; {error, Reason} -> error_msg("failed registering agent - " "handling agent " "~p <~p,~p>: ~n~w", - [TargetName, Addr, Port, Reason]), + [TargetName, Domain, Addr, Reason]), ok end; {register, UserId2, TargetName, Config} -> @@ -2141,18 +2142,19 @@ do_handle_agent(DefUserId, DefMod, "~n TargetName: ~p" "~n Config: ~p", [UserId2, TargetName, Config]), - Config2 = ensure_present([{address, Addr}, {port, Port}], - Config), + Config2 = + ensure_present( + [{tdomain, Domain}, {taddress, Addr}], Config), Config3 = [{reg_type, target_name} | Config2], - case snmpm_config:register_agent(UserId2, - TargetName, Config3) of + case snmpm_config:register_agent( + UserId2, TargetName, Config3) of ok -> ok; {error, Reason} -> error_msg("failed registering agent - " "handling agent " "~p <~p,~p>: ~n~w", - [TargetName, Addr, Port, Reason]), + [TargetName, Domain, Addr, Reason]), ok end; _Ignore -> @@ -2170,34 +2172,38 @@ do_handle_agent(DefUserId, DefMod, %% Backward compatibillity crap RegType = target_name, - Target = mk_target_name(Addr, Port, default_agent_config()), + Target = mk_target_name(Domain, Addr, default_agent_config()), case Type of report -> SnmpInform = SnmpInfo, - handle_report(DefUserId, DefMod, - RegType, Target, Addr, Port, - SnmpInform, DefData, State); + handle_report( + DefUserId, DefMod, + RegType, Target, Domain, Addr, + SnmpInform, DefData, State); inform -> SnmpInform = SnmpInfo, - handle_inform(DefUserId, DefMod, Ref, - RegType, Target, Addr, Port, - SnmpInform, DefData, State); + handle_inform( + DefUserId, DefMod, Ref, + RegType, Target, Domain, Addr, + SnmpInform, DefData, State); trap -> SnmpTrapInfo = SnmpInfo, - handle_trap(DefUserId, DefMod, - RegType, Target, Addr, Port, - SnmpTrapInfo, DefData, State); + handle_trap( + DefUserId, DefMod, + RegType, Target, Domain, Addr, + SnmpTrapInfo, DefData, State); _ -> - error_msg("failed delivering ~w info to default user - " - "regarding agent " - "<~p,~p>: ~n~w", [Type, Addr, Port, SnmpInfo]) + error_msg( + "failed delivering ~w info to default user - " + "regarding agent " + "<~p,~p>: ~n~w", [Type, Domain, Addr, SnmpInfo]) end; T:E -> - CallbackArgs = [Addr, Port, Type, SnmpInfo, DefData], + CallbackArgs = [Domain, Addr, Type, SnmpInfo, DefData], handle_invalid_result(handle_agent, CallbackArgs, T, E) end. @@ -2215,50 +2221,51 @@ ensure_present([{Key, _Val} = Elem|Ensure], Config) -> %% Retrieve user info for this agent. %% If this is an unknown agent, then use the default user -handle_snmp_trap(#trappdu{enterprise = Enteprise, - generic_trap = Generic, - specific_trap = Spec, - time_stamp = Timestamp, - varbinds = Varbinds} = Trap, - Addr, Port, State) -> - - ?vtrace("handle_snmp_trap [trappdu] -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n Trap: ~p", [Addr, Port, Trap]), +handle_snmp_trap( + #trappdu{enterprise = Enteprise, + generic_trap = Generic, + specific_trap = Spec, + time_stamp = Timestamp, + varbinds = Varbinds} = Trap, Domain, Addr, State) -> + + ?vtrace("handle_snmp_trap [trappdu] -> entry with~n" + " Domain: ~p~n" + " Addr: ~p~n" + " Trap: ~p", [Domain, Addr, Trap]), Varbinds2 = fix_vbs_BITS(Varbinds), SnmpTrapInfo = {Enteprise, Generic, Spec, Timestamp, Varbinds2}, - do_handle_snmp_trap(SnmpTrapInfo, Addr, Port, State); + do_handle_snmp_trap(SnmpTrapInfo, Domain, Addr, State); handle_snmp_trap(#pdu{error_status = EStatus, error_index = EIndex, varbinds = Varbinds} = Trap, - Addr, Port, State) -> + Domain, Addr, State) -> - ?vtrace("handle_snmp_trap [pdu] -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n Trap: ~p", [Addr, Port, Trap]), + ?vtrace("handle_snmp_trap [pdu] -> entry with~n" + " Domain: ~p~n" + " Addr: ~p~n" + " Trap: ~p", [Domain, Addr, Trap]), Varbinds2 = fix_vbs_BITS(Varbinds), SnmpTrapInfo = {EStatus, EIndex, Varbinds2}, - do_handle_snmp_trap(SnmpTrapInfo, Addr, Port, State); + do_handle_snmp_trap(SnmpTrapInfo, Domain, Addr, State); -handle_snmp_trap(CrapTrap, Addr, Port, _State) -> +handle_snmp_trap(CrapTrap, Domain, Addr, _State) -> error_msg("received crap (snmp) trap from ~w:~w =>" - "~p", [Addr, Port, CrapTrap]), + "~p", [Domain, Addr, CrapTrap]), ok. -do_handle_snmp_trap(SnmpTrapInfo, Addr, Port, State) -> - case snmpm_config:get_agent_user_info(Addr, Port) of +do_handle_snmp_trap(SnmpTrapInfo, Domain, Addr, State) -> + case snmpm_config:get_agent_user_info(Domain, Addr) of {ok, UserId, Target, RegType} -> ?vtrace("handle_snmp_trap -> found user: ~p", [UserId]), case snmpm_config:user_info(UserId) of {ok, Mod, Data} -> - handle_trap(UserId, Mod, - RegType, Target, Addr, Port, - SnmpTrapInfo, Data, State); + handle_trap( + UserId, Mod, + RegType, Target, Domain, Addr, + SnmpTrapInfo, Data, State); Error1 -> %% User no longer exists, unregister agent @@ -2270,66 +2277,72 @@ do_handle_snmp_trap(SnmpTrapInfo, Addr, Port, State) -> %% Try use the default user case snmpm_config:user_info() of {ok, DefUserId, DefMod, DefData} -> - handle_agent(DefUserId, DefMod, - Addr, Port, - trap, ignore, - SnmpTrapInfo, DefData, State); + handle_agent( + DefUserId, DefMod, + Domain, Addr, + trap, ignore, + SnmpTrapInfo, DefData, State); Error2 -> - error_msg("failed retreiving the default " - "user info handling report from " - "~p <~p,~p>: ~n~w~n~w", - [Target, Addr, Port, - Error2, SnmpTrapInfo]) + error_msg( + "failed retreiving the default " + "user info handling report from " + "~p <~p,~p>: ~n~w~n~w", + [Target, Domain, Addr, + Error2, SnmpTrapInfo]) end; Error3 -> %% Failed unregister agent, %% now its getting messy... - warning_msg("failed unregister agent ~p <~p,~p> " - "belonging to non-existing " - "user ~p, handling trap: " - "~n Error: ~w" - "~n Trap info: ~w", - [Target, Addr, Port, UserId, - Error3, SnmpTrapInfo]) + warning_msg( + "failed unregister agent ~p <~p,~p> " + "belonging to non-existing " + "user ~p, handling trap: " + "~n Error: ~w" + "~n Trap info: ~w", + [Target, Domain, Addr, UserId, + Error3, SnmpTrapInfo]) end end; Error4 -> %% Unknown agent, pass it on to the default user ?vlog("[trap] failed retreiving user id for agent <~p,~p>: " - "~n ~p", [Addr, Port, Error4]), + "~n ~p", [Domain, Addr, Error4]), case snmpm_config:user_info() of {ok, DefUserId, DefMod, DefData} -> - handle_agent(DefUserId, DefMod, - Addr, Port, - trap, ignore, - SnmpTrapInfo, DefData, State); + handle_agent( + DefUserId, DefMod, + Domain, Addr, + trap, ignore, + SnmpTrapInfo, DefData, State); Error5 -> - error_msg("failed retreiving " - "the default user info handling trap from " - "<~p,~p>: ~n~w~n~w", - [Addr, Port, Error5, SnmpTrapInfo]) + error_msg( + "failed retreiving " + "the default user info handling trap from " + "<~p,~p>: ~n~w~n~w", + [Domain, Addr, Error5, SnmpTrapInfo]) end end, ok. -handle_trap(UserId, Mod, - RegType, Target, Addr, Port, SnmpTrapInfo, Data, State) -> +handle_trap( + UserId, Mod, RegType, Target, Domain, Addr, SnmpTrapInfo, Data, State) -> ?vtrace("handle_trap -> entry with" "~n UserId: ~p" "~n Mod: ~p", [UserId, Mod]), F = fun() -> - do_handle_trap(UserId, Mod, - RegType, Target, Addr, Port, - SnmpTrapInfo, Data, State) + do_handle_trap( + UserId, Mod, + RegType, Target, Domain, Addr, + SnmpTrapInfo, Data, State) end, handle_callback(F), ok. -do_handle_trap(UserId, Mod, - RegType, Target, Addr, Port, SnmpTrapInfo, Data, _State) -> +do_handle_trap( + UserId, Mod, RegType, Target, Domain, Addr, SnmpTrapInfo, Data, _State) -> ?vdebug("do_handle_trap -> entry with" "~n UserId: ~p", [UserId]), {HandleTrap, CallbackArgs} = @@ -2338,8 +2351,9 @@ do_handle_trap(UserId, Mod, {fun() -> Mod:handle_trap(Target, SnmpTrapInfo, Data) end, [Target, SnmpTrapInfo, Data]}; addr_port -> - {fun() -> Mod:handle_trap(Addr, Port, SnmpTrapInfo, Data) end, - [Addr, Port, SnmpTrapInfo, Data]} + {Ip, Port} = Addr, + {fun() -> Mod:handle_trap(Ip, Port, SnmpTrapInfo, Data) end, + [Ip, Port, SnmpTrapInfo, Data]} end, try HandleTrap() of @@ -2347,9 +2361,10 @@ do_handle_trap(UserId, Mod, ?vtrace("do_handle_trap -> register: " "~n UserId2: ~p" "~n Config: ~p", [UserId2, Config]), - Target2 = mk_target_name(Addr, Port, Config), - Config2 = [{reg_type, target_name}, - {address, Addr}, {port, Port} | Config], + Target2 = mk_target_name(Domain, Addr, Config), + Config2 = + [{reg_type, target_name}, + {tdomain, Domain}, {taddress, Addr} | Config], case snmpm_config:register_agent(UserId2, Target2, Config2) of ok -> ok; @@ -2357,7 +2372,7 @@ do_handle_trap(UserId, Mod, error_msg("failed registering agent " "handling trap " "<~p,~p>: ~n~w", - [Addr, Port, Reason]), + [Domain, Addr, Reason]), ok end; {register, UserId2, Target2, Config} -> @@ -2375,20 +2390,19 @@ do_handle_trap(UserId, Mod, error_msg("failed registering agent " "handling trap " "~p <~p,~p>: ~n~w", - [Target2, Addr, Port, Reason]), + [Target2, Domain, Addr, Reason]), reply end; unregister -> ?vtrace("do_handle_trap -> unregister", []), - case snmpm_config:unregister_agent(UserId, - Addr, Port) of + case snmpm_config:unregister_agent(UserId, Domain, Addr) of ok -> ok; {error, Reason} -> error_msg("failed unregistering agent " "handling trap " "<~p,~p>: ~n~w", - [Addr, Port, Reason]), + [Domain, Addr, Reason]), ok end; ignore -> @@ -2405,28 +2419,30 @@ do_handle_trap(UserId, Mod, end. -handle_snmp_inform(Ref, - #pdu{error_status = EStatus, - error_index = EIndex, - varbinds = Varbinds} = Pdu, Addr, Port, State) -> +handle_snmp_inform( + Ref, + #pdu{error_status = EStatus, + error_index = EIndex, + varbinds = Varbinds} = Pdu, Domain, Addr, State) -> - ?vtrace("handle_snmp_inform -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n Pdu: ~p", [Addr, Port, Pdu]), + ?vtrace("handle_snmp_inform -> entry with~n" + " Domain: ~p~n" + " Addr: ~p~n" + " Pdu: ~p", [Domain, Addr, Pdu]), Varbinds2 = fix_vbs_BITS(Varbinds), SnmpInform = {EStatus, EIndex, Varbinds2}, - case snmpm_config:get_agent_user_info(Addr, Port) of + case snmpm_config:get_agent_user_info(Domain, Addr) of {ok, UserId, Target, RegType} -> case snmpm_config:user_info(UserId) of {ok, Mod, Data} -> ?vdebug("[inform] callback handle_inform with: " "~n UserId: ~p" "~n Mod: ~p", [UserId, Mod]), - handle_inform(UserId, Mod, Ref, - RegType, Target, Addr, Port, - SnmpInform, Data, State); + handle_inform( + UserId, Mod, Ref, + RegType, Target, Domain, Addr, + SnmpInform, Data, State); Error1 -> %% User no longer exists, unregister agent case snmpm_config:unregister_agent(UserId, Target) of @@ -2437,15 +2453,16 @@ handle_snmp_inform(Ref, "~n ~p", [UserId, Error1]), case snmpm_config:user_info() of {ok, DefUserId, DefMod, DefData} -> - handle_agent(DefUserId, DefMod, - Addr, Port, - inform, Ref, - SnmpInform, DefData, State); + handle_agent( + DefUserId, DefMod, + Domain, Addr, + inform, Ref, + SnmpInform, DefData, State); Error2 -> error_msg("failed retreiving the default " "user info handling inform from " "~p <~p,~p>: ~n~w~n~w", - [Target, Addr, Port, + [Target, Domain, Addr, Error2, Pdu]) end; Error3 -> @@ -2456,7 +2473,7 @@ handle_snmp_inform(Ref, "user ~p, handling inform: " "~n Error: ~w" "~n Pdu: ~w", - [Target, Addr, Port, UserId, + [Target, Domain, Addr, UserId, Error3, Pdu]) end end; @@ -2464,42 +2481,46 @@ handle_snmp_inform(Ref, Error4 -> %% Unknown agent, pass it on to the default user ?vlog("[inform] failed retreiving user id for agent <~p,~p>: " - "~n ~p", [Addr, Port, Error4]), + "~n ~p", [Domain, Addr, Error4]), case snmpm_config:user_info() of {ok, DefUserId, DefMod, DefData} -> - handle_agent(DefUserId, DefMod, - Addr, Port, - inform, Ref, - SnmpInform, DefData, State); + handle_agent( + DefUserId, DefMod, + Domain, Addr, + inform, Ref, + SnmpInform, DefData, State); Error5 -> error_msg("failed retreiving " "the default user info handling inform from " "<~p,~p>: ~n~w~n~w", - [Addr, Port, Error5, Pdu]) + [Domain, Addr, Error5, Pdu]) end end, ok; -handle_snmp_inform(_Ref, CrapInform, Addr, Port, _State) -> +handle_snmp_inform(_Ref, CrapInform, Domain, Addr, _State) -> error_msg("received crap (snmp) inform from ~w:~w =>" - "~p", [Addr, Port, CrapInform]), + "~p", [Domain, Addr, CrapInform]), ok. -handle_inform(UserId, Mod, Ref, - RegType, Target, Addr, Port, SnmpInform, Data, State) -> +handle_inform( + UserId, Mod, Ref, + RegType, Target, Domain, Addr, SnmpInform, Data, State) -> ?vtrace("handle_inform -> entry with" "~n UserId: ~p" "~n Mod: ~p", [UserId, Mod]), F = fun() -> - do_handle_inform(UserId, Mod, Ref, - RegType, Target, Addr, Port, SnmpInform, - Data, State) + do_handle_inform( + UserId, Mod, Ref, + RegType, Target, Domain, Addr, SnmpInform, + Data, State) end, handle_callback(F), ok. -do_handle_inform(UserId, Mod, Ref, - RegType, Target, Addr, Port, SnmpInform, Data, State) -> +do_handle_inform( + UserId, Mod, Ref, + RegType, Target, Domain, Addr, SnmpInform, Data, State) -> ?vdebug("do_handle_inform -> entry with" "~n UserId: ~p", [UserId]), {HandleInform, CallbackArgs} = @@ -2508,8 +2529,9 @@ do_handle_inform(UserId, Mod, Ref, {fun() -> Mod:handle_inform(Target, SnmpInform, Data) end, [Target, SnmpInform, Data]}; addr_port -> - {fun() -> Mod:handle_inform(Addr, Port, SnmpInform, Data) end, - [Addr, Port, SnmpInform, Data]} + {Ip, Port} = Addr, + {fun() -> Mod:handle_inform(Ip, Port, SnmpInform, Data) end, + [Ip, Port, SnmpInform, Data]} end, Rep = @@ -2520,9 +2542,11 @@ do_handle_inform(UserId, Mod, Ref, "~n Config: ~p", [UserId2, Config]), %% The only user which would do this is the %% default user - Target2 = mk_target_name(Addr, Port, Config), - Config2 = [{reg_type, target_name}, - {address, Addr}, {port, Port} | Config], + Target2 = mk_target_name(Domain, Addr, Config), + Config2 = + [{reg_type, target_name} | + ensure_present( + [{tdomain, Domain}, {taddress, Addr}], Config)], case snmpm_config:register_agent(UserId2, Target2, Config2) of ok -> reply; @@ -2530,7 +2554,7 @@ do_handle_inform(UserId, Mod, Ref, error_msg("failed registering agent " "handling inform " "~p <~p,~p>: ~n~w", - [Target2, Addr, Port, Reason]), + [Target2, Domain, Addr, Reason]), reply end; @@ -2549,21 +2573,21 @@ do_handle_inform(UserId, Mod, Ref, error_msg("failed registering agent " "handling inform " "~p <~p,~p>: ~n~w", - [Target2, Addr, Port, Reason]), + [Target2, Domain, Addr, Reason]), reply end; unregister -> ?vtrace("do_handle_inform -> unregister", []), - case snmpm_config:unregister_agent(UserId, - Addr, Port) of + case snmpm_config:unregister_agent( + UserId, Domain, Addr) of ok -> reply; {error, Reason} -> error_msg("failed unregistering agent " "handling inform " "<~p,~p>: ~n~w", - [Addr, Port, Reason]), + [Domain, Addr, Reason]), reply end; @@ -2576,8 +2600,8 @@ do_handle_inform(UserId, Mod, Ref, reply; InvalidResult -> - handle_invalid_result(handle_inform, CallbackArgs, - InvalidResult), + handle_invalid_result( + handle_inform, CallbackArgs, InvalidResult), reply catch @@ -2586,31 +2610,34 @@ do_handle_inform(UserId, Mod, Ref, reply end, - handle_inform_response(Rep, Ref, Addr, Port, State), + handle_inform_response(Rep, Ref, Domain, Addr, State), ok. -handle_inform_response(_, ignore, _Addr, _Port, _State) -> +handle_inform_response(_, ignore, _Domain, _Addr, _State) -> ignore; -handle_inform_response(no_reply, _Ref, _Addr, _Port, _State) -> +handle_inform_response(no_reply, _Ref, _Domain, _Addr, _State) -> no_reply; -handle_inform_response(_, Ref, Addr, Port, - #state{net_if = Pid, net_if_mod = Mod}) -> +handle_inform_response( + _, Ref, Domain, Addr, + #state{net_if = Pid, net_if_mod = Mod}) -> ?vdebug("handle_inform -> response", []), - (catch Mod:inform_response(Pid, Ref, Addr, Port)). + (catch Mod:inform_response(Pid, Ref, Domain, Addr)). -handle_snmp_report(#pdu{error_status = EStatus, - error_index = EIndex, - varbinds = Varbinds} = Pdu, Addr, Port, State) -> +handle_snmp_report( + #pdu{error_status = EStatus, + error_index = EIndex, + varbinds = Varbinds} = Pdu, + Domain, Addr, State) -> - ?vtrace("handle_snmp_report -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n Pdu: ~p", [Addr, Port, Pdu]), + ?vtrace("handle_snmp_report -> entry with~n" + " Domain: ~p~n" + " Addr: ~p~n" + " Pdu: ~p", [Domain, Addr, Pdu]), Varbinds2 = fix_vbs_BITS(Varbinds), SnmpReport = {EStatus, EIndex, Varbinds2}, - case snmpm_config:get_agent_user_info(Addr, Port) of + case snmpm_config:get_agent_user_info(Domain, Addr) of {ok, UserId, Target, RegType} -> case snmpm_config:user_info(UserId) of {ok, Mod, Data} -> @@ -2620,7 +2647,7 @@ handle_snmp_report(#pdu{error_status = EStatus, "~n ~p" "~n ~p", [UserId, Mod, Target, SnmpReport]), handle_report(UserId, Mod, - RegType, Target, Addr, Port, + RegType, Target, Domain, Addr, SnmpReport, Data, State); Error1 -> %% User no longer exists, unregister agent @@ -2633,7 +2660,7 @@ handle_snmp_report(#pdu{error_status = EStatus, case snmpm_config:user_info() of {ok, DefUserId, DefMod, DefData} -> handle_agent(DefUserId, DefMod, - Addr, Port, + Domain, Addr, report, ignore, SnmpReport, DefData, State); @@ -2641,7 +2668,7 @@ handle_snmp_report(#pdu{error_status = EStatus, error_msg("failed retreiving the default " "user info handling report from " "~p <~p,~p>: ~n~w~n~w", - [Target, Addr, Port, + [Target, Domain, Addr, Error2, Pdu]) end; Error3 -> @@ -2652,7 +2679,7 @@ handle_snmp_report(#pdu{error_status = EStatus, "user ~p, handling report: " "~n Error: ~w" "~n Report: ~w", - [Target, Addr, Port, UserId, + [Target, Domain, Addr, UserId, Error3, Pdu]) end end; @@ -2660,25 +2687,25 @@ handle_snmp_report(#pdu{error_status = EStatus, Error4 -> %% Unknown agent, pass it on to the default user ?vlog("[report] failed retreiving user id for agent <~p,~p>: " - "~n ~p", [Addr, Port, Error4]), + "~n ~p", [Domain, Addr, Error4]), case snmpm_config:user_info() of {ok, DefUserId, DefMod, DefData} -> handle_agent(DefUserId, DefMod, - Addr, Port, + Domain, Addr, report, ignore, SnmpReport, DefData, State); Error5 -> error_msg("failed retreiving " "the default user info handling report from " "<~p,~p>: ~n~w~n~w", - [Addr, Port, Error5, Pdu]) + [Domain, Addr, Error5, Pdu]) end end, ok; -handle_snmp_report(CrapReport, Addr, Port, _State) -> +handle_snmp_report(CrapReport, Domain, Addr, _State) -> error_msg("received crap (snmp) report from ~w:~w =>" - "~p", [Addr, Port, CrapReport]), + "~p", [Domain, Addr, CrapReport]), ok. %% This could be from a failed get-request, so we might have a user @@ -2686,20 +2713,20 @@ handle_snmp_report(CrapReport, Addr, Port, _State) -> %% get-response (except for tha data which is different). Otherwise, %% we handle it as an error (reported via the handle_error callback %% function). -handle_snmp_report(ReqId, - #pdu{error_status = EStatus, - error_index = EIndex, - varbinds = Varbinds} = Pdu, - {ReportReason, Info} = Rep, - Addr, Port, State) - when is_integer(ReqId) -> - - ?vtrace("handle_snmp_report -> entry with" - "~n Addr: ~p" - "~n Port: ~p" - "~n ReqId: ~p" - "~n Rep: ~p" - "~n Pdu: ~p", [Addr, Port, ReqId, Rep, Pdu]), +handle_snmp_report( + ReqId, + #pdu{error_status = EStatus, + error_index = EIndex, + varbinds = Varbinds} = Pdu, + {ReportReason, Info} = Rep, + Domain, Addr, State) when is_integer(ReqId) -> + + ?vtrace("handle_snmp_report -> entry with~n" + " Domain: ~p~n" + " Addr: ~p~n" + " ReqId: ~p~n" + " Rep: ~p~n" + " Pdu: ~p", [Domain, Addr, ReqId, Rep, Pdu]), Varbinds2 = fix_vbs_BITS(Varbinds), SnmpReport = {EStatus, EIndex, Varbinds2}, @@ -2744,7 +2771,7 @@ handle_snmp_report(ReqId, %% Either not a sync request or no such request. Either %% way, this is error info, so handle it as such. - case snmpm_config:get_agent_user_id(Addr, Port) of + case snmpm_config:get_agent_user_id(Domain, Addr) of {ok, UserId} -> case snmpm_config:user_info(UserId) of {ok, Mod, Data} -> @@ -2768,7 +2795,7 @@ handle_snmp_report(ReqId, "default user " "info handling report from " "<~p,~p>: ~n~w~n~w~n~w", - [Addr, Port, Error, + [Domain, Addr, Error, ReqId, Reason]) end end; @@ -2776,7 +2803,7 @@ handle_snmp_report(ReqId, %% Unknown agent, pass it on to the default user ?vlog("[report] failed retreiving user id for " "agent <~p,~p>: " - "~n ~p", [Addr, Port, Error]), + "~n ~p", [Domain, Addr, Error]), case snmpm_config:user_info() of {ok, DefUserId, DefMod, DefData} -> handle_error(DefUserId, DefMod, Reason, ReqId, @@ -2786,32 +2813,36 @@ handle_snmp_report(ReqId, "the default user info handling " "report from " "<~p,~p>: ~n~w~n~w~n~w", - [Addr, Port, Error, ReqId, Reason]) + [Domain, Addr, Error, ReqId, Reason]) end end end, ok; -handle_snmp_report(CrapReqId, CrapReport, CrapInfo, Addr, Port, _State) -> - error_msg("received crap (snmp) report from ~w:~w =>" - "~n~p~n~p~n~p", [Addr, Port, CrapReqId, CrapReport, CrapInfo]), +handle_snmp_report(CrapReqId, CrapReport, CrapInfo, Domain, Addr, _State) -> + error_msg( + "received crap (snmp) report from ~w:~w =>" + "~n~p~n~p~n~p", + [Domain, Addr, CrapReqId, CrapReport, CrapInfo]), ok. -handle_report(UserId, Mod, RegType, Target, Addr, Port, +handle_report(UserId, Mod, RegType, Target, Domain, Addr, SnmpReport, Data, State) -> ?vtrace("handle_report -> entry with" "~n UserId: ~p" "~n Mod: ~p", [UserId, Mod]), F = fun() -> - do_handle_report(UserId, Mod, RegType, Target, Addr, Port, - SnmpReport, Data, State) + do_handle_report( + UserId, Mod, RegType, Target, Domain, Addr, + SnmpReport, Data, State) end, handle_callback(F), ok. -do_handle_report(UserId, Mod, - RegType, Target, Addr, Port, SnmpReport, Data, _State) -> +do_handle_report( + UserId, Mod, RegType, Target, Domain, Addr, + SnmpReport, Data, _State) -> ?vdebug("do_handle_report -> entry with" "~n UserId: ~p", [UserId]), {HandleReport, CallbackArgs} = @@ -2820,8 +2851,9 @@ do_handle_report(UserId, Mod, {fun() -> Mod:handle_report(Target, SnmpReport, Data) end, [Target, SnmpReport, Data]}; addr_port -> - {fun() -> Mod:handle_report(Addr, Port, SnmpReport, Data) end, - [Addr, Port, SnmpReport, Data]} + {Ip, Port} = Addr, + {fun() -> Mod:handle_report(Ip, Port, SnmpReport, Data) end, + [Ip, Port, SnmpReport, Data]} end, try HandleReport() of @@ -2831,17 +2863,18 @@ do_handle_report(UserId, Mod, "~n Config: ~p", [UserId2, Config]), %% The only user which would do this is the %% default user - Target2 = mk_target_name(Addr, Port, Config), - Config2 = [{reg_type, target_name}, - {address, Addr}, {port, Port} | Config], + Target2 = mk_target_name(Domain, Addr, Config), + Config2 = + [{reg_type, target_name}, + {tdomain, Domain}, {taddress, Addr} | Config], case snmpm_config:register_agent(UserId2, Target2, Config2) of ok -> ok; {error, Reason} -> error_msg("failed registering agent " "handling report " - "<~p,~p>: ~n~w", - [Addr, Port, Reason]), + "<~p,~p>: ~n~w", + [Domain, Addr, Reason]), ok end; @@ -2860,21 +2893,20 @@ do_handle_report(UserId, Mod, error_msg("failed registering agent " "handling report " "~p <~p,~p>: ~n~w", - [Target2, Addr, Port, Reason]), + [Target2, Domain, Addr, Reason]), reply end; unregister -> ?vtrace("do_handle_trap -> unregister", []), - case snmpm_config:unregister_agent(UserId, - Addr, Port) of + case snmpm_config:unregister_agent(UserId, Domain, Addr) of ok -> ok; {error, Reason} -> error_msg("failed unregistering agent " "handling report " "<~p,~p>: ~n~w", - [Addr, Port, Reason]), + [Domain, Addr, Reason]), ok end; @@ -3012,50 +3044,49 @@ do_gc(Key, Now) -> %% %%---------------------------------------------------------------------- -send_get_request(Oids, Vsn, MsgData, Domain, Addr, Port, ExtraInfo, +send_get_request(Oids, Vsn, MsgData, Domain, Addr, ExtraInfo, #state{net_if = NetIf, net_if_mod = Mod, mini_mib = MiniMIB}) -> Pdu = make_pdu(get, Oids, MiniMIB), - ?vtrace("send_get_request -> send get-request:" - "~n Mod: ~p" - "~n NetIf: ~p" - "~n Pdu: ~p" - "~n Vsn: ~p" - "~n MsgData: ~p" - "~n Domain: ~p" - "~n Addr: ~p" - "~n Port: ~p", - [Mod, NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port]), + ?vtrace("send_get_request -> send get-request:~n" + " Mod: ~p~n" + " NetIf: ~p~n" + " Pdu: ~p~n" + " Vsn: ~p~n" + " MsgData: ~p~n" + " Domain: ~p~n" + " Addr: ~p", + [Mod, NetIf, Pdu, Vsn, MsgData, Domain, Addr]), Res = (catch Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, - Domain, Addr, Port, ExtraInfo)), + Domain, Addr, ExtraInfo)), ?vtrace("send_get_request -> send result:" "~n ~p", [Res]), Pdu#pdu.request_id. -send_get_next_request(Oids, Vsn, MsgData, Domain, Addr, Port, ExtraInfo, +send_get_next_request(Oids, Vsn, MsgData, Domain, Addr, ExtraInfo, #state{mini_mib = MiniMIB, net_if = NetIf, net_if_mod = Mod}) -> Pdu = make_pdu(get_next, Oids, MiniMIB), - Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo), + Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo), Pdu#pdu.request_id. -send_get_bulk_request(Oids, Vsn, MsgData, Domain, Addr, Port, +send_get_bulk_request(Oids, Vsn, MsgData, Domain, Addr, NonRep, MaxRep, ExtraInfo, #state{mini_mib = MiniMIB, net_if = NetIf, net_if_mod = Mod}) -> Pdu = make_pdu(bulk, {NonRep, MaxRep, Oids}, MiniMIB), - Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo), + Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo), Pdu#pdu.request_id. -send_set_request(VarsAndVals, Vsn, MsgData, Domain, Addr, Port, ExtraInfo, +send_set_request(VarsAndVals, Vsn, MsgData, Domain, Addr, ExtraInfo, #state{mini_mib = MiniMIB, net_if = NetIf, net_if_mod = Mod}) -> Pdu = make_pdu(set, VarsAndVals, MiniMIB), - Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo), + Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo), Pdu#pdu.request_id. %% send_discovery(Vsn, MsgData, Addr, Port, ExtraInfo, @@ -3291,10 +3322,9 @@ agent_data(TargetName, SendOpts) -> {Comm, SecModel} end, Domain = agent_data_item(tdomain, TargetName), - Addr = agent_data_item(address, TargetName), - Port = agent_data_item(port, TargetName), + Addr = agent_data_item(taddress, TargetName), RegType = agent_data_item(reg_type, TargetName), - {ok, RegType, Domain, Addr, Port, version(Version), MsgData}; + {ok, RegType, Domain, Addr, version(Version), MsgData}; Error -> Error end. @@ -3440,9 +3470,9 @@ maybe_demonitor(MonRef) -> t() -> {A,B,C} = erlang:now(), A*1000000000+B*1000+(C div 1000). - -mk_target_name(Addr, Port, Config) -> - snmpm_config:mk_target_name(Addr, Port, Config). + +mk_target_name(Domain, Addr, Config) -> + snmpm_config:mk_target_name(Domain, Addr, Config). default_agent_config() -> case snmpm_config:agent_info() of diff --git a/lib/snmp/src/manager/snmpm_user.erl b/lib/snmp/src/manager/snmpm_user.erl index e6b0b6943e..8e5a874f77 100644 --- a/lib/snmp/src/manager/snmpm_user.erl +++ b/lib/snmp/src/manager/snmpm_user.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -39,20 +39,25 @@ %% *** handle_error *** %% An "asynchronous" error has been detected --callback handle_error(ReqId :: integer(), - Reason :: {unexpected_pdu, SnmpInfo :: snmp_gen_info()} | - {invalid_sec_info, SecInfo :: term(), SnmpInfo :: snmp_gen_info()} | - {empty_message, Addr :: ip_address(), Port :: port_number()} | - term(), - UserData :: term()) -> +-callback handle_error( + ReqId :: integer(), + Reason :: {unexpected_pdu, SnmpInfo :: snmp_gen_info()} | + {invalid_sec_info, + SecInfo :: term(), + SnmpInfo :: snmp_gen_info()} | + {empty_message, + TransportDomain :: atom(), + {Addr :: ip_address(), Port :: port_number()}} | + term(), + UserData :: term()) -> snmp:void(). %% *** handle_agent *** %% A message was received from an unknown agent --callback handle_agent(Addr :: term(), - Port :: pos_integer(), +-callback handle_agent(Domain :: atom(), + Address :: term(), Type :: pdu | trap | inform | report, SnmpInfo :: snmp_gen_info() | snmp_v1_trap_info(), UserData :: term()) -> diff --git a/lib/snmp/src/manager/snmpm_user_default.erl b/lib/snmp/src/manager/snmpm_user_default.erl index 015198cb76..b827713f27 100644 --- a/lib/snmp/src/manager/snmpm_user_default.erl +++ b/lib/snmp/src/manager/snmpm_user_default.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -36,13 +36,13 @@ handle_error(ReqId, Reason, UserData) -> ignore. -handle_agent(Addr, Port, Type, SnmpInfo, UserData) -> - info("received handle_agent:" - "~n Addr: ~p" - "~n Port: ~p" - "~n Type: ~p" - "~n SnmpInfo: ~p" - "~n UserData: ~p", [Addr, Port, Type, SnmpInfo, UserData]), +handle_agent(Domain, Address, Type, SnmpInfo, UserData) -> + info("received handle_agent:~n" + " Domain: ~p~n" + " Address: ~p~n" + " Type: ~p~n" + " SnmpInfo: ~p~n" + " UserData: ~p", [Domain, Address, Type, SnmpInfo, UserData]), ignore. diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl index 46625989d5..f4483995cb 100644 --- a/lib/snmp/src/misc/snmp_conf.erl +++ b/lib/snmp/src/misc/snmp_conf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -25,35 +25,42 @@ %% External exports %% Avoid warning for local function error/1 clashing with autoimported BIF. -compile({no_auto_import,[error/1]}). --export([read_files/2, read/2]). +-export([read_files/2, no_gen/2, no_order/2, no_filter/1, keyorder/4]). +-export([read/2, read/3]). %% Basic (type) check functions -export([check_mandatory/2, check_integer/1, check_integer/2, - + check_string/1, check_string/2, - check_atom/2, + check_atom/2, check_timer/1, - all_domains/0, - check_domain/1, - all_tdomains/0, - check_tdomain/1, - mk_tdomain/1, - which_domain/1, - check_ip/1, check_ip/2, - check_taddress/1, check_taddress/2, - mk_taddress/3, - - check_packet_size/1, + all_domains/0, + check_domain/1, + domain_to_name/1, + all_tdomains/0, + check_tdomain/1, + mk_tdomain/0, mk_tdomain/1, + tdomain_to_family/1, tdomain_to_domain/1, + which_domain/1, + mk_addr_string/1, + check_ip/1, check_ip/2, + check_port/1, +%% ip_port_to_domaddr/2, + check_address/2, check_address/3, + check_taddress/2, + mk_taddress/1, mk_taddress/2, + + check_packet_size/1, check_oid/1, - check_imask/1, check_emask/1, - - check_mp_model/1, - check_sec_model/1, check_sec_model/2, check_sec_model/3, + check_imask/1, check_emask/1, + + check_mp_model/1, + check_sec_model/1, check_sec_model/2, check_sec_model/3, check_sec_level/1, all_integer/1 @@ -70,17 +77,53 @@ -include("snmp_verbosity.hrl"). +-define(is_word(P), (((P) band (bnot 65535)) =:= 0)). +-define(is_word(P0, P1), ((((P0) bor (P1)) band (bnot 255)) =:= 0)). + +mk_word(B0, B1) -> ((B0) bsl 8) bor (B1). +mk_bytes(W) -> [(W) bsr 8,(W) band 255]. + +-define( + is_ipv4_addr(A0, A1, A2, A3), + ((((A0) bor (A1) bor (A2) bor (A3)) band (bnot 255)) =:= 0)). + +-define( + is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ((((A0) bor (A1) bor (A2) bor (A3) bor (A4) bor (A5) bor (A6) bor (A7)) + band (bnot 65535)) =:= 0)). +-define( + is_ipv6_addr( + A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15), + ((((A0) bor (A1) bor (A2) bor (A3) bor + (A4) bor (A5) bor (A6) bor (A7) bor + (A8) bor (A9) bor (A10) bor (A11) bor + (A12) bor (A13) bor (A14) bor (A15)) + band (bnot 65535)) =:= 0)). + + %%----------------------------------------------------------------- %% read_files(Dir, Files) -> Configs %% Dir - string() - Full path to the config dir. -%% Files - [{Gen, Filter, Check, FileName}] +%% Files - [{FileName, Gen, Order, Check, Filter}] +%% FileName - string() - Name of the config file. %% Gen - function/2 - In case of failure when reading the config file, %% this function is called to either generate a %% default file or issue the error. -%% Filter - function/1 - Filters all the config entries read from the file -%% Check - function/1 - Check each entry as they are read from the file. -%% FileName - string() - Name of the config file. +%% Returns a generated config list corresponding +%% to the written file. +%% (Dir, Error) -> Configs. +%% Order - function/2 - An ordering function that is used to process +%% the read config entries using lists:sort/2. +%% Returns true if arg 1 compares less than or +%% equal to arg 2, false otherwise. +%% Check - function/2 - Check each entry as they are read from the file. +%% (Entry, State) -> +%% {ok,NewState} | {{ok,NewEntry},NewState} | +%% throw(Error) +%% State =:= 'undefined' the first time. +%% Filter - function/1 - Process all the config entries read from the file +%% (Configs) -> [config_entry()]. %% Configs - [config_entry()] %% config_entry() - term() @@ -89,99 +132,143 @@ read_files(Dir, Files) when is_list(Dir) andalso is_list(Files) -> read_files(_Dir, [], Res) -> lists:reverse(Res); -read_files(Dir, [{Gen, Filter, Check, FileName}|Files], Res) - when is_function(Filter) andalso - is_function(Check) andalso - is_list(FileName) -> - ?vdebug("read_files -> entry with" - "~n FileName: ~p", [FileName]), +read_files(Dir, [{FileName, Gen, Order, Check, Filter}|Files], Res) + when is_list(FileName), + is_function(Gen), + is_function(Order), + is_function(Check), + is_function(Filter) -> + ?vdebug("read_files -> entry with~n" + " FileName: ~p", [FileName]), File = filename:join(Dir, FileName), - case file:read_file_info(File) of - {ok, _} -> - Confs = read(File, Check), - read_files(Dir, Files, [Filter(Confs)|Res]); - {error, R} -> - ?vlog("failed reading file info for ~s: " - "~n ~p", [FileName, R]), - Gen(Dir, R), - read_files(Dir, Files, [Filter([])|Res]) - end. - + Confs = + case file:read_file_info(File) of + {ok,_} -> + read(File, Order, Check); + {error, R} -> + ?vlog("failed reading file info for ~s: ~n" + " ~p", [FileName, R]), + Gen(Dir, R) + end, + read_files(Dir, Files, [Filter(Confs)|Res]). + + + +no_gen(_Dir, _R) -> []. +no_order(_, _) -> true. +no_filter(X) -> X. + +%% Order tuples on element N with Keys first in appearence order. +%% +%% An ordering function (A, B) shall return true iff +%% A is less than or equal to B i.e shall return +%% false iff A is to be ordered after B. +keyorder(N, A, B, _) when element(N, A) == element(N, B) -> + true; +keyorder(N, A, B, [Key | _]) + when tuple_size(A) >= 1, element(N, B) == Key -> + false; +keyorder(N, A, B, [Key | _]) + when element(N, A) == Key, tuple_size(B) >= 1 -> + true; +keyorder(N, A, B, [_ | Keys]) -> + keyorder(N, A, B, Keys); +keyorder(_, A, B, []) when tuple_size(A) >= 1, tuple_size(B) >= 1 -> + %% Do not order other keys + true; +keyorder(N, A, B, sort) -> + %% Order other keys according to standard sort order + element(N, A) =< element(N, B). + + +read(File, Verify) -> + Check = fun (Row, State) -> {Verify(Row), State} end, + read(File, fun no_order/2, Check). %% Ret. Res | exit(Reason) -read(File, Check) when is_function(Check) -> - ?vdebug("read -> entry with" - "~n File: ~p", [File]), - +read(File, Order, Check) when is_function(Order), is_function(Check) -> + ?vdebug("read -> entry with~n" + " File: ~p", [File]), Fd = open_file(File), + read_fd(File, Order, Check, Fd, 1, []). - case loop(Fd, [], Check, 1, File) of - {error, Reason} -> - file:close(Fd), - error(Reason); - {ok, Res} -> - file:close(Fd), - Res +read_fd(File, Order, Check, Fd, StartLine, Res) -> + case do_read(Fd, "", StartLine) of + {ok, Row, EndLine} -> + ?vtrace("read_fd ->~n" + " Row: ~p~n" + " EndLine: ~p", [Row,EndLine]), + read_fd( + File, Order, Check, Fd, EndLine, + [{StartLine, Row, EndLine}|Res]); + {error, Error, EndLine} -> + ?vtrace("read_fd -> read failure:~n" + " Error: ~p~n" + " EndLine: ~p", [Error,EndLine]), + file:close(Fd), + error({failed_reading, File, StartLine, EndLine, Error}); + {eof, _EndLine} -> + Lines = + lists:sort( + fun ({_, RowA, _}, {_, RowB, _}) -> + Order(RowA, RowB) + end, + lists:reverse(Res)), + ?vtrace("read_fd to read_check ->~n" + " Lines: ~p", [Lines]), + read_check(File, Check, Lines, undefined, []) end. -open_file(File) -> - case file:open(File, [read]) of - {ok, Fd} -> - Fd; - {error, Reason} -> - error({failed_open, File, Reason}) +read_check(_, _, [], _, Res) -> + lists:reverse(Res); +read_check(File, Check, [{StartLine, Row, EndLine}|Lines], State, Res) -> + try Check(Row, State) of + {Rows, NewState} when is_list(Rows) -> + ?vtrace("read_check -> ok:~n" + " Rows: ~p~n", [Rows]), + read_check(File, Check, Lines, NewState, Rows ++ Res); + {ok, NewState} -> + ?vtrace("read_check -> ok", []), + read_check(File, Check, Lines, NewState, [Row | Res]); + {{ok, NewRow}, NewState} -> + ?vtrace("read_check -> ok:~n" + " NewRow: ~p~n", [NewRow]), + read_check(File, Check, Lines, NewState, [NewRow | Res]) + catch + {error, Reason} -> + ?vtrace("read_check -> error:~n" + " Reason: ~p", [Reason]), + error({failed_check, File, StartLine, EndLine, Reason}); + Class:Reason -> + Error = {Class,Reason,erlang:get_stacktrace()}, + ?vtrace("read_check -> failure:~n" + " Error: ~p", [Error]), + error({failed_check, File, StartLine, EndLine, Error}) end. -loop(Fd, Res, Check, StartLine, File) -> - case do_read(Fd, "", StartLine) of - {ok, Row, EndLine} -> - ?vtrace("loop -> " - "~n Row: ~p" - "~n EndLine: ~p", [Row, EndLine]), - case (catch Check(Row)) of - ok -> - ?vtrace("loop -> ok", []), - loop(Fd, [Row | Res], Check, EndLine, File); - {ok, NewRow} -> - ?vtrace("loop -> ok: " - "~n NewRow: ~p", [NewRow]), - loop(Fd, [NewRow | Res], Check, EndLine, File); - {error, Reason} -> - ?vtrace("loop -> check error: " - "~n Reason: ~p", [Reason]), - {error, {failed_check, File, StartLine, EndLine, Reason}}; - Error -> - ?vtrace("loop -> check failure: " - "~n Error: ~p", [Error]), - {error, {failed_check, File, StartLine, EndLine, Error}} - end; - {error, EndLine, Error} -> - ?vtrace("loop -> read failure: " - "~n Error: ~p", [Error]), - {error, {failed_reading, File, StartLine, EndLine, Error}}; - eof -> - {ok, Res} +open_file(File) -> + case file:open(File, [read]) of + {ok, Fd} -> + Fd; + {error, Reason} -> + error({failed_open, File, Reason}) end. - do_read(Io, Prompt, StartLine) -> case io:request(Io, {get_until,Prompt,erl_scan,tokens,[StartLine]}) of - {ok, Toks, EndLine} -> - case erl_parse:parse_term(Toks) of - {ok, Term} -> - {ok, Term, EndLine}; - {error, {Line, erl_parse, Error}} -> - {error, Line, {parse_error, Error}} - end; - {error,E,EndLine} -> - {error, EndLine, E}; - {eof, _EndLine} -> - eof; - Other -> - Other + {ok, Toks, EndLine} -> + case erl_parse:parse_term(Toks) of + {ok, Term} -> + {ok, Term, EndLine}; + {error, {Line, erl_parse, Error}} -> + {error, {parse_error, Error}, Line} + end; + Other -> + Other end. + %%----------------------------------------------------------------- @@ -384,7 +471,7 @@ all_tdomains() -> check_tdomain(TDomain) -> SupportedTDomains = [ - ?snmpUDPDomain, + ?snmpUDPDomain, % Legacy ?transportDomainUdpIpv4, ?transportDomainUdpIpv6 ], @@ -404,6 +491,9 @@ check_tdomain(TDomain) -> %% --------- +mk_tdomain() -> + mk_tdomain(snmpUDPDomain). + mk_tdomain(snmpUDPDomain) -> mk_tdomain(transportDomainUdpIpv4); mk_tdomain(transportDomainUdpIpv4) -> @@ -416,40 +506,64 @@ mk_tdomain(BadDomain) -> %% --------- -check_taddress(X) -> - check_taddress(snmpUDPDomain, X). +tdomain_to_family(snmpUDPDomain) -> + inet; +tdomain_to_family(transportDomainUdpIpv4) -> + inet; +tdomain_to_family(transportDomainUdpIpv6) -> + inet6; +tdomain_to_family(?snmpUDPDomain) -> + inet; +tdomain_to_family(?transportDomainUdpIpv4) -> + inet; +tdomain_to_family(?transportDomainUdpIpv6) -> + inet6; +tdomain_to_family(BadDomain) -> + error({bad_domain, BadDomain}). + + +%% --------- + +tdomain_to_domain(?snmpUDPDomain) -> + snmpUDPDomain; +tdomain_to_domain(?transportDomainUdpIpv4) -> + transportDomainUdpIpv4; +tdomain_to_domain(?transportDomainUdpIpv6) -> + transportDomainUdpIpv6; +tdomain_to_domain(BadTDomain) -> + error({bad_tdomain, BadTDomain}). + + +%% --------- check_taddress(?snmpUDPDomain, X) -> check_taddress(transportDomainUdpIpv4, X); check_taddress(snmpUDPDomain, X) -> check_taddress(transportDomainUdpIpv4, X); - +%% check_taddress(?transportDomainUdpIpv4, X) -> check_taddress(transportDomainUdpIpv4, X); -check_taddress(transportDomainUdpIpv4, X) - when is_list(X) andalso (length(X) =:= 6) -> - case (catch all_integer(X)) of - true -> +check_taddress(transportDomainUdpIpv4, X) -> + case X of + [A0,A1,A2,A3,P0,P1] + when ?is_ipv4_addr(A0, A1, A2, A3), ?is_word(P0, P1) -> ok; - false -> + _ -> error({invalid_taddress, X}) end; -check_taddress(transportDomainUdpIpv4, X) -> - error({invalid_taddress, X}); - +%% check_taddress(?transportDomainUdpIpv6, X) -> check_taddress(transportDomainUdpIpv6, X); -check_taddress(transportDomainUdpIpv6, X) - when is_list(X) andalso (length(X) =:= 10) -> - case (catch all_integer(X)) of - true -> +check_taddress(transportDomainUdpIpv6, X) -> + case X of + [A0,A1,A2,A3,A4,A5,A6,A7,P0,P1] + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ?is_word(P0, P1) -> ok; - false -> + _ -> error({invalid_taddress, X}) end; -check_taddress(transportDomainUdpIpv6, X) -> - error({invalid_taddress, X}); - +%% check_taddress(BadDomain, _X) -> error({invalid_tdomain, BadDomain}). @@ -512,96 +626,357 @@ all_domains() -> transportDomainSctpDns ]. +check_domain(snmpUDPDomain) -> ok; +check_domain(transportDomainUdpIpv4) -> ok; +check_domain(transportDomainUdpIpv6) -> ok; check_domain(Domain) -> - SupportedDomains = - [ - snmpUDPDomain, - transportDomainUdpIpv4, - transportDomainUdpIpv6 - ], - AllDomains = all_domains(), - case lists:member(Domain, SupportedDomains) of + case lists:member(Domain, all_domains()) of true -> - ok; + error({unsupported_domain, Domain}); false -> - case lists:member(Domain, AllDomains) of - true -> - error({unsupported_domain, Domain}); - false -> - error({unknown_domain, Domain}) - end + error({unknown_domain, Domain}) end. - + +domain_to_name(snmpUDPDomain) -> + undefined; +domain_to_name(transportDomainUdpIpv4) -> + udpIpv4; +domain_to_name(transportDomainUdpIpv6) -> + udpIpv6; +domain_to_name(transportDomainUdpIpv4z) -> + udpIpv4z; +domain_to_name(transportDomainUdpIpv6z) -> + udpIpv6z; +domain_to_name(transportDomainTcpIpv4) -> + tcpIpv4; +domain_to_name(transportDomainTcpIpv6) -> + tcpIpv6; +domain_to_name(transportDomainTcpIpv4z) -> + tcpIpv4z; +domain_to_name(transportDomainTcpIpv6z) -> + tcpIpv6z; +domain_to_name(transportDomainSctpIpv4) -> + sctpIpv4; +domain_to_name(transportDomainSctpIpv6) -> + sctpIpv6; +domain_to_name(transportDomainSctpIpv4z) -> + sctpIpv4z; +domain_to_name(transportDomainSctpIpv6z) -> + sctpIpv6z; +domain_to_name(transportDomainLocal) -> + local; +domain_to_name(transportDomainUdpDns) -> + udpDns; +domain_to_name(transportDomainTcpDns) -> + tcpDns; +domain_to_name(transportDomainSctpDns) -> + sctpDns; +domain_to_name(BadDomain) -> + error({bad_domain, BadDomain}). %% --------- -%% The values of Ip and Port has both been checked at this -%% point, so we dont need to do that again. -mk_taddress(snmpUDPDomain, Ip, Port) -> - mk_taddress(transportDomainUdpIpv4, Ip, Port); -mk_taddress(transportDomainUdpIpv4, Ip, Port) when is_list(Ip) -> - Ip ++ [Port div 256, Port rem 256]; -mk_taddress(transportDomainUdpIpv4 = Domain, Ip, Port) when is_tuple(Ip) -> - mk_taddress(Domain, tuple_to_list(Ip), Port); -mk_taddress(transportDomainUdpIpv6, Ip, Port) when is_list(Ip) -> - Ip ++ [Port div 256, Port rem 256]; -mk_taddress(transportDomainUdpIpv6 = Domain, Ip, Port) when is_tuple(Ip) -> - mk_taddress(Domain, tuple_to_list(Ip), Port); +mk_taddress(Address) -> + mk_taddress(snmpUDPDomain, Address). +%% The values of Domain, Ip and Port has both been checked at this +%% point, so we dont need to do that again, but this function is +%% also used on incoming packets from net_if so a little +%% check that net_if does not supply bad arguments is in order. +%% %% These are just for convenience -mk_taddress(?snmpUDPDomain, Ip, Port) -> - mk_taddress(snmpUDPDomain, Ip, Port); -mk_taddress(?transportDomainUdpIpv4, Ip, Port) -> - mk_taddress(transportDomainUdpIpv4, Ip, Port); -mk_taddress(?transportDomainUdpIpv6, Ip, Port) -> - mk_taddress(transportDomainUdpIpv6, Ip, Port); - +mk_taddress(?snmpUDPDomain, Address) -> + mk_taddress(snmpUDPDomain, Address); +mk_taddress(?transportDomainUdpIpv4, Address) -> + mk_taddress(transportDomainUdpIpv4, Address); +mk_taddress(?transportDomainUdpIpv6, Address) -> + mk_taddress(transportDomainUdpIpv6, Address); +%% +mk_taddress(snmpUDPDomain, Address) -> % Legacy + mk_taddress(transportDomainUdpIpv4, Address); +mk_taddress(transportDomainUdpIpv4 = Domain, Address) -> + case Address of + [] -> % Empty mask + []; + {Ip, Port} when tuple_size(Ip) =:= 4, is_integer(Port) -> + tuple_to_list(Ip) ++ mk_bytes(Port); + _ -> + erlang:error(badarg, [Domain,Address]) + end; +mk_taddress(transportDomainUdpIpv6 = Domain, Address) -> + case Address of + [] -> % Empty mask + []; + {{A, B, C, D, E, F, G, H}, Port} -> + [A bsr 8, A band 255, + B bsr 8, B band 255, + C bsr 8, C band 255, + D bsr 8, D band 255, + E bsr 8, E band 255, + F bsr 8, F band 255, + G bsr 8, G band 255, + H bsr 8, H band 255, + Port bsr 8, Port band 255]; + _ -> + erlang:error(badarg, [Domain,Address]) + end; %% Bad domain -mk_taddress(BadDomain, _Ip, _Port) -> +mk_taddress(BadDomain, _) -> error({bad_domain, BadDomain}). - + %% --------- -which_domain(Ip) when is_list(Ip) andalso (length(Ip) =:= 4) -> +%% XXX remove, when net_if handles one socket per transport domain + +which_domain([A0,A1,A2,A3]) + when ?is_ipv4_addr(A0, A1, A2, A3) -> transportDomainUdpIpv4; -which_domain(Ip) when is_tuple(Ip) andalso (size(Ip) =:= 4) -> +which_domain({A0, A1, A2, A3}) + when ?is_ipv4_addr(A0, A1, A2, A3) -> transportDomainUdpIpv4; -which_domain(Ip) when is_list(Ip) andalso (length(Ip) =:= 8) -> +which_domain([A0,A1,A2,A3,A4,A5,A6,A7]) + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7) -> + transportDomainUdpIpv6; +which_domain([A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15]) + when ?is_ipv6_addr( + A0, A1, A2, A3, A4, A5, A6, A7, + A8, A9, A10, A11, A12, A13, A14, A15) -> transportDomainUdpIpv6; -which_domain(Ip) when is_tuple(Ip) andalso (size(Ip) =:= 8) -> +which_domain({A0, A1, A2, A3, A4, A5, A6, A7}) + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7) -> transportDomainUdpIpv6. - %% --------- +mk_addr_string({_IP, Port} = Addr) when is_integer(Port) -> + mk_addr_string({snmpUDPDomain, Addr}); +mk_addr_string({Domain, Addr}) when is_atom(Domain) -> + %% XXX There is only code for IP domains here + case check_address_ip(Domain, Addr) of + false -> + case check_address_ip_port(Domain, Addr) of + false -> + error({bad_address, {Domain, Addr}}); + true -> + {IP, Port} = Addr, + mk_addr_string_ntoa(Domain, IP, Port); + {IP, Port} -> + mk_addr_string_ntoa(Domain, IP, Port) + end; + true -> + mk_addr_string_ntoa(Domain, Addr); + IP -> + mk_addr_string_ntoa(Domain, IP) + end. + + +mk_addr_string_ntoa({_, _, _, _} = IP) -> + inet:ntoa(IP); +mk_addr_string_ntoa(IP) -> + lists:flatten(io_lib:format("[~s]", [inet:ntoa(IP)])). + +mk_addr_string_ntoa(Domain, IP) -> + case domain_to_name(Domain) of + undefined -> + mk_addr_string_ntoa(IP); + Name -> + lists:flatten( + io_lib:format("~w://~s", [Name, mk_addr_string_ntoa(IP)])) + end. + +mk_addr_string_ntoa(Domain, IP, Port) -> + lists:flatten( + io_lib:format( + "~s:~w", [mk_addr_string_ntoa(Domain, IP), Port])). + +%% --------- + check_ip(X) -> check_ip(snmpUDPDomain, X). -check_ip(snmpUDPDomain, X) -> - check_ip(transportDomainUdpIpv4, X); -check_ip(transportDomainUdpIpv4, X) when is_list(X) andalso (length(X) =:= 4) -> - case (catch all_integer(X)) of - true -> +check_ip(Domain, IP) -> + %% XXX There is only code for IP domains here + case check_address_ip(Domain, IP) of + false -> + error({bad_address, {Domain, IP}}); + true -> ok; - false -> - error({invalid_ip_address, X}) - end; -check_ip(transportDomainUdpIpv4, X) -> - error({invalid_ip_address, X}); + FixedIP -> + {ok, FixedIP} + end. -check_ip(transportDomainUdpIpv6, X) when is_list(X) andalso (length(X) =:= 8) -> - case (catch all_integer(X)) of - true -> + +%% --------- + +check_port(Port) when ?is_word(Port) -> + ok; +check_port(Port) -> + error({bad_port, Port}). + +%% ip_port_to_domaddr(IP, Port) when ?is_word(Port) -> +%% %% XXX There is only code for IP domains here +%% case check_address_ip(transportDomainUdpIpv4, IP) of +%% false -> +%% case check_address_ip(transportDomainUdpIpv6, IP) of +%% false -> +%% error({bad_address, {transportDomainUdpIpv4, {IP, Port}}}); +%% true -> +%% {transportDomainUdpIpv6, {IP, Port}}; +%% FixedIP -> +%% {transportDomainUdpIpv6, {FixedIP, Port}} +%% end; +%% true -> +%% {transportDomainUdpIpv4, {IP, Port}}; +%% FixedIP -> +%% {transportDomainUdpIpv4, {FixedIP, Port}} +%% end; +%% ip_port_to_domaddr(IP, Port) -> +%% error({bad_address, {transportDomainUdpIpv4, {IP, Port}}}). + +%% Check a configuration term field from a file to see if it +%% can be fixed to be fed to mk_taddress/2. + +check_address(Domain, Address, DefaultPort) -> + %% If Address does not contain Port or contains Port =:= 0 + %% create an address containing DefaultPort + %% + %% XXX There is only code for IP domains here + case check_address_ip(Domain, Address) of + false -> + case check_address_ip_port(Domain, Address) of + false -> + error({bad_address, {Domain, Address}}); + true -> + case Address of + {IP, 0} -> + {ok, {IP, DefaultPort}}; + _ -> + ok + end; + {FixedIP, 0} -> + {ok, {FixedIP, DefaultPort}}; + FixedAddress -> + {ok, FixedAddress} + end; + true -> + {ok, {Address, DefaultPort}}; + FixedIP -> + {ok, {FixedIP, DefaultPort}} + end. + +check_address(Domain, Address) -> + %% Address has to contain Port + %% + %% XXX There is only code for IP domains here + case check_address_ip_port(Domain, Address) of + false -> + error({bad_address, {Domain, Address}}); + true -> ok; - false -> - error({invalid_ip_address, X}) + FixedAddress -> + {ok, FixedAddress} + end. + +%% -> IP +check_address_ip(Domain, Address) + when Domain =:= snmpUDPDomain; + Domain =:= transportDomainUdpIpv4 -> + case Address of + %% Erlang native format + {A0, A1, A2, A3} + when ?is_ipv4_addr(A0, A1, A2, A3) -> + true; + %% Erlangish format + [A0,A1,A2,A3] + when ?is_ipv4_addr(A0, A1, A2, A3) -> + {A0, A1, A2, A3}; + _ -> + false + end; +check_address_ip(transportDomainUdpIpv6, Address) -> + case Address of + %% Erlang native format + {A0, A1, A2, A3, A4, A5, A6, A7} + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7) -> + true; + %% Erlangish format + [A0,A1,A2,A3,A4,A5,A6,A7] + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7) -> + {A0, A1, A2, A3, A4, A5, A6, A7}; + %% SNMP standards format + [A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15] + when ?is_ipv6_addr( + A0, A1, A2, A3, A4, A5, A6, A7, + A8, A9, A10, A11, A12, A13, A14, A15) -> + {mk_word(A0, A1), mk_word(A2, A3), + mk_word(A4, A5), mk_word(A6, A7), + mk_word(A8, A9), mk_word(A10, A11), + mk_word(A12, A13), mk_word(A14, A15)}; + _ -> + false end; -check_ip(transportDomainUdpIpv6, X) -> - error({invalid_ip_address, X}); +check_address_ip(BadDomain, _) -> + error({bad_domain, BadDomain}). -check_ip(BadDomain, _X) -> - error({invalid_domain, BadDomain}). +%% -> {IP, Port} +check_address_ip_port(Domain, Address) + when Domain =:= snmpUDPDomain; + Domain =:= transportDomainUdpIpv4 -> + case Address of + {IP, Port} when ?is_word(Port) -> + case check_address_ip(Domain, IP) of + false -> + false; + true -> + true; + FixedIP -> + {FixedIP, Port} + end; + %% SNMP standards format + [A0,A1,A2,A3,P0,P1] + when ?is_ipv4_addr(A0, A1, A2, A3), ?is_word(P0, P1) -> + {{A0, A1, A2, A3}, mk_word(P0, P1)}; + _ -> + false + end; +check_address_ip_port(transportDomainUdpIpv6 = Domain, Address) -> + case Address of + {IP, Port} when ?is_word(Port) -> + case check_address_ip(Domain, IP) of + false -> + false; + true -> + true; + FixedIP -> + {FixedIP, Port} + end; + %% Erlang friendly list format + [A0,A1,A2,A3,A4,A5,A6,A7,P] + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ?is_word(P) -> + {{A0, A1, A2, A3, A4, A5, A6, A7}, P}; + %% Strange hybrid format with port as bytes + [A0,A1,A2,A3,A4,A5,A6,A7,P0,P1] + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ?is_word(P0, P1) -> + {{A0, A1, A2, A3, A4, A5, A6, A7}, mk_word(P0, P1)}; + %% SNMP standards format + [A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,P0,P1] + when ?is_ipv6_addr( + A0, A1, A2, A3, A4, A5, A6, A7, + A8, A9, A10, A11, A12, A13, A14, A15), + ?is_word(P0, P1) -> + {{mk_word(A0, A1), mk_word(A2, A3), + mk_word(A4, A5), mk_word(A6, A7), + mk_word(A8, A9), mk_word(A10, A11), + mk_word(A12, A13), mk_word(A14, A15)}, + mk_word(P0, P1)}; + _ -> + false + end; +check_address_ip_port(BadDomain, _) -> + error({bad_domain, BadDomain}). diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl index a222f842e5..9e9865f3b5 100644 --- a/lib/snmp/src/misc/snmp_config.erl +++ b/lib/snmp/src/misc/snmp_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -26,16 +26,21 @@ -compile({no_auto_import,[error/1]}). -export([config/0]). --export([write_config_file/4, append_config_file/4, read_config_file/3]). +%%-export([write_config_file/4, append_config_file/4, read_config_file/4]). + +-export([write_config_file/6, append_config_file/6, read_config_file/4]). -export([write_agent_snmp_files/7, write_agent_snmp_files/12, + write_agent_snmp_files/6, write_agent_snmp_files/11, - write_agent_snmp_conf/5, + write_agent_snmp_conf/4, write_agent_snmp_conf/5, write_agent_snmp_context_conf/1, write_agent_snmp_community_conf/1, write_agent_snmp_standard_conf/2, - write_agent_snmp_target_addr_conf/4, - write_agent_snmp_target_addr_conf/6, + write_agent_snmp_target_addr_conf/3, + write_agent_snmp_target_addr_conf/4, + write_agent_snmp_target_addr_conf/5, + write_agent_snmp_target_addr_conf/6, write_agent_snmp_target_params_conf/2, write_agent_snmp_notify_conf/2, write_agent_snmp_usm_conf/5, @@ -90,9 +95,9 @@ ]). --export_type([void/0, - verify_config_entry_function/0, - verify_config_function/0, +-export_type([void/0, + order_config_entry_function/0, + check_config_entry_function/0, write_config_function/0]). @@ -567,11 +572,9 @@ config_agent_snmp(Dir, Vsns) -> end, NT end, - case (catch write_agent_snmp_files(Dir, - Vsns, ManagerIP, TrapUdp, - AgentIP, AgentUDP, - SysName, NotifType, SecType, - Passwd, EngineID, MMS)) of + case (catch write_agent_snmp_files( + Dir, Vsns, ManagerIP, TrapUdp, AgentIP, AgentUDP, SysName, + NotifType, SecType, Passwd, EngineID, MMS)) of ok -> i("~n- - - - - - - - - - - - -"), i("Info: 1. SecurityName \"initial\" has noAuthNoPriv read access~n" @@ -1580,35 +1583,63 @@ remove_newline(Str) -> %% File generation %%====================================================================== +write_agent_snmp_files( + Dir, Vsns, Domain, ManagerAddr, AgentAddr, SysName) + when is_list(Dir), + is_list(Vsns), + is_atom(Domain), + is_list(SysName) -> + write_agent_snmp_files( + Dir, Vsns, Domain, ManagerAddr, AgentAddr, SysName, + trap, none, "", "agentEngine", 484). + %%---------------------------------------------------------------------- %% Dir: string() (ex: "../conf/") %% ManagerIP, AgentIP: [int(),int(),int(),int()] %% TrapUdp, AgentUDP: integer() %% SysName: string() %%---------------------------------------------------------------------- -write_agent_snmp_files(Dir, Vsns, ManagerIP, TrapUdp, - AgentIP, AgentUDP, SysName) - when is_list(Dir) andalso - is_list(Vsns) andalso - is_list(ManagerIP) andalso - is_integer(TrapUdp) andalso - is_list(AgentIP) andalso - is_integer(AgentUDP) andalso +write_agent_snmp_files( + Dir, Vsns, ManagerIP, TrapUDP, AgentIP, AgentUDP, SysName) + when is_list(Dir) andalso + is_list(Vsns) andalso + is_list(ManagerIP) andalso + is_integer(TrapUDP) andalso + is_list(AgentIP) andalso + is_integer(AgentUDP) andalso is_list(SysName) -> - write_agent_snmp_files(Dir, Vsns, ManagerIP, TrapUdp, AgentIP, AgentUDP, - SysName, "trap", none, "", "agentEngine", 484). + write_agent_snmp_files( + Dir, Vsns, ManagerIP, TrapUDP, AgentIP, AgentUDP, SysName, + trap, none, "", "agentEngine", 484). %% %% ----- Agent config files generator functions ----- %% -write_agent_snmp_files(Dir, Vsns, ManagerIP, TrapUdp, AgentIP, AgentUDP, - SysName, NotifType, SecType, Passwd, EngineID, MMS) -> +write_agent_snmp_files( + Dir, Vsns, Domain, ManagerAddr, AgentAddr, SysName, + NotifType, SecType, Passwd, EngineID, MMS) -> + write_agent_snmp_conf(Dir, Domain, AgentAddr, EngineID, MMS), + write_agent_snmp_context_conf(Dir), + write_agent_snmp_community_conf(Dir), + write_agent_snmp_standard_conf(Dir, SysName), + write_agent_snmp_target_addr_conf(Dir, Domain, ManagerAddr, Vsns), + write_agent_snmp_target_params_conf(Dir, Vsns), + write_agent_snmp_notify_conf(Dir, NotifType), + write_agent_snmp_usm_conf(Dir, Vsns, EngineID, SecType, Passwd), + write_agent_snmp_vacm_conf(Dir, Vsns, SecType), + ok. + +write_agent_snmp_files( + Dir, Vsns, ManagerIP, TrapUDP, AgentIP, AgentUDP, SysName, + NotifType, SecType, Passwd, EngineID, MMS) -> + Domain = snmp_target_mib:default_domain(), + ManagerAddr = {ManagerIP, TrapUDP}, write_agent_snmp_conf(Dir, AgentIP, AgentUDP, EngineID, MMS), write_agent_snmp_context_conf(Dir), write_agent_snmp_community_conf(Dir), write_agent_snmp_standard_conf(Dir, SysName), - write_agent_snmp_target_addr_conf(Dir, ManagerIP, TrapUdp, Vsns), + write_agent_snmp_target_addr_conf(Dir, Domain, ManagerAddr, Vsns), write_agent_snmp_target_params_conf(Dir, Vsns), write_agent_snmp_notify_conf(Dir, NotifType), write_agent_snmp_usm_conf(Dir, Vsns, EngineID, SecType, Passwd), @@ -1616,11 +1647,38 @@ write_agent_snmp_files(Dir, Vsns, ManagerIP, TrapUdp, AgentIP, AgentUDP, ok. + %% %% ------ [agent] agent.conf ------ %% -write_agent_snmp_conf(Dir, AgentIP, AgentUDP, EngineID, MMS) -> +write_agent_snmp_conf(Dir, Transports, EngineID, MMS) -> + Conf = + [{intAgentTransports, Transports}, + {snmpEngineID, EngineID}, + {snmpEngineMaxMessageSize, MMS}], + do_write_agent_snmp_conf(Dir, Conf). + +write_agent_snmp_conf(Dir, Domain, AgentAddr, EngineID, MMS) + when is_atom(Domain) -> + {AgentIP, AgentUDP} = AgentAddr, + Conf = + [{intAgentTransportDomain, Domain}, + {intAgentUDPPort, AgentUDP}, + {intAgentIpAddress, AgentIP}, + {snmpEngineID, EngineID}, + {snmpEngineMaxMessageSize, MMS}], + do_write_agent_snmp_conf(Dir, Conf); +write_agent_snmp_conf(Dir, AgentIP, AgentUDP, EngineID, MMS) + when is_integer(AgentUDP) -> + Conf = + [{intAgentUDPPort, AgentUDP}, + {intAgentIpAddress, AgentIP}, + {snmpEngineID, EngineID}, + {snmpEngineMaxMessageSize, MMS}], + do_write_agent_snmp_conf(Dir, Conf). + +do_write_agent_snmp_conf(Dir, Conf) -> Comment = "%% This file defines the Agent local configuration info\n" "%% The data is inserted into the snmpEngine* variables defined\n" @@ -1635,11 +1693,7 @@ write_agent_snmp_conf(Dir, AgentIP, AgentUDP, EngineID, MMS) -> "%% {snmpEngineID, \"agentEngine\"}.\n" "%% {snmpEngineMaxMessageSize, 484}.\n" "%%\n\n", - Hdr = header() ++ Comment, - Conf = [{intAgentUDPPort, AgentUDP}, - {intAgentIpAddress, AgentIP}, - {snmpEngineID, EngineID}, - {snmpEngineMaxMessageSize, MMS}], + Hdr = header() ++ Comment, write_agent_config(Dir, Hdr, Conf). write_agent_config(Dir, Hdr, Conf) -> @@ -1745,17 +1799,19 @@ update_agent_standard_config(Dir, Conf) -> %% ------ target_addr.conf ------ %% -write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> - Timeout = 1500, - RetryCount = 3, - write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP, - Timeout, RetryCount, - Vsns). +write_agent_snmp_target_addr_conf(Dir, Addresses, Vsns) -> + Timeout = 1500, + RetryCount = 3, + write_agent_snmp_target_addr_conf( + Dir, Addresses, Timeout, RetryCount, Vsns). -write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP, - Timeout, RetryCount, - Vsns) -> - Comment = +write_agent_snmp_target_addr_conf(Dir, Domain_or_Ip, Addr_or_Port, Vsns) -> + Addresses = [{Domain_or_Ip, Addr_or_Port}], + write_agent_snmp_target_addr_conf(Dir, Addresses, Vsns). + +write_agent_snmp_target_addr_conf( + Dir, Addresses, Timeout, RetryCount, Vsns) -> + Comment = "%% This file defines the target address parameters.\n" "%% The data is inserted into the snmpTargetAddrTable defined\n" "%% in SNMP-TARGET-MIB, and in the snmpTargetAddrExtTable defined\n" @@ -1774,36 +1830,59 @@ write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP, "%% [127,0,0,0], 2048}.\n" "%%\n\n", Hdr = header() ++ Comment, - F = fun(v1 = Vsn, Acc) -> - [{mk_ip(ManagerIp, Vsn), - snmp_target_mib:default_domain(), - ManagerIp, UDP, Timeout, RetryCount, - "std_trap", mk_param(Vsn), "", [], 2048}| Acc]; - (v2 = Vsn, Acc) -> - [{mk_ip(ManagerIp, Vsn), - snmp_target_mib:default_domain(), - ManagerIp, UDP, Timeout, RetryCount, - "std_trap", mk_param(Vsn), "", [], 2048}, - {lists:flatten(io_lib:format("~s.2",[mk_ip(ManagerIp, Vsn)])), - ManagerIp, UDP, Timeout, RetryCount, - "std_inform", mk_param(Vsn), "", [], 2048}| Acc]; - (v3 = Vsn, Acc) -> - [{mk_ip(ManagerIp, Vsn), - snmp_target_mib:default_domain(), - ManagerIp, UDP, Timeout, RetryCount, - "std_trap", mk_param(Vsn), "", [], 2048}, - {lists:flatten(io_lib:format("~s.3",[mk_ip(ManagerIp, Vsn)])), - ManagerIp, UDP, Timeout, RetryCount, - "std_inform", mk_param(Vsn), "mgrEngine", [], 2048}| Acc] - end, - Conf = lists:foldl(F, [], Vsns), + Conf = + lists:foldl( + fun ({Domain_or_Ip, Addr_or_Port} = Address, OuterAcc) -> + lists:foldl( + fun(v1 = Vsn, Acc) -> + [{mk_name(Address, Vsn), + Domain_or_Ip, Addr_or_Port, + Timeout, RetryCount, + "std_trap", mk_param(Vsn), "", + [], 2048}| Acc]; + (v2 = Vsn, Acc) -> + [{mk_name(Address, Vsn), + Domain_or_Ip, Addr_or_Port, + Timeout, RetryCount, + "std_trap", mk_param(Vsn), "", + [], 2048}, + {lists:flatten( + io_lib:format( + "~s.2", [mk_name(Address, Vsn)])), + Domain_or_Ip, Addr_or_Port, + Timeout, RetryCount, + "std_inform", mk_param(Vsn), "", + [], 2048}| Acc]; + (v3 = Vsn, Acc) -> + [{mk_name(Address, Vsn), + Domain_or_Ip, Addr_or_Port, + Timeout, RetryCount, + "std_trap", mk_param(Vsn), "", + [], 2048}, + {lists:flatten( + io_lib:format( + "~s.3", [mk_name(Address, Vsn)])), + Domain_or_Ip, Addr_or_Port, + Timeout, RetryCount, + "std_inform", mk_param(Vsn), "mgrEngine", + [], 2048} | Acc] + end, OuterAcc, Vsns) + end, [], Addresses), write_agent_target_addr_config(Dir, Hdr, Conf). +write_agent_snmp_target_addr_conf( + Dir, Domain_or_Ip, Addr_or_Port, Timeout, RetryCount, Vsns) -> + Addresses = [{Domain_or_Ip, Addr_or_Port}], + write_agent_snmp_target_addr_conf( + Dir, Addresses, Timeout, RetryCount, Vsns). + mk_param(Vsn) -> lists:flatten(io_lib:format("target_~w", [Vsn])). -mk_ip([A,B,C,D], Vsn) -> - lists:flatten(io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn])). +mk_name(Address, Vsn) -> + lists:flatten( + io_lib:format( + "~s ~w", [snmp_conf:mk_addr_string(Address), Vsn])). write_agent_target_addr_config(Dir, Hdr, Conf) -> snmpa_conf:write_target_addr_config(Dir, Hdr, Conf). @@ -2049,10 +2128,19 @@ write_manager_snmp_conf(Dir, IP, Port, MMS, EngineID) -> "%% {max_message_size, 484}.\n" "%%\n\n", Hdr = header() ++ Comment, - Conf = [{port, Port}, - {address, IP}, - {engine_id, EngineID}, - {max_message_size, MMS}], + Conf = + case Port of + {Addr, P} when is_integer(P), is_atom(IP) -> + Domain = IP, + [{domain, Domain}, + {port, P}, + {address, Addr}]; + _ when is_integer(Port) -> + [{port, Port}, + {address, IP}] + end ++ + [{engine_id, EngineID}, + {max_message_size, MMS}], write_manager_config(Dir, Hdr, Conf). write_manager_config(Dir, Hdr, Conf) -> @@ -2410,83 +2498,92 @@ header() -> [?MODULE, ?version, Y, Mo, D, H, Mi, S]). -%% *If* these functions are successfull, they successfully return anything -%% (which is ignored), but they fail with either a throw or an exit or -%% something similar. - -%% Verification of one config entry read from a file --type(verify_config_entry_function() :: - fun((Entry :: term()) -> ok | {error, Reason :: term()})). - -%% Verification of config to be written --type(verify_config_function() :: - fun(() -> void())). - -%% Write config to file (as defined by Fd) --type(write_config_function() :: - fun((Fd :: file:io_device()) -> void())). - --spec write_config_file(Dir :: string(), - FileName :: string(), - Verify :: verify_config_function(), - Write :: write_config_function()) -> - ok | {error, Reason :: term()}. - -write_config_file(Dir, FileName, Verify, Write) - when (is_list(Dir) andalso - is_list(FileName) andalso - is_function(Verify) andalso - is_function(Write)) -> +%% *If* these functions are successfull, they successfully return +%% (value is ignored), but they fail preferably with +%% throw({error, Reason}). Other exceptions are also handled. + +%% Sorting order for config entries (see lists:sort/2) +-type(order_config_entry_function() :: + fun((term(), term()) -> boolean())). + +%% Check of config entries. Initial State is 'undefined' +-type(check_config_entry_function() :: + fun((Entry :: term(), State :: undefined | term()) -> + {ok | {ok, NewEntry :: term()}, NewState :: term()})). + +%% Write configuration entries to file descriptor Fd +-type(write_config_function() :: + fun((Fd :: file:io_device(), [Entry :: term()]) -> ok)). + +-spec write_config_file( + Dir :: string(), + FileName :: string(), + Order :: order_config_entry_function(), + Check :: check_config_entry_function(), + Write :: write_config_function(), + Entries :: [term()]) -> + ok | {error, term()}. + +write_config_file(Dir, FileName, Order, Check, Write, Entries) + when is_list(Dir), is_list(FileName), + is_function(Order), is_function(Check), is_function(Write), + is_list(Entries) -> try - begin - do_write_config_file(Dir, FileName, Verify, Write) - end + SortedEntries = lists:sort(Order, Entries), + _ = + lists:foldl( + fun (Entry, State) -> + case Check(Entry, State) of + {Ok, NewState} when is_list(Ok) -> + NewState; + {ok, NewState} -> + NewState; + {{ok, _}, NewState} -> + NewState + end + end, undefined, SortedEntries), + ok + of + _ -> + case file:open(filename:join(Dir, FileName), [write]) of + {ok, Fd} -> + write_config_file(Dir, FileName, Write, Entries, Fd); + Error -> + Error + end catch - throw:Error -> - Error; - T:E -> - {error, {failed_write, Dir, FileName, T, E}} - end. - - -do_write_config_file(Dir, FileName, Verify, Write) -> - Verify(), - case file:open(filename:join(Dir, FileName), [write]) of - {ok, Fd} -> - file_write_and_close(Write, Fd, Dir, FileName); Error -> - Error - end. - -append_config_file(Dir, FileName, Verify, Write) - when (is_list(Dir) andalso - is_list(FileName) andalso - is_function(Verify) andalso - is_function(Write)) -> - try - begin - do_append_config_file(Dir, FileName, Verify, Write) - end - catch - throw:Error -> + S = erlang:get_stacktrace(), + d("File write of ~s throwed: ~p~n ~p~n", + [FileName, Error, S]), Error; - T:E -> - {error, {failed_append, Dir, FileName, T, E}} + C:E -> + S = erlang:get_stacktrace(), + d("File write of ~s exception: ~p:~p~n ~p~n", + [FileName,C,E,S]), + {error, {failed_write, Dir, FileName, {C, E, S}}} end. -do_append_config_file(Dir, FileName, Verify, Write) -> - Verify(), - case file:open(filename:join(Dir, FileName), [read, write]) of - {ok, Fd} -> - file:position(Fd, eof), - file_write_and_close(Write, Fd, Dir, FileName); +write_config_file(Dir, FileName, Write, Entries, Fd) -> + try Write(Fd, Entries) of + ok -> + close_config_file(Dir, FileName, Fd) + catch Error -> - Error + S = erlang:get_stacktrace(), + d("File write of ~s throwed: ~p~n ~p~n", + [FileName, Error, S]), + close_config_file(Dir, FileName, Fd), + Error; + C:E -> + S = erlang:get_stacktrace(), + d("File write of ~s exception: ~p:~p~n ~p~n", + [FileName,C,E,S]), + close_config_file(Dir, FileName, Fd), + {error, {failed_write, Dir, FileName, {C, E, S}}} end. - -file_write_and_close(Write, Fd, Dir, FileName) -> - ok = Write(Fd), +close_config_file(Dir, FileName, Fd) -> case file:sync(Fd) of ok -> case file:close(Fd) of @@ -2496,63 +2593,159 @@ file_write_and_close(Write, Fd, Dir, FileName) -> {error, {failed_closing, Dir, FileName, Reason}} end; {error, Reason} -> + _ = file:close(Fd), {error, {failed_syncing, Dir, FileName, Reason}} end. --spec read_config_file(Dir :: string(), - FileName :: string(), - Verify :: verify_config_entry_function()) -> - {ok, Config :: list()} | {error, Reason :: term()}. -read_config_file(Dir, FileName, Verify) - when is_list(Dir) andalso is_list(FileName) andalso is_function(Verify) -> - (catch do_read_config_file(Dir, FileName, Verify)). +-spec append_config_file( + Dir :: string(), + FileName :: string(), + Order :: order_config_entry_function(), + Check :: check_config_entry_function(), + Write :: write_config_function(), + Entries :: [term()]) -> + ok | {error, term()}. + +append_config_file(Dir, FileName, Order, Check, Write, Entries) + when is_list(Dir), is_list(FileName), + is_function(Order), is_function(Check), is_function(Write), + is_list(Entries) -> + case file:open(filename:join(Dir, FileName), [read, write]) of + {ok, Fd} -> + append_config_file( + Dir, FileName, Order, Check, Write, Entries, Fd); + Error -> + Error + end. + +append_config_file(Dir, FileName, Order, Check, Write, Entries, Fd) -> + try + %% Verify the entries together with the file content + LinesInFileR = read_lines(Fd, [], 1), + StartLine = + case LinesInFileR of + [] -> + 1; + [{_, _, EndLine} | _] -> + EndLine + end, + LinesR = prepend_lines(LinesInFileR, Entries, StartLine), + SortedLines = sort_lines(lists:reverse(LinesR), Order), + _ = verify_lines(SortedLines, Check, undefined, []), + %% Append to the file + Write(Fd, Entries) + of + ok -> + close_config_file(Dir, FileName, Fd) + catch + Error -> + S = erlang:get_stacktrace(), + d("File append of ~s throwed: ~p~n ~p~n", + [FileName, Error, S]), + close_config_file(Dir, FileName, Fd), + Error; + C:E -> + S = erlang:get_stacktrace(), + d("File append of ~s exception: ~p:~p~n ~p~n", + [FileName,C,E,S]), + close_config_file(Dir, FileName, Fd), + {error, {failed_append, Dir, FileName, {C, E, S}}} + end. -do_read_config_file(Dir, FileName, Verify) -> +%% Fake line numbers, one per entry +prepend_lines(Lines, [], _) -> + Lines; +prepend_lines(Lines, [Entry | Entries], StartLine) -> + EndLine = StartLine + 1, + prepend_lines([{StartLine, Entry, EndLine} | Lines], Entries, EndLine). + + + +-spec read_config_file( + Dir :: string(), + FileName :: string(), + Order :: order_config_entry_function(), + Check :: check_config_entry_function()) -> + {ok, Config :: [Entry :: term()]} | + {error, Reason :: term()}. + +read_config_file(Dir, FileName, Order, Check) + when is_list(Dir), is_list(FileName), + is_function(Order), is_function(Check) -> case file:open(filename:join(Dir, FileName), [read]) of {ok, Fd} -> - Result = read_loop(Fd, [], Verify, 1), - file:close(Fd), - Result; + try + Lines = lists:reverse(read_lines(Fd, [], 1)), + SortedLines = sort_lines(Lines, Order), + {ok, verify_lines(SortedLines, Check, undefined, [])} + catch + Error -> + S = erlang:get_stacktrace(), + d("File read of ~s throwed: ~p~n ~p~n", + [FileName, Error, S]), + {error, Error}; + T:E -> + S = erlang:get_stacktrace(), + d("File read of ~s exception: ~p:~p~n ~p~n", + [FileName,T,E,S]), + {error, {failed_read, Dir, FileName, {T, E, S}}} + after + file:close(Fd) + end; {error, Reason} -> {error, {Reason, FileName}} end. -read_loop(Fd, Acc, Check, StartLine) -> - case read_term(Fd, StartLine) of +read_lines(Fd, Acc, StartLine) -> + case read_and_parse_term(Fd, StartLine) of {ok, Term, EndLine} -> - case (catch Check(Term)) of - ok -> - read_loop(Fd, [Term | Acc], Check, EndLine); - {error, Reason} -> - {error, {failed_check, StartLine, EndLine, Reason}}; - Error -> - {error, {failed_check, StartLine, EndLine, Error}} - end; - {error, EndLine, Error} -> - {error, {failed_reading, StartLine, EndLine, Error}}; - eof -> - {ok, lists:reverse(Acc)} + read_lines(Fd, [{StartLine, Term, EndLine}|Acc], EndLine); + {error, Error, EndLine} -> + throw({failed_reading, StartLine, EndLine, Error}); + {eof, _EndLine} -> + Acc end. - -read_term(Fd, StartLine) -> + +read_and_parse_term(Fd, StartLine) -> case io:request(Fd, {get_until, "", erl_scan, tokens, [StartLine]}) of {ok, Tokens, EndLine} -> case erl_parse:parse_term(Tokens) of {ok, Term} -> {ok, Term, EndLine}; {error, {Line, erl_parse, Error}} -> - {error, Line, {parse_error, Error}} + {error, {parse_error, Error}, Line} end; - {error, E, EndLine} -> - {error, EndLine, E}; - {eof, _EndLine} -> - eof; Other -> Other end. +sort_lines(Lines, Order) -> + lists:sort( + fun ({_, T1, _}, {_, T2, _}) -> + Order(T1, T2) + end, Lines). + +verify_lines([], _, _, Acc) -> + lists:reverse(Acc); +verify_lines( + [{StartLine, Term, EndLine}|Lines], Check, State, Acc) -> + try Check(Term, State) of + {Terms, NewState} when is_list(Terms) -> + verify_lines(Lines, Check, NewState, Terms ++ Acc); + {ok, NewState} -> + verify_lines(Lines, Check, NewState, [Term|Acc]); + {{ok, NewTerm}, NewState} -> + verify_lines(Lines, Check, NewState, [NewTerm|Acc]) + catch + {error, Reason} -> + throw({failed_check, StartLine, EndLine, Reason}); + C:R -> + S = erlang:get_stacktrace(), + throw({failed_check, StartLine, EndLine, {C, R, S}}) + end. + agent_snmp_mk_secret(Alg, Passwd, EngineID) -> snmp_usm:passwd2localized_key(Alg, Passwd, EngineID). @@ -2575,8 +2768,8 @@ ensure_started(App) -> %% ------------------------------------------------------------------------- -% d(F, A) -> -% i("DBG: " ++ F, A). +d(F, A) -> + i("DBG: " ++ F, A). i(F) -> i(F, []). diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl index ae28df37fa..4b22281b89 100644 --- a/lib/snmp/src/misc/snmp_log.erl +++ b/lib/snmp/src/misc/snmp_log.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. 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 @@ -23,7 +23,7 @@ -export([ create/4, create/5, create/6, open/1, open/2, change_size/2, close/1, sync/1, info/1, - log/4, + log/3, log/4, log_to_txt/6, log_to_txt/7, log_to_txt/8, log_to_io/5, log_to_io/6, log_to_io/7 ]). @@ -231,7 +231,20 @@ validate(Log, SeqNoReq) validate_seqno(PrevSN, SeqNo), {Timestamp, SeqNo}; - ({Timestamp, _Packet, _Addr, _Port}, {PrevTS, _PrevSN}) when SeqNoReq =:= true -> + ({Timestamp, SeqNo, _Packet, _AddrStr}, {PrevTS, PrevSN}) + when is_integer(SeqNo) -> + ?vtrace("validating log entry when" + "~n Timestamp: ~p" + "~n SeqNo: ~p" + "~n PrevTS: ~p" + "~n PrevSN: ~p", + [Timestamp, SeqNo, PrevTS, PrevSN]), + validate_timestamp(PrevTS, Timestamp), + validate_seqno(PrevSN, SeqNo), + {Timestamp, SeqNo}; + + ({Timestamp, _Packet, _Addr, _Port}, {PrevTS, _PrevSN}) + when SeqNoReq =:= true -> ?vtrace("validating log entry when" "~n Timestamp: ~p" "~n PrevTS: ~p", @@ -344,12 +357,20 @@ validate_loop(Error, _Log, _Write, _PrevTS, _PrevSN) -> %% log(Log, Packet, Addr, Port) %%----------------------------------------------------------------- -log(#snmp_log{id = Log, seqno = SeqNo}, Packet, Addr, Port) -> +log(#snmp_log{id = Log, seqno = SeqNo}, Packet, AddrStr) -> + ?vtrace( + "log -> entry with~n" + " Log: ~p~n" + " AddrStr: ~s", [Log, AddrStr]), + Entry = make_entry(SeqNo, Packet, AddrStr), + disk_log:alog(Log, Entry). + +log(#snmp_log{id = Log, seqno = SeqNo}, Packet, Ip, Port) -> ?vtrace("log -> entry with" "~n Log: ~p" - "~n Addr: ~p" - "~n Port: ~p", [Log, Addr, Port]), - Entry = make_entry(SeqNo, Packet, Addr, Port), + "~n Ip: ~p" + "~n Port: ~p", [Log, Ip, Port]), + Entry = make_entry(SeqNo, Packet, Ip, Port), %% io:format("log -> " %% "~n Entry: ~p" %% "~n Info: ~p" @@ -361,18 +382,35 @@ log(#snmp_log{id = Log, seqno = SeqNo}, Packet, Addr, Port) -> %% "~n", [Res, disk_log:info(Log)]), %% disk_log:sync(Log), Res. - -make_entry(SeqNoGen, Packet, Addr, Port) -> + +make_entry(SeqNoGen, Packet, AddrStr) + when is_integer(Packet); + is_tuple(AddrStr) -> + erlang:error(badarg, [SeqNoGen, Packet, AddrStr]); +make_entry(SeqNoGen, Packet, AddrStr) -> try next_seqno(SeqNoGen) of disabled -> - {timestamp(), Packet, Addr, Port}; - {ok, NextSeqNo} -> - {timestamp(), NextSeqNo, Packet, Addr, Port} + {timestamp(), Packet, AddrStr}; + {ok, NextSeqNo} when is_integer(NextSeqNo) -> + {timestamp(), NextSeqNo, Packet, AddrStr} catch _:_ -> - {timestamp(), Packet, Addr, Port} + {timestamp(), Packet, AddrStr} + end. + +make_entry(SeqNoGen, Packet, Ip, Port) when is_integer(Packet) -> + erlang:error(badarg, [SeqNoGen, Packet, Ip, Port]); +make_entry(SeqNoGen, Packet, Ip, Port) -> + try next_seqno(SeqNoGen) of + disabled -> + {timestamp(), Packet, Ip, Port}; + {ok, NextSeqNo} when is_integer(NextSeqNo) -> + {timestamp(), NextSeqNo, Packet, Ip, Port} + catch + _:_ -> + {timestamp(), Packet, Ip, Port} end. next_seqno({M, F, A}) -> @@ -674,60 +712,68 @@ format_msg(Entry, Mib, Start, Stop) -> end. %% This is an old-style entry, that never had the sequence-number -do_format_msg({Timestamp, Packet, {Addr, Port}}, Mib) -> - do_format_msg(Timestamp, Packet, Addr, Port, Mib); +do_format_msg({Timestamp, Packet, {Ip, Port}}, Mib) -> + do_format_msg(Timestamp, Packet, ipPort2Str(Ip, Port), Mib); +%% This is the format without sequence-number +do_format_msg({Timestamp, Packet, AddrStr}, Mib) -> + do_format_msg(Timestamp, Packet, AddrStr, Mib); +%% This is the format with sequence-number +do_format_msg({Timestamp, SeqNo, Packet, AddrStr}, Mib) + when is_integer(SeqNo) -> + do_format_msg(Timestamp, Packet, AddrStr, Mib); %% This is the format without sequence-number -do_format_msg({Timestamp, Packet, Addr, Port}, Mib) -> - do_format_msg(Timestamp, Packet, Addr, Port, Mib); +do_format_msg({Timestamp, Packet, Ip, Port}, Mib) -> + do_format_msg(Timestamp, Packet, ipPort2Str(Ip, Port), Mib); %% This is the format with sequence-number -do_format_msg({Timestamp, SeqNo, Packet, Addr, Port}, Mib) -> - do_format_msg(Timestamp, SeqNo, Packet, Addr, Port, Mib); +do_format_msg({Timestamp, SeqNo, Packet, Ip, Port}, Mib) -> + do_format_msg(Timestamp, SeqNo, Packet, ipPort2Str(Ip, Port), Mib); %% This is crap... do_format_msg(_, _) -> format_tab("** unknown entry in log file\n\n", []). -do_format_msg(TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port, Mib) -> +do_format_msg(TimeStamp, {V3Hdr, ScopedPdu}, AddrStr, Mib) -> case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of ScopedPDU when is_record(ScopedPDU, scopedPdu) -> Msg = #message{version = 'version-3', vsn_hdr = V3Hdr, data = ScopedPDU}, - f(ts2str(TimeStamp), "", Msg, Addr, Port, Mib); + f(ts2str(TimeStamp), "", Msg, AddrStr, Mib); {'EXIT', Reason} -> - format_tab("** error in log file at ~s from ~p:~w ~p\n\n", - [ts2str(TimeStamp), ip(Addr), Port, Reason]) + format_tab( + "** error in log file at ~s from ~s ~p\n\n", + [ts2str(TimeStamp), AddrStr, Reason]) end; -do_format_msg(TimeStamp, Packet, Addr, Port, Mib) -> +do_format_msg(TimeStamp, Packet, AddrStr, Mib) -> case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of Msg when is_record(Msg, message) -> - f(ts2str(TimeStamp), "", Msg, Addr, Port, Mib); + f(ts2str(TimeStamp), "", Msg, AddrStr, Mib); {'EXIT', Reason} -> format_tab("** error in log file ~p\n\n", [Reason]) end. -do_format_msg(TimeStamp, SeqNo, {V3Hdr, ScopedPdu}, Addr, Port, Mib) -> +do_format_msg(TimeStamp, SeqNo, {V3Hdr, ScopedPdu}, AddrStr, Mib) -> case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of ScopedPDU when is_record(ScopedPDU, scopedPdu) -> Msg = #message{version = 'version-3', vsn_hdr = V3Hdr, data = ScopedPDU}, - f(ts2str(TimeStamp), sn2str(SeqNo), Msg, Addr, Port, Mib); + f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib); {'EXIT', Reason} -> - format_tab("** error in log file at ~s from ~p:~w ~p\n\n", - [ts2str(TimeStamp), sn2str(SeqNo), - ip(Addr), Port, Reason]) + format_tab( + "** error in log file at ~s from ~s ~p\n\n", + [ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason]) end; -do_format_msg(TimeStamp, SeqNo, Packet, Addr, Port, Mib) -> +do_format_msg(TimeStamp, SeqNo, Packet, AddrStr, Mib) -> case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of Msg when is_record(Msg, message) -> - f(ts2str(TimeStamp), sn2str(SeqNo), Msg, Addr, Port, Mib); + f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib); {'EXIT', Reason} -> - format_tab("** error in log file ~s from ~p:~w ~p\n\n", - [ts2str(TimeStamp), sn2str(SeqNo), - ip(Addr), Port, Reason]) + format_tab( + "** error in log file ~s from ~s ~p\n\n", + [ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason]) end. @@ -771,44 +817,71 @@ do_format_msg(TimeStamp, SeqNo, Packet, Addr, Port, Mib) -> f(TimeStamp, SeqNo, #message{version = Vsn, vsn_hdr = VsnHdr, data = Data}, - Addr, Port, Mib) -> + AddrStr, Mib) -> Str = format_pdu(Data, Mib), HdrStr = format_header(Vsn, VsnHdr), - case get_type(Data) of - trappdu -> - f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); - 'snmpv2-trap' -> - f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); - 'inform-request' -> - f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); - 'get-response' -> - f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); - report -> - f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); - _ -> - f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) - end. + Class = + case get_type(Data) of + trappdu -> + trap; + 'snmpv2-trap' -> + trap; + 'inform-request' -> + inform; + 'get-response' -> + response; + report -> + report; + _ -> + request + end, + format_tab( + "~w ~s - ~s [~s]~s ~w\n~s", + [Class, AddrStr, HdrStr, TimeStamp, SeqNo, Vsn, Str]). + +%% f(TimeStamp, SeqNo, +%% #message{version = Vsn, vsn_hdr = VsnHdr, data = Data}, +%% Addr, Port, Mib) -> +%% Str = format_pdu(Data, Mib), +%% HdrStr = format_header(Vsn, VsnHdr), +%% case get_type(Data) of +%% trappdu -> +%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); +%% 'snmpv2-trap' -> +%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); +%% 'inform-request' -> +%% f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); +%% 'get-response' -> +%% f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); +%% report -> +%% f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); +%% _ -> +%% f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) +%% end. -f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("request ~s:~w - ~s [~s]~s ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). +%% f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> +%% format_tab("request ~s:~w - ~s [~s]~s ~w\n~s", +%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). -f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("response ~s:~w - ~s [~s]~s ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). +%% f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> +%% format_tab("response ~s:~w - ~s [~s]~s ~w\n~s", +%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). -f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("report ~s:~w - ~s [~s]~s ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). +%% f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> +%% format_tab("report ~s:~w - ~s [~s]~s ~w\n~s", +%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). -f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("trap ~s:~w - ~s [~s]~s ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). +%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> +%% format_tab("trap ~s:~w - ~s [~s]~s ~w\n~s", +%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). -f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("inform ~s:~w - ~s [~s]~s ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). +%% f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> +%% format_tab("inform ~s:~w - ~s [~s]~s ~w\n~s", +%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). +ipPort2Str(Ip, Port) -> + snmp_conf:mk_addr_string({Ip, Port}). + %% io_lib:format("~s:~w", [ip(Ip), Port]). %% Convert a timestamp 2-tupple to a printable string %% @@ -909,8 +982,10 @@ get_type(#pdu{type = Type}) -> Type. -ip({A,B,C,D}) -> - io_lib:format("~w.~w.~w.~w", [A,B,C,D]). +%% ip(Domain, Addr) -> +%% snmp_conf:mk_addr_string(Domain, Addr). +%% ip({A,B,C,D}) -> +%% io_lib:format("~w.~w.~w.~w", [A,B,C,D]). diff --git a/lib/snmp/src/misc/snmp_pdus.erl b/lib/snmp/src/misc/snmp_pdus.erl index 15156f7467..90fa4c0dea 100644 --- a/lib/snmp/src/misc/snmp_pdus.erl +++ b/lib/snmp/src/misc/snmp_pdus.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -174,7 +174,7 @@ dec_pdu_tag(168) -> dec_pdu([164 | Bytes]) -> % It's a trap Bytes2 = get_data_bytes(Bytes), {Enterprise, Rest1} = dec_oid_tag(Bytes2), - {{'IpAddress', AgentAddr}, Rest2} = dec_value(Rest1), + {{'IpAddress', [_, _, _, _] = AgentAddr}, Rest2} = dec_value(Rest1), {GenericTrap, Rest3} = dec_int_tag(Rest2), {SpecificTrap, Rest4} = dec_int_tag(Rest3), {{'TimeTicks', TimeStamp}, VBBytes} = dec_value(Rest4), @@ -664,7 +664,9 @@ enc_value('BITS', Val) -> enc_oct_str_tag(bits_to_str(Val)); enc_value('OBJECT IDENTIFIER', Val) -> enc_oid_tag(Val); -enc_value('IpAddress', Val) -> +enc_value('IpAddress', {A, B, C, D}) -> + enc_value('IpAddress', [A,B,C,D]); +enc_value('IpAddress', Val) when is_list(Val) -> Bytes2 = enc_oct_str_notag(Val), Len2 = elength(length(Bytes2)), lists:append([64 | Len2],Bytes2); diff --git a/lib/snmp/test/Makefile b/lib/snmp/test/Makefile index 7bc9dd07d4..a9bbe7fe62 100644 --- a/lib/snmp/test/Makefile +++ b/lib/snmp/test/Makefile @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2012. All Rights Reserved. +# Copyright Ericsson AB 1997-2014. 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 @@ -36,7 +36,7 @@ VSN = $(SNMP_VSN) include modules.mk SNMP_ROOT = .. -SNMP_SUITE = snmp_SUITE +SNMP_SUITE = snmp_SUITE ERL_FILES = $(MODULES:%=%.erl) @@ -239,6 +239,7 @@ release_tests_spec: opt $(INSTALL_DATA) $(RELTEST_FILES) $(COVER_SPEC_FILE) "$(RELSYSDIR)" chmod -R u+w "$(RELSYSDIR)" tar cf - snmp_test_data | (cd "$(RELSYSDIR)"; tar xf -) + tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) release_docs_spec: diff --git a/lib/snmp/test/klas3.erl b/lib/snmp/test/klas3.erl index ec78d19dbb..4cbd852b2d 100644 --- a/lib/snmp/test/klas3.erl +++ b/lib/snmp/test/klas3.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. 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 @@ -67,11 +67,15 @@ fname(get) -> end, case snmpa:current_address() of {value, {[_A,_B,_C,_D], E}} when is_integer(E) -> ok; - {value, _} -> throw("bad_ip"); - _ -> throw("bad_adr") + {value, {D, _}} when is_atom(D) -> ok; + {value, Ip} -> + throw(format_string("bad_ip: ~p", [Ip])); + Other -> + throw(format_string("bad_adr: ~p", [Other])) end, case snmpa:current_net_if_data() of {value, []} -> ok; + {value, [{request_ref, R}]} when is_reference(R) -> ok; {value, _} -> throw("bad_nil"); _ -> throw("bad_nid") end, @@ -160,3 +164,6 @@ ftab2(get_next, [9], _Cols) -> % bad return value io:format("** Here comes Error Report get_next 3 bad return~n"), [{[1,5],1},{[2,5],3},{[2,6],3}]. + +format_string(Format, Args) -> + lists:flatten(io_lib:format(Format, Args)). diff --git a/lib/snmp/test/modules.mk b/lib/snmp/test/modules.mk index fd8315ec4d..1bf08a9729 100644 --- a/lib/snmp/test/modules.mk +++ b/lib/snmp/test/modules.mk @@ -19,6 +19,7 @@ SUITE_MODULES = \ snmp_SUITE \ + snmp_to_snmpnet_SUITE \ snmp_app_test \ snmp_appup_test \ snmp_compiler_test \ diff --git a/lib/snmp/test/snmp_SUITE.erl b/lib/snmp/test/snmp_SUITE.erl index 22b9c64588..6fabf6410f 100644 --- a/lib/snmp/test/snmp_SUITE.erl +++ b/lib/snmp/test/snmp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. 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 @@ -80,7 +80,8 @@ groups() -> {group, note_store_test}]}, {agent, [], [{group, mibs_test}, {group, nfilter_test}, - {group, agent_test}]}, + {group, agent_test}, + {group, snmpnet_test}]}, {manager, [], [{group, manager_config_test}, {group, manager_user_test}, {group, manager_test}]}, @@ -95,6 +96,7 @@ groups() -> {mibs_test, [], [{snmp_agent_mibs_test, all}]}, {nfilter_test, [], [{snmp_agent_nfilter_test, all}]}, {agent_test, [], [{snmp_agent_test, all}]}, + {snmpnet_test, [], [{snmp_to_snmpnet_SUITE, all}]}, {manager_config_test, [], [{snmp_manager_config_test, all}]}, {manager_user_test, [], [{snmp_manager_user_test, all}]}, {manager_test, [], [{snmp_manager_test, all}]} @@ -107,15 +109,18 @@ init_per_group(GroupName, Config0) -> "~n GroupName: ~p" "~n Config0: ~p", [GroupName, Config0]), - %% Group name is not really the suite name - %% (but it is a good enough approximation), - %% but it does not matter since we only need - %% it to be unique. - snmp_test_lib:init_suite_top_dir(GroupName, Config0). - - + case GroupName of + snmpnet_test -> + Config0; + _ -> + %% Group name is not really the suite name + %% (but it is a good enough approximation), + %% but it does not matter since we only need + %% it to be unique. + snmp_test_lib:init_suite_top_dir(GroupName, Config0) + end. + +end_per_group(snmpnet_test, Config) -> + Config; end_per_group(_GroupName, Config) -> lists:keydelete(snmp_suite_top_dir, 1, Config). - - - diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl index 2a9f2e842d..9a9258aa91 100644 --- a/lib/snmp/test/snmp_agent_test.erl +++ b/lib/snmp/test/snmp_agent_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2013. All Rights Reserved. +%% Copyright Ericsson AB 2003-2014. 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 @@ -37,7 +37,7 @@ v1_processing/1, big/1, big2/1, - loop_mib_1/1, + loop_mib_1/1, api/1, subagent/1, mnesia/1, @@ -298,7 +298,6 @@ %% tickets2 otp8395/1, otp9884/1 - ]). %% Internal exports @@ -390,9 +389,9 @@ usm_read/0, usm_del_user/0, usm_bad/0, - loop_mib_1_test/0, - loop_mib_2_test/0, - loop_mib_3_test/0, + loop_mib_1_test/0, + loop_mib_2_test/0, + loop_mib_3_test/0, otp_1129_i/1, otp_1162_test/0, otp_1131_test/0, @@ -518,9 +517,13 @@ groups() -> {mib_storage_varm_mnesia, [], varm_mib_storage_mnesia_cases()}, {misc, [], misc_cases()}, {test_v1, [], v1_cases()}, + {test_v1_ipv6, [], v1_cases_ipv6()}, {test_v2, [], v2_cases()}, + {test_v2_ipv6, [], v2_cases_ipv6()}, {test_v1_v2, [], v1_v2_cases()}, + {test_v1_v2_ipv6, [], v1_v2_cases()}, {test_v3, [], v3_cases()}, + {test_v3_ipv6, [], v3_cases_ipv6()}, {test_multi_threaded, [], mt_cases()}, {multiple_reqs, [], mul_cases()}, {multiple_reqs_2, [], mul_cases_2()}, @@ -611,6 +614,14 @@ init_per_group(test_v2 = GroupName, Config) -> init_v2(snmp_test_lib:init_group_top_dir(GroupName, Config)); init_per_group(test_v1 = GroupName, Config) -> init_v1(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(test_v1_ipv6 = GroupName, Config) -> + init_per_group_ipv6(GroupName, Config, fun init_v1/1); +init_per_group(test_v2_ipv6 = GroupName, Config) -> + init_per_group_ipv6(GroupName, Config, fun init_v2/1); +init_per_group(test_v1_v2_ipv6 = GroupName, Config) -> + init_per_group_ipv6(GroupName, Config, fun init_v1_v2/1); +init_per_group(test_v3_ipv6 = GroupName, Config) -> + init_per_group_ipv6(GroupName, Config, fun init_v3/1); init_per_group(misc = GroupName, Config) -> init_misc(snmp_test_lib:init_group_top_dir(GroupName, Config)); init_per_group(mib_storage_varm_mnesia = GroupName, Config) -> @@ -637,6 +648,18 @@ init_per_group(mib_storage_ets = GroupName, Config) -> init_per_group(GroupName, Config) -> snmp_test_lib:init_group_top_dir(GroupName, Config). +init_per_group_ipv6(GroupName, Config, Init) -> + case ct:require(ipv6_hosts) of + ok -> + Init( + snmp_test_lib:init_group_top_dir( + GroupName, + [{ipfamily, inet6}, + {ip, ?LOCALHOST(inet6)} | lists:keydelete(ip, 1, Config)])); + _ -> + {skip, "Host does not support IPV6"} + end. + end_per_group(all_tcs, Config) -> finish_all(Config); end_per_group(otp7157, Config) -> @@ -655,31 +678,39 @@ end_per_group(multiple_reqs_3, Config) -> finish_mul(Config); end_per_group(test_multi_threaded, Config) -> finish_mt(Config); -end_per_group(test_v3, Config) -> +end_per_group(test_v3_ipv6, Config) -> + finish_v3(Config); +end_per_group(test_v1_v2_ipv6, Config) -> + finish_v1_v2(Config); +end_per_group(test_v2_ipv6, Config) -> + finish_v2(Config); +end_per_group(test_v1_ipv6, Config) -> + finish_v1(Config); +end_per_group(test_v3, Config) -> finish_v3(Config); -end_per_group(test_v1_v2, Config) -> +end_per_group(test_v1_v2, Config) -> finish_v1_v2(Config); -end_per_group(test_v2, Config) -> +end_per_group(test_v2, Config) -> finish_v2(Config); -end_per_group(test_v1, Config) -> +end_per_group(test_v1, Config) -> finish_v1(Config); -end_per_group(misc, Config) -> +end_per_group(misc, Config) -> finish_misc(Config); -end_per_group(mib_storage_varm_mnesia, Config) -> +end_per_group(mib_storage_varm_mnesia, Config) -> finish_varm_mib_storage_mnesia(Config); -end_per_group(mib_storage_varm_dets, Config) -> +end_per_group(mib_storage_varm_dets, Config) -> finish_varm_mib_storage_dets(Config); -end_per_group(mib_storage_size_check_mnesia, Config) -> +end_per_group(mib_storage_size_check_mnesia, Config) -> finish_size_check_msm(Config); -end_per_group(mib_storage_size_check_dets, Config) -> +end_per_group(mib_storage_size_check_dets, Config) -> finish_size_check_msd(Config); -end_per_group(mib_storage_size_check_ets, Config) -> +end_per_group(mib_storage_size_check_ets, Config) -> finish_size_check_mse(Config); -end_per_group(mib_storage_mnesia, Config) -> +end_per_group(mib_storage_mnesia, Config) -> finish_mib_storage_mnesia(Config); -end_per_group(mib_storage_dets, Config) -> +end_per_group(mib_storage_dets, Config) -> finish_mib_storage_dets(Config); -end_per_group(mib_storage_ets, Config) -> +end_per_group(mib_storage_ets, Config) -> finish_mib_storage_ets(Config); end_per_group(_GroupName, Config) -> Config. @@ -810,6 +841,10 @@ cases() -> {group, test_v2}, {group, test_v1_v2}, {group, test_v3}, + {group, test_v1_ipv6}, + {group, test_v2_ipv6}, + {group, test_v1_v2_ipv6}, + {group, test_v3_ipv6}, {group, test_multi_threaded}, {group, mib_storage}, {group, tickets1} @@ -865,8 +900,8 @@ start_v2_agent(Config) -> start_v2_agent(Config, Opts) -> snmp_agent_test_lib:start_v2_agent(Config, Opts). -start_v3_agent(Config) -> - snmp_agent_test_lib:start_v3_agent(Config). +%% start_v3_agent(Config) -> +%% snmp_agent_test_lib:start_v3_agent(Config). start_v3_agent(Config, Opts) -> snmp_agent_test_lib:start_v3_agent(Config, Opts). @@ -1636,7 +1671,7 @@ del_dir(Dir, Depth) -> ok end. -%v1_cases() -> [loop_mib]; +%v1_cases() -> [loop_mib_1]; v1_cases() -> [ simple, @@ -1644,7 +1679,7 @@ v1_cases() -> v1_processing, big, big2, - loop_mib_1, + loop_mib_1, api, subagent, mnesia, @@ -1662,14 +1697,40 @@ v1_cases() -> change_target_addr_config ]. +v1_cases_ipv6() -> + [ + simple, + v1_processing, + loop_mib_1, +%% big, +%% big2, + api, + subagent, +%% mnesia, +%% {group, multiple_reqs}, + sa_register, +%% v1_trap, % sends v1 trap +%% sa_error, + next_across_sa, + undo, +%% {group, reported_bugs}, + {group, standard_mibs}, % snmp_standard_mib still failing, sends v1 trap + sparse_table, +%% cnt_64, % sends v1 trap + opaque +%% change_target_addr_config % sends v1 trap + ]. + init_v1(Config) when is_list(Config) -> ?line SaNode = ?config(snmp_sa, Config), ?line create_tables(SaNode), ?line AgentConfDir = ?config(agent_conf_dir, Config), ?line MgrDir = ?config(mgr_dir, Config), ?line Ip = ?config(ip, Config), - ?line config([v1], MgrDir, AgentConfDir, - tuple_to_list(Ip), tuple_to_list(Ip)), + ?line IpFamily = config_ipfamily(Config), + ?line config( + [v1], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip), IpFamily), [{vsn, v1} | start_v1_agent(Config)]. finish_v1(Config) when is_list(Config) -> @@ -1706,14 +1767,43 @@ v2_cases() -> v2_caps ]. +v2_cases_ipv6() -> + [ + simple_2, + v2_processing, +%% big_2, +%% big2_2, + loop_mib_2, + api_2, + subagent_2, +%% mnesia_2, +%% {group, multiple_reqs_2}, + sa_register_2, + v2_trap, + {group, v2_inform}, +%% sa_error_2, + next_across_sa_2, + undo_2, +%% {group, reported_bugs_2}, + {group, standard_mibs_2}, + v2_types, + implied, + sparse_table_2, + cnt_64_2, + opaque_2, + v2_caps + ]. + init_v2(Config) when is_list(Config) -> SaNode = ?config(snmp_sa, Config), create_tables(SaNode), AgentConfDir = ?config(agent_conf_dir, Config), MgrDir = ?config(mgr_dir, Config), Ip = ?config(ip, Config), - config([v2], MgrDir, AgentConfDir, - tuple_to_list(Ip), tuple_to_list(Ip)), + IpFamily = config_ipfamily(Config), + config( + [v2], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip), IpFamily), [{vsn, v2} | start_v2_agent(Config)]. finish_v2(Config) when is_list(Config) -> @@ -1732,8 +1822,9 @@ init_v1_v2(Config) when is_list(Config) -> AgentConfDir = ?config(agent_conf_dir, Config), MgrDir = ?config(mgr_dir, Config), Ip = ?config(ip, Config), + IpFamily = config_ipfamily(Config), config([v1,v2], MgrDir, AgentConfDir, - tuple_to_list(Ip), tuple_to_list(Ip)), + tuple_to_list(Ip), tuple_to_list(Ip), IpFamily), [{vsn, bilingual} | start_bilingual_agent(Config)]. finish_v1_v2(Config) when is_list(Config) -> @@ -1771,6 +1862,34 @@ v3_cases() -> v2_caps_3 ]. +v3_cases_ipv6() -> + [ + simple_3, + v3_processing, +%% big_3, +%% big2_3, + api_3, + subagent_3, +%% mnesia_3, + loop_mib_3, +%% {group, multiple_reqs_3}, + sa_register_3, + v3_trap, + {group, v3_inform}, +%% sa_error_3, + next_across_sa_3, + undo_3, +%% {group, reported_bugs_3}, + {group, standard_mibs_3}, + {group, v3_security}, + v2_types_3, + implied_3, + sparse_table_3, + cnt_64_3, + opaque_3, + v2_caps_3 + ]. + init_v3(Config) when is_list(Config) -> %% Make sure crypto works, otherwise start_agent will fail %% and we will be stuck with a bunch of mnesia tables for @@ -1792,9 +1911,16 @@ init_v3(Config) when is_list(Config) -> AgentConfDir = ?config(agent_conf_dir, Config), MgrDir = ?config(mgr_dir, Config), Ip = ?config(ip, Config), - ?line ok = config([v3], MgrDir, AgentConfDir, - tuple_to_list(Ip), tuple_to_list(Ip)), - [{vsn, v3} | start_v3_agent(Config)]. + IpFamily = config_ipfamily(Config), + ?line ok = + config( + [v3], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip), IpFamily), + Opts = + [{master_agent_verbosity, trace}, + {agent_verbosity, trace}, + {net_if_verbosity, trace}], + [{vsn, v3} | start_v3_agent(Config, Opts)]. finish_v3(Config) when is_list(Config) -> delete_tables(), @@ -5546,7 +5672,7 @@ usm_bad() -> %%----------------------------------------------------------------- loop_mib_1(suite) -> []; loop_mib_1(Config) when is_list(Config) -> - ?P(loop_mib_1), + ?P(loop_mib_1), ?LOG("loop_mib_1 -> initiate case",[]), %% snmpa:verbosity(master_agent,debug), %% snmpa:verbosity(mib_server,info), @@ -5554,7 +5680,7 @@ loop_mib_1(Config) when is_list(Config) -> ?DBG("loop_mib_1 -> ~n" "\tSaNode: ~p~n" "\tMgrNode: ~p~n" - "\tMibDir: ~p", [_SaNode, _MgrNode, _MibDir]), + "\tMibDir: ~p",[_SaNode, _MgrNode, _MibDir]), ?DBG("loop_mib_1 -> load mib SNMP-COMMUNITY-MIB",[]), ?line load_master_std("SNMP-COMMUNITY-MIB"), ?DBG("loop_mib_1 -> load mib SNMP-MPD-MIB",[]), @@ -6378,8 +6504,6 @@ otp_4394_config(AgentConfDir, MgrDir, Ip0) -> ?line write_notify_conf(AgentConfDir), ok. - - otp_4394_finish(Config) when is_list(Config) -> ?DBG("finish_otp_4394 -> entry", []), C1 = stop_agent(Config), @@ -6532,6 +6656,7 @@ otp8395({init, Config}) when is_list(Config) -> %% SubAgentHost = ?HPSTNAME(SubAgentNode), ManagerHost = ?HOSTNAME(ManagerNode), + IpFamily = inet, Host = snmp_test_lib:hostname(), Ip = ?LOCALHOST(), {ok, AgentIP0} = snmp_misc:ip(AgentHost), @@ -6549,9 +6674,7 @@ otp8395({init, Config}) when is_list(Config) -> Vsns = [v1], AgentConfDir = ?config(agent_conf_dir, Config), ManagerConfDir = ?config(manager_top_dir, Config), - snmp_agent_test_lib:config(Vsns, - ManagerConfDir, AgentConfDir, - ManagerIP, AgentIP), + config(Vsns, ManagerConfDir, AgentConfDir, ManagerIP, AgentIP, IpFamily), %% -- @@ -6560,6 +6683,7 @@ otp8395({init, Config}) when is_list(Config) -> Config2 = start_agent([{host, Host}, {ip, Ip}, + {ipfamily, IpFamily}, {agent_node, AgentNode}, {agent_host, AgentHost}, {agent_ip, AgentIP}, @@ -6639,6 +6763,7 @@ otp8395(Config) when is_list(Config) -> put(mib_dir, ?config(mib_dir, Config)), put(vsn, v1), put(master_host, ?config(agent_host, Config)), + put(ipfamily, ?config(ipfamily, Config)), try_test(simple_standard_test), ?SLEEP(1000), @@ -6666,126 +6791,12 @@ otp8395(Config) when is_list(Config) -> otp9884({init, Config}) when is_list(Config) -> ?DBG("otp9884(init) -> entry with" "~n Config: ~p", [Config]), - - %% -- - %% Start nodes - %% - - {ok, AgentNode} = start_node(agent), - - %% We don't use a manager in this test but the (common) config - %% function takes an argument that is derived from this - {ok, ManagerNode} = start_node(manager), - - %% -- - %% Mnesia init - %% - - AgentDbDir = ?config(agent_db_dir, Config), - AgentMnesiaDir = join([AgentDbDir, "mnesia"]), - mnesia_init(AgentNode, AgentMnesiaDir), - - mnesia_create_schema(AgentNode, [AgentNode]), - - mnesia_start(AgentNode), - - %% -- - %% Host & IP - %% - - AgentHost = ?HOSTNAME(AgentNode), - ManagerHost = ?HOSTNAME(ManagerNode), - - Host = snmp_test_lib:hostname(), - Ip = ?LOCALHOST(), - {ok, AgentIP0} = snmp_misc:ip(AgentHost), - AgentIP = tuple_to_list(AgentIP0), - {ok, ManagerIP0} = snmp_misc:ip(ManagerHost), - ManagerIP = tuple_to_list(ManagerIP0), - - - %% -- - %% Write agent config - %% - - Vsns = [v1], - ManagerConfDir = ?config(manager_top_dir, Config), - AgentConfDir = ?config(agent_conf_dir, Config), - AgentTopDir = ?config(agent_top_dir, Config), - AgentBkpDir1 = join([AgentTopDir, backup1]), - AgentBkpDir2 = join([AgentTopDir, backup2]), - ok = file:make_dir(AgentBkpDir1), - ok = file:make_dir(AgentBkpDir2), - AgentBkpDirs = [AgentBkpDir1, AgentBkpDir2], - snmp_agent_test_lib:config(Vsns, - ManagerConfDir, AgentConfDir, - ManagerIP, AgentIP), - - - %% -- - %% Start the agent - %% - - Config2 = start_agent([{host, Host}, - {ip, Ip}, - {agent_node, AgentNode}, - {agent_host, AgentHost}, - {agent_ip, AgentIP}, - {agent_backup_dirs, AgentBkpDirs}|Config]), - - %% -- - %% Create watchdog - %% - - Dog = ?WD_START(?MINS(1)), - - [{watchdog, Dog} | Config2]; + init_v1_agent([{ipfamily, inet} | Config]); otp9884({fin, Config}) when is_list(Config) -> ?DBG("otp9884(fin) -> entry with" "~n Config: ~p", [Config]), - - AgentNode = ?config(agent_node, Config), - ManagerNode = ?config(manager_node, Config), - - %% - - %% Stop agent (this is the nice way to do it, - %% so logs and files can be closed in the proper way). - %% - - AgentSup = ?config(agent_sup, Config), - ?DBG("otp9884(fin) -> stop (stand-alone) agent: ~p", [AgentSup]), - stop_stdalone_agent(AgentSup), - - %% - - %% Stop mnesia - %% - ?DBG("otp9884(fin) -> stop mnesia", []), - mnesia_stop(AgentNode), - - - %% - - %% Stop the agent node - %% - - ?DBG("otp9884(fin) -> stop agent node", []), - stop_node(AgentNode), - - - %% SubAgentNode = ?config(sub_agent_node, Config), - %% stop_node(SubAgentNode), - - - %% - - %% Stop the manager node - %% - - ?DBG("otp9884(fin) -> stop manager node", []), - stop_node(ManagerNode), - - Dog = ?config(watchdog, Config), - ?WD_STOP(Dog), - lists:keydelete(watchdog, 1, Config); + fin_v1_agent(Config); otp9884(doc) -> "OTP-9884 - Simlutaneous backup call should not work. "; @@ -6845,8 +6856,6 @@ otp9884_await_backup_completion(First, Second) end; otp9884_await_backup_completion(First, Second) -> throw({error, {bad_completion, First, Second}}). - - %%----------------------------------------------------------------- agent_log_validation(Node) -> @@ -7143,6 +7152,9 @@ delete_files(Config) -> config(Vsns, MgrDir, AgentDir, MIp, AIp) -> snmp_agent_test_lib:config(Vsns, MgrDir, AgentDir, MIp, AIp). +config(Vsns, MgrDir, AgentDir, MIp, AIp, IpFamily) -> + snmp_agent_test_lib:config(Vsns, MgrDir, AgentDir, MIp, AIp, IpFamily). + update_usm(Vsns, Dir) -> snmp_agent_test_lib:update_usm(Vsns, Dir). @@ -7387,3 +7399,124 @@ p(F, A) -> formated_timestamp() -> snmp_test_lib:formated_timestamp(). + +init_v1_agent(Config) -> + %% -- + %% Start nodes + %% + + {ok, AgentNode} = start_node(agent), + + %% We don't use a manager in this test but the (common) config + %% function takes an argument that is derived from this + {ok, ManagerNode} = start_node(manager), + + %% -- + %% Mnesia init + %% + + AgentDbDir = ?config(agent_db_dir, Config), + AgentMnesiaDir = join([AgentDbDir, "mnesia"]), + mnesia_init(AgentNode, AgentMnesiaDir), + + mnesia_create_schema(AgentNode, [AgentNode]), + + mnesia_start(AgentNode), + + %% -- + %% Host & IP + %% + + AgentHost = ?HOSTNAME(AgentNode), + ManagerHost = ?HOSTNAME(ManagerNode), + + Host = snmp_test_lib:hostname(), + IpFamily = config_ipfamily(Config), + Ip = ?LOCALHOST(IpFamily), + {ok, AgentIP0} = snmp_misc:ip(AgentHost, IpFamily), + AgentIP = tuple_to_list(AgentIP0), + {ok, ManagerIP0} = snmp_misc:ip(ManagerHost, IpFamily), + ManagerIP = tuple_to_list(ManagerIP0), + + + %% -- + %% Write agent config + %% + + Vsns = [v1], + ManagerConfDir = ?config(manager_top_dir, Config), + AgentConfDir = ?config(agent_conf_dir, Config), + AgentTopDir = ?config(agent_top_dir, Config), + AgentBkpDir1 = join([AgentTopDir, backup1]), + AgentBkpDir2 = join([AgentTopDir, backup2]), + ok = file:make_dir(AgentBkpDir1), + ok = file:make_dir(AgentBkpDir2), + AgentBkpDirs = [AgentBkpDir1, AgentBkpDir2], + config(Vsns, ManagerConfDir, AgentConfDir, ManagerIP, AgentIP, IpFamily), + + + %% -- + %% Start the agent + %% + + Config2 = start_agent([{host, Host}, + {ip, Ip}, + {agent_node, AgentNode}, + {agent_host, AgentHost}, + {agent_ip, AgentIP}, + {agent_backup_dirs, AgentBkpDirs}|Config]), + + %% -- + %% Create watchdog + %% + + Dog = ?WD_START(?MINS(1)), + + [{watchdog, Dog} | Config2]. + +fin_v1_agent(Config) -> + AgentNode = ?config(agent_node, Config), + ManagerNode = ?config(manager_node, Config), + + %% - + %% Stop agent (this is the nice way to do it, + %% so logs and files can be closed in the proper way). + %% + + AgentSup = ?config(agent_sup, Config), + stop_stdalone_agent(AgentSup), + + %% - + %% Stop mnesia + %% + mnesia_stop(AgentNode), + + + %% - + %% Stop the agent node + %% + stop_node(AgentNode), + + + %% SubAgentNode = ?config(sub_agent_node, Config), + %% stop_node(SubAgentNode), + + + %% - + %% Stop the manager node + %% + stop_node(ManagerNode), + + Dog = ?config(watchdog, Config), + ?WD_STOP(Dog), + lists:keydelete(watchdog, 1, Config). + + + +config_ipfamily(Config) -> + case ?config(ipfamily, Config) of + undefined -> + inet; + Value -> + Value + end. diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl index d7109253f7..333fe6eb66 100644 --- a/lib/snmp/test/snmp_agent_test_lib.erl +++ b/lib/snmp/test/snmp_agent_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. 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 @@ -39,7 +39,7 @@ get_req/2, get_next_req/1, - config/5, + config/5, config/6, delete_files/1, copy_file/2, update_usm/2, @@ -232,13 +232,14 @@ init_case(Config) when is_list(Config) -> MgrNode = ?config(snmp_mgr, Config), MasterNode = ?config(snmp_master, Config), %% MasterNode = node(), - + IpFamily = proplists:get_value(ipfamily, Config, inet), + SaHost = ?HOSTNAME(SaNode), MgrHost = ?HOSTNAME(MgrNode), MasterHost = ?HOSTNAME(MasterNode), - {ok, MasterIP} = snmp_misc:ip(MasterHost), - {ok, MIP} = snmp_misc:ip(MgrHost), - {ok, SIP} = snmp_misc:ip(SaHost), + {ok, MasterIP} = snmp_misc:ip(MasterHost, IpFamily), + {ok, MIP} = snmp_misc:ip(MgrHost, IpFamily), + {ok, SIP} = snmp_misc:ip(SaHost, IpFamily), put(mgr_node, MgrNode), @@ -250,6 +251,7 @@ init_case(Config) when is_list(Config) -> put(mip, tuple_to_list(MIP)), put(masterip, tuple_to_list(MasterIP)), put(sip, tuple_to_list(SIP)), + put(ipfamily, IpFamily), MibDir = ?config(mib_dir, Config), put(mib_dir, MibDir), @@ -358,6 +360,7 @@ run(Mod, Func, Args, Opts) -> {packet_server_debug,true}, {debug,true}, {agent, get(master_host)}, + {ipfamily, get(ipfamily)}, {agent_udp, 4000}, {trap_udp, 5000}, {recbuf,65535}, @@ -1368,16 +1371,35 @@ stop_node(Node) -> %%%----------------------------------------------------------------- config(Vsns, MgrDir, AgentConfDir, MIp, AIp) -> + config(Vsns, MgrDir, AgentConfDir, MIp, AIp, inet). + +config(Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily) -> ?LOG("config -> entry with" - "~n Vsns: ~p" - "~n MgrDir: ~p" - "~n AgentConfDir: ~p" - "~n MIp: ~p" - "~n AIp: ~p", - [Vsns, MgrDir, AgentConfDir, MIp, AIp]), - ?line snmp_config:write_agent_snmp_files(AgentConfDir, Vsns, - MIp, ?TRAP_UDP, AIp, 4000, - "test"), + "~n Vsns: ~p" + "~n MgrDir: ~p" + "~n AgentConfDir: ~p" + "~n MIp: ~p" + "~n AIp: ~p" + "~n IpFamily: ~p", + [Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily]), + ?line {Domain, ManagerAddr} = + case IpFamily of + inet6 -> + Ipv6Domain = transportDomainUdpIpv6, + AgentIpv6Addr = {AIp, 4000}, + ManagerIpv6Addr = {MIp, ?TRAP_UDP}, + ?line ok = + snmp_config:write_agent_snmp_files( + AgentConfDir, Vsns, + Ipv6Domain, ManagerIpv6Addr, AgentIpv6Addr, "test"), + {Ipv6Domain, ManagerIpv6Addr}; + _ -> + ?line ok = + snmp_config:write_agent_snmp_files( + AgentConfDir, Vsns, MIp, ?TRAP_UDP, AIp, 4000, "test"), + {snmpUDPDomain, {MIp, ?TRAP_UDP}} + end, + ?line case update_usm(Vsns, AgentConfDir) of true -> ?line copy_file(join(AgentConfDir, "usm.conf"), @@ -1388,7 +1410,7 @@ config(Vsns, MgrDir, AgentConfDir, MIp, AIp) -> end, ?line update_community(Vsns, AgentConfDir), ?line update_vacm(Vsns, AgentConfDir), - ?line write_target_addr_conf(AgentConfDir, MIp, ?TRAP_UDP, Vsns), + ?line write_target_addr_conf(AgentConfDir, Domain, ManagerAddr, Vsns), ?line write_target_params_conf(AgentConfDir, Vsns), ?line write_notify_conf(AgentConfDir), ok. @@ -1486,7 +1508,7 @@ rewrite_usm_mgr(Dir, ShaKey, DesKey) -> {"mgrEngine", "newUser", "newUser", zeroDotZero, usmHMACSHAAuthProtocol, "", "", usmDESPrivProtocol, "", "", "", ShaKey, DesKey}], - ok = snmp_config:write_agent_usm_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_usm_config(Dir, "", Conf). reset_usm_mgr(Dir) -> ?line ok = file:rename(join(Dir,"usm.old"), @@ -1512,13 +1534,15 @@ update_vacm(_Vsn, Dir) -> write_community_conf(Dir, Conf) -> - snmp_config:write_agent_community_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_community_config(Dir, "", Conf). write_target_addr_conf(Dir, Conf) -> - snmp_config:write_agent_target_addr_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_target_addr_config(Dir, "", Conf). -write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> - snmp_config:write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP, Vsns). +write_target_addr_conf(Dir, Ip_or_Domain, Port_or_Addr, Vsns) -> + ?line ok = + snmp_config:write_agent_snmp_target_addr_conf( + Dir, Ip_or_Domain, Port_or_Addr, Vsns). rewrite_target_addr_conf(Dir, NewPort) -> ?DBG("rewrite_target_addr_conf -> entry with" @@ -1534,8 +1558,7 @@ rewrite_target_addr_conf(Dir, NewPort) -> end, ?line [TrapAddr|Addrs] = - snmp_conf:read(TAFile, - fun(R) -> rewrite_target_addr_conf_check(R) end), + snmp_conf:read(TAFile, fun rewrite_target_addr_conf_check/1), ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]), @@ -1571,14 +1594,14 @@ write_target_params_conf(Dir, Vsns) -> (v3) -> {"target_v3", v3, usm, "all-rights", noAuthNoPriv} end, Conf = [F(Vsn) || Vsn <- Vsns], - snmp_config:write_agent_target_params_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_target_params_config(Dir, "", Conf). rewrite_target_params_conf(Dir, SecName, SecLevel) when is_list(SecName) andalso is_atom(SecLevel) -> ?line ok = file:rename(join(Dir,"target_params.conf"), join(Dir,"target_params.old")), Conf = [{"target_v3", v3, usm, SecName, SecLevel}], - snmp_config:write_agent_target_params_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_target_params_config(Dir, "", Conf). reset_target_params_conf(Dir) -> ?line ok = file:rename(join(Dir,"target_params.old"), @@ -1587,12 +1610,12 @@ reset_target_params_conf(Dir) -> write_notify_conf(Dir) -> Conf = [{"standard trap", "std_trap", trap}, {"standard inform", "std_inform", inform}], - snmp_config:write_agent_notify_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_notify_config(Dir, "", Conf). write_view_conf(Dir) -> Conf = [{2, [1,3,6], included, null}, {2, ?tDescr_instance, excluded, null}], - snmp_config:write_agent_view_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_view_config(Dir, "", Conf). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/snmp/test/snmp_conf_test.erl b/lib/snmp/test/snmp_conf_test.erl index c4341d8d7e..7f5d11c0e7 100644 --- a/lib/snmp/test/snmp_conf_test.erl +++ b/lib/snmp/test/snmp_conf_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2014. 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 @@ -373,6 +373,8 @@ verify_ip(Val) -> case (catch snmp_conf:check_ip(Val)) of {error, Reason} -> ?FAIL({verify_ip, Val, Reason}); + {ok, _} -> + ok; ok -> ok end. @@ -401,7 +403,7 @@ check_taddress(Config) when is_list(Config) -> ok. verify_taddress(Val) -> - case (catch snmp_conf:check_taddress(Val)) of + case (catch snmp_conf:check_taddress(snmpUDPDomain, Val)) of {error, Reason} -> ?FAIL({verify_taddress, Val, Reason}); ok -> @@ -409,7 +411,7 @@ verify_taddress(Val) -> end. verify_not_taddress(Val) -> - case (catch snmp_conf:check_taddress(Val)) of + case (catch snmp_conf:check_taddress(snmpUDPDomain, Val)) of ok -> ?FAIL({verify_taddress, Val}); {error, _Reason} -> diff --git a/lib/snmp/test/snmp_manager_config_test.erl b/lib/snmp/test/snmp_manager_config_test.erl index 7b9924b83c..2f5c68d14d 100644 --- a/lib/snmp/test/snmp_manager_config_test.erl +++ b/lib/snmp/test/snmp_manager_config_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -693,7 +693,7 @@ start_with_invalid_manager_conf_file1(Conf) when is_list(Conf) -> "arne_anka", "4001", "500", "\"bmkEngine\""), ?line {error, Reason12} = config_start(Opts), p("start failed (as expected): ~p", [Reason12]), - ?line {failed_check, _, _, 2, {invalid_ip_address, _}} = Reason12, + ?line {failed_check, _, _, 2, {bad_address, _}} = Reason12, await_config_not_running(), %% -- @@ -702,7 +702,7 @@ start_with_invalid_manager_conf_file1(Conf) when is_list(Conf) -> "9999", "4001", "500", "\"bmkEngine\""), ?line {error, Reason13} = config_start(Opts), p("start failed (as expected): ~p", [Reason13]), - ?line {failed_check, _, _, 2, {invalid_ip_address, _}} = Reason13, + ?line {failed_check, _, _, 2, {bad_address, _}} = Reason13, await_config_not_running(), %% -- @@ -720,7 +720,8 @@ start_with_invalid_manager_conf_file1(Conf) when is_list(Conf) -> "[134,138,177,189]", "-1", "500", "\"bmkEngine\""), ?line {error, Reason22} = config_start(Opts), p("start failed (as expected): ~p", [Reason22]), - ?line {failed_check, _, _, 3, {invalid_integer, _}} = Reason22, + io:format("Reason22: ~p~n", [Reason22]), + ?line {failed_check, _, _, 3, {bad_port, _}} = Reason22, await_config_not_running(), %% -- @@ -729,7 +730,7 @@ start_with_invalid_manager_conf_file1(Conf) when is_list(Conf) -> "[134,138,177,189]", "\"kalle-anka\"", "500", "\"bmkEngine\""), ?line {error, Reason23} = config_start(Opts), p("start failed (as expected): ~p", [Reason23]), - ?line {failed_check, _, _, 3, {invalid_integer, _}} = Reason23, + ?line {failed_check, _, _, 3, {bad_port, _}} = Reason23, await_config_not_running(), %% -- @@ -1073,7 +1074,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> case config_start(Opts) of {error, Reason53} -> p("start failed (as expected): ~p", [Reason53]), - ?line {failed_check, _, _, _, {invalid_ip_address, _}} = Reason53, + ?line {failed_check, _, _, _, {bad_address, _}} = Reason53, await_config_not_running(); OK_53 -> exit({error, {unexpected_success, "53", OK_53}}) @@ -1086,7 +1087,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> case config_start(Opts) of {error, Reason54} -> p("start failed (as expected): ~p", [Reason54]), - ?line {failed_check, _, _, _, {invalid_ip_address, _}} = Reason54, + ?line {failed_check, _, _, _, {bad_address, _}} = Reason54, await_config_not_running(); OK_54 -> exit({error, {unexpected_success, "54", OK_54}}) @@ -1098,7 +1099,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> write_agents_conf(ConfDir, [Agent55]), ?line {error, Reason55} = config_start(Opts), p("start failed (as expected): ~p", [Reason55]), - ?line {failed_check, _, _, _, {invalid_ip_address, _}} = Reason55, + ?line {failed_check, _, _, _, {bad_address, _}} = Reason55, await_config_not_running(), %% -- @@ -1107,7 +1108,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> write_agents_conf(ConfDir, [Agent61]), ?line {error, Reason61} = config_start(Opts), p("start failed (as expected): ~p", [Reason61]), - ?line {failed_check, _, _, _, {invalid_integer, _}} = Reason61, + ?line {failed_check, _, _, _, {bad_address, _}} = Reason61, await_config_not_running(), %% -- @@ -1116,7 +1117,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> write_agents_conf(ConfDir, [Agent62]), ?line {error, Reason62} = config_start(Opts), p("start failed (as expected): ~p", [Reason62]), - ?line {failed_check, _, _, _, {invalid_integer, _}} = Reason62, + ?line {failed_check, _, _, _, {bad_address, _}} = Reason62, await_config_not_running(), %% -- @@ -1125,7 +1126,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> write_agents_conf(ConfDir, [Agent63]), ?line {error, Reason63} = config_start(Opts), p("start failed (as expected): ~p", [Reason63]), - ?line {failed_check, _, _, _, {invalid_integer, _}} = Reason63, + ?line {failed_check, _, _, _, {bad_address, _}} = Reason63, await_config_not_running(), %% -- diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl index 3a654a2805..78352e59cf 100644 --- a/lib/snmp/test/snmp_manager_test.erl +++ b/lib/snmp/test/snmp_manager_test.erl @@ -241,8 +241,11 @@ init_per_testcase2(Case, Config) -> AgLogDir = filename:join(AgTopDir, "log/"), ?line ok = file:make_dir(AgLogDir), + Family = proplists:get_value(ipfamily, Config, inet), + Conf = [{watchdog, ?WD_START(?MINS(5))}, - {ip, ?LOCALHOST()}, + {ipfamily, Family}, + {ip, ?LOCALHOST(Family)}, {case_top_dir, CaseTopDir}, {agent_dir, AgTopDir}, {agent_conf_dir, AgConfDir}, @@ -410,7 +413,9 @@ all() -> {group, event_tests}, {group, event_tests_mt}, discovery, - {group, tickets} + {group, tickets}, + {group, ipv6}, + {group, ipv6_mt} ]. groups() -> @@ -545,9 +550,29 @@ groups() -> [ otp8395_1 ] - } + }, + {ipv6, [], ipv6_tests()}, + {ipv6_mt, [], ipv6_tests()} + + ]. + +ipv6_tests() -> + [ + register_agent1, + simple_sync_get_next3, + simple_async_get2, + simple_sync_get3, + simple_async_get_next2, + simple_sync_set3, + simple_async_set2, + simple_sync_get_bulk2, + simple_async_get_bulk3, + misc_async2, + inform1, + inform_swarm ]. + init_per_group(request_tests_mt = GroupName, Config) -> snmp_test_lib:init_group_top_dir( GroupName, @@ -556,10 +581,26 @@ init_per_group(event_tests_mt = GroupName, Config) -> snmp_test_lib:init_group_top_dir( GroupName, [{manager_net_if_module, snmpm_net_if_mt} | Config]); +init_per_group(ipv6_mt = GroupName, Config) -> + case ct:require(ipv6_hosts) of + ok -> + ipv6_init( + snmp_test_lib:init_group_top_dir( + GroupName, + [{manager_net_if_module, snmpm_net_if_mt} | Config])); + _ -> + {skip, "Host does not support IPV6"} + end; +init_per_group(ipv6 = GroupName, Config) -> + case ct:require(ipv6_hosts) of + ok -> + ipv6_init(snmp_test_lib:init_group_top_dir(GroupName, Config)); + _ -> + {skip, "Host does not support IPV6"} + end; init_per_group(GroupName, Config) -> snmp_test_lib:init_group_top_dir(GroupName, Config). - - + end_per_group(_GroupName, Config) -> %% Do we really need to do this? lists:keydelete(snmp_group_top_dir, 1, Config). @@ -1508,7 +1549,7 @@ register_agent3(Config) when is_list(Config) -> TargetName2 = "agent3", ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName2, [{tdomain, transportDomainUdpIpv6}, - {address, LocalHost}, + {address, {0,0,0,0,0,0,0,1}}, {port, 5002}, {engine_id, "agentEngineId-2"}]), TargetName3 = "agent4", @@ -5074,7 +5115,7 @@ inform_swarm_collector(N) -> inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, _) when ((N == SentAckCnt) and (N == RespCnt) and - (N >= RecvCnt)) -> + (N =< RecvCnt)) -> p("inform_swarm_collector -> done when" "~n N: ~w" "~n SentAckCnt: ~w" @@ -5750,12 +5791,24 @@ fin_mgr_user(Conf) -> init_mgr_user_data1(Conf) -> Node = ?config(manager_node, Conf), TargetName = ?config(manager_agent_target_name, Conf), - Addr = ?config(ip, Conf), + IpFamily = ?config(ipfamily, Conf), + Ip = ?config(ip, Conf), Port = ?AGENT_PORT, - ?line ok = mgr_user_register_agent(Node, TargetName, - [{address, Addr}, - {port, Port}, - {engine_id, "agentEngine"}]), + ?line ok = + case IpFamily of + inet -> + mgr_user_register_agent( + Node, TargetName, + [{address, Ip}, + {port, Port}, + {engine_id, "agentEngine"}]); + inet6 -> + mgr_user_register_agent( + Node, TargetName, + [{tdomain, transportDomainUdpIpv6}, + {taddress, {Ip, Port}}, + {engine_id, "agentEngine"}]) + end, _Agents = mgr_user_which_own_agents(Node), ?DBG("Own agents: ~p", [_Agents]), @@ -5780,12 +5833,24 @@ init_mgr_user_data2(Conf) -> "~n Conf: ~p", [Conf]), Node = ?config(manager_node, Conf), TargetName = ?config(manager_agent_target_name, Conf), - Addr = ?config(ip, Conf), + IpFamily = ?config(ipfamily, Conf), + Ip = ?config(ip, Conf), Port = ?AGENT_PORT, - ?line ok = mgr_user_register_agent(Node, TargetName, - [{address, Addr}, - {port, Port}, - {engine_id, "agentEngine"}]), + ?line ok = + case IpFamily of + inet -> + mgr_user_register_agent( + Node, TargetName, + [{address, Ip}, + {port, Port}, + {engine_id, "agentEngine"}]); + inet6 -> + mgr_user_register_agent( + Node, TargetName, + [{tdomain, transportDomainUdpIpv6}, + {taddress, {Ip, Port}}, + {engine_id, "agentEngine"}]) + end, _Agents = mgr_user_which_own_agents(Node), ?DBG("Own agents: ~p", [_Agents]), @@ -6182,10 +6247,16 @@ await_stopped(Node, N) -> write_manager_config(Config) -> Dir = ?config(manager_conf_dir, Config), - Ip = ?config(ip, Config), - Addr = tuple_to_list(Ip), - snmp_config:write_manager_snmp_files(Dir, Addr, ?MGR_PORT, - ?MGR_MMS, ?MGR_ENGINE_ID, [], [], []). + Ip = tuple_to_list(?config(ip, Config)), + {Addr, Port} = + case ?config(ipfamily, Config) of + inet -> + {Ip, ?MGR_PORT}; + inet6 -> + {transportDomainUdpIpv6, {Ip, ?MGR_PORT}} + end, + snmp_config:write_manager_snmp_files( + Dir, Addr, Port, ?MGR_MMS, ?MGR_ENGINE_ID, [], [], []). write_manager_conf(Dir) -> Port = "5000", @@ -6214,25 +6285,27 @@ write_manager_conf(Dir, Str) -> write_agent_config(Vsns, Conf) -> Dir = ?config(agent_conf_dir, Conf), - Ip = ?config(ip, Conf), - ?line Addr = tuple_to_list(Ip), - ?line ok = write_agent_config_files(Dir, Vsns, Addr), + ?line Ip = tuple_to_list(?config(ip, Conf)), + ?line Domain = + case ?config(ipfamily, Conf) of + inet -> + snmpUDPDomain; + inet6 -> + transportDomainUdpIpv6 + end, + ?line ok = write_agent_config_files(Dir, Vsns, Domain, Ip), ?line ok = update_agent_usm(Vsns, Dir), ?line ok = update_agent_community(Vsns, Dir), ?line ok = update_agent_vacm(Vsns, Dir), - ?line ok = write_agent_target_addr_conf(Dir, Addr, Vsns), + ?line ok = write_agent_target_addr_conf(Dir, Domain, Ip, Vsns), ?line ok = write_agent_target_params_conf(Dir, Vsns), ?line ok = write_agent_notify_conf(Dir), ok. -write_agent_config_files(Dir, Vsns, Addr) -> - snmp_config:write_agent_snmp_files(Dir, Vsns, - Addr, ?MGR_PORT, - Addr, ?AGENT_PORT, - "mgr-test", "trap", - none, "", - ?AGENT_ENGINE_ID, - ?AGENT_MMS). +write_agent_config_files(Dir, Vsns, Domain, Ip) -> + snmp_config:write_agent_snmp_files( + Dir, Vsns, Domain, {Ip, ?MGR_PORT}, {Ip, ?AGENT_PORT}, "mgr-test", + trap, none, "", ?AGENT_ENGINE_ID, ?AGENT_MMS). update_agent_usm(Vsns, Dir) -> case lists:member(v3, Vsns) of @@ -6300,9 +6373,9 @@ update_agent_vacm(_Vsns, Dir) -> excluded, null}], snmp_config:update_agent_vacm_config(Dir, Conf). -write_agent_target_addr_conf(Dir, Addr, Vsns) -> - snmp_config:write_agent_snmp_target_addr_conf(Dir, Addr, ?MGR_PORT, - 300, 3, Vsns). +write_agent_target_addr_conf(Dir, Domain, Ip, Vsns) -> + snmp_config:write_agent_snmp_target_addr_conf( + Dir, Domain, {Ip, ?MGR_PORT}, 300, 3, Vsns). write_agent_target_params_conf(Dir, Vsns) -> F = fun(v1) -> {"target_v1", v1, v1, "all-rights", noAuthNoPriv}; @@ -6426,3 +6499,5 @@ formated_timestamp() -> %% p(TName, F, A) -> %% io:format("~w -> " ++ F ++ "~n", [TName|A]). +ipv6_init(Config) when is_list(Config) -> + [{ipfamily, inet6} | Config]. diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl index fbb891e40d..5e611340a3 100644 --- a/lib/snmp/test/snmp_test_lib.erl +++ b/lib/snmp/test/snmp_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2013. All Rights Reserved. +%% Copyright Ericsson AB 2002-2014. 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 @@ -22,7 +22,7 @@ -include_lib("kernel/include/file.hrl"). --export([hostname/0, hostname/1, localhost/0, os_type/0, sz/1, +-export([hostname/0, hostname/1, localhost/0, localhost/1, os_type/0, sz/1, display_suite_info/1]). -export([non_pc_tc_maybe_skip/4, os_based_skip/1]). -export([fix_data_dir/1, @@ -60,6 +60,9 @@ from(_H, []) -> []. localhost() -> {ok, Ip} = snmp_misc:ip(net_adm:localhost()), Ip. +localhost(Family) -> + {ok, Ip} = snmp_misc:ip(net_adm:localhost(), Family), + Ip. sz(L) when is_list(L) -> length(L); diff --git a/lib/snmp/test/snmp_test_lib.hrl b/lib/snmp/test/snmp_test_lib.hrl index 8cc3f75dc5..9b7609b831 100644 --- a/lib/snmp/test/snmp_test_lib.hrl +++ b/lib/snmp/test/snmp_test_lib.hrl @@ -1,5 +1,5 @@ %%<copyright> -%% <year>2002-2008</year> +%% <year>2002-2014</year> %% <holder>Ericsson AB, All Rights Reserved</holder> %%</copyright> %%<legalnotice> @@ -32,14 +32,15 @@ -define(APPLICATION, snmp). -endif. --define(SCONF(K,D,C), snmp_test_lib:set_config(K,D,C)). --define(GCONF(K,C), snmp_test_lib:get_config(K,C)). --define(RCONF(K,C,V), snmp_test_lib:replace_config(K,C,V)). --define(HOSTNAME(N), snmp_test_lib:hostname(N)). --define(LOCALHOST(), snmp_test_lib:localhost()). --define(SZ(X), snmp_test_lib:sz(X)). --define(OSTYPE(), snmp_test_lib:os_type()). --define(DISPLAY_SUITE_INFO(), snmp_test_lib:display_suite_info(?MODULE)). +-define(SCONF(K,D,C), snmp_test_lib:set_config(K,D,C)). +-define(GCONF(K,C), snmp_test_lib:get_config(K,C)). +-define(RCONF(K,C,V), snmp_test_lib:replace_config(K,C,V)). +-define(HOSTNAME(N), snmp_test_lib:hostname(N)). +-define(LOCALHOST(), snmp_test_lib:localhost()). +-define(LOCALHOST(Family), snmp_test_lib:localhost(Family)). +-define(SZ(X), snmp_test_lib:sz(X)). +-define(OSTYPE(), snmp_test_lib:os_type()). +-define(DISPLAY_SUITE_INFO(), snmp_test_lib:display_suite_info(?MODULE)). %% - Test case macros - diff --git a/lib/snmp/test/snmp_test_manager.erl b/lib/snmp/test/snmp_test_manager.erl index 925ae77ab5..6d8673eecd 100644 --- a/lib/snmp/test/snmp_test_manager.erl +++ b/lib/snmp/test/snmp_test_manager.erl @@ -56,7 +56,7 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]). --record(state, {mgr, parent, req, agent_target_name}). +-record(state, {parent, req, agent_target_name}). -define(SERVER, ?MODULE). -define(USER, ?MODULE). @@ -130,10 +130,10 @@ init([Parent, Opts]) -> do_init(Opts) -> {MgrDir, MgrConf, MgrOpts, AgentTargetName, AgentConf} = parse_opts(Opts), ok = snmp_config:write_manager_config(MgrDir, "", MgrConf), - {ok, Pid} = snmpm:start_link(MgrOpts), + ok = snmpm:start_link(MgrOpts), ok = snmpm:register_user(?USER, ?MODULE, self()), ok = snmpm:register_agent(?USER, AgentTargetName, AgentConf), - {ok, #state{mgr = Pid, agent_target_name = AgentTargetName}}. + {ok, #state{agent_target_name = AgentTargetName}}. parse_opts(Opts) -> diff --git a/lib/snmp/test/snmp_test_mgr.erl b/lib/snmp/test/snmp_test_mgr.erl index d4eb00ff91..cf62edba1c 100644 --- a/lib/snmp/test/snmp_test_mgr.erl +++ b/lib/snmp/test/snmp_test_mgr.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -235,21 +235,23 @@ init({Options, CallerPid}) -> VsnHdrD = {Com, User, EngineId, CtxEngineId, mk_seclevel(SecLevel)}, io:format("[~w] ~p -> VsnHdrD: ~p~n", [?MODULE, self(), VsnHdrD]), + IpFamily = get_value(ipfamily, Options, inet), + io:format("[~w] ~p -> IpFamily: ~p~n", [?MODULE, self(), IpFamily]), AgIp = case snmp_misc:assq(agent, Options) of {value, Tuple4} when is_tuple(Tuple4) andalso (size(Tuple4) =:= 4) -> Tuple4; {value, Host} when is_list(Host) -> - {ok, Ip} = snmp_misc:ip(Host), + {ok, Ip} = snmp_misc:ip(Host, IpFamily), Ip end, io:format("[~w] ~p -> AgIp: ~p~n", [?MODULE, self(), AgIp]), Quiet = lists:member(quiet, Options), io:format("[~w] ~p -> Quiet: ~p~n", [?MODULE, self(), Quiet]), - PackServ = start_packet_server(Quiet, Options, CallerPid, - AgIp, Udp, TrapUdp, - VsnHdrD, Version, Dir, RecBufSz, - PacksDbg), + PackServ = + start_packet_server( + Quiet, Options, CallerPid, AgIp, Udp, TrapUdp, + VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily), d("init -> packet server: ~p",[PackServ]), State = #state{parent = CallerPid, quiet = Quiet, @@ -263,23 +265,21 @@ init({Options, CallerPid}) -> end. start_packet_server(false, _Options, _CallerPid, AgIp, Udp, TrapUdp, - VsnHdrD, Version, Dir, RecBufSz, PacksDbg) -> + VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily) -> d("start_packet_server -> entry", []), - ?PACK_SERV:start_link_packet({msg, self()}, - AgIp, Udp, TrapUdp, - VsnHdrD, Version, Dir, RecBufSz, - PacksDbg); + ?PACK_SERV:start_link_packet( + {msg, self()}, AgIp, Udp, TrapUdp, + VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily); start_packet_server(true, Options, CallerPid, AgIp, Udp, TrapUdp, - VsnHdrD, Version, Dir, RecBufSz, PacksDbg) -> + VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily) -> Type = get_value(receive_type, Options, pdu), d("start_packet_server -> entry with" "~n CallerPid: ~p" "~n when" "~n Type: ~p",[CallerPid, Type]), - ?PACK_SERV:start_link_packet({Type, CallerPid}, - AgIp, Udp, TrapUdp, - VsnHdrD, Version, Dir, RecBufSz, - PacksDbg). + ?PACK_SERV:start_link_packet( + {Type, CallerPid}, AgIp, Udp, TrapUdp, + VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily). is_options_ok([{mibs,List}|Opts]) when is_list(List) -> is_options_ok(Opts); @@ -287,6 +287,10 @@ is_options_ok([quiet|Opts]) -> is_options_ok(Opts); is_options_ok([{agent,_}|Opts]) -> is_options_ok(Opts); +is_options_ok([{ipfamily,IpFamily}|Opts]) + when IpFamily =:= inet; + IpFamily =:= inet6 -> + is_options_ok(Opts); is_options_ok([{agent_udp,Int}|Opts]) when is_integer(Int) -> is_options_ok(Opts); is_options_ok([{trap_udp,Int}|Opts]) when is_integer(Int) -> diff --git a/lib/snmp/test/snmp_test_mgr_misc.erl b/lib/snmp/test/snmp_test_mgr_misc.erl index 5525c5c3ec..5274dcacd9 100644 --- a/lib/snmp/test/snmp_test_mgr_misc.erl +++ b/lib/snmp/test/snmp_test_mgr_misc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -23,7 +23,7 @@ -module(snmp_test_mgr_misc). %% API --export([start_link_packet/8, start_link_packet/9, +-export([start_link_packet/8, start_link_packet/9, start_link_packet/10, stop/1, send_discovery_pdu/2, send_pdu/2, send_msg/4, send_bytes/2, @@ -31,7 +31,7 @@ get_pdu/1, set_pdu/2, format_hdr/1]). %% internal exports --export([init_packet/10]). +-export([init_packet/11]). -compile({no_auto_import, [error/2]}). @@ -42,22 +42,26 @@ %%---------------------------------------------------------------------- %% The InHandler process will receive messages on the form {snmp_pdu, Pdu}. %%---------------------------------------------------------------------- -start_link_packet(InHandler, - AgentIp, UdpPort, TrapUdp, - VsnHdr, Version, Dir, BufSz) -> - start_link_packet(InHandler, - AgentIp, UdpPort, TrapUdp, - VsnHdr, Version, Dir, BufSz, - false). - -start_link_packet(InHandler, - AgentIp, UdpPort, TrapUdp, - VsnHdr, Version, Dir, BufSz, - Dbg) when is_integer(UdpPort) -> - Args = [self(), InHandler, - AgentIp, UdpPort, TrapUdp, - VsnHdr, Version, Dir, BufSz, - Dbg], +start_link_packet( + InHandler, AgentIp, UdpPort, TrapUdp, VsnHdr, Version, Dir, BufSz) -> + start_link_packet( + InHandler, AgentIp, UdpPort, TrapUdp, VsnHdr, Version, Dir, BufSz, + false). + +start_link_packet( + InHandler, AgentIp, UdpPort, TrapUdp, VsnHdr, Version, Dir, BufSz, + Dbg) -> + start_link_packet( + InHandler, AgentIp, UdpPort, TrapUdp, VsnHdr, Version, Dir, BufSz, + Dbg, inet). + +start_link_packet( + InHandler, AgentIp, UdpPort, TrapUdp, VsnHdr, Version, Dir, BufSz, + Dbg, IpFamily) when is_integer(UdpPort) -> + Args = + [self(), + InHandler, AgentIp, UdpPort, TrapUdp, VsnHdr, Version, Dir, BufSz, + Dbg, IpFamily], proc_lib:start_link(?MODULE, init_packet, Args). stop(Pid) -> @@ -90,12 +94,14 @@ send_bytes(Bytes, PacketPid) -> %%-------------------------------------------------- %% The SNMP encode/decode process %%-------------------------------------------------- -init_packet(Parent, SnmpMgr, - AgentIp, UdpPort, TrapUdp, - VsnHdr, Version, Dir, BufSz, DbgOptions) -> +init_packet( + Parent, + SnmpMgr, AgentIp, UdpPort, TrapUdp, VsnHdr, Version, Dir, BufSz, + DbgOptions, IpFamily) -> put(sname, mgr_misc), init_debug(DbgOptions), - {ok, UdpId} = gen_udp:open(TrapUdp, [{recbuf,BufSz},{reuseaddr, true}]), + {ok, UdpId} = + gen_udp:open(TrapUdp, [{recbuf,BufSz}, {reuseaddr, true}, IpFamily]), put(msg_id, 1), proc_lib:init_ack(Parent, self()), init_usm(Version, Dir), diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl new file mode 100644 index 0000000000..6e9c57bce9 --- /dev/null +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl @@ -0,0 +1,433 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014-2014. 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% +%% +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test suite uses the following external programs: +%% snmpget From packet 'snmp' (in Ubuntu 12.04) +%% snmptrapd From packet 'snmpd' (in Ubuntu 12.04) +%% They originate from the Net-SNMP applications, see: +%% http://net-snmp.sourceforge.net/ + + +-module(snmp_to_snmpnet_SUITE). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("snmp/include/STANDARD-MIB.hrl"). + +-define(AGENT_ENGINE_ID, "ErlangSnmpAgent"). +-define(AGENT_PORT, 4000). +-define(MANAGER_PORT, 8989). +-define(DEFAULT_MAX_MESSAGE_SIZE, 484). + +expected(?sysDescr_instance = Oid, get) -> + OidStr = oid_str(Oid), + iolist_to_binary([OidStr | " = STRING: \"Erlang SNMP agent\""]). + +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [ + {group, ipv4}, + {group, ipv6}, + {group, ipv4_ipv6} + ]. + +groups() -> + [{ipv4, [], + [{group, get}, + {group, inform} + ]}, + {ipv6, [], + [{group, get}, + {group, inform} + ]}, + {ipv4_ipv6, [], + [{group, get}, + {group, inform} + ]}, + %% + {get, [], + [erlang_agent_netsnmp_get]}, + {inform, [], + [erlang_agent_netsnmp_inform]} + ]. + +init_per_suite(Config) -> + [{agent_port, ?AGENT_PORT}, {manager_port, ?MANAGER_PORT} | Config]. + +end_per_suite(_Config) -> + ok. + +init_per_group(ipv4, Config) -> + init_per_group_ip([inet], Config); +init_per_group(ipv6, Config) -> + init_per_group_ipv6([inet6], Config); +init_per_group(ipv4_ipv6, Config) -> + init_per_group_ipv6([inet, inet6], Config); +%% +init_per_group(get, Config) -> + %% From Ubuntu package snmp + find_executable(snmpget, Config); +init_per_group(inform, Config) -> + %% From Ubuntu package snmpd + find_executable(snmptrapd, Config); +%% +init_per_group(_, Config) -> + Config. + +init_per_group_ipv6(Families, Config) -> + case ct:require(ipv6_hosts) of + ok -> + init_per_group_ip(Families, Config); + _ -> + {skip, "Host does not support IPV6"} + end. + +init_per_group_ip(Families, Config) -> + Dir = ?config(priv_dir, Config), + AgentPort = ?config(agent_port, Config), + ManagerPort = ?config(manager_port, Config), + Versions = [v2], + {ok, Host} = inet:gethostname(), + Transports = + [begin + {ok, Addr} = inet:getaddr(Host, Family), + {domain(Family), {Addr, AgentPort}} + end || Family <- Families], + Targets = + [begin + {ok, Addr} = inet:getaddr(Host, Family), + {domain(Family), {Addr, ManagerPort}} + end || Family <- Families], + agent_config(Dir, Transports, Targets, Versions), + [{port, ?AGENT_PORT}, {snmp_versions, Versions}, + {transports, Transports}, {targets, Targets} + | Config]. + + + +end_per_group(_GroupName, Config) -> + Config. + +init_per_testcase(_Case, Config) -> + Dog = ct:timetrap(10000), + application:stop(snmp), + application:unload(snmp), + [{watchdog, Dog} | Config]. + +end_per_testcase(_, Config) -> + case application:stop(snmp) of + ok -> + ok; + E1 -> + ct:pal("application:stop(snmp) -> ~p", [E1]) + end, + case application:unload(snmp) of + ok -> + ok; + E2 -> + ct:pal("application:unload(snmp) -> ~p", [E2]) + end, + Config. + +find_executable(Exec, Config) -> + ExecStr = atom_to_list(Exec), + case os:find_executable(ExecStr) of + false -> + %% The sbin dirs are not in the PATH on all platforms... + find_sys_executable( + Exec, ExecStr, + [["usr", "local", "sbin"], + ["usr", "sbin"], + ["sbin"]], + Config); + Path -> + [{Exec, Path} | Config] + end. + +find_sys_executable(_Exec, ExecStr, [], _Config) -> + {skip, ExecStr ++ " not found"}; +find_sys_executable(Exec, ExecStr, [Dir | Dirs], Config) -> + case os:find_executable(filename:join(["/" | Dir] ++ [ExecStr])) of + false -> + find_sys_executable(Exec, ExecStr, Dirs, Config); + Path -> + [{Exec, Path} | Config] + end. + +start_agent(Config) -> + ok = application:load(snmp), + ok = application:set_env(snmp, agent, app_env(Config)), + ok = application:start(snmp). + +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- +erlang_agent_netsnmp_get() -> + [{doc,"Test that we can access erlang snmp agent " + "from snmpnet manager"}]. + +erlang_agent_netsnmp_get(Config) when is_list(Config) -> + Transports = ?config(transports, Config), + start_agent(Config), + Oid = ?sysDescr_instance, + Expected = expected(Oid, get), + [Expected = snmpget(Oid, Transport, Config) + || Transport <- Transports], + ok. + +%%-------------------------------------------------------------------- +erlang_agent_netsnmp_inform(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Mib = "TestTrapv2", + + start_agent(Config), + ok = snmpa:load_mib(snmp_master_agent, filename:join(DataDir, Mib)), + + ProgHandle = start_snmptrapd(Mib, Config), + + snmpa:send_notification( + snmp_master_agent, testTrapv22, {erlang_agent_test, self()}), + + receive + {snmp_targets, erlang_agent_test, Addresses} -> + ct:pal("Notification sent to: ~p~n", [Addresses]), + erlang_agent_netsnmp_inform_responses(Addresses) + end, + stop_program(ProgHandle). + +erlang_agent_netsnmp_inform_responses([]) -> + receive + {snmp_notification, erlang_agent_test, _} = Unexpected -> + ct:pal("Unexpected response: ~p", [Unexpected]), + erlang_agent_netsnmp_inform_responses([]) + after 0 -> + ok + end; +erlang_agent_netsnmp_inform_responses([Address | Addresses]) -> + receive + {snmp_notification, erlang_agent_test, + {got_response, Address}} -> + ct:pal("Got response from: ~p~n", [Address]), + erlang_agent_netsnmp_inform_responses(Addresses); + {snmp_notification, erlang_agent_test, + {no_response, _} = NoResponse} -> + ct:fail(NoResponse) + end. + +%%-------------------------------------------------------------------- +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- +snmpget(Oid, Transport, Config) -> + Versions = ?config(snmp_versions, Config), + + Args = + ["-c", "public", net_snmp_version(Versions), + "-m", "", + "-Cf", + net_snmp_addr_str(Transport), + oid_str(Oid)], + ProgHandle = start_program(snmpget, Args, none, Config), + {_, line, Line} = get_program_output(ProgHandle), + stop_program(ProgHandle), + Line. + +start_snmptrapd(Mibs, Config) -> + DataDir = ?config(data_dir, Config), + MibDir = filename:join(code:lib_dir(snmp), "mibs"), + Targets = ?config(targets, Config), + SnmptrapdArgs = + ["-f", "-Lo", "-C", + "-m", Mibs, + "-M", MibDir++":"++DataDir, + "--disableAuthorization=yes", + "--snmpTrapdAddr=" ++ net_snmp_addr_str(Targets)], + {ok, StartCheckMP} = re:compile("NET-SNMP version ", [anchored]), + start_program(snmptrapd, SnmptrapdArgs, StartCheckMP, Config). + +start_program(Prog, Args, StartCheckMP, Config) -> + Path = ?config(Prog, Config), + DataDir = ?config(data_dir, Config), + StartWrapper = filename:join(DataDir, "start_stop_wrapper"), + Parent = self(), + Pid = + spawn_link( + fun () -> + run_program(Parent, StartWrapper, [Path | Args]) + end), + start_check(Pid, erlang:monitor(process, Pid), StartCheckMP). + +start_check(Pid, Mon, none) -> + {Pid, Mon}; +start_check(Pid, Mon, StartCheckMP) -> + receive + {Pid, line, Line} -> + case re:run(Line, StartCheckMP, [{capture, none}]) of + match -> + {Pid, Mon}; + nomatch -> + start_check(Pid, Mon, StartCheckMP) + end; + {'DOWN', Mon, _, _, Reason} -> + ct:fail("Prog ~p start failed: ~p", [Pid, Reason]) + end. + +get_program_output({Pid, Mon}) -> + receive + {Pid, _, _} = Msg -> + Msg; + {'DOWN', Mon, _, _, Reason} -> + ct:fail("Prog ~p crashed: ~p", [Pid, Reason]) + end. + +stop_program({Pid, _} = Handle) -> + Pid ! {self(), stop}, + wait_program_stop(Handle). + +wait_program_stop({Pid, Mon}) -> + receive + {Pid, exit, ExitStatus} -> + receive + {'DOWN', Mon, _, _, _} -> + ExitStatus + end; + {'DOWN', Mon, _, _, Reason} -> + ct:fail("Prog stop: ~p", [Reason]) + end. + +run_program(Parent, StartWrapper, ProgAndArgs) -> + Port = + open_port( + {spawn_executable, StartWrapper}, + [{args, ProgAndArgs}, binary, stderr_to_stdout, {line, 80}, + exit_status]), + ct:pal("Prog ~p started: ~p", [Port, ProgAndArgs]), + run_program_loop(Parent, Port, []). + +run_program_loop(Parent, Port, Buf) -> + receive + {Parent, stop} -> + true = port_command(Port, <<"stop\n">>), + ct:pal("Prog ~p stop", [Port]), + run_program_loop(Parent, Port, Buf); + {Port, {data, {Flag, Data}}} -> + case Flag of + eol -> + Line = iolist_to_binary(lists:reverse(Buf, Data)), + ct:pal("Prog ~p output: ~s", [Port, Line]), + Parent ! {self(), line, Line}, + run_program_loop(Parent, Port, []); + noeol -> + run_program_loop(Parent, Port, [Data | Buf]) + end; + {Port, {exit_status,ExitStatus}} -> + ct:pal("Prog ~p exit: ~p", [Port, ExitStatus]), + catch port_close(Port), + Parent ! {self(), exit, ExitStatus}; + Unexpected -> + ct:pal("run_program_loop Unexpected: ~p", [Unexpected]), + run_program_loop(Parent, Port, Buf) + end. + + +app_env(Config) -> + Dir = ?config(priv_dir, Config), + Vsns = ?config(snmp_versions, Config), + [{versions, Vsns}, + {agent_type, master}, + {agent_verbosity, trace}, + {db_dir, Dir}, + {audit_trail_log, [{type, read_write}, + {dir, Dir}, + {size, {10240, 10}}]}, + {config, [{dir, Dir}, + {force_load, true}, + {verbosity, trace}]}, + {local_db, [{repair, true}, + {verbosity, silence}]}, + {mib_server, [{verbosity, silence}]}, + {symbolic_store, [{verbosity, silence}]}, + {note_store, [{verbosity, silence}]}, + {net_if, [{verbosity, trace}]}]. + +oid_str([1 | Ints]) -> + "iso." ++ oid_str_tl(Ints); +oid_str(Ints) -> + oid_str_tl(Ints). + +oid_str_tl([]) -> + ""; +oid_str_tl([Int]) -> + integer_to_list(Int); +oid_str_tl([Int | Ints]) -> + integer_to_list(Int) ++ "." ++ oid_str_tl(Ints). + +agent_config(Dir, Transports, TargetDomain, TargetAddr, Versions) -> + agent_config(Dir, Transports, [{TargetDomain, TargetAddr}], Versions). +%% +agent_config(Dir, Transports, Targets, Versions) -> + EngineID = ?AGENT_ENGINE_ID, + MMS = ?DEFAULT_MAX_MESSAGE_SIZE, + ok = snmp_config:write_agent_snmp_conf(Dir, Transports, EngineID, MMS), + ok = snmp_config:write_agent_snmp_context_conf(Dir), + ok = snmp_config:write_agent_snmp_community_conf(Dir), + ok = + snmp_config:write_agent_snmp_standard_conf( + Dir, "snmp_to_snmpnet_SUITE"), + ok = + snmp_config:write_agent_snmp_target_addr_conf( + Dir, Targets, Versions), + ok = snmp_config:write_agent_snmp_target_params_conf(Dir, Versions), + ok = snmp_config:write_agent_snmp_notify_conf(Dir, inform), + ok = snmp_config:write_agent_snmp_vacm_conf(Dir, Versions, none). + +net_snmp_version([v3 | _]) -> + "-v3"; +net_snmp_version([v2 | _]) -> + "-v2c"; +net_snmp_version([v1 | _]) -> + "-v1". + +domain(inet) -> + transportDomainUdpIpv4; +domain(inet6) -> + transportDomainUdpIpv6. + +net_snmp_addr_str([Target | Targets]) -> + net_snmp_addr_str(Target) ++ + case Targets of + [] -> + []; + [_ | _] -> + "," ++ net_snmp_addr_str(Targets) + end; +net_snmp_addr_str({transportDomainUdpIpv4, {Addr, Port}}) -> + "udp:" ++ + inet_parse:ntoa(Addr) ++ ":" ++ + integer_to_list(Port); +net_snmp_addr_str({transportDomainUdpIpv6, {Addr, Port}}) -> + "udp6:[" ++ + inet_parse:ntoa(Addr) ++ "]:" ++ + integer_to_list(Port). diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.bin b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.bin Binary files differnew file mode 100644 index 0000000000..9d0790498d --- /dev/null +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.bin diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.mib b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.mib new file mode 100644 index 0000000000..679ddc14b0 --- /dev/null +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.mib @@ -0,0 +1,71 @@ +TestTrapv2 DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2, enterprises, IpAddress, + Integer32 + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp, RowStatus, TruthValue, + TEXTUAL-CONVENTION + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF + + system, snmp, ifIndex, ifAdminStatus, ifOperStatus + FROM RFC1213-MIB + snmpTraps + FROM SNMPv2-MIB; + +testTrapv2 MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "IETF SNMPv2 Working Group" + CONTACT-INFO + " Marshall T. Rose + + Postal: Dover Beach Consulting, Inc. + 420 Whisman Court + Mountain View, CA 94043-2186 + US + + Tel: +1 415 968 1052 + + E-mail: [email protected]" + DESCRIPTION + "The MIB module for SNMPv2 entities." + REVISION "9304010000Z" + DESCRIPTION + "The initial revision of this MIB module was published as + RFC 1450." + ::= { system 100 } + + +tst OBJECT IDENTIFIER ::= { system 0 } + +testTrapv21 NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "This trap is exactly the v2 correspondance of testTrap1 in + TestTrap mib." + ::= { snmp 1 } + +testTrapv22 NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "This trap is exactly the v2 correspondance of testTrap2 in + TestTrap mib." + ::= { system 0 1 } + +linkUp NOTIFICATION-TYPE + OBJECTS { ifIndex, ifAdminStatus, ifOperStatus } + STATUS current + DESCRIPTION + "A linkUp trap signifies that the SNMPv2 entity, + acting in an agent role, has detected that the + ifOperStatus object for one of its communication links + has transitioned out of the down state." + ::= { snmpTraps 4 } + + + + +END diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE_data/start_stop_wrapper b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/start_stop_wrapper new file mode 100755 index 0000000000..f806ab5c12 --- /dev/null +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/start_stop_wrapper @@ -0,0 +1,47 @@ +#! /bin/sh +## +## %CopyrightBegin% +## +## Copyright Ericsson AB 2014-2014. 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% +## +# + +## Start the given executable, wait for stop command, +## stop the running executable and wait for exit. + +die () { + r=$? + echo "$0:" "$*" 1>&2 + exit $r +} + +test -x "$1" || die "Not Executable: $1" + +# Redirect stdin to make sure the stop command is read by us below +# and does not go to the executable +"$@" 0< /dev/null & +PID=$! + +# Wait for stop command +while read LINE; do + case :"$LINE" in + :"stop") + break;; + esac +done + +kill $PID +wait $PID diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index 04c3cc9392..fd10244386 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = snmp -SNMP_VSN = 4.25.1 +SNMP_VSN = 5.0 PRE_VSN = APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)" diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 84d5e5c86e..0dbec7527a 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -29,6 +29,48 @@ <file>notes.xml</file> </header> +<section><title>Ssh 3.0.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Removed mail address from error reports and corrected + spelling error (Stacktace -> stacktrace)</p> + <p> + Own Id: OTP-11883 Aux Id: seq12586 </p> + </item> + <item> + <p> + Decode/encode fixes in SSH_MSG_IGNORE and + SSH_MSG_UNIMPLEMENTED.</p> + <p> + Own Id: OTP-11983</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Accepts that some older OpenSSH clients sends incorrect + disconnect messages.</p> + <p> + Own Id: OTP-11972</p> + </item> + <item> + <p> + Handle inet and inet6 option correctly</p> + <p> + Own Id: OTP-11976</p> + </item> + </list> + </section> + +</section> + <section><title>Ssh 3.0.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 5a141ced3c..876eba598a 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2004</year><year>2013</year> + <year>2004</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -97,6 +97,8 @@ <seealso marker="ssh_connection#session_channel/2">ssh_connection:session_channel/[2, 4]</seealso>.</p> <p>Options are:</p> <taglist> + <tag><c><![CDATA[{inet, inet | inet6}]]></c></tag> + <item> IP version to use.</item> <tag><c><![CDATA[{user_dir, string()}]]></c></tag> <item> <p>Sets the user directory i.e. the directory containing @@ -230,6 +232,8 @@ port.</p> <p>Options are:</p> <taglist> + <tag><c><![CDATA[{inet, inet | inet6}]]></c></tag> + <item> IP version to use when the host address is specified as <c>any</c>. </item> <tag><c><![CDATA[{subsystems, [subsystem_spec()]]]></c></tag> <item> Provides specifications for handling of subsystems. The diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src index 42eb2167e0..8269f89e40 100644 --- a/lib/ssh/src/ssh.appup.src +++ b/lib/ssh/src/ssh.appup.src @@ -19,13 +19,25 @@ {"%VSN%", [ + {"3.0.2", [{load_module, ssh_message, soft_purge, soft_purge, []}, + {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, + {load_module, ssh_io, soft_purge, soft_purge, []}]}, {"3.0.1", [{load_module, ssh, soft_purge, soft_purge, []}, - {load_module, ssh_acceptor, soft_purge, soft_purge, []}]}, + {load_module, ssh_acceptor, soft_purge, soft_purge, []}, + {load_module, ssh_message, soft_purge, soft_purge, []}, + {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, + {load_module, ssh_io, soft_purge, soft_purge, []}]}, {<<".*">>, [{restart_application, ssh}]} ], [ + {"3.0.2", [{load_module, ssh_message, soft_purge, soft_purge, []}, + {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, + {load_module, ssh_io, soft_purge, soft_purge, []}]}, {"3.0.1", [{load_module, ssh, soft_purge, soft_purge, []}, - {load_module, ssh_acceptor, soft_purge, soft_purge, []}]}, + {load_module, ssh_acceptor, soft_purge, soft_purge, []}, + {load_module, ssh_message, soft_purge, soft_purge, []}, + {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, + {load_module, ssh_io, soft_purge, soft_purge, []}]}, {<<".*">>, [{restart_application, ssh}]} ] }. diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 240de69eff..743c01a42c 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -74,8 +74,7 @@ connect(Host, Port, Options, Timeout) -> {_, Transport, _} = TransportOpts = proplists:get_value(transport, Options, {tcp, gen_tcp, tcp_closed}), ConnectionTimeout = proplists:get_value(connect_timeout, Options, infinity), - Inet = proplists:get_value(inet, SshOptions, inet), - try Transport:connect(Host, Port, [ {active, false}, Inet | SocketOptions], ConnectionTimeout) of + try Transport:connect(Host, Port, [ {active, false} | SocketOptions], ConnectionTimeout) of {ok, Socket} -> Opts = [{user_pid, self()}, {host, Host} | fix_idle_time(SshOptions)], ssh_connection_handler:start_connection(client, Socket, Opts, Timeout); @@ -256,8 +255,8 @@ do_start_daemon(Host, Port, Options, SocketOptions) -> handle_options(Opts) -> try handle_option(proplists:unfold(Opts), [], []) of - {_,_} = Options -> - Options + {Inet, Ssh} -> + {handle_ip(Inet), Ssh} catch throw:Error -> Error @@ -433,13 +432,14 @@ handle_ssh_option(Opt) -> throw({error, {eoptions, Opt}}). handle_inet_option({active, _} = Opt) -> - throw({error, {{eoptions, Opt}, "Ssh has built in flow control, " - "and activ is handled internaly user is not allowd" + throw({error, {{eoptions, Opt}, "SSH has built in flow control, " + "and active is handled internally, user is not allowed" "to specify this option"}}); -handle_inet_option({inet, Value} = Opt) when (Value == inet) or (Value == inet6) -> - Opt; + +handle_inet_option({inet, Value}) when (Value == inet) or (Value == inet6) -> + Value; handle_inet_option({reuseaddr, _} = Opt) -> - throw({error, {{eoptions, Opt},"Is set internaly user is not allowd" + throw({error, {{eoptions, Opt},"Is set internally, user is not allowed" "to specify this option"}}); %% Option verified by inet handle_inet_option(Opt) -> @@ -460,3 +460,17 @@ handle_pref_algs([H|T], Acc) -> _ -> false end. + +handle_ip(Inet) -> %% Default to ipv4 + case lists:member(inet, Inet) of + true -> + Inet; + false -> + case lists:member(inet6, Inet) of + true -> + Inet; + false -> + [inet | Inet] + end + end. + diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 06866392da..86804c4436 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -104,21 +104,11 @@ start_connection(client = Role, Socket, Options, Timeout) -> start_connection(server = Role, Socket, Options, Timeout) -> try - Sups = proplists:get_value(supervisors, Options), - ConnectionSup = proplists:get_value(connection_sup, Sups), - Opts = [{supervisors, Sups}, {user_pid, self()} | proplists:get_value(ssh_opts, Options, [])], - {ok, Pid} = ssh_connection_sup:start_child(ConnectionSup, [Role, Socket, Opts]), - {_, Callback, _} = proplists:get_value(transport, Options, {tcp, gen_tcp, tcp_closed}), - socket_control(Socket, Pid, Callback), - case proplists:get_value(parallel_login, Opts, false) of + case proplists:get_value(parallel_login, Options, false) of true -> - spawn(fun() -> - Ref = erlang:monitor(process, Pid), - handshake(Pid, Ref, Timeout) - end); + spawn(fun() -> start_server_connection(Role, Socket, Options, Timeout) end); false -> - Ref = erlang:monitor(process, Pid), - handshake(Pid, Ref, Timeout) + start_server_connection(Role, Socket, Options, Timeout) end catch exit:{noproc, _} -> @@ -127,6 +117,18 @@ start_connection(server = Role, Socket, Options, Timeout) -> {error, Error} end. + +start_server_connection(server = Role, Socket, Options, Timeout) -> + Sups = proplists:get_value(supervisors, Options), + ConnectionSup = proplists:get_value(connection_sup, Sups), + Opts = [{supervisors, Sups}, {user_pid, self()} | proplists:get_value(ssh_opts, Options, [])], + {ok, Pid} = ssh_connection_sup:start_child(ConnectionSup, [Role, Socket, Opts]), + {_, Callback, _} = proplists:get_value(transport, Options, {tcp, gen_tcp, tcp_closed}), + socket_control(Socket, Pid, Callback), + Ref = erlang:monitor(process, Pid), + handshake(Pid, Ref, Timeout). + + start_link(Role, Socket, Options) -> {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Socket, Options]])}. diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl index 8d6c77c0ed..76b57cb995 100644 --- a/lib/ssh/src/ssh_message.erl +++ b/lib/ssh/src/ssh_message.erl @@ -255,7 +255,7 @@ encode(#ssh_msg_ignore{data = Data}) -> ssh_bits:encode([?SSH_MSG_IGNORE, Data], [byte, string]); encode(#ssh_msg_unimplemented{sequence = Seq}) -> - ssh_bits:encode([?SSH_MSG_IGNORE, Seq], [byte, uint32]); + ssh_bits:encode([?SSH_MSG_UNIMPLEMENTED, Seq], [byte, uint32]); encode(#ssh_msg_debug{always_display = Bool, message = Msg, @@ -391,13 +391,6 @@ decode(<<?BYTE(?SSH_MSG_USERAUTH_INFO_REQUEST), ?UINT32(Len0), Name:Len0/binary, data = Data}; %%% Unhandled message, also masked by same 1:st byte value as ?SSH_MSG_USERAUTH_INFO_REQUEST: -decode(<<?BYTE(?SSH_MSG_USERAUTH_PK_OK), ?UINT32(Len), Alg:Len/binary, KeyBlob/binary>>) -> - #ssh_msg_userauth_pk_ok{ - algorithm_name = Alg, - key_blob = KeyBlob - }; - -%%% Unhandled message, also masked by same 1:st byte value as ?SSH_MSG_USERAUTH_INFO_REQUEST: decode(<<?BYTE(?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ), ?UINT32(Len0), Prompt:Len0/binary, ?UINT32(Len1), Lang:Len1/binary>>) -> #ssh_msg_userauth_passwd_changereq{ @@ -405,6 +398,13 @@ decode(<<?BYTE(?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ), ?UINT32(Len0), Prompt:Len0/b languge = Lang }; +%%% Unhandled message, also masked by same 1:st byte value as ?SSH_MSG_USERAUTH_INFO_REQUEST: +decode(<<?BYTE(?SSH_MSG_USERAUTH_PK_OK), ?UINT32(Len), Alg:Len/binary, KeyBlob/binary>>) -> + #ssh_msg_userauth_pk_ok{ + algorithm_name = Alg, + key_blob = KeyBlob + }; + decode(<<?BYTE(?SSH_MSG_USERAUTH_INFO_RESPONSE), ?UINT32(Num), Data/binary>>) -> #ssh_msg_userauth_info_response{ num_responses = Num, @@ -461,10 +461,19 @@ decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), language = Lang }; +%% Accept bad disconnects from ancient openssh clients that doesn't send language tag. Use english as a work-around. +decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), + ?UINT32(Len0), Desc:Len0/binary>>) -> + #ssh_msg_disconnect{ + code = Code, + description = unicode:characters_to_list(Desc), + language = <<"en">> + }; + decode(<<?SSH_MSG_NEWKEYS>>) -> #ssh_msg_newkeys{}; -decode(<<?BYTE(?SSH_MSG_IGNORE), Data/binary>>) -> +decode(<<?BYTE(?SSH_MSG_IGNORE), ?UINT32(Len), Data:Len/binary>>) -> #ssh_msg_ignore{data = Data}; decode(<<?BYTE(?SSH_MSG_UNIMPLEMENTED), ?UINT32(Seq)>>) -> diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index ba38c1da40..35fca21021 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -59,14 +59,19 @@ groups() -> {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, {internal_error, [], [internal_error]}, - {hardening_tests, [], [max_sessions]} + {hardening_tests, [], [ssh_connect_nonegtimeout_connected_parallel, + ssh_connect_nonegtimeout_connected_sequential, + ssh_connect_negtimeout_parallel, + ssh_connect_negtimeout_sequential, + max_sessions]} ]. basic_tests() -> [send, close, peername_sockname, exec, exec_compressed, shell, cli, known_hosts, - idle_time, rekey, openssh_zlib_basic_test]. + idle_time, rekey, openssh_zlib_basic_test, + misc_ssh_options, inet_option]. %%-------------------------------------------------------------------- @@ -175,16 +180,47 @@ misc_ssh_options(Config) when is_list(Config) -> SystemDir = filename:join(?config(priv_dir, Config), system), UserDir = ?config(priv_dir, Config), - CMiscOpt0 = [{connecect_timeout, 1000}, {ip_v6_disabled, false}, {user_dir, UserDir}], - CMiscOpt1 = [{connecect_timeout, infinity}, {ip_v6_disabled, true}, {user_dir, UserDir}], - SMiscOpt0 = [{ip_v6_disabled, false}, {user_dir, UserDir}, {system_dir, SystemDir}], - SMiscOpt1 = [{ip_v6_disabled, true}, {user_dir, UserDir}, {system_dir, SystemDir}], + CMiscOpt0 = [{connect_timeout, 1000}, {user_dir, UserDir}], + CMiscOpt1 = [{connect_timeout, infinity}, {user_dir, UserDir}], + SMiscOpt0 = [{user_dir, UserDir}, {system_dir, SystemDir}], + SMiscOpt1 = [{user_dir, UserDir}, {system_dir, SystemDir}], + + basic_test([{client_opts, CMiscOpt0}, {server_opts, SMiscOpt0}]), + basic_test([{client_opts, CMiscOpt1}, {server_opts, SMiscOpt1}]). + +%%-------------------------------------------------------------------- +inet_option() -> + [{doc, "Test configuring IPv4"}]. +inet_option(Config) when is_list(Config) -> + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), + ClientOpts = [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}], + ServerOpts = [{system_dir, SystemDir}, + {user_dir, UserDir}, + {failfun, fun ssh_test_lib:failfun/2}], - basic_test([{client_opts, CMiscOpt0 ++ ClientOpts}, {server_opts, SMiscOpt0 ++ ServerOpts}]), - basic_test([{client_opts, CMiscOpt1 ++ ClientOpts}, {server_opts, SMiscOpt1 ++ ServerOpts}]). + basic_test([{client_opts, [{inet, inet} | ClientOpts]}, + {server_opts, [{inet, inet} | ServerOpts]}]). + +%%-------------------------------------------------------------------- +inet6_option() -> + [{doc, "Test configuring IPv6"}]. +inet6_option(Config) when is_list(Config) -> + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + + ClientOpts = [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}], + ServerOpts = [{system_dir, SystemDir}, + {user_dir, UserDir}, + {failfun, fun ssh_test_lib:failfun/2}], + + basic_test([{client_opts, [{inet, inet6} | ClientOpts]}, + {server_opts, [{inet, inet6} | ServerOpts]}]). %%-------------------------------------------------------------------- exec() -> @@ -711,6 +747,98 @@ ms_passed(N1={_,_,M1}, N2={_,_,M2}) -> 1000 * (Min*60 + Sec + (M2-M1)/1000000). %%-------------------------------------------------------------------- +ssh_connect_negtimeout_parallel(Config) -> ssh_connect_negtimeout(Config,true). +ssh_connect_negtimeout_sequential(Config) -> ssh_connect_negtimeout(Config,false). + +ssh_connect_negtimeout(Config, Parallel) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + NegTimeOut = 2000, % ms + ct:log("Parallel: ~p",[Parallel]), + + {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, + {parallel_login, Parallel}, + {negotiation_timeout, NegTimeOut}, + {failfun, fun ssh_test_lib:failfun/2}]), + + {ok,Socket} = gen_tcp:connect(Host, Port, []), + ct:pal("And now sleeping 1.2*NegTimeOut (~p ms)...", [round(1.2 * NegTimeOut)]), + receive after round(1.2 * NegTimeOut) -> ok end, + + case inet:sockname(Socket) of + {ok,_} -> ct:fail("Socket not closed"); + {error,_} -> ok + end. + +%%-------------------------------------------------------------------- +ssh_connect_nonegtimeout_connected_parallel() -> + [{doc, "Test that ssh connection does not timeout if the connection is established (parallel)"}]. +ssh_connect_nonegtimeout_connected_parallel(Config) -> + ssh_connect_nonegtimeout_connected(Config, true). + +ssh_connect_nonegtimeout_connected_sequential() -> + [{doc, "Test that ssh connection does not timeout if the connection is established (non-parallel)"}]. +ssh_connect_nonegtimeout_connected_sequential(Config) -> + ssh_connect_nonegtimeout_connected(Config, false). + + +ssh_connect_nonegtimeout_connected(Config, Parallel) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + NegTimeOut = 20000, % ms + ct:log("Parallel: ~p",[Parallel]), + + {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, + {parallel_login, Parallel}, + {negotiation_timeout, NegTimeOut}, + {failfun, fun ssh_test_lib:failfun/2}]), + ct:sleep(500), + + IO = ssh_test_lib:start_io_server(), + Shell = ssh_test_lib:start_shell(Port, IO, UserDir), + receive + {'EXIT', _, _} -> + ct:fail(no_ssh_connection); + ErlShellStart -> + ct:pal("---Erlang shell start: ~p~n", [ErlShellStart]), + one_shell_op(IO, NegTimeOut), + one_shell_op(IO, NegTimeOut), + ct:pal("And now sleeping 1.2*NegTimeOut (~p ms)...", [round(1.2 * NegTimeOut)]), + receive after round(1.2 * NegTimeOut) -> ok end, + one_shell_op(IO, NegTimeOut) + end, + exit(Shell, kill). + + +one_shell_op(IO, TimeOut) -> + ct:pal("One shell op: Waiting for prompter"), + receive + ErlPrompt0 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt0]) + after TimeOut -> ct:fail("Timeout waiting for promter") + end, + + IO ! {input, self(), "2*3*7.\r\n"}, + receive + Echo0 -> ct:log("Echo: ~p ~n", [Echo0]) + after TimeOut -> ct:fail("Timeout waiting for echo") + end, + + receive + ?NEWLINE -> ct:log("NEWLINE received", []) + after TimeOut -> + receive Any1 -> ct:log("Bad NEWLINE: ~p",[Any1]) + after 0 -> ct:fail("Timeout waiting for NEWLINE") + end + end, + + receive + Result0 -> ct:log("Result: ~p~n", [Result0]) + after TimeOut -> ct:fail("Timeout waiting for result") + end. + +%%-------------------------------------------------------------------- openssh_zlib_basic_test() -> [{doc, "Test basic connection with openssh_zlib"}]. diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 40ed27d8f5..9bef10a366 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,5 +1,5 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 3.0.2 +SSH_VSN = 3.0.4 APP_VSN = "ssh-$(SSH_VSN)" diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index c61b2a9c2f..1b37a2baa2 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -25,7 +25,119 @@ <file>notes.xml</file> </header> <p>This document describes the changes made to the SSL application.</p> - <section><title>SSL 5.3.4</title> + <section><title>SSL 5.3.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + ssl:recv now returns {error, einval} if applied to a non + passive socket, the same as gen_tcp:recv. </p> + <p> + Thanks to Danil Zagoskin for reporting this issue</p> + <p> + Own Id: OTP-11878</p> + </item> + <item> + <p> + Corrected handling of default values for + signature_algorithms extension in TLS-1.2 and + corresponding values used in previous versions that does + not support this extension. </p> + <p> + Thanks to Danil Zagoskin</p> + <p> + Own Id: OTP-11886</p> + </item> + <item> + <p> + Handle socket option inheritance when pooling of accept + sockets is used</p> + <p> + Own Id: OTP-11897</p> + </item> + <item> + <p> + Make sure that the list of versions, possibly supplied in + the versions option, is not order dependent.</p> + <p> + Thanks to Ransom Richardson for reporting this issue</p> + <p> + Own Id: OTP-11912</p> + </item> + <item> + <p> + Reject connection if the next_protocol message is sent + twice.</p> + <p> + Own Id: OTP-11926</p> + </item> + <item> + <p> + Correct options handling when ssl:ssl_accept/3 is called + with new ssl options after calling ssl:listen/2</p> + <p> + Own Id: OTP-11950</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Gracefully handle unknown alerts</p> + <p> + Thanks to Atul Atri for reporting this issue</p> + <p> + Own Id: OTP-11874</p> + </item> + <item> + <p> + Gracefully ignore cipher suites sent by client not + supported by the SSL/TLS version that the client has + negotiated.</p> + <p> + Thanks to Danil Zagoskin for reporting this issue</p> + <p> + Own Id: OTP-11875</p> + </item> + <item> + <p> + Gracefully handle structured garbage, i.e a client sends + some garbage in a ssl record instead of a valid fragment.</p> + <p> + Thanks to Danil Zagoskin</p> + <p> + Own Id: OTP-11880</p> + </item> + <item> + <p> + Gracefully handle invalid alerts</p> + <p> + Own Id: OTP-11890</p> + </item> + <item> + <p> + Generalize handling of default ciphers</p> + <p> + Thanks to Andreas Schultz</p> + <p> + Own Id: OTP-11966</p> + </item> + <item> + <p> + Make sure change cipher spec is correctly handled</p> + <p> + Own Id: OTP-11975</p> + </item> + </list> + </section> + +</section> + +<section><title>SSL 5.3.4</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index be1041ca13..d741fa63fb 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -339,14 +339,10 @@ negotiated_next_protocol(#sslsocket{pid = Pid}) -> ssl_connection:negotiated_next_protocol(Pid). %%-------------------------------------------------------------------- --spec cipher_suites() -> [ssl_cipher:erl_cipher_suite()]. --spec cipher_suites(erlang | openssl | all) -> [ssl_cipher:erl_cipher_suite()] | [string()]. - +-spec cipher_suites(erlang | openssl | all) -> [ssl_cipher:erl_cipher_suite()] | + [string()]. %% Description: Returns all supported cipher suites. %%-------------------------------------------------------------------- -cipher_suites() -> - cipher_suites(erlang). - cipher_suites(erlang) -> Version = tls_record:highest_protocol_version([]), ssl_cipher:filter_suites([suite_definition(S) @@ -358,11 +354,14 @@ cipher_suites(openssl) -> cipher_suites(all) -> Version = tls_record:highest_protocol_version([]), Supported = ssl_cipher:all_suites(Version) - ++ ssl_cipher:anonymous_suites(Version) + ++ ssl_cipher:anonymous_suites() ++ ssl_cipher:psk_suites(Version) ++ ssl_cipher:srp_suites(), ssl_cipher:filter_suites([suite_definition(S) || S <- Supported]). +cipher_suites() -> + cipher_suites(erlang). + %%-------------------------------------------------------------------- -spec getopts(#sslsocket{}, [gen_tcp:option_name()]) -> {ok, [gen_tcp:option()]} | {error, reason()}. diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl index b186a1015a..53366b060c 100644 --- a/lib/ssl/src/ssl_certificate.erl +++ b/lib/ssl/src/ssl_certificate.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014 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 @@ -232,7 +232,12 @@ find_issuer(OtpCert, CertDbHandle) -> IsIssuerFun = fun({_Key, {_Der, #'OTPCertificate'{} = ErlCertCandidate}}, Acc) -> case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of true -> - throw(public_key:pkix_issuer_id(ErlCertCandidate, self)); + case verify_cert_signer(OtpCert, ErlCertCandidate#'OTPCertificate'.tbsCertificate) of + true -> + throw(public_key:pkix_issuer_id(ErlCertCandidate, self)); + false -> + Acc + end; false -> Acc end; @@ -254,3 +259,19 @@ is_valid_extkey_usage(KeyUse, client) -> is_valid_extkey_usage(KeyUse, server) -> %% Server wants to verify client is_valid_key_usage(KeyUse, ?'id-kp-clientAuth'). + +verify_cert_signer(OtpCert, SignerTBSCert) -> + PublicKey = public_key(SignerTBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo), + public_key:pkix_verify(public_key:pkix_encode('OTPCertificate', OtpCert, otp), PublicKey). + +public_key(#'OTPSubjectPublicKeyInfo'{algorithm = #'PublicKeyAlgorithm'{algorithm = ?'id-ecPublicKey', + parameters = Params}, + subjectPublicKey = Point}) -> + {Point, Params}; +public_key(#'OTPSubjectPublicKeyInfo'{algorithm = #'PublicKeyAlgorithm'{algorithm = ?'rsaEncryption'}, + subjectPublicKey = Key}) -> + Key; +public_key(#'OTPSubjectPublicKeyInfo'{algorithm = #'PublicKeyAlgorithm'{algorithm = ?'id-dsa', + parameters = {params, Params}}, + subjectPublicKey = Key}) -> + {Key, Params}. diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 34006612a2..4ac4e81d9e 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -58,7 +58,10 @@ %%==================================================================== %%-------------------------------------------------------------------- -spec connect(tls_connection | dtls_connection, - host(), inet:port_number(), port(), {#ssl_options{}, #socket_options{}}, + host(), inet:port_number(), port(), + {#ssl_options{}, #socket_options{}, + %% Tracker only needed on server side + undefined}, pid(), tuple(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% @@ -73,9 +76,10 @@ connect(Connection, Host, Port, Socket, Options, User, CbInfo, Timeout) -> end. %%-------------------------------------------------------------------- -spec ssl_accept(tls_connection | dtls_connection, - inet:port_number(), port(), {#ssl_options{}, #socket_options{}}, - pid(), tuple(), timeout()) -> - {ok, #sslsocket{}} | {error, reason()}. + inet:port_number(), port(), + {#ssl_options{}, #socket_options{}, undefined | pid()}, + pid(), tuple(), timeout()) -> + {ok, #sslsocket{}} | {error, reason()}. %% %% Description: Performs accept on an ssl listen socket. e.i. performs %% ssl handshake. @@ -102,7 +106,8 @@ handshake(#sslsocket{pid = Pid}, Timeout) -> end. %%-------------------------------------------------------------------- --spec handshake(#sslsocket{}, #ssl_options{}, timeout()) -> ok | {error, reason()}. +-spec handshake(#sslsocket{}, {#ssl_options{},#socket_options{}}, + timeout()) -> ok | {error, reason()}. %% %% Description: Starts ssl handshake with some new options %%-------------------------------------------------------------------- @@ -322,6 +327,7 @@ abbreviated(#hello_request{}, State0, Connection) -> abbreviated(#finished{verify_data = Data} = Finished, #state{role = server, negotiated_version = Version, + expecting_finished = true, tls_handshake_history = Handshake, session = #session{master_secret = MasterSecret}, connection_states = ConnectionStates0} = @@ -334,7 +340,8 @@ abbreviated(#finished{verify_data = Data} = Finished, ssl_record:set_client_verify_data(current_both, Data, ConnectionStates0), Connection:next_state_connection(abbreviated, ack_connection( - State#state{connection_states = ConnectionStates})); + State#state{connection_states = ConnectionStates, + expecting_finished = false})); #alert{} = Alert -> Connection:handle_own_alert(Alert, Version, abbreviated, State) end; @@ -354,7 +361,7 @@ abbreviated(#finished{verify_data = Data} = Finished, finalize_handshake(State0#state{connection_states = ConnectionStates1}, abbreviated, Connection), Connection:next_state_connection(abbreviated, - ack_connection(State)); + ack_connection(State#state{expecting_finished = false})); #alert{} = Alert -> Connection:handle_own_alert(Alert, Version, abbreviated, State0) end; @@ -365,7 +372,7 @@ abbreviated(#next_protocol{selected_protocol = SelectedProtocol}, #state{role = server, expecting_next_protocol_negotiation = true} = State0, Connection) -> {Record, State} = Connection:next_record(State0#state{next_protocol = SelectedProtocol}), - Connection:next_state(abbreviated, abbreviated, Record, State); + Connection:next_state(abbreviated, abbreviated, Record, State#state{expecting_next_protocol_negotiation = false}); abbreviated(timeout, State, _) -> {next_state, abbreviated, State, hibernate }; @@ -589,6 +596,7 @@ cipher(#finished{verify_data = Data} = Finished, host = Host, port = Port, role = Role, + expecting_finished = true, session = #session{master_secret = MasterSecret} = Session0, connection_states = ConnectionStates0, @@ -599,7 +607,7 @@ cipher(#finished{verify_data = Data} = Finished, MasterSecret, Handshake0) of verified -> Session = register_session(Role, Host, Port, Session0), - cipher_role(Role, Data, Session, State, Connection); + cipher_role(Role, Data, Session, State#state{expecting_finished = false}, Connection); #alert{} = Alert -> Connection:handle_own_alert(Alert, Version, cipher, State) end; @@ -607,7 +615,8 @@ cipher(#finished{verify_data = Data} = Finished, %% only allowed to send next_protocol message after change cipher spec %% & before finished message and it is not allowed during renegotiation cipher(#next_protocol{selected_protocol = SelectedProtocol}, - #state{role = server, expecting_next_protocol_negotiation = true} = State0, Connection) -> + #state{role = server, expecting_next_protocol_negotiation = true, + expecting_finished = true} = State0, Connection) -> {Record, State} = Connection:next_record(State0#state{next_protocol = SelectedProtocol}), Connection:next_state(cipher, cipher, Record, State#state{expecting_next_protocol_negotiation = false}); @@ -1034,9 +1043,6 @@ server_hello_done(State, Connection) -> HelloDone = ssl_handshake:server_hello_done(), Connection:send_handshake(HelloDone, State). - - - handle_peer_cert(Role, PeerCert, PublicKeyInfo, #state{session = #session{cipher_suite = CipherSuite} = Session} = State0, Connection) -> diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl index 592889b177..c544a0591f 100644 --- a/lib/ssl/src/ssl_connection.hrl +++ b/lib/ssl/src/ssl_connection.hrl @@ -77,6 +77,7 @@ terminated = false ::boolean(), allow_renegotiate = true ::boolean(), expecting_next_protocol_negotiation = false ::boolean(), + expecting_finished = false ::boolean(), next_protocol = undefined :: undefined | binary(), client_ecc, % {Curves, PointFmt} tracker :: pid() %% Tracker process for listen socket diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index fc67d2c28d..25bdc5ef93 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -207,7 +207,7 @@ client_certificate_verify(OwnCert, MasterSecret, Version, %% Description: Creates a certificate_request message, called by the server. %%-------------------------------------------------------------------- certificate_request(CipherSuite, CertDbHandle, CertDbRef, Version) -> - Types = certificate_types(CipherSuite), + Types = certificate_types(ssl_cipher:suite_definition(CipherSuite), Version), HashSigns = advertised_hash_signs(Version), Authorities = certificate_authorities(CertDbHandle, CertDbRef), #certificate_request{ @@ -1098,19 +1098,31 @@ supported_ecc(_) -> %%-------------certificate handling -------------------------------- -certificate_types({KeyExchange, _, _, _}) - when KeyExchange == rsa; - KeyExchange == dhe_dss; - KeyExchange == dhe_rsa; - KeyExchange == ecdhe_rsa -> - <<?BYTE(?RSA_SIGN), ?BYTE(?DSS_SIGN)>>; +certificate_types(_, {N, M}) when N >= 3 andalso M >= 3 -> + case proplists:get_bool(ecdsa, + proplists:get_value(public_keys, crypto:supports())) of + true -> + <<?BYTE(?ECDSA_SIGN), ?BYTE(?RSA_SIGN), ?BYTE(?DSS_SIGN)>>; + false -> + <<?BYTE(?RSA_SIGN), ?BYTE(?DSS_SIGN)>> + end; + +certificate_types({KeyExchange, _, _, _}, _) when KeyExchange == rsa; + KeyExchange == dhe_rsa; + KeyExchange == ecdhe_rsa -> + <<?BYTE(?RSA_SIGN)>>; -certificate_types({KeyExchange, _, _, _}) - when KeyExchange == dh_ecdsa; - KeyExchange == dhe_ecdsa -> +certificate_types({KeyExchange, _, _, _}, _) when KeyExchange == dhe_dss, + KeyExchange == srp_dss -> + <<?BYTE(?DSS_SIGN)>>; + +certificate_types({KeyExchange, _, _, _}, _) when KeyExchange == dh_ecdsa; + KeyExchange == dhe_ecdsa; + KeyExchange == ecdh_ecdsa; + KeyExchange == ecdhe_ecdsa -> <<?BYTE(?ECDSA_SIGN)>>; -certificate_types(_) -> +certificate_types(_, _) -> <<?BYTE(?RSA_SIGN)>>. certificate_authorities(CertDbHandle, CertDbRef) -> @@ -1719,6 +1731,11 @@ dec_hello_extensions(<<?UINT16(?EC_POINT_FORMATS_EXT), ?UINT16(Len), dec_hello_extensions(Rest, Acc#hello_extensions{ec_point_formats = #ec_point_formats{ec_point_format_list = ECPointFormats}}); + +dec_hello_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len), + ExtData:Len/binary, Rest/binary>>, Acc) -> + <<?UINT16(_), NameList/binary>> = ExtData, + dec_hello_extensions(Rest, Acc#hello_extensions{sni = dec_sni(NameList)}); %% Ignore data following the ClientHello (i.e., %% extensions) if not understood. @@ -1731,6 +1748,13 @@ dec_hello_extensions(_, Acc) -> dec_hashsign(<<?BYTE(HashAlgo), ?BYTE(SignAlgo)>>) -> {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)}. +%% Ignore unknown names (only host_name is supported) +dec_sni(<<?BYTE(?SNI_NAMETYPE_HOST_NAME), ?UINT16(Len), + HostName:Len/binary, _/binary>>) -> + #sni{hostname = binary_to_list(HostName)}; +dec_sni(<<?BYTE(_), ?UINT16(Len), _:Len, Rest/binary>>) -> dec_sni(Rest); +dec_sni(_) -> undefined. + decode_next_protocols({next_protocol_negotiation, Protocols}) -> decode_next_protocols(Protocols, []). decode_next_protocols(<<>>, Acc) -> diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index fbc73e0e42..d6e5064c39 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -52,8 +52,8 @@ last_delay_timer = {undefined, undefined}%% Keep for testing purposes }). --define('24H_in_msec', 8640000). --define('24H_in_sec', 8640). +-define('24H_in_msec', 86400000). +-define('24H_in_sec', 86400). -define(GEN_UNIQUE_ID_MAX_TRIES, 10). -define(SESSION_VALIDATION_INTERVAL, 60000). -define(CLEAR_PEM_CACHE, 120000). diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 2ab085321a..26de51985a 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -444,12 +444,16 @@ next_state(_, StateName, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, St next_state(StateName, StateName, Record, State) end; next_state(Current, Next, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = <<1>>} = - _ChangeCipher, - #state{connection_states = ConnectionStates0} = State0) -> + _ChangeCipher, + #state{connection_states = ConnectionStates0} = State0) + when Next == cipher; Next == abbreviated -> ConnectionStates1 = ssl_record:activate_pending_connection_state(ConnectionStates0, read), {Record, State} = next_record(State0#state{connection_states = ConnectionStates1}), - next_state(Current, Next, Record, State); + next_state(Current, Next, Record, State#state{expecting_finished = true}); +next_state(Current, _Next, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = <<1>>} = + _ChangeCipher, #state{negotiated_version = Version} = State) -> + handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Version, Current, State); next_state(Current, Next, #ssl_tls{type = _Unknown}, State0) -> %% Ignore unknown type {Record, State} = next_record(State0), diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile index 2f8ff6f04e..3639c2b2da 100644 --- a/lib/ssl/test/Makefile +++ b/lib/ssl/test/Makefile @@ -37,6 +37,7 @@ VSN=$(GS_VSN) MODULES = \ ssl_test_lib \ ssl_basic_SUITE \ + ssl_bench_SUITE \ ssl_cipher_SUITE \ ssl_certificate_verify_SUITE\ ssl_crl_SUITE\ @@ -130,7 +131,7 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)" $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(HRL_FILES_NEEDED_IN_TEST) $(COVER_FILE) "$(RELSYSDIR)" - $(INSTALL_DATA) ssl.spec ssl.cover "$(RELSYSDIR)" + $(INSTALL_DATA) ssl.spec ssl_bench.spec ssl.cover "$(RELSYSDIR)" chmod -R u+w "$(RELSYSDIR)" @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) diff --git a/lib/ssl/test/erl_make_certs.erl b/lib/ssl/test/erl_make_certs.erl index 22dc951ac1..daf4466f11 100644 --- a/lib/ssl/test/erl_make_certs.erl +++ b/lib/ssl/test/erl_make_certs.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2013. All Rights Reserved. +%% Copyright Ericsson AB 2011-2014. 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 @@ -325,14 +325,14 @@ sign_algorithm(#'RSAPrivateKey'{}, Opts) -> {Type, 'NULL'}; sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) -> {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}; -sign_algorithm(#'ECPrivateKey'{}, Opts) -> +sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) -> Type = case proplists:get_value(digest, Opts, sha1) of sha1 -> ?'ecdsa-with-SHA1'; sha512 -> ?'ecdsa-with-SHA512'; sha384 -> ?'ecdsa-with-SHA384'; sha256 -> ?'ecdsa-with-SHA256' end, - {Type, 'NULL'}. + {Type, Parms}. make_key(rsa, _Opts) -> %% (OBS: for testing only) diff --git a/lib/ssl/test/ssl.spec b/lib/ssl/test/ssl.spec index fc7c1bbb82..86e14c033e 100644 --- a/lib/ssl/test/ssl.spec +++ b/lib/ssl/test/ssl.spec @@ -1 +1,4 @@ {suites,"../ssl_test",all}. +{skip_cases, "../ssl_test", + ssl_bench_SUITE, [setup_sequential, setup_concurrent, payload_simple], + "Benchmarks run separately"}. diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl index 608f2f11c3..77e4c80bbe 100644 --- a/lib/ssl/test/ssl_ECC_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. 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 @@ -57,41 +57,51 @@ all_versions_groups ()-> ]. key_cert_combinations() -> - [client_ec_server_ec, - client_rsa_server_ec, - client_ec_server_rsa, - client_rsa_server_rsa]. + [client_ecdh_server_ecdh, + client_rsa_server_ecdh, + client_ecdh_server_rsa, + client_rsa_server_rsa, + client_ecdsa_server_ecdsa, + client_ecdsa_server_rsa, + client_rsa_server_ecdsa + ]. %%-------------------------------------------------------------------- -init_per_suite(Config) -> - catch crypto:stop(), +init_per_suite(Config0) -> + end_per_suite(Config0), try crypto:start() of ok -> - ssl:start(), - Config + %% make rsa certs using oppenssl + Result = + (catch make_certs:all(?config(data_dir, Config0), + ?config(priv_dir, Config0))), + ct:log("Make certs ~p~n", [Result]), + Config1 = ssl_test_lib:make_ecdsa_cert(Config0), + Config2 = ssl_test_lib:make_ecdh_rsa_cert(Config1), + ssl_test_lib:cert_options(Config2) catch _:_ -> {skip, "Crypto did not start"} end. end_per_suite(_Config) -> - ssl:stop(), + application:stop(ssl), application:stop(crypto). %%-------------------------------------------------------------------- -init_per_group(erlang_client, Config) -> +init_per_group(erlang_client = Group, Config) -> case ssl_test_lib:is_sane_ecc(openssl) of true -> - common_init_per_group(erlang_client, [{server_type, openssl}, - {client_type, erlang} | Config]); + common_init_per_group(Group, [{server_type, openssl}, + {client_type, erlang} | Config]); false -> {skip, "Known ECC bug in openssl"} end; -init_per_group(erlang_server, Config) -> +init_per_group(erlang_server = Group, Config) -> case ssl_test_lib:is_sane_ecc(openssl) of true -> - common_init_per_group(erlang_client, [{server_type, erlang}, - {client_type, openssl} | Config]); + common_init_per_group(Group, [{server_type, erlang}, + {client_type, openssl} | Config]); false -> {skip, "Known ECC bug in openssl"} end; @@ -99,11 +109,21 @@ init_per_group(erlang_server, Config) -> init_per_group(erlang = Group, Config) -> case ssl_test_lib:sufficient_crypto_support(Group) of true -> - common_init_per_group(erlang, [{server_type, erlang}, - {client_type, erlang} | Config]); + common_init_per_group(Group, [{server_type, erlang}, + {client_type, erlang} | Config]); + false -> + {skip, "Crypto does not support ECC"} + end; + +init_per_group(openssl = Group, Config) -> + case ssl_test_lib:sufficient_crypto_support(Group) of + true -> + common_init_per_group(Group, [{server_type, openssl}, + {client_type, openssl} | Config]); false -> {skip, "Crypto does not support ECC"} - end; + end; + init_per_group(Group, Config) -> common_init_per_group(Group, Config). @@ -121,76 +141,118 @@ end_per_group(_GroupName, Config) -> %%-------------------------------------------------------------------- -init_per_testcase(_TestCase, Config) -> +init_per_testcase(TestCase, Config) -> ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]), + end_per_testcase(TestCase, Config), + ssl:start(), Config. -end_per_testcase(_TestCase, Config) -> +end_per_testcase(_TestCase, Config) -> + application:stop(ssl), Config. %%-------------------------------------------------------------------- %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- -client_ec_server_ec(Config) when is_list(Config) -> - basic_test("ec1.crt", "ec1.key", "ec2.crt", "ec2.key", Config). - -client_ec_server_rsa(Config) when is_list(Config) -> - basic_test("ec1.crt", "ec1.key", "rsa1.crt", "rsa1.key", Config). +client_ecdh_server_ecdh(Config) when is_list(Config) -> + COpts = ?config(client_ecdh_rsa_opts, Config), + SOpts = ?config(server_ecdh_rsa_verify_opts, Config), + basic_test(COpts, SOpts, Config). + +client_ecdh_server_rsa(Config) when is_list(Config) -> + COpts = ?config(client_ecdh_rsa_opts, Config), + SOpts = ?config(server_verification_opts, Config), + basic_test(COpts, SOpts, Config). + +client_rsa_server_ecdh(Config) when is_list(Config) -> + COpts = ?config(client_verification_opts, Config), + SOpts = ?config(server_ecdh_rsa_verify_opts, Config), + basic_test(COpts, SOpts, Config). + +client_rsa_server_rsa(Config) when is_list(Config) -> + COpts = ?config(client_verification_opts, Config), + SOpts = ?config(server_verification_opts, Config), + basic_test(COpts, SOpts, Config). + +client_ecdsa_server_ecdsa(Config) when is_list(Config) -> + COpts = ?config(client_ecdsa_opts, Config), + SOpts = ?config(server_ecdsa_verify_opts, Config), + basic_test(COpts, SOpts, Config). -client_rsa_server_ec(Config) when is_list(Config) -> - basic_test("rsa1.crt", "rsa1.key", "ec2.crt", "ec2.key", Config). +client_ecdsa_server_rsa(Config) when is_list(Config) -> + COpts = ?config(client_ecdsa_opts, Config), + SOpts = ?config(server_verification_opts, Config), + basic_test(COpts, SOpts, Config). -client_rsa_server_rsa(Config) when is_list(Config) -> - basic_test("rsa1.crt", "rsa1.key", "rsa2.crt", "rsa2.key", Config). +client_rsa_server_ecdsa(Config) when is_list(Config) -> + COpts = ?config(client_verification_opts, Config), + SOpts = ?config(server_ecdsa_verify_opts, Config), + basic_test(COpts, SOpts, Config). %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- -basic_test(ClientCert, ClientKey, ServerCert, ServerKey, Config) -> - DataDir = ?config(data_dir, Config), +basic_test(COpts, SOpts, Config) -> + basic_test(proplists:get_value(certfile, COpts), + proplists:get_value(keyfile, COpts), + proplists:get_value(cacertfile, COpts), + proplists:get_value(certfile, SOpts), + proplists:get_value(keyfile, SOpts), + proplists:get_value(cacertfile, SOpts), + Config). + +basic_test(ClientCert, ClientKey, ClientCA, ServerCert, ServerKey, ServerCA, Config) -> SType = ?config(server_type, Config), CType = ?config(client_type, Config), {Server, Port} = start_server(SType, - filename:join(DataDir, "CA.pem"), - filename:join(DataDir, ServerCert), - filename:join(DataDir, ServerKey), + ClientCA, ServerCA, + ServerCert, + ServerKey, Config), - Client = start_client(CType, Port, filename:join(DataDir, "CA.pem"), - filename:join(DataDir, ClientCert), - filename:join(DataDir, ClientKey), Config), - check_result(Server, SType, Client, CType). + Client = start_client(CType, Port, ServerCA, ClientCA, + ClientCert, + ClientKey, Config), + check_result(Server, SType, Client, CType), + close(Server, Client). -start_client(openssl, Port, CA, Cert, Key, _) -> +start_client(openssl, Port, CA, OwnCa, Cert, Key, Config) -> + PrivDir = ?config(priv_dir, Config), + NewCA = new_ca(filename:join(PrivDir, "new_ca.pem"), CA, OwnCa), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ Cert ++ " -CAfile " ++ CA - ++ " -key " ++ Key ++ " -host localhost -msg", + Cmd = "openssl s_client -verify 2 -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ + " -cert " ++ Cert ++ " -CAfile " ++ NewCA + ++ " -key " ++ Key ++ " -host localhost -msg -debug", OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), true = port_command(OpenSslPort, "Hello world"), OpenSslPort; -start_client(erlang, Port, CA, Cert, Key, Config) -> +start_client(erlang, Port, CA, _, Cert, Key, Config) -> {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, - {options, [{verify, verify_peer}, {cacertfile, CA}, + {options, [{verify, verify_peer}, + {cacertfile, CA}, {certfile, Cert}, {keyfile, Key}]}]). -start_server(openssl, CA, Cert, Key, _) -> +start_server(openssl, CA, OwnCa, Cert, Key, Config) -> + PrivDir = ?config(priv_dir, Config), + NewCA = new_ca(filename:join(PrivDir, "new_ca.pem"), CA, OwnCa), + Port = ssl_test_lib:inet_port(node()), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ Cert ++ " -CAfile " ++ CA - ++ " -key " ++ Key ++ " -Verify 2 -msg", + " -verify 2 -cert " ++ Cert ++ " -CAfile " ++ NewCA + ++ " -key " ++ Key ++ " -msg -debug", OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), ssl_test_lib:wait_for_openssl_server(), true = port_command(OpenSslPort, "Hello world"), {OpenSslPort, Port}; -start_server(erlang, CA, Cert, Key, Config) -> +start_server(erlang, CA, _, Cert, Key, Config) -> + {_, ServerNode, _} = ssl_test_lib:run_where(Config), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, @@ -217,9 +279,31 @@ openssl_check(_, Config) -> TLSVersion = ?config(tls_version, Config), case ssl_test_lib:check_sane_openssl_version(TLSVersion) of true -> - ssl:start(), Config; false -> {skip, "TLS version not supported by openssl"} end. +close(Port1, Port2) when is_port(Port1), is_port(Port2) -> + ssl_test_lib:close_port(Port1), + ssl_test_lib:close_port(Port2); +close(Port, Pid) when is_port(Port) -> + ssl_test_lib:close_port(Port), + ssl_test_lib:close(Pid); +close(Pid, Port) when is_port(Port) -> + ssl_test_lib:close_port(Port), + ssl_test_lib:close(Pid); +close(Client, Server) -> + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%% Work around OpenSSL bug, apparently the same bug as we had fixed in +%% 11629690ba61f8e0c93ef9b2b6102fd279825977 +new_ca(FileName, CA, OwnCa) -> + {ok, P1} = file:read_file(CA), + E1 = public_key:pem_decode(P1), + {ok, P2} = file:read_file(OwnCa), + E2 = public_key:pem_decode(P2), + Pem = public_key:pem_encode(E2 ++E1), + file:write_file(FileName, Pem), + FileName. diff --git a/lib/ssl/test/ssl_ECC_SUITE_data/CA.pem b/lib/ssl/test/ssl_ECC_SUITE_data/CA.pem deleted file mode 100644 index f82efdefc5..0000000000 --- a/lib/ssl/test/ssl_ECC_SUITE_data/CA.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICGjCCAYegAwIBAgIQZIIqq4RXfpBKJXV69Jc4BjAJBgUrDgMCHQUAMB0xGzAZ -BgNVBAMTEklTQSBUZXN0IEF1dGhvcml0eTAeFw0xMjAzMjAxNzEzMjFaFw0zOTEy -MzEyMzU5NTlaMB0xGzAZBgNVBAMTEklTQSBUZXN0IEF1dGhvcml0eTCBnzANBgkq -hkiG9w0BAQEFAAOBjQAwgYkCgYEAqnt6FSyFQVSDyP7mY63IhCzgysTxBEg1qDb8 -nBHj9REReZA5UQ5iyEOdTbdLyOaSk2rJyA2wdTjYkNnLzK49nZFlpf89r3/bakAM -wZv69S3FJi9W2z9m4JPv/5+QCYnFNRSnnHw3maNElwoQyknx96I3W7EuVOvKtKhh -4DaD0WsCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zBOBgNVHQEERzBFgBBCHwn2 -8AmbN+cvJl1iJ1bsoR8wHTEbMBkGA1UEAxMSSVNBIFRlc3QgQXV0aG9yaXR5ghBk -giqrhFd+kEoldXr0lzgGMAkGBSsOAwIdBQADgYEAIlVecua5Cr1z/cdwQ8znlgOU -U+y/uzg0nupKkopzVnRYhwV4hxZt3izAz4C/SJZB7eL0bUKlg1ceGjbQsGEm0fzF -LEV3vym4G51bxv03Iecwo96G4NgjJ7+9/7ciBVzfxZyfuCpYG1M2LyrbOyuevtTy -2+vIueT0lv6UftgBfIE= ------END CERTIFICATE----- diff --git a/lib/ssl/test/ssl_ECC_SUITE_data/ec1.crt b/lib/ssl/test/ssl_ECC_SUITE_data/ec1.crt deleted file mode 100644 index 7d2b9cde9d..0000000000 --- a/lib/ssl/test/ssl_ECC_SUITE_data/ec1.crt +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBhjCB8AIBBjANBgkqhkiG9w0BAQUFADAdMRswGQYDVQQDExJJU0EgVGVzdCBB -dXRob3JpdHkwHhcNMTMwODA4MTAxNDI3WhcNMjMwODA2MTAxNDI3WjBFMQswCQYD -VQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWExFTATBgNVBAcTDEZvcnQgQmVsdm9p -cjEMMAoGA1UEAxMDZWMxMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEpiRIxUCESROR -P8IByg+vBv1fDdAg7yXfAh95GxFtvhBqZs6ATwaRKyLmZYgUm/4NUAyUeqmTBb7s -2msKo5mnNzANBgkqhkiG9w0BAQUFAAOBgQAmwzoB1DVO69FQOUdBVnyups4t0c1c -8h+1z/5P4EtPltk4o3mRn0AZogqdXCpNbuSGbSJh+dep5xW30VLxNHdc+tZSLK6j -pT7A3hymMk8qbi13hxeH/VpEP25y1EjHowow9Wmb6ebtT/v7qFQ9AAHD9ONcIM4I -FCC8vdFo7M5GgQ== ------END CERTIFICATE----- diff --git a/lib/ssl/test/ssl_ECC_SUITE_data/ec1.key b/lib/ssl/test/ssl_ECC_SUITE_data/ec1.key deleted file mode 100644 index 2dc9508b3c..0000000000 --- a/lib/ssl/test/ssl_ECC_SUITE_data/ec1.key +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN EC PARAMETERS----- -BgUrgQQACg== ------END EC PARAMETERS----- ------BEGIN EC PRIVATE KEY----- -MHQCAQEEIOO0WK8znNzLyZIoGRIlaKnCNr2Wy8uk9i+GGFIhDGNAoAcGBSuBBAAK -oUQDQgAEpiRIxUCESRORP8IByg+vBv1fDdAg7yXfAh95GxFtvhBqZs6ATwaRKyLm -ZYgUm/4NUAyUeqmTBb7s2msKo5mnNw== ------END EC PRIVATE KEY----- diff --git a/lib/ssl/test/ssl_ECC_SUITE_data/ec2.crt b/lib/ssl/test/ssl_ECC_SUITE_data/ec2.crt deleted file mode 100644 index b0558a0ebc..0000000000 --- a/lib/ssl/test/ssl_ECC_SUITE_data/ec2.crt +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBhjCB8AIBBzANBgkqhkiG9w0BAQUFADAdMRswGQYDVQQDExJJU0EgVGVzdCBB -dXRob3JpdHkwHhcNMTMwODA4MTAxNDM0WhcNMjMwODA2MTAxNDM0WjBFMQswCQYD -VQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWExFTATBgNVBAcTDEZvcnQgQmVsdm9p -cjEMMAoGA1UEAxMDZWMyMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzXaYReUyvoYl -FwGOe0MJEXWCUncMfr2xG4GMjGYlfZsvLGEokefsJIvW+I+9jgUT2UFjxFXYNAvm -uD1A1iWVWjANBgkqhkiG9w0BAQUFAAOBgQBFa6iIlrT9DWptIdB8uSYvp7qwiHxN -hiVH5YhGIHHqjGZqtRHrSxqNEYMXXrgH9Hxc6gDbk9PsHZyVVoh/HgVWddqW1inh -tStZm420PAKCuH4T6Cfsk76GE2m7FRzJvw9TM1f2A5nIy9abyrpup8lZGcIL4Kmq -1Fix1LRtrmLNTA== ------END CERTIFICATE----- diff --git a/lib/ssl/test/ssl_ECC_SUITE_data/ec2.key b/lib/ssl/test/ssl_ECC_SUITE_data/ec2.key deleted file mode 100644 index 366d13648b..0000000000 --- a/lib/ssl/test/ssl_ECC_SUITE_data/ec2.key +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN EC PARAMETERS----- -BgUrgQQACg== ------END EC PARAMETERS----- ------BEGIN EC PRIVATE KEY----- -MHQCAQEEIPR3ORUpAFMTQhUJ0jllN38LKWziG8yP2H54Y/9vh1PwoAcGBSuBBAAK -oUQDQgAEzXaYReUyvoYlFwGOe0MJEXWCUncMfr2xG4GMjGYlfZsvLGEokefsJIvW -+I+9jgUT2UFjxFXYNAvmuD1A1iWVWg== ------END EC PRIVATE KEY----- diff --git a/lib/ssl/test/ssl_ECC_SUITE_data/rsa1.crt b/lib/ssl/test/ssl_ECC_SUITE_data/rsa1.crt deleted file mode 100644 index ed9beacf68..0000000000 --- a/lib/ssl/test/ssl_ECC_SUITE_data/rsa1.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDVjCCAr8CAQkwDQYJKoZIhvcNAQEFBQAwHTEbMBkGA1UEAxMSSVNBIFRlc3Qg -QXV0aG9yaXR5MB4XDTEzMDgwODEwMTUzNFoXDTQwMTIyNDEwMTUzNFowRjELMAkG -A1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMRUwEwYDVQQHEwxGb3J0IEJlbHZv -aXIxDTALBgNVBAMTBHJzYTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQC62v40w1AjV3oJuyYC2Fw6XhTOi1il6xZFnB9J1WhCmuxAB/VMhBcNypx38mNk -eQ7a/ERQ5ddhZey29DYeFYU8oqfDURgWx5USHufb90xBen9KPmX3VNuQ8ZFP2q8Q -b01/oRHBJQRBuaCtFHzpGIVBjC6dD5yeQgJsYaF4u+PBbonsIGROXMybcvUzXmjU -dwpy2NhjGQL5sWcOdIeRP43APSyRYvq4tuBUZk2XxWfBcvA8LpcoYPMlRTf6jGL1 -/fAAcCYJ9lh3h92w0NZ/7ZRa/ebTplxK6yqCftuSKui1KdL69m0WZqHl79AUSfs9 -lsOwx9lHkyYvJeMofyeDbZ+3OYLmVqEBG1fza2aV2XVh9zJ8fAwmXy/c2IDhw/oD -HAe/rSg/Sgt03ydIKqtZHbl3v0EexQQRlJRULIzdtON02dJMUd4EFUgQ9OUtEmC2 -Psj9Jdu1g5cevU7Mymu8Ot+fjHiGTcBUsXNuXFCbON3Gw7cIDl4+iv+cpDHHVC9L -HK3PMEq3vu3qOGXSz+LDOoqkfROcLG7BclBuN2zoVSsMHFkB4aJhwy7eHhGz0z2W -c6LTVd+GAApdY80kmjOjT//QxHEsX/n1useHza3OszQqZiArr4ub4rtq+l1DxAS/ -DWrZ/JGsbKL8cjWso6qBF94xTi8WhjkKuUYhsm+qLAbNOQIDAQABMA0GCSqGSIb3 -DQEBBQUAA4GBAIcuzqRkfypV/9Z85ZQCCoejPm5Urhv7dfg1/B3QtazogPBZLgL5 -e60fG1uAw5GmqTViHLvW06z73oQvJrFkrCLVvadDNtrKYKXnXqdkgVyk36F/B737 -A43HGnMfSxCfRhIOuKZB9clP5PiNlhw36yi3DratqT6TUvI69hg8a7jA ------END CERTIFICATE----- diff --git a/lib/ssl/test/ssl_ECC_SUITE_data/rsa1.key b/lib/ssl/test/ssl_ECC_SUITE_data/rsa1.key deleted file mode 100644 index 6e0d913d79..0000000000 --- a/lib/ssl/test/ssl_ECC_SUITE_data/rsa1.key +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKAIBAAKCAgEAutr+NMNQI1d6CbsmAthcOl4UzotYpesWRZwfSdVoQprsQAf1 -TIQXDcqcd/JjZHkO2vxEUOXXYWXstvQ2HhWFPKKnw1EYFseVEh7n2/dMQXp/Sj5l -91TbkPGRT9qvEG9Nf6ERwSUEQbmgrRR86RiFQYwunQ+cnkICbGGheLvjwW6J7CBk -TlzMm3L1M15o1HcKctjYYxkC+bFnDnSHkT+NwD0skWL6uLbgVGZNl8VnwXLwPC6X -KGDzJUU3+oxi9f3wAHAmCfZYd4fdsNDWf+2UWv3m06ZcSusqgn7bkirotSnS+vZt -Fmah5e/QFEn7PZbDsMfZR5MmLyXjKH8ng22ftzmC5lahARtX82tmldl1YfcyfHwM -Jl8v3NiA4cP6AxwHv60oP0oLdN8nSCqrWR25d79BHsUEEZSUVCyM3bTjdNnSTFHe -BBVIEPTlLRJgtj7I/SXbtYOXHr1OzMprvDrfn4x4hk3AVLFzblxQmzjdxsO3CA5e -Por/nKQxx1QvSxytzzBKt77t6jhl0s/iwzqKpH0TnCxuwXJQbjds6FUrDBxZAeGi -YcMu3h4Rs9M9lnOi01XfhgAKXWPNJJozo0//0MRxLF/59brHh82tzrM0KmYgK6+L -m+K7avpdQ8QEvw1q2fyRrGyi/HI1rKOqgRfeMU4vFoY5CrlGIbJvqiwGzTkCAwEA -AQKCAgBkXyaWKSRvF5pSh9lPRfGk2MzMdkXUOofoNIkKHDy5KocljiDSTVIk8mVC -eU2ytuSn9UKtQgmEJEAXtu8rEdxUSftcC7+o3OTSqw9ZNWoc8jRWKVaUmVyoa1rn -Tk0jwuYaXOcwnTXAKHqK/qpqe+V45FhVvgEfcc3jcj5OoH8jdMFZubyn62ltRz83 -rMsa9icCskDqWpEil40IUshP2ZfHYBUEs+qCNpoiPCIKGNw3KgqqCUzhP9LcfmYn -jCnMge/eDGAikdXLv4vyYvwWFATRK/pGTuLcy542IvbHeY0vY5wVezH2CoOFBGD9 -xQ/UcZwE5hVtQToNsYhoRIVxL/3Of0qDk1M6W2Plh2MAstyejIHE3ct0pPfW3rsu -j/9Z/H0P9Q5ghSjarwOp2qGrrz6/4LVbbTDY8V1L928l4SqbUMtEQxcxTBN8YFoD -mPV3Jc3zls9wiiEX53RcH8MK5tjrcRwWqurTZvi/pkLfXlGDgKGCOaa3HgWVQyU+ -L6jVZM+u1nwN+jNXQYGeLEro/6tvG8WQbRMHQoxLG+rm4V3/SwH0DcfrVFDTg+i6 -3wMU1GC/aQEdTFWXvHAkpwrf4M9QWvjtheiaSxtBUoAY6l+ixCVHKrIk6glKLEjx -92HxmcJdopQScFETAyg8eVKV0kOGfVeFEpIqwq7hVedmTflpQQKCAQEA44h4dAta -cYeBqBr8eljWcgs79gmgwBEQxQUnwE/zuzLKn5NxAW324Kh25V/n/MupUzBlLPWn -91UHfw9PCXT8/HvgYQ4S5sXbKRbGmuPSsTmz4Rfe2ix6RggVNUOwORVNDyM7SQh7 -USdzZH5dMxKfF5L/b4Byx7eQZaoeKlfaXcqgikNZZ6pkhVCNxUKi9vvjS9r2wwCd -xtgu5MfTpdEci0zH1+uuRisVRcEbcRX9umUTCiZrmEeddZXNiwTAS3FtX7qGzuq9 -LKIeETwcOZrWj0E48UvbSfK4Axn7sf5J0n7/Qo7I089S5QQEI6ZDP501i71dNFhn -qfcY30c1k3TC7QKCAQEA0juuVHExKNLLNmQejNPfuHYoH0Uk2BH/8x96/Mkj6k6K -SUCHDS3iWOljXGw8YtpS8v5mGBGgMhJ+s/vCRM6R9eXYTc8u2ktY/kjyW0PgW8/Z -vb9VrQpn5svTNwj2Q8qYsTqXnQKO7YuL+hnQpQNAcID6FTeOASVLGObEf810qRfN -4y3RqCWUnYXXTyXj+cJdbXTxfF7HVZPIAQKqE7J5Qo9ynYILY62oSmUGC6m8VKyE -rrvDMK1IVi0X4w+Jx4HX0IC2+DBKxCaLWT69bE1IwjB06Q5zoTQPVi6c6qQp7K0H -kqSyLJ/ctwcEubu0DPNmvMlgWtAbAsoESA5GbIit/QKCAQEAxRzp9OYNAUM6AK74 -QOmLRZsT4+6tUxa1p2jy6fiZlnfG731kra9c630mG0n9iJPK6aWIUO20CGGiL+HM -P84YiIaseIgfucp4NV1kyrRJR31MptjuF6Xme5ru/IjaNmmMq2uDJZ7ybfi2T73k -8aTVLDANl8P4K6qLrnc00MvxAcXTVFRKNLN5h8CkQNqcoUjPvVxA3+g9xxBrd4jh -gsnoZ4kpq5WiEWmrcRV8t3gsqfh8CRQFrBOGhmIzgZapG/J0pTTLKqBTKEJ9t8KS -VRkdfVcshGWJ4MMjxJQS5zz7KR8Z9cgKlOwLzRiwmU2k/owr4hY3k2xuyeClrHBd -KpRBdQKCAQBvDk/dE55gbloi9WieBB6eluxC+IeqDHgkunCBsM9kKvEqGQg+kgqL -5V4zqImNvr8q1fCgrk7tpI+CDHBnYKgCOdS15cheUIdGbMp6I7UVSws/DR/5NRIF -/Y4p+HX/Abr/hHAq5PsTyS+8gn6RbNJRnBB/vMUrHcQ5902+JY6G9KgyZjXmmVOU -kutWSDHR8jbgZ3JZvMeYEWUKA5pMpW8hFh35zoStt0K7afpzlsqCAFBm7ZEC2cbo -nxGLRN4HojObVSNSoFAepi3eiyINYBYbXvWjV5sFgTbI0/7YhLgQ6qahdJcas6go -l3CLnPhUDxAqkkZwMpbSNl1kowXYt6sRAoIBAAOWnXgf9Bdb9OWKGgt42gVfC4cz -zj2JoLpbDTtbEdHNn8XQvPhGbpdtgnsuEMijIMy1UTlmv17jbFWdZTDeN31EUJrC -smgKX0OlVFKD90AI0BiIREK0hJUBV0pV4JoUjwnQBHGvranD06/wAtHEqgqF1Ipp -DCAKwxggM7qtB1R1vkrc/aLQej+mlwA8N6q92rnEsg+EnEbhtLDDZQcV/q5cSDCN -MMcnM+QdyjKwEeCVXHaqNfeSqKg/Ab2eZbS9VxA+XZD73+eUY/JeJsg7LfZrRz0T -ij5LCS7A+nVB5/B5tGkk4fcNhk2n356be6l46S98BEgtuwGLC9pqXf7zyp4= ------END RSA PRIVATE KEY----- diff --git a/lib/ssl/test/ssl_ECC_SUITE_data/rsa2.crt b/lib/ssl/test/ssl_ECC_SUITE_data/rsa2.crt deleted file mode 100644 index 06ca92dda3..0000000000 --- a/lib/ssl/test/ssl_ECC_SUITE_data/rsa2.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDVjCCAr8CAQowDQYJKoZIhvcNAQEFBQAwHTEbMBkGA1UEAxMSSVNBIFRlc3Qg -QXV0aG9yaXR5MB4XDTEzMDgwODEwMTYwMloXDTQwMTIyNDEwMTYwMlowRjELMAkG -A1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMRUwEwYDVQQHEwxGb3J0IEJlbHZv -aXIxDTALBgNVBAMTBHJzYTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCjQUe0BGOpULjOAmLbXM4SSQzJvxJbCFi3tryyd+OARq6Fdp6/fslVhsr0PhWE -X8yRbAugIjseTpLwz+1OC6LavOGV1ixzGTI/9HDXGKbf8qoCrSdh28sqQJnmqGT4 -UCKLn6Rqjg2iyBBcSK3LrtKEPI4C7NaSOZUtANkppvziEMwm+0r16sgHh2Xx6mxd -22q01kq1lJqwEnIDPMSz3+ESUVQQ4T3ka7yFIhc9PYmILIXkZi0x7AiDeRkIILul -GQrduTWSPGY3prXeDAbmQNazxrHp8fcR2AfFSI6HYxMALq9jWxc4xDIkss6BO2Et -riJOIgXFpbyVsYCbkI1kXhEWFDt3uJBIcmtJKGzro4xv+XLG6BbUeTJgSHXMc7Cb -fX87+CBIFR5a/aqkEKh/mcvsDdaV+kpNKdr7q4wAuIQb8g7IyXEDuAm1VZjQs9WC -KFRGSq9sergEw9gna0iThRZjD+dzNzB17XmlAK4wa98a7MntwqpAt/GsCFOiPM8E -c+8gpuo8WqC0kP8OpImyw9cQhlZ3dca1qkr2cyKyAOGxUxyA67FgiHSsxJJ2Xhse -o49qeKTjMZd8zhSokM2TH6qEf7YfOePU51YRfAHUhzRmE31N/MExqDjFjklksEtM -iHhbPo+cOoxV8x1u13umdUvtTaAUSBA/DpvzWdnORvnaqQIDAQABMA0GCSqGSIb3 -DQEBBQUAA4GBAFD+O7h+5R5S1rIN9eC+oEGpvRhMG4v4G3pJp+c7bbtO7ifFx1WP -bta1b5YtiQYcKP0ORABm/3Kcvsb3VbaMH/zkxWEbASZsmIcBY3ml4f2kkn6WT2hD -Wc6VMIAR3N6Mj1b30yI1qYVIid+zIouiykMB+zqllm+Uar0SPNjKxDU/ ------END CERTIFICATE----- diff --git a/lib/ssl/test/ssl_ECC_SUITE_data/rsa2.key b/lib/ssl/test/ssl_ECC_SUITE_data/rsa2.key deleted file mode 100644 index d415ef0391..0000000000 --- a/lib/ssl/test/ssl_ECC_SUITE_data/rsa2.key +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJJwIBAAKCAgEAo0FHtARjqVC4zgJi21zOEkkMyb8SWwhYt7a8snfjgEauhXae -v37JVYbK9D4VhF/MkWwLoCI7Hk6S8M/tTgui2rzhldYscxkyP/Rw1xim3/KqAq0n -YdvLKkCZ5qhk+FAii5+kao4NosgQXEity67ShDyOAuzWkjmVLQDZKab84hDMJvtK -9erIB4dl8epsXdtqtNZKtZSasBJyAzzEs9/hElFUEOE95Gu8hSIXPT2JiCyF5GYt -MewIg3kZCCC7pRkK3bk1kjxmN6a13gwG5kDWs8ax6fH3EdgHxUiOh2MTAC6vY1sX -OMQyJLLOgTthLa4iTiIFxaW8lbGAm5CNZF4RFhQ7d7iQSHJrSShs66OMb/lyxugW -1HkyYEh1zHOwm31/O/ggSBUeWv2qpBCof5nL7A3WlfpKTSna+6uMALiEG/IOyMlx -A7gJtVWY0LPVgihURkqvbHq4BMPYJ2tIk4UWYw/nczcwde15pQCuMGvfGuzJ7cKq -QLfxrAhTojzPBHPvIKbqPFqgtJD/DqSJssPXEIZWd3XGtapK9nMisgDhsVMcgOux -YIh0rMSSdl4bHqOPanik4zGXfM4UqJDNkx+qhH+2Hznj1OdWEXwB1Ic0ZhN9TfzB -Mag4xY5JZLBLTIh4Wz6PnDqMVfMdbtd7pnVL7U2gFEgQPw6b81nZzkb52qkCAwEA -AQKCAgBORLHXwHL3bdfsDIDQooG5ioQzBQQL2MiP63A0L/5GNZzeJ6ycKnDkLCeJ -SWqPeE5fOemo8EBfm1QfV9BxpmqBbCTK7U+KLv5EYzDmLs9ydqjDd7h11iZlL2uZ -hgpCckjdn7/3xfsLm9ccJ0wLZtlOxKlhBaMpn6nBVbLHoWOEDoGR/tBFbjZQRb2+ -aaFirhtOb56Jx6ER4QYAP1Ye1qrVWWBwZ0yBApXzThDOL36MZqwagFISqRK71YcG -uoq78HGhM3ZXkdV/wNFYj3OPWG6W6h/KBVNqnqO7FbofdoRZhghYHgfYE1fm+ELA -+nLwr5eK1gzmYTs0mVELRBZFlEOkCfYNOnuRgysFezEklS+ICp3HzIhYXza3kyTf -B2ZBwZZVCv/94MKyibyANErmv1a5ugY5Hsn9/WKC8qTto+qLYoyFCvBjzj0PSaVX -/3cty2DY0SK16K1Y4AOPtJMYTXYB3tVX8Akgjz1F6REBtZSOXrSQ3Vhy1ORl3Hzf -WCBYDqL8K0hJiBVgkvneIyIjmFHsdM60Nr7EldBEnJ/UrPzsl2VuWFPZlnasfUaW -x+vq1H4Dfz+bHt8coBRHDjKgUvwkfFeBQOBR5DG3vMrxguVRA1EYYMRR5C3yxk2m -ARAtdh4VxUQDQjjrmr7Dl/y1rU34aInXIrrFWpuvIhl8Ht09sQKCAQEA1pXKK5f0 -HkKfM/qk5xzF+WdHClBrPXi0XwLN6UQ+WWMMNhkGZ+FMPXl/6IJDT91s6DA3tPhr -OZF64n9ZFaGgHNBXNiB+Txjv5vZeSBMFt3hSonqt42aijx6gXfmLnkA+TYpa6Wex -YCeEgdH8LocJa7Gj2vzrYliPYk3deh6SnZZ6N8bI+ciwK3ZGF/pkWaTX83dIFq3w -YyZ+0dEpNGbA9812wNVourPg3OfqG3/CdnTfvY1M9KCC3JalpyzQL4Zm5soXF0wj -36C2yTxA02AyFz3TvUIBrvsN6i0gmGfE79+UIp29JYrFRsIgBDt+ze2vQWUz2MX5 -GeX6/yCBgiTXtwKCAQEAwsNf6k2m5Cw+WtuLzzUfBBJCN+t1lrnYJ6lF0HubW6TZ -vX1kBWyc+Rpo4ljr/+f4R9aC/gTEQOmV/hNVZy1RU2dAI8cH+r6JWG9lgif+8h// -5R81txE7gnuK1Na7PmvnQPPN661zsQZ5e1ENPXS3TJmUW/M01JxAMqEQjvAPa/II -H2KjL5NX28k9Hiw9rP6n+qXAfG/LEwXgoVCcehPwfANqQ1l95UgOdKDmjG94dipI -h2DEK70ZbrsgQbT60Wd8I5h0yhiQsik2/bVkqLmcG4SSg0/5cf2vZMApgoH/adUz -rJFdthm7iGPLhwS6fbhXew17Af96FvzfkifUV+cgnwKCAQBNUlYyFSQKz1jMgxFu -kciokNVhWw75bIgaAEmwNz38OZuJ1sSfI+iz8hbr8hxNJ+15UP6RwD3q1YghG2A/ -Uij+mPgD8ftxhvvTDo10jR4vOTUVhP0phq8mwRNqKWRs1ptcl3Egz5NzoWm22bJ0 -FYaIfs8bNq2el2i7NHGM8n1EOZe6h2+dyfno/0pMk5YbUzHZce7Q9UY8g/+InUSq -tCfuYuPaokuFkxGAqDSMSiIJSx3gEI1dTIU69TGlppkxts1XdhSR+YanqyKSKpr1 -T6FdDJNCjAlNQvuFmVM4d5PYF4kqXApu/60MTSD6RXHwxCe1ecEP6G5VLbCew9jG -y33LAoIBAGsWyC9pwQEm/qYwn4AwYjx32acrtX1J9HtiTLvkqzjJvNu/DXcaEHm7 -tr32TNVp9A9z+JS5hDt49Hs+oC/aMCRe2lqRvmZ1y8kvfy4A1eLGC4stDPj65bDK -QzziURRyejYxmCElPz6wI63VlCUdfwgEThn88SiSPY5ZF2SwxJoC+8peDwJCzwVP -cmabxtHPOAfOibciNRPhoHCyhUdunUVjD1O26k1ewGwKaJoBVMgMWdLuNw8hq9FB -3OukGmF3uD9OPbE9rpn3pX/89Dr9y8MpsvG20J6H8Z/BNVHILus/SmlxiIhvP7kv -viIgTHaCHL/RWrhvg+8N3dRcSBqJQFsCggEAFe2TMEq2AlnBn4gsuAOIuZPYKQCg -2a+tl1grQzmNth6AGGQcIqShadICD6SnVMIS64HHV/m18Cuz7GhJ06ZVjXJsHueG -UpTE9wAmI2LxnNkupkLJu+SVcW3N86PujWmQBFpHkd+IRPLS51xjD9W5zLJ7HL4/ -fnKO+B+ZK6Imxbe5C5vJezkGfeOSyQoVtt6MT/XtSKNEGPBX+M6fLKgUMMg2H2Mt -/SsD7DkOzFteKXzaEg/K8oOTpsOPkVDwNl2KErlEqbJv0k7yEVw50mYmsn/OLjh8 -+9EibISwCODbPxB+PhV6u2ue1IvGLRqtsN60lFOvbGn+kSewy9EUVHHQDQ== ------END RSA PRIVATE KEY----- diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 2f440f1f3c..1da4e88077 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -1371,6 +1371,7 @@ tcp_connect_big() -> [{doc,"Test what happens when a tcp tries to connect, i,e. a bad big (ssl) packet is sent first"}]. tcp_connect_big(Config) when is_list(Config) -> + process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), TcpOpts = [binary, {reuseaddr, true}], @@ -1396,7 +1397,9 @@ tcp_connect_big(Config) when is_list(Config) -> {Server, {error, timeout}} -> ct:fail("hangs"); {Server, {error, Error}} -> - ct:log("Error ~p", [Error]) + ct:log("Error ~p", [Error]); + {'EXIT', Server, _} -> + ok end end. diff --git a/lib/ssl/test/ssl_bench.spec b/lib/ssl/test/ssl_bench.spec new file mode 100644 index 0000000000..d2f75b4203 --- /dev/null +++ b/lib/ssl/test/ssl_bench.spec @@ -0,0 +1 @@ +{suites,"../ssl_test",[ssl_bench_SUITE]}. diff --git a/lib/ssl/test/ssl_bench_SUITE.erl b/lib/ssl/test/ssl_bench_SUITE.erl new file mode 100644 index 0000000000..b6b3769922 --- /dev/null +++ b/lib/ssl/test/ssl_bench_SUITE.erl @@ -0,0 +1,366 @@ +%%%------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. 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/.2 +%% +%% 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(ssl_bench_SUITE). +-compile(export_all). +-include_lib("common_test/include/ct_event.hrl"). + +-define(remote_host, "NETMARKS_REMOTE_HOST"). + +suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}]. + +all() -> [{group, setup}, {group, payload}]. + +groups() -> + [{setup, [{repeat, 3}], [setup_sequential, setup_concurrent]}, + {payload, [{repeat, 3}], [payload_simple]} + ]. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, _Config) -> + ok. + +init_per_suite(Config) -> + try + Server = setup(ssl, node()), + [{server_node, Server}|Config] + catch _:_ -> + {skipped, "Benchmark machines only"} + end. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_Func, Conf) -> + Conf. + +end_per_testcase(_Func, _Conf) -> + ok. + + +-define(COUNT, 400). +-define(TC(Cmd), tc(fun() -> Cmd end, ?MODULE, ?LINE)). + +-define(FPROF_CLIENT, false). +-define(FPROF_SERVER, false). +-define(EPROF_CLIENT, false). +-define(EPROF_SERVER, false). +-define(PERCEPT_SERVER, false). + +%% Current numbers gives roughly a testcase per minute on todays hardware.. + +setup_sequential(Config) -> + Server = proplists:get_value(server_node, Config), + Server =/= undefined orelse error(no_server), + {ok, Result} = do_test(ssl, setup_connection, ?COUNT * 20, 1, Server), + ct_event:notify(#event{name = benchmark_data, + data=[{value, Result}, + {suite, "ssl"}, {name, "Sequential setup"}]}), + ok. + +setup_concurrent(Config) -> + Server = proplists:get_value(server_node, Config), + Server =/= undefined orelse error(no_server), + {ok, Result} = do_test(ssl, setup_connection, ?COUNT, 100, Server), + ct_event:notify(#event{name = benchmark_data, + data=[{value, Result}, + {suite, "ssl"}, {name, "Concurrent setup"}]}), + ok. + +payload_simple(Config) -> + Server = proplists:get_value(server_node, Config), + Server =/= undefined orelse error(no_server), + {ok, Result} = do_test(ssl, payload, ?COUNT*300, 10, Server), + ct_event:notify(#event{name = benchmark_data, + data=[{value, Result}, + {suite, "ssl"}, {name, "Payload simple"}]}), + ok. + + +ssl() -> + test(ssl, ?COUNT, node()). + +test(Type, Count, Host) -> + Server = setup(Type, Host), + (do_test(Type, setup_connection, Count * 20, 1, Server)), + (do_test(Type, setup_connection, Count, 100, Server)), + (do_test(Type, payload, Count*300, 10, Server)), + ok. + +do_test(Type, TC, Loop, ParallellConnections, Server) -> + _ = ssl:stop(), + {ok, _} = ensure_all_started(ssl, []), + + {ok, {SPid, Host, Port}} = rpc:call(Server, ?MODULE, setup_server_init, + [Type, TC, Loop, ParallellConnections]), + link(SPid), + Me = self(), + Test = fun(Id) -> + CData = client_init(Me, Type, TC, Host, Port), + receive + go -> + ?FPROF_CLIENT andalso Id =:= 1 andalso + start_profile(fprof, [self(),new]), + ?EPROF_CLIENT andalso Id =:= 1 andalso + start_profile(eprof, [ssl_connection_sup, ssl_manager]), + ok = ?MODULE:TC(Loop, Type, CData), + ?FPROF_CLIENT andalso Id =:= 1 andalso + stop_profile(fprof, "test_connection_client_res.fprof"), + ?EPROF_CLIENT andalso Id =:= 1 andalso + stop_profile(eprof, "test_connection_client_res.eprof"), + Me ! self() + end + end, + Spawn = fun(Id) -> + Pid = spawn(fun() -> Test(Id) end), + receive {Pid, init} -> Pid end + end, + Pids = [Spawn(Id) || Id <- lists:seq(ParallellConnections, 1, -1)], + Run = fun() -> + [Pid ! go || Pid <- Pids], + [receive Pid -> ok end || Pid <- Pids] + end, + {TimeInMicro, _} = timer:tc(Run), + TotalTests = ParallellConnections * Loop, + TestPerSecond = 1000000 * TotalTests div TimeInMicro, + io:format("TC ~p ~p ~p ~p 1/s~n", [TC, Type, ParallellConnections, TestPerSecond]), + unlink(SPid), + SPid ! quit, + {ok, TestPerSecond}. + +server_init(ssl, setup_connection, _, _, Server) -> + {ok, Socket} = ssl:listen(0, ssl_opts(listen)), + {ok, {_Host, Port}} = ssl:sockname(Socket), + {ok, Host} = inet:gethostname(), + ?FPROF_SERVER andalso start_profile(fprof, [whereis(ssl_manager), new]), + %%?EPROF_SERVER andalso start_profile(eprof, [ssl_connection_sup, ssl_manager]), + ?EPROF_SERVER andalso start_profile(eprof, [ssl_manager]), + ?PERCEPT_SERVER andalso percept:profile("/tmp/ssl_server.percept"), + Server ! {self(), {init, Host, Port}}, + Test = fun(TSocket) -> + ok = ssl:ssl_accept(TSocket), + ssl:close(TSocket) + end, + setup_server_connection(Socket, Test); +server_init(ssl, payload, Loop, _, Server) -> + {ok, Socket} = ssl:listen(0, ssl_opts(listen)), + {ok, {_Host, Port}} = ssl:sockname(Socket), + {ok, Host} = inet:gethostname(), + Server ! {self(), {init, Host, Port}}, + Test = fun(TSocket) -> + ok = ssl:ssl_accept(TSocket), + Size = byte_size(msg()), + server_echo(TSocket, Size, Loop), + ssl:close(TSocket) + end, + setup_server_connection(Socket, Test); + +server_init(Type, Tc, _, _, Server) -> + io:format("No server init code for ~p ~p~n",[Type, Tc]), + Server ! {self(), no_init}. + +client_init(Master, ssl, setup_connection, Host, Port) -> + Master ! {self(), init}, + {Host, Port, ssl_opts(connect)}; +client_init(Master, ssl, payload, Host, Port) -> + {ok, Sock} = ssl:connect(Host, Port, ssl_opts(connect)), + Master ! {self(), init}, + Size = byte_size(msg()), + {Sock, Size}; +client_init(_Me, Type, Tc, Host, Port) -> + io:format("No client init code for ~p ~p~n",[Type, Tc]), + {Host, Port}. + +setup_server_connection(LSocket, Test) -> + receive quit -> + ?FPROF_SERVER andalso stop_profile(fprof, "test_server_res.fprof"), + ?EPROF_SERVER andalso stop_profile(eprof, "test_server_res.eprof"), + ?PERCEPT_SERVER andalso stop_profile(percept, "/tmp/ssl_server.percept"), + ok + after 0 -> + case ssl:transport_accept(LSocket, 2000) of + {ok, TSocket} -> spawn_link(fun() -> Test(TSocket) end); + {error, timeout} -> ok + end, + setup_server_connection(LSocket, Test) + end. + +server_echo(Socket, Size, Loop) when Loop > 0 -> + {ok, Msg} = ssl:recv(Socket, Size), + ok = ssl:send(Socket, Msg), + server_echo(Socket, Size, Loop-1); +server_echo(_, _, _) -> ok. + +setup_connection(N, ssl, Env = {Host, Port, Opts}) when N > 0 -> + case ssl:connect(Host, Port, Opts) of + {ok, Sock} -> + ssl:close(Sock), + setup_connection(N-1, ssl, Env); + {error, Error} -> + io:format("Error: ~p (~p)~n",[Error, length(erlang:ports())]), + setup_connection(N, ssl, Env) + end; +setup_connection(_, _, _) -> + ok. + +payload(Loop, ssl, D = {Socket, Size}) when Loop > 0 -> + ok = ssl:send(Socket, msg()), + {ok, _} = ssl:recv(Socket, Size), + payload(Loop-1, ssl, D); +payload(_, _, {Socket, _}) -> + ssl:close(Socket). + +msg() -> + <<"Hello", + 0:(512*8), + "asdlkjsafsdfoierwlejsdlkfjsdf", + 1:(512*8), + "asdlkjsafsdfoierwlejsdlkfjsdf">>. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +setup(_Type, nonode@nohost) -> + exit(dist_not_enabled); +setup(Type, _This) -> + Host = case os:getenv(?remote_host) of + false -> + {ok, This} = inet:gethostname(), + This; + RemHost -> + RemHost + end, + Node = list_to_atom("perf_server@" ++ Host), + SlaveArgs = case init:get_argument(pa) of + {ok, PaPaths} -> + lists:append([" -pa " ++ P || [P] <- PaPaths]); + _ -> [] + end, + %% io:format("Slave args: ~p~n",[SlaveArgs]), + Prog = + case os:find_executable("erl") of + false -> "erl"; + P -> P + end, + io:format("Prog = ~p~n", [Prog]), + + case net_adm:ping(Node) of + pong -> ok; + pang -> + {ok, Node} = slave:start(Host, perf_server, SlaveArgs, no_link, Prog) + end, + Path = code:get_path(), + true = rpc:call(Node, code, set_path, [Path]), + ok = rpc:call(Node, ?MODULE, setup_server, [Type, node()]), + io:format("Client (~p) using ~s~n",[node(), code:which(ssl)]), + (Node =:= node()) andalso restrict_schedulers(client), + Node. + +setup_server(_Type, ClientNode) -> + (ClientNode =:= node()) andalso restrict_schedulers(server), + io:format("Server (~p) using ~s~n",[node(), code:which(ssl)]), + ok. + + +ensure_all_started(App, Ack) -> + case application:start(App) of + ok -> {ok, [App|Ack]}; + {error, {not_started, Dep}} -> + {ok, Ack1} = ensure_all_started(Dep, Ack), + ensure_all_started(App, Ack1); + {error, {already_started, _}} -> + {ok, Ack} + end. + +setup_server_init(Type, Tc, Loop, PC) -> + _ = ssl:stop(), + {ok, _} = ensure_all_started(ssl, []), + Me = self(), + Pid = spawn_link(fun() -> server_init(Type, Tc, Loop, PC, Me) end), + Res = receive + {Pid, {init, Host, Port}} -> {ok, {Pid, Host, Port}}; + {Pid, Error} -> {error, Error} + end, + unlink(Pid), + Res. + +restrict_schedulers(Type) -> + %% We expect this to run on 8 core machine + Extra0 = 1, + Extra = if (Type =:= server) -> -Extra0; true -> Extra0 end, + Scheds = erlang:system_info(schedulers), + erlang:system_flag(schedulers_online, (Scheds div 2) + Extra). + +tc(Fun, Mod, Line) -> + case timer:tc(Fun) of + {_,{'EXIT',Reason}} -> + io:format("Process EXITED ~p:~p \n", [Mod, Line]), + exit(Reason); + {_T,R={error,_}} -> + io:format("Process Error ~p:~p \n", [Mod, Line]), + R; + {T,R} -> + io:format("~p:~p: Time: ~p\n", [Mod, Line, T]), + R + end. + +start_profile(eprof, Procs) -> + profiling = eprof:start_profiling(Procs), + io:format("(E)Profiling ...",[]); +start_profile(fprof, Procs) -> + fprof:trace([start, {procs, Procs}]), + io:format("(F)Profiling ...",[]). + +stop_profile(percept, File) -> + percept:stop_profile(), + percept:analyze(File), + {started, _Host, Port} = percept:start_webserver(), + wx:new(), + wx_misc:launchDefaultBrowser("http://" ++ net_adm:localhost() ++ ":" ++ integer_to_list(Port)), + ok; +stop_profile(eprof, File) -> + profiling_stopped = eprof:stop_profiling(), + eprof:log(File), + io:format(".analysed => ~s ~n",[File]), + eprof:analyze(total), + eprof:stop(); +stop_profile(fprof, File) -> + fprof:trace(stop), + io:format("..collect..",[]), + fprof:profile(), + fprof:analyse([{dest, File},{totals, true}]), + io:format(".analysed => ~s ~n",[File]), + fprof:stop(), + ok. + +ssl_opts(listen) -> + [{backlog, 500} | ssl_opts("server")]; +ssl_opts(connect) -> + [{verify, verify_peer} + | ssl_opts("client")]; +ssl_opts(Role) -> + Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]), + [{active, false}, + {depth, 2}, + {reuseaddr, true}, + {mode,binary}, + {nodelay, true}, + {ciphers, [{dhe_rsa,aes_256_cbc,sha}]}, + {cacertfile, filename:join([Dir, Role, "cacerts.pem"])}, + {certfile, filename:join([Dir, Role, "cert.pem"])}, + {keyfile, filename:join([Dir, Role, "key.pem"])}]. diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl index 5f36842f9e..e5e942ce1b 100644 --- a/lib/ssl/test/ssl_handshake_SUITE.erl +++ b/lib/ssl/test/ssl_handshake_SUITE.erl @@ -38,6 +38,7 @@ all() -> [decode_hello_handshake, decode_supported_elliptic_curves_hello_extension_correctly, decode_unknown_hello_extension_correctly, encode_single_hello_sni_extension_correctly, + decode_single_hello_sni_extension_correctly, select_proper_tls_1_2_rsa_default_hashsign]. %%-------------------------------------------------------------------- @@ -98,6 +99,13 @@ encode_single_hello_sni_extension_correctly(_Config) -> Encoded = ssl_handshake:encode_hello_extensions(Exts), HelloExt = Encoded. +decode_single_hello_sni_extension_correctly(_Config) -> + Exts = #hello_extensions{sni = #sni{hostname = "test.com"}}, + SNI = <<16#00, 16#00, 16#00, 16#0d, 16#00, 16#0b, 16#00, 16#00, 16#08, + $t, $e, $s, $t, $., $c, $o, $m>>, + Decoded = ssl_handshake:decode_hello_extensions(SNI), + Exts = Decoded. + select_proper_tls_1_2_rsa_default_hashsign(_Config) -> % RFC 5246 section 7.4.1.4.1 tells to use {sha1,rsa} as default signature_algorithm for RSA key exchanges {sha, rsa} = ssl_handshake:select_hashsign_algs(undefined, ?rsaEncryption, {3,3}), diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 150b5037d7..74d71263de 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -450,7 +450,7 @@ make_ecdsa_cert(Config) -> {cacertfile, ServerCaCertFile}, {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]}, {server_ecdsa_verify_opts, [{ssl_imp, new},{reuseaddr, true}, - {cacertfile, ClientCaCertFile}, + {cacertfile, ServerCaCertFile}, {certfile, ServerCertFile}, {keyfile, ServerKeyFile}, {verify, verify_peer}]}, {client_ecdsa_opts, [{ssl_imp, new},{reuseaddr, true}, @@ -475,7 +475,7 @@ make_ecdh_rsa_cert(Config) -> {cacertfile, ServerCaCertFile}, {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]}, {server_ecdh_rsa_verify_opts, [{ssl_imp, new},{reuseaddr, true}, - {cacertfile, ClientCaCertFile}, + {cacertfile, ServerCaCertFile}, {certfile, ServerCertFile}, {keyfile, ServerKeyFile}, {verify, verify_peer}]}, {client_ecdh_rsa_opts, [{ssl_imp, new},{reuseaddr, true}, @@ -1136,3 +1136,36 @@ filter_suites(Ciphers0) -> Supported1 = ssl_cipher:filter_suites(Supported0), Supported2 = [ssl:suite_definition(S) || S <- Supported1], [Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported2)]. + +-define(OPENSSL_QUIT, "Q\n"). +close_port(Port) -> + catch port_command(Port, ?OPENSSL_QUIT), + close_loop(Port, 500, false). + +close_loop(Port, Time, SentClose) -> + receive + {Port, {data,Debug}} when is_port(Port) -> + ct:log("openssl ~s~n",[Debug]), + close_loop(Port, Time, SentClose); + {ssl,_,Msg} -> + ct:log("ssl Msg ~s~n",[Msg]), + close_loop(Port, Time, SentClose); + {Port, closed} -> + ct:log("Port Closed~n",[]), + ok; + {'EXIT', Port, Reason} -> + ct:log("Port Closed ~p~n",[Reason]), + ok; + Msg -> + ct:log("Port Msg ~p~n",[Msg]), + close_loop(Port, Time, SentClose) + after Time -> + case SentClose of + false -> + ct:log("Closing port ~n",[]), + catch erlang:port_close(Port), + close_loop(Port, Time, true); + true -> + ct:log("Timeout~n",[]) + end + end. diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index d36e441c7a..942c446ec4 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -226,7 +226,7 @@ basic_erlang_client_openssl_server(Config) when is_list(Config) -> ssl_test_lib:check_result(Client, ok), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client), process_flag(trap_exit, false). @@ -259,7 +259,7 @@ basic_erlang_server_openssl_client(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! ssl_test_lib:close(Server), - close_port(OpenSslPort), + ssl_test_lib:close_port(OpenSslPort), process_flag(trap_exit, false), ok. %%-------------------------------------------------------------------- @@ -298,7 +298,7 @@ erlang_client_openssl_server(Config) when is_list(Config) -> ssl_test_lib:check_result(Client, ok), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client), process_flag(trap_exit, false). @@ -332,11 +332,9 @@ erlang_server_openssl_client(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! ssl_test_lib:close(Server), - close_port(OpenSslPort), + ssl_test_lib:close_port(OpenSslPort), process_flag(trap_exit, false). -%%-------------------------------------------------------------------- - erlang_client_openssl_server_dsa_cert() -> [{doc,"Test erlang server with openssl client"}]. erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) -> @@ -376,7 +374,7 @@ erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) -> ssl_test_lib:check_result(Client, ok), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client), process_flag(trap_exit, false), ok. @@ -414,7 +412,7 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! ssl_test_lib:close(Server), - close_port(OpenSslPort), + ssl_test_lib:close_port(OpenSslPort), process_flag(trap_exit, false). %%-------------------------------------------------------------------- @@ -450,7 +448,7 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! ssl_test_lib:close(Server), - close_port(OpenSslPort), + ssl_test_lib:close_port(OpenSslPort), process_flag(trap_exit, false), ok. @@ -496,7 +494,7 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) -> ssl_test_lib:check_result(Client, ok), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client), process_flag(trap_exit, false), ok. @@ -542,7 +540,7 @@ erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) -> ssl_test_lib:check_result(Client, ok), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client), process_flag(trap_exit, false). %%-------------------------------------------------------------------- @@ -581,7 +579,7 @@ erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! ssl_test_lib:close(Server), - close_port(OpenSslPort), + ssl_test_lib:close_port(OpenSslPort), process_flag(trap_exit, false). %%-------------------------------------------------------------------- @@ -624,7 +622,7 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) -> ssl_test_lib:check_result(Client, ok), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client), process_flag(trap_exit, false). @@ -666,7 +664,7 @@ erlang_client_openssl_server_client_cert(Config) when is_list(Config) -> ssl_test_lib:check_result(Client, ok), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client), process_flag(trap_exit, false). @@ -708,7 +706,7 @@ erlang_server_openssl_client_client_cert(Config) when is_list(Config) -> ssl_test_lib:check_result(Server, ok), %% Clean close down! Server needs to be closed first !! - close_port(OpenSslPort), + ssl_test_lib:close_port(OpenSslPort), ssl_test_lib:close(Server), process_flag(trap_exit, false). @@ -821,7 +819,7 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) -> [{versions, [Version]} | ClientOpts]}]), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client1), process_flag(trap_exit, false), ok. @@ -878,7 +876,7 @@ expired_session(Config) when is_list(Config) -> {from, self()}, {options, ClientOpts}]), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client2), process_flag(trap_exit, false). @@ -1089,7 +1087,7 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) -> Result = ssl_test_lib:wait_for_result(Client, ok), %% Clean close down! Server needs to be closed first !! - close_port(OpenSslPort), + ssl_test_lib:close_port(OpenSslPort), ssl_test_lib:close(Client), Return = case Result of @@ -1136,7 +1134,7 @@ start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, Opens Callback(Client, OpensslPort), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client), process_flag(trap_exit, false). @@ -1175,7 +1173,7 @@ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callbac Callback(Client, OpensslPort), %% Clean close down! Server needs to be closed first !! - close_port(OpensslPort), + ssl_test_lib:close_port(OpensslPort), ssl_test_lib:close(Client), process_flag(trap_exit, false). @@ -1205,7 +1203,7 @@ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callbac ssl_test_lib:close(Server), - close_port(OpenSslPort), + ssl_test_lib:close_port(OpenSslPort), process_flag(trap_exit, false). @@ -1234,7 +1232,7 @@ start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenS ssl_test_lib:close(Server), - close_port(OpenSslPort), + ssl_test_lib:close_port(OpenSslPort), process_flag(trap_exit, false). @@ -1282,39 +1280,6 @@ delayed_send(Socket, [ErlData, OpenSslData]) -> ssl:send(Socket, ErlData), erlang_ssl_receive(Socket, OpenSslData). -close_port(Port) -> - catch port_command(Port, ?OPENSSL_QUIT), - close_loop(Port, 500, false). - -close_loop(Port, Time, SentClose) -> - receive - {Port, {data,Debug}} when is_port(Port) -> - ct:log("openssl ~s~n",[Debug]), - close_loop(Port, Time, SentClose); - {ssl,_,Msg} -> - ct:log("ssl Msg ~s~n",[Msg]), - close_loop(Port, Time, SentClose); - {Port, closed} -> - ct:log("Port Closed~n",[]), - ok; - {'EXIT', Port, Reason} -> - ct:log("Port Closed ~p~n",[Reason]), - ok; - Msg -> - ct:log("Port Msg ~p~n",[Msg]), - close_loop(Port, Time, SentClose) - after Time -> - case SentClose of - false -> - ct:log("Closing port ~n",[]), - catch erlang:port_close(Port), - close_loop(Port, Time, true); - true -> - ct:log("Timeout~n",[]) - end - end. - - server_sent_garbage(Socket) -> receive server_sent_garbage -> diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile index ff77c3eea0..f5d8b2072a 100644 --- a/lib/stdlib/doc/src/Makefile +++ b/lib/stdlib/doc/src/Makefile @@ -76,7 +76,6 @@ XML_REF3_FILES = \ ms_transform.xml \ orddict.xml \ ordsets.xml \ - pg.xml \ pool.xml \ proc_lib.xml \ proplists.xml \ diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml index 2410f1f9b8..0fde763bfb 100644 --- a/lib/stdlib/doc/src/binary.xml +++ b/lib/stdlib/doc/src/binary.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2009</year> - <year>2013</year> + <year>2014</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -450,7 +450,7 @@ store(Binary, GBSet) -> </code> <p>In this example, we chose to copy the binary content before - inserting it in the <c>gb_set()</c> if it references a binary more than + inserting it in the <c>gb_sets:set()</c> if it references a binary more than twice the size of the data we're going to keep. Of course different rules for when copying will apply to different programs.</p> diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml index b9dfff833e..5c96d6e576 100644 --- a/lib/stdlib/doc/src/gen_event.xml +++ b/lib/stdlib/doc/src/gen_event.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -44,6 +44,7 @@ <pre> gen_event module Callback module ---------------- --------------- +gen_event:start gen_event:start_link -----> - gen_event:add_handler @@ -177,7 +178,7 @@ gen_event:stop -----> Module:terminate/2 <name>add_handler(EventMgrRef, Handler, Args) -> Result</name> <fsummary>Add an event handler to a generic event manager.</fsummary> <type> - <v>EventMgr = Name | {Name,Node} | {global,GlobalName} + <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()</v> <v> Name = Node = atom()</v> <v> GlobalName = ViaName = term()</v> @@ -223,7 +224,7 @@ gen_event:stop -----> Module:terminate/2 <name>add_sup_handler(EventMgrRef, Handler, Args) -> Result</name> <fsummary>Add a supervised event handler to a generic event manager.</fsummary> <type> - <v>EventMgr = Name | {Name,Node} | {global,GlobalName} + <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()</v> <v> Name = Node = atom()</v> <v> GlobalName = ViaName = term()</v> @@ -456,19 +457,37 @@ gen_event:stop -----> Module:terminate/2 </func> <func> <name>stop(EventMgrRef) -> ok</name> + <name>stop(EventMgrRef, Reason, Timeout) -> ok</name> <fsummary>Terminate a generic event manager.</fsummary> <type> <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()</v> <v>Name = Node = atom()</v> <v>GlobalName = ViaName = term()</v> + <v>Reason = term()</v> + <v>Timeout = int()>0 | infinity</v> </type> <desc> - <p>Terminates the event manager <c>EventMgrRef</c>. Before - terminating, the event manager will call - <c>Module:terminate(stop,...)</c> for each installed event - handler.</p> - <p>See <c>add_handler/3</c> for a description of the argument.</p> + <p>Orders the event manager <c>EventMgrRef</c> to exit with + the given <c>Reason</c> and waits for it to + terminate. Before terminating, the gen_event will call + <seealso marker="#Module:terminate/2">Module:terminate(stop,...)</seealso> + for each installed event handler.</p> + <p>The function returns <c>ok</c> if the event manager terminates + with the expected reason. Any other reason than <c>normal</c>, + <c>shutdown</c>, or <c>{shutdown,Term}</c> will cause an + error report to be issued using + <seealso marker="kernel:error_logger#format/2">error_logger:format/2</seealso>. + The default <c>Reason</c> is <c>normal</c>.</p> + <p><c>Timeout</c> is an integer greater than zero which + specifies how many milliseconds to wait for the event manager to + terminate, or the atom <c>infinity</c> to wait + indefinitely. The default value is <c>infinity</c>. If the + event manager has not terminated within the specified time, a + <c>timeout</c> exception is raised.</p> + <p>If the process does not exist, a <c>noproc</c> exception + is raised.</p> + <p>See <c>add_handler/3</c> for a description of <c>EventMgrRef</c>.</p> </desc> </func> </funcs> diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml index 1713367bd8..b1bba3eff0 100644 --- a/lib/stdlib/doc/src/gen_fsm.xml +++ b/lib/stdlib/doc/src/gen_fsm.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -43,8 +43,11 @@ <pre> gen_fsm module Callback module -------------- --------------- +gen_fsm:start gen_fsm:start_link -----> Module:init/1 +gen_fsm:stop -----> Module:terminate/3 + gen_fsm:send_event -----> Module:StateName/2 gen_fsm:send_all_state_event -----> Module:handle_event/3 @@ -115,7 +118,7 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 If <c>FsmName={global,GlobalName}</c>, the gen_fsm is registered globally as <c>GlobalName</c> using <c>global:register_name/2</c>. - If <c>EventMgrName={via,Module,ViaName}</c>, the event manager will + If <c>FsmName={via,Module,ViaName}</c>, the gen_fsm will register with the registry represented by <c>Module</c>. The <c>Module</c> callback should export the functions <c>register_name/2</c>, <c>unregister_name/1</c>, @@ -187,6 +190,39 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 </desc> </func> <func> + <name>stop(FsmRef) -> ok</name> + <name>stop(FsmRef, Reason, Timeout) -> ok</name> + <fsummary>Synchronously stop a generic FSM.</fsummary> + <type> + <v>FsmRef = Name | {Name,Node} | {global,GlobalName} + | {via,Module,ViaName} | pid()</v> + <v> Node = atom()</v> + <v> GlobalName = ViaName = term()</v> + <v>Reason = term()</v> + <v>Timeout = int()>0 | infinity</v> + </type> + <desc> + <p>Orders a generic FSM to exit with the given <c>Reason</c> + and waits for it to terminate. The gen_fsm will call + <seealso marker="#Module:terminate/3">Module:terminate/3</seealso> + before exiting.</p> + <p>The function returns <c>ok</c> if the generic FSM terminates + with the expected reason. Any other reason than <c>normal</c>, + <c>shutdown</c>, or <c>{shutdown,Term}</c> will cause an + error report to be issued using + <seealso marker="kernel:error_logger#format/2">error_logger:format/2</seealso>. + The default <c>Reason</c> is <c>normal</c>.</p> + <p><c>Timeout</c> is an integer greater than zero which + specifies how many milliseconds to wait for the generic FSM + to terminate, or the atom <c>infinity</c> to wait + indefinitely. The default value is <c>infinity</c>. If the + generic FSM has not terminated within the specified time, a + <c>timeout</c> exception is raised.</p> + <p>If the process does not exist, a <c>noproc</c> exception + is raised.</p> + </desc> + </func> + <func> <name>send_event(FsmRef, Event) -> ok</name> <fsummary>Send an event asynchronously to a generic FSM.</fsummary> <type> @@ -210,7 +246,7 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 registered at another node, or</item> <item><c>{global,GlobalName}</c>, if the gen_fsm is globally registered.</item> - <item><c>{via,Module,ViaName}</c>, if the event manager is registered + <item><c>{via,Module,ViaName}</c>, if the gen_fsm is registered through an alternative process registry.</item> </list> <p><c>Event</c> is an arbitrary term which is passed as one of @@ -528,7 +564,8 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <c>Module:init/1</c> for a description of <c>Timeout</c> and <c>hibernate</c>.</p> <p>If the function returns <c>{stop,Reason,NewStateData}</c>, the gen_fsm will call - <c>Module:terminate(Reason,NewStateData)</c> and terminate.</p> + <c>Module:terminate(Reason,StateName,NewStateData)</c> and + terminate.</p> </desc> </func> <func> @@ -614,7 +651,8 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <c>{stop,Reason,NewStateData}</c>, any reply to <c>From</c> must be given explicitly using <c>gen_fsm:reply/2</c>. The gen_fsm will then call - <c>Module:terminate(Reason,NewStateData)</c> and terminate.</p> + <c>Module:terminate(Reason,StateName,NewStateData)</c> and + terminate.</p> </desc> </func> <func> diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml index 4c83fde237..a915e567a5 100644 --- a/lib/stdlib/doc/src/gen_server.xml +++ b/lib/stdlib/doc/src/gen_server.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -43,8 +43,11 @@ <pre> gen_server module Callback module ----------------- --------------- +gen_server:start gen_server:start_link -----> Module:init/1 +gen_server:stop -----> Module:terminate/2 + gen_server:call gen_server:multi_call -----> Module:handle_call/3 @@ -113,7 +116,7 @@ gen_server:abcast -----> Module:handle_cast/2 registered globally as <c>GlobalName</c> using <c>global:register_name/2</c>. If no name is provided, the gen_server is not registered. - If <c>EventMgrName={via,Module,ViaName}</c>, the event manager will + If <c>ServerName={via,Module,ViaName}</c>, the gen_server will register with the registry represented by <c>Module</c>. The <c>Module</c> callback should export the functions <c>register_name/2</c>, <c>unregister_name/1</c>, @@ -184,6 +187,40 @@ gen_server:abcast -----> Module:handle_cast/2 </desc> </func> <func> + <name>stop(ServerRef) -> ok</name> + <name>stop(ServerRef, Reason, Timeout) -> ok</name> + <fsummary>Synchronously stop a generic server.</fsummary> + <type> + <v>ServerRef = Name | {Name,Node} | {global,GlobalName} + | {via,Module,ViaName} | pid()</v> + <v> Node = atom()</v> + <v> GlobalName = ViaName = term()</v> + <v>Reason = term()</v> + <v>Timeout = int()>0 | infinity</v> + </type> + <desc> + <p>Orders a generic server to exit with the + given <c>Reason</c> and waits for it to terminate. The + gen_server will call + <seealso marker="#Module:terminate/2">Module:terminate/2</seealso> + before exiting.</p> + <p>The function returns <c>ok</c> if the server terminates + with the expected reason. Any other reason than <c>normal</c>, + <c>shutdown</c>, or <c>{shutdown,Term}</c> will cause an + error report to be issued using + <seealso marker="kernel:error_logger#format/2">error_logger:format/2</seealso>. + The default <c>Reason</c> is <c>normal</c>.</p> + <p><c>Timeout</c> is an integer greater than zero which + specifies how many milliseconds to wait for the server to + terminate, or the atom <c>infinity</c> to wait + indefinitely. The default value is <c>infinity</c>. If the + server has not terminated within the specified time, a + <c>timeout</c> exception is raised.</p> + <p>If the process does not exist, a <c>noproc</c> exception + is raised.</p> + </desc> + </func> + <func> <name>call(ServerRef, Request) -> Reply</name> <name>call(ServerRef, Request, Timeout) -> Reply</name> <fsummary>Make a synchronous call to a generic server.</fsummary> diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index 15e6fdfa9f..5e74616099 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -30,6 +30,106 @@ </header> <p>This document describes the changes made to the STDLIB application.</p> +<section><title>STDLIB 2.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + OTP-11850 fixed filelib:wildcard/1 to work with broken + symlinks. This correction, however, introduced problems + since symlinks were no longer followed for functions like + filelib:ensure_dir/1, filelib:is_dir/1, + filelib:file_size/1, etc. This is now corrected.</p> + <p> + Own Id: OTP-12054 Aux Id: seq12660 </p> + </item> + </list> + </section> + +</section> + +<section><title>STDLIB 2.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p><c>filelib:wildcard("broken_symlink")</c> would return + an empty list if "broken_symlink" was a symlink that did + not point to an existing file.</p> + <p> + Own Id: OTP-11850 Aux Id: seq12571 </p> + </item> + <item> + <p><c>erl_tar</c> can now handle files names that contain + Unicode characters. See "UNICODE SUPPORT" in the + documentation for <c>erl_tar</c>.</p> + <p>When creating a tar file, <c>erl_tar</c> would + sometime write a too short end of tape marker. GNU tar + would correctly extract files from such tar file, but + would complain about "A lone zero block at...".</p> + <p> + Own Id: OTP-11854</p> + </item> + <item> + <p> When redefining and exporting the type <c>map()</c> + the Erlang Code Linter (<c>erl_lint</c>) erroneously + emitted an error. This bug has been fixed. </p> + <p> + Own Id: OTP-11872</p> + </item> + <item> + <p> + Fix evaluation of map updates in the debugger and + erl_eval</p> + <p> + Reported-by: José Valim</p> + <p> + Own Id: OTP-11922</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>The following native functions now bump an appropriate + amount of reductions and yield when out of + reductions:</p> <list> + <item><c>erlang:binary_to_list/1</c></item> + <item><c>erlang:binary_to_list/3</c></item> + <item><c>erlang:bitstring_to_list/1</c></item> + <item><c>erlang:list_to_binary/1</c></item> + <item><c>erlang:iolist_to_binary/1</c></item> + <item><c>erlang:list_to_bitstring/1</c></item> + <item><c>binary:list_to_bin/1</c></item> </list> + <p>Characteristics impact:</p> <taglist> + <tag>Performance</tag> <item>The functions converting + from lists got a performance loss for very small lists, + and a performance gain for very large lists.</item> + <tag>Priority</tag> <item>Previously a process executing + one of these functions effectively got an unfair priority + boost. This priority boost depended on the input size. + The larger the input was, the larger the priority boost + got. This unfair priority boost is now lost. </item> + </taglist> + <p> + Own Id: OTP-11888</p> + </item> + <item> + <p> + Add <c>maps:get/3</c> to maps module. The function will + return the supplied default value if the key does not + exist in the map.</p> + <p> + Own Id: OTP-11951</p> + </item> + </list> + </section> + +</section> + <section><title>STDLIB 2.0</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -343,10 +443,10 @@ "hello"}, % add new associations</c></item> <item><c>#{ "hi" := V1, a := V2, b := V3} = M2. % match keys with values</c></item> </taglist></p> - <p> - For information on how to use Maps please see the - <seealso marker="doc/reference_manual:maps">Reference - Manual</seealso>.</p> + <p> + For information on how to use Maps please see Map Expressions in the + <seealso marker="doc/reference_manual:expressions#map_expressions"> + Reference Manual</seealso>.</p> <p> The current implementation is without the following features: <taglist> <item>No variable keys</item> @@ -2193,7 +2293,7 @@ platforms than before. If <c>configure</c> warns about no atomic implementation available, try using the <c>libatomic_ops</c> library. Use the <seealso - marker="doc/installation_guide:INSTALL#How-to-Build-and-Install-ErlangOTP_A-Closer-Look-at-the-individual-Steps_Configuring">--with-libatomic_ops=PATH</seealso> + marker="doc/installation_guide:INSTALL#Advanced-configuration-and-build-of-ErlangOTP">--with-libatomic_ops=PATH</seealso> <c>configure</c> command line argument when specifying where the <c>libatomic_ops</c> installation is located. The <c>libatomic_ops</c> library can be downloaded from: @@ -2211,7 +2311,7 @@ the pentium 4 processor. If you want the runtime system to be compatible with older processors (back to 486) you need to pass the <seealso - marker="doc/installation_guide:INSTALL#How-to-Build-and-Install-ErlangOTP_A-Closer-Look-at-the-individual-Steps_Configuring">--enable-ethread-pre-pentium4-compatibility</seealso> + marker="doc/installation_guide:INSTALL#Advanced-configuration-and-build-of-ErlangOTP">--enable-ethread-pre-pentium4-compatibility</seealso> <c>configure</c> command line argument when configuring the system.</p> <p> diff --git a/lib/stdlib/doc/src/pg.xml b/lib/stdlib/doc/src/pg.xml deleted file mode 100644 index a3b69884b6..0000000000 --- a/lib/stdlib/doc/src/pg.xml +++ /dev/null @@ -1,114 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE erlref SYSTEM "erlref.dtd"> - -<erlref> - <header> - <copyright> - <year>1996</year> - <year>2014</year> - <holder>Ericsson AB, All Rights Reserved</holder> - </copyright> - <legalnotice> - 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. - - The Initial Developer of the Original Code is Ericsson AB. - </legalnotice> - - <title>pg</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <module>pg</module> - <modulesummary>Distributed, Named Process Groups</modulesummary> - <description> - <warning> - <p>This module is deprecated and will be removed in Erlang/OTP 18.</p> - </warning> - <p>This (experimental) module implements process groups. A process - group is a group of processes that can be accessed by a common - name. For example, a group named <c>foobar</c> can include a set - of processes as members of this group and they can be located on - different nodes.</p> - <p>When messages are sent to the named group, all members of - the group receive the message. The messages are serialized. If - the process <c>P1</c> sends the message <c>M1</c> to the group, - and process <c>P2</c> simultaneously sends message <c>M2</c>, then - all members of the group receive the two messages in the same - order. If members of a group terminate, they are automatically - removed from the group.</p> - <p>This module is not complete. The module is inspired by the ISIS - system and the causal order protocol of the ISIS system should - also be implemented. At the moment, all messages are serialized - by sending them through a group master process.</p> - </description> - <funcs> - <func> - <name name="create" arity="1"/> - <fsummary>Create an empty group</fsummary> - <desc> - <p>Creates an empty group named <c><anno>PgName</anno></c> on the current - node.</p> - </desc> - </func> - <func> - <name name="create" arity="2"/> - <fsummary>Create an empty group on another node</fsummary> - <desc> - <p>Creates an empty group named <c><anno>PgName</anno></c> on the node - <c><anno>Node</anno></c>.</p> - </desc> - </func> - <func> - <name name="join" arity="2"/> - <fsummary>Join a pid to a process group</fsummary> - <desc> - <p>Joins the pid <c><anno>Pid</anno></c> to the process group - <c><anno>PgName</anno></c>. - Returns a list of all old members of the group.</p> - </desc> - </func> - <func> - <name name="send" arity="2"/> - <fsummary>Send a message to all members of a process group</fsummary> - <desc> - <p>Sends the tuple <c>{pg_message, From, PgName, Msg}</c> to - all members of the process group <c><anno>PgName</anno></c>.</p> - <p>Failure: <c>{badarg, {<anno>PgName</anno>, <anno>Msg</anno>}}</c> - if <c><anno>PgName</anno></c> is - not a process group (a globally registered name).</p> - </desc> - </func> - <func> - <name name="esend" arity="2"/> - <fsummary>Send a message to all members of a process group, except ourselves</fsummary> - <desc> - <p>Sends the tuple <c>{pg_message, From, PgName, Msg}</c> to - all members of the process group <c><anno>PgName</anno></c>, except - ourselves.</p> - <p>Failure: <c>{badarg, {<anno>PgName</anno>, <anno>Msg</anno>}}</c> - if <c><anno>PgName</anno></c> is - not a process group (a globally registered name).</p> - </desc> - </func> - <func> - <name name="members" arity="1"/> - <fsummary>Return a list of all members of a process group</fsummary> - <desc> - <p>Returns a list of all members of the process group - <c>PgName</c>.</p> - </desc> - </func> - </funcs> -</erlref> - diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml index 5bf5744622..f27a974242 100644 --- a/lib/stdlib/doc/src/proc_lib.xml +++ b/lib/stdlib/doc/src/proc_lib.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -298,6 +298,40 @@ init(Parent) -> <c>proc_lib</c> functions.</p> </desc> </func> + <func> + <name name="stop" arity="1"/> + <fsummary>Terminate a process synchronously.</fsummary> + <type variable="Process"/> + <desc> + <p>Equivalent to <seealso marker="#stop/3">stop(Process, + normal, infinity)</seealso>.</p> + </desc> + </func> + <func> + <name name="stop" arity="3"/> + <fsummary>Terminate a process synchronously.</fsummary> + <type variable="Process"/> + <type variable="Reason"/> + <type variable="Timeout"/> + <desc> + <p>Orders the process to exit with the given <c>Reason</c> and + waits for it to terminate.</p> + <p>The function returns <c>ok</c> if the process exits with + the given <c>Reason</c> within <c>Timeout</c> + milliseconds.</p> + <p>If the call times out, a <c>timeout</c> exception is + raised.</p> + <p>If the process does not exist, a <c>noproc</c> + exception is raised.</p> + <p>The implementation of this function is based on the + <c>terminate</c> system message, and requires that the + process handles system messages correctly. + See <seealso marker="sys">sys(3)</seealso> + and <seealso marker="doc/design_principles:spec_proc">OTP + Design Principles</seealso> for information about system + messages.</p> + </desc> + </func> </funcs> <section> diff --git a/lib/stdlib/doc/src/ref_man.xml b/lib/stdlib/doc/src/ref_man.xml index 6c35578bdf..ea4009dc3e 100644 --- a/lib/stdlib/doc/src/ref_man.xml +++ b/lib/stdlib/doc/src/ref_man.xml @@ -73,7 +73,6 @@ <xi:include href="ms_transform.xml"/> <xi:include href="orddict.xml"/> <xi:include href="ordsets.xml"/> - <xi:include href="pg.xml"/> <xi:include href="pool.xml"/> <xi:include href="proc_lib.xml"/> <xi:include href="proplists.xml"/> diff --git a/lib/stdlib/doc/src/specs.xml b/lib/stdlib/doc/src/specs.xml index 60a04ed5e7..fd77b52da6 100644 --- a/lib/stdlib/doc/src/specs.xml +++ b/lib/stdlib/doc/src/specs.xml @@ -39,7 +39,6 @@ <xi:include href="../specs/specs_ms_transform.xml"/> <xi:include href="../specs/specs_orddict.xml"/> <xi:include href="../specs/specs_ordsets.xml"/> - <xi:include href="../specs/specs_pg.xml"/> <xi:include href="../specs/specs_pool.xml"/> <xi:include href="../specs/specs_proc_lib.xml"/> <xi:include href="../specs/specs_proplists.xml"/> diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index a46fa1289f..cf7df54d1d 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -115,6 +115,9 @@ <datatype> <name name="dbg_fun"/> </datatype> + <datatype> + <name name="format_fun"/> + </datatype> </datatypes> <funcs> <func> @@ -356,6 +359,17 @@ installed.</p> </desc> </func> + <func> + <name name="terminate" arity="2"/> + <name name="terminate" arity="3"/> + <fsummary>Terminate the process</fsummary> + <desc> + <p>This function orders the process to terminate with the + given <c><anno>Reason</anno></c>. The termination is done + asynchronously, so there is no guarantee that the process is + actually terminated when the function returns.</p> + </desc> + </func> </funcs> <section> diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile index 9ab2cd4134..1b3744b6fb 100644 --- a/lib/stdlib/src/Makefile +++ b/lib/stdlib/src/Makefile @@ -97,7 +97,6 @@ MODULES= \ otp_internal \ orddict \ ordsets \ - pg \ re \ pool \ proc_lib \ diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl index c32da1624f..76e03bbfaa 100644 --- a/lib/stdlib/src/dets.erl +++ b/lib/stdlib/src/dets.erl @@ -440,9 +440,10 @@ insert(Tab, Objs) when is_list(Objs) -> insert(Tab, Obj) -> badarg(treq(Tab, {insert, [Obj]}), [Tab, Obj]). --spec insert_new(Name, Objects) -> boolean() when +-spec insert_new(Name, Objects) -> boolean() | {'error', Reason} when Name :: tab_name(), - Objects :: object() | [object()]. + Objects :: object() | [object()], + Reason :: term(). insert_new(Tab, Objs) when is_list(Objs) -> badarg(treq(Tab, {insert_new, Objs}), [Tab, Objs]); diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index 9b506b0a44..5f8637c118 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -1121,8 +1121,20 @@ skip_toks(From, St, [I|Sis]) -> skip_toks(From, St#epp{location=Cl}, Sis); {ok,_Toks,Cl} -> skip_toks(From, St#epp{location=Cl}, [I|Sis]); - {error,_E,Cl} -> - skip_toks(From, St#epp{location=Cl}, [I|Sis]); + {error,E,Cl} -> + case E of + {_,file_io_server,invalid_unicode} -> + %% The compiler needs to know that there was + %% invalid unicode characters in the file + %% (and there is no point in continuing anyway + %% since io server process has terminated). + epp_reply(From, {error,E}), + leave_file(wait_request(St), St); + _ -> + %% Some other invalid token, such as a bad floating + %% point number. Just ignore it. + skip_toks(From, St#epp{location=Cl}, [I|Sis]) + end; {eof,Cl} -> leave_file(From, St#epp{location=Cl,istk=[I|Sis]}); {error,_E} -> diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index 3cfedfee97..639ddfc214 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -77,7 +77,7 @@ %% Only exprs/2 checks the command by calling erl_lint. The reason is %% that if there is a function handler present, then it is possible %% that there are valid constructs in Expression to be taken care of -%% by a function handler but considerad errors by erl_lint. +%% by a function handler but considered errors by erl_lint. -spec(exprs(Expressions, Bindings) -> {value, Value, NewBindings} when Expressions :: expressions(), diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index 57e768ba9d..c74f68647f 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2012. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. 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 @@ -38,6 +38,8 @@ checked_ra=[] % successfully accessed records }). +-define(REC_OFFSET, 100000000). % A hundred millions. Also in v3_core. + -spec(module(AbsForms, CompileOptions) -> AbsForms when AbsForms :: [erl_parse:abstract_form()], CompileOptions :: [compile:option()]). @@ -144,10 +146,11 @@ pattern({map_field_exact,Line,K0,V0}, St0) -> %% {{struct,Line,Tag,TPs},TPsvs,St1}; pattern({record_index,Line,Name,Field}, St) -> {index_expr(Line, Field, Name, record_fields(Name, St)),St}; -pattern({record,Line,Name,Pfs}, St0) -> +pattern({record,Line0,Name,Pfs}, St0) -> Fs = record_fields(Name, St0), {TMs,St1} = pattern_list(pattern_fields(Fs, Pfs), St0), - {{tuple,Line,[{atom,Line,Name} | TMs]},St1}; + Line = record_offset(Line0, St1), + {{tuple,Line,[{atom,Line0,Name} | TMs]},St1}; pattern({bin,Line,Es0}, St0) -> {Es1,St1} = pattern_bin(Es0, St0), {{bin,Line,Es1},St1}; @@ -329,8 +332,9 @@ expr({map_field_exact,Line,K0,V0}, St0) -> expr({record_index,Line,Name,F}, St) -> I = index_expr(Line, F, Name, record_fields(Name, St)), expr(I, St); -expr({record,Line,Name,Is}, St) -> - expr({tuple,Line,[{atom,Line,Name} | +expr({record,Line0,Name,Is}, St) -> + Line = record_offset(Line0, St), + expr({tuple,Line,[{atom,Line0,Name} | record_inits(record_fields(Name, St), Is)]}, St); expr({record_field,Line,R,Name,F}, St) -> @@ -582,8 +586,9 @@ strict_get_record_field(Line, R, {atom,_,F}=Index, Name, St0) -> I = index_expr(F, Fs, 2), P = record_pattern(2, I, Var, length(Fs)+1, Line, [{atom,Line,Name}]), NLine = neg_line(Line), + RLine = record_offset(NLine, St), E = {'case',NLine,R, - [{clause,NLine,[{tuple,NLine,P}],[],[Var]}, + [{clause,NLine,[{tuple,RLine,P}],[],[Var]}, {clause,NLine,[{var,NLine,'_'}],[], [{call,NLine,{remote,NLine, {atom,NLine,erlang}, @@ -836,7 +841,7 @@ optimize_is_record(H0, G0, #exprec{compile=Opts}) -> [] -> {H0,G0}; Rs0 -> - case lists:member(no_is_record_optimization, Opts) of + case lists:member(dialyzer, Opts) of % no_is_record_optimization true -> {H0,G0}; false -> @@ -961,3 +966,10 @@ opt_remove_2(A, _) -> A. neg_line(L) -> erl_parse:set_line(L, fun(Line) -> -abs(Line) end). + +record_offset(L, St) -> + case lists:member(dialyzer, St#exprec.compile) of + true when L >= 0 -> L+?REC_OFFSET; + true when L < 0 -> L-?REC_OFFSET; + false -> L + end. diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl index edfb097de0..e523b6b476 100644 --- a/lib/stdlib/src/erl_internal.erl +++ b/lib/stdlib/src/erl_internal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. +%% Copyright Ericsson AB 1998-2014. 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 @@ -51,6 +51,8 @@ type_test/2,new_type_test/2,old_type_test/2,old_bif/2]). -export([arith_op/2,bool_op/2,comp_op/2,list_op/2,send_op/2,op_type/2]). +-export([is_type/2]). + %%--------------------------------------------------------------------------- %% Erlang builtin functions allowed in guards. @@ -530,3 +532,53 @@ old_bif(unlink, 1) -> true; old_bif(unregister, 1) -> true; old_bif(whereis, 1) -> true; old_bif(Name, A) when is_atom(Name), is_integer(A) -> false. + +-spec is_type(Name, NumberOfTypeVariables) -> boolean() when + Name :: atom(), + NumberOfTypeVariables :: non_neg_integer(). +%% Returns true if Name/NumberOfTypeVariables is a predefined type. + +is_type(any, 0) -> true; +is_type(arity, 0) -> true; +is_type(atom, 0) -> true; +is_type(binary, 0) -> true; +is_type(bitstring, 0) -> true; +is_type(bool, 0) -> true; +is_type(boolean, 0) -> true; +is_type(byte, 0) -> true; +is_type(char, 0) -> true; +is_type(float, 0) -> true; +is_type(function, 0) -> true; +is_type(identifier, 0) -> true; +is_type(integer, 0) -> true; +is_type(iodata, 0) -> true; +is_type(iolist, 0) -> true; +is_type(list, 0) -> true; +is_type(list, 1) -> true; +is_type(map, 0) -> true; +is_type(maybe_improper_list, 0) -> true; +is_type(maybe_improper_list, 2) -> true; +is_type(mfa, 0) -> true; +is_type(module, 0) -> true; +is_type(neg_integer, 0) -> true; +is_type(nil, 0) -> true; +is_type(no_return, 0) -> true; +is_type(node, 0) -> true; +is_type(non_neg_integer, 0) -> true; +is_type(none, 0) -> true; +is_type(nonempty_improper_list, 2) -> true; +is_type(nonempty_list, 0) -> true; +is_type(nonempty_list, 1) -> true; +is_type(nonempty_maybe_improper_list, 0) -> true; +is_type(nonempty_maybe_improper_list, 2) -> true; +is_type(nonempty_string, 0) -> true; +is_type(number, 0) -> true; +is_type(pid, 0) -> true; +is_type(port, 0) -> true; +is_type(pos_integer, 0) -> true; +is_type(reference, 0) -> true; +is_type(string, 0) -> true; +is_type(term, 0) -> true; +is_type(timeout, 0) -> true; +is_type(tuple, 0) -> true; +is_type(_, _) -> false. diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 39cc03cf7a..f34c3b5c7b 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -130,6 +130,8 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> :: dict:dict(mfa(), line()), callbacks = dict:new() %Callback types :: dict:dict(mfa(), line()), + optional_callbacks = dict:new() %Optional callbacks + :: dict:dict(mfa(), line()), types = dict:new() %Type definitions :: dict:dict(ta(), #typeinfo{}), exp_types=gb_sets:empty() %Exported types @@ -313,13 +315,20 @@ format_error({undefined_behaviour,Behaviour}) -> io_lib:format("behaviour ~w undefined", [Behaviour]); format_error({undefined_behaviour_callbacks,Behaviour}) -> io_lib:format("behaviour ~w callback functions are undefined", - [Behaviour]); + [Behaviour]); format_error({ill_defined_behaviour_callbacks,Behaviour}) -> io_lib:format("behaviour ~w callback functions erroneously defined", [Behaviour]); +format_error({ill_defined_optional_callbacks,Behaviour}) -> + io_lib:format("behaviour ~w optional callback functions erroneously defined", + [Behaviour]); format_error({behaviour_info, {_M,F,A}}) -> io_lib:format("cannot define callback attibute for ~w/~w when " "behaviour_info is defined",[F,A]); +format_error({redefine_optional_callback, {F, A}}) -> + io_lib:format("optional callback ~w/~w duplicated", [F, A]); +format_error({undefined_callback, {_M, F, A}}) -> + io_lib:format("callback ~w/~w is undefined", [F, A]); %% --- types and specs --- format_error({singleton_typevar, Name}) -> io_lib:format("type variable ~w is only used once (is unbound)", [Name]); @@ -331,14 +340,10 @@ format_error({undefined_type, {TypeName, Arity}}) -> io_lib:format("type ~w~s undefined", [TypeName, gen_type_paren(Arity)]); format_error({unused_type, {TypeName, Arity}}) -> io_lib:format("type ~w~s is unused", [TypeName, gen_type_paren(Arity)]); -%% format_error({new_builtin_type, {TypeName, Arity}}) -> -%% io_lib:format("type ~w~s is a new builtin type; " -%% "its (re)definition is allowed only until the next release", -%% [TypeName, gen_type_paren(Arity)]); -format_error({new_var_arity_type, TypeName}) -> - io_lib:format("type ~w is a new builtin type; " +format_error({new_builtin_type, {TypeName, Arity}}) -> + io_lib:format("type ~w~s is a new builtin type; " "its (re)definition is allowed only until the next release", - [TypeName]); + [TypeName, gen_type_paren(Arity)]); format_error({builtin_type, {TypeName, Arity}}) -> io_lib:format("type ~w~s is a builtin type; it cannot be redefined", [TypeName, gen_type_paren(Arity)]); @@ -352,10 +357,14 @@ format_error({type_syntax, Constr}) -> io_lib:format("bad ~w type", [Constr]); format_error({redefine_spec, {M, F, A}}) -> io_lib:format("spec for ~w:~w/~w already defined", [M, F, A]); -format_error({redefine_callback, {M, F, A}}) -> - io_lib:format("callback ~w:~w/~w already defined", [M, F, A]); -format_error({spec_fun_undefined, {M, F, A}}) -> - io_lib:format("spec for undefined function ~w:~w/~w", [M, F, A]); +format_error({redefine_spec, {F, A}}) -> + io_lib:format("spec for ~w/~w already defined", [F, A]); +format_error({redefine_callback, {F, A}}) -> + io_lib:format("callback ~w/~w already defined", [F, A]); +format_error({bad_callback, {M, F, A}}) -> + io_lib:format("explicit module not allowed for callback ~w:~w/~w ", [M, F, A]); +format_error({spec_fun_undefined, {F, A}}) -> + io_lib:format("spec for undefined function ~w/~w", [F, A]); format_error({missing_spec, {F,A}}) -> io_lib:format("missing specification for function ~w/~w", [F, A]); format_error(spec_wrong_arity) -> @@ -727,6 +736,8 @@ attribute_state({attribute,L,spec,{Fun,Types}}, St) -> spec_decl(L, Fun, Types, St); attribute_state({attribute,L,callback,{Fun,Types}}, St) -> callback_decl(L, Fun, Types, St); +attribute_state({attribute,L,optional_callbacks,Es}, St) -> + optional_callbacks(L, Es, St); attribute_state({attribute,L,on_load,Val}, St) -> on_load(L, Val, St); attribute_state({attribute,_L,_Other,_Val}, St) -> % Ignore others @@ -834,57 +845,73 @@ check_behaviour(St0) -> %% Check behaviours for existence and defined functions. behaviour_check(Bs, St0) -> - {AllBfs,St1} = all_behaviour_callbacks(Bs, [], St0), - St = behaviour_missing_callbacks(AllBfs, St1), + {AllBfs0, St1} = all_behaviour_callbacks(Bs, [], St0), + St = behaviour_missing_callbacks(AllBfs0, St1), + Exports = exports(St0), + F = fun(Bfs, OBfs) -> + [B || B <- Bfs, + not lists:member(B, OBfs) + orelse gb_sets:is_member(B, Exports)] + end, + %% After fixing missing callbacks new warnings may be emitted. + AllBfs = [{Item,F(Bfs0, OBfs0)} || {Item,Bfs0,OBfs0} <- AllBfs0], behaviour_conflicting(AllBfs, St). all_behaviour_callbacks([{Line,B}|Bs], Acc, St0) -> - {Bfs0,St} = behaviour_callbacks(Line, B, St0), - all_behaviour_callbacks(Bs, [{{Line,B},Bfs0}|Acc], St); + {Bfs0,OBfs0,St} = behaviour_callbacks(Line, B, St0), + all_behaviour_callbacks(Bs, [{{Line,B},Bfs0,OBfs0}|Acc], St); all_behaviour_callbacks([], Acc, St) -> {reverse(Acc),St}. behaviour_callbacks(Line, B, St0) -> try B:behaviour_info(callbacks) of - Funcs when is_list(Funcs) -> - All = all(fun({FuncName, Arity}) -> - is_atom(FuncName) andalso is_integer(Arity); - ({FuncName, Arity, Spec}) -> - is_atom(FuncName) andalso is_integer(Arity) - andalso is_list(Spec); - (_Other) -> - false - end, - Funcs), - MaybeRemoveSpec = fun({_F,_A}=FA) -> FA; - ({F,A,_S}) -> {F,A}; - (Other) -> Other - end, - if - All =:= true -> - {[MaybeRemoveSpec(F) || F <- Funcs], St0}; + undefined -> + St1 = add_warning(Line, {undefined_behaviour_callbacks, B}, St0), + {[], [], St1}; + Funcs -> + case is_fa_list(Funcs) of true -> + try B:behaviour_info(optional_callbacks) of + undefined -> + {Funcs, [], St0}; + OptFuncs -> + %% OptFuncs should always be OK thanks to + %% sys_pre_expand. + case is_fa_list(OptFuncs) of + true -> + {Funcs, OptFuncs, St0}; + false -> + W = {ill_defined_optional_callbacks, B}, + St1 = add_warning(Line, W, St0), + {Funcs, [], St1} + end + catch + _:_ -> + {Funcs, [], St0} + end; + false -> St1 = add_warning(Line, - {ill_defined_behaviour_callbacks,B}, + {ill_defined_behaviour_callbacks, B}, St0), - {[], St1} - end; - undefined -> - St1 = add_warning(Line, {undefined_behaviour_callbacks,B}, St0), - {[], St1}; - _Other -> - St1 = add_warning(Line, {ill_defined_behaviour_callbacks,B}, St0), - {[], St1} + {[], [], St1} + end catch _:_ -> - St1 = add_warning(Line, {undefined_behaviour,B}, St0), - {[], St1} + St1 = add_warning(Line, {undefined_behaviour, B}, St0), + {[], [], St1} end. -behaviour_missing_callbacks([{{Line,B},Bfs}|T], St0) -> +behaviour_missing_callbacks([{{Line,B},Bfs0,OBfs}|T], St0) -> + Bfs = ordsets:subtract(ordsets:from_list(Bfs0), ordsets:from_list(OBfs)), Exports = gb_sets:to_list(exports(St0)), - Missing = ordsets:subtract(ordsets:from_list(Bfs), Exports), + Missing = ordsets:subtract(Bfs, Exports), St = foldl(fun (F, S0) -> - add_warning(Line, {undefined_behaviour_func,F,B}, S0) + case is_fa(F) of + true -> + M = {undefined_behaviour_func,F,B}, + add_warning(Line, M, S0); + false -> + S0 % ill_defined_behaviour_callbacks + end end, St0, Missing), behaviour_missing_callbacks(T, St); behaviour_missing_callbacks([], St) -> St. @@ -1046,10 +1073,9 @@ check_undefined_types(#lint{usage=Usage,types=Def}=St0) -> Used = Usage#usage.used_types, UTAs = dict:fetch_keys(Used), Undef = [{TA,dict:fetch(TA, Used)} || - {T,_}=TA <- UTAs, + TA <- UTAs, not dict:is_key(TA, Def), - not is_default_type(TA), - not is_newly_introduced_var_arity_type(T)], + not is_default_type(TA)], foldl(fun ({TA,L}, St) -> add_error(L, {undefined_type,TA}, St) end, St0, Undef). @@ -1127,19 +1153,29 @@ check_unused_records(Forms, St0) -> end. check_callback_information(#lint{callbacks = Callbacks, - defined = Defined} = State) -> - case gb_sets:is_member({behaviour_info,1}, Defined) of - false -> State; + optional_callbacks = OptionalCbs, + defined = Defined} = St0) -> + OptFun = fun({MFA, Line}, St) -> + case dict:is_key(MFA, Callbacks) of + true -> + St; + false -> + add_error(Line, {undefined_callback, MFA}, St) + end + end, + St1 = lists:foldl(OptFun, St0, dict:to_list(OptionalCbs)), + case gb_sets:is_member({behaviour_info, 1}, Defined) of + false -> St1; true -> case dict:size(Callbacks) of - 0 -> State; + 0 -> St1; _ -> CallbacksList = dict:to_list(Callbacks), FoldL = - fun({Fa,Line},St) -> + fun({Fa, Line}, St) -> add_error(Line, {behaviour_info, Fa}, St) end, - lists:foldl(FoldL, State, CallbacksList) + lists:foldl(FoldL, St1, CallbacksList) end end. @@ -2615,30 +2651,21 @@ type_def(Attr, Line, TypeName, ProtoType, Args, St0) -> true -> case is_obsolete_builtin_type(TypePair) of true -> StoreType(St0); - false -> add_error(Line, {builtin_type, TypePair}, St0) -%% case is_newly_introduced_builtin_type(TypePair) of -%% %% allow some types just for bootstrapping -%% true -> -%% Warn = {new_builtin_type, TypePair}, -%% St1 = add_warning(Line, Warn, St0), -%% StoreType(St1); -%% false -> -%% add_error(Line, {builtin_type, TypePair}, St0) -%% end + false -> + case is_newly_introduced_builtin_type(TypePair) of + %% allow some types just for bootstrapping + true -> + Warn = {new_builtin_type, TypePair}, + St1 = add_warning(Line, Warn, St0), + StoreType(St1); + false -> + add_error(Line, {builtin_type, TypePair}, St0) + end end; false -> - case - dict:is_key(TypePair, TypeDefs) orelse - is_var_arity_type(TypeName) - of + case dict:is_key(TypePair, TypeDefs) of true -> - case is_newly_introduced_var_arity_type(TypeName) of - true -> - Warn = {new_var_arity_type, TypeName}, - add_warning(Line, Warn, St0); - false -> - add_error(Line, {redefine_type, TypePair}, St0) - end; + add_error(Line, {redefine_type, TypePair}, St0); false -> St1 = case Attr =:= opaque andalso @@ -2675,7 +2702,7 @@ check_type({paren_type, _L, [Type]}, SeenVars, St) -> check_type({remote_type, L, [{atom, _, Mod}, {atom, _, Name}, Args]}, SeenVars, #lint{module=CurrentMod} = St) -> case Mod =:= CurrentMod of - true -> check_type({type, L, Name, Args}, SeenVars, St); + true -> check_type({user_type, L, Name, Args}, SeenVars, St); false -> lists:foldl(fun(T, {AccSeenVars, AccSt}) -> check_type(T, AccSeenVars, AccSt) @@ -2709,12 +2736,15 @@ check_type({type, L, range, [From, To]}, SeenVars, St) -> _ -> add_error(L, {type_syntax, range}, St) end, {SeenVars, St1}; -check_type({type, _L, map, any}, SeenVars, St) -> {SeenVars, St}; +check_type({type, L, map, any}, SeenVars, St) -> + %% To get usage right while map/0 is a newly_introduced_builtin_type. + St1 = used_type({map, 0}, L, St), + {SeenVars, St1}; check_type({type, _L, map, Pairs}, SeenVars, St) -> lists:foldl(fun(Pair, {AccSeenVars, AccSt}) -> check_type(Pair, AccSeenVars, AccSt) end, {SeenVars, St}, Pairs); -check_type({type, _L, map_field_assoc, Dom, Range}, SeenVars, St) -> +check_type({type, _L, map_field_assoc, [Dom, Range]}, SeenVars, St) -> check_type({type, -1, product, [Dom, Range]}, SeenVars, St); check_type({type, _L, tuple, any}, SeenVars, St) -> {SeenVars, St}; check_type({type, _L, any}, SeenVars, St) -> {SeenVars, St}; @@ -2733,41 +2763,39 @@ check_type({type, L, record, [Name|Fields]}, SeenVars, St) -> check_record_types(L, Atom, Fields, SeenVars, St1); _ -> {SeenVars, add_error(L, {type_syntax, record}, St)} end; -check_type({type, _L, product, Args}, SeenVars, St) -> +check_type({type, _L, Tag, Args}, SeenVars, St) when Tag =:= product; + Tag =:= union; + Tag =:= tuple -> lists:foldl(fun(T, {AccSeenVars, AccSt}) -> check_type(T, AccSeenVars, AccSt) end, {SeenVars, St}, Args); check_type({type, La, TypeName, Args}, SeenVars, St) -> - #lint{usage=Usage, module = Module, types=Types} = St, + #lint{module = Module, types=Types} = St, Arity = length(Args), TypePair = {TypeName, Arity}, - St1 = case is_var_arity_type(TypeName) of - true -> St; - false -> - Obsolete = (is_warn_enabled(deprecated_type, St) - andalso obsolete_builtin_type(TypePair)), - IsObsolete = - case Obsolete of - {deprecated, Repl, _} when element(1, Repl) =/= Module -> - case dict:find(TypePair, Types) of - {ok, _} -> false; - error -> true - end; - _ -> false - end, - case IsObsolete of - true -> + Obsolete = (is_warn_enabled(deprecated_type, St) + andalso obsolete_builtin_type(TypePair)), + St1 = case Obsolete of + {deprecated, Repl, _} when element(1, Repl) =/= Module -> + case dict:find(TypePair, Types) of + {ok, _} -> + used_type(TypePair, La, St); + error -> {deprecated, Replacement, Rel} = Obsolete, Tag = deprecated_builtin_type, W = {Tag, TypePair, Replacement, Rel}, - add_warning(La, W, St); - false -> - OldUsed = Usage#usage.used_types, - UsedTypes = dict:store(TypePair, La, OldUsed), - St#lint{usage=Usage#usage{used_types=UsedTypes}} - end - end, + add_warning(La, W, St) + end; + _ -> St + end, check_type({type, -1, product, Args}, SeenVars, St1); +check_type({user_type, L, TypeName, Args}, SeenVars, St) -> + Arity = length(Args), + TypePair = {TypeName, Arity}, + St1 = used_type(TypePair, L, St), + lists:foldl(fun(T, {AccSeenVars, AccSt}) -> + check_type(T, AccSeenVars, AccSt) + end, {SeenVars, St1}, Args); check_type(I, SeenVars, St) -> case erl_eval:partial_eval(I) of {integer,_ILn,_Integer} -> {SeenVars, St}; @@ -2809,95 +2837,24 @@ check_record_types([{type, _, field_type, [{atom, AL, FName}, Type]}|Left], check_record_types([], _Name, _DefFields, SeenVars, St, _SeenFields) -> {SeenVars, St}. -is_var_arity_type(tuple) -> true; -is_var_arity_type(map) -> true; -is_var_arity_type(product) -> true; -is_var_arity_type(union) -> true; -is_var_arity_type(record) -> true; -is_var_arity_type(_) -> false. - -is_default_type({any, 0}) -> true; -is_default_type({arity, 0}) -> true; -is_default_type({array, 0}) -> true; -is_default_type({atom, 0}) -> true; -is_default_type({atom, 1}) -> true; -is_default_type({binary, 0}) -> true; -is_default_type({binary, 2}) -> true; -is_default_type({bitstring, 0}) -> true; -is_default_type({bool, 0}) -> true; -is_default_type({boolean, 0}) -> true; -is_default_type({byte, 0}) -> true; -is_default_type({char, 0}) -> true; -is_default_type({dict, 0}) -> true; -is_default_type({digraph, 0}) -> true; -is_default_type({float, 0}) -> true; -is_default_type({'fun', 0}) -> true; -is_default_type({'fun', 2}) -> true; -is_default_type({function, 0}) -> true; -is_default_type({gb_set, 0}) -> true; -is_default_type({gb_tree, 0}) -> true; -is_default_type({identifier, 0}) -> true; -is_default_type({integer, 0}) -> true; -is_default_type({integer, 1}) -> true; -is_default_type({iodata, 0}) -> true; -is_default_type({iolist, 0}) -> true; -is_default_type({list, 0}) -> true; -is_default_type({list, 1}) -> true; -is_default_type({maybe_improper_list, 0}) -> true; -is_default_type({maybe_improper_list, 2}) -> true; -is_default_type({mfa, 0}) -> true; -is_default_type({module, 0}) -> true; -is_default_type({neg_integer, 0}) -> true; -is_default_type({nil, 0}) -> true; -is_default_type({no_return, 0}) -> true; -is_default_type({node, 0}) -> true; -is_default_type({non_neg_integer, 0}) -> true; -is_default_type({none, 0}) -> true; -is_default_type({nonempty_list, 0}) -> true; -is_default_type({nonempty_list, 1}) -> true; -is_default_type({nonempty_improper_list, 2}) -> true; -is_default_type({nonempty_maybe_improper_list, 0}) -> true; -is_default_type({nonempty_maybe_improper_list, 2}) -> true; -is_default_type({nonempty_string, 0}) -> true; -is_default_type({number, 0}) -> true; -is_default_type({pid, 0}) -> true; -is_default_type({port, 0}) -> true; -is_default_type({pos_integer, 0}) -> true; -is_default_type({queue, 0}) -> true; -is_default_type({range, 2}) -> true; -is_default_type({reference, 0}) -> true; -is_default_type({set, 0}) -> true; -is_default_type({string, 0}) -> true; -is_default_type({term, 0}) -> true; -is_default_type({timeout, 0}) -> true; -is_default_type({var, 1}) -> true; -is_default_type(_) -> false. - -is_newly_introduced_var_arity_type(map) -> true; -is_newly_introduced_var_arity_type(_) -> false. - -%% is_newly_introduced_builtin_type({Name, _}) when is_atom(Name) -> false. +used_type(TypePair, L, St) -> + Usage = St#lint.usage, + OldUsed = Usage#usage.used_types, + UsedTypes = dict:store(TypePair, L, OldUsed), + St#lint{usage=Usage#usage{used_types=UsedTypes}}. + +is_default_type({Name, NumberOfTypeVariables}) -> + erl_internal:is_type(Name, NumberOfTypeVariables). + +is_newly_introduced_builtin_type({map, 0}) -> true; +is_newly_introduced_builtin_type({Name, _}) when is_atom(Name) -> false. is_obsolete_builtin_type(TypePair) -> obsolete_builtin_type(TypePair) =/= no. -%% Obsolete in OTP 17.0. -obsolete_builtin_type({array, 0}) -> - {deprecated, {array, array, 1}, "OTP 18.0"}; -obsolete_builtin_type({dict, 0}) -> - {deprecated, {dict, dict, 2}, "OTP 18.0"}; -obsolete_builtin_type({digraph, 0}) -> - {deprecated, {digraph, graph}, "OTP 18.0"}; -obsolete_builtin_type({gb_set, 0}) -> - {deprecated, {gb_sets, set, 1}, "OTP 18.0"}; -obsolete_builtin_type({gb_tree, 0}) -> - {deprecated, {gb_trees, tree, 2}, "OTP 18.0"}; -obsolete_builtin_type({queue, 0}) -> - {deprecated, {queue, queue, 1}, "OTP 18.0"}; -obsolete_builtin_type({set, 0}) -> - {deprecated, {sets, set, 1}, "OTP 18.0"}; -obsolete_builtin_type({tid, 0}) -> - {deprecated, {ets, tid}, "OTP 18.0"}; +%% To keep Dialyzer silent... +obsolete_builtin_type({1, 255}) -> + {deprecated, {2, 255}, ""}; obsolete_builtin_type({Name, A}) when is_atom(Name), is_integer(A) -> no. %% spec_decl(Line, Fun, Types, State) -> State. @@ -2909,7 +2866,7 @@ spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) -> end, St1 = St0#lint{specs = dict:store(MFA, Line, Specs)}, case dict:is_key(MFA, Specs) of - true -> add_error(Line, {redefine_spec, MFA}, St1); + true -> add_error(Line, {redefine_spec, MFA0}, St1); false -> check_specs(TypeSpecs, Arity, St1) end. @@ -2917,16 +2874,50 @@ spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) -> callback_decl(Line, MFA0, TypeSpecs, St0 = #lint{callbacks = Callbacks, module = Mod}) -> - MFA = case MFA0 of - {F, Arity} -> {Mod, F, Arity}; - {_M, _F, Arity} -> MFA0 - end, - St1 = St0#lint{callbacks = dict:store(MFA, Line, Callbacks)}, - case dict:is_key(MFA, Callbacks) of - true -> add_error(Line, {redefine_callback, MFA}, St1); - false -> check_specs(TypeSpecs, Arity, St1) + case MFA0 of + {_M, _F, _A} -> add_error(Line, {bad_callback, MFA0}, St0); + {F, Arity} -> + MFA = {Mod, F, Arity}, + St1 = St0#lint{callbacks = dict:store(MFA, Line, Callbacks)}, + case dict:is_key(MFA, Callbacks) of + true -> add_error(Line, {redefine_callback, MFA0}, St1); + false -> check_specs(TypeSpecs, Arity, St1) + end end. +%% optional_callbacks(Line, FAs, State) -> State. + +optional_callbacks(Line, Term, St0) -> + try true = is_fa_list(Term), Term of + FAs -> + optional_cbs(Line, FAs, St0) + catch + _:_ -> + St0 % ignore others + end. + +optional_cbs(_Line, [], St) -> + St; +optional_cbs(Line, [{F,A}|FAs], St0) -> + #lint{optional_callbacks = OptionalCbs, module = Mod} = St0, + MFA = {Mod, F, A}, + St1 = St0#lint{optional_callbacks = dict:store(MFA, Line, OptionalCbs)}, + St2 = case dict:is_key(MFA, OptionalCbs) of + true -> + add_error(Line, {redefine_optional_callback, {F,A}}, St1); + false -> + St1 + end, + optional_cbs(Line, FAs, St2). + +is_fa_list([E|L]) -> is_fa(E) andalso is_fa_list(L); +is_fa_list([]) -> true; +is_fa_list(_) -> false. + +is_fa({FuncName, Arity}) + when is_atom(FuncName), is_integer(Arity), Arity >= 0 -> true; +is_fa(_) -> false. + check_specs([FunType|Left], Arity, St0) -> {FunType1, CTypes} = case FunType of @@ -2950,10 +2941,11 @@ check_specs([], _Arity, St) -> St. check_specs_without_function(#lint{module=Mod,defined=Funcs,specs=Specs}=St) -> - Fun = fun({M, F, A} = MFA, Line, AccSt) when M =:= Mod -> - case gb_sets:is_element({F, A}, Funcs) of + Fun = fun({M, F, A}, Line, AccSt) when M =:= Mod -> + FA = {F, A}, + case gb_sets:is_element(FA, Funcs) of true -> AccSt; - false -> add_error(Line, {spec_fun_undefined, MFA}, AccSt) + false -> add_error(Line, {spec_fun_undefined, FA}, AccSt) end; ({_M, _F, _A}, _Line, AccSt) -> AccSt end, diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index e1ae3b7aea..a626d98ee4 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -146,8 +146,7 @@ type -> '(' top_type ')' : {paren_type, ?line('$2'), ['$2']}. type -> var : '$1'. type -> atom : '$1'. type -> atom '(' ')' : build_gen_type('$1'). -type -> atom '(' top_types ')' : {type, ?line('$1'), - normalise('$1'), '$3'}. +type -> atom '(' top_types ')' : build_type('$1', '$3'). type -> atom ':' atom '(' ')' : {remote_type, ?line('$1'), ['$1', '$3', []]}. type -> atom ':' atom '(' top_types ')' : {remote_type, ?line('$1'), @@ -181,7 +180,7 @@ fun_type -> '(' top_types ')' '->' top_type map_pair_types -> map_pair_type : ['$1']. map_pair_types -> map_pair_type ',' map_pair_types : ['$1'|'$3']. -map_pair_type -> top_type '=>' top_type : {type, ?line('$2'), map_field_assoc,'$1','$3'}. +map_pair_type -> top_type '=>' top_type : {type, ?line('$2'), map_field_assoc,['$1','$3']}. field_types -> field_type : ['$1']. field_types -> field_type ',' field_types : ['$1'|'$3']. @@ -665,6 +664,8 @@ find_arity_from_specs([Spec|_]) -> {type, _, 'fun', [{type, _, product, Args},_]} = Fun, length(Args). +build_def({var, L, '_'}, _Types) -> + ret_err(L, "bad type variable"); build_def(LHS, Types) -> IsSubType = {atom, ?line(LHS), is_subtype}, {type, ?line(LHS), constraint, [IsSubType, [LHS, Types]]}. @@ -684,7 +685,8 @@ build_gen_type({atom, La, tuple}) -> build_gen_type({atom, La, map}) -> {type, La, map, any}; build_gen_type({atom, La, Name}) -> - {type, La, Name, []}. + Tag = type_tag(Name, 0), + {Tag, La, Name, []}. build_bin_type([{var, _, '_'}|Left], Int) -> build_bin_type(Left, Int); @@ -693,6 +695,16 @@ build_bin_type([], Int) -> build_bin_type([{var, La, _}|_], _) -> ret_err(La, "Bad binary type"). +build_type({atom, L, Name}, Types) -> + Tag = type_tag(Name, length(Types)), + {Tag, L, Name, Types}. + +type_tag(TypeName, NumberOfTypeVariables) -> + case erl_internal:is_type(TypeName, NumberOfTypeVariables) of + true -> type; + false -> user_type + end. + %% build_attribute(AttrName, AttrValue) -> %% {attribute,Line,module,Module} %% {attribute,Line,export,Exports} diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl index 82bc2c1460..10842d21ab 100644 --- a/lib/stdlib/src/erl_pp.erl +++ b/lib/stdlib/src/erl_pp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -232,13 +232,21 @@ lattribute(import, Name, _Opts, _State) when is_list(Name) -> attr("import", [{var,0,pname(Name)}]); lattribute(import, {From,Falist}, _Opts, _State) -> attr("import",[{var,0,pname(From)},falist(Falist)]); +lattribute(optional_callbacks, Falist, Opts, _State) -> + ArgL = try falist(Falist) + catch _:_ -> abstract(Falist, Opts) + end, + call({var,0,"-optional_callbacks"}, [ArgL], 0, options(none)); lattribute(file, {Name,Line}, _Opts, State) -> attr("file", [{var,0,(State#pp.string_fun)(Name)},{integer,0,Line}]); lattribute(record, {Name,Is}, Opts, _State) -> Nl = leaf(format("-record(~w,", [Name])), [{first,Nl,record_fields(Is, Opts)},$)]; -lattribute(Name, Arg, #options{encoding = Encoding}, _State) -> - attr(write(Name), [erl_parse:abstract(Arg, [{encoding,Encoding}])]). +lattribute(Name, Arg, Options, _State) -> + attr(write(Name), [abstract(Arg, Options)]). + +abstract(Arg, #options{encoding = Encoding}) -> + erl_parse:abstract(Arg, [{encoding,Encoding}]). typeattr(Tag, {TypeName,Type,Args}, _Opts) -> {first,leaf("-"++atom_to_list(Tag)++" "), @@ -277,6 +285,9 @@ ltype({type,_,'fun',[{type,_,any},_]}=FunType) -> ltype({type,_Line,'fun',[{type,_,product,_},_]}=FunType) -> [fun_type(['fun',$(], FunType),$)]; ltype({type,Line,T,Ts}) -> + %% Compatibility. Before 18.0. + simple_type({atom,Line,T}, Ts); +ltype({user_type,Line,T,Ts}) -> simple_type({atom,Line,T}, Ts); ltype({remote_type,Line,[M,F,Ts]}) -> simple_type({remote,Line,M,F}, Ts); @@ -299,7 +310,7 @@ map_type(Fs) -> map_pair_types(Fs) -> tuple_type(Fs, fun map_pair_type/1). -map_pair_type({type,_Line,map_field_assoc,Ktype,Vtype}) -> +map_pair_type({type,_Line,map_field_assoc,[Ktype,Vtype]}) -> {seq,[],[]," =>",[ltype(Ktype),ltype(Vtype)]}. record_type(Name, Fields) -> diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl index c0921e4cf1..9efbe8da20 100644 --- a/lib/stdlib/src/filelib.erl +++ b/lib/stdlib/src/filelib.erl @@ -265,7 +265,7 @@ do_wildcard(Pattern, Cwd, Mod) -> lists:sort(Files). do_wildcard_1({exists,File}, Mod) -> - case eval_read_file_info(File, Mod) of + case eval_read_link_info(File, Mod) of {ok,_} -> [File]; _ -> [] end; @@ -488,7 +488,7 @@ badpattern(Reason) -> error({badpattern,Reason}). eval_read_file_info(File, file) -> - file:read_link_info(File); + file:read_file_info(File); eval_read_file_info(File, erl_prim_loader) -> case erl_prim_loader:read_file_info(File) of error -> {error, erl_prim_loader}; @@ -497,6 +497,16 @@ eval_read_file_info(File, erl_prim_loader) -> eval_read_file_info(File, Mod) -> Mod:read_file_info(File). +eval_read_link_info(File, file) -> + file:read_link_info(File); +eval_read_link_info(File, erl_prim_loader) -> + case erl_prim_loader:read_link_info(File) of + error -> {error, erl_prim_loader}; + Res-> Res + end; +eval_read_link_info(File, Mod) -> + Mod:read_link_info(File). + eval_list_dir(Dir, file) -> file:list_dir(Dir); eval_list_dir(Dir, erl_prim_loader) -> diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl index 63116fa16e..6d7ca3d75c 100644 --- a/lib/stdlib/src/gen.erl +++ b/lib/stdlib/src/gen.erl @@ -26,7 +26,7 @@ %%% The standard behaviour should export init_it/6. %%%----------------------------------------------------------------- -export([start/5, start/6, debug_options/1, - call/3, call/4, reply/2]). + call/3, call/4, reply/2, stop/1, stop/3]). -export([init_it/6, init_it/7]). @@ -145,56 +145,10 @@ init_it2(GenMod, Starter, Parent, Name, Mod, Args, Options) -> call(Process, Label, Request) -> call(Process, Label, Request, ?default_timeout). -%% Local or remote by pid -call(Pid, Label, Request, Timeout) - when is_pid(Pid), Timeout =:= infinity; - is_pid(Pid), is_integer(Timeout), Timeout >= 0 -> - do_call(Pid, Label, Request, Timeout); -%% Local by name -call(Name, Label, Request, Timeout) - when is_atom(Name), Timeout =:= infinity; - is_atom(Name), is_integer(Timeout), Timeout >= 0 -> - case whereis(Name) of - Pid when is_pid(Pid) -> - do_call(Pid, Label, Request, Timeout); - undefined -> - exit(noproc) - end; -%% Global by name call(Process, Label, Request, Timeout) - when ((tuple_size(Process) == 2 andalso element(1, Process) == global) - orelse - (tuple_size(Process) == 3 andalso element(1, Process) == via)) - andalso - (Timeout =:= infinity orelse (is_integer(Timeout) andalso Timeout >= 0)) -> - case where(Process) of - Pid when is_pid(Pid) -> - Node = node(Pid), - try do_call(Pid, Label, Request, Timeout) - catch - exit:{nodedown, Node} -> - %% A nodedown not yet detected by global, - %% pretend that it was. - exit(noproc) - end; - undefined -> - exit(noproc) - end; -%% Local by name in disguise -call({Name, Node}, Label, Request, Timeout) - when Node =:= node(), Timeout =:= infinity; - Node =:= node(), is_integer(Timeout), Timeout >= 0 -> - call(Name, Label, Request, Timeout); -%% Remote by name -call({_Name, Node}=Process, Label, Request, Timeout) - when is_atom(Node), Timeout =:= infinity; - is_atom(Node), is_integer(Timeout), Timeout >= 0 -> - if - node() =:= nonode@nohost -> - exit({nodedown, Node}); - true -> - do_call(Process, Label, Request, Timeout) - end. + when Timeout =:= infinity; is_integer(Timeout), Timeout >= 0 -> + Fun = fun(Pid) -> do_call(Pid, Label, Request, Timeout) end, + do_for_proc(Process, Fun). do_call(Process, Label, Request, Timeout) -> try erlang:monitor(process, Process) of @@ -276,6 +230,65 @@ reply({To, Tag}, Reply) -> Msg = {Tag, Reply}, try To ! Msg catch _:_ -> Msg end. +%%----------------------------------------------------------------- +%% Syncronously stop a generic process +%%----------------------------------------------------------------- +stop(Process) -> + stop(Process, normal, infinity). + +stop(Process, Reason, Timeout) + when Timeout =:= infinity; is_integer(Timeout), Timeout >= 0 -> + Fun = fun(Pid) -> proc_lib:stop(Pid, Reason, Timeout) end, + do_for_proc(Process, Fun). + +%%----------------------------------------------------------------- +%% Map different specifications of a process to either Pid or +%% {Name,Node}. Execute the given Fun with the process as only +%% argument. +%% ----------------------------------------------------------------- + +%% Local or remote by pid +do_for_proc(Pid, Fun) when is_pid(Pid) -> + Fun(Pid); +%% Local by name +do_for_proc(Name, Fun) when is_atom(Name) -> + case whereis(Name) of + Pid when is_pid(Pid) -> + Fun(Pid); + undefined -> + exit(noproc) + end; +%% Global by name +do_for_proc(Process, Fun) + when ((tuple_size(Process) == 2 andalso element(1, Process) == global) + orelse + (tuple_size(Process) == 3 andalso element(1, Process) == via)) -> + case where(Process) of + Pid when is_pid(Pid) -> + Node = node(Pid), + try Fun(Pid) + catch + exit:{nodedown, Node} -> + %% A nodedown not yet detected by global, + %% pretend that it was. + exit(noproc) + end; + undefined -> + exit(noproc) + end; +%% Local by name in disguise +do_for_proc({Name, Node}, Fun) when Node =:= node() -> + do_for_proc(Name, Fun); +%% Remote by name +do_for_proc({_Name, Node} = Process, Fun) when is_atom(Node) -> + if + node() =:= nonode@nohost -> + exit({nodedown, Node}); + true -> + Fun(Process) + end. + + %%%----------------------------------------------------------------- %%% Misc. functions. %%%----------------------------------------------------------------- diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl index d39dd89d3a..934b112f6f 100644 --- a/lib/stdlib/src/gen_event.erl +++ b/lib/stdlib/src/gen_event.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -31,8 +31,8 @@ %%% Modified by Martin - uses proc_lib, sys and gen! --export([start/0, start/1, start_link/0, start_link/1, stop/1, notify/2, - sync_notify/2, +-export([start/0, start/1, start_link/0, start_link/1, stop/1, stop/3, + notify/2, sync_notify/2, add_handler/3, add_sup_handler/3, delete_handler/3, swap_handler/3, swap_sup_handler/3, which_handlers/1, call/3, call/4, wake_hib/4]). @@ -101,6 +101,14 @@ -callback code_change(OldVsn :: (term() | {down, term()}), State :: term(), Extra :: term()) -> {ok, NewState :: term()}. +-callback format_status(Opt, StatusData) -> Status when + Opt :: 'normal' | 'terminate', + StatusData :: [PDict | State], + PDict :: [{Key :: term(), Value :: term()}], + State :: term(), + Status :: term(). + +-optional_callbacks([format_status/2]). %%--------------------------------------------------------------------------- @@ -185,7 +193,11 @@ swap_sup_handler(M, {H1, A1}, {H2, A2}) -> which_handlers(M) -> rpc(M, which_handlers). -spec stop(emgr_ref()) -> 'ok'. -stop(M) -> rpc(M, stop). +stop(M) -> + gen:stop(M). + +stop(M, Reason, Timeout) -> + gen:stop(M, Reason, Timeout). rpc(M, Cmd) -> {ok, Reply} = gen:call(M, self(), Cmd, infinity), @@ -284,9 +296,6 @@ handle_msg(Msg, Parent, ServerName, MSL, Debug) -> Args2, MSL, Sup, ServerName), ?reply(Reply), loop(Parent, ServerName, MSL1, Debug, Hib); - {From, Tag, stop} -> - catch terminate_server(normal, Parent, MSL, ServerName), - ?reply(ok); {From, Tag, which_handlers} -> ?reply(the_handlers(MSL)), loop(Parent, ServerName, MSL, Debug, false); diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl index e914f7d0b2..29b1d80088 100644 --- a/lib/stdlib/src/gen_fsm.erl +++ b/lib/stdlib/src/gen_fsm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -106,6 +106,7 @@ -export([start/3, start/4, start_link/3, start_link/4, + stop/1, stop/3, send_event/2, sync_send_event/2, sync_send_event/3, send_all_state_event/2, sync_send_all_state_event/2, sync_send_all_state_event/3, @@ -160,6 +161,14 @@ -callback code_change(OldVsn :: term() | {down, term()}, StateName :: atom(), StateData :: term(), Extra :: term()) -> {ok, NextStateName :: atom(), NewStateData :: term()}. +-callback format_status(Opt, StatusData) -> Status when + Opt :: 'normal' | 'terminate', + StatusData :: [PDict | State], + PDict :: [{Key :: term(), Value :: term()}], + State :: term(), + Status :: term(). + +-optional_callbacks([format_status/2]). %%% --------------------------------------------------- %%% Starts a generic state machine. @@ -189,6 +198,11 @@ start_link(Mod, Args, Options) -> start_link(Name, Mod, Args, Options) -> gen:start(?MODULE, link, Name, Mod, Args, Options). +stop(Name) -> + gen:stop(Name). + +stop(Name, Reason, Timeout) -> + gen:stop(Name, Reason, Timeout). send_event({global, Name}, Event) -> catch global:send(Name, {'$gen_event', Event}), diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl index 202a931fae..9794c73cc2 100644 --- a/lib/stdlib/src/gen_server.erl +++ b/lib/stdlib/src/gen_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -88,6 +88,7 @@ %% API -export([start/3, start/4, start_link/3, start_link/4, + stop/1, stop/3, call/2, call/3, cast/2, reply/2, abcast/2, abcast/3, @@ -137,6 +138,15 @@ -callback code_change(OldVsn :: (term() | {down, term()}), State :: term(), Extra :: term()) -> {ok, NewState :: term()} | {error, Reason :: term()}. +-callback format_status(Opt, StatusData) -> Status when + Opt :: 'normal' | 'terminate', + StatusData :: [PDict | State], + PDict :: [{Key :: term(), Value :: term()}], + State :: term(), + Status :: term(). + +-optional_callbacks([format_status/2]). + %%% ----------------------------------------------------------------- %%% Starts a generic server. @@ -168,6 +178,17 @@ start_link(Name, Mod, Args, Options) -> %% ----------------------------------------------------------------- +%% Stop a generic server and wait for it to terminate. +%% If the server is located at another node, that node will +%% be monitored. +%% ----------------------------------------------------------------- +stop(Name) -> + gen:stop(Name). + +stop(Name, Reason, Timeout) -> + gen:stop(Name, Reason, Timeout). + +%% ----------------------------------------------------------------- %% Make a call to a generic server. %% If the server is located at another node, that node will %% be monitored. diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl index 56e15a17ec..89ae6fb187 100644 --- a/lib/stdlib/src/io_lib_format.erl +++ b/lib/stdlib/src/io_lib_format.erl @@ -255,7 +255,7 @@ term(T, none, _Adj, none, _Pad) -> T; term(T, none, Adj, P, Pad) -> term(T, P, Adj, P, Pad); term(T, F, Adj, P0, Pad) -> L = lists:flatlength(T), - P = case P0 of none -> erlang:min(L, F); _ -> P0 end, + P = erlang:min(L, case P0 of none -> F; _ -> min(P0, F) end), if L > P -> adjust(chars($*, P), chars(Pad, F-P), Adj); diff --git a/lib/stdlib/src/maps.erl b/lib/stdlib/src/maps.erl index 4ef1638e6d..3f019aa35a 100644 --- a/lib/stdlib/src/maps.erl +++ b/lib/stdlib/src/maps.erl @@ -133,10 +133,10 @@ to_list(_) -> erlang:nif_error(undef). update(_,_,_) -> erlang:nif_error(undef). --spec values(Map) -> Keys when +-spec values(Map) -> Values when Map :: map(), - Keys :: [Key], - Key :: term(). + Values :: [Value], + Value :: term(). values(_) -> erlang:nif_error(undef). diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index c0ee8799c8..662a0aca74 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -577,8 +577,6 @@ obsolete_1(asn1rt, utf8_binary_to_list, 1) -> {deprecated,{unicode,characters_to_list,1}}; obsolete_1(asn1rt, utf8_list_to_binary, 1) -> {deprecated,{unicode,characters_to_binary,1}}; -obsolete_1(pg, _, _) -> - {deprecated,"deprecated; will be removed in OTP 18"}; obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/src/pg.erl b/lib/stdlib/src/pg.erl deleted file mode 100644 index a41fd329c2..0000000000 --- a/lib/stdlib/src/pg.erl +++ /dev/null @@ -1,187 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2014. 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(pg). --deprecated(module). - -%% pg provides a process group facility. Messages -%% can be multicasted to all members in the group - --export([create/1, - create/2, - standby/2, - join/2, - send/2, - esend/2, - members/1, - name_to_pid/1, - master/1]). - - -%% Create a brand new empty process group with the master residing -%% at the local node - --spec create(PgName) -> 'ok' | {'error', Reason} when - PgName :: term(), - Reason :: 'already_created' | term(). - -create(PgName) -> - catch begin check(PgName), - Pid = spawn(pg,master,[PgName]), - global:register_name(PgName,Pid), - ok end. - -%% Create a brand new empty process group with the master -%% residing at Node - --spec create(PgName, Node) -> 'ok' | {'error', Reason} when - PgName :: term(), - Node :: node(), - Reason :: 'already_created' | term(). - -create(PgName, Node) -> - catch begin check(PgName), - Pid = spawn(Node,pg,master,[PgName]), - global:register_name(PgName,Pid), - ok end. - -%% Have a process on Node that will act as a standby for the process -%% group manager. So if the node where the manager runs fails, the -%% process group will continue to function. - --spec standby(term(), node()) -> 'ok'. - -standby(_PgName, _Node) -> - ok. - -%% Tell process group PgName that Pid is a new member of the group -%% synchronously return a list of all old members in the group - --spec join(PgName, Pid) -> Members when - PgName :: term(), - Pid :: pid(), - Members :: [pid()]. - -join(PgName, Pid) when is_atom(PgName) -> - global:send(PgName, {join,self(),Pid}), - receive - {_P,{members,Members}} -> - Members - end. - -%% Multi cast Mess to all members in the group - --spec send(PgName, Msg) -> 'ok' when - PgName :: term(), - Msg :: term(). - -send(PgName, Mess) when is_atom(PgName) -> - global:send(PgName, {send, self(), Mess}), - ok; -send(Pg, Mess) when is_pid(Pg) -> - Pg ! {send,self(),Mess}, - ok. - -%% multi cast a message to all members in the group but ourselves -%% If we are a member - --spec esend(PgName, Msg) -> 'ok' when - PgName :: term(), - Msg :: term(). - -esend(PgName, Mess) when is_atom(PgName) -> - global:send(PgName, {esend,self(),Mess}), - ok; -esend(Pg, Mess) when is_pid(Pg) -> - Pg ! {esend,self(),Mess}, - ok. - -%% Return the members of the group - --spec members(PgName) -> Members when - PgName :: term(), - Members :: [pid()]. - -members(PgName) when is_atom(PgName) -> - global:send(PgName, {self() ,members}), - receive - {_P,{members,Members}} -> - Members - end; -members(Pg) when is_pid(Pg) -> - Pg ! {self,members}, - receive - {_P,{members,Members}} -> - Members - end. - --spec name_to_pid(atom()) -> pid() | 'undefined'. - -name_to_pid(PgName) when is_atom(PgName) -> - global:whereis_name(PgName). - --spec master(term()) -> no_return(). - -master(PgName) -> - process_flag(trap_exit, true), - master_loop(PgName, []). - -master_loop(PgName,Members) -> - receive - {send,From,Message} -> - send_all(Members,{pg_message,From,PgName,Message}), - master_loop(PgName,Members); - {esend,From,Message} -> - send_all(lists:delete(From,Members), - {pg_message,From,PgName,Message}), - master_loop(PgName,Members); - {join,From,Pid} -> - link(Pid), - send_all(Members,{new_member,PgName,Pid}), - From ! {self(),{members,Members}}, - master_loop(PgName,[Pid|Members]); - {From,members} -> - From ! {self(),{members,Members}}, - master_loop(PgName,Members); - {'EXIT',From,_} -> - L = - case lists:member(From,Members) of - true -> - NewMembers = lists:delete(From,Members), - send_all(NewMembers, {crashed_member,PgName,From}), - NewMembers; - false -> - Members - end, - master_loop(PgName,L) - end. - -send_all([], _) -> ok; -send_all([P|Ps], M) -> - P ! M, - send_all(Ps, M). - -%% Check if the process group already exists - -check(PgName) -> - case global:whereis_name(PgName) of - Pid when is_pid(Pid) -> - throw({error,already_created}); - undefined -> - ok - end. diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl index 1eb6fc2e86..c925e70613 100644 --- a/lib/stdlib/src/proc_lib.erl +++ b/lib/stdlib/src/proc_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -30,7 +30,8 @@ hibernate/3, init_ack/1, init_ack/2, init_p/3,init_p/5,format/1,format/2,initial_call/1, - translate_initial_call/1]). + translate_initial_call/1, + stop/1, stop/3]). %% Internal exports. -export([wake_up/3]). @@ -750,3 +751,50 @@ format_tag(Tag, Data) -> modifier(latin1) -> ""; modifier(_) -> "t". + + +%%% ----------------------------------------------------------- +%%% Stop a process and wait for it to terminate +%%% ----------------------------------------------------------- +-spec stop(Process) -> 'ok' when + Process :: pid() | RegName | {RegName,node()}, + RegName :: atom(). +stop(Process) -> + stop(Process, normal, infinity). + +-spec stop(Process, Reason, Timeout) -> 'ok' when + Process :: pid() | RegName | {RegName,node()}, + RegName :: atom(), + Reason :: term(), + Timeout :: timeout(). +stop(Process, Reason, Timeout) -> + {Pid, Mref} = erlang:spawn_monitor(do_stop(Process, Reason)), + receive + {'DOWN', Mref, _, _, Reason} -> + ok; + {'DOWN', Mref, _, _, {noproc,{sys,terminate,_}}} -> + exit(noproc); + {'DOWN', Mref, _, _, CrashReason} -> + exit(CrashReason) + after Timeout -> + exit(Pid, kill), + receive + {'DOWN', Mref, _, _, _} -> + exit(timeout) + end + end. + +-spec do_stop(Process, Reason) -> Fun when + Process :: pid() | RegName | {RegName,node()}, + RegName :: atom(), + Reason :: term(), + Fun :: fun(() -> no_return()). +do_stop(Process, Reason) -> + fun() -> + Mref = erlang:monitor(process, Process), + ok = sys:terminate(Process, Reason, infinity), + receive + {'DOWN', Mref, _, _, ExitReason} -> + exit(ExitReason) + end + end. diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index 3b90542452..679c13f0cf 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -371,6 +371,14 @@ expand_expr({bc,L,E,Qs}, C) -> {bc,L,expand_expr(E, C),expand_quals(Qs, C)}; expand_expr({tuple,L,Elts}, C) -> {tuple,L,expand_exprs(Elts, C)}; +expand_expr({map,L,Es}, C) -> + {map,L,expand_exprs(Es, C)}; +expand_expr({map,L,Arg,Es}, C) -> + {map,L,expand_expr(Arg, C),expand_exprs(Es, C)}; +expand_expr({map_field_assoc,L,K,V}, C) -> + {map_field_assoc,L,expand_expr(K, C),expand_expr(V, C)}; +expand_expr({map_field_exact,L,K,V}, C) -> + {map_field_exact,L,expand_expr(K, C),expand_expr(V, C)}; expand_expr({record_index,L,Name,F}, C) -> {record_index,L,Name,expand_expr(F, C)}; expand_expr({record,L,Name,Is}, C) -> diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src index d388410de0..c25ab41a54 100644 --- a/lib/stdlib/src/stdlib.app.src +++ b/lib/stdlib/src/stdlib.app.src @@ -77,7 +77,6 @@ orddict, ordsets, otp_internal, - pg, pool, proc_lib, proplists, @@ -103,7 +102,7 @@ dets]}, {applications, [kernel]}, {env, []}, - {runtime_dependencies, ["sasl-2.4","kernel-3.0","erts-6.0","crypto-3.3", + {runtime_dependencies, ["sasl-2.4","kernel-3.0.2","erts-6.1.2","crypto-3.3", "compiler-5.0"]} ]}. diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 22eefb2514..e718fce140 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -17,9 +17,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 - {<<"1\\.19(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R16 + [{<<"2\\.1(\\.[0-9]+)*">>,[restart_new_emulator]}, %% 17.1 + {<<"2\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}], %% 17.0 %% Down to - max one major revision back - [{<<"2\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 - {<<"1\\.19(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R16 + [{<<"2\\.1(\\.[0-9]+)*">>,[restart_new_emulator]}, %% 17.1 + {<<"2\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}] %% 17.0 }. diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl index e25cc25f57..7e4bfa1fdd 100644 --- a/lib/stdlib/src/sys.erl +++ b/lib/stdlib/src/sys.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -24,6 +24,7 @@ get_state/1, get_state/2, replace_state/2, replace_state/3, change_code/4, change_code/5, + terminate/2, terminate/3, log/2, log/3, trace/2, trace/3, statistics/2, statistics/3, log_to_file/2, log_to_file/3, no_debug/1, no_debug/2, install/2, install/3, remove/2, remove/3]). @@ -46,7 +47,7 @@ {N :: non_neg_integer(), [{Event :: system_event(), FuncState :: _, - FormFunc :: dbg_fun()}]}} + FormFunc :: format_fun()}]}} | {'statistics', {file:date_time(), {'reductions', non_neg_integer()}, MessagesIn :: non_neg_integer(), @@ -57,6 +58,10 @@ Event :: system_event(), ProcState :: _) -> 'done' | (NewFuncState :: _)). +-type format_fun() :: fun((Device :: io:device() | file:io_device(), + Event :: system_event(), + Extra :: term()) -> any()). + %%----------------------------------------------------------------- %% System messages %%----------------------------------------------------------------- @@ -159,6 +164,19 @@ change_code(Name, Mod, Vsn, Extra) -> change_code(Name, Mod, Vsn, Extra, Timeout) -> send_system_msg(Name, {change_code, Mod, Vsn, Extra}, Timeout). +-spec terminate(Name, Reason) -> 'ok' when + Name :: name(), + Reason :: term(). +terminate(Name, Reason) -> + send_system_msg(Name, {terminate, Reason}). + +-spec terminate(Name, Reason, Timeout) -> 'ok' when + Name :: name(), + Reason :: term(), + Timeout :: timeout(). +terminate(Name, Reason, Timeout) -> + send_system_msg(Name, {terminate, Reason}, Timeout). + %%----------------------------------------------------------------- %% Debug commands %%----------------------------------------------------------------- @@ -294,6 +312,8 @@ mfa(Name, {debug, {Func, Arg2}}) -> {sys, Func, [Name, Arg2]}; mfa(Name, {change_code, Mod, Vsn, Extra}) -> {sys, change_code, [Name, Mod, Vsn, Extra]}; +mfa(Name, {terminate, Reason}) -> + {sys, terminate, [Name, Reason]}; mfa(Name, Atom) -> {sys, Atom, [Name]}. @@ -309,7 +329,7 @@ mfa(Name, Req, Timeout) -> %% Returns: This function *never* returns! It calls the function %% Module:system_continue(Parent, NDebug, Misc) %% there the process continues the execution or -%% Module:system_terminate(Raeson, Parent, Debug, Misc) if +%% Module:system_terminate(Reason, Parent, Debug, Misc) if %% the process should terminate. %% The Module must export system_continue/3, system_terminate/4 %% and format_status/2 for status information. @@ -335,7 +355,10 @@ handle_system_msg(SysState, Msg, From, Parent, Mod, Debug, Misc, Hib) -> suspend_loop(suspended, Parent, Mod, NDebug, NMisc, Hib); {running, Reply, NDebug, NMisc} -> _ = gen:reply(From, Reply), - Mod:system_continue(Parent, NDebug, NMisc) + Mod:system_continue(Parent, NDebug, NMisc); + {{terminating, Reason}, Reply, NDebug, NMisc} -> + _ = gen:reply(From, Reply), + Mod:system_terminate(Reason, Parent, NDebug, NMisc) end. %%----------------------------------------------------------------- @@ -346,7 +369,7 @@ handle_system_msg(SysState, Msg, From, Parent, Mod, Debug, Misc, Hib) -> %%----------------------------------------------------------------- -spec handle_debug(Debug, FormFunc, Extra, Event) -> [dbg_opt()] when Debug :: [dbg_opt()], - FormFunc :: dbg_fun(), + FormFunc :: format_fun(), Extra :: term(), Event :: system_event(). handle_debug([{trace, true} | T], FormFunc, State, Event) -> @@ -415,6 +438,8 @@ do_cmd(SysState, get_status, Parent, Mod, Debug, Misc) -> do_cmd(SysState, {debug, What}, _Parent, _Mod, Debug, Misc) -> {Res, NDebug} = debug_cmd(What, Debug), {SysState, Res, NDebug, Misc}; +do_cmd(_, {terminate, Reason}, _Parent, _Mod, Debug, Misc) -> + {{terminating, Reason}, ok, Debug, Misc}; do_cmd(suspended, {change_code, Module, Vsn, Extra}, _Parent, Mod, Debug, Misc) -> {Res, NMisc} = do_change_code(Mod, Module, Vsn, Extra, Misc), diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl index 6be37cbecf..119b4dc7cb 100644 --- a/lib/stdlib/test/dets_SUITE.erl +++ b/lib/stdlib/test/dets_SUITE.erl @@ -2032,6 +2032,12 @@ match(Config, Version) -> CrashPos = if Version =:= 8 -> 5; Version =:= 9 -> 1 end, crash(Fname, ObjPos2+CrashPos), {ok, _} = dets:open_file(T, Args), + case dets:insert_new(T, Obj) of % OTP-12024 + ok -> + bad_object(dets:sync(T), Fname); + Else3 -> + bad_object(Else3, Fname) + end, io:format("Expect corrupt table:~n"), case ins(T, N) of ok -> diff --git a/lib/stdlib/test/erl_internal_SUITE.erl b/lib/stdlib/test/erl_internal_SUITE.erl index b6b3c004ea..197a7a33eb 100644 --- a/lib/stdlib/test/erl_internal_SUITE.erl +++ b/lib/stdlib/test/erl_internal_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -51,7 +51,7 @@ end_per_group(_GroupName, Config) -> -define(default_timeout, ?t:minutes(2)). init_per_testcase(_Case, Config) -> - ?line Dog = test_server:timetrap(?default_timeout), + Dog = test_server:timetrap(?default_timeout), [{watchdog, Dog}|Config]. end_per_testcase(_Case, Config) -> @@ -63,27 +63,50 @@ behav(suite) -> []; behav(doc) -> ["Check that the behaviour callbacks are correctly defined"]; behav(_) -> - ?line check_behav_list([{start,2}, {stop,1}], - application:behaviour_info(callbacks)), - ?line check_behav_list([{init,1}, {handle_call,3}, {handle_cast,2}, - {handle_info,2}, {terminate,2}, {code_change,3}], - gen_server:behaviour_info(callbacks)), - ?line check_behav_list([{init,1}, {handle_event,3}, {handle_sync_event,4}, - {handle_info,3}, {terminate,3}, {code_change,4}], - gen_fsm:behaviour_info(callbacks)), - ?line check_behav_list([{init,1}, {handle_event,2}, {handle_call,2}, - {handle_info,2}, {terminate,2}, {code_change,3}], - gen_event:behaviour_info(callbacks)), - ?line check_behav_list( [{init,1}, {terminate,2}], - supervisor_bridge:behaviour_info(callbacks)), - ?line check_behav_list([{init,1}], - supervisor:behaviour_info(callbacks)), - ok. + Modules = [application, gen_server, gen_fsm, gen_event, + supervisor_bridge, supervisor], + lists:foreach(fun check_behav/1, Modules). + +check_behav(Module) -> + Callbacks = callbacks(Module), + Optional = optional_callbacks(Module), + check_behav_list(Callbacks, Module:behaviour_info(callbacks)), + check_behav_list(Optional, Module:behaviour_info(optional_callbacks)). check_behav_list([], []) -> ok; check_behav_list([L | L1], L2) -> - ?line true = lists:member(L, L2), - ?line L3 = lists:delete(L, L2), + true = lists:member(L, L2), + L3 = lists:delete(L, L2), check_behav_list(L1, L3). - +callbacks(application) -> + [{start,2}, {stop,1}]; +callbacks(gen_server) -> + [{init,1}, {handle_call,3}, {handle_cast,2}, + {handle_info,2}, {terminate,2}, {code_change,3}, + {format_status,2}]; +callbacks(gen_fsm) -> + [{init,1}, {handle_event,3}, {handle_sync_event,4}, + {handle_info,3}, {terminate,3}, {code_change,4}, + {format_status,2}]; +callbacks(gen_event) -> + [{init,1}, {handle_event,2}, {handle_call,2}, + {handle_info,2}, {terminate,2}, {code_change,3}, + {format_status,2}]; +callbacks(supervisor_bridge) -> + [{init,1}, {terminate,2}]; +callbacks(supervisor) -> + [{init,1}]. + +optional_callbacks(application) -> + []; +optional_callbacks(gen_server) -> + [{format_status,2}]; +optional_callbacks(gen_fsm) -> + [{format_status,2}]; +optional_callbacks(gen_event) -> + [{format_status,2}]; +optional_callbacks(supervisor_bridge) -> + []; +optional_callbacks(supervisor) -> + []. diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index ea61b2082b..ca91d94213 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -55,7 +55,7 @@ otp_11772/1, otp_11771/1, otp_11872/1, export_all/1, bif_clash/1, - behaviour_basic/1, behaviour_multiple/1, + behaviour_basic/1, behaviour_multiple/1, otp_11861/1, otp_7550/1, otp_8051/1, format_warn/1, @@ -63,7 +63,7 @@ too_many_arguments/1, basic_errors/1,bin_syntax_errors/1, predef/1, - maps/1,maps_type/1 + maps/1,maps_type/1,otp_11851/1 ]). % Default timetrap timeout (set in init_per_testcase). @@ -89,10 +89,10 @@ all() -> otp_5362, otp_5371, otp_7227, otp_5494, otp_5644, otp_5878, otp_5917, otp_6585, otp_6885, otp_10436, otp_11254, otp_11772, otp_11771, otp_11872, export_all, - bif_clash, behaviour_basic, behaviour_multiple, + bif_clash, behaviour_basic, behaviour_multiple, otp_11861, otp_7550, otp_8051, format_warn, {group, on_load}, too_many_arguments, basic_errors, bin_syntax_errors, predef, - maps, maps_type]. + maps, maps_type, otp_11851]. groups() -> [{unused_vars_warn, [], @@ -2648,8 +2648,9 @@ otp_11872(Config) when is_list(Config) -> t() -> 1. ">>, - {error,[{6,erl_lint,{undefined_type,{product,0}}}], - [{8,erl_lint,{new_var_arity_type,map}}]} = + {error,[{6,erl_lint,{undefined_type,{product,0}}}, + {8,erl_lint,{undefined_type,{dict,0}}}], + [{8,erl_lint,{new_builtin_type,{map,0}}}]} = run_test2(Config, Ts, []), ok. @@ -3080,6 +3081,193 @@ behaviour_multiple(Config) when is_list(Config) -> ?line [] = run(Config, Ts), ok. +otp_11861(doc) -> + "OTP-11861. behaviour_info() and -callback."; +otp_11861(suite) -> []; +otp_11861(Conf) when is_list(Conf) -> + CallbackFiles = [callback1, callback2, callback3, + bad_behaviour1, bad_behaviour2], + lists:foreach(fun(M) -> + F = filename:join(?datadir, M), + Opts = [{outdir,?privdir}, return], + {ok, M, []} = compile:file(F, Opts) + end, CallbackFiles), + CodePath = code:get_path(), + true = code:add_path(?privdir), + Ts = [{otp_11861_1, + <<" + -export([b1/1]). + -behaviour(callback1). + -behaviour(callback2). + + -spec b1(atom()) -> integer(). + b1(A) when is_atom(A)-> + 3. + ">>, + [], + %% b2/1 is optional in both modules + {warnings,[{4,erl_lint, + {conflicting_behaviours,{b1,1},callback2,3,callback1}}]}}, + {otp_11861_2, + <<" + -export([b2/1]). + -behaviour(callback1). + -behaviour(callback2). + + -spec b2(integer()) -> atom(). + b2(I) when is_integer(I)-> + a. + ">>, + [], + %% b2/1 is optional in callback2, but not in callback1 + {warnings,[{3,erl_lint,{undefined_behaviour_func,{b1,1},callback1}}, + {4,erl_lint, + {conflicting_behaviours,{b2,1},callback2,3,callback1}}]}}, + {otp_11861_3, + <<" + -callback b(_) -> atom(). + -optional_callbacks({b1,1}). % non-existing and ignored + ">>, + [], + []}, + {otp_11861_4, + <<" + -callback b(_) -> atom(). + -optional_callbacks([{b1,1}]). % non-existing + ">>, + [], + %% No behaviour-info(), but callback. + {errors,[{3,erl_lint,{undefined_callback,{lint_test,b1,1}}}],[]}}, + {otp_11861_5, + <<" + -optional_callbacks([{b1,1}]). % non-existing + ">>, + [], + %% No behaviour-info() and no callback: warning anyway + {errors,[{2,erl_lint,{undefined_callback,{lint_test,b1,1}}}],[]}}, + {otp_11861_6, + <<" + -optional_callbacks([b1/1]). % non-existing + behaviour_info(callbacks) -> [{b1,1}]. + ">>, + [], + %% behaviour-info() and no callback: warning anyway + {errors,[{2,erl_lint,{undefined_callback,{lint_test,b1,1}}}],[]}}, + {otp_11861_7, + <<" + -optional_callbacks([b1/1]). % non-existing + -callback b(_) -> atom(). + behaviour_info(callbacks) -> [{b1,1}]. + ">>, + [], + %% behaviour-info() callback: warning + {errors,[{2,erl_lint,{undefined_callback,{lint_test,b1,1}}}, + {3,erl_lint,{behaviour_info,{lint_test,b,1}}}], + []}}, + {otp_11861_8, + <<" + -callback b(_) -> atom(). + -optional_callbacks([b/1, {b, 1}]). + ">>, + [], + {errors,[{3,erl_lint,{redefine_optional_callback,{b,1}}}],[]}}, + {otp_11861_9, + <<" + -behaviour(gen_server). + -export([handle_call/3,handle_cast/2,handle_info/2, + code_change/3, init/1, terminate/2]). + handle_call(_, _, _) -> ok. + handle_cast(_, _) -> ok. + handle_info(_, _) -> ok. + code_change(_, _, _) -> ok. + init(_) -> ok. + terminate(_, _) -> ok. + ">>, + [], + []}, + {otp_11861_9, + <<" + -behaviour(gen_server). + -export([handle_call/3,handle_cast/2,handle_info/2, + code_change/3, init/1, terminate/2, format_status/2]). + handle_call(_, _, _) -> ok. + handle_cast(_, _) -> ok. + handle_info(_, _) -> ok. + code_change(_, _, _) -> ok. + init(_) -> ok. + terminate(_, _) -> ok. + format_status(_, _) -> ok. % optional callback + ">>, + [], + %% Nothing... + []}, + {otp_11861_10, + <<" + -optional_callbacks([{b1,1,bad}]). % badly formed and ignored + behaviour_info(callbacks) -> [{b1,1}]. + ">>, + [], + []}, + {otp_11861_11, + <<" + -behaviour(bad_behaviour1). + ">>, + [], + {warnings,[{2,erl_lint, + {ill_defined_behaviour_callbacks,bad_behaviour1}}]}}, + {otp_11861_12, + <<" + -behaviour(non_existing_behaviour). + ">>, + [], + {warnings,[{2,erl_lint, + {undefined_behaviour,non_existing_behaviour}}]}}, + {otp_11861_13, + <<" + -behaviour(bad_behaviour_none). + ">>, + [], + {warnings,[{2,erl_lint,{undefined_behaviour,bad_behaviour_none}}]}}, + {otp_11861_14, + <<" + -callback b(_) -> atom(). + ">>, + [], + []}, + {otp_11861_15, + <<" + -optional_callbacks([{b1,1,bad}]). % badly formed + -callback b(_) -> atom(). + ">>, + [], + []}, + {otp_11861_16, + <<" + -callback b(_) -> atom(). + -callback b(_) -> atom(). + ">>, + [], + {errors,[{3,erl_lint,{redefine_callback,{b,1}}}],[]}}, + {otp_11861_17, + <<" + -behaviour(bad_behaviour2). + ">>, + [], + {warnings,[{2,erl_lint,{undefined_behaviour_callbacks, + bad_behaviour2}}]}}, + {otp_11861_18, + <<" + -export([f1/1]). + -behaviour(callback3). + f1(_) -> ok. + ">>, + [], + []} + ], + ?line [] = run(Conf, Ts), + true = code:set_path(CodePath), + ok. + otp_7550(doc) -> "Test that the new utf8/utf16/utf32 types do not allow size or unit specifiers."; otp_7550(Config) when is_list(Config) -> @@ -3145,8 +3333,8 @@ format_warn(Config) when is_list(Config) -> ok. format_level(Level, Count, Config) -> - ?line W = get_compilation_warnings(Config, "format", - [{warn_format, Level}]), + ?line W = get_compilation_result(Config, "format", + [{warn_format, Level}]), %% Pick out the 'format' warnings. ?line FW = lists:filter(fun({_Line, erl_lint, {format_error, _}}) -> true; (_) -> false @@ -3330,42 +3518,22 @@ bin_syntax_errors(Config) -> ok. predef(doc) -> - "OTP-10342: Predefined types: array(), digraph(), and so on"; + "OTP-10342: No longer predefined types: array(), digraph(), and so on"; predef(suite) -> []; predef(Config) when is_list(Config) -> - W = get_compilation_warnings(Config, "predef", []), + W = get_compilation_result(Config, "predef", []), [] = W, - W2 = get_compilation_warnings(Config, "predef2", []), - Tag = deprecated_builtin_type, - [{7,erl_lint,{Tag,{array,0},{array,array,1},"OTP 18.0"}}, - {12,erl_lint,{Tag,{dict,0},{dict,dict,2},"OTP 18.0"}}, - {17,erl_lint,{Tag,{digraph,0},{digraph,graph},"OTP 18.0"}}, - {27,erl_lint,{Tag,{gb_set,0},{gb_sets,set,1},"OTP 18.0"}}, - {32,erl_lint,{Tag,{gb_tree,0},{gb_trees,tree,2},"OTP 18.0"}}, - {37,erl_lint,{Tag,{queue,0},{queue,queue,1},"OTP 18.0"}}, - {42,erl_lint,{Tag,{set,0},{sets,set,1},"OTP 18.0"}}, - {47,erl_lint,{Tag,{tid,0},{ets,tid},"OTP 18.0"}}] = W2, - Ts = [{otp_10342_1, - <<"-compile(nowarn_deprecated_type). - - -spec t(dict()) -> non_neg_integer(). - - t(D) -> - erlang:phash2(D, 3000). - ">>, - {[nowarn_unused_function]}, - []}, - {otp_10342_2, - <<"-spec t(dict()) -> non_neg_integer(). - - t(D) -> - erlang:phash2(D, 3000). - ">>, - {[nowarn_unused_function]}, - {warnings,[{1,erl_lint, - {deprecated_builtin_type,{dict,0},{dict,dict,2}, - "OTP 18.0"}}]}}], - [] = run(Config, Ts), + %% dict(), digraph() and so on were removed in Erlang/OTP 18.0. + E2 = get_compilation_result(Config, "predef2", []), + Tag = undefined_type, + {[{7,erl_lint,{Tag,{array,0}}}, + {12,erl_lint,{Tag,{dict,0}}}, + {17,erl_lint,{Tag,{digraph,0}}}, + {27,erl_lint,{Tag,{gb_set,0}}}, + {32,erl_lint,{Tag,{gb_tree,0}}}, + {37,erl_lint,{Tag,{queue,0}}}, + {42,erl_lint,{Tag,{set,0}}}, + {47,erl_lint,{Tag,{tid,0}}}],[]} = E2, ok. maps(Config) -> @@ -3470,7 +3638,94 @@ maps_type(Config) when is_list(Config) -> t(M) -> M. ">>, [], - {warnings,[{3,erl_lint,{new_var_arity_type,map}}]}}], + {warnings,[{3,erl_lint,{new_builtin_type,{map,0}}}]}}], + [] = run(Config, Ts), + ok. + +otp_11851(doc) -> + "OTP-11851: More atoms can be used as type names + bug fixes."; +otp_11851(Config) when is_list(Config) -> + Ts = [ + {otp_11851_1, + <<"-export([t/0]). + -type range(A, B) :: A | B. + + -type union(A) :: A. + + -type product() :: integer(). + + -type tuple(A) :: A. + + -type map(A) :: A. + + -type record() :: a | b. + + -type integer(A) :: A. + + -type atom(A) :: A. + + -type binary(A, B) :: A | B. + + -type 'fun'() :: integer(). + + -type 'fun'(X) :: X. + + -type 'fun'(X, Y) :: X | Y. + + -type all() :: range(atom(), integer()) | union(pid()) | product() + | tuple(reference()) | map(function()) | record() + | integer(atom()) | atom(integer()) + | binary(pid(), tuple()) | 'fun'(port()) + | 'fun'() | 'fun'(<<>>, 'none'). + + -spec t() -> all(). + + t() -> + a. + ">>, + [], + []}, + {otp_11851_2, + <<"-export([a/1, b/1, t/0]). + + -callback b(_) -> integer(). + + -callback ?MODULE:a(_) -> integer(). + + a(_) -> 3. + + b(_) -> a. + + t()-> a. + ">>, + [], + {errors,[{5,erl_lint,{bad_callback,{lint_test,a,1}}}],[]}}, + {otp_11851_3, + <<"-export([a/1]). + + -spec a(_A) -> boolean() when + _ :: atom(), + _A :: integer(). + + a(_) -> true. + ">>, + [], + {errors,[{4,erl_parse,"bad type variable"}],[]}}, + {otp_11851_4, + <<" + -spec a(_) -> ok. + -spec a(_) -> ok. + + -spec ?MODULE:a(_) -> ok. + -spec ?MODULE:a(_) -> ok. + ">>, + [], + {errors,[{3,erl_lint,{redefine_spec,{a,1}}}, + {5,erl_lint,{redefine_spec,{lint_test,a,1}}}, + {6,erl_lint,{redefine_spec,{lint_test,a,1}}}, + {6,erl_lint,{spec_fun_undefined,{a,1}}}], + []}} + ], [] = run(Config, Ts), ok. @@ -3487,9 +3742,9 @@ run(Config, Tests) -> end, lists:foldl(F, [], Tests). -%% Compiles a test file and returns the list of warnings. +%% Compiles a test file and returns the list of warnings/errors. -get_compilation_warnings(Conf, Filename, Warnings) -> +get_compilation_result(Conf, Filename, Warnings) -> ?line DataDir = ?datadir, ?line File = filename:join(DataDir, Filename), {ok,Bin} = file:read_file(File++".erl"), @@ -3498,6 +3753,7 @@ get_compilation_warnings(Conf, Filename, Warnings) -> Test = lists:nthtail(Start+Length, FileS), case run_test(Conf, Test, Warnings) of {warnings, Ws} -> Ws; + {errors,Es,Ws} -> {Es,Ws}; [] -> [] end. diff --git a/lib/stdlib/test/erl_lint_SUITE_data/bad_behaviour1.erl b/lib/stdlib/test/erl_lint_SUITE_data/bad_behaviour1.erl new file mode 100644 index 0000000000..230f4b4519 --- /dev/null +++ b/lib/stdlib/test/erl_lint_SUITE_data/bad_behaviour1.erl @@ -0,0 +1,6 @@ +-module(bad_behaviour1). + +-export([behaviour_info/1]). + +behaviour_info(callbacks) -> + [{a,1,bad}]. diff --git a/lib/stdlib/test/erl_lint_SUITE_data/bad_behaviour2.erl b/lib/stdlib/test/erl_lint_SUITE_data/bad_behaviour2.erl new file mode 100644 index 0000000000..bb755ce18b --- /dev/null +++ b/lib/stdlib/test/erl_lint_SUITE_data/bad_behaviour2.erl @@ -0,0 +1,6 @@ +-module(bad_behaviour2). + +-export([behaviour_info/1]). + +behaviour_info(callbacks) -> + undefined. diff --git a/lib/stdlib/test/erl_lint_SUITE_data/callback1.erl b/lib/stdlib/test/erl_lint_SUITE_data/callback1.erl new file mode 100644 index 0000000000..3cc5b51879 --- /dev/null +++ b/lib/stdlib/test/erl_lint_SUITE_data/callback1.erl @@ -0,0 +1,6 @@ +-module(callback1). + +-callback b1(I :: integer()) -> atom(). +-callback b2(A :: atom()) -> integer(). + +-optional_callbacks([{b2,1}]). diff --git a/lib/stdlib/test/erl_lint_SUITE_data/callback2.erl b/lib/stdlib/test/erl_lint_SUITE_data/callback2.erl new file mode 100644 index 0000000000..211cf9f115 --- /dev/null +++ b/lib/stdlib/test/erl_lint_SUITE_data/callback2.erl @@ -0,0 +1,6 @@ +-module(callback2). + +-callback b1(I :: integer()) -> atom(). +-callback b2(A :: atom()) -> integer(). + +-optional_callbacks([b1/1, b2/1]). diff --git a/lib/stdlib/test/erl_lint_SUITE_data/callback3.erl b/lib/stdlib/test/erl_lint_SUITE_data/callback3.erl new file mode 100644 index 0000000000..97b3ecb860 --- /dev/null +++ b/lib/stdlib/test/erl_lint_SUITE_data/callback3.erl @@ -0,0 +1,8 @@ +-module(callback3). + +-export([behaviour_info/1]). + +behaviour_info(callbacks) -> + [{f1, 1}]; +behaviour_info(_) -> + undefined. diff --git a/lib/stdlib/test/erl_lint_SUITE_data/predef.erl b/lib/stdlib/test/erl_lint_SUITE_data/predef.erl index ee9073aa67..3cb7bf40f1 100644 --- a/lib/stdlib/test/erl_lint_SUITE_data/predef.erl +++ b/lib/stdlib/test/erl_lint_SUITE_data/predef.erl @@ -5,8 +5,8 @@ -export_type([array/0, digraph/0, gb_set/0]). -%% Before Erlang/OTP 17.0 local re-definitions of pre-defined opaque -%% types were ignored but did not generate any warning. +%% Since Erlang/OTP 18.0 array() and so on are no longer pre-defined, +%% so there is nothing special about them at all. -opaque array() :: atom(). -opaque digraph() :: atom(). -opaque gb_set() :: atom(). diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index babf3a49eb..12817943d0 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2013. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. 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 @@ -50,7 +50,7 @@ otp_6321/1, otp_6911/1, otp_6914/1, otp_8150/1, otp_8238/1, otp_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1, - otp_10302/1, otp_10820/1, otp_11100/1]). + otp_10302/1, otp_10820/1, otp_11100/1, otp_11861/1]). %% Internal export. -export([ehook/6]). @@ -83,7 +83,7 @@ groups() -> {tickets, [], [otp_6321, otp_6911, otp_6914, otp_8150, otp_8238, otp_8473, otp_8522, otp_8567, otp_8664, otp_9147, - otp_10302, otp_10820, otp_11100]}]. + otp_10302, otp_10820, otp_11100, otp_11861]}]. init_per_suite(Config) -> Config. @@ -874,6 +874,7 @@ type_examples() -> {ex3,<<"-type paren() :: (ann2()). ">>}, {ex4,<<"-type t1() :: atom(). ">>}, {ex5,<<"-type t2() :: [t1()]. ">>}, + {ex56,<<"-type integer(A) :: A. ">>}, {ex6,<<"-type t3(Atom) :: integer(Atom). ">>}, {ex7,<<"-type '\\'t::4'() :: t3('\\'foobar'). ">>}, {ex8,<<"-type t5() :: {t1(), t3(foo)}. ">>}, @@ -1204,8 +1205,18 @@ otp_11100(Config) when is_list(Config) -> []}}), ok. +otp_11861(doc) -> + "OTP-11861. behaviour_info() and -callback."; +otp_11861(suite) -> []; +otp_11861(Config) when is_list(Config) -> + "-optional_callbacks([bar/0]).\n" = + pf({attribute,3,optional_callbacks,[{bar,0}]}), + "-optional_callbacks([{bar,1,bad}]).\n" = + pf({attribute,4,optional_callbacks,[{bar,1,bad}]}), + ok. + pf(Form) -> - lists:flatten(erl_pp:form(Form,none)). + lists:flatten(erl_pp:form(Form, none)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl index 8203a03a7a..040ae1effc 100644 --- a/lib/stdlib/test/filelib_SUITE.erl +++ b/lib/stdlib/test/filelib_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. 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 @@ -23,7 +23,8 @@ init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2, wildcard_one/1,wildcard_two/1,wildcard_errors/1, - fold_files/1,otp_5960/1,ensure_dir_eexist/1,symlinks/1]). + fold_files/1,otp_5960/1,ensure_dir_eexist/1,ensure_dir_symlink/1, + wildcard_symlink/1, is_file_symlink/1, file_props_symlink/1]). -import(lists, [foreach/2]). @@ -43,7 +44,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [wildcard_one, wildcard_two, wildcard_errors, - fold_files, otp_5960, ensure_dir_eexist, symlinks]. + fold_files, otp_5960, ensure_dir_eexist, ensure_dir_symlink, + wildcard_symlink, is_file_symlink, file_props_symlink]. groups() -> []. @@ -367,9 +369,28 @@ ensure_dir_eexist(Config) when is_list(Config) -> ?line {error, eexist} = filelib:ensure_dir(NeedFileB), ok. -symlinks(Config) when is_list(Config) -> +ensure_dir_symlink(Config) when is_list(Config) -> PrivDir = ?config(priv_dir, Config), - Dir = filename:join(PrivDir, ?MODULE_STRING++"_symlinks"), + Dir = filename:join(PrivDir, "ensure_dir_symlink"), + Name = filename:join(Dir, "same_name_as_file_and_dir"), + ok = filelib:ensure_dir(Name), + ok = file:write_file(Name, <<"some string\n">>), + %% With a symlink to the directory. + Symlink = filename:join(PrivDir, "ensure_dir_symlink_link"), + case file:make_symlink(Dir, Symlink) of + {error,enotsup} -> + {skip,"Symlinks not supported on this platform"}; + {error,eperm} -> + {win32,_} = os:type(), + {skip,"Windows user not privileged to create symlinks"}; + ok -> + SymlinkedName = filename:join(Symlink, "same_name_as_file_and_dir"), + ok = filelib:ensure_dir(SymlinkedName) + end. + +wildcard_symlink(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + Dir = filename:join(PrivDir, ?MODULE_STRING++"_wildcard_symlink"), SubDir = filename:join(Dir, "sub"), AFile = filename:join(SubDir, "a_file"), Alias = filename:join(Dir, "symlink"), @@ -387,6 +408,18 @@ symlinks(Config) when is_list(Config) -> basenames(Dir, filelib:wildcard(filename:join(Dir, "*"))), ["symlink"] = basenames(Dir, filelib:wildcard(filename:join(Dir, "symlink"))), + ["sub","symlink"] = + basenames(Dir, filelib:wildcard(filename:join(Dir, "*"), + erl_prim_loader)), + ["symlink"] = + basenames(Dir, filelib:wildcard(filename:join(Dir, "symlink"), + erl_prim_loader)), + ["sub","symlink"] = + basenames(Dir, filelib:wildcard(filename:join(Dir, "*"), + prim_file)), + ["symlink"] = + basenames(Dir, filelib:wildcard(filename:join(Dir, "symlink"), + prim_file)), ok = file:delete(AFile), %% The symlink should still be visible even when its target %% has been deleted. @@ -394,6 +427,18 @@ symlinks(Config) when is_list(Config) -> basenames(Dir, filelib:wildcard(filename:join(Dir, "*"))), ["symlink"] = basenames(Dir, filelib:wildcard(filename:join(Dir, "symlink"))), + ["sub","symlink"] = + basenames(Dir, filelib:wildcard(filename:join(Dir, "*"), + erl_prim_loader)), + ["symlink"] = + basenames(Dir, filelib:wildcard(filename:join(Dir, "symlink"), + erl_prim_loader)), + ["sub","symlink"] = + basenames(Dir, filelib:wildcard(filename:join(Dir, "*"), + prim_file)), + ["symlink"] = + basenames(Dir, filelib:wildcard(filename:join(Dir, "symlink"), + prim_file)), ok end. @@ -402,3 +447,60 @@ basenames(Dir, Files) -> Dir = filename:dirname(F), filename:basename(F) end || F <- Files]. + +is_file_symlink(Config) -> + PrivDir = ?config(priv_dir, Config), + Dir = filename:join(PrivDir, ?MODULE_STRING++"_is_file_symlink"), + SubDir = filename:join(Dir, "sub"), + AFile = filename:join(SubDir, "a_file"), + DirAlias = filename:join(Dir, "dir_symlink"), + FileAlias = filename:join(Dir, "file_symlink"), + ok = file:make_dir(Dir), + ok = file:make_dir(SubDir), + ok = file:write_file(AFile, "not that big\n"), + case file:make_symlink(SubDir, DirAlias) of + {error, enotsup} -> + {skip, "Links not supported on this platform"}; + {error, eperm} -> + {win32,_} = os:type(), + {skip, "Windows user not privileged to create symlinks"}; + ok -> + true = filelib:is_dir(DirAlias), + true = filelib:is_dir(DirAlias, erl_prim_loader), + true = filelib:is_dir(DirAlias, prim_file), + true = filelib:is_file(DirAlias), + true = filelib:is_file(DirAlias, erl_prim_loader), + true = filelib:is_file(DirAlias, prim_file), + ok = file:make_symlink(AFile,FileAlias), + true = filelib:is_file(FileAlias), + true = filelib:is_file(FileAlias, erl_prim_loader), + true = filelib:is_file(FileAlias, prim_file), + true = filelib:is_regular(FileAlias), + true = filelib:is_regular(FileAlias, erl_prim_loader), + true = filelib:is_regular(FileAlias, prim_file), + ok + end. + +file_props_symlink(Config) -> + PrivDir = ?config(priv_dir, Config), + Dir = filename:join(PrivDir, ?MODULE_STRING++"_file_props_symlink"), + AFile = filename:join(Dir, "a_file"), + Alias = filename:join(Dir, "symlink"), + ok = file:make_dir(Dir), + ok = file:write_file(AFile, "not that big\n"), + case file:make_symlink(AFile, Alias) of + {error, enotsup} -> + {skip, "Links not supported on this platform"}; + {error, eperm} -> + {win32,_} = os:type(), + {skip, "Windows user not privileged to create symlinks"}; + ok -> + {_,_} = LastMod = filelib:last_modified(AFile), + LastMod = filelib:last_modified(Alias), + LastMod = filelib:last_modified(Alias, erl_prim_loader), + LastMod = filelib:last_modified(Alias, prim_file), + FileSize = filelib:file_size(AFile), + FileSize = filelib:file_size(Alias), + FileSize = filelib:file_size(Alias, erl_prim_loader), + FileSize = filelib:file_size(Alias, prim_file) + end. diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl index 60a1ba8c60..576a5adfce 100644 --- a/lib/stdlib/test/gen_event_SUITE.erl +++ b/lib/stdlib/test/gen_event_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -106,7 +106,7 @@ start(Config) when is_list(Config) -> ?line {error, {already_started, _}} = gen_event:start({global, my_dummy_name}), - exit(Pid6, shutdown), + ok = gen_event:stop({global, my_dummy_name}, shutdown, 10000), receive {'EXIT', Pid6, shutdown} -> ok after 10000 -> diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl index 8aeec07ae8..2e266198e9 100644 --- a/lib/stdlib/test/gen_fsm_SUITE.erl +++ b/lib/stdlib/test/gen_fsm_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -27,6 +27,9 @@ -export([start1/1, start2/1, start3/1, start4/1, start5/1, start6/1, start7/1, start8/1, start9/1, start10/1, start11/1, start12/1]). +-export([stop1/1, stop2/1, stop3/1, stop4/1, stop5/1, stop6/1, stop7/1, + stop8/1, stop9/1, stop10/1]). + -export([ abnormal1/1, abnormal2/1]). -export([shutdown/1]). @@ -64,6 +67,8 @@ groups() -> [{start, [], [start1, start2, start3, start4, start5, start6, start7, start8, start9, start10, start11, start12]}, + {stop, [], + [stop1, stop2, stop3, stop4, stop5, stop6, stop7, stop8, stop9, stop10]}, {abnormal, [], [abnormal1, abnormal2]}, {sys, [], [sys1, call_format_status, error_format_status, get_state, replace_state]}]. @@ -278,6 +283,105 @@ start12(Config) when is_list(Config) -> ok. +%% Anonymous, reason 'normal' +stop1(_Config) -> + {ok, Pid} = gen_fsm:start(?MODULE, [], []), + ok = gen_fsm:stop(Pid), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_fsm:stop(Pid)), + ok. + +%% Anonymous, other reason +stop2(_Config) -> + {ok,Pid} = gen_fsm:start(?MODULE, [], []), + ok = gen_fsm:stop(Pid, other_reason, infinity), + false = erlang:is_process_alive(Pid), + ok. + +%% Anonymous, invalid timeout +stop3(_Config) -> + {ok,Pid} = gen_fsm:start(?MODULE, [], []), + {'EXIT',_} = (catch gen_fsm:stop(Pid, other_reason, invalid_timeout)), + true = erlang:is_process_alive(Pid), + ok = gen_fsm:stop(Pid), + false = erlang:is_process_alive(Pid), + ok. + +%% Registered name +stop4(_Config) -> + {ok,Pid} = gen_fsm:start({local,to_stop},?MODULE, [], []), + ok = gen_fsm:stop(to_stop), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_fsm:stop(to_stop)), + ok. + +%% Registered name and local node +stop5(_Config) -> + {ok,Pid} = gen_fsm:start({local,to_stop},?MODULE, [], []), + ok = gen_fsm:stop({to_stop,node()}), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_fsm:stop({to_stop,node()})), + ok. + +%% Globally registered name +stop6(_Config) -> + {ok, Pid} = gen_fsm:start({global, to_stop}, ?MODULE, [], []), + ok = gen_fsm:stop({global,to_stop}), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_fsm:stop({global,to_stop})), + ok. + +%% 'via' registered name +stop7(_Config) -> + dummy_via:reset(), + {ok, Pid} = gen_fsm:start({via, dummy_via, to_stop}, + ?MODULE, [], []), + ok = gen_fsm:stop({via, dummy_via, to_stop}), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_fsm:stop({via, dummy_via, to_stop})), + ok. + +%% Anonymous on remote node +stop8(_Config) -> + {ok,Node} = test_server:start_node(gen_fsm_SUITE_stop8,slave,[]), + Dir = filename:dirname(code:which(?MODULE)), + rpc:call(Node,code,add_path,[Dir]), + {ok, Pid} = rpc:call(Node,gen_fsm,start,[?MODULE,[],[]]), + ok = gen_fsm:stop(Pid), + false = rpc:call(Node,erlang,is_process_alive,[Pid]), + {'EXIT',noproc} = (catch gen_fsm:stop(Pid)), + true = test_server:stop_node(Node), + {'EXIT',{{nodedown,Node},_}} = (catch gen_fsm:stop(Pid)), + ok. + +%% Registered name on remote node +stop9(_Config) -> + {ok,Node} = test_server:start_node(gen_fsm_SUITE_stop9,slave,[]), + Dir = filename:dirname(code:which(?MODULE)), + rpc:call(Node,code,add_path,[Dir]), + {ok, Pid} = rpc:call(Node,gen_fsm,start,[{local,to_stop},?MODULE,[],[]]), + ok = gen_fsm:stop({to_stop,Node}), + undefined = rpc:call(Node,erlang,whereis,[to_stop]), + false = rpc:call(Node,erlang,is_process_alive,[Pid]), + {'EXIT',noproc} = (catch gen_fsm:stop({to_stop,Node})), + true = test_server:stop_node(Node), + {'EXIT',{{nodedown,Node},_}} = (catch gen_fsm:stop({to_stop,Node})), + ok. + +%% Globally registered name on remote node +stop10(_Config) -> + {ok,Node} = test_server:start_node(gen_fsm_SUITE_stop10,slave,[]), + Dir = filename:dirname(code:which(?MODULE)), + rpc:call(Node,code,add_path,[Dir]), + {ok, Pid} = rpc:call(Node,gen_fsm,start,[{global,to_stop},?MODULE,[],[]]), + global:sync(), + ok = gen_fsm:stop({global,to_stop}), + false = rpc:call(Node,erlang,is_process_alive,[Pid]), + {'EXIT',noproc} = (catch gen_fsm:stop({global,to_stop})), + true = test_server:stop_node(Node), + {'EXIT',noproc} = (catch gen_fsm:stop({global,to_stop})), + ok. + %% Check that time outs in calls work abnormal1(suite) -> []; abnormal1(Config) when is_list(Config) -> diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl index 960e7f60e7..c3ec4932b3 100644 --- a/lib/stdlib/test/gen_server_SUITE.erl +++ b/lib/stdlib/test/gen_server_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -35,6 +35,9 @@ error_format_status/1, get_state/1, replace_state/1, call_with_huge_message_queue/1 ]). +-export([stop1/1, stop2/1, stop3/1, stop4/1, stop5/1, stop6/1, stop7/1, + stop8/1, stop9/1, stop10/1]). + % spawn export -export([spec_init_local/2, spec_init_global/2, spec_init_via/2, spec_init_default_timeout/2, spec_init_global_default_timeout/2, @@ -50,7 +53,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [start, crash, call, cast, cast_fast, info, abcast, + [start, {group,stop}, crash, call, cast, cast_fast, info, abcast, multicall, multicall_down, call_remote1, call_remote2, call_remote3, call_remote_n1, call_remote_n2, call_remote_n3, spec_init, @@ -61,7 +64,8 @@ all() -> call_with_huge_message_queue]. groups() -> - []. + [{stop, [], + [stop1, stop2, stop3, stop4, stop5, stop6, stop7, stop8, stop9, stop10]}]. init_per_suite(Config) -> Config. @@ -235,6 +239,105 @@ start(Config) when is_list(Config) -> process_flag(trap_exit, OldFl), ok. +%% Anonymous, reason 'normal' +stop1(_Config) -> + {ok, Pid} = gen_server:start(?MODULE, [], []), + ok = gen_server:stop(Pid), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_server:stop(Pid)), + ok. + +%% Anonymous, other reason +stop2(_Config) -> + {ok,Pid} = gen_server:start(?MODULE, [], []), + ok = gen_server:stop(Pid, other_reason, infinity), + false = erlang:is_process_alive(Pid), + ok. + +%% Anonymous, invalid timeout +stop3(_Config) -> + {ok,Pid} = gen_server:start(?MODULE, [], []), + {'EXIT',_} = (catch gen_server:stop(Pid, other_reason, invalid_timeout)), + true = erlang:is_process_alive(Pid), + ok = gen_server:stop(Pid), + false = erlang:is_process_alive(Pid), + ok. + +%% Registered name +stop4(_Config) -> + {ok,Pid} = gen_server:start({local,to_stop},?MODULE, [], []), + ok = gen_server:stop(to_stop), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_server:stop(to_stop)), + ok. + +%% Registered name and local node +stop5(_Config) -> + {ok,Pid} = gen_server:start({local,to_stop},?MODULE, [], []), + ok = gen_server:stop({to_stop,node()}), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_server:stop({to_stop,node()})), + ok. + +%% Globally registered name +stop6(_Config) -> + {ok, Pid} = gen_server:start({global, to_stop}, ?MODULE, [], []), + ok = gen_server:stop({global,to_stop}), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_server:stop({global,to_stop})), + ok. + +%% 'via' registered name +stop7(_Config) -> + dummy_via:reset(), + {ok, Pid} = gen_server:start({via, dummy_via, to_stop}, + ?MODULE, [], []), + ok = gen_server:stop({via, dummy_via, to_stop}), + false = erlang:is_process_alive(Pid), + {'EXIT',noproc} = (catch gen_server:stop({via, dummy_via, to_stop})), + ok. + +%% Anonymous on remote node +stop8(_Config) -> + {ok,Node} = test_server:start_node(gen_server_SUITE_stop8,slave,[]), + Dir = filename:dirname(code:which(?MODULE)), + rpc:call(Node,code,add_path,[Dir]), + {ok, Pid} = rpc:call(Node,gen_server,start,[?MODULE,[],[]]), + ok = gen_server:stop(Pid), + false = rpc:call(Node,erlang,is_process_alive,[Pid]), + {'EXIT',noproc} = (catch gen_server:stop(Pid)), + true = test_server:stop_node(Node), + {'EXIT',{{nodedown,Node},_}} = (catch gen_server:stop(Pid)), + ok. + +%% Registered name on remote node +stop9(_Config) -> + {ok,Node} = test_server:start_node(gen_server_SUITE_stop9,slave,[]), + Dir = filename:dirname(code:which(?MODULE)), + rpc:call(Node,code,add_path,[Dir]), + {ok, Pid} = rpc:call(Node,gen_server,start,[{local,to_stop},?MODULE,[],[]]), + ok = gen_server:stop({to_stop,Node}), + undefined = rpc:call(Node,erlang,whereis,[to_stop]), + false = rpc:call(Node,erlang,is_process_alive,[Pid]), + {'EXIT',noproc} = (catch gen_server:stop({to_stop,Node})), + true = test_server:stop_node(Node), + {'EXIT',{{nodedown,Node},_}} = (catch gen_server:stop({to_stop,Node})), + ok. + +%% Globally registered name on remote node +stop10(_Config) -> + {ok,Node} = test_server:start_node(gen_server_SUITE_stop10,slave,[]), + Dir = filename:dirname(code:which(?MODULE)), + rpc:call(Node,code,add_path,[Dir]), + {ok, Pid} = rpc:call(Node,gen_server,start,[{global,to_stop},?MODULE,[],[]]), + global:sync(), + ok = gen_server:stop({global,to_stop}), + false = rpc:call(Node,erlang,is_process_alive,[Pid]), + {'EXIT',noproc} = (catch gen_server:stop({global,to_stop})), + true = test_server:stop_node(Node), + {'EXIT',noproc} = (catch gen_server:stop({global,to_stop})), + ok. + crash(Config) when is_list(Config) -> ?line error_logger_forwarder:register(), diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 5a8971c071..3a76275f31 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -30,7 +30,7 @@ io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1, printable_range/1, io_lib_print_binary_depth_one/1, otp_10302/1, otp_10755/1, - otp_10836/1]). + otp_10836/1, io_lib_width_too_small/1]). -export([pretty/2]). @@ -69,7 +69,8 @@ all() -> io_lib_collect_line_3_wb, cr_whitespace_in_string, io_fread_newlines, otp_8989, io_lib_fread_literal, printable_range, - io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836]. + io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836, + io_lib_width_too_small]. groups() -> []. @@ -2213,3 +2214,8 @@ compile_file(File, Text, Config) -> try compile:file(Fname, [return]) after ok %file:delete(Fname) end. + +io_lib_width_too_small(Config) -> + "**" = lists:flatten(io_lib:format("~2.3w", [3.14])), + "**" = lists:flatten(io_lib:format("~2.5w", [3.14])), + ok. diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl index 8dca69bac4..b6f1973a05 100644 --- a/lib/stdlib/test/proc_lib_SUITE.erl +++ b/lib/stdlib/test/proc_lib_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -27,7 +27,7 @@ init_per_group/2,end_per_group/2, crash/1, sync_start_nolink/1, sync_start_link/1, spawn_opt/1, sp1/0, sp2/0, sp3/1, sp4/2, sp5/1, - hibernate/1]). + hibernate/1, stop/1]). -export([ otp_6345/1, init_dont_hang/1]). -export([hib_loop/1, awaken/1]). @@ -38,6 +38,7 @@ -export([otp_6345_init/1, init_dont_hang_init/1]). +-export([system_terminate/4]). -ifdef(STANDALONE). -define(line, noop, ). @@ -49,7 +50,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [crash, {group, sync_start}, spawn_opt, hibernate, - {group, tickets}]. + {group, tickets}, stop]. groups() -> [{tickets, [], [otp_6345, init_dont_hang]}, @@ -361,10 +362,94 @@ init_dont_hang(Config) when is_list(Config) -> exit(Error) end. -init_dont_hang_init(Parent) -> +init_dont_hang_init(_Parent) -> 1 = 2. +%% Test proc_lib:stop/1,3 +stop(_Config) -> + Parent = self(), + SysMsgProc = + fun() -> + receive + {system,From,Request} -> + sys:handle_system_msg(Request,From,Parent,?MODULE,[],[]) + end + end, + + %% Normal case: + %% Process handles system message and terminated with given reason + Pid1 = proc_lib:spawn(SysMsgProc), + ok = proc_lib:stop(Pid1), + false = erlang:is_process_alive(Pid1), + + %% Process does not exit + {'EXIT',noproc} = (catch proc_lib:stop(Pid1)), + + %% Badly handled system message + DieProc = + fun() -> + receive + {system,_From,_Request} -> + exit(die) + end + end, + Pid2 = proc_lib:spawn(DieProc), + {'EXIT',{die,_}} = (catch proc_lib:stop(Pid2)), + + %% Hanging process => timeout + HangProc = + fun() -> + receive + {system,_From,_Request} -> + timer:sleep(5000) + end + end, + Pid3 = proc_lib:spawn(HangProc), + {'EXIT',timeout} = (catch proc_lib:stop(Pid3,normal,1000)), + + %% Success case with other reason than 'normal' + Pid4 = proc_lib:spawn(SysMsgProc), + ok = proc_lib:stop(Pid4,other_reason,infinity), + false = erlang:is_process_alive(Pid4), + + %% System message is handled, but process dies with other reason + %% than the given (in system_terminate/4 below) + Pid5 = proc_lib:spawn(SysMsgProc), + {'EXIT',{badmatch,2}} = (catch proc_lib:stop(Pid5,crash,infinity)), + false = erlang:is_process_alive(Pid5), + + %% Local registered name + Pid6 = proc_lib:spawn(SysMsgProc), + register(to_stop,Pid6), + ok = proc_lib:stop(to_stop), + undefined = whereis(to_stop), + false = erlang:is_process_alive(Pid6), + + %% Remote registered name + {ok,Node} = test_server:start_node(proc_lib_SUITE_stop,slave,[]), + Dir = filename:dirname(code:which(?MODULE)), + rpc:call(Node,code,add_path,[Dir]), + Pid7 = spawn(Node,SysMsgProc), + true = rpc:call(Node,erlang,register,[to_stop,Pid7]), + Pid7 = rpc:call(Node,erlang,whereis,[to_stop]), + ok = proc_lib:stop({to_stop,Node}), + undefined = rpc:call(Node,erlang,whereis,[to_stop]), + false = rpc:call(Node,erlang,is_process_alive,[Pid7]), + + %% Local and remote registered name, but non-existing + {'EXIT',noproc} = (catch proc_lib:stop(to_stop)), + {'EXIT',noproc} = (catch proc_lib:stop({to_stop,Node})), + + true = test_server:stop_node(Node), + + %% Remote registered name, but non-existing node + {'EXIT',{{nodedown,Node},_}} = (catch proc_lib:stop({to_stop,Node})), + ok. +system_terminate(crash,_Parent,_Deb,_State) -> + 1 = 2; +system_terminate(Reason,_Parent,_Deb,_State) -> + exit(Reason). %%----------------------------------------------------------------- %% The error_logger handler used. diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl index e016432f4d..f841e2c4a6 100644 --- a/lib/stdlib/test/shell_SUITE.erl +++ b/lib/stdlib/test/shell_SUITE.erl @@ -2532,6 +2532,11 @@ otp_6554(Config) when is_list(Config) -> "\n end.\nok.\n" = t(<<"begin F = fun() -> foo end, 1 end. B = F(). C = 17. b().">>), + ?line "3: command not found" = comm_err(<<"#{v(3) => v}.">>), + ?line "3: command not found" = comm_err(<<"#{k => v(3)}.">>), + ?line "3: command not found" = comm_err(<<"#{v(3) := v}.">>), + ?line "3: command not found" = comm_err(<<"#{k := v(3)}.">>), + ?line "3: command not found" = comm_err(<<"(v(3))#{}.">>), %% Tests I'd like to do: (you should try them manually) %% "catch spawn_link(fun() -> timer:sleep(1000), exit(foo) end)." %% "** exception error: foo" should be output after 1 second diff --git a/lib/stdlib/test/sys_SUITE.erl b/lib/stdlib/test/sys_SUITE.erl index f38bc87ae5..047ee9f1fa 100644 --- a/lib/stdlib/test/sys_SUITE.erl +++ b/lib/stdlib/test/sys_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -202,14 +202,7 @@ spec_proc(Mod) -> {Mod,system_get_state},{throw,fail}},_}} -> ok end, - Mod:stop(), - WaitForUnregister = fun W() -> - case whereis(Mod) of - undefined -> ok; - _ -> timer:sleep(10), W() - end - end, - WaitForUnregister(), + ok = sys:terminate(Mod, normal), {ok,_} = Mod:start_link(4), ok = case catch sys:replace_state(Mod, fun(_) -> {} end) of {} -> @@ -218,8 +211,7 @@ spec_proc(Mod) -> {Mod,system_replace_state},{throw,fail}},_}} -> ok end, - Mod:stop(), - WaitForUnregister(), + ok = sys:terminate(Mod, normal), {ok,_} = Mod:start_link(4), StateFun = fun(_) -> error(fail) end, ok = case catch sys:replace_state(Mod, StateFun) of @@ -231,7 +223,7 @@ spec_proc(Mod) -> {'EXIT',{{callback_failed,StateFun,{error,fail}},_}} -> ok end, - Mod:stop(). + ok = sys:terminate(Mod, normal). %%%%%%%%%%%%%%%%%%%% %% Dummy server diff --git a/lib/stdlib/test/sys_sp1.erl b/lib/stdlib/test/sys_sp1.erl index e84ffcfa12..0fb288991f 100644 --- a/lib/stdlib/test/sys_sp1.erl +++ b/lib/stdlib/test/sys_sp1.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -17,7 +17,7 @@ %% %CopyrightEnd% %% -module(sys_sp1). --export([start_link/1, stop/0]). +-export([start_link/1]). -export([alloc/0, free/1]). -export([init/1]). -export([system_continue/3, system_terminate/4, @@ -31,10 +31,6 @@ start_link(NumCh) -> proc_lib:start_link(?MODULE, init, [[self(),NumCh]]). -stop() -> - ?MODULE ! stop, - ok. - alloc() -> ?MODULE ! {self(), alloc}, receive @@ -70,11 +66,7 @@ loop(Chs, Parent, Deb) -> loop(Chs2, Parent, Deb2); {system, From, Request} -> sys:handle_system_msg(Request, From, Parent, - ?MODULE, Deb, Chs); - stop -> - sys:handle_debug(Deb, fun write_debug/3, - ?MODULE, {in, stop}), - ok + ?MODULE, Deb, Chs) end. system_continue(Parent, Deb, Chs) -> diff --git a/lib/stdlib/test/sys_sp2.erl b/lib/stdlib/test/sys_sp2.erl index 56a5e4d071..a0847b5838 100644 --- a/lib/stdlib/test/sys_sp2.erl +++ b/lib/stdlib/test/sys_sp2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -17,7 +17,7 @@ %% %CopyrightEnd% %% -module(sys_sp2). --export([start_link/1, stop/0]). +-export([start_link/1]). -export([alloc/0, free/1]). -export([init/1]). -export([system_continue/3, system_terminate/4, @@ -30,10 +30,6 @@ start_link(NumCh) -> proc_lib:start_link(?MODULE, init, [[self(),NumCh]]). -stop() -> - ?MODULE ! stop, - ok. - alloc() -> ?MODULE ! {self(), alloc}, receive @@ -45,11 +41,6 @@ free(Ch) -> ?MODULE ! {free, Ch}, ok. -%% can't use 2-tuple for state here as we do in sys_sp1, since the 2-tuple -%% is not compatible with the backward compatibility handling for -%% sys:get_state in sys.erl --record(state, {alloc,free}). - init([Parent,NumCh]) -> register(?MODULE, self()), Chs = channels(NumCh), @@ -74,11 +65,7 @@ loop(Chs, Parent, Deb) -> loop(Chs2, Parent, Deb2); {system, From, Request} -> sys:handle_system_msg(Request, From, Parent, - ?MODULE, Deb, Chs); - stop -> - sys:handle_debug(Deb, fun write_debug/3, - ?MODULE, {in, stop}), - ok + ?MODULE, Deb, Chs) end. system_continue(Parent, Deb, Chs) -> @@ -91,17 +78,17 @@ write_debug(Dev, Event, Name) -> io:format(Dev, "~p event = ~p~n", [Name, Event]). channels(NumCh) -> - #state{alloc=[], free=lists:seq(1,NumCh)}. + {_Allocated=[], _Free=lists:seq(1,NumCh)}. -alloc(#state{free=[]}=Channels) -> - {{error, "no channels available"}, Channels}; -alloc(#state{alloc=Allocated, free=[H|T]}) -> - {H, #state{alloc=[H|Allocated], free=T}}. +alloc({_, []}) -> + {error, "no channels available"}; +alloc({Allocated, [H|T]}) -> + {H, {[H|Allocated], T}}. -free(Ch, #state{alloc=Alloc, free=Free}=Channels) -> +free(Ch, {Alloc, Free}=Channels) -> case lists:member(Ch, Alloc) of true -> - #state{alloc=lists:delete(Ch, Alloc), free=[Ch|Free]}; + {lists:delete(Ch, Alloc), [Ch|Free]}; false -> Channels end. diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index 37a6590b06..9881ab040e 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 2.0 +STDLIB_VSN = 2.1.1 diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml index 4e1e6d8cb1..8384af53b0 100644 --- a/lib/syntax_tools/doc/src/notes.xml +++ b/lib/syntax_tools/doc/src/notes.xml @@ -31,6 +31,45 @@ <p>This document describes the changes made to the Syntax_Tools application.</p> +<section><title>Syntax_Tools 1.6.16</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> The default encoding for Erlang source files is now + UTF-8. As a temporary measure to ease the transition from + the old default of Latin-1, if EDoc encounters byte + sequences that are not valid UTF-8 sequences, EDoc will + re-try in Latin-1 mode. This workaround will be removed + in a future release. </p> + <p> + Own Id: OTP-12008</p> + </item> + </list> + </section> + +</section> + +<section><title>Syntax_Tools 1.6.15</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix reverting map in syntax_tools</p> + <p> + There was a bug in erl_syntax when running e.g. + erl_syntax:revert_forms, affecting maps. Instead of + getting Key/Value you got Key/Key in the resulting + abstract form.</p> + <p> + Own Id: OTP-11930</p> + </item> + </list> + </section> + +</section> + <section><title>Syntax_Tools 1.6.14</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl index 131be4e8e4..7e12eab1b5 100644 --- a/lib/syntax_tools/src/epp_dodger.erl +++ b/lib/syntax_tools/src/epp_dodger.erl @@ -184,9 +184,27 @@ quick_parse_file(File, Options) -> parse_file(File, fun quick_parse/3, Options ++ [no_fail]). parse_file(File, Parser, Options) -> + case do_parse_file(utf8, File, Parser, Options) of + {ok, Forms}=Ret -> + case find_invalid_unicode(Forms) of + none -> + Ret; + invalid_unicode -> + case epp:read_encoding(File) of + utf8 -> + Ret; + _ -> + do_parse_file(latin1, File, Parser, Options) + end + end; + Else -> + Else + end. + +do_parse_file(DefEncoding, File, Parser, Options) -> case file:open(File, [read]) of {ok, Dev} -> - _ = epp:set_encoding(Dev), + _ = epp:set_encoding(Dev, DefEncoding), try Parser(Dev, 1, Options) after ok = file:close(Dev) end; @@ -194,6 +212,14 @@ parse_file(File, Parser, Options) -> Error end. +find_invalid_unicode([H|T]) -> + case H of + {error, {_Line, file_io_server, invalid_unicode}} -> + invalid_unicode; + _Other -> + find_invalid_unicode(T) + end; +find_invalid_unicode([]) -> none. %% ===================================================================== %% @spec parse(IODevice) -> {ok, Forms} | {error, errorinfo()} diff --git a/lib/syntax_tools/src/erl_comment_scan.erl b/lib/syntax_tools/src/erl_comment_scan.erl index dae7530ce7..03429d4d42 100644 --- a/lib/syntax_tools/src/erl_comment_scan.erl +++ b/lib/syntax_tools/src/erl_comment_scan.erl @@ -72,13 +72,24 @@ file(Name) -> {ok, V} -> case V of {ok, B} -> - Enc = case epp:read_encoding(Name) of + Encoding = epp:read_encoding_from_binary(B), + Enc = case Encoding of none -> epp:default_encoding(); Enc0 -> Enc0 end, case catch unicode:characters_to_list(B, Enc) of String when is_list(String) -> string(String); + R when Encoding =:= none -> + case + catch unicode:characters_to_list(B, latin1) + of + String when is_list(String) -> + string(String); + _ -> + error_read_file(Name1), + exit(R) + end; R -> error_read_file(Name1), exit(R) diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 46a5ca48df..7f1e7dda31 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -3320,6 +3320,11 @@ attribute_arguments(Node) -> [set_pos( list(unfold_function_names(Data, Pos)), Pos)]; + optional_callbacks -> + D = try list(unfold_function_names(Data, Pos)) + catch _:_ -> abstract(Data) + end, + [set_pos(D, Pos)]; import -> {Module, Imports} = Data, [set_pos(atom(Module), Pos), @@ -6129,6 +6134,13 @@ abstract_tail(H, T) -> %% {@link char/1} function to explicitly create an abstract %% character.) %% +%% Note: `arity_qualifier' nodes are recognized. This is to follow The +%% Erlang Parser when it comes to wild attributes: both {F, A} and F/A +%% are recognized, which makes it possible to turn wild attributes +%% into recognized attributes without at the same time making it +%% impossible to compile files using the new syntax with the old +%% version of the Erlang Compiler. +%% %% @see abstract/1 %% @see is_literal/1 %% @see char/1 @@ -6170,6 +6182,20 @@ concrete(Node) -> {value, concrete(F), []} end, [], true), B; + arity_qualifier -> + A = erl_syntax:arity_qualifier_argument(Node), + case erl_syntax:type(A) of + integer -> + F = erl_syntax:arity_qualifier_body(Node), + case erl_syntax:type(F) of + atom -> + {F, A}; + _ -> + erlang:error({badarg, Node}) + end; + _ -> + erlang:error({badarg, Node}) + end; _ -> erlang:error({badarg, Node}) end. diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk index cf396ce636..6a80734f83 100644 --- a/lib/syntax_tools/vsn.mk +++ b/lib/syntax_tools/vsn.mk @@ -1 +1 @@ -SYNTAX_TOOLS_VSN = 1.6.14 +SYNTAX_TOOLS_VSN = 1.6.16 diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml index 556fe94a2a..a801a87725 100644 --- a/lib/test_server/doc/src/notes.xml +++ b/lib/test_server/doc/src/notes.xml @@ -32,6 +32,45 @@ <file>notes.xml</file> </header> +<section><title>Test_Server 3.7.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The mechanism for running code cover analysis with + common_test has been improved. Earlier, if a test run + consisted of multiple tests, cover would be started and + stopped for each test. This would give "intermediate" + cover logs available from the "Coverage log" link on the + test suite result pages. To accumulate cover data over + all tests, the 'export' option had to be used in the + cover spec file. This was not well documented, and the + functionality was quite confusing.</p> + <p> + Using the 'nodes' option in the cover spec file would + fail when the test run consisted of multiple tests, since + the specified nodes would only be included in the cover + analysis of the first test.</p> + <p> + The repeated compilation and analysis of the same modules + was also very time consuming.</p> + <p> + To overcome these problems, ct will now only cover + compile and analyze modules once per test run, i.e. once + for each cover spec file. The log file is available via a + new button on the top level index page. The old "Coverage + log" links on the test suite result pages still exist, + but they all point to the same log containing the + accumulated result.</p> + <p> + Own Id: OTP-11971</p> + </item> + </list> + </section> + +</section> + <section><title>Test_Server 3.7</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 70dc7a1441..9192a76a17 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -22,7 +22,7 @@ %%% TEST_SERVER_CTRL INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export([run_test_case_apply/1,init_target_info/0,init_purify/0]). --export([cover_compile/1,cover_analyse/3]). +-export([cover_compile/1,cover_analyse/2]). %%% TEST_SERVER_SUP INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export([get_loc/1,set_tc_state/1]). @@ -80,8 +80,8 @@ init_purify() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% cover_compile({App,Include,Exclude,Cross}) -> -%% {ok,AnalyseModules} | {error,Reason} +%% cover_compile(#cover{app=App,incl=Include,excl=Exclude,cross=Cross}) -> +%% {ok,#cover{mods=AnalyseModules}} | {error,Reason} %% %% App = atom() , name of application to be compiled %% Exclude = [atom()], list of modules to exclude @@ -90,33 +90,35 @@ init_purify() -> %% Cross = [atoms()], list of modules outside of App shat should be included %% in the cover compilation, but that shall not be part of %% the cover analysis for this application. +%% AnalyseModules = [atom()], list of successfully compiled modules %% -%% Cover compile the given application. Return {ok,AnalyseMods} if application -%% is found, else {error,application_not_found}. +%% Cover compile the given application. Return {ok,CoverInfo} if +%% compilation succeeds, else (if application is not found and there +%% are no modules to compile) {error,application_not_found}. -cover_compile({none,_Exclude,Include,Cross}) -> +cover_compile(CoverInfo=#cover{app=none,incl=Include,cross=Cross}) -> CrossMods = lists:flatmap(fun({_,M}) -> M end,Cross), CompileMods = Include++CrossMods, case length(CompileMods) of 0 -> io:fwrite("WARNING: No modules to cover compile!\n\n",[]), cover:start(), % start cover server anyway - {ok,[]}; + {ok,CoverInfo#cover{mods=[]}}; N -> io:fwrite("Cover compiling ~w modules - " "this may take some time... ",[N]), do_cover_compile(CompileMods), io:fwrite("done\n\n",[]), - {ok,Include} + {ok,CoverInfo#cover{mods=Include}} end; -cover_compile({App,all,Include,Cross}) -> +cover_compile(CoverInfo=#cover{app=App,excl=all,incl=Include,cross=Cross}) -> CrossMods = lists:flatmap(fun({_,M}) -> M end,Cross), CompileMods = Include++CrossMods, case length(CompileMods) of 0 -> io:fwrite("WARNING: No modules to cover compile!\n\n",[]), cover:start(), % start cover server anyway - {ok,[]}; + {ok,CoverInfo#cover{mods=[]}}; N -> io:fwrite("Cover compiling '~w' (~w files) - " "this may take some time... ",[App,N]), @@ -126,9 +128,9 @@ cover_compile({App,all,Include,Cross}) -> "~tp\n", [App,CompileMods]), do_cover_compile(CompileMods), io:fwrite("done\n\n",[]), - {ok,Include} + {ok,CoverInfo#cover{mods=Include}} end; -cover_compile({App,Exclude,Include,Cross}) -> +cover_compile(CoverInfo=#cover{app=App,excl=Exclude,incl=Include,cross=Cross}) -> CrossMods = lists:flatmap(fun({_,M}) -> M end,Cross), case code:lib_dir(App) of {error,bad_name} -> @@ -146,7 +148,7 @@ cover_compile({App,Exclude,Include,Cross}) -> "~tp\n", [App,Include]), do_cover_compile(CompileMods), io:fwrite("done\n\n",[]), - {ok,Include} + {ok,CoverInfo#cover{mods=Include}} end; LibDir -> EbinDir = filename:join([LibDir,"ebin"]), @@ -158,13 +160,13 @@ cover_compile({App,Exclude,Include,Cross}) -> 0 -> io:fwrite("WARNING: No modules to cover compile!\n\n",[]), cover:start(), % start cover server anyway - {ok,[]}; + {ok,CoverInfo#cover{mods=[]}}; N -> io:fwrite("Cover compiling '~w' (~w files) - " "this may take some time... ",[App,N]), do_cover_compile(CompileMods), io:fwrite("done\n\n",[]), - {ok,AnalyseMods} + {ok,CoverInfo#cover{mods=AnalyseMods}} end end. @@ -174,9 +176,11 @@ module_names(Beams) -> do_cover_compile(Modules) -> - do_cover_compile1(lists:usort(Modules)). % remove duplicates + cover:start(), + pmap1(fun(M) -> do_cover_compile1(M) end,lists:usort(Modules)), + ok. -do_cover_compile1([M|Rest]) -> +do_cover_compile1(M) -> case {code:is_sticky(M),code:is_loaded(M)} of {true,_} -> code:unstick_mod(M), @@ -187,15 +191,13 @@ do_cover_compile1([M|Rest]) -> io:fwrite("\nWARNING: Could not cover compile ~w: ~p\n", [M,Error]) end, - code:stick_mod(M), - do_cover_compile1(Rest); + code:stick_mod(M); {false,false} -> case code:load_file(M) of {module,_} -> - do_cover_compile1([M|Rest]); + do_cover_compile1(M); Error -> - io:fwrite("\nWARNING: Could not load ~w: ~p\n",[M,Error]), - do_cover_compile1(Rest) + io:fwrite("\nWARNING: Could not load ~w: ~p\n",[M,Error]) end; {false,_} -> case cover:compile_beam(M) of @@ -204,23 +206,52 @@ do_cover_compile1([M|Rest]) -> Error -> io:fwrite("\nWARNING: Could not cover compile ~w: ~p\n", [M,Error]) - end, - do_cover_compile1(Rest) - end; -do_cover_compile1([]) -> - ok. + end + end. + +pmap1(Fun,List) -> + NTot = length(List), + NProcs = erlang:system_info(schedulers) * 2, + NPerProc = (NTot div NProcs) + 1, + + {[],Pids} = + lists:foldr( + fun(_,{L,Ps}) -> + {L1,L2} = if length(L)>=NPerProc -> lists:split(NPerProc,L); + true -> {L,[]} % last chunk + end, + {P,_Ref} = + spawn_monitor(fun() -> + exit(lists:map(Fun,L1)) + end), + {L2,[P|Ps]} + end, + {List,[]}, + lists:seq(1,NProcs)), + collect(Pids,[]). + +collect([],Acc) -> + lists:append(Acc); +collect([Pid|Pids],Acc) -> + receive + {'DOWN', _Ref, process, Pid, Result} -> + %% collect(lists:delete(Pid,Pids),[Result|Acc]) + collect(Pids,[Result|Acc]) + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% cover_analyse(Analyse,Modules,Stop) -> [{M,{Cov,NotCov,Details}}] +%% cover_analyse(Dir,#cover{level=Analyse,mods=Modules,stop=Stop) -> +%% [{M,{Cov,NotCov,Details}}] %% -%% Analyse = {details,Dir} | details | {overview,void()} | overview +%% Dir = string() +%% Analyse = details | overview %% Modules = [atom()], the modules to analyse %% -%% Cover analysis. If Analyse=={details,Dir} analyse_to_file is used. +%% Cover analysis. If Analyse==details analyse_to_file is used. %% -%% If Analyse=={overview,Dir} analyse_to_file is not used, only an -%% overview containing the number of covered/not covered lines in each -%% module. +%% If Analyse==overview analyse_to_file is not used, only an overview +%% containing the number of covered/not covered lines in each module. %% %% Also, cover data will be exported to a file called all.coverdata in %% the given directory. @@ -235,11 +266,11 @@ do_cover_compile1([]) -> %% which means that the modules will stay cover compiled. Note that %% this is only recommended if the erlang node is being terminated %% after the test is completed. -cover_analyse(Analyse,Modules,Stop) -> - print(stdout, "Cover analysing...\n", []), +cover_analyse(Dir,#cover{level=Analyse,mods=Modules,stop=Stop}) -> + io:fwrite(user, "Cover analysing... ", []), DetailsFun = case Analyse of - {details,Dir} -> + details -> case cover:export(filename:join(Dir,"all.coverdata")) of ok -> fun(M) -> @@ -256,7 +287,7 @@ cover_analyse(Analyse,Modules,Stop) -> Error -> fun(_) -> Error end end; - {overview,Dir} -> + overview -> case cover:export(filename:join(Dir,"all.coverdata")) of ok -> fun(_) -> undefined end; @@ -264,17 +295,19 @@ cover_analyse(Analyse,Modules,Stop) -> fun(_) -> Error end end end, - R = pmap( + R = pmap2( fun(M) -> case cover:analyse(M,module) of {ok,{M,{Cov,NotCov}}} -> {M,{Cov,NotCov,DetailsFun(M)}}; Err -> - io:fwrite("WARNING: Analysis failed for ~w. Reason: ~p\n", + io:fwrite(user, + "\nWARNING: Analysis failed for ~w. Reason: ~p\n", [M,Err]), {M,Err} end end, Modules), + io:fwrite(user, "done\n\n", []), case Stop of true -> @@ -286,12 +319,12 @@ cover_analyse(Analyse,Modules,Stop) -> end, R. -pmap(Fun,List) -> +pmap2(Fun,List) -> Collector = self(), Pids = lists:map(fun(E) -> spawn(fun() -> - Collector ! {res,self(),Fun(E)} - end) + Collector ! {res,self(),Fun(E)} + end) end, List), lists:map(fun(Pid) -> receive @@ -300,7 +333,6 @@ pmap(Fun,List) -> end end, Pids). - do_cover_for_node(Node,CoverFunc) -> do_cover_for_node(Node,CoverFunc,true). do_cover_for_node(Node,CoverFunc,StickUnstick) -> diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 5fbc47a813..af8921fe75 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2013. All Rights Reserved. +%% Copyright Ericsson AB 2002-2014. 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 @@ -52,7 +52,9 @@ -export([reject_io_reqs/1, get_levels/0, set_levels/3]). -export([multiply_timetraps/1, scale_timetraps/1, get_timetrap_parameters/0]). -export([create_priv_dir/1]). --export([cover/2, cover/3, cover/8, cross_cover_analyse/2, trc/1, stop_trace/0]). +-export([cover/1, cover/2, cover/3, + cover_compile/7, cover_analyse/2, cross_cover_analyse/2, + trc/1, stop_trace/0]). -export([testcase_callback/1]). -export([set_random_seed/1]). -export([kill_slavenodes/0]). @@ -409,11 +411,26 @@ cover(App, Analyse) when is_atom(App) -> cover(CoverFile, Analyse) -> cover(none, CoverFile, Analyse). cover(App, CoverFile, Analyse) -> - controller_call({cover,{App,CoverFile},Analyse,true}). -cover(App, CoverFile, Exclude, Include, Cross, Export, Analyse, Stop) -> - controller_call({cover, - {App,{CoverFile,Exclude,Include,Cross,Export}}, - Analyse,Stop}). + {Excl,Incl,Cross} = read_cover_file(CoverFile), + CoverInfo = #cover{app=App, + file=CoverFile, + excl=Excl, + incl=Incl, + cross=Cross, + level=Analyse}, + controller_call({cover,CoverInfo}). + +cover(CoverInfo) -> + controller_call({cover,CoverInfo}). + +cover_compile(App,File,Excl,Incl,Cross,Analyse,Stop) -> + cover_compile(#cover{app=App, + file=File, + excl=Excl, + incl=Incl, + cross=Cross, + level=Analyse, + stop=Stop}). testcase_callback(ModFunc) -> controller_call({testcase_callback,ModFunc}). @@ -563,7 +580,7 @@ handle_call({add_job,Dir,Name,TopCase,Skip}, _From, State) -> ExtraTools = case State#state.cover of false -> []; - {App,Analyse,Stop} -> [{cover,App,Analyse,Stop}] + CoverInfo -> [{cover,CoverInfo}] end, ExtraTools1 = case State#state.random_seed of @@ -816,13 +833,13 @@ handle_call(stop_trace, _From, State) -> {reply,R,State#state{trc=false}}; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% handle_call({cover,App,Analyse,Stop}, _, State) -> ok | {error,Reason} +%% handle_call({cover,CoverInfo}, _, State) -> ok | {error,Reason} %% -%% All modules inn application App are cover compiled -%% Analyse indicates on which level the coverage should be analysed +%% Set specification of cover analysis to be used when running tests +%% (see start_extra_tools/1 and stop_extra_tools/1) -handle_call({cover,App,Analyse,Stop}, _From, State) -> - {reply,ok,State#state{cover={App,Analyse,Stop}}}; +handle_call({cover,CoverInfo}, _From, State) -> + {reply,ok,State#state{cover=CoverInfo}}; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% handle_call({create_priv_dir,Value}, _, State) -> ok | {error,Reason} @@ -1203,11 +1220,10 @@ elapsed_time(Before, After) -> start_extra_tools(ExtraTools) -> start_extra_tools(ExtraTools, []). -start_extra_tools([{cover,App,Analyse,Stop} | ExtraTools], Started) -> - case cover_compile(App) of - {ok,AnalyseMods} -> - start_extra_tools(ExtraTools, - [{cover,App,Analyse,AnalyseMods,Stop}|Started]); +start_extra_tools([{cover,CoverInfo} | ExtraTools], Started) -> + case start_cover(CoverInfo) of + {ok,NewCoverInfo} -> + start_extra_tools(ExtraTools,[{cover,NewCoverInfo}|Started]); {error,_} -> start_extra_tools(ExtraTools, Started) end; @@ -1226,8 +1242,8 @@ stop_extra_tools(ExtraTools) -> end, stop_extra_tools(ExtraTools, TestDir). -stop_extra_tools([{cover,App,Analyse,AnalyseMods,Stop}|ExtraTools], TestDir) -> - cover_analyse(App, Analyse, AnalyseMods, Stop, TestDir), +stop_extra_tools([{cover,CoverInfo}|ExtraTools], TestDir) -> + stop_cover(CoverInfo,TestDir), stop_extra_tools(ExtraTools, TestDir); %%stop_extra_tools([_ | ExtraTools], TestDir) -> %% stop_extra_tools(ExtraTools, TestDir); @@ -1569,16 +1585,24 @@ do_test_cases(TopCases, SkipCases, ok end end, - + CoverLog = + case get(test_server_cover_log_dir) of + undefined -> + ?coverlog_name; + AbsLogDir -> + AbsLog = filename:join(AbsLogDir,?coverlog_name), + make_relative(AbsLog, TestDir) + end, print(html, "<p><ul>\n" "<li><a href=\"~ts\">Full textual log</a></li>\n" "<li><a href=\"~ts\">Coverage log</a></li>\n" "<li><a href=\"~ts\">Unexpected I/O log</a></li>\n</ul></p>\n", - [?suitelog_name,?coverlog_name,?unexpected_io_log]), + [?suitelog_name,CoverLog,?unexpected_io_log]), print(html, "<p>~ts</p>\n" ++ - xhtml("<table bgcolor=\"white\" border=\"3\" cellpadding=\"5\">", + xhtml(["<table bgcolor=\"white\" border=\"3\" cellpadding=\"5\">\n", + "<thead>\n"], ["<table id=\"",?sortable_table_name,"\">\n", "<thead>\n"]) ++ "<tr><th>Num</th><th>Module</th><th>Group</th>" ++ @@ -5087,15 +5111,15 @@ pinfo(P) -> %% Cover compilation %% The compilation is executed on the target node -cover_compile({App,{_File,Exclude,Include,Cross,_Export}}) -> - cover_compile1({App,Exclude,Include,Cross}); +start_cover(#cover{}=CoverInfo) -> + cover_compile(CoverInfo); +start_cover({log,CoverLogDir}=CoverInfo) -> + %% Cover is controlled by the framework - here's the log + put(test_server_cover_log_dir,CoverLogDir), + {ok,CoverInfo}. -cover_compile({App,CoverFile}) -> - {Exclude,Include,Cross} = read_cover_file(CoverFile), - cover_compile1({App,Exclude,Include,Cross}). - -cover_compile1(What) -> - test_server:cover_compile(What). +cover_compile(CoverInfo) -> + test_server:cover_compile(CoverInfo). %% Read the coverfile for an application and return a list of modules %% that are members of the application but shall not be compiled @@ -5163,25 +5187,45 @@ check_cross([]) -> %% %% This per application analysis writes the file cover.html in the %% application's run.<timestamp> directory. -cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> +stop_cover(#cover{}=CoverInfo, TestDir) -> + cover_analyse(CoverInfo, TestDir); +stop_cover(_CoverInfo, _TestDir) -> + %% Cover is probably controlled by the framework + ok. + +make_relative(AbsDir, VsDir) -> + DirTokens = filename:split(AbsDir), + VsTokens = filename:split(VsDir), + filename:join(make_relative1(DirTokens, VsTokens)). + +make_relative1([T | DirTs], [T | VsTs]) -> + make_relative1(DirTs, VsTs); +make_relative1(Last = [_File], []) -> + Last; +make_relative1(Last = [_File], VsTs) -> + Ups = ["../" || _ <- VsTs], + Ups ++ Last; +make_relative1(DirTs, []) -> + DirTs; +make_relative1(DirTs, VsTs) -> + Ups = ["../" || _ <- VsTs], + Ups ++ DirTs. + + +cover_analyse(CoverInfo, TestDir) -> write_default_cross_coverlog(TestDir), {ok,CoverLog} = open_html_file(filename:join(TestDir, ?coverlog_name)), write_coverlog_header(CoverLog), + #cover{app=App, + file=CoverFile, + excl=Excluded, + cross=Cross} = CoverInfo, io:fwrite(CoverLog, "<h1>Coverage for application '~w'</h1>\n", [App]), io:fwrite(CoverLog, "<p><a href=\"~ts\">Coverdata collected over all tests</a></p>", [?cross_coverlog_name]), - {CoverFile,_Included,Excluded,Cross} = - case CoverInfo of - {File,Excl,Incl,Cr,Export} -> - cover:export(Export), - {File,Incl,Excl,Cr}; - File -> - {Excl,Incl,Cr} = read_cover_file(File), - {File,Incl,Excl,Cr} - end, io:fwrite(CoverLog, "<p>CoverFile: <code>~tp</code>\n", [CoverFile]), write_cross_cover_info(TestDir,Cross), @@ -5196,7 +5240,7 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> io:fwrite(CoverLog, "<p>Excluded module(s): <code>~tp</code>\n", [Excluded]), - Coverage = cover_analyse(Analyse, AnalyseMods, Stop), + Coverage = test_server:cover_analyse(TestDir, CoverInfo), write_binary_file(filename:join(TestDir,?raw_coverlog_name), term_to_binary(Coverage)), @@ -5215,11 +5259,6 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> write_binary_file(filename:join(TestDir, ?cover_total), term_to_binary(TotPercent)). -cover_analyse(Analyse, AnalyseMods, Stop) -> - TestDir = get(test_server_log_dir_base), - test_server:cover_analyse({Analyse,TestDir}, AnalyseMods, Stop). - - %% Cover analysis - accumulated over multiple tests %% This can be executed on any node after all tests are finished. %% Analyse = overview | details diff --git a/lib/test_server/src/test_server_internal.hrl b/lib/test_server/src/test_server_internal.hrl index 4e734a330b..bafeeaabfe 100644 --- a/lib/test_server/src/test_server_internal.hrl +++ b/lib/test_server/src/test_server_internal.hrl @@ -49,3 +49,12 @@ master, cookie}). + +-record(cover, {app, % application; Name | none + file, % cover spec file + incl, % explicitly include modules + excl, % explicitly exclude modules + level, % analyse level; details | overview + mods, % actually cover compiled modules + stop=true, % stop cover after analyse; boolean() + cross}).% cross cover analyse info diff --git a/lib/test_server/src/ts.erl b/lib/test_server/src/ts.erl index bc7d244c7c..d6d2e865e2 100644 --- a/lib/test_server/src/ts.erl +++ b/lib/test_server/src/ts.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. 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 @@ -641,16 +641,17 @@ get_last_app_tests([Dir|Dirs],RE,Acc) -> NewAcc = case re:run(Dir,RE,[{capture,all,list}]) of {match,[Dir,AppStr]} -> + Dir1 = filename:dirname(Dir), % cover logs in ct_run.<t> dir App = list_to_atom(AppStr), case lists:keytake(App,1,Acc) of {value,{App,LastDir},Rest} -> - if Dir > LastDir -> - [{App,Dir}|Rest]; + if Dir1 > LastDir -> + [{App,Dir1}|Rest]; true -> Acc end; false -> - [{App,Dir} | Acc] + [{App,Dir1} | Acc] end; _ -> Acc diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk index 4eb70aa2cd..9e1ac8fd12 100644 --- a/lib/test_server/vsn.mk +++ b/lib/test_server/vsn.mk @@ -1 +1 @@ -TEST_SERVER_VSN = 3.7 +TEST_SERVER_VSN = 3.7.1 diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index 136e0a3127..1ba2514977 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -30,6 +30,24 @@ </header> <p>This document describes the changes made to the Tools application.</p> +<section><title>Tools 2.6.15</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Removed <c>erlang:bitstr_to_list/1</c> and + <c>erlang:list_to_bitstr/1</c>. They were added by + mistake, and have always raised an <c>undefined</c> + exception when called.</p> + <p> + Own Id: OTP-11942</p> + </item> + </list> + </section> + +</section> + <section><title>Tools 2.6.14</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el index ec5a1f4bc5..4e3c49c717 100644 --- a/lib/tools/emacs/erlang.el +++ b/lib/tools/emacs/erlang.el @@ -853,7 +853,6 @@ resulting regexp is surrounded by \\_< and \\_>." "append_element" "await_proc_exit" "await_sched_wall_time_modifications" - "bitstr_to_list" "bump_reductions" "call_on_load_function" "cancel_timer" @@ -899,7 +898,6 @@ resulting regexp is surrounded by \\_< and \\_>." "hibernate" "insert_element" "is_builtin" - "list_to_bitstr" "load_nif" "loaded" "localtime" diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl index 20ee32c861..f1251fddab 100644 --- a/lib/tools/src/lcnt.erl +++ b/lib/tools/src/lcnt.erl @@ -61,6 +61,8 @@ locations/1, inspect/1, inspect/2, + histogram/1, + histogram/2, information/0, swap_pid_keys/0, % set options @@ -89,14 +91,14 @@ duration = 0 }). - -record(stats, { - file, - line, - tries, - colls, - time, % us - nt % #timings collected + file :: atom(), + line :: non_neg_integer(), + tries :: non_neg_integer(), + colls :: non_neg_integer(), + time :: non_neg_integer(), % us + nt :: non_neg_integer(), % #timings collected + hist :: tuple() % histogram }). -record(lock, { @@ -115,7 +117,9 @@ colls, cr, % collision ratio time, - dtr % time duration ratio + dtr, % time duration ratio + %% new + hist % log2 histogram of lock wait_time }). @@ -127,7 +131,7 @@ %% -------------------------------------------------------------------- %% start() -> gen_server:start({local, ?MODULE}, ?MODULE, [], []). -stop() -> gen_server:cast(?MODULE, stop). +stop() -> gen_server:call(?MODULE, stop, infinity). init([]) -> {ok, #state{ locks = [], duration = 0 } }. %% -------------------------------------------------------------------- %% @@ -171,6 +175,8 @@ conflicts() -> call({conflicts, []}). conflicts(Opts) -> call({conflicts, Opts}). inspect(Lock) -> call({inspect, Lock, []}). inspect(Lock, Opts) -> call({inspect, Lock, Opts}). +histogram(Lock) -> call({histogram, Lock, []}). +histogram(Lock, Opts)-> call({histogram, Lock, Opts}). information() -> call(information). swap_pid_keys() -> call(swap_pid_keys). raw() -> call(raw). @@ -283,14 +289,14 @@ handle_call({locations, InOpts}, _From, #state{ locks = Locks } = State) when is {reply, ok, State}; -handle_call({inspect, Lockname, InOpts}, _From, #state{ duration = Duration, locks = Locks } = State) when is_list(InOpts) -> +handle_call({inspect, Lockname, InOpts}, _From, #state{ duration=Duration, locks=Locks } = State) when is_list(InOpts) -> Default = [ {sort, time}, {reverse, false}, - {print, [name,id,tries,colls,ratio,time,duration]}, + {print, [name,id,tries,colls,ratio,time,duration,histogram]}, {max_locks, 20}, {combine, false}, - {thresholds, [] }, + {thresholds, []}, {locations, false}], Opts = options(InOpts, Default), @@ -299,7 +305,7 @@ handle_call({inspect, Lockname, InOpts}, _From, #state{ duration = Duration, loc {true, true} -> locks_ids(Filtered); _ -> [] end, - Combos = combine_classes(Filtered, proplists:get_value(combine, Opts)), + Combos = combine_classes(Filtered, proplists:get_value(combine, Opts)), case proplists:get_value(locations, Opts) of true -> lists:foreach(fun @@ -313,17 +319,14 @@ handle_call({inspect, Lockname, InOpts}, _From, #state{ duration = Duration, loc [] -> ok; _ -> - %io:format("Combined ~p~n", [Combined]), print("lock: " ++ term2string(Name)), print("id: " ++ IdString), print("type: " ++ term2string(Type)), Ps = stats2print(Combined, Duration), - Opts1 = options([{print, [entry, tries,colls,ratio,time,duration]}, + Opts1 = options([{print, [entry, tries,colls,ratio,time,duration,histogram]}, {thresholds, [{tries, -1}, {colls, -1}, {time, -1}]}], Opts), print_lock_information(filter_print(Ps, Opts1), proplists:get_value(print, Opts1)) end - % (#lock{ name = Name, id = Id}) -> - % io:format("Empty lock ~p ~p~n", [Name, Id]) end, Combos); _ -> Print1 = locks2print(Combos, Duration), @@ -332,6 +335,34 @@ handle_call({inspect, Lockname, InOpts}, _From, #state{ duration = Duration, loc end, {reply, ok, State}; +%% histogram + +handle_call({histogram, Lockname, InOpts}, _From, #state{ duration=Duration, locks=Locks} = State)-> + Default = [ + {sort, time}, + {reverse, false}, + {print, [name,id,tries,colls,ratio,time,duration,histogram]}, + {max_locks, 20}, + {combine, true}, + {thresholds, []}, + {locations, false}], + + Opts = options(InOpts, Default), + Filtered = filter_locks(Locks, Lockname), + Combos = combine_classes(Filtered, proplists:get_value(combine, Opts)), + lists:foreach(fun + (#lock{ stats = Stats }=L) -> + SumStats = summate_stats(Stats), + Opts1 = options([{print, [name,id,tries,colls,ratio,time,duration]}, + {thresholds, [{tries, -1}, {colls, -1}, {time, -1}]}], Opts), + Prints = locks2print([L], Duration), + print_lock_information(Prints, proplists:get_value(print, Opts1)), + print_full_histogram(SumStats#stats.hist), + io:format("~n") + end, Combos), + + {reply, ok, State}; + handle_call(raw, _From, #state{ locks = Locks} = State)-> {reply, Locks, State}; @@ -347,7 +378,6 @@ handle_call(swap_pid_keys, _From, #state{ locks = Locks } = State)-> (L) -> L end, Locks), - {reply, ok, State#state{ locks = SwappedLocks}}; % settings @@ -380,6 +410,8 @@ handle_call({save, Filename}, _From, State) -> {reply, {error, Error}, State} end; +handle_call(stop, _From, State) -> + {stop, normal, ok, State}; handle_call(Command, _From, State) -> {reply, {error, {undefined, Command}}, State}. @@ -390,8 +422,6 @@ handle_call(Command, _From, State) -> %% %% -------------------------------------------------------------------- %% -handle_cast(stop, State) -> - {stop, normal, State}; handle_cast(_, State) -> {noreply, State}. @@ -432,15 +462,32 @@ code_change(_OldVsn, State, _Extra) -> summate_locks(Locks) -> summate_locks(Locks, #stats{ tries = 0, colls = 0, time = 0, nt = 0}). summate_locks([], Stats) -> Stats; -summate_locks([L|Ls], #stats{ tries = Tries, colls = Colls, time = Time, nt = Nt}) -> +summate_locks([L|Ls], #stats{ tries = Tries, colls = Colls, time = Time, nt = Nt, hist = Hist}) -> S = summate_stats(L#lock.stats), - summate_locks(Ls, #stats{ tries = Tries + S#stats.tries, colls = Colls + S#stats.colls, time = Time + S#stats.time, nt = Nt + S#stats.nt}). + summate_locks(Ls, #stats{ + tries = Tries + S#stats.tries, + colls = Colls + S#stats.colls, + time = Time + S#stats.time, + nt = Nt + S#stats.nt, + hist = summate_histogram(Hist, S#stats.hist) + }). summate_stats(Stats) -> summate_stats(Stats, #stats{ tries = 0, colls = 0, time = 0, nt = 0}). summate_stats([], Stats) -> Stats; -summate_stats([S|Ss], #stats{ tries = Tries, colls = Colls, time = Time, nt = Nt}) -> - summate_stats(Ss, #stats{ tries = Tries + S#stats.tries, colls = Colls + S#stats.colls, time = Time + S#stats.time, nt = Nt + S#stats.nt}). - +summate_stats([S|Ss], #stats{ tries = Tries, colls = Colls, time = Time, nt = Nt, hist = Hist}) -> + summate_stats(Ss, #stats{ + tries = Tries + S#stats.tries, + colls = Colls + S#stats.colls, + time = Time + S#stats.time, + nt = Nt + S#stats.nt, + hist = summate_histogram(Hist, S#stats.hist) + }). + +%% first call is undefined +summate_histogram(Tup,undefined) when is_tuple(Tup) -> Tup; +summate_histogram(undefined,Tup) when is_tuple(Tup) -> Tup; +summate_histogram(Hs1,Hs2) -> + list_to_tuple([ A + B || {A,B} <- lists:zip(tuple_to_list(Hs1),tuple_to_list(Hs2))]). %% manipulators filter_locks_type(Locks, undefined) -> Locks; @@ -465,17 +512,16 @@ filter_print(PLs, Opts) -> TLs = threshold_locks(PLs, proplists:get_value(thresholds, Opts, [])), SLs = sort_locks(TLs, proplists:get_value(sort, Opts, time)), CLs = cut_locks(SLs, proplists:get_value(max_locks, Opts, none)), - reverse_locks(CLs, proplists:get_value(reverse, Opts, false)). - -sort_locks(Locks, Type) -> lists:reverse(sort_locks0(Locks, Type)). -sort_locks0(Locks, name) -> lists:keysort(#print.name, Locks); -sort_locks0(Locks, id) -> lists:keysort(#print.id, Locks); -sort_locks0(Locks, type) -> lists:keysort(#print.type, Locks); -sort_locks0(Locks, tries) -> lists:keysort(#print.tries, Locks); -sort_locks0(Locks, colls) -> lists:keysort(#print.colls, Locks); -sort_locks0(Locks, ratio) -> lists:keysort(#print.cr, Locks); -sort_locks0(Locks, time) -> lists:keysort(#print.time, Locks); -sort_locks0(Locks, _) -> sort_locks0(Locks, time). + reverse_locks(CLs, not proplists:get_value(reverse,Opts, false)). + +sort_locks(Locks, name) -> lists:keysort(#print.name, Locks); +sort_locks(Locks, id) -> lists:keysort(#print.id, Locks); +sort_locks(Locks, type) -> lists:keysort(#print.type, Locks); +sort_locks(Locks, tries) -> lists:keysort(#print.tries, Locks); +sort_locks(Locks, colls) -> lists:keysort(#print.colls, Locks); +sort_locks(Locks, ratio) -> lists:keysort(#print.cr, Locks); +sort_locks(Locks, time) -> lists:keysort(#print.time, Locks); +sort_locks(Locks, _) -> sort_locks(Locks, time). % cut locks not above certain thresholds threshold_locks(Locks, Thresholds) -> @@ -556,45 +602,61 @@ locks_ids(Locks) -> locks_ids(Locks, []). locks_ids([], Out) -> Out; locks_ids([#lock{ name = Key } = L|Ls], Out) -> case proplists:get_value(Key, Out) of - undefined -> - locks_ids(Ls, [{Key, [L#lock.id] } | Out]); - Ids -> - locks_ids(Ls, [{Key, [L#lock.id | Ids] } | proplists:delete(Key,Out)]) + undefined -> locks_ids(Ls, [{Key, [L#lock.id]}|Out]); + Ids -> locks_ids(Ls, [{Key, [L#lock.id|Ids]}|proplists:delete(Key,Out)]) end. stats2print(Stats, Duration) -> lists:map(fun (S) -> - #print{ - entry = term2string("~tp:~p", [S#stats.file, S#stats.line]), - colls = S#stats.colls, - tries = S#stats.tries, - cr = percent(S#stats.colls, S#stats.tries), - time = S#stats.time, - dtr = percent(S#stats.time, Duration) - } + #print{entry = term2string("~tp:~p", [S#stats.file, S#stats.line]), + colls = S#stats.colls, + tries = S#stats.tries, + cr = percent(S#stats.colls, S#stats.tries), + time = S#stats.time, + dtr = percent(S#stats.time, Duration), + hist = format_histogram(S#stats.hist)} end, Stats). locks2print(Locks, Duration) -> lists:map( fun (L) -> - Tries = lists:sum([T || #stats{ tries = T} <- L#lock.stats]), - Colls = lists:sum([C || #stats{ colls = C} <- L#lock.stats]), - Time = lists:sum([T || #stats{ time = T} <- L#lock.stats]), - Cr = percent(Colls, Tries), - Dtr = percent(Time, Duration), - #print{ - name = L#lock.name, - id = L#lock.id, - type = L#lock.type, - tries = Tries, - colls = Colls, - cr = Cr, - time = Time, - dtr = Dtr - } + #stats{tries = Tries, + colls = Colls, + time = Time, + hist = Hist} = summate_stats(L#lock.stats), + Cr = percent(Colls, Tries), + Dtr = percent(Time, Duration), + #print{name = L#lock.name, + id = L#lock.id, + type = L#lock.type, + tries = Tries, + colls = Colls, + hist = format_histogram(Hist), + cr = Cr, + time = Time, + dtr = Dtr} end, Locks). + +format_histogram(Tup) when is_tuple(Tup) -> + Vs = tuple_to_list(Tup), + Max = lists:max(Vs), + case Max of + 0 -> string_histogram(Vs); + _ -> string_histogram([case V of 0 -> 0; _ -> V/Max end || V <- Vs]) + end. + +string_histogram([0|Vs]) -> + [$\s|string_histogram(Vs)]; +string_histogram([V|Vs]) when V > 0.66 -> + [$X|string_histogram(Vs)]; +string_histogram([V|Vs]) when V > 0.33 -> + [$x|string_histogram(Vs)]; +string_histogram([_|Vs]) -> + [$.|string_histogram(Vs)]; +string_histogram([]) -> []. + %% state making data2state(Data, State) -> @@ -606,22 +668,32 @@ data2state(Data, State) -> locks = Locks }. -locks2records(Locks) -> locks2records(Locks, []). -locks2records([], Out) -> Out; -locks2records([{Name, Id, Type, Stats}|Locks], Out) -> - Lock = #lock{ - name = Name, - id = clean_id_creation(Id), - type = Type, - stats = [ #stats{ - file = File, - line = Line, - tries = Tries, - colls = Colls, - time = time2us({S, Ns}), - nt = N - } || {{File, Line}, {Tries, Colls, {S, Ns, N}}} <- Stats] }, - locks2records(Locks, [Lock|Out]). +locks2records([{Name, Id, Type, Stats}|Locks]) -> + [#lock{name = Name, + id = clean_id_creation(Id), + type = Type, + stats = stats2record(Stats)}|locks2records(Locks)]; +locks2records([]) -> []. + +%% new stats with histogram +stats2record([{{File,Line},{Tries,Colls,{S,Ns,N}},Hist}|Stats]) -> + [#stats{file = File, + line = Line, + hist = Hist, + tries = Tries, + colls = Colls, + time = time2us({S, Ns}), + nt = N} | stats2record(Stats)]; +%% old stats without histogram +stats2record([{{File,Line},{Tries,Colls,{S,Ns,N}}}|Stats]) -> + [#stats{file = File, + line = Line, + hist = {}, + tries = Tries, + colls = Colls, + time = time2us({S, Ns}), + nt = N} | stats2record(Stats)]; +stats2record([]) -> []. clean_id_creation(Id) when is_pid(Id) -> Bin = term_to_binary(Id), @@ -647,22 +719,45 @@ state2list(State) -> (X, Y) -> {X,Y} end, record_info(fields, state), Values). -list2state(List) -> list2state(record_info(fields, state), List, [state]). -list2state([], _, Out) -> list_to_tuple(lists:reverse(Out)); -list2state([locks|Fs], List, Out) -> - Locks = [ list2lock(Lock) || Lock <- proplists:get_value(locks, List, [])], - list2state(Fs, List, [Locks|Out]); -list2state([F|Fs], List, Out) -> list2state(Fs, List, [proplists:get_value(F, List, state_default(F))|Out]). - lock_default(Field) -> proplists:get_value(Field, lock2list(#lock{})). lock2list(Lock) -> [_|Values] = tuple_to_list(Lock), lists:zip(record_info(fields, lock), Values). -list2lock(List) -> list2lock(record_info(fields, lock), List, [lock]). -list2lock([], _, Out) -> list_to_tuple(lists:reverse(Out)); -list2lock([F|Fs], List, Out) -> list2lock(Fs, List, [proplists:get_value(F, List, lock_default(F))|Out]). + +list2state(List) -> + list_to_tuple([state|list2state(record_info(fields, state), List)]). +list2state([], _) -> []; +list2state([locks|Fs], List) -> + Locks = [list2lock(Lock) || Lock <- proplists:get_value(locks, List, [])], + [Locks|list2state(Fs,List)]; +list2state([F|Fs], List) -> + [proplists:get_value(F, List, state_default(F))|list2state(Fs, List)]. + +list2lock(Ls) -> + list_to_tuple([lock|list2lock(record_info(fields, lock), Ls)]). + +list2lock([],_) -> []; +list2lock([stats=F|Fs], Ls) -> + Stats = stats2stats(proplists:get_value(F, Ls, lock_default(F))), + [Stats|list2lock(Fs, Ls)]; +list2lock([F|Fs], Ls) -> + [proplists:get_value(F, Ls, lock_default(F))|list2lock(Fs, Ls)]. + +%% process old stats (hack) +%% old stats had no histograms +%% in future versions stats should be serialized as a list, not a record + +stats2stats([]) -> []; +stats2stats([Stat|Stats]) -> + Sz = tuple_size(#stats{}), + [stat2stat(Stat,Sz)|stats2stats(Stats)]. + +stat2stat(Stat,Sz) when tuple_size(Stat) =:= Sz -> Stat; +stat2stat(Stat,_) -> + %% assume no histogram at the end + list_to_tuple(tuple_to_list(Stat) ++ [{0}]). %% printing @@ -683,7 +778,7 @@ auto_print_width(Locks, Print) -> ({print,print}, Out) -> [print|Out]; ({Str, Len}, Out) -> [erlang:min(erlang:max(length(s(Str))+1,Len),80)|Out] end, [], lists:zip(tuple_to_list(L), tuple_to_list(Max))))) - end, #print{ id = 4, type = 5, entry = 5, name = 6, tries = 8, colls = 13, cr = 16, time = 11, dtr = 14 }, + end, #print{ id = 4, type = 5, entry = 5, name = 6, tries = 8, colls = 13, cr = 16, time = 11, dtr = 14, hist=20 }, Locks), % Setup the offsets for later pruning Offsets = [ @@ -695,7 +790,9 @@ auto_print_width(Locks, Print) -> {colls, R#print.colls}, {ratio, R#print.cr}, {time, R#print.time}, - {duration, R#print.dtr}], + {duration, R#print.dtr}, + {histogram, R#print.hist} + ], % Prune offsets to only allow specified print options lists:foldr(fun ({Type, W}, Out) -> [{Type, W}|Out]; @@ -705,9 +802,7 @@ auto_print_width(Locks, Print) -> print_lock_information(Locks, Print) -> % remake Print to autosize entries AutoPrint = auto_print_width(Locks, Print), - print_header(AutoPrint), - lists:foreach(fun (L) -> print_lock(L, AutoPrint) @@ -724,7 +819,8 @@ print_header(Opts) -> colls = "#collisions", cr = "collisions [%]", time = "time [us]", - dtr = "duration [%]" + dtr = "duration [%]", + hist = "histogram" }, Divider = #print{ name = lists:duplicate(1 + length(Header#print.name), 45), @@ -735,39 +831,44 @@ print_header(Opts) -> colls = lists:duplicate(1 + length(Header#print.colls), 45), cr = lists:duplicate(1 + length(Header#print.cr), 45), time = lists:duplicate(1 + length(Header#print.time), 45), - dtr = lists:duplicate(1 + length(Header#print.dtr), 45) + dtr = lists:duplicate(1 + length(Header#print.dtr), 45), + hist = lists:duplicate(1 + length(Header#print.hist), 45) }, print_lock(Header, Opts), print_lock(Divider, Opts), ok. -print_lock(L, Opts) -> print_lock(L, Opts, []). -print_lock(_, [], Formats) -> print(strings(lists:reverse(Formats))); -print_lock(L, [Opt|Opts], Formats) -> +print_lock(L, Opts) -> + print(strings(format_lock(L, Opts))). + +format_lock(_, []) -> []; +format_lock(L, [Opt|Opts]) -> case Opt of - id -> print_lock(L, Opts, [{space, 25, s(L#print.id) } | Formats]); - {id, W} -> print_lock(L, Opts, [{space, W, s(L#print.id) } | Formats]); - type -> print_lock(L, Opts, [{space, 18, s(L#print.type) } | Formats]); - {type, W} -> print_lock(L, Opts, [{space, W, s(L#print.type) } | Formats]); - entry -> print_lock(L, Opts, [{space, 30, s(L#print.entry)} | Formats]); - {entry, W} -> print_lock(L, Opts, [{space, W, s(L#print.entry)} | Formats]); - name -> print_lock(L, Opts, [{space, 22, s(L#print.name) } | Formats]); - {name, W} -> print_lock(L, Opts, [{space, W, s(L#print.name) } | Formats]); - tries -> print_lock(L, Opts, [{space, 12, s(L#print.tries)} | Formats]); - {tries, W} -> print_lock(L, Opts, [{space, W, s(L#print.tries)} | Formats]); - colls -> print_lock(L, Opts, [{space, 14, s(L#print.colls)} | Formats]); - {colls, W} -> print_lock(L, Opts, [{space, W, s(L#print.colls)} | Formats]); - ratio -> print_lock(L, Opts, [{space, 20, s(L#print.cr) } | Formats]); - {ratio, W} -> print_lock(L, Opts, [{space, W, s(L#print.cr) } | Formats]); - time -> print_lock(L, Opts, [{space, 15, s(L#print.time) } | Formats]); - {time, W} -> print_lock(L, Opts, [{space, W, s(L#print.time) } | Formats]); - duration -> print_lock(L, Opts, [{space, 20, s(L#print.dtr) } | Formats]); - {duration, W} -> print_lock(L, Opts, [{space, W, s(L#print.dtr) } | Formats]); - _ -> print_lock(L, Opts, Formats) + id -> [{space, 25, s(L#print.id) } | format_lock(L, Opts)]; + {id, W} -> [{space, W, s(L#print.id) } | format_lock(L, Opts)]; + type -> [{space, 18, s(L#print.type) } | format_lock(L, Opts)]; + {type, W} -> [{space, W, s(L#print.type) } | format_lock(L, Opts)]; + entry -> [{space, 30, s(L#print.entry)} | format_lock(L, Opts)]; + {entry, W} -> [{space, W, s(L#print.entry)} | format_lock(L, Opts)]; + name -> [{space, 22, s(L#print.name) } | format_lock(L, Opts)]; + {name, W} -> [{space, W, s(L#print.name) } | format_lock(L, Opts)]; + tries -> [{space, 12, s(L#print.tries)} | format_lock(L, Opts)]; + {tries, W} -> [{space, W, s(L#print.tries)} | format_lock(L, Opts)]; + colls -> [{space, 14, s(L#print.colls)} | format_lock(L, Opts)]; + {colls, W} -> [{space, W, s(L#print.colls)} | format_lock(L, Opts)]; + ratio -> [{space, 20, s(L#print.cr) } | format_lock(L, Opts)]; + {ratio, W} -> [{space, W, s(L#print.cr) } | format_lock(L, Opts)]; + time -> [{space, 15, s(L#print.time) } | format_lock(L, Opts)]; + {time, W} -> [{space, W, s(L#print.time) } | format_lock(L, Opts)]; + duration -> [{space, 20, s(L#print.dtr) } | format_lock(L, Opts)]; + {duration, W} -> [{space, W, s(L#print.dtr) } | format_lock(L, Opts)]; + histogram -> [{space, 0, s(L#print.hist) } | format_lock(L, Opts)]; + {histogram, W} -> [{space, W, s(L#print.hist) } | format_lock(L, Opts)]; + _ -> format_lock(L, Opts) end. -print_state_information(#state{ locks = Locks} = State) -> +print_state_information(#state{locks = Locks} = State) -> Stats = summate_locks(Locks), print("information:"), print(kv("#locks", s(length(Locks)))), @@ -779,9 +880,25 @@ print_state_information(#state{ locks = Locks} = State) -> print(kv("percent of duration", s(Stats#stats.time/State#state.duration*100) ++ " %")), ok. + +print_full_histogram(T) when is_tuple(T) -> + Vs = tuple_to_list(T), + Max = lists:max(Vs), + W = 60, + print_full_histogram(0,Vs,Max,W). + +print_full_histogram(_,[],_,_) -> ok; +print_full_histogram(Ix,[V|Vs],0,W) -> + io:format("~2w = log2 : ~8w |~n", [Ix,V]), + print_full_histogram(Ix+1,Vs,0,W); +print_full_histogram(Ix,[V|Vs],Max,W) -> + io:format("~2w = log2 : ~8w | ~s~n", [Ix,V,lists:duplicate(trunc(W*(V/Max)), $#)]), + print_full_histogram(Ix+1,Vs,Max,W). + + %% AUX -time2us({S, Ns}) -> round(S*1000000 + Ns/1000). +time2us({S, Ns}) -> S*1000000 + (Ns div 1000). percent(_,0) -> 0.0; percent(T,N) -> T/N*100. @@ -808,7 +925,7 @@ s(T) -> term2string(T). strings(Strings) -> strings(Strings, []). strings([], Out) -> Out; -strings([{space, N, S} | Ss], Out) -> strings(Ss, Out ++ term2string(term2string("~~~ps", [N]), [S])); +strings([{space, N, S} | Ss], Out) -> strings(Ss, Out ++ term2string(term2string("~~~ws", [N]), [S])); strings([{format, Format, S} | Ss], Out) -> strings(Ss, Out ++ term2string(Format, [S])); strings([S|Ss], Out) -> strings(Ss, Out ++ term2string("~ts", [S])). @@ -825,7 +942,7 @@ term2string(Term) when is_pid(Term) -> term2string(Term) -> term2string("~w", [Term]). term2string(Format, Terms) -> lists:flatten(io_lib:format(Format, Terms)). -%%% AUD id binary +%%% AUX id binary bytes16(Value) -> B0 = Value band 255, diff --git a/lib/tools/test/lcnt_SUITE.erl b/lib/tools/test/lcnt_SUITE.erl index 1bee6021ab..010dffe138 100644 --- a/lib/tools/test/lcnt_SUITE.erl +++ b/lib/tools/test/lcnt_SUITE.erl @@ -27,11 +27,11 @@ %% Test cases -export([ - load_v1/1, - conflicts/1, - locations/1, - swap_keys/1 - ]). + t_load/1, + t_conflicts/1, + t_locations/1, + t_swap_keys/1 + ]). %% Default timetrap timeout (set in init_per_testcase) -define(default_timeout, ?t:minutes(4)). @@ -54,48 +54,52 @@ end_per_testcase(_Case, Config) -> suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> - [load_v1, conflicts, locations, swap_keys]. +all() -> [t_load, t_conflicts, t_locations, t_swap_keys]. -groups() -> - []. +groups() -> []. -init_per_group(_GroupName, Config) -> - Config. +init_per_group(_GroupName, Config) -> Config. -end_per_group(_GroupName, Config) -> - Config. +end_per_group(_GroupName, Config) -> Config. %%---------------------------------------------------------------------- %% Tests %%---------------------------------------------------------------------- -load_v1(suite) -> - []; -load_v1(doc) -> - ["Load data from file."]; -load_v1(Config) when is_list(Config) -> - ?line {ok, _} = lcnt:start(), - ?line Path = ?config(data_dir, Config), - ?line File = filename:join([Path,"big_bang_40.lcnt"]), - ?line ok = lcnt:load(File), - ?line ok = lcnt:stop(), +t_load(suite) -> []; +t_load(doc) -> ["Load data from file."]; +t_load(Config) when is_list(Config) -> + Path = ?config(data_dir, Config), + Files = [filename:join([Path,"big_bang_40.lcnt"]), + filename:join([Path,"ehb_3_3_hist.lcnt"])], + ok = t_load_file(Files), ok. -conflicts(suite) -> - []; -conflicts(doc) -> - ["API: conflicts"]; -conflicts(Config) when is_list(Config) -> - ?line {ok, _} = lcnt:start(), - ?line Path = ?config(data_dir, Config), - ?line File = filename:join([Path,"big_bang_40.lcnt"]), - ?line ok = lcnt:load(File), - ?line ok = lcnt:conflicts(), - THs = [-1, 0, 100, 1000], - Print = [name , id , type , entry , tries , colls , ratio , time , duration], - Opts = [ +t_load_file([]) -> ok; +t_load_file([File|Files]) -> + {ok, _} = lcnt:start(), + ok = lcnt:load(File), + ok = lcnt:stop(), + t_load_file(Files). + +t_conflicts(suite) -> []; +t_conflicts(doc) -> ["API: conflicts"]; +t_conflicts(Config) when is_list(Config) -> + Path = ?config(data_dir, Config), + Files = [filename:join([Path,"big_bang_40.lcnt"]), + filename:join([Path,"ehb_3_3_hist.lcnt"])], + ok = t_conflicts_file(Files), + ok. + +t_conflicts_file([]) -> ok; +t_conflicts_file([File|Files]) -> + {ok, _} = lcnt:start(), + ok = lcnt:load(File), + ok = lcnt:conflicts(), + THs = [-1, 0, 100, 1000], + Print = [name , id , type , entry , tries , colls , ratio , time , duration], + Opts = [ [{sort, Sort}, {reverse, Rev}, {max_locks, ML}, {combine, Combine}, {thresholds, [TH]}, {print, [Print]}] || Sort <- [name , id , type , tries , colls , ratio , time , entry], ML <- [none, 1 , 32, 4096], @@ -103,28 +107,33 @@ conflicts(Config) when is_list(Config) -> TH <- [{tries, Tries} || Tries <- THs] ++ [{colls, Colls} || Colls <- THs] ++ [{time, Time} || Time <- THs], Rev <- [true, false] ], - ?line ok = test_conflicts_opts(Opts), - ?line ok = lcnt:stop(), - ok. + ok = test_conflicts_opts(Opts), + ok = lcnt:stop(), + t_conflicts_file(Files). + test_conflicts_opts([]) -> ok; test_conflicts_opts([Opt|Opts]) -> - ?line ok = lcnt:conflicts(Opt), + ok = lcnt:conflicts(Opt), test_conflicts_opts(Opts). -locations(suite) -> - []; -locations(doc) -> - ["API: locations"]; -locations(Config) when is_list(Config) -> - ?line {ok, _} = lcnt:start(), - ?line Path = ?config(data_dir, Config), - ?line File = filename:join([Path,"big_bang_40.lcnt"]), - ?line ok = lcnt:load(File), - ?line ok = lcnt:locations(), - THs = [-1, 0, 100, 1000], - Print = [name , id , type , entry , tries , colls , ratio , time , duration], - Opts = [ +t_locations(suite) -> []; +t_locations(doc) -> ["API: locations"]; +t_locations(Config) when is_list(Config) -> + Path = ?config(data_dir, Config), + Files = [filename:join([Path,"big_bang_40.lcnt"]), + filename:join([Path,"ehb_3_3_hist.lcnt"])], + ok = t_locations_file(Files), + ok. + +t_locations_file([]) -> ok; +t_locations_file([File|Files]) -> + {ok, _} = lcnt:start(), + ok = lcnt:load(File), + ok = lcnt:locations(), + THs = [-1, 0, 100, 1000], + Print = [name , id , type , entry , tries , colls , ratio , time , duration], + Opts = [ [{full_id, Id}, {sort, Sort}, {max_locks, ML}, {combine, Combine}, {thresholds, [TH]}, {print, Print}] || Sort <- [name , id , type , tries , colls , ratio , time , entry], ML <- [none, 1 , 64], @@ -132,30 +141,34 @@ locations(Config) when is_list(Config) -> TH <- [{tries, Tries} || Tries <- THs] ++ [{colls, Colls} || Colls <- THs] ++ [{time, Time} || Time <- THs], Id <- [true, false] ], - ?line ok = test_locations_opts(Opts), - ?line ok = lcnt:stop(), - ok. + ok = test_locations_opts(Opts), + ok = lcnt:stop(), + t_locations_file(Files). test_locations_opts([]) -> ok; test_locations_opts([Opt|Opts]) -> - ?line ok = lcnt:locations(Opt), + ok = lcnt:locations(Opt), test_locations_opts(Opts). -swap_keys(suite) -> - []; -swap_keys(doc) -> - ["Test interchanging port/process id with class"]; -swap_keys(Config) when is_list(Config) -> - ?line {ok, _} = lcnt:start(), - ?line Path = ?config(data_dir, Config), - ?line File = filename:join([Path,"big_bang_40.lcnt"]), - ?line ok = lcnt:load(File), - ?line ok = lcnt:conflicts(), - ?line ok = lcnt:swap_pid_keys(), - ?line ok = lcnt:conflicts(), - ?line ok = lcnt:stop(), +t_swap_keys(suite) -> []; +t_swap_keys(doc) -> ["Test interchanging port/process id with class"]; +t_swap_keys(Config) when is_list(Config) -> + Path = ?config(data_dir, Config), + Files = [filename:join([Path,"big_bang_40.lcnt"]), + filename:join([Path,"ehb_3_3_hist.lcnt"])], + ok = t_swap_keys_file(Files), ok. +t_swap_keys_file([]) -> ok; +t_swap_keys_file([File|Files]) -> + {ok, _} = lcnt:start(), + ok = lcnt:load(File), + ok = lcnt:conflicts(), + ok = lcnt:swap_pid_keys(), + ok = lcnt:conflicts(), + ok = lcnt:stop(), + t_swap_keys_file(Files). + %%---------------------------------------------------------------------- %% Auxiliary tests diff --git a/lib/tools/test/lcnt_SUITE_data/ehb_3_3_hist.lcnt b/lib/tools/test/lcnt_SUITE_data/ehb_3_3_hist.lcnt Binary files differnew file mode 100644 index 0000000000..ff5bdcbdaa --- /dev/null +++ b/lib/tools/test/lcnt_SUITE_data/ehb_3_3_hist.lcnt diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl index 353275ae3b..6870aefe5c 100644 --- a/lib/tools/test/xref_SUITE.erl +++ b/lib/tools/test/xref_SUITE.erl @@ -1098,7 +1098,6 @@ read_expected(Version) -> {POS1+1,{FF,{mod17,fun17,0}}}, {POS1+2,{FF,{erlang,spawn,1}}}, {POS1+2,{FF,{read,local,0}}}, - {POS1+3,{FF,{erlang,binary_to_term,1}}}, {POS1+3,{FF,{erlang,spawn,1}}}, {POS1+4,{FF,{dist,func,0}}}, {POS1+4,{FF,{erlang,spawn,1}}}, @@ -1207,6 +1206,7 @@ read_expected(Version) -> OKB1 = [{POS13+1,{FF,{erts_debug,apply,4}}}, {POS13+2,{FF,{erts_debug,apply,4}}}, {POS13+3,{FF,{erts_debug,apply,4}}}, + {POS1+3, {FF,{erlang,binary_to_term,1}}}, {POS3+1, {FF,{erlang,spawn,3}}}, {POS3+2, {FF,{erlang,spawn,3}}}, {POS3+3, {FF,{erlang,spawn_link,3}}}, diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index 2d2970de3a..54dc4ec91d 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1 +1 @@ -TOOLS_VSN = 2.6.14 +TOOLS_VSN = 2.6.15 diff --git a/lib/typer/doc/src/notes.xml b/lib/typer/doc/src/notes.xml index 53d554820d..23e22759d6 100644 --- a/lib/typer/doc/src/notes.xml +++ b/lib/typer/doc/src/notes.xml @@ -30,6 +30,21 @@ </header> <p>This document describes the changes made to TypEr.</p> +<section><title>TypEr 0.9.8</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> The name of a compiler option has been fixed in the + Makefile. </p> + <p> + Own Id: OTP-11996</p> + </item> + </list> + </section> + +</section> + <section><title>TypEr 0.9.7</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl index 572bf24ca4..cbad05081e 100644 --- a/lib/typer/src/typer.erl +++ b/lib/typer/src/typer.erl @@ -405,7 +405,7 @@ get_type({{M, F, A} = MFA, Range, Arg}, CodeServer, Records) -> case dialyzer_codeserver:lookup_mfa_contract(MFA, CodeServer) of error -> {{F, A}, {Range, Arg}}; - {ok, {_FileLine, Contract}} -> + {ok, {_FileLine, Contract, _Xtra}} -> Sig = erl_types:t_fun(Arg, Range), case dialyzer_contracts:check_contract(Contract, Sig) of ok -> {{F, A}, {contract, Contract}}; diff --git a/lib/typer/vsn.mk b/lib/typer/vsn.mk index 9cc044c621..ce658e257b 100644 --- a/lib/typer/vsn.mk +++ b/lib/typer/vsn.mk @@ -1 +1 @@ -TYPER_VSN = 0.9.7 +TYPER_VSN = 0.9.8 diff --git a/lib/wx/api_gen/wx_doxygen.conf b/lib/wx/api_gen/wx_doxygen.conf index a8516aa08e..f4d3c99ec0 100644 --- a/lib/wx/api_gen/wx_doxygen.conf +++ b/lib/wx/api_gen/wx_doxygen.conf @@ -249,6 +249,7 @@ PREDEFINED = \ wxUSE_DATAOBJ=1 \ wxUSE_SLIDER=1 \ wxUSE_CLIPBOARD=1 \ + wxUSE_POPUPWIN=1 \ wxUSE_SYSTEM_OPTIONS=1 \ wxUSE_INTL=1 \ wxABI_VERSION=20809 \ diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl index 31ed1374c2..107d064f4a 100644 --- a/lib/wx/api_gen/wx_gen_cpp.erl +++ b/lib/wx/api_gen/wx_gen_cpp.erl @@ -71,7 +71,8 @@ gen_derived_dest_2(C=#class{name=Class, options=Opts}) -> if Derived andalso (TaylorMade =:= false) -> case lists:keysearch(ifdef,1,Opts) of - {value, {ifdef, What}} -> w("#if ~p~n",[What]); + {value, {ifdef, What}} when is_list(What)-> w("#if ~s~n",[What]); + {value, {ifdef, What}} when is_atom(What) -> w("#if ~p~n",[What]); _ -> ok end, w("class E~s : public ~s {~n",[Class,Class]), @@ -190,13 +191,14 @@ gen_funcs(Defs) -> %% w(" case WXE_REMOVE_PORT:~n", []), %% w(" { destroyMemEnv(Ecmd.port); } break;~n", []), w(" case DESTROY_OBJECT: {~n"), - w(" wxObject *This = (wxObject *) getPtr(bp,memenv);~n"), - w(" if(This) {~n"), - w(" if(recurse_level > 1) {~n"), + w(" void *This = getPtr(bp,memenv);~n"), + w(" wxeRefData *refd = getRefData(This);~n"), + w(" if(This && refd) {~n"), + w(" if(recurse_level > 1 && refd->type != 4) {~n"), w(" delayed_delete->Append(Ecmd.Save());~n"), w(" } else {~n"), - w(" ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n"), - w(" delete This; }~n"), + w(" ((WxeApp *) wxTheApp)->clearPtr(This);~n"), + w(" delete_object(This, refd); }~n"), w(" } } break;~n"), w(" case WXE_REGISTER_OBJECT: {~n" " registerPid(bp, Ecmd.caller, memenv);~n" @@ -270,7 +272,8 @@ gen_class(C=#class{name=Name,methods=Ms,options=Opts}) -> false -> case lists:keysearch(ifdef,1,Opts) of {value, {ifdef, What}} -> - w("#if ~p~n",[What]), + is_atom(What) andalso w("#if ~p~n",[What]), + is_list(What) andalso w("#if ~s~n",[What]), Methods = lists:flatten(Ms), MsR = [gen_method(Name,M) || M <- lists:keysort(#method.id, Methods)], @@ -735,9 +738,13 @@ call_wx(_N,{constructor,_},#type{base={class,RClass}},Ps) -> false -> 0 end; false -> - case hd(reverse(wx_gen_erl:parents(RClass))) of - root -> Id; - _ -> 1 + case is_dc(RClass) of + true -> 4; + false -> + case hd(reverse(wx_gen_erl:parents(RClass))) of + root -> Id; + _ -> 1 + end end end, case virtual_dest(ClassDef) orelse (CType =/= 0) of @@ -899,6 +906,10 @@ is_window(Class) -> is_dialog(Class) -> lists:member("wxDialog", wx_gen_erl:parents(Class)). +is_dc(Class) -> + Parents = wx_gen_erl:parents(Class), + lists:member("wxDC", Parents) orelse lists:member("wxGraphicsContext", Parents). + build_return_vals(Type,Ps) -> HaveType = case Type of void -> 0; _ -> 1 end, NoOut = lists:sum([1 || #param{in=In} <- Ps, In =/= true]) + HaveType, @@ -1097,6 +1108,7 @@ gen_macros() -> w("#include <wx/listbook.h>~n"), w("#include <wx/treebook.h>~n"), w("#include <wx/taskbar.h>~n"), + w("#include <wx/popupwin.h>~n"), w("#include <wx/html/htmlwin.h>~n"), w("#include <wx/html/htmlcell.h>~n"), w("#include <wx/filename.h>~n"), diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index 3a1dcc7ba5..2e961cce98 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -31,7 +31,8 @@ %% wxALWAYS_NATIVE_DOUBLE_BUFFER, wxGAUGE_EMULATE_INDETERMINATE_MODE, - wxTR_DEFAULT_STYLE + wxTR_DEFAULT_STYLE, + wxSL_LABELS ]}. {gvars, @@ -877,6 +878,7 @@ {class, wxTextCtrl, wxControl, [], ['wxTextCtrl','~wxTextCtrl','AppendText','CanCopy','CanCut','CanPaste', 'CanRedo','CanUndo','Clear','Copy','Create','Cut','DiscardEdits', + 'ChangeValue', 'EmulateKeyPress','GetDefaultStyle','GetInsertionPoint','GetLastPosition', 'GetLineLength','GetLineText','GetNumberOfLines','GetRange','GetSelection', 'GetStringSelection','GetStyle','GetValue',%'HitTest', %no Mac @@ -1902,3 +1904,14 @@ 'GetSystemEncoding','GetSystemEncodingName', 'GetSystemLanguage', 'IsLoaded','IsOk']}. + +{class, wxActivateEvent, wxEvent, + [{acc, [{m_active, "GetActive()"}]}, + {event, [wxEVT_ACTIVATE, wxEVT_ACTIVATE_APP, wxEVT_HIBERNATE]}], + ['GetActive']}. + +{class, wxPopupWindow, wxWindow, [{ifdef, wxUSE_POPUPWIN}], + ['wxPopupWindow', '~wxPopupWindow', 'Create', 'Position']}. + +{class, wxPopupTransientWindow, wxPopupWindow, [{ifdef, wxUSE_POPUPWIN}], + ['wxPopupTransientWindow', '~wxPopupTransientWindow', 'Popup', 'Dismiss']}. diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h index 42925bff3a..0a3765a910 100644 --- a/lib/wx/c_src/gen/wxe_derived_dest.h +++ b/lib/wx/c_src/gen/wxe_derived_dest.h @@ -770,3 +770,19 @@ class EwxLocale : public wxLocale { EwxLocale() : wxLocale() {}; }; +#if wxUSE_POPUPWIN +class EwxPopupWindow : public wxPopupWindow { + public: ~EwxPopupWindow() {((WxeApp *)wxTheApp)->clearPtr(this);}; + EwxPopupWindow(wxWindow * parent,int flags) : wxPopupWindow(parent,flags) {}; + EwxPopupWindow() : wxPopupWindow() {}; +}; +#endif // wxUSE_POPUPWIN + +#if wxUSE_POPUPWIN +class EwxPopupTransientWindow : public wxPopupTransientWindow { + public: ~EwxPopupTransientWindow() {((WxeApp *)wxTheApp)->clearPtr(this);}; + EwxPopupTransientWindow(wxWindow * parent,int style) : wxPopupTransientWindow(parent,style) {}; + EwxPopupTransientWindow() : wxPopupTransientWindow() {}; +}; +#endif // wxUSE_POPUPWIN + diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp index 0ca059ead4..255b36c2fa 100644 --- a/lib/wx/c_src/gen/wxe_events.cpp +++ b/lib/wx/c_src/gen/wxe_events.cpp @@ -298,6 +298,9 @@ void initEventTable() {wxEVT_TASKBAR_LEFT_DCLICK, 228, "taskbar_left_dclick"}, {wxEVT_TASKBAR_RIGHT_DCLICK, 228, "taskbar_right_dclick"}, {wxEVT_INIT_DIALOG, 229, "init_dialog"}, + {wxEVT_ACTIVATE, 231, "activate"}, + {wxEVT_ACTIVATE_APP, 231, "activate_app"}, + {wxEVT_HIBERNATE, 231, "hibernate"}, {-1, 0, } }; for(int i=0; event_types[i].ev_type != -1; i++) { @@ -812,6 +815,15 @@ case 229: {// wxInitDialogEvent rt.addTupleCount(2); break; } +case 231: {// wxActivateEvent + wxActivateEvent * ev = (wxActivateEvent *) event; + evClass = (char*)"wxActivateEvent"; + rt.addAtom((char*)"wxActivate"); + rt.addAtom(Etype->eName); + rt.addBool(ev->GetActive()); + rt.addTupleCount(3); + break; +} } rt.addTupleCount(5); diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index c1e9f3829a..91ce5d810c 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -45,13 +45,14 @@ void WxeApp::wxe_dispatch(wxeCommand& Ecmd) switch (Ecmd.op) { case DESTROY_OBJECT: { - wxObject *This = (wxObject *) getPtr(bp,memenv); - if(This) { - if(recurse_level > 1) { + void *This = getPtr(bp,memenv); + wxeRefData *refd = getRefData(This); + if(This && refd) { + if(recurse_level > 1 && refd->type != 4) { delayed_delete->Append(Ecmd.Save()); } else { - ((WxeApp *) wxTheApp)->clearPtr((void *) This); - delete This; } + ((WxeApp *) wxTheApp)->clearPtr(This); + delete_object(This, refd); } } } break; case WXE_REGISTER_OBJECT: { registerPid(bp, Ecmd.caller, memenv); @@ -5843,26 +5844,26 @@ case wxMirrorDC_new: { // wxMirrorDC::wxMirrorDC wxDC *dc = (wxDC *) getPtr(bp,memenv); bp += 4; bool * mirror = (bool *) bp; bp += 4; wxMirrorDC * Result = new EwxMirrorDC(*dc,*mirror); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxMirrorDC"); break; } case wxScreenDC_new: { // wxScreenDC::wxScreenDC wxScreenDC * Result = new EwxScreenDC(); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxScreenDC"); break; } case wxPostScriptDC_new_0: { // wxPostScriptDC::wxPostScriptDC wxPostScriptDC * Result = new EwxPostScriptDC(); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxPostScriptDC"); break; } case wxPostScriptDC_new_1: { // wxPostScriptDC::wxPostScriptDC wxPrintData *printData = (wxPrintData *) getPtr(bp,memenv); bp += 4; wxPostScriptDC * Result = new EwxPostScriptDC(*printData); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxPostScriptDC"); break; } @@ -5883,7 +5884,7 @@ case wxPostScriptDC_GetResolution: { // wxPostScriptDC::GetResolution #if !wxCHECK_VERSION(2,9,0) case wxWindowDC_new_0: { // wxWindowDC::wxWindowDC wxWindowDC * Result = new EwxWindowDC(); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxWindowDC"); break; } @@ -5891,14 +5892,14 @@ case wxWindowDC_new_0: { // wxWindowDC::wxWindowDC case wxWindowDC_new_1: { // wxWindowDC::wxWindowDC wxWindow *win = (wxWindow *) getPtr(bp,memenv); bp += 4; wxWindowDC * Result = new EwxWindowDC(win); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxWindowDC"); break; } #if !wxCHECK_VERSION(2,9,0) case wxClientDC_new_0: { // wxClientDC::wxClientDC wxClientDC * Result = new EwxClientDC(); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxClientDC"); break; } @@ -5906,14 +5907,14 @@ case wxClientDC_new_0: { // wxClientDC::wxClientDC case wxClientDC_new_1: { // wxClientDC::wxClientDC wxWindow *win = (wxWindow *) getPtr(bp,memenv); bp += 4; wxClientDC * Result = new EwxClientDC(win); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxClientDC"); break; } #if !wxCHECK_VERSION(2,9,0) case wxPaintDC_new_0: { // wxPaintDC::wxPaintDC wxPaintDC * Result = new EwxPaintDC(); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxPaintDC"); break; } @@ -5921,27 +5922,27 @@ case wxPaintDC_new_0: { // wxPaintDC::wxPaintDC case wxPaintDC_new_1: { // wxPaintDC::wxPaintDC wxWindow *win = (wxWindow *) getPtr(bp,memenv); bp += 4; wxPaintDC * Result = new EwxPaintDC(win); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxPaintDC"); break; } case wxMemoryDC_new_1_0: { // wxMemoryDC::wxMemoryDC wxBitmap *bitmap = (wxBitmap *) getPtr(bp,memenv); bp += 4; wxMemoryDC * Result = new EwxMemoryDC(*bitmap); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxMemoryDC"); break; } case wxMemoryDC_new_1_1: { // wxMemoryDC::wxMemoryDC wxDC * dc = (wxDC *) getPtr(bp,memenv); bp += 4; wxMemoryDC * Result = new EwxMemoryDC(dc); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxMemoryDC"); break; } case wxMemoryDC_new_0: { // wxMemoryDC::wxMemoryDC wxMemoryDC * Result = new EwxMemoryDC(); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxMemoryDC"); break; } @@ -5961,7 +5962,7 @@ case wxMemoryDC_SelectObjectAsSource: { // wxMemoryDC::SelectObjectAsSource } case wxBufferedDC_new_0: { // wxBufferedDC::wxBufferedDC wxBufferedDC * Result = new EwxBufferedDC(); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxBufferedDC"); break; } @@ -5979,7 +5980,7 @@ buffer = (wxBitmap *) getPtr(bp,memenv); bp += 4; } break; }}; wxBufferedDC * Result = new EwxBufferedDC(dc,*buffer,style); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxBufferedDC"); break; } @@ -5996,7 +5997,7 @@ case wxBufferedDC_new_3: { // wxBufferedDC::wxBufferedDC } break; }}; wxBufferedDC * Result = new EwxBufferedDC(dc,area,style); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxBufferedDC"); break; } @@ -6043,7 +6044,7 @@ case wxBufferedPaintDC_new_3: { // wxBufferedPaintDC::wxBufferedPaintDC } break; }}; wxBufferedPaintDC * Result = new EwxBufferedPaintDC(window,*buffer,style); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxBufferedPaintDC"); break; } @@ -6057,7 +6058,7 @@ case wxBufferedPaintDC_new_2: { // wxBufferedPaintDC::wxBufferedPaintDC } break; }}; wxBufferedPaintDC * Result = new EwxBufferedPaintDC(window,style); - newPtr((void *) Result, 1, memenv); + newPtr((void *) Result, 4, memenv); rt.addRef(getRef((void *)Result,memenv), "wxBufferedPaintDC"); break; } @@ -16774,6 +16775,15 @@ case wxTextCtrl_DiscardEdits: { // wxTextCtrl::DiscardEdits This->DiscardEdits(); break; } +case wxTextCtrl_ChangeValue: { // wxTextCtrl::ChangeValue + wxTextCtrl *This = (wxTextCtrl *) getPtr(bp,memenv); bp += 4; + int * valueLen = (int *) bp; bp += 4; + wxString value = wxString(bp, wxConvUTF8); + bp += *valueLen+((8-((0+ *valueLen) & 7)) & 7); + if(!This) throw wxe_badarg(0); + This->ChangeValue(value); + break; +} case wxTextCtrl_EmulateKeyPress: { // wxTextCtrl::EmulateKeyPress wxTextCtrl *This = (wxTextCtrl *) getPtr(bp,memenv); bp += 4; wxKeyEvent *event = (wxKeyEvent *) getPtr(bp,memenv); bp += 4; @@ -31627,6 +31637,102 @@ case wxLocale_IsOk: { // wxLocale::IsOk rt.addBool(Result); break; } +case wxActivateEvent_GetActive: { // wxActivateEvent::GetActive + wxActivateEvent *This = (wxActivateEvent *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + bool Result = This->GetActive(); + rt.addBool(Result); + break; +} +#if wxUSE_POPUPWIN +case wxPopupWindow_new_2: { // wxPopupWindow::wxPopupWindow + int flags=wxBORDER_NONE; + wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4; + bp += 4; /* Align */ + while( * (int*) bp) { switch (* (int*) bp) { + case 1: {bp += 4; + flags = (int)*(int *) bp; bp += 4; + } break; + }}; + wxPopupWindow * Result = new EwxPopupWindow(parent,flags); + newPtr((void *) Result, 0, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxPopupWindow"); + break; +} +case wxPopupWindow_new_0: { // wxPopupWindow::wxPopupWindow + wxPopupWindow * Result = new EwxPopupWindow(); + newPtr((void *) Result, 0, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxPopupWindow"); + break; +} +case wxPopupWindow_Create: { // wxPopupWindow::Create + int flags=wxBORDER_NONE; + wxPopupWindow *This = (wxPopupWindow *) getPtr(bp,memenv); bp += 4; + wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4; + while( * (int*) bp) { switch (* (int*) bp) { + case 1: {bp += 4; + flags = (int)*(int *) bp; bp += 4; + } break; + }}; + if(!This) throw wxe_badarg(0); + bool Result = This->Create(parent,flags); + rt.addBool(Result); + break; +} +case wxPopupWindow_Position: { // wxPopupWindow::Position + wxPopupWindow *This = (wxPopupWindow *) getPtr(bp,memenv); bp += 4; + int * ptOriginX = (int *) bp; bp += 4; + int * ptOriginY = (int *) bp; bp += 4; + wxPoint ptOrigin = wxPoint(*ptOriginX,*ptOriginY); + int * sizeW = (int *) bp; bp += 4; + int * sizeH = (int *) bp; bp += 4; + wxSize size = wxSize(*sizeW,*sizeH); + if(!This) throw wxe_badarg(0); + This->Position(ptOrigin,size); + break; +} +#endif // wxUSE_POPUPWIN +#if wxUSE_POPUPWIN +case wxPopupTransientWindow_new_0: { // wxPopupTransientWindow::wxPopupTransientWindow + wxPopupTransientWindow * Result = new EwxPopupTransientWindow(); + newPtr((void *) Result, 0, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxPopupTransientWindow"); + break; +} +case wxPopupTransientWindow_new_2: { // wxPopupTransientWindow::wxPopupTransientWindow + int style=wxBORDER_NONE; + wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4; + bp += 4; /* Align */ + while( * (int*) bp) { switch (* (int*) bp) { + case 1: {bp += 4; + style = (int)*(int *) bp; bp += 4; + } break; + }}; + wxPopupTransientWindow * Result = new EwxPopupTransientWindow(parent,style); + newPtr((void *) Result, 0, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxPopupTransientWindow"); + break; +} +case wxPopupTransientWindow_Popup: { // wxPopupTransientWindow::Popup + wxWindow * focus=NULL; + wxPopupTransientWindow *This = (wxPopupTransientWindow *) getPtr(bp,memenv); bp += 4; + bp += 4; /* Align */ + while( * (int*) bp) { switch (* (int*) bp) { + case 1: {bp += 4; +focus = (wxWindow *) getPtr(bp,memenv); bp += 4; + } break; + }}; + if(!This) throw wxe_badarg(0); + This->Popup(focus); + break; +} +case wxPopupTransientWindow_Dismiss: { // wxPopupTransientWindow::Dismiss + wxPopupTransientWindow *This = (wxPopupTransientWindow *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->Dismiss(); + break; +} +#endif // wxUSE_POPUPWIN default: { wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false); error.addAtom("_wxe_error_"); error.addInt((int) Ecmd.op); diff --git a/lib/wx/c_src/gen/wxe_init.cpp b/lib/wx/c_src/gen/wxe_init.cpp index a75298392b..3a4bced790 100644 --- a/lib/wx/c_src/gen/wxe_init.cpp +++ b/lib/wx/c_src/gen/wxe_init.cpp @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2008-2011. All Rights Reserved. + * Copyright Ericsson AB 2008-2014. 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 @@ -36,6 +36,8 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) { rt.addTupleCount(2); rt.addAtom("wxGAUGE_EMULATE_INDETERMINATE_MODE"); rt.addInt(wxGAUGE_EMULATE_INDETERMINATE_MODE); rt.addTupleCount(2); + rt.addAtom("wxSL_LABELS"); rt.addInt(wxSL_LABELS); + rt.addTupleCount(2); rt.addAtom("wxTR_DEFAULT_STYLE"); rt.addInt(wxTR_DEFAULT_STYLE); rt.addTupleCount(2); rt.addAtom("wxBETA_NUMBER"); rt.addInt(wxBETA_NUMBER); @@ -136,7 +138,7 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) { rt.addTupleCount(2); rt.addAtom("wxWHITE_PEN"); rt.addRef(getRef((void *)wxWHITE_PEN,memenv),"wxPen"); rt.addTupleCount(2); - rt.endList(56); + rt.endList(57); rt.addTupleCount(2); rt.send(); } diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h index 2da24f5d5e..c8ca9bfe5b 100644 --- a/lib/wx/c_src/gen/wxe_macros.h +++ b/lib/wx/c_src/gen/wxe_macros.h @@ -58,6 +58,7 @@ #include <wx/listbook.h> #include <wx/treebook.h> #include <wx/taskbar.h> +#include <wx/popupwin.h> #include <wx/html/htmlwin.h> #include <wx/html/htmlcell.h> #include <wx/filename.h> @@ -1716,1664 +1717,1676 @@ #define wxTextCtrl_Create 1824 #define wxTextCtrl_Cut 1825 #define wxTextCtrl_DiscardEdits 1826 -#define wxTextCtrl_EmulateKeyPress 1827 -#define wxTextCtrl_GetDefaultStyle 1828 -#define wxTextCtrl_GetInsertionPoint 1829 -#define wxTextCtrl_GetLastPosition 1830 -#define wxTextCtrl_GetLineLength 1831 -#define wxTextCtrl_GetLineText 1832 -#define wxTextCtrl_GetNumberOfLines 1833 -#define wxTextCtrl_GetRange 1834 -#define wxTextCtrl_GetSelection 1835 -#define wxTextCtrl_GetStringSelection 1836 -#define wxTextCtrl_GetStyle 1837 -#define wxTextCtrl_GetValue 1838 -#define wxTextCtrl_IsEditable 1839 -#define wxTextCtrl_IsModified 1840 -#define wxTextCtrl_IsMultiLine 1841 -#define wxTextCtrl_IsSingleLine 1842 -#define wxTextCtrl_LoadFile 1843 -#define wxTextCtrl_MarkDirty 1844 -#define wxTextCtrl_Paste 1845 -#define wxTextCtrl_PositionToXY 1846 -#define wxTextCtrl_Redo 1847 -#define wxTextCtrl_Remove 1848 -#define wxTextCtrl_Replace 1849 -#define wxTextCtrl_SaveFile 1850 -#define wxTextCtrl_SetDefaultStyle 1851 -#define wxTextCtrl_SetEditable 1852 -#define wxTextCtrl_SetInsertionPoint 1853 -#define wxTextCtrl_SetInsertionPointEnd 1854 -#define wxTextCtrl_SetMaxLength 1856 -#define wxTextCtrl_SetSelection 1857 -#define wxTextCtrl_SetStyle 1858 -#define wxTextCtrl_SetValue 1859 -#define wxTextCtrl_ShowPosition 1860 -#define wxTextCtrl_Undo 1861 -#define wxTextCtrl_WriteText 1862 -#define wxTextCtrl_XYToPosition 1863 -#define wxNotebook_new_0 1866 -#define wxNotebook_new_3 1867 -#define wxNotebook_destruct 1868 -#define wxNotebook_AddPage 1869 -#define wxNotebook_AdvanceSelection 1870 -#define wxNotebook_AssignImageList 1871 -#define wxNotebook_Create 1872 -#define wxNotebook_DeleteAllPages 1873 -#define wxNotebook_DeletePage 1874 -#define wxNotebook_RemovePage 1875 -#define wxNotebook_GetCurrentPage 1876 -#define wxNotebook_GetImageList 1877 -#define wxNotebook_GetPage 1879 -#define wxNotebook_GetPageCount 1880 -#define wxNotebook_GetPageImage 1881 -#define wxNotebook_GetPageText 1882 -#define wxNotebook_GetRowCount 1883 -#define wxNotebook_GetSelection 1884 -#define wxNotebook_GetThemeBackgroundColour 1885 -#define wxNotebook_HitTest 1887 -#define wxNotebook_InsertPage 1889 -#define wxNotebook_SetImageList 1890 -#define wxNotebook_SetPadding 1891 -#define wxNotebook_SetPageSize 1892 -#define wxNotebook_SetPageImage 1893 -#define wxNotebook_SetPageText 1894 -#define wxNotebook_SetSelection 1895 -#define wxNotebook_ChangeSelection 1896 -#define wxChoicebook_new_0 1897 -#define wxChoicebook_new_3 1898 -#define wxChoicebook_AddPage 1899 -#define wxChoicebook_AdvanceSelection 1900 -#define wxChoicebook_AssignImageList 1901 -#define wxChoicebook_Create 1902 -#define wxChoicebook_DeleteAllPages 1903 -#define wxChoicebook_DeletePage 1904 -#define wxChoicebook_RemovePage 1905 -#define wxChoicebook_GetCurrentPage 1906 -#define wxChoicebook_GetImageList 1907 -#define wxChoicebook_GetPage 1909 -#define wxChoicebook_GetPageCount 1910 -#define wxChoicebook_GetPageImage 1911 -#define wxChoicebook_GetPageText 1912 -#define wxChoicebook_GetSelection 1913 -#define wxChoicebook_HitTest 1914 -#define wxChoicebook_InsertPage 1915 -#define wxChoicebook_SetImageList 1916 -#define wxChoicebook_SetPageSize 1917 -#define wxChoicebook_SetPageImage 1918 -#define wxChoicebook_SetPageText 1919 -#define wxChoicebook_SetSelection 1920 -#define wxChoicebook_ChangeSelection 1921 -#define wxChoicebook_destroy 1922 -#define wxToolbook_new_0 1923 -#define wxToolbook_new_3 1924 -#define wxToolbook_AddPage 1925 -#define wxToolbook_AdvanceSelection 1926 -#define wxToolbook_AssignImageList 1927 -#define wxToolbook_Create 1928 -#define wxToolbook_DeleteAllPages 1929 -#define wxToolbook_DeletePage 1930 -#define wxToolbook_RemovePage 1931 -#define wxToolbook_GetCurrentPage 1932 -#define wxToolbook_GetImageList 1933 -#define wxToolbook_GetPage 1935 -#define wxToolbook_GetPageCount 1936 -#define wxToolbook_GetPageImage 1937 -#define wxToolbook_GetPageText 1938 -#define wxToolbook_GetSelection 1939 -#define wxToolbook_HitTest 1941 -#define wxToolbook_InsertPage 1942 -#define wxToolbook_SetImageList 1943 -#define wxToolbook_SetPageSize 1944 -#define wxToolbook_SetPageImage 1945 -#define wxToolbook_SetPageText 1946 -#define wxToolbook_SetSelection 1947 -#define wxToolbook_ChangeSelection 1948 -#define wxToolbook_destroy 1949 -#define wxListbook_new_0 1950 -#define wxListbook_new_3 1951 -#define wxListbook_AddPage 1952 -#define wxListbook_AdvanceSelection 1953 -#define wxListbook_AssignImageList 1954 -#define wxListbook_Create 1955 -#define wxListbook_DeleteAllPages 1956 -#define wxListbook_DeletePage 1957 -#define wxListbook_RemovePage 1958 -#define wxListbook_GetCurrentPage 1959 -#define wxListbook_GetImageList 1960 -#define wxListbook_GetPage 1962 -#define wxListbook_GetPageCount 1963 -#define wxListbook_GetPageImage 1964 -#define wxListbook_GetPageText 1965 -#define wxListbook_GetSelection 1966 -#define wxListbook_HitTest 1968 -#define wxListbook_InsertPage 1969 -#define wxListbook_SetImageList 1970 -#define wxListbook_SetPageSize 1971 -#define wxListbook_SetPageImage 1972 -#define wxListbook_SetPageText 1973 -#define wxListbook_SetSelection 1974 -#define wxListbook_ChangeSelection 1975 -#define wxListbook_destroy 1976 -#define wxTreebook_new_0 1977 -#define wxTreebook_new_3 1978 -#define wxTreebook_AddPage 1979 -#define wxTreebook_AdvanceSelection 1980 -#define wxTreebook_AssignImageList 1981 -#define wxTreebook_Create 1982 -#define wxTreebook_DeleteAllPages 1983 -#define wxTreebook_DeletePage 1984 -#define wxTreebook_RemovePage 1985 -#define wxTreebook_GetCurrentPage 1986 -#define wxTreebook_GetImageList 1987 -#define wxTreebook_GetPage 1989 -#define wxTreebook_GetPageCount 1990 -#define wxTreebook_GetPageImage 1991 -#define wxTreebook_GetPageText 1992 -#define wxTreebook_GetSelection 1993 -#define wxTreebook_ExpandNode 1994 -#define wxTreebook_IsNodeExpanded 1995 -#define wxTreebook_HitTest 1997 -#define wxTreebook_InsertPage 1998 -#define wxTreebook_InsertSubPage 1999 -#define wxTreebook_SetImageList 2000 -#define wxTreebook_SetPageSize 2001 -#define wxTreebook_SetPageImage 2002 -#define wxTreebook_SetPageText 2003 -#define wxTreebook_SetSelection 2004 -#define wxTreebook_ChangeSelection 2005 -#define wxTreebook_destroy 2006 -#define wxTreeCtrl_new_2 2009 -#define wxTreeCtrl_new_0 2010 -#define wxTreeCtrl_destruct 2012 -#define wxTreeCtrl_AddRoot 2013 -#define wxTreeCtrl_AppendItem 2014 -#define wxTreeCtrl_AssignImageList 2015 -#define wxTreeCtrl_AssignStateImageList 2016 -#define wxTreeCtrl_Collapse 2017 -#define wxTreeCtrl_CollapseAndReset 2018 -#define wxTreeCtrl_Create 2019 -#define wxTreeCtrl_Delete 2020 -#define wxTreeCtrl_DeleteAllItems 2021 -#define wxTreeCtrl_DeleteChildren 2022 -#define wxTreeCtrl_EditLabel 2023 -#define wxTreeCtrl_EnsureVisible 2024 -#define wxTreeCtrl_Expand 2025 -#define wxTreeCtrl_GetBoundingRect 2026 -#define wxTreeCtrl_GetChildrenCount 2028 -#define wxTreeCtrl_GetCount 2029 -#define wxTreeCtrl_GetEditControl 2030 -#define wxTreeCtrl_GetFirstChild 2031 -#define wxTreeCtrl_GetNextChild 2032 -#define wxTreeCtrl_GetFirstVisibleItem 2033 -#define wxTreeCtrl_GetImageList 2034 -#define wxTreeCtrl_GetIndent 2035 -#define wxTreeCtrl_GetItemBackgroundColour 2036 -#define wxTreeCtrl_GetItemData 2037 -#define wxTreeCtrl_GetItemFont 2038 -#define wxTreeCtrl_GetItemImage_1 2039 -#define wxTreeCtrl_GetItemImage_2 2040 -#define wxTreeCtrl_GetItemText 2041 -#define wxTreeCtrl_GetItemTextColour 2042 -#define wxTreeCtrl_GetLastChild 2043 -#define wxTreeCtrl_GetNextSibling 2044 -#define wxTreeCtrl_GetNextVisible 2045 -#define wxTreeCtrl_GetItemParent 2046 -#define wxTreeCtrl_GetPrevSibling 2047 -#define wxTreeCtrl_GetPrevVisible 2048 -#define wxTreeCtrl_GetRootItem 2049 -#define wxTreeCtrl_GetSelection 2050 -#define wxTreeCtrl_GetSelections 2051 -#define wxTreeCtrl_GetStateImageList 2052 -#define wxTreeCtrl_HitTest 2053 -#define wxTreeCtrl_InsertItem 2055 -#define wxTreeCtrl_IsBold 2056 -#define wxTreeCtrl_IsExpanded 2057 -#define wxTreeCtrl_IsSelected 2058 -#define wxTreeCtrl_IsVisible 2059 -#define wxTreeCtrl_ItemHasChildren 2060 -#define wxTreeCtrl_IsTreeItemIdOk 2061 -#define wxTreeCtrl_PrependItem 2062 -#define wxTreeCtrl_ScrollTo 2063 -#define wxTreeCtrl_SelectItem_1 2064 -#define wxTreeCtrl_SelectItem_2 2065 -#define wxTreeCtrl_SetIndent 2066 -#define wxTreeCtrl_SetImageList 2067 -#define wxTreeCtrl_SetItemBackgroundColour 2068 -#define wxTreeCtrl_SetItemBold 2069 -#define wxTreeCtrl_SetItemData 2070 -#define wxTreeCtrl_SetItemDropHighlight 2071 -#define wxTreeCtrl_SetItemFont 2072 -#define wxTreeCtrl_SetItemHasChildren 2073 -#define wxTreeCtrl_SetItemImage_2 2074 -#define wxTreeCtrl_SetItemImage_3 2075 -#define wxTreeCtrl_SetItemText 2076 -#define wxTreeCtrl_SetItemTextColour 2077 -#define wxTreeCtrl_SetStateImageList 2078 -#define wxTreeCtrl_SetWindowStyle 2079 -#define wxTreeCtrl_SortChildren 2080 -#define wxTreeCtrl_Toggle 2081 -#define wxTreeCtrl_ToggleItemSelection 2082 -#define wxTreeCtrl_Unselect 2083 -#define wxTreeCtrl_UnselectAll 2084 -#define wxTreeCtrl_UnselectItem 2085 -#define wxScrollBar_new_0 2086 -#define wxScrollBar_new_3 2087 -#define wxScrollBar_destruct 2088 -#define wxScrollBar_Create 2089 -#define wxScrollBar_GetRange 2090 -#define wxScrollBar_GetPageSize 2091 -#define wxScrollBar_GetThumbPosition 2092 -#define wxScrollBar_GetThumbSize 2093 -#define wxScrollBar_SetThumbPosition 2094 -#define wxScrollBar_SetScrollbar 2095 -#define wxSpinButton_new_2 2097 -#define wxSpinButton_new_0 2098 -#define wxSpinButton_Create 2099 -#define wxSpinButton_GetMax 2100 -#define wxSpinButton_GetMin 2101 -#define wxSpinButton_GetValue 2102 -#define wxSpinButton_SetRange 2103 -#define wxSpinButton_SetValue 2104 -#define wxSpinButton_destroy 2105 -#define wxSpinCtrl_new_0 2106 -#define wxSpinCtrl_new_2 2107 -#define wxSpinCtrl_Create 2109 -#define wxSpinCtrl_SetValue_1_1 2112 -#define wxSpinCtrl_SetValue_1_0 2113 -#define wxSpinCtrl_GetValue 2115 -#define wxSpinCtrl_SetRange 2117 -#define wxSpinCtrl_SetSelection 2118 -#define wxSpinCtrl_GetMin 2120 -#define wxSpinCtrl_GetMax 2122 -#define wxSpinCtrl_destroy 2123 -#define wxStaticText_new_0 2124 -#define wxStaticText_new_4 2125 -#define wxStaticText_Create 2126 -#define wxStaticText_GetLabel 2127 -#define wxStaticText_SetLabel 2128 -#define wxStaticText_Wrap 2129 -#define wxStaticText_destroy 2130 -#define wxStaticBitmap_new_0 2131 -#define wxStaticBitmap_new_4 2132 -#define wxStaticBitmap_Create 2133 -#define wxStaticBitmap_GetBitmap 2134 -#define wxStaticBitmap_SetBitmap 2135 -#define wxStaticBitmap_destroy 2136 -#define wxRadioBox_new 2137 -#define wxRadioBox_destruct 2139 -#define wxRadioBox_Create 2140 -#define wxRadioBox_Enable_2 2141 -#define wxRadioBox_Enable_1 2142 -#define wxRadioBox_GetSelection 2143 -#define wxRadioBox_GetString 2144 -#define wxRadioBox_SetSelection 2145 -#define wxRadioBox_Show_2 2146 -#define wxRadioBox_Show_1 2147 -#define wxRadioBox_GetColumnCount 2148 -#define wxRadioBox_GetItemHelpText 2149 -#define wxRadioBox_GetItemToolTip 2150 -#define wxRadioBox_GetItemFromPoint 2152 -#define wxRadioBox_GetRowCount 2153 -#define wxRadioBox_IsItemEnabled 2154 -#define wxRadioBox_IsItemShown 2155 -#define wxRadioBox_SetItemHelpText 2156 -#define wxRadioBox_SetItemToolTip 2157 -#define wxRadioButton_new_0 2158 -#define wxRadioButton_new_4 2159 -#define wxRadioButton_Create 2160 -#define wxRadioButton_GetValue 2161 -#define wxRadioButton_SetValue 2162 -#define wxRadioButton_destroy 2163 -#define wxSlider_new_6 2165 -#define wxSlider_new_0 2166 -#define wxSlider_Create 2167 -#define wxSlider_GetLineSize 2168 -#define wxSlider_GetMax 2169 -#define wxSlider_GetMin 2170 -#define wxSlider_GetPageSize 2171 -#define wxSlider_GetThumbLength 2172 -#define wxSlider_GetValue 2173 -#define wxSlider_SetLineSize 2174 -#define wxSlider_SetPageSize 2175 -#define wxSlider_SetRange 2176 -#define wxSlider_SetThumbLength 2177 -#define wxSlider_SetValue 2178 -#define wxSlider_destroy 2179 -#define wxDialog_new_4 2181 -#define wxDialog_new_0 2182 -#define wxDialog_destruct 2184 -#define wxDialog_Create 2185 -#define wxDialog_CreateButtonSizer 2186 -#define wxDialog_CreateStdDialogButtonSizer 2187 -#define wxDialog_EndModal 2188 -#define wxDialog_GetAffirmativeId 2189 -#define wxDialog_GetReturnCode 2190 -#define wxDialog_IsModal 2191 -#define wxDialog_SetAffirmativeId 2192 -#define wxDialog_SetReturnCode 2193 -#define wxDialog_Show 2194 -#define wxDialog_ShowModal 2195 -#define wxColourDialog_new_0 2196 -#define wxColourDialog_new_2 2197 -#define wxColourDialog_destruct 2198 -#define wxColourDialog_Create 2199 -#define wxColourDialog_GetColourData 2200 -#define wxColourData_new_0 2201 -#define wxColourData_new_1 2202 -#define wxColourData_destruct 2203 -#define wxColourData_GetChooseFull 2204 -#define wxColourData_GetColour 2205 -#define wxColourData_GetCustomColour 2207 -#define wxColourData_SetChooseFull 2208 -#define wxColourData_SetColour 2209 -#define wxColourData_SetCustomColour 2210 -#define wxPalette_new_0 2211 -#define wxPalette_new_4 2212 -#define wxPalette_destruct 2214 -#define wxPalette_Create 2215 -#define wxPalette_GetColoursCount 2216 -#define wxPalette_GetPixel 2217 -#define wxPalette_GetRGB 2218 -#define wxPalette_IsOk 2219 -#define wxDirDialog_new 2223 -#define wxDirDialog_destruct 2224 -#define wxDirDialog_GetPath 2225 -#define wxDirDialog_GetMessage 2226 -#define wxDirDialog_SetMessage 2227 -#define wxDirDialog_SetPath 2228 -#define wxFileDialog_new 2232 -#define wxFileDialog_destruct 2233 -#define wxFileDialog_GetDirectory 2234 -#define wxFileDialog_GetFilename 2235 -#define wxFileDialog_GetFilenames 2236 -#define wxFileDialog_GetFilterIndex 2237 -#define wxFileDialog_GetMessage 2238 -#define wxFileDialog_GetPath 2239 -#define wxFileDialog_GetPaths 2240 -#define wxFileDialog_GetWildcard 2241 -#define wxFileDialog_SetDirectory 2242 -#define wxFileDialog_SetFilename 2243 -#define wxFileDialog_SetFilterIndex 2244 -#define wxFileDialog_SetMessage 2245 -#define wxFileDialog_SetPath 2246 -#define wxFileDialog_SetWildcard 2247 -#define wxPickerBase_SetInternalMargin 2248 -#define wxPickerBase_GetInternalMargin 2249 -#define wxPickerBase_SetTextCtrlProportion 2250 -#define wxPickerBase_SetPickerCtrlProportion 2251 -#define wxPickerBase_GetTextCtrlProportion 2252 -#define wxPickerBase_GetPickerCtrlProportion 2253 -#define wxPickerBase_HasTextCtrl 2254 -#define wxPickerBase_GetTextCtrl 2255 -#define wxPickerBase_IsTextCtrlGrowable 2256 -#define wxPickerBase_SetPickerCtrlGrowable 2257 -#define wxPickerBase_SetTextCtrlGrowable 2258 -#define wxPickerBase_IsPickerCtrlGrowable 2259 -#define wxFilePickerCtrl_new_0 2260 -#define wxFilePickerCtrl_new_3 2261 -#define wxFilePickerCtrl_Create 2262 -#define wxFilePickerCtrl_GetPath 2263 -#define wxFilePickerCtrl_SetPath 2264 -#define wxFilePickerCtrl_destroy 2265 -#define wxDirPickerCtrl_new_0 2266 -#define wxDirPickerCtrl_new_3 2267 -#define wxDirPickerCtrl_Create 2268 -#define wxDirPickerCtrl_GetPath 2269 -#define wxDirPickerCtrl_SetPath 2270 -#define wxDirPickerCtrl_destroy 2271 -#define wxColourPickerCtrl_new_0 2272 -#define wxColourPickerCtrl_new_3 2273 -#define wxColourPickerCtrl_Create 2274 -#define wxColourPickerCtrl_GetColour 2275 -#define wxColourPickerCtrl_SetColour_1_1 2276 -#define wxColourPickerCtrl_SetColour_1_0 2277 -#define wxColourPickerCtrl_destroy 2278 -#define wxDatePickerCtrl_new_0 2279 -#define wxDatePickerCtrl_new_3 2280 -#define wxDatePickerCtrl_GetRange 2281 -#define wxDatePickerCtrl_GetValue 2282 -#define wxDatePickerCtrl_SetRange 2283 -#define wxDatePickerCtrl_SetValue 2284 -#define wxDatePickerCtrl_destroy 2285 -#define wxFontPickerCtrl_new_0 2286 -#define wxFontPickerCtrl_new_3 2287 -#define wxFontPickerCtrl_Create 2288 -#define wxFontPickerCtrl_GetSelectedFont 2289 -#define wxFontPickerCtrl_SetSelectedFont 2290 -#define wxFontPickerCtrl_GetMaxPointSize 2291 -#define wxFontPickerCtrl_SetMaxPointSize 2292 -#define wxFontPickerCtrl_destroy 2293 -#define wxFindReplaceDialog_new_0 2296 -#define wxFindReplaceDialog_new_4 2297 -#define wxFindReplaceDialog_destruct 2298 -#define wxFindReplaceDialog_Create 2299 -#define wxFindReplaceDialog_GetData 2300 -#define wxFindReplaceData_new_0 2301 -#define wxFindReplaceData_new_1 2302 -#define wxFindReplaceData_GetFindString 2303 -#define wxFindReplaceData_GetReplaceString 2304 -#define wxFindReplaceData_GetFlags 2305 -#define wxFindReplaceData_SetFlags 2306 -#define wxFindReplaceData_SetFindString 2307 -#define wxFindReplaceData_SetReplaceString 2308 -#define wxFindReplaceData_destroy 2309 -#define wxMultiChoiceDialog_new_0 2310 -#define wxMultiChoiceDialog_new_5 2312 -#define wxMultiChoiceDialog_GetSelections 2313 -#define wxMultiChoiceDialog_SetSelections 2314 -#define wxMultiChoiceDialog_destroy 2315 -#define wxSingleChoiceDialog_new_0 2316 -#define wxSingleChoiceDialog_new_5 2318 -#define wxSingleChoiceDialog_GetSelection 2319 -#define wxSingleChoiceDialog_GetStringSelection 2320 -#define wxSingleChoiceDialog_SetSelection 2321 -#define wxSingleChoiceDialog_destroy 2322 -#define wxTextEntryDialog_new 2323 -#define wxTextEntryDialog_GetValue 2324 -#define wxTextEntryDialog_SetValue 2325 -#define wxTextEntryDialog_destroy 2326 -#define wxPasswordEntryDialog_new 2327 -#define wxPasswordEntryDialog_destroy 2328 -#define wxFontData_new_0 2329 -#define wxFontData_new_1 2330 -#define wxFontData_destruct 2331 -#define wxFontData_EnableEffects 2332 -#define wxFontData_GetAllowSymbols 2333 -#define wxFontData_GetColour 2334 -#define wxFontData_GetChosenFont 2335 -#define wxFontData_GetEnableEffects 2336 -#define wxFontData_GetInitialFont 2337 -#define wxFontData_GetShowHelp 2338 -#define wxFontData_SetAllowSymbols 2339 -#define wxFontData_SetChosenFont 2340 -#define wxFontData_SetColour 2341 -#define wxFontData_SetInitialFont 2342 -#define wxFontData_SetRange 2343 -#define wxFontData_SetShowHelp 2344 -#define wxFontDialog_new_0 2348 -#define wxFontDialog_new_2 2350 -#define wxFontDialog_Create 2352 -#define wxFontDialog_GetFontData 2353 -#define wxFontDialog_destroy 2355 -#define wxProgressDialog_new 2356 -#define wxProgressDialog_destruct 2357 -#define wxProgressDialog_Resume 2358 -#define wxProgressDialog_Update_2 2359 -#define wxProgressDialog_Update_0 2360 -#define wxMessageDialog_new 2361 -#define wxMessageDialog_destruct 2362 -#define wxPageSetupDialog_new 2363 -#define wxPageSetupDialog_destruct 2364 -#define wxPageSetupDialog_GetPageSetupData 2365 -#define wxPageSetupDialog_ShowModal 2366 -#define wxPageSetupDialogData_new_0 2367 -#define wxPageSetupDialogData_new_1_0 2368 -#define wxPageSetupDialogData_new_1_1 2369 -#define wxPageSetupDialogData_destruct 2370 -#define wxPageSetupDialogData_EnableHelp 2371 -#define wxPageSetupDialogData_EnableMargins 2372 -#define wxPageSetupDialogData_EnableOrientation 2373 -#define wxPageSetupDialogData_EnablePaper 2374 -#define wxPageSetupDialogData_EnablePrinter 2375 -#define wxPageSetupDialogData_GetDefaultMinMargins 2376 -#define wxPageSetupDialogData_GetEnableMargins 2377 -#define wxPageSetupDialogData_GetEnableOrientation 2378 -#define wxPageSetupDialogData_GetEnablePaper 2379 -#define wxPageSetupDialogData_GetEnablePrinter 2380 -#define wxPageSetupDialogData_GetEnableHelp 2381 -#define wxPageSetupDialogData_GetDefaultInfo 2382 -#define wxPageSetupDialogData_GetMarginTopLeft 2383 -#define wxPageSetupDialogData_GetMarginBottomRight 2384 -#define wxPageSetupDialogData_GetMinMarginTopLeft 2385 -#define wxPageSetupDialogData_GetMinMarginBottomRight 2386 -#define wxPageSetupDialogData_GetPaperId 2387 -#define wxPageSetupDialogData_GetPaperSize 2388 -#define wxPageSetupDialogData_GetPrintData 2390 -#define wxPageSetupDialogData_IsOk 2391 -#define wxPageSetupDialogData_SetDefaultInfo 2392 -#define wxPageSetupDialogData_SetDefaultMinMargins 2393 -#define wxPageSetupDialogData_SetMarginTopLeft 2394 -#define wxPageSetupDialogData_SetMarginBottomRight 2395 -#define wxPageSetupDialogData_SetMinMarginTopLeft 2396 -#define wxPageSetupDialogData_SetMinMarginBottomRight 2397 -#define wxPageSetupDialogData_SetPaperId 2398 -#define wxPageSetupDialogData_SetPaperSize_1_1 2399 -#define wxPageSetupDialogData_SetPaperSize_1_0 2400 -#define wxPageSetupDialogData_SetPrintData 2401 -#define wxPrintDialog_new_2_0 2402 -#define wxPrintDialog_new_2_1 2403 -#define wxPrintDialog_destruct 2404 -#define wxPrintDialog_GetPrintDialogData 2405 -#define wxPrintDialog_GetPrintDC 2406 -#define wxPrintDialogData_new_0 2407 -#define wxPrintDialogData_new_1_1 2408 -#define wxPrintDialogData_new_1_0 2409 -#define wxPrintDialogData_destruct 2410 -#define wxPrintDialogData_EnableHelp 2411 -#define wxPrintDialogData_EnablePageNumbers 2412 -#define wxPrintDialogData_EnablePrintToFile 2413 -#define wxPrintDialogData_EnableSelection 2414 -#define wxPrintDialogData_GetAllPages 2415 -#define wxPrintDialogData_GetCollate 2416 -#define wxPrintDialogData_GetFromPage 2417 -#define wxPrintDialogData_GetMaxPage 2418 -#define wxPrintDialogData_GetMinPage 2419 -#define wxPrintDialogData_GetNoCopies 2420 -#define wxPrintDialogData_GetPrintData 2421 -#define wxPrintDialogData_GetPrintToFile 2422 -#define wxPrintDialogData_GetSelection 2423 -#define wxPrintDialogData_GetToPage 2424 -#define wxPrintDialogData_IsOk 2425 -#define wxPrintDialogData_SetCollate 2426 -#define wxPrintDialogData_SetFromPage 2427 -#define wxPrintDialogData_SetMaxPage 2428 -#define wxPrintDialogData_SetMinPage 2429 -#define wxPrintDialogData_SetNoCopies 2430 -#define wxPrintDialogData_SetPrintData 2431 -#define wxPrintDialogData_SetPrintToFile 2432 -#define wxPrintDialogData_SetSelection 2433 -#define wxPrintDialogData_SetToPage 2434 -#define wxPrintData_new_0 2435 -#define wxPrintData_new_1 2436 -#define wxPrintData_destruct 2437 -#define wxPrintData_GetCollate 2438 -#define wxPrintData_GetBin 2439 -#define wxPrintData_GetColour 2440 -#define wxPrintData_GetDuplex 2441 -#define wxPrintData_GetNoCopies 2442 -#define wxPrintData_GetOrientation 2443 -#define wxPrintData_GetPaperId 2444 -#define wxPrintData_GetPrinterName 2445 -#define wxPrintData_GetQuality 2446 -#define wxPrintData_IsOk 2447 -#define wxPrintData_SetBin 2448 -#define wxPrintData_SetCollate 2449 -#define wxPrintData_SetColour 2450 -#define wxPrintData_SetDuplex 2451 -#define wxPrintData_SetNoCopies 2452 -#define wxPrintData_SetOrientation 2453 -#define wxPrintData_SetPaperId 2454 -#define wxPrintData_SetPrinterName 2455 -#define wxPrintData_SetQuality 2456 -#define wxPrintPreview_new_2 2459 -#define wxPrintPreview_new_3 2460 -#define wxPrintPreview_destruct 2462 -#define wxPrintPreview_GetCanvas 2463 -#define wxPrintPreview_GetCurrentPage 2464 -#define wxPrintPreview_GetFrame 2465 -#define wxPrintPreview_GetMaxPage 2466 -#define wxPrintPreview_GetMinPage 2467 -#define wxPrintPreview_GetPrintout 2468 -#define wxPrintPreview_GetPrintoutForPrinting 2469 -#define wxPrintPreview_IsOk 2470 -#define wxPrintPreview_PaintPage 2471 -#define wxPrintPreview_Print 2472 -#define wxPrintPreview_RenderPage 2473 -#define wxPrintPreview_SetCanvas 2474 -#define wxPrintPreview_SetCurrentPage 2475 -#define wxPrintPreview_SetFrame 2476 -#define wxPrintPreview_SetPrintout 2477 -#define wxPrintPreview_SetZoom 2478 -#define wxPreviewFrame_new 2479 -#define wxPreviewFrame_destruct 2480 -#define wxPreviewFrame_CreateControlBar 2481 -#define wxPreviewFrame_CreateCanvas 2482 -#define wxPreviewFrame_Initialize 2483 -#define wxPreviewFrame_OnCloseWindow 2484 -#define wxPreviewControlBar_new 2485 -#define wxPreviewControlBar_destruct 2486 -#define wxPreviewControlBar_CreateButtons 2487 -#define wxPreviewControlBar_GetPrintPreview 2488 -#define wxPreviewControlBar_GetZoomControl 2489 -#define wxPreviewControlBar_SetZoomControl 2490 -#define wxPrinter_new 2492 -#define wxPrinter_CreateAbortWindow 2493 -#define wxPrinter_GetAbort 2494 -#define wxPrinter_GetLastError 2495 -#define wxPrinter_GetPrintDialogData 2496 -#define wxPrinter_Print 2497 -#define wxPrinter_PrintDialog 2498 -#define wxPrinter_ReportError 2499 -#define wxPrinter_Setup 2500 -#define wxPrinter_destroy 2501 -#define wxXmlResource_new_1 2502 -#define wxXmlResource_new_2 2503 -#define wxXmlResource_destruct 2504 -#define wxXmlResource_AttachUnknownControl 2505 -#define wxXmlResource_ClearHandlers 2506 -#define wxXmlResource_CompareVersion 2507 -#define wxXmlResource_Get 2508 -#define wxXmlResource_GetFlags 2509 -#define wxXmlResource_GetVersion 2510 -#define wxXmlResource_GetXRCID 2511 -#define wxXmlResource_InitAllHandlers 2512 -#define wxXmlResource_Load 2513 -#define wxXmlResource_LoadBitmap 2514 -#define wxXmlResource_LoadDialog_2 2515 -#define wxXmlResource_LoadDialog_3 2516 -#define wxXmlResource_LoadFrame_2 2517 -#define wxXmlResource_LoadFrame_3 2518 -#define wxXmlResource_LoadIcon 2519 -#define wxXmlResource_LoadMenu 2520 -#define wxXmlResource_LoadMenuBar_2 2521 -#define wxXmlResource_LoadMenuBar_1 2522 -#define wxXmlResource_LoadPanel_2 2523 -#define wxXmlResource_LoadPanel_3 2524 -#define wxXmlResource_LoadToolBar 2525 -#define wxXmlResource_Set 2526 -#define wxXmlResource_SetFlags 2527 -#define wxXmlResource_Unload 2528 -#define wxXmlResource_xrcctrl 2529 -#define wxHtmlEasyPrinting_new 2530 -#define wxHtmlEasyPrinting_destruct 2531 -#define wxHtmlEasyPrinting_GetPrintData 2532 -#define wxHtmlEasyPrinting_GetPageSetupData 2533 -#define wxHtmlEasyPrinting_PreviewFile 2534 -#define wxHtmlEasyPrinting_PreviewText 2535 -#define wxHtmlEasyPrinting_PrintFile 2536 -#define wxHtmlEasyPrinting_PrintText 2537 -#define wxHtmlEasyPrinting_PageSetup 2538 -#define wxHtmlEasyPrinting_SetFonts 2539 -#define wxHtmlEasyPrinting_SetHeader 2540 -#define wxHtmlEasyPrinting_SetFooter 2541 -#define wxGLCanvas_new_2 2543 -#define wxGLCanvas_new_3_1 2544 -#define wxGLCanvas_new_3_0 2545 -#define wxGLCanvas_GetContext 2546 -#define wxGLCanvas_SetCurrent 2548 -#define wxGLCanvas_SwapBuffers 2549 -#define wxGLCanvas_destroy 2550 -#define wxAuiManager_new 2551 -#define wxAuiManager_destruct 2552 -#define wxAuiManager_AddPane_2_1 2553 -#define wxAuiManager_AddPane_3 2554 -#define wxAuiManager_AddPane_2_0 2555 -#define wxAuiManager_DetachPane 2556 -#define wxAuiManager_GetAllPanes 2557 -#define wxAuiManager_GetArtProvider 2558 -#define wxAuiManager_GetDockSizeConstraint 2559 -#define wxAuiManager_GetFlags 2560 -#define wxAuiManager_GetManagedWindow 2561 -#define wxAuiManager_GetManager 2562 -#define wxAuiManager_GetPane_1_1 2563 -#define wxAuiManager_GetPane_1_0 2564 -#define wxAuiManager_HideHint 2565 -#define wxAuiManager_InsertPane 2566 -#define wxAuiManager_LoadPaneInfo 2567 -#define wxAuiManager_LoadPerspective 2568 -#define wxAuiManager_SavePaneInfo 2569 -#define wxAuiManager_SavePerspective 2570 -#define wxAuiManager_SetArtProvider 2571 -#define wxAuiManager_SetDockSizeConstraint 2572 -#define wxAuiManager_SetFlags 2573 -#define wxAuiManager_SetManagedWindow 2574 -#define wxAuiManager_ShowHint 2575 -#define wxAuiManager_UnInit 2576 -#define wxAuiManager_Update 2577 -#define wxAuiPaneInfo_new_0 2578 -#define wxAuiPaneInfo_new_1 2579 -#define wxAuiPaneInfo_destruct 2580 -#define wxAuiPaneInfo_BestSize_1 2581 -#define wxAuiPaneInfo_BestSize_2 2582 -#define wxAuiPaneInfo_Bottom 2583 -#define wxAuiPaneInfo_BottomDockable 2584 -#define wxAuiPaneInfo_Caption 2585 -#define wxAuiPaneInfo_CaptionVisible 2586 -#define wxAuiPaneInfo_Centre 2587 -#define wxAuiPaneInfo_CentrePane 2588 -#define wxAuiPaneInfo_CloseButton 2589 -#define wxAuiPaneInfo_DefaultPane 2590 -#define wxAuiPaneInfo_DestroyOnClose 2591 -#define wxAuiPaneInfo_Direction 2592 -#define wxAuiPaneInfo_Dock 2593 -#define wxAuiPaneInfo_Dockable 2594 -#define wxAuiPaneInfo_Fixed 2595 -#define wxAuiPaneInfo_Float 2596 -#define wxAuiPaneInfo_Floatable 2597 -#define wxAuiPaneInfo_FloatingPosition_1 2598 -#define wxAuiPaneInfo_FloatingPosition_2 2599 -#define wxAuiPaneInfo_FloatingSize_1 2600 -#define wxAuiPaneInfo_FloatingSize_2 2601 -#define wxAuiPaneInfo_Gripper 2602 -#define wxAuiPaneInfo_GripperTop 2603 -#define wxAuiPaneInfo_HasBorder 2604 -#define wxAuiPaneInfo_HasCaption 2605 -#define wxAuiPaneInfo_HasCloseButton 2606 -#define wxAuiPaneInfo_HasFlag 2607 -#define wxAuiPaneInfo_HasGripper 2608 -#define wxAuiPaneInfo_HasGripperTop 2609 -#define wxAuiPaneInfo_HasMaximizeButton 2610 -#define wxAuiPaneInfo_HasMinimizeButton 2611 -#define wxAuiPaneInfo_HasPinButton 2612 -#define wxAuiPaneInfo_Hide 2613 -#define wxAuiPaneInfo_IsBottomDockable 2614 -#define wxAuiPaneInfo_IsDocked 2615 -#define wxAuiPaneInfo_IsFixed 2616 -#define wxAuiPaneInfo_IsFloatable 2617 -#define wxAuiPaneInfo_IsFloating 2618 -#define wxAuiPaneInfo_IsLeftDockable 2619 -#define wxAuiPaneInfo_IsMovable 2620 -#define wxAuiPaneInfo_IsOk 2621 -#define wxAuiPaneInfo_IsResizable 2622 -#define wxAuiPaneInfo_IsRightDockable 2623 -#define wxAuiPaneInfo_IsShown 2624 -#define wxAuiPaneInfo_IsToolbar 2625 -#define wxAuiPaneInfo_IsTopDockable 2626 -#define wxAuiPaneInfo_Layer 2627 -#define wxAuiPaneInfo_Left 2628 -#define wxAuiPaneInfo_LeftDockable 2629 -#define wxAuiPaneInfo_MaxSize_1 2630 -#define wxAuiPaneInfo_MaxSize_2 2631 -#define wxAuiPaneInfo_MaximizeButton 2632 -#define wxAuiPaneInfo_MinSize_1 2633 -#define wxAuiPaneInfo_MinSize_2 2634 -#define wxAuiPaneInfo_MinimizeButton 2635 -#define wxAuiPaneInfo_Movable 2636 -#define wxAuiPaneInfo_Name 2637 -#define wxAuiPaneInfo_PaneBorder 2638 -#define wxAuiPaneInfo_PinButton 2639 -#define wxAuiPaneInfo_Position 2640 -#define wxAuiPaneInfo_Resizable 2641 -#define wxAuiPaneInfo_Right 2642 -#define wxAuiPaneInfo_RightDockable 2643 -#define wxAuiPaneInfo_Row 2644 -#define wxAuiPaneInfo_SafeSet 2645 -#define wxAuiPaneInfo_SetFlag 2646 -#define wxAuiPaneInfo_Show 2647 -#define wxAuiPaneInfo_ToolbarPane 2648 -#define wxAuiPaneInfo_Top 2649 -#define wxAuiPaneInfo_TopDockable 2650 -#define wxAuiPaneInfo_Window 2651 -#define wxAuiNotebook_new_0 2652 -#define wxAuiNotebook_new_2 2653 -#define wxAuiNotebook_AddPage 2654 -#define wxAuiNotebook_Create 2655 -#define wxAuiNotebook_DeletePage 2656 -#define wxAuiNotebook_GetArtProvider 2657 -#define wxAuiNotebook_GetPage 2658 -#define wxAuiNotebook_GetPageBitmap 2659 -#define wxAuiNotebook_GetPageCount 2660 -#define wxAuiNotebook_GetPageIndex 2661 -#define wxAuiNotebook_GetPageText 2662 -#define wxAuiNotebook_GetSelection 2663 -#define wxAuiNotebook_InsertPage 2664 -#define wxAuiNotebook_RemovePage 2665 -#define wxAuiNotebook_SetArtProvider 2666 -#define wxAuiNotebook_SetFont 2667 -#define wxAuiNotebook_SetPageBitmap 2668 -#define wxAuiNotebook_SetPageText 2669 -#define wxAuiNotebook_SetSelection 2670 -#define wxAuiNotebook_SetTabCtrlHeight 2671 -#define wxAuiNotebook_SetUniformBitmapSize 2672 -#define wxAuiNotebook_destroy 2673 -#define wxMDIParentFrame_new_0 2674 -#define wxMDIParentFrame_new_4 2675 -#define wxMDIParentFrame_destruct 2676 -#define wxMDIParentFrame_ActivateNext 2677 -#define wxMDIParentFrame_ActivatePrevious 2678 -#define wxMDIParentFrame_ArrangeIcons 2679 -#define wxMDIParentFrame_Cascade 2680 -#define wxMDIParentFrame_Create 2681 -#define wxMDIParentFrame_GetActiveChild 2682 -#define wxMDIParentFrame_GetClientWindow 2683 -#define wxMDIParentFrame_Tile 2684 -#define wxMDIChildFrame_new_0 2685 -#define wxMDIChildFrame_new_4 2686 -#define wxMDIChildFrame_destruct 2687 -#define wxMDIChildFrame_Activate 2688 -#define wxMDIChildFrame_Create 2689 -#define wxMDIChildFrame_Maximize 2690 -#define wxMDIChildFrame_Restore 2691 -#define wxMDIClientWindow_new_0 2692 -#define wxMDIClientWindow_new_2 2693 -#define wxMDIClientWindow_destruct 2694 -#define wxMDIClientWindow_CreateClient 2695 -#define wxLayoutAlgorithm_new 2696 -#define wxLayoutAlgorithm_LayoutFrame 2697 -#define wxLayoutAlgorithm_LayoutMDIFrame 2698 -#define wxLayoutAlgorithm_LayoutWindow 2699 -#define wxLayoutAlgorithm_destroy 2700 -#define wxEvent_GetId 2701 -#define wxEvent_GetSkipped 2702 -#define wxEvent_GetTimestamp 2703 -#define wxEvent_IsCommandEvent 2704 -#define wxEvent_ResumePropagation 2705 -#define wxEvent_ShouldPropagate 2706 -#define wxEvent_Skip 2707 -#define wxEvent_StopPropagation 2708 -#define wxCommandEvent_getClientData 2709 -#define wxCommandEvent_GetExtraLong 2710 -#define wxCommandEvent_GetInt 2711 -#define wxCommandEvent_GetSelection 2712 -#define wxCommandEvent_GetString 2713 -#define wxCommandEvent_IsChecked 2714 -#define wxCommandEvent_IsSelection 2715 -#define wxCommandEvent_SetInt 2716 -#define wxCommandEvent_SetString 2717 -#define wxScrollEvent_GetOrientation 2718 -#define wxScrollEvent_GetPosition 2719 -#define wxScrollWinEvent_GetOrientation 2720 -#define wxScrollWinEvent_GetPosition 2721 -#define wxMouseEvent_AltDown 2722 -#define wxMouseEvent_Button 2723 -#define wxMouseEvent_ButtonDClick 2724 -#define wxMouseEvent_ButtonDown 2725 -#define wxMouseEvent_ButtonUp 2726 -#define wxMouseEvent_CmdDown 2727 -#define wxMouseEvent_ControlDown 2728 -#define wxMouseEvent_Dragging 2729 -#define wxMouseEvent_Entering 2730 -#define wxMouseEvent_GetButton 2731 -#define wxMouseEvent_GetPosition 2734 -#define wxMouseEvent_GetLogicalPosition 2735 -#define wxMouseEvent_GetLinesPerAction 2736 -#define wxMouseEvent_GetWheelRotation 2737 -#define wxMouseEvent_GetWheelDelta 2738 -#define wxMouseEvent_GetX 2739 -#define wxMouseEvent_GetY 2740 -#define wxMouseEvent_IsButton 2741 -#define wxMouseEvent_IsPageScroll 2742 -#define wxMouseEvent_Leaving 2743 -#define wxMouseEvent_LeftDClick 2744 -#define wxMouseEvent_LeftDown 2745 -#define wxMouseEvent_LeftIsDown 2746 -#define wxMouseEvent_LeftUp 2747 -#define wxMouseEvent_MetaDown 2748 -#define wxMouseEvent_MiddleDClick 2749 -#define wxMouseEvent_MiddleDown 2750 -#define wxMouseEvent_MiddleIsDown 2751 -#define wxMouseEvent_MiddleUp 2752 -#define wxMouseEvent_Moving 2753 -#define wxMouseEvent_RightDClick 2754 -#define wxMouseEvent_RightDown 2755 -#define wxMouseEvent_RightIsDown 2756 -#define wxMouseEvent_RightUp 2757 -#define wxMouseEvent_ShiftDown 2758 -#define wxSetCursorEvent_GetCursor 2759 -#define wxSetCursorEvent_GetX 2760 -#define wxSetCursorEvent_GetY 2761 -#define wxSetCursorEvent_HasCursor 2762 -#define wxSetCursorEvent_SetCursor 2763 -#define wxKeyEvent_AltDown 2764 -#define wxKeyEvent_CmdDown 2765 -#define wxKeyEvent_ControlDown 2766 -#define wxKeyEvent_GetKeyCode 2767 -#define wxKeyEvent_GetModifiers 2768 -#define wxKeyEvent_GetPosition 2771 -#define wxKeyEvent_GetRawKeyCode 2772 -#define wxKeyEvent_GetRawKeyFlags 2773 -#define wxKeyEvent_GetUnicodeKey 2774 -#define wxKeyEvent_GetX 2775 -#define wxKeyEvent_GetY 2776 -#define wxKeyEvent_HasModifiers 2777 -#define wxKeyEvent_MetaDown 2778 -#define wxKeyEvent_ShiftDown 2779 -#define wxSizeEvent_GetSize 2780 -#define wxMoveEvent_GetPosition 2781 -#define wxEraseEvent_GetDC 2782 -#define wxFocusEvent_GetWindow 2783 -#define wxChildFocusEvent_GetWindow 2784 -#define wxMenuEvent_GetMenu 2785 -#define wxMenuEvent_GetMenuId 2786 -#define wxMenuEvent_IsPopup 2787 -#define wxCloseEvent_CanVeto 2788 -#define wxCloseEvent_GetLoggingOff 2789 -#define wxCloseEvent_SetCanVeto 2790 -#define wxCloseEvent_SetLoggingOff 2791 -#define wxCloseEvent_Veto 2792 -#define wxShowEvent_SetShow 2793 -#define wxShowEvent_GetShow 2794 -#define wxIconizeEvent_Iconized 2795 -#define wxJoystickEvent_ButtonDown 2796 -#define wxJoystickEvent_ButtonIsDown 2797 -#define wxJoystickEvent_ButtonUp 2798 -#define wxJoystickEvent_GetButtonChange 2799 -#define wxJoystickEvent_GetButtonState 2800 -#define wxJoystickEvent_GetJoystick 2801 -#define wxJoystickEvent_GetPosition 2802 -#define wxJoystickEvent_GetZPosition 2803 -#define wxJoystickEvent_IsButton 2804 -#define wxJoystickEvent_IsMove 2805 -#define wxJoystickEvent_IsZMove 2806 -#define wxUpdateUIEvent_CanUpdate 2807 -#define wxUpdateUIEvent_Check 2808 -#define wxUpdateUIEvent_Enable 2809 -#define wxUpdateUIEvent_Show 2810 -#define wxUpdateUIEvent_GetChecked 2811 -#define wxUpdateUIEvent_GetEnabled 2812 -#define wxUpdateUIEvent_GetShown 2813 -#define wxUpdateUIEvent_GetSetChecked 2814 -#define wxUpdateUIEvent_GetSetEnabled 2815 -#define wxUpdateUIEvent_GetSetShown 2816 -#define wxUpdateUIEvent_GetSetText 2817 -#define wxUpdateUIEvent_GetText 2818 -#define wxUpdateUIEvent_GetMode 2819 -#define wxUpdateUIEvent_GetUpdateInterval 2820 -#define wxUpdateUIEvent_ResetUpdateTime 2821 -#define wxUpdateUIEvent_SetMode 2822 -#define wxUpdateUIEvent_SetText 2823 -#define wxUpdateUIEvent_SetUpdateInterval 2824 -#define wxMouseCaptureChangedEvent_GetCapturedWindow 2825 -#define wxPaletteChangedEvent_SetChangedWindow 2826 -#define wxPaletteChangedEvent_GetChangedWindow 2827 -#define wxQueryNewPaletteEvent_SetPaletteRealized 2828 -#define wxQueryNewPaletteEvent_GetPaletteRealized 2829 -#define wxNavigationKeyEvent_GetDirection 2830 -#define wxNavigationKeyEvent_SetDirection 2831 -#define wxNavigationKeyEvent_IsWindowChange 2832 -#define wxNavigationKeyEvent_SetWindowChange 2833 -#define wxNavigationKeyEvent_IsFromTab 2834 -#define wxNavigationKeyEvent_SetFromTab 2835 -#define wxNavigationKeyEvent_GetCurrentFocus 2836 -#define wxNavigationKeyEvent_SetCurrentFocus 2837 -#define wxHelpEvent_GetOrigin 2838 -#define wxHelpEvent_GetPosition 2839 -#define wxHelpEvent_SetOrigin 2840 -#define wxHelpEvent_SetPosition 2841 -#define wxContextMenuEvent_GetPosition 2842 -#define wxContextMenuEvent_SetPosition 2843 -#define wxIdleEvent_CanSend 2844 -#define wxIdleEvent_GetMode 2845 -#define wxIdleEvent_RequestMore 2846 -#define wxIdleEvent_MoreRequested 2847 -#define wxIdleEvent_SetMode 2848 -#define wxGridEvent_AltDown 2849 -#define wxGridEvent_ControlDown 2850 -#define wxGridEvent_GetCol 2851 -#define wxGridEvent_GetPosition 2852 -#define wxGridEvent_GetRow 2853 -#define wxGridEvent_MetaDown 2854 -#define wxGridEvent_Selecting 2855 -#define wxGridEvent_ShiftDown 2856 -#define wxNotifyEvent_Allow 2857 -#define wxNotifyEvent_IsAllowed 2858 -#define wxNotifyEvent_Veto 2859 -#define wxSashEvent_GetEdge 2860 -#define wxSashEvent_GetDragRect 2861 -#define wxSashEvent_GetDragStatus 2862 -#define wxListEvent_GetCacheFrom 2863 -#define wxListEvent_GetCacheTo 2864 -#define wxListEvent_GetKeyCode 2865 -#define wxListEvent_GetIndex 2866 -#define wxListEvent_GetColumn 2867 -#define wxListEvent_GetPoint 2868 -#define wxListEvent_GetLabel 2869 -#define wxListEvent_GetText 2870 -#define wxListEvent_GetImage 2871 -#define wxListEvent_GetData 2872 -#define wxListEvent_GetMask 2873 -#define wxListEvent_GetItem 2874 -#define wxListEvent_IsEditCancelled 2875 -#define wxDateEvent_GetDate 2876 -#define wxCalendarEvent_GetWeekDay 2877 -#define wxFileDirPickerEvent_GetPath 2878 -#define wxColourPickerEvent_GetColour 2879 -#define wxFontPickerEvent_GetFont 2880 -#define wxStyledTextEvent_GetPosition 2881 -#define wxStyledTextEvent_GetKey 2882 -#define wxStyledTextEvent_GetModifiers 2883 -#define wxStyledTextEvent_GetModificationType 2884 -#define wxStyledTextEvent_GetText 2885 -#define wxStyledTextEvent_GetLength 2886 -#define wxStyledTextEvent_GetLinesAdded 2887 -#define wxStyledTextEvent_GetLine 2888 -#define wxStyledTextEvent_GetFoldLevelNow 2889 -#define wxStyledTextEvent_GetFoldLevelPrev 2890 -#define wxStyledTextEvent_GetMargin 2891 -#define wxStyledTextEvent_GetMessage 2892 -#define wxStyledTextEvent_GetWParam 2893 -#define wxStyledTextEvent_GetLParam 2894 -#define wxStyledTextEvent_GetListType 2895 -#define wxStyledTextEvent_GetX 2896 -#define wxStyledTextEvent_GetY 2897 -#define wxStyledTextEvent_GetDragText 2898 -#define wxStyledTextEvent_GetDragAllowMove 2899 -#define wxStyledTextEvent_GetDragResult 2900 -#define wxStyledTextEvent_GetShift 2901 -#define wxStyledTextEvent_GetControl 2902 -#define wxStyledTextEvent_GetAlt 2903 -#define utils_wxGetKeyState 2904 -#define utils_wxGetMousePosition 2905 -#define utils_wxGetMouseState 2906 -#define utils_wxSetDetectableAutoRepeat 2907 -#define utils_wxBell 2908 -#define utils_wxFindMenuItemId 2909 -#define utils_wxGenericFindWindowAtPoint 2910 -#define utils_wxFindWindowAtPoint 2911 -#define utils_wxBeginBusyCursor 2912 -#define utils_wxEndBusyCursor 2913 -#define utils_wxIsBusy 2914 -#define utils_wxShutdown 2915 -#define utils_wxShell 2916 -#define utils_wxLaunchDefaultBrowser 2917 -#define utils_wxGetEmailAddress 2918 -#define utils_wxGetUserId 2919 -#define utils_wxGetHomeDir 2920 -#define utils_wxNewId 2921 -#define utils_wxRegisterId 2922 -#define utils_wxGetCurrentId 2923 -#define utils_wxGetOsDescription 2924 -#define utils_wxIsPlatformLittleEndian 2925 -#define utils_wxIsPlatform64Bit 2926 -#define gdicmn_wxDisplaySize 2927 -#define gdicmn_wxSetCursor 2928 -#define wxPrintout_new 2929 -#define wxPrintout_destruct 2930 -#define wxPrintout_GetDC 2931 -#define wxPrintout_GetPageSizeMM 2932 -#define wxPrintout_GetPageSizePixels 2933 -#define wxPrintout_GetPaperRectPixels 2934 -#define wxPrintout_GetPPIPrinter 2935 -#define wxPrintout_GetPPIScreen 2936 -#define wxPrintout_GetTitle 2937 -#define wxPrintout_IsPreview 2938 -#define wxPrintout_FitThisSizeToPaper 2939 -#define wxPrintout_FitThisSizeToPage 2940 -#define wxPrintout_FitThisSizeToPageMargins 2941 -#define wxPrintout_MapScreenSizeToPaper 2942 -#define wxPrintout_MapScreenSizeToPage 2943 -#define wxPrintout_MapScreenSizeToPageMargins 2944 -#define wxPrintout_MapScreenSizeToDevice 2945 -#define wxPrintout_GetLogicalPaperRect 2946 -#define wxPrintout_GetLogicalPageRect 2947 -#define wxPrintout_GetLogicalPageMarginsRect 2948 -#define wxPrintout_SetLogicalOrigin 2949 -#define wxPrintout_OffsetLogicalOrigin 2950 -#define wxStyledTextCtrl_new_2 2951 -#define wxStyledTextCtrl_new_0 2952 -#define wxStyledTextCtrl_destruct 2953 -#define wxStyledTextCtrl_Create 2954 -#define wxStyledTextCtrl_AddText 2955 -#define wxStyledTextCtrl_AddStyledText 2956 -#define wxStyledTextCtrl_InsertText 2957 -#define wxStyledTextCtrl_ClearAll 2958 -#define wxStyledTextCtrl_ClearDocumentStyle 2959 -#define wxStyledTextCtrl_GetLength 2960 -#define wxStyledTextCtrl_GetCharAt 2961 -#define wxStyledTextCtrl_GetCurrentPos 2962 -#define wxStyledTextCtrl_GetAnchor 2963 -#define wxStyledTextCtrl_GetStyleAt 2964 -#define wxStyledTextCtrl_Redo 2965 -#define wxStyledTextCtrl_SetUndoCollection 2966 -#define wxStyledTextCtrl_SelectAll 2967 -#define wxStyledTextCtrl_SetSavePoint 2968 -#define wxStyledTextCtrl_GetStyledText 2969 -#define wxStyledTextCtrl_CanRedo 2970 -#define wxStyledTextCtrl_MarkerLineFromHandle 2971 -#define wxStyledTextCtrl_MarkerDeleteHandle 2972 -#define wxStyledTextCtrl_GetUndoCollection 2973 -#define wxStyledTextCtrl_GetViewWhiteSpace 2974 -#define wxStyledTextCtrl_SetViewWhiteSpace 2975 -#define wxStyledTextCtrl_PositionFromPoint 2976 -#define wxStyledTextCtrl_PositionFromPointClose 2977 -#define wxStyledTextCtrl_GotoLine 2978 -#define wxStyledTextCtrl_GotoPos 2979 -#define wxStyledTextCtrl_SetAnchor 2980 -#define wxStyledTextCtrl_GetCurLine 2981 -#define wxStyledTextCtrl_GetEndStyled 2982 -#define wxStyledTextCtrl_ConvertEOLs 2983 -#define wxStyledTextCtrl_GetEOLMode 2984 -#define wxStyledTextCtrl_SetEOLMode 2985 -#define wxStyledTextCtrl_StartStyling 2986 -#define wxStyledTextCtrl_SetStyling 2987 -#define wxStyledTextCtrl_GetBufferedDraw 2988 -#define wxStyledTextCtrl_SetBufferedDraw 2989 -#define wxStyledTextCtrl_SetTabWidth 2990 -#define wxStyledTextCtrl_GetTabWidth 2991 -#define wxStyledTextCtrl_SetCodePage 2992 -#define wxStyledTextCtrl_MarkerDefine 2993 -#define wxStyledTextCtrl_MarkerSetForeground 2994 -#define wxStyledTextCtrl_MarkerSetBackground 2995 -#define wxStyledTextCtrl_MarkerAdd 2996 -#define wxStyledTextCtrl_MarkerDelete 2997 -#define wxStyledTextCtrl_MarkerDeleteAll 2998 -#define wxStyledTextCtrl_MarkerGet 2999 -#define wxStyledTextCtrl_MarkerNext 3000 -#define wxStyledTextCtrl_MarkerPrevious 3001 -#define wxStyledTextCtrl_MarkerDefineBitmap 3002 -#define wxStyledTextCtrl_MarkerAddSet 3003 -#define wxStyledTextCtrl_MarkerSetAlpha 3004 -#define wxStyledTextCtrl_SetMarginType 3005 -#define wxStyledTextCtrl_GetMarginType 3006 -#define wxStyledTextCtrl_SetMarginWidth 3007 -#define wxStyledTextCtrl_GetMarginWidth 3008 -#define wxStyledTextCtrl_SetMarginMask 3009 -#define wxStyledTextCtrl_GetMarginMask 3010 -#define wxStyledTextCtrl_SetMarginSensitive 3011 -#define wxStyledTextCtrl_GetMarginSensitive 3012 -#define wxStyledTextCtrl_StyleClearAll 3013 -#define wxStyledTextCtrl_StyleSetForeground 3014 -#define wxStyledTextCtrl_StyleSetBackground 3015 -#define wxStyledTextCtrl_StyleSetBold 3016 -#define wxStyledTextCtrl_StyleSetItalic 3017 -#define wxStyledTextCtrl_StyleSetSize 3018 -#define wxStyledTextCtrl_StyleSetFaceName 3019 -#define wxStyledTextCtrl_StyleSetEOLFilled 3020 -#define wxStyledTextCtrl_StyleResetDefault 3021 -#define wxStyledTextCtrl_StyleSetUnderline 3022 -#define wxStyledTextCtrl_StyleSetCase 3023 -#define wxStyledTextCtrl_StyleSetHotSpot 3024 -#define wxStyledTextCtrl_SetSelForeground 3025 -#define wxStyledTextCtrl_SetSelBackground 3026 -#define wxStyledTextCtrl_GetSelAlpha 3027 -#define wxStyledTextCtrl_SetSelAlpha 3028 -#define wxStyledTextCtrl_SetCaretForeground 3029 -#define wxStyledTextCtrl_CmdKeyAssign 3030 -#define wxStyledTextCtrl_CmdKeyClear 3031 -#define wxStyledTextCtrl_CmdKeyClearAll 3032 -#define wxStyledTextCtrl_SetStyleBytes 3033 -#define wxStyledTextCtrl_StyleSetVisible 3034 -#define wxStyledTextCtrl_GetCaretPeriod 3035 -#define wxStyledTextCtrl_SetCaretPeriod 3036 -#define wxStyledTextCtrl_SetWordChars 3037 -#define wxStyledTextCtrl_BeginUndoAction 3038 -#define wxStyledTextCtrl_EndUndoAction 3039 -#define wxStyledTextCtrl_IndicatorSetStyle 3040 -#define wxStyledTextCtrl_IndicatorGetStyle 3041 -#define wxStyledTextCtrl_IndicatorSetForeground 3042 -#define wxStyledTextCtrl_IndicatorGetForeground 3043 -#define wxStyledTextCtrl_SetWhitespaceForeground 3044 -#define wxStyledTextCtrl_SetWhitespaceBackground 3045 -#define wxStyledTextCtrl_GetStyleBits 3046 -#define wxStyledTextCtrl_SetLineState 3047 -#define wxStyledTextCtrl_GetLineState 3048 -#define wxStyledTextCtrl_GetMaxLineState 3049 -#define wxStyledTextCtrl_GetCaretLineVisible 3050 -#define wxStyledTextCtrl_SetCaretLineVisible 3051 -#define wxStyledTextCtrl_GetCaretLineBackground 3052 -#define wxStyledTextCtrl_SetCaretLineBackground 3053 -#define wxStyledTextCtrl_AutoCompShow 3054 -#define wxStyledTextCtrl_AutoCompCancel 3055 -#define wxStyledTextCtrl_AutoCompActive 3056 -#define wxStyledTextCtrl_AutoCompPosStart 3057 -#define wxStyledTextCtrl_AutoCompComplete 3058 -#define wxStyledTextCtrl_AutoCompStops 3059 -#define wxStyledTextCtrl_AutoCompSetSeparator 3060 -#define wxStyledTextCtrl_AutoCompGetSeparator 3061 -#define wxStyledTextCtrl_AutoCompSelect 3062 -#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3063 -#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3064 -#define wxStyledTextCtrl_AutoCompSetFillUps 3065 -#define wxStyledTextCtrl_AutoCompSetChooseSingle 3066 -#define wxStyledTextCtrl_AutoCompGetChooseSingle 3067 -#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3068 -#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3069 -#define wxStyledTextCtrl_UserListShow 3070 -#define wxStyledTextCtrl_AutoCompSetAutoHide 3071 -#define wxStyledTextCtrl_AutoCompGetAutoHide 3072 -#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3073 -#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3074 -#define wxStyledTextCtrl_RegisterImage 3075 -#define wxStyledTextCtrl_ClearRegisteredImages 3076 -#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3077 -#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3078 -#define wxStyledTextCtrl_AutoCompSetMaxWidth 3079 -#define wxStyledTextCtrl_AutoCompGetMaxWidth 3080 -#define wxStyledTextCtrl_AutoCompSetMaxHeight 3081 -#define wxStyledTextCtrl_AutoCompGetMaxHeight 3082 -#define wxStyledTextCtrl_SetIndent 3083 -#define wxStyledTextCtrl_GetIndent 3084 -#define wxStyledTextCtrl_SetUseTabs 3085 -#define wxStyledTextCtrl_GetUseTabs 3086 -#define wxStyledTextCtrl_SetLineIndentation 3087 -#define wxStyledTextCtrl_GetLineIndentation 3088 -#define wxStyledTextCtrl_GetLineIndentPosition 3089 -#define wxStyledTextCtrl_GetColumn 3090 -#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3091 -#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3092 -#define wxStyledTextCtrl_SetIndentationGuides 3093 -#define wxStyledTextCtrl_GetIndentationGuides 3094 -#define wxStyledTextCtrl_SetHighlightGuide 3095 -#define wxStyledTextCtrl_GetHighlightGuide 3096 -#define wxStyledTextCtrl_GetLineEndPosition 3097 -#define wxStyledTextCtrl_GetCodePage 3098 -#define wxStyledTextCtrl_GetCaretForeground 3099 -#define wxStyledTextCtrl_GetReadOnly 3100 -#define wxStyledTextCtrl_SetCurrentPos 3101 -#define wxStyledTextCtrl_SetSelectionStart 3102 -#define wxStyledTextCtrl_GetSelectionStart 3103 -#define wxStyledTextCtrl_SetSelectionEnd 3104 -#define wxStyledTextCtrl_GetSelectionEnd 3105 -#define wxStyledTextCtrl_SetPrintMagnification 3106 -#define wxStyledTextCtrl_GetPrintMagnification 3107 -#define wxStyledTextCtrl_SetPrintColourMode 3108 -#define wxStyledTextCtrl_GetPrintColourMode 3109 -#define wxStyledTextCtrl_FindText 3110 -#define wxStyledTextCtrl_FormatRange 3111 -#define wxStyledTextCtrl_GetFirstVisibleLine 3112 -#define wxStyledTextCtrl_GetLine 3113 -#define wxStyledTextCtrl_GetLineCount 3114 -#define wxStyledTextCtrl_SetMarginLeft 3115 -#define wxStyledTextCtrl_GetMarginLeft 3116 -#define wxStyledTextCtrl_SetMarginRight 3117 -#define wxStyledTextCtrl_GetMarginRight 3118 -#define wxStyledTextCtrl_GetModify 3119 -#define wxStyledTextCtrl_SetSelection 3120 -#define wxStyledTextCtrl_GetSelectedText 3121 -#define wxStyledTextCtrl_GetTextRange 3122 -#define wxStyledTextCtrl_HideSelection 3123 -#define wxStyledTextCtrl_LineFromPosition 3124 -#define wxStyledTextCtrl_PositionFromLine 3125 -#define wxStyledTextCtrl_LineScroll 3126 -#define wxStyledTextCtrl_EnsureCaretVisible 3127 -#define wxStyledTextCtrl_ReplaceSelection 3128 -#define wxStyledTextCtrl_SetReadOnly 3129 -#define wxStyledTextCtrl_CanPaste 3130 -#define wxStyledTextCtrl_CanUndo 3131 -#define wxStyledTextCtrl_EmptyUndoBuffer 3132 -#define wxStyledTextCtrl_Undo 3133 -#define wxStyledTextCtrl_Cut 3134 -#define wxStyledTextCtrl_Copy 3135 -#define wxStyledTextCtrl_Paste 3136 -#define wxStyledTextCtrl_Clear 3137 -#define wxStyledTextCtrl_SetText 3138 -#define wxStyledTextCtrl_GetText 3139 -#define wxStyledTextCtrl_GetTextLength 3140 -#define wxStyledTextCtrl_GetOvertype 3141 -#define wxStyledTextCtrl_SetCaretWidth 3142 -#define wxStyledTextCtrl_GetCaretWidth 3143 -#define wxStyledTextCtrl_SetTargetStart 3144 -#define wxStyledTextCtrl_GetTargetStart 3145 -#define wxStyledTextCtrl_SetTargetEnd 3146 -#define wxStyledTextCtrl_GetTargetEnd 3147 -#define wxStyledTextCtrl_ReplaceTarget 3148 -#define wxStyledTextCtrl_SearchInTarget 3149 -#define wxStyledTextCtrl_SetSearchFlags 3150 -#define wxStyledTextCtrl_GetSearchFlags 3151 -#define wxStyledTextCtrl_CallTipShow 3152 -#define wxStyledTextCtrl_CallTipCancel 3153 -#define wxStyledTextCtrl_CallTipActive 3154 -#define wxStyledTextCtrl_CallTipPosAtStart 3155 -#define wxStyledTextCtrl_CallTipSetHighlight 3156 -#define wxStyledTextCtrl_CallTipSetBackground 3157 -#define wxStyledTextCtrl_CallTipSetForeground 3158 -#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3159 -#define wxStyledTextCtrl_CallTipUseStyle 3160 -#define wxStyledTextCtrl_VisibleFromDocLine 3161 -#define wxStyledTextCtrl_DocLineFromVisible 3162 -#define wxStyledTextCtrl_WrapCount 3163 -#define wxStyledTextCtrl_SetFoldLevel 3164 -#define wxStyledTextCtrl_GetFoldLevel 3165 -#define wxStyledTextCtrl_GetLastChild 3166 -#define wxStyledTextCtrl_GetFoldParent 3167 -#define wxStyledTextCtrl_ShowLines 3168 -#define wxStyledTextCtrl_HideLines 3169 -#define wxStyledTextCtrl_GetLineVisible 3170 -#define wxStyledTextCtrl_SetFoldExpanded 3171 -#define wxStyledTextCtrl_GetFoldExpanded 3172 -#define wxStyledTextCtrl_ToggleFold 3173 -#define wxStyledTextCtrl_EnsureVisible 3174 -#define wxStyledTextCtrl_SetFoldFlags 3175 -#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3176 -#define wxStyledTextCtrl_SetTabIndents 3177 -#define wxStyledTextCtrl_GetTabIndents 3178 -#define wxStyledTextCtrl_SetBackSpaceUnIndents 3179 -#define wxStyledTextCtrl_GetBackSpaceUnIndents 3180 -#define wxStyledTextCtrl_SetMouseDwellTime 3181 -#define wxStyledTextCtrl_GetMouseDwellTime 3182 -#define wxStyledTextCtrl_WordStartPosition 3183 -#define wxStyledTextCtrl_WordEndPosition 3184 -#define wxStyledTextCtrl_SetWrapMode 3185 -#define wxStyledTextCtrl_GetWrapMode 3186 -#define wxStyledTextCtrl_SetWrapVisualFlags 3187 -#define wxStyledTextCtrl_GetWrapVisualFlags 3188 -#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3189 -#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3190 -#define wxStyledTextCtrl_SetWrapStartIndent 3191 -#define wxStyledTextCtrl_GetWrapStartIndent 3192 -#define wxStyledTextCtrl_SetLayoutCache 3193 -#define wxStyledTextCtrl_GetLayoutCache 3194 -#define wxStyledTextCtrl_SetScrollWidth 3195 -#define wxStyledTextCtrl_GetScrollWidth 3196 -#define wxStyledTextCtrl_TextWidth 3197 -#define wxStyledTextCtrl_GetEndAtLastLine 3198 -#define wxStyledTextCtrl_TextHeight 3199 -#define wxStyledTextCtrl_SetUseVerticalScrollBar 3200 -#define wxStyledTextCtrl_GetUseVerticalScrollBar 3201 -#define wxStyledTextCtrl_AppendText 3202 -#define wxStyledTextCtrl_GetTwoPhaseDraw 3203 -#define wxStyledTextCtrl_SetTwoPhaseDraw 3204 -#define wxStyledTextCtrl_TargetFromSelection 3205 -#define wxStyledTextCtrl_LinesJoin 3206 -#define wxStyledTextCtrl_LinesSplit 3207 -#define wxStyledTextCtrl_SetFoldMarginColour 3208 -#define wxStyledTextCtrl_SetFoldMarginHiColour 3209 -#define wxStyledTextCtrl_LineDown 3210 -#define wxStyledTextCtrl_LineDownExtend 3211 -#define wxStyledTextCtrl_LineUp 3212 -#define wxStyledTextCtrl_LineUpExtend 3213 -#define wxStyledTextCtrl_CharLeft 3214 -#define wxStyledTextCtrl_CharLeftExtend 3215 -#define wxStyledTextCtrl_CharRight 3216 -#define wxStyledTextCtrl_CharRightExtend 3217 -#define wxStyledTextCtrl_WordLeft 3218 -#define wxStyledTextCtrl_WordLeftExtend 3219 -#define wxStyledTextCtrl_WordRight 3220 -#define wxStyledTextCtrl_WordRightExtend 3221 -#define wxStyledTextCtrl_Home 3222 -#define wxStyledTextCtrl_HomeExtend 3223 -#define wxStyledTextCtrl_LineEnd 3224 -#define wxStyledTextCtrl_LineEndExtend 3225 -#define wxStyledTextCtrl_DocumentStart 3226 -#define wxStyledTextCtrl_DocumentStartExtend 3227 -#define wxStyledTextCtrl_DocumentEnd 3228 -#define wxStyledTextCtrl_DocumentEndExtend 3229 -#define wxStyledTextCtrl_PageUp 3230 -#define wxStyledTextCtrl_PageUpExtend 3231 -#define wxStyledTextCtrl_PageDown 3232 -#define wxStyledTextCtrl_PageDownExtend 3233 -#define wxStyledTextCtrl_EditToggleOvertype 3234 -#define wxStyledTextCtrl_Cancel 3235 -#define wxStyledTextCtrl_DeleteBack 3236 -#define wxStyledTextCtrl_Tab 3237 -#define wxStyledTextCtrl_BackTab 3238 -#define wxStyledTextCtrl_NewLine 3239 -#define wxStyledTextCtrl_FormFeed 3240 -#define wxStyledTextCtrl_VCHome 3241 -#define wxStyledTextCtrl_VCHomeExtend 3242 -#define wxStyledTextCtrl_ZoomIn 3243 -#define wxStyledTextCtrl_ZoomOut 3244 -#define wxStyledTextCtrl_DelWordLeft 3245 -#define wxStyledTextCtrl_DelWordRight 3246 -#define wxStyledTextCtrl_LineCut 3247 -#define wxStyledTextCtrl_LineDelete 3248 -#define wxStyledTextCtrl_LineTranspose 3249 -#define wxStyledTextCtrl_LineDuplicate 3250 -#define wxStyledTextCtrl_LowerCase 3251 -#define wxStyledTextCtrl_UpperCase 3252 -#define wxStyledTextCtrl_LineScrollDown 3253 -#define wxStyledTextCtrl_LineScrollUp 3254 -#define wxStyledTextCtrl_DeleteBackNotLine 3255 -#define wxStyledTextCtrl_HomeDisplay 3256 -#define wxStyledTextCtrl_HomeDisplayExtend 3257 -#define wxStyledTextCtrl_LineEndDisplay 3258 -#define wxStyledTextCtrl_LineEndDisplayExtend 3259 -#define wxStyledTextCtrl_HomeWrapExtend 3260 -#define wxStyledTextCtrl_LineEndWrap 3261 -#define wxStyledTextCtrl_LineEndWrapExtend 3262 -#define wxStyledTextCtrl_VCHomeWrap 3263 -#define wxStyledTextCtrl_VCHomeWrapExtend 3264 -#define wxStyledTextCtrl_LineCopy 3265 -#define wxStyledTextCtrl_MoveCaretInsideView 3266 -#define wxStyledTextCtrl_LineLength 3267 -#define wxStyledTextCtrl_BraceHighlight 3268 -#define wxStyledTextCtrl_BraceBadLight 3269 -#define wxStyledTextCtrl_BraceMatch 3270 -#define wxStyledTextCtrl_GetViewEOL 3271 -#define wxStyledTextCtrl_SetViewEOL 3272 -#define wxStyledTextCtrl_SetModEventMask 3273 -#define wxStyledTextCtrl_GetEdgeColumn 3274 -#define wxStyledTextCtrl_SetEdgeColumn 3275 -#define wxStyledTextCtrl_SetEdgeMode 3276 -#define wxStyledTextCtrl_GetEdgeMode 3277 -#define wxStyledTextCtrl_GetEdgeColour 3278 -#define wxStyledTextCtrl_SetEdgeColour 3279 -#define wxStyledTextCtrl_SearchAnchor 3280 -#define wxStyledTextCtrl_SearchNext 3281 -#define wxStyledTextCtrl_SearchPrev 3282 -#define wxStyledTextCtrl_LinesOnScreen 3283 -#define wxStyledTextCtrl_UsePopUp 3284 -#define wxStyledTextCtrl_SelectionIsRectangle 3285 -#define wxStyledTextCtrl_SetZoom 3286 -#define wxStyledTextCtrl_GetZoom 3287 -#define wxStyledTextCtrl_GetModEventMask 3288 -#define wxStyledTextCtrl_SetSTCFocus 3289 -#define wxStyledTextCtrl_GetSTCFocus 3290 -#define wxStyledTextCtrl_SetStatus 3291 -#define wxStyledTextCtrl_GetStatus 3292 -#define wxStyledTextCtrl_SetMouseDownCaptures 3293 -#define wxStyledTextCtrl_GetMouseDownCaptures 3294 -#define wxStyledTextCtrl_SetSTCCursor 3295 -#define wxStyledTextCtrl_GetSTCCursor 3296 -#define wxStyledTextCtrl_SetControlCharSymbol 3297 -#define wxStyledTextCtrl_GetControlCharSymbol 3298 -#define wxStyledTextCtrl_WordPartLeft 3299 -#define wxStyledTextCtrl_WordPartLeftExtend 3300 -#define wxStyledTextCtrl_WordPartRight 3301 -#define wxStyledTextCtrl_WordPartRightExtend 3302 -#define wxStyledTextCtrl_SetVisiblePolicy 3303 -#define wxStyledTextCtrl_DelLineLeft 3304 -#define wxStyledTextCtrl_DelLineRight 3305 -#define wxStyledTextCtrl_GetXOffset 3306 -#define wxStyledTextCtrl_ChooseCaretX 3307 -#define wxStyledTextCtrl_SetXCaretPolicy 3308 -#define wxStyledTextCtrl_SetYCaretPolicy 3309 -#define wxStyledTextCtrl_GetPrintWrapMode 3310 -#define wxStyledTextCtrl_SetHotspotActiveForeground 3311 -#define wxStyledTextCtrl_SetHotspotActiveBackground 3312 -#define wxStyledTextCtrl_SetHotspotActiveUnderline 3313 -#define wxStyledTextCtrl_SetHotspotSingleLine 3314 -#define wxStyledTextCtrl_ParaDownExtend 3315 -#define wxStyledTextCtrl_ParaUp 3316 -#define wxStyledTextCtrl_ParaUpExtend 3317 -#define wxStyledTextCtrl_PositionBefore 3318 -#define wxStyledTextCtrl_PositionAfter 3319 -#define wxStyledTextCtrl_CopyRange 3320 -#define wxStyledTextCtrl_CopyText 3321 -#define wxStyledTextCtrl_SetSelectionMode 3322 -#define wxStyledTextCtrl_GetSelectionMode 3323 -#define wxStyledTextCtrl_LineDownRectExtend 3324 -#define wxStyledTextCtrl_LineUpRectExtend 3325 -#define wxStyledTextCtrl_CharLeftRectExtend 3326 -#define wxStyledTextCtrl_CharRightRectExtend 3327 -#define wxStyledTextCtrl_HomeRectExtend 3328 -#define wxStyledTextCtrl_VCHomeRectExtend 3329 -#define wxStyledTextCtrl_LineEndRectExtend 3330 -#define wxStyledTextCtrl_PageUpRectExtend 3331 -#define wxStyledTextCtrl_PageDownRectExtend 3332 -#define wxStyledTextCtrl_StutteredPageUp 3333 -#define wxStyledTextCtrl_StutteredPageUpExtend 3334 -#define wxStyledTextCtrl_StutteredPageDown 3335 -#define wxStyledTextCtrl_StutteredPageDownExtend 3336 -#define wxStyledTextCtrl_WordLeftEnd 3337 -#define wxStyledTextCtrl_WordLeftEndExtend 3338 -#define wxStyledTextCtrl_WordRightEnd 3339 -#define wxStyledTextCtrl_WordRightEndExtend 3340 -#define wxStyledTextCtrl_SetWhitespaceChars 3341 -#define wxStyledTextCtrl_SetCharsDefault 3342 -#define wxStyledTextCtrl_AutoCompGetCurrent 3343 -#define wxStyledTextCtrl_Allocate 3344 -#define wxStyledTextCtrl_FindColumn 3345 -#define wxStyledTextCtrl_GetCaretSticky 3346 -#define wxStyledTextCtrl_SetCaretSticky 3347 -#define wxStyledTextCtrl_ToggleCaretSticky 3348 -#define wxStyledTextCtrl_SetPasteConvertEndings 3349 -#define wxStyledTextCtrl_GetPasteConvertEndings 3350 -#define wxStyledTextCtrl_SelectionDuplicate 3351 -#define wxStyledTextCtrl_SetCaretLineBackAlpha 3352 -#define wxStyledTextCtrl_GetCaretLineBackAlpha 3353 -#define wxStyledTextCtrl_StartRecord 3354 -#define wxStyledTextCtrl_StopRecord 3355 -#define wxStyledTextCtrl_SetLexer 3356 -#define wxStyledTextCtrl_GetLexer 3357 -#define wxStyledTextCtrl_Colourise 3358 -#define wxStyledTextCtrl_SetProperty 3359 -#define wxStyledTextCtrl_SetKeyWords 3360 -#define wxStyledTextCtrl_SetLexerLanguage 3361 -#define wxStyledTextCtrl_GetProperty 3362 -#define wxStyledTextCtrl_GetStyleBitsNeeded 3363 -#define wxStyledTextCtrl_GetCurrentLine 3364 -#define wxStyledTextCtrl_StyleSetSpec 3365 -#define wxStyledTextCtrl_StyleSetFont 3366 -#define wxStyledTextCtrl_StyleSetFontAttr 3367 -#define wxStyledTextCtrl_StyleSetCharacterSet 3368 -#define wxStyledTextCtrl_StyleSetFontEncoding 3369 -#define wxStyledTextCtrl_CmdKeyExecute 3370 -#define wxStyledTextCtrl_SetMargins 3371 -#define wxStyledTextCtrl_GetSelection 3372 -#define wxStyledTextCtrl_PointFromPosition 3373 -#define wxStyledTextCtrl_ScrollToLine 3374 -#define wxStyledTextCtrl_ScrollToColumn 3375 -#define wxStyledTextCtrl_SetVScrollBar 3376 -#define wxStyledTextCtrl_SetHScrollBar 3377 -#define wxStyledTextCtrl_GetLastKeydownProcessed 3378 -#define wxStyledTextCtrl_SetLastKeydownProcessed 3379 -#define wxStyledTextCtrl_SaveFile 3380 -#define wxStyledTextCtrl_LoadFile 3381 -#define wxStyledTextCtrl_DoDragOver 3382 -#define wxStyledTextCtrl_DoDropText 3383 -#define wxStyledTextCtrl_GetUseAntiAliasing 3384 -#define wxStyledTextCtrl_AddTextRaw 3385 -#define wxStyledTextCtrl_InsertTextRaw 3386 -#define wxStyledTextCtrl_GetCurLineRaw 3387 -#define wxStyledTextCtrl_GetLineRaw 3388 -#define wxStyledTextCtrl_GetSelectedTextRaw 3389 -#define wxStyledTextCtrl_GetTextRangeRaw 3390 -#define wxStyledTextCtrl_SetTextRaw 3391 -#define wxStyledTextCtrl_GetTextRaw 3392 -#define wxStyledTextCtrl_AppendTextRaw 3393 -#define wxArtProvider_GetBitmap 3394 -#define wxArtProvider_GetIcon 3395 -#define wxTreeEvent_GetKeyCode 3396 -#define wxTreeEvent_GetItem 3397 -#define wxTreeEvent_GetKeyEvent 3398 -#define wxTreeEvent_GetLabel 3399 -#define wxTreeEvent_GetOldItem 3400 -#define wxTreeEvent_GetPoint 3401 -#define wxTreeEvent_IsEditCancelled 3402 -#define wxTreeEvent_SetToolTip 3403 -#define wxNotebookEvent_GetOldSelection 3404 -#define wxNotebookEvent_GetSelection 3405 -#define wxNotebookEvent_SetOldSelection 3406 -#define wxNotebookEvent_SetSelection 3407 -#define wxFileDataObject_new 3408 -#define wxFileDataObject_AddFile 3409 -#define wxFileDataObject_GetFilenames 3410 -#define wxFileDataObject_destroy 3411 -#define wxTextDataObject_new 3412 -#define wxTextDataObject_GetTextLength 3413 -#define wxTextDataObject_GetText 3414 -#define wxTextDataObject_SetText 3415 -#define wxTextDataObject_destroy 3416 -#define wxBitmapDataObject_new_1_1 3417 -#define wxBitmapDataObject_new_1_0 3418 -#define wxBitmapDataObject_GetBitmap 3419 -#define wxBitmapDataObject_SetBitmap 3420 -#define wxBitmapDataObject_destroy 3421 -#define wxClipboard_new 3423 -#define wxClipboard_destruct 3424 -#define wxClipboard_AddData 3425 -#define wxClipboard_Clear 3426 -#define wxClipboard_Close 3427 -#define wxClipboard_Flush 3428 -#define wxClipboard_GetData 3429 -#define wxClipboard_IsOpened 3430 -#define wxClipboard_Open 3431 -#define wxClipboard_SetData 3432 -#define wxClipboard_UsePrimarySelection 3434 -#define wxClipboard_IsSupported 3435 -#define wxClipboard_Get 3436 -#define wxSpinEvent_GetPosition 3437 -#define wxSpinEvent_SetPosition 3438 -#define wxSplitterWindow_new_0 3439 -#define wxSplitterWindow_new_2 3440 -#define wxSplitterWindow_destruct 3441 -#define wxSplitterWindow_Create 3442 -#define wxSplitterWindow_GetMinimumPaneSize 3443 -#define wxSplitterWindow_GetSashGravity 3444 -#define wxSplitterWindow_GetSashPosition 3445 -#define wxSplitterWindow_GetSplitMode 3446 -#define wxSplitterWindow_GetWindow1 3447 -#define wxSplitterWindow_GetWindow2 3448 -#define wxSplitterWindow_Initialize 3449 -#define wxSplitterWindow_IsSplit 3450 -#define wxSplitterWindow_ReplaceWindow 3451 -#define wxSplitterWindow_SetSashGravity 3452 -#define wxSplitterWindow_SetSashPosition 3453 -#define wxSplitterWindow_SetSashSize 3454 -#define wxSplitterWindow_SetMinimumPaneSize 3455 -#define wxSplitterWindow_SetSplitMode 3456 -#define wxSplitterWindow_SplitHorizontally 3457 -#define wxSplitterWindow_SplitVertically 3458 -#define wxSplitterWindow_Unsplit 3459 -#define wxSplitterWindow_UpdateSize 3460 -#define wxSplitterEvent_GetSashPosition 3461 -#define wxSplitterEvent_GetX 3462 -#define wxSplitterEvent_GetY 3463 -#define wxSplitterEvent_GetWindowBeingRemoved 3464 -#define wxSplitterEvent_SetSashPosition 3465 -#define wxHtmlWindow_new_0 3466 -#define wxHtmlWindow_new_2 3467 -#define wxHtmlWindow_AppendToPage 3468 -#define wxHtmlWindow_GetOpenedAnchor 3469 -#define wxHtmlWindow_GetOpenedPage 3470 -#define wxHtmlWindow_GetOpenedPageTitle 3471 -#define wxHtmlWindow_GetRelatedFrame 3472 -#define wxHtmlWindow_HistoryBack 3473 -#define wxHtmlWindow_HistoryCanBack 3474 -#define wxHtmlWindow_HistoryCanForward 3475 -#define wxHtmlWindow_HistoryClear 3476 -#define wxHtmlWindow_HistoryForward 3477 -#define wxHtmlWindow_LoadFile 3478 -#define wxHtmlWindow_LoadPage 3479 -#define wxHtmlWindow_SelectAll 3480 -#define wxHtmlWindow_SelectionToText 3481 -#define wxHtmlWindow_SelectLine 3482 -#define wxHtmlWindow_SelectWord 3483 -#define wxHtmlWindow_SetBorders 3484 -#define wxHtmlWindow_SetFonts 3485 -#define wxHtmlWindow_SetPage 3486 -#define wxHtmlWindow_SetRelatedFrame 3487 -#define wxHtmlWindow_SetRelatedStatusBar 3488 -#define wxHtmlWindow_ToText 3489 -#define wxHtmlWindow_destroy 3490 -#define wxHtmlLinkEvent_GetLinkInfo 3491 -#define wxSystemSettings_GetColour 3492 -#define wxSystemSettings_GetFont 3493 -#define wxSystemSettings_GetMetric 3494 -#define wxSystemSettings_GetScreenType 3495 -#define wxSystemOptions_GetOption 3496 -#define wxSystemOptions_GetOptionInt 3497 -#define wxSystemOptions_HasOption 3498 -#define wxSystemOptions_IsFalse 3499 -#define wxSystemOptions_SetOption_2_1 3500 -#define wxSystemOptions_SetOption_2_0 3501 -#define wxAuiNotebookEvent_SetSelection 3502 -#define wxAuiNotebookEvent_GetSelection 3503 -#define wxAuiNotebookEvent_SetOldSelection 3504 -#define wxAuiNotebookEvent_GetOldSelection 3505 -#define wxAuiNotebookEvent_SetDragSource 3506 -#define wxAuiNotebookEvent_GetDragSource 3507 -#define wxAuiManagerEvent_SetManager 3508 -#define wxAuiManagerEvent_GetManager 3509 -#define wxAuiManagerEvent_SetPane 3510 -#define wxAuiManagerEvent_GetPane 3511 -#define wxAuiManagerEvent_SetButton 3512 -#define wxAuiManagerEvent_GetButton 3513 -#define wxAuiManagerEvent_SetDC 3514 -#define wxAuiManagerEvent_GetDC 3515 -#define wxAuiManagerEvent_Veto 3516 -#define wxAuiManagerEvent_GetVeto 3517 -#define wxAuiManagerEvent_SetCanVeto 3518 -#define wxAuiManagerEvent_CanVeto 3519 -#define wxLogNull_new 3520 -#define wxLogNull_destroy 3521 -#define wxTaskBarIcon_new 3522 -#define wxTaskBarIcon_destruct 3523 -#define wxTaskBarIcon_PopupMenu 3524 -#define wxTaskBarIcon_RemoveIcon 3525 -#define wxTaskBarIcon_SetIcon 3526 -#define wxLocale_new_0 3527 -#define wxLocale_new_2 3529 -#define wxLocale_destruct 3530 -#define wxLocale_Init 3532 -#define wxLocale_AddCatalog_1 3533 -#define wxLocale_AddCatalog_3 3534 -#define wxLocale_AddCatalogLookupPathPrefix 3535 -#define wxLocale_GetCanonicalName 3536 -#define wxLocale_GetLanguage 3537 -#define wxLocale_GetLanguageName 3538 -#define wxLocale_GetLocale 3539 -#define wxLocale_GetName 3540 -#define wxLocale_GetString_2 3541 -#define wxLocale_GetString_4 3542 -#define wxLocale_GetHeaderValue 3543 -#define wxLocale_GetSysName 3544 -#define wxLocale_GetSystemEncoding 3545 -#define wxLocale_GetSystemEncodingName 3546 -#define wxLocale_GetSystemLanguage 3547 -#define wxLocale_IsLoaded 3548 -#define wxLocale_IsOk 3549 +#define wxTextCtrl_ChangeValue 1827 +#define wxTextCtrl_EmulateKeyPress 1828 +#define wxTextCtrl_GetDefaultStyle 1829 +#define wxTextCtrl_GetInsertionPoint 1830 +#define wxTextCtrl_GetLastPosition 1831 +#define wxTextCtrl_GetLineLength 1832 +#define wxTextCtrl_GetLineText 1833 +#define wxTextCtrl_GetNumberOfLines 1834 +#define wxTextCtrl_GetRange 1835 +#define wxTextCtrl_GetSelection 1836 +#define wxTextCtrl_GetStringSelection 1837 +#define wxTextCtrl_GetStyle 1838 +#define wxTextCtrl_GetValue 1839 +#define wxTextCtrl_IsEditable 1840 +#define wxTextCtrl_IsModified 1841 +#define wxTextCtrl_IsMultiLine 1842 +#define wxTextCtrl_IsSingleLine 1843 +#define wxTextCtrl_LoadFile 1844 +#define wxTextCtrl_MarkDirty 1845 +#define wxTextCtrl_Paste 1846 +#define wxTextCtrl_PositionToXY 1847 +#define wxTextCtrl_Redo 1848 +#define wxTextCtrl_Remove 1849 +#define wxTextCtrl_Replace 1850 +#define wxTextCtrl_SaveFile 1851 +#define wxTextCtrl_SetDefaultStyle 1852 +#define wxTextCtrl_SetEditable 1853 +#define wxTextCtrl_SetInsertionPoint 1854 +#define wxTextCtrl_SetInsertionPointEnd 1855 +#define wxTextCtrl_SetMaxLength 1857 +#define wxTextCtrl_SetSelection 1858 +#define wxTextCtrl_SetStyle 1859 +#define wxTextCtrl_SetValue 1860 +#define wxTextCtrl_ShowPosition 1861 +#define wxTextCtrl_Undo 1862 +#define wxTextCtrl_WriteText 1863 +#define wxTextCtrl_XYToPosition 1864 +#define wxNotebook_new_0 1867 +#define wxNotebook_new_3 1868 +#define wxNotebook_destruct 1869 +#define wxNotebook_AddPage 1870 +#define wxNotebook_AdvanceSelection 1871 +#define wxNotebook_AssignImageList 1872 +#define wxNotebook_Create 1873 +#define wxNotebook_DeleteAllPages 1874 +#define wxNotebook_DeletePage 1875 +#define wxNotebook_RemovePage 1876 +#define wxNotebook_GetCurrentPage 1877 +#define wxNotebook_GetImageList 1878 +#define wxNotebook_GetPage 1880 +#define wxNotebook_GetPageCount 1881 +#define wxNotebook_GetPageImage 1882 +#define wxNotebook_GetPageText 1883 +#define wxNotebook_GetRowCount 1884 +#define wxNotebook_GetSelection 1885 +#define wxNotebook_GetThemeBackgroundColour 1886 +#define wxNotebook_HitTest 1888 +#define wxNotebook_InsertPage 1890 +#define wxNotebook_SetImageList 1891 +#define wxNotebook_SetPadding 1892 +#define wxNotebook_SetPageSize 1893 +#define wxNotebook_SetPageImage 1894 +#define wxNotebook_SetPageText 1895 +#define wxNotebook_SetSelection 1896 +#define wxNotebook_ChangeSelection 1897 +#define wxChoicebook_new_0 1898 +#define wxChoicebook_new_3 1899 +#define wxChoicebook_AddPage 1900 +#define wxChoicebook_AdvanceSelection 1901 +#define wxChoicebook_AssignImageList 1902 +#define wxChoicebook_Create 1903 +#define wxChoicebook_DeleteAllPages 1904 +#define wxChoicebook_DeletePage 1905 +#define wxChoicebook_RemovePage 1906 +#define wxChoicebook_GetCurrentPage 1907 +#define wxChoicebook_GetImageList 1908 +#define wxChoicebook_GetPage 1910 +#define wxChoicebook_GetPageCount 1911 +#define wxChoicebook_GetPageImage 1912 +#define wxChoicebook_GetPageText 1913 +#define wxChoicebook_GetSelection 1914 +#define wxChoicebook_HitTest 1915 +#define wxChoicebook_InsertPage 1916 +#define wxChoicebook_SetImageList 1917 +#define wxChoicebook_SetPageSize 1918 +#define wxChoicebook_SetPageImage 1919 +#define wxChoicebook_SetPageText 1920 +#define wxChoicebook_SetSelection 1921 +#define wxChoicebook_ChangeSelection 1922 +#define wxChoicebook_destroy 1923 +#define wxToolbook_new_0 1924 +#define wxToolbook_new_3 1925 +#define wxToolbook_AddPage 1926 +#define wxToolbook_AdvanceSelection 1927 +#define wxToolbook_AssignImageList 1928 +#define wxToolbook_Create 1929 +#define wxToolbook_DeleteAllPages 1930 +#define wxToolbook_DeletePage 1931 +#define wxToolbook_RemovePage 1932 +#define wxToolbook_GetCurrentPage 1933 +#define wxToolbook_GetImageList 1934 +#define wxToolbook_GetPage 1936 +#define wxToolbook_GetPageCount 1937 +#define wxToolbook_GetPageImage 1938 +#define wxToolbook_GetPageText 1939 +#define wxToolbook_GetSelection 1940 +#define wxToolbook_HitTest 1942 +#define wxToolbook_InsertPage 1943 +#define wxToolbook_SetImageList 1944 +#define wxToolbook_SetPageSize 1945 +#define wxToolbook_SetPageImage 1946 +#define wxToolbook_SetPageText 1947 +#define wxToolbook_SetSelection 1948 +#define wxToolbook_ChangeSelection 1949 +#define wxToolbook_destroy 1950 +#define wxListbook_new_0 1951 +#define wxListbook_new_3 1952 +#define wxListbook_AddPage 1953 +#define wxListbook_AdvanceSelection 1954 +#define wxListbook_AssignImageList 1955 +#define wxListbook_Create 1956 +#define wxListbook_DeleteAllPages 1957 +#define wxListbook_DeletePage 1958 +#define wxListbook_RemovePage 1959 +#define wxListbook_GetCurrentPage 1960 +#define wxListbook_GetImageList 1961 +#define wxListbook_GetPage 1963 +#define wxListbook_GetPageCount 1964 +#define wxListbook_GetPageImage 1965 +#define wxListbook_GetPageText 1966 +#define wxListbook_GetSelection 1967 +#define wxListbook_HitTest 1969 +#define wxListbook_InsertPage 1970 +#define wxListbook_SetImageList 1971 +#define wxListbook_SetPageSize 1972 +#define wxListbook_SetPageImage 1973 +#define wxListbook_SetPageText 1974 +#define wxListbook_SetSelection 1975 +#define wxListbook_ChangeSelection 1976 +#define wxListbook_destroy 1977 +#define wxTreebook_new_0 1978 +#define wxTreebook_new_3 1979 +#define wxTreebook_AddPage 1980 +#define wxTreebook_AdvanceSelection 1981 +#define wxTreebook_AssignImageList 1982 +#define wxTreebook_Create 1983 +#define wxTreebook_DeleteAllPages 1984 +#define wxTreebook_DeletePage 1985 +#define wxTreebook_RemovePage 1986 +#define wxTreebook_GetCurrentPage 1987 +#define wxTreebook_GetImageList 1988 +#define wxTreebook_GetPage 1990 +#define wxTreebook_GetPageCount 1991 +#define wxTreebook_GetPageImage 1992 +#define wxTreebook_GetPageText 1993 +#define wxTreebook_GetSelection 1994 +#define wxTreebook_ExpandNode 1995 +#define wxTreebook_IsNodeExpanded 1996 +#define wxTreebook_HitTest 1998 +#define wxTreebook_InsertPage 1999 +#define wxTreebook_InsertSubPage 2000 +#define wxTreebook_SetImageList 2001 +#define wxTreebook_SetPageSize 2002 +#define wxTreebook_SetPageImage 2003 +#define wxTreebook_SetPageText 2004 +#define wxTreebook_SetSelection 2005 +#define wxTreebook_ChangeSelection 2006 +#define wxTreebook_destroy 2007 +#define wxTreeCtrl_new_2 2010 +#define wxTreeCtrl_new_0 2011 +#define wxTreeCtrl_destruct 2013 +#define wxTreeCtrl_AddRoot 2014 +#define wxTreeCtrl_AppendItem 2015 +#define wxTreeCtrl_AssignImageList 2016 +#define wxTreeCtrl_AssignStateImageList 2017 +#define wxTreeCtrl_Collapse 2018 +#define wxTreeCtrl_CollapseAndReset 2019 +#define wxTreeCtrl_Create 2020 +#define wxTreeCtrl_Delete 2021 +#define wxTreeCtrl_DeleteAllItems 2022 +#define wxTreeCtrl_DeleteChildren 2023 +#define wxTreeCtrl_EditLabel 2024 +#define wxTreeCtrl_EnsureVisible 2025 +#define wxTreeCtrl_Expand 2026 +#define wxTreeCtrl_GetBoundingRect 2027 +#define wxTreeCtrl_GetChildrenCount 2029 +#define wxTreeCtrl_GetCount 2030 +#define wxTreeCtrl_GetEditControl 2031 +#define wxTreeCtrl_GetFirstChild 2032 +#define wxTreeCtrl_GetNextChild 2033 +#define wxTreeCtrl_GetFirstVisibleItem 2034 +#define wxTreeCtrl_GetImageList 2035 +#define wxTreeCtrl_GetIndent 2036 +#define wxTreeCtrl_GetItemBackgroundColour 2037 +#define wxTreeCtrl_GetItemData 2038 +#define wxTreeCtrl_GetItemFont 2039 +#define wxTreeCtrl_GetItemImage_1 2040 +#define wxTreeCtrl_GetItemImage_2 2041 +#define wxTreeCtrl_GetItemText 2042 +#define wxTreeCtrl_GetItemTextColour 2043 +#define wxTreeCtrl_GetLastChild 2044 +#define wxTreeCtrl_GetNextSibling 2045 +#define wxTreeCtrl_GetNextVisible 2046 +#define wxTreeCtrl_GetItemParent 2047 +#define wxTreeCtrl_GetPrevSibling 2048 +#define wxTreeCtrl_GetPrevVisible 2049 +#define wxTreeCtrl_GetRootItem 2050 +#define wxTreeCtrl_GetSelection 2051 +#define wxTreeCtrl_GetSelections 2052 +#define wxTreeCtrl_GetStateImageList 2053 +#define wxTreeCtrl_HitTest 2054 +#define wxTreeCtrl_InsertItem 2056 +#define wxTreeCtrl_IsBold 2057 +#define wxTreeCtrl_IsExpanded 2058 +#define wxTreeCtrl_IsSelected 2059 +#define wxTreeCtrl_IsVisible 2060 +#define wxTreeCtrl_ItemHasChildren 2061 +#define wxTreeCtrl_IsTreeItemIdOk 2062 +#define wxTreeCtrl_PrependItem 2063 +#define wxTreeCtrl_ScrollTo 2064 +#define wxTreeCtrl_SelectItem_1 2065 +#define wxTreeCtrl_SelectItem_2 2066 +#define wxTreeCtrl_SetIndent 2067 +#define wxTreeCtrl_SetImageList 2068 +#define wxTreeCtrl_SetItemBackgroundColour 2069 +#define wxTreeCtrl_SetItemBold 2070 +#define wxTreeCtrl_SetItemData 2071 +#define wxTreeCtrl_SetItemDropHighlight 2072 +#define wxTreeCtrl_SetItemFont 2073 +#define wxTreeCtrl_SetItemHasChildren 2074 +#define wxTreeCtrl_SetItemImage_2 2075 +#define wxTreeCtrl_SetItemImage_3 2076 +#define wxTreeCtrl_SetItemText 2077 +#define wxTreeCtrl_SetItemTextColour 2078 +#define wxTreeCtrl_SetStateImageList 2079 +#define wxTreeCtrl_SetWindowStyle 2080 +#define wxTreeCtrl_SortChildren 2081 +#define wxTreeCtrl_Toggle 2082 +#define wxTreeCtrl_ToggleItemSelection 2083 +#define wxTreeCtrl_Unselect 2084 +#define wxTreeCtrl_UnselectAll 2085 +#define wxTreeCtrl_UnselectItem 2086 +#define wxScrollBar_new_0 2087 +#define wxScrollBar_new_3 2088 +#define wxScrollBar_destruct 2089 +#define wxScrollBar_Create 2090 +#define wxScrollBar_GetRange 2091 +#define wxScrollBar_GetPageSize 2092 +#define wxScrollBar_GetThumbPosition 2093 +#define wxScrollBar_GetThumbSize 2094 +#define wxScrollBar_SetThumbPosition 2095 +#define wxScrollBar_SetScrollbar 2096 +#define wxSpinButton_new_2 2098 +#define wxSpinButton_new_0 2099 +#define wxSpinButton_Create 2100 +#define wxSpinButton_GetMax 2101 +#define wxSpinButton_GetMin 2102 +#define wxSpinButton_GetValue 2103 +#define wxSpinButton_SetRange 2104 +#define wxSpinButton_SetValue 2105 +#define wxSpinButton_destroy 2106 +#define wxSpinCtrl_new_0 2107 +#define wxSpinCtrl_new_2 2108 +#define wxSpinCtrl_Create 2110 +#define wxSpinCtrl_SetValue_1_1 2113 +#define wxSpinCtrl_SetValue_1_0 2114 +#define wxSpinCtrl_GetValue 2116 +#define wxSpinCtrl_SetRange 2118 +#define wxSpinCtrl_SetSelection 2119 +#define wxSpinCtrl_GetMin 2121 +#define wxSpinCtrl_GetMax 2123 +#define wxSpinCtrl_destroy 2124 +#define wxStaticText_new_0 2125 +#define wxStaticText_new_4 2126 +#define wxStaticText_Create 2127 +#define wxStaticText_GetLabel 2128 +#define wxStaticText_SetLabel 2129 +#define wxStaticText_Wrap 2130 +#define wxStaticText_destroy 2131 +#define wxStaticBitmap_new_0 2132 +#define wxStaticBitmap_new_4 2133 +#define wxStaticBitmap_Create 2134 +#define wxStaticBitmap_GetBitmap 2135 +#define wxStaticBitmap_SetBitmap 2136 +#define wxStaticBitmap_destroy 2137 +#define wxRadioBox_new 2138 +#define wxRadioBox_destruct 2140 +#define wxRadioBox_Create 2141 +#define wxRadioBox_Enable_2 2142 +#define wxRadioBox_Enable_1 2143 +#define wxRadioBox_GetSelection 2144 +#define wxRadioBox_GetString 2145 +#define wxRadioBox_SetSelection 2146 +#define wxRadioBox_Show_2 2147 +#define wxRadioBox_Show_1 2148 +#define wxRadioBox_GetColumnCount 2149 +#define wxRadioBox_GetItemHelpText 2150 +#define wxRadioBox_GetItemToolTip 2151 +#define wxRadioBox_GetItemFromPoint 2153 +#define wxRadioBox_GetRowCount 2154 +#define wxRadioBox_IsItemEnabled 2155 +#define wxRadioBox_IsItemShown 2156 +#define wxRadioBox_SetItemHelpText 2157 +#define wxRadioBox_SetItemToolTip 2158 +#define wxRadioButton_new_0 2159 +#define wxRadioButton_new_4 2160 +#define wxRadioButton_Create 2161 +#define wxRadioButton_GetValue 2162 +#define wxRadioButton_SetValue 2163 +#define wxRadioButton_destroy 2164 +#define wxSlider_new_6 2166 +#define wxSlider_new_0 2167 +#define wxSlider_Create 2168 +#define wxSlider_GetLineSize 2169 +#define wxSlider_GetMax 2170 +#define wxSlider_GetMin 2171 +#define wxSlider_GetPageSize 2172 +#define wxSlider_GetThumbLength 2173 +#define wxSlider_GetValue 2174 +#define wxSlider_SetLineSize 2175 +#define wxSlider_SetPageSize 2176 +#define wxSlider_SetRange 2177 +#define wxSlider_SetThumbLength 2178 +#define wxSlider_SetValue 2179 +#define wxSlider_destroy 2180 +#define wxDialog_new_4 2182 +#define wxDialog_new_0 2183 +#define wxDialog_destruct 2185 +#define wxDialog_Create 2186 +#define wxDialog_CreateButtonSizer 2187 +#define wxDialog_CreateStdDialogButtonSizer 2188 +#define wxDialog_EndModal 2189 +#define wxDialog_GetAffirmativeId 2190 +#define wxDialog_GetReturnCode 2191 +#define wxDialog_IsModal 2192 +#define wxDialog_SetAffirmativeId 2193 +#define wxDialog_SetReturnCode 2194 +#define wxDialog_Show 2195 +#define wxDialog_ShowModal 2196 +#define wxColourDialog_new_0 2197 +#define wxColourDialog_new_2 2198 +#define wxColourDialog_destruct 2199 +#define wxColourDialog_Create 2200 +#define wxColourDialog_GetColourData 2201 +#define wxColourData_new_0 2202 +#define wxColourData_new_1 2203 +#define wxColourData_destruct 2204 +#define wxColourData_GetChooseFull 2205 +#define wxColourData_GetColour 2206 +#define wxColourData_GetCustomColour 2208 +#define wxColourData_SetChooseFull 2209 +#define wxColourData_SetColour 2210 +#define wxColourData_SetCustomColour 2211 +#define wxPalette_new_0 2212 +#define wxPalette_new_4 2213 +#define wxPalette_destruct 2215 +#define wxPalette_Create 2216 +#define wxPalette_GetColoursCount 2217 +#define wxPalette_GetPixel 2218 +#define wxPalette_GetRGB 2219 +#define wxPalette_IsOk 2220 +#define wxDirDialog_new 2224 +#define wxDirDialog_destruct 2225 +#define wxDirDialog_GetPath 2226 +#define wxDirDialog_GetMessage 2227 +#define wxDirDialog_SetMessage 2228 +#define wxDirDialog_SetPath 2229 +#define wxFileDialog_new 2233 +#define wxFileDialog_destruct 2234 +#define wxFileDialog_GetDirectory 2235 +#define wxFileDialog_GetFilename 2236 +#define wxFileDialog_GetFilenames 2237 +#define wxFileDialog_GetFilterIndex 2238 +#define wxFileDialog_GetMessage 2239 +#define wxFileDialog_GetPath 2240 +#define wxFileDialog_GetPaths 2241 +#define wxFileDialog_GetWildcard 2242 +#define wxFileDialog_SetDirectory 2243 +#define wxFileDialog_SetFilename 2244 +#define wxFileDialog_SetFilterIndex 2245 +#define wxFileDialog_SetMessage 2246 +#define wxFileDialog_SetPath 2247 +#define wxFileDialog_SetWildcard 2248 +#define wxPickerBase_SetInternalMargin 2249 +#define wxPickerBase_GetInternalMargin 2250 +#define wxPickerBase_SetTextCtrlProportion 2251 +#define wxPickerBase_SetPickerCtrlProportion 2252 +#define wxPickerBase_GetTextCtrlProportion 2253 +#define wxPickerBase_GetPickerCtrlProportion 2254 +#define wxPickerBase_HasTextCtrl 2255 +#define wxPickerBase_GetTextCtrl 2256 +#define wxPickerBase_IsTextCtrlGrowable 2257 +#define wxPickerBase_SetPickerCtrlGrowable 2258 +#define wxPickerBase_SetTextCtrlGrowable 2259 +#define wxPickerBase_IsPickerCtrlGrowable 2260 +#define wxFilePickerCtrl_new_0 2261 +#define wxFilePickerCtrl_new_3 2262 +#define wxFilePickerCtrl_Create 2263 +#define wxFilePickerCtrl_GetPath 2264 +#define wxFilePickerCtrl_SetPath 2265 +#define wxFilePickerCtrl_destroy 2266 +#define wxDirPickerCtrl_new_0 2267 +#define wxDirPickerCtrl_new_3 2268 +#define wxDirPickerCtrl_Create 2269 +#define wxDirPickerCtrl_GetPath 2270 +#define wxDirPickerCtrl_SetPath 2271 +#define wxDirPickerCtrl_destroy 2272 +#define wxColourPickerCtrl_new_0 2273 +#define wxColourPickerCtrl_new_3 2274 +#define wxColourPickerCtrl_Create 2275 +#define wxColourPickerCtrl_GetColour 2276 +#define wxColourPickerCtrl_SetColour_1_1 2277 +#define wxColourPickerCtrl_SetColour_1_0 2278 +#define wxColourPickerCtrl_destroy 2279 +#define wxDatePickerCtrl_new_0 2280 +#define wxDatePickerCtrl_new_3 2281 +#define wxDatePickerCtrl_GetRange 2282 +#define wxDatePickerCtrl_GetValue 2283 +#define wxDatePickerCtrl_SetRange 2284 +#define wxDatePickerCtrl_SetValue 2285 +#define wxDatePickerCtrl_destroy 2286 +#define wxFontPickerCtrl_new_0 2287 +#define wxFontPickerCtrl_new_3 2288 +#define wxFontPickerCtrl_Create 2289 +#define wxFontPickerCtrl_GetSelectedFont 2290 +#define wxFontPickerCtrl_SetSelectedFont 2291 +#define wxFontPickerCtrl_GetMaxPointSize 2292 +#define wxFontPickerCtrl_SetMaxPointSize 2293 +#define wxFontPickerCtrl_destroy 2294 +#define wxFindReplaceDialog_new_0 2297 +#define wxFindReplaceDialog_new_4 2298 +#define wxFindReplaceDialog_destruct 2299 +#define wxFindReplaceDialog_Create 2300 +#define wxFindReplaceDialog_GetData 2301 +#define wxFindReplaceData_new_0 2302 +#define wxFindReplaceData_new_1 2303 +#define wxFindReplaceData_GetFindString 2304 +#define wxFindReplaceData_GetReplaceString 2305 +#define wxFindReplaceData_GetFlags 2306 +#define wxFindReplaceData_SetFlags 2307 +#define wxFindReplaceData_SetFindString 2308 +#define wxFindReplaceData_SetReplaceString 2309 +#define wxFindReplaceData_destroy 2310 +#define wxMultiChoiceDialog_new_0 2311 +#define wxMultiChoiceDialog_new_5 2313 +#define wxMultiChoiceDialog_GetSelections 2314 +#define wxMultiChoiceDialog_SetSelections 2315 +#define wxMultiChoiceDialog_destroy 2316 +#define wxSingleChoiceDialog_new_0 2317 +#define wxSingleChoiceDialog_new_5 2319 +#define wxSingleChoiceDialog_GetSelection 2320 +#define wxSingleChoiceDialog_GetStringSelection 2321 +#define wxSingleChoiceDialog_SetSelection 2322 +#define wxSingleChoiceDialog_destroy 2323 +#define wxTextEntryDialog_new 2324 +#define wxTextEntryDialog_GetValue 2325 +#define wxTextEntryDialog_SetValue 2326 +#define wxTextEntryDialog_destroy 2327 +#define wxPasswordEntryDialog_new 2328 +#define wxPasswordEntryDialog_destroy 2329 +#define wxFontData_new_0 2330 +#define wxFontData_new_1 2331 +#define wxFontData_destruct 2332 +#define wxFontData_EnableEffects 2333 +#define wxFontData_GetAllowSymbols 2334 +#define wxFontData_GetColour 2335 +#define wxFontData_GetChosenFont 2336 +#define wxFontData_GetEnableEffects 2337 +#define wxFontData_GetInitialFont 2338 +#define wxFontData_GetShowHelp 2339 +#define wxFontData_SetAllowSymbols 2340 +#define wxFontData_SetChosenFont 2341 +#define wxFontData_SetColour 2342 +#define wxFontData_SetInitialFont 2343 +#define wxFontData_SetRange 2344 +#define wxFontData_SetShowHelp 2345 +#define wxFontDialog_new_0 2349 +#define wxFontDialog_new_2 2351 +#define wxFontDialog_Create 2353 +#define wxFontDialog_GetFontData 2354 +#define wxFontDialog_destroy 2356 +#define wxProgressDialog_new 2357 +#define wxProgressDialog_destruct 2358 +#define wxProgressDialog_Resume 2359 +#define wxProgressDialog_Update_2 2360 +#define wxProgressDialog_Update_0 2361 +#define wxMessageDialog_new 2362 +#define wxMessageDialog_destruct 2363 +#define wxPageSetupDialog_new 2364 +#define wxPageSetupDialog_destruct 2365 +#define wxPageSetupDialog_GetPageSetupData 2366 +#define wxPageSetupDialog_ShowModal 2367 +#define wxPageSetupDialogData_new_0 2368 +#define wxPageSetupDialogData_new_1_0 2369 +#define wxPageSetupDialogData_new_1_1 2370 +#define wxPageSetupDialogData_destruct 2371 +#define wxPageSetupDialogData_EnableHelp 2372 +#define wxPageSetupDialogData_EnableMargins 2373 +#define wxPageSetupDialogData_EnableOrientation 2374 +#define wxPageSetupDialogData_EnablePaper 2375 +#define wxPageSetupDialogData_EnablePrinter 2376 +#define wxPageSetupDialogData_GetDefaultMinMargins 2377 +#define wxPageSetupDialogData_GetEnableMargins 2378 +#define wxPageSetupDialogData_GetEnableOrientation 2379 +#define wxPageSetupDialogData_GetEnablePaper 2380 +#define wxPageSetupDialogData_GetEnablePrinter 2381 +#define wxPageSetupDialogData_GetEnableHelp 2382 +#define wxPageSetupDialogData_GetDefaultInfo 2383 +#define wxPageSetupDialogData_GetMarginTopLeft 2384 +#define wxPageSetupDialogData_GetMarginBottomRight 2385 +#define wxPageSetupDialogData_GetMinMarginTopLeft 2386 +#define wxPageSetupDialogData_GetMinMarginBottomRight 2387 +#define wxPageSetupDialogData_GetPaperId 2388 +#define wxPageSetupDialogData_GetPaperSize 2389 +#define wxPageSetupDialogData_GetPrintData 2391 +#define wxPageSetupDialogData_IsOk 2392 +#define wxPageSetupDialogData_SetDefaultInfo 2393 +#define wxPageSetupDialogData_SetDefaultMinMargins 2394 +#define wxPageSetupDialogData_SetMarginTopLeft 2395 +#define wxPageSetupDialogData_SetMarginBottomRight 2396 +#define wxPageSetupDialogData_SetMinMarginTopLeft 2397 +#define wxPageSetupDialogData_SetMinMarginBottomRight 2398 +#define wxPageSetupDialogData_SetPaperId 2399 +#define wxPageSetupDialogData_SetPaperSize_1_1 2400 +#define wxPageSetupDialogData_SetPaperSize_1_0 2401 +#define wxPageSetupDialogData_SetPrintData 2402 +#define wxPrintDialog_new_2_0 2403 +#define wxPrintDialog_new_2_1 2404 +#define wxPrintDialog_destruct 2405 +#define wxPrintDialog_GetPrintDialogData 2406 +#define wxPrintDialog_GetPrintDC 2407 +#define wxPrintDialogData_new_0 2408 +#define wxPrintDialogData_new_1_1 2409 +#define wxPrintDialogData_new_1_0 2410 +#define wxPrintDialogData_destruct 2411 +#define wxPrintDialogData_EnableHelp 2412 +#define wxPrintDialogData_EnablePageNumbers 2413 +#define wxPrintDialogData_EnablePrintToFile 2414 +#define wxPrintDialogData_EnableSelection 2415 +#define wxPrintDialogData_GetAllPages 2416 +#define wxPrintDialogData_GetCollate 2417 +#define wxPrintDialogData_GetFromPage 2418 +#define wxPrintDialogData_GetMaxPage 2419 +#define wxPrintDialogData_GetMinPage 2420 +#define wxPrintDialogData_GetNoCopies 2421 +#define wxPrintDialogData_GetPrintData 2422 +#define wxPrintDialogData_GetPrintToFile 2423 +#define wxPrintDialogData_GetSelection 2424 +#define wxPrintDialogData_GetToPage 2425 +#define wxPrintDialogData_IsOk 2426 +#define wxPrintDialogData_SetCollate 2427 +#define wxPrintDialogData_SetFromPage 2428 +#define wxPrintDialogData_SetMaxPage 2429 +#define wxPrintDialogData_SetMinPage 2430 +#define wxPrintDialogData_SetNoCopies 2431 +#define wxPrintDialogData_SetPrintData 2432 +#define wxPrintDialogData_SetPrintToFile 2433 +#define wxPrintDialogData_SetSelection 2434 +#define wxPrintDialogData_SetToPage 2435 +#define wxPrintData_new_0 2436 +#define wxPrintData_new_1 2437 +#define wxPrintData_destruct 2438 +#define wxPrintData_GetCollate 2439 +#define wxPrintData_GetBin 2440 +#define wxPrintData_GetColour 2441 +#define wxPrintData_GetDuplex 2442 +#define wxPrintData_GetNoCopies 2443 +#define wxPrintData_GetOrientation 2444 +#define wxPrintData_GetPaperId 2445 +#define wxPrintData_GetPrinterName 2446 +#define wxPrintData_GetQuality 2447 +#define wxPrintData_IsOk 2448 +#define wxPrintData_SetBin 2449 +#define wxPrintData_SetCollate 2450 +#define wxPrintData_SetColour 2451 +#define wxPrintData_SetDuplex 2452 +#define wxPrintData_SetNoCopies 2453 +#define wxPrintData_SetOrientation 2454 +#define wxPrintData_SetPaperId 2455 +#define wxPrintData_SetPrinterName 2456 +#define wxPrintData_SetQuality 2457 +#define wxPrintPreview_new_2 2460 +#define wxPrintPreview_new_3 2461 +#define wxPrintPreview_destruct 2463 +#define wxPrintPreview_GetCanvas 2464 +#define wxPrintPreview_GetCurrentPage 2465 +#define wxPrintPreview_GetFrame 2466 +#define wxPrintPreview_GetMaxPage 2467 +#define wxPrintPreview_GetMinPage 2468 +#define wxPrintPreview_GetPrintout 2469 +#define wxPrintPreview_GetPrintoutForPrinting 2470 +#define wxPrintPreview_IsOk 2471 +#define wxPrintPreview_PaintPage 2472 +#define wxPrintPreview_Print 2473 +#define wxPrintPreview_RenderPage 2474 +#define wxPrintPreview_SetCanvas 2475 +#define wxPrintPreview_SetCurrentPage 2476 +#define wxPrintPreview_SetFrame 2477 +#define wxPrintPreview_SetPrintout 2478 +#define wxPrintPreview_SetZoom 2479 +#define wxPreviewFrame_new 2480 +#define wxPreviewFrame_destruct 2481 +#define wxPreviewFrame_CreateControlBar 2482 +#define wxPreviewFrame_CreateCanvas 2483 +#define wxPreviewFrame_Initialize 2484 +#define wxPreviewFrame_OnCloseWindow 2485 +#define wxPreviewControlBar_new 2486 +#define wxPreviewControlBar_destruct 2487 +#define wxPreviewControlBar_CreateButtons 2488 +#define wxPreviewControlBar_GetPrintPreview 2489 +#define wxPreviewControlBar_GetZoomControl 2490 +#define wxPreviewControlBar_SetZoomControl 2491 +#define wxPrinter_new 2493 +#define wxPrinter_CreateAbortWindow 2494 +#define wxPrinter_GetAbort 2495 +#define wxPrinter_GetLastError 2496 +#define wxPrinter_GetPrintDialogData 2497 +#define wxPrinter_Print 2498 +#define wxPrinter_PrintDialog 2499 +#define wxPrinter_ReportError 2500 +#define wxPrinter_Setup 2501 +#define wxPrinter_destroy 2502 +#define wxXmlResource_new_1 2503 +#define wxXmlResource_new_2 2504 +#define wxXmlResource_destruct 2505 +#define wxXmlResource_AttachUnknownControl 2506 +#define wxXmlResource_ClearHandlers 2507 +#define wxXmlResource_CompareVersion 2508 +#define wxXmlResource_Get 2509 +#define wxXmlResource_GetFlags 2510 +#define wxXmlResource_GetVersion 2511 +#define wxXmlResource_GetXRCID 2512 +#define wxXmlResource_InitAllHandlers 2513 +#define wxXmlResource_Load 2514 +#define wxXmlResource_LoadBitmap 2515 +#define wxXmlResource_LoadDialog_2 2516 +#define wxXmlResource_LoadDialog_3 2517 +#define wxXmlResource_LoadFrame_2 2518 +#define wxXmlResource_LoadFrame_3 2519 +#define wxXmlResource_LoadIcon 2520 +#define wxXmlResource_LoadMenu 2521 +#define wxXmlResource_LoadMenuBar_2 2522 +#define wxXmlResource_LoadMenuBar_1 2523 +#define wxXmlResource_LoadPanel_2 2524 +#define wxXmlResource_LoadPanel_3 2525 +#define wxXmlResource_LoadToolBar 2526 +#define wxXmlResource_Set 2527 +#define wxXmlResource_SetFlags 2528 +#define wxXmlResource_Unload 2529 +#define wxXmlResource_xrcctrl 2530 +#define wxHtmlEasyPrinting_new 2531 +#define wxHtmlEasyPrinting_destruct 2532 +#define wxHtmlEasyPrinting_GetPrintData 2533 +#define wxHtmlEasyPrinting_GetPageSetupData 2534 +#define wxHtmlEasyPrinting_PreviewFile 2535 +#define wxHtmlEasyPrinting_PreviewText 2536 +#define wxHtmlEasyPrinting_PrintFile 2537 +#define wxHtmlEasyPrinting_PrintText 2538 +#define wxHtmlEasyPrinting_PageSetup 2539 +#define wxHtmlEasyPrinting_SetFonts 2540 +#define wxHtmlEasyPrinting_SetHeader 2541 +#define wxHtmlEasyPrinting_SetFooter 2542 +#define wxGLCanvas_new_2 2544 +#define wxGLCanvas_new_3_1 2545 +#define wxGLCanvas_new_3_0 2546 +#define wxGLCanvas_GetContext 2547 +#define wxGLCanvas_SetCurrent 2549 +#define wxGLCanvas_SwapBuffers 2550 +#define wxGLCanvas_destroy 2551 +#define wxAuiManager_new 2552 +#define wxAuiManager_destruct 2553 +#define wxAuiManager_AddPane_2_1 2554 +#define wxAuiManager_AddPane_3 2555 +#define wxAuiManager_AddPane_2_0 2556 +#define wxAuiManager_DetachPane 2557 +#define wxAuiManager_GetAllPanes 2558 +#define wxAuiManager_GetArtProvider 2559 +#define wxAuiManager_GetDockSizeConstraint 2560 +#define wxAuiManager_GetFlags 2561 +#define wxAuiManager_GetManagedWindow 2562 +#define wxAuiManager_GetManager 2563 +#define wxAuiManager_GetPane_1_1 2564 +#define wxAuiManager_GetPane_1_0 2565 +#define wxAuiManager_HideHint 2566 +#define wxAuiManager_InsertPane 2567 +#define wxAuiManager_LoadPaneInfo 2568 +#define wxAuiManager_LoadPerspective 2569 +#define wxAuiManager_SavePaneInfo 2570 +#define wxAuiManager_SavePerspective 2571 +#define wxAuiManager_SetArtProvider 2572 +#define wxAuiManager_SetDockSizeConstraint 2573 +#define wxAuiManager_SetFlags 2574 +#define wxAuiManager_SetManagedWindow 2575 +#define wxAuiManager_ShowHint 2576 +#define wxAuiManager_UnInit 2577 +#define wxAuiManager_Update 2578 +#define wxAuiPaneInfo_new_0 2579 +#define wxAuiPaneInfo_new_1 2580 +#define wxAuiPaneInfo_destruct 2581 +#define wxAuiPaneInfo_BestSize_1 2582 +#define wxAuiPaneInfo_BestSize_2 2583 +#define wxAuiPaneInfo_Bottom 2584 +#define wxAuiPaneInfo_BottomDockable 2585 +#define wxAuiPaneInfo_Caption 2586 +#define wxAuiPaneInfo_CaptionVisible 2587 +#define wxAuiPaneInfo_Centre 2588 +#define wxAuiPaneInfo_CentrePane 2589 +#define wxAuiPaneInfo_CloseButton 2590 +#define wxAuiPaneInfo_DefaultPane 2591 +#define wxAuiPaneInfo_DestroyOnClose 2592 +#define wxAuiPaneInfo_Direction 2593 +#define wxAuiPaneInfo_Dock 2594 +#define wxAuiPaneInfo_Dockable 2595 +#define wxAuiPaneInfo_Fixed 2596 +#define wxAuiPaneInfo_Float 2597 +#define wxAuiPaneInfo_Floatable 2598 +#define wxAuiPaneInfo_FloatingPosition_1 2599 +#define wxAuiPaneInfo_FloatingPosition_2 2600 +#define wxAuiPaneInfo_FloatingSize_1 2601 +#define wxAuiPaneInfo_FloatingSize_2 2602 +#define wxAuiPaneInfo_Gripper 2603 +#define wxAuiPaneInfo_GripperTop 2604 +#define wxAuiPaneInfo_HasBorder 2605 +#define wxAuiPaneInfo_HasCaption 2606 +#define wxAuiPaneInfo_HasCloseButton 2607 +#define wxAuiPaneInfo_HasFlag 2608 +#define wxAuiPaneInfo_HasGripper 2609 +#define wxAuiPaneInfo_HasGripperTop 2610 +#define wxAuiPaneInfo_HasMaximizeButton 2611 +#define wxAuiPaneInfo_HasMinimizeButton 2612 +#define wxAuiPaneInfo_HasPinButton 2613 +#define wxAuiPaneInfo_Hide 2614 +#define wxAuiPaneInfo_IsBottomDockable 2615 +#define wxAuiPaneInfo_IsDocked 2616 +#define wxAuiPaneInfo_IsFixed 2617 +#define wxAuiPaneInfo_IsFloatable 2618 +#define wxAuiPaneInfo_IsFloating 2619 +#define wxAuiPaneInfo_IsLeftDockable 2620 +#define wxAuiPaneInfo_IsMovable 2621 +#define wxAuiPaneInfo_IsOk 2622 +#define wxAuiPaneInfo_IsResizable 2623 +#define wxAuiPaneInfo_IsRightDockable 2624 +#define wxAuiPaneInfo_IsShown 2625 +#define wxAuiPaneInfo_IsToolbar 2626 +#define wxAuiPaneInfo_IsTopDockable 2627 +#define wxAuiPaneInfo_Layer 2628 +#define wxAuiPaneInfo_Left 2629 +#define wxAuiPaneInfo_LeftDockable 2630 +#define wxAuiPaneInfo_MaxSize_1 2631 +#define wxAuiPaneInfo_MaxSize_2 2632 +#define wxAuiPaneInfo_MaximizeButton 2633 +#define wxAuiPaneInfo_MinSize_1 2634 +#define wxAuiPaneInfo_MinSize_2 2635 +#define wxAuiPaneInfo_MinimizeButton 2636 +#define wxAuiPaneInfo_Movable 2637 +#define wxAuiPaneInfo_Name 2638 +#define wxAuiPaneInfo_PaneBorder 2639 +#define wxAuiPaneInfo_PinButton 2640 +#define wxAuiPaneInfo_Position 2641 +#define wxAuiPaneInfo_Resizable 2642 +#define wxAuiPaneInfo_Right 2643 +#define wxAuiPaneInfo_RightDockable 2644 +#define wxAuiPaneInfo_Row 2645 +#define wxAuiPaneInfo_SafeSet 2646 +#define wxAuiPaneInfo_SetFlag 2647 +#define wxAuiPaneInfo_Show 2648 +#define wxAuiPaneInfo_ToolbarPane 2649 +#define wxAuiPaneInfo_Top 2650 +#define wxAuiPaneInfo_TopDockable 2651 +#define wxAuiPaneInfo_Window 2652 +#define wxAuiNotebook_new_0 2653 +#define wxAuiNotebook_new_2 2654 +#define wxAuiNotebook_AddPage 2655 +#define wxAuiNotebook_Create 2656 +#define wxAuiNotebook_DeletePage 2657 +#define wxAuiNotebook_GetArtProvider 2658 +#define wxAuiNotebook_GetPage 2659 +#define wxAuiNotebook_GetPageBitmap 2660 +#define wxAuiNotebook_GetPageCount 2661 +#define wxAuiNotebook_GetPageIndex 2662 +#define wxAuiNotebook_GetPageText 2663 +#define wxAuiNotebook_GetSelection 2664 +#define wxAuiNotebook_InsertPage 2665 +#define wxAuiNotebook_RemovePage 2666 +#define wxAuiNotebook_SetArtProvider 2667 +#define wxAuiNotebook_SetFont 2668 +#define wxAuiNotebook_SetPageBitmap 2669 +#define wxAuiNotebook_SetPageText 2670 +#define wxAuiNotebook_SetSelection 2671 +#define wxAuiNotebook_SetTabCtrlHeight 2672 +#define wxAuiNotebook_SetUniformBitmapSize 2673 +#define wxAuiNotebook_destroy 2674 +#define wxMDIParentFrame_new_0 2675 +#define wxMDIParentFrame_new_4 2676 +#define wxMDIParentFrame_destruct 2677 +#define wxMDIParentFrame_ActivateNext 2678 +#define wxMDIParentFrame_ActivatePrevious 2679 +#define wxMDIParentFrame_ArrangeIcons 2680 +#define wxMDIParentFrame_Cascade 2681 +#define wxMDIParentFrame_Create 2682 +#define wxMDIParentFrame_GetActiveChild 2683 +#define wxMDIParentFrame_GetClientWindow 2684 +#define wxMDIParentFrame_Tile 2685 +#define wxMDIChildFrame_new_0 2686 +#define wxMDIChildFrame_new_4 2687 +#define wxMDIChildFrame_destruct 2688 +#define wxMDIChildFrame_Activate 2689 +#define wxMDIChildFrame_Create 2690 +#define wxMDIChildFrame_Maximize 2691 +#define wxMDIChildFrame_Restore 2692 +#define wxMDIClientWindow_new_0 2693 +#define wxMDIClientWindow_new_2 2694 +#define wxMDIClientWindow_destruct 2695 +#define wxMDIClientWindow_CreateClient 2696 +#define wxLayoutAlgorithm_new 2697 +#define wxLayoutAlgorithm_LayoutFrame 2698 +#define wxLayoutAlgorithm_LayoutMDIFrame 2699 +#define wxLayoutAlgorithm_LayoutWindow 2700 +#define wxLayoutAlgorithm_destroy 2701 +#define wxEvent_GetId 2702 +#define wxEvent_GetSkipped 2703 +#define wxEvent_GetTimestamp 2704 +#define wxEvent_IsCommandEvent 2705 +#define wxEvent_ResumePropagation 2706 +#define wxEvent_ShouldPropagate 2707 +#define wxEvent_Skip 2708 +#define wxEvent_StopPropagation 2709 +#define wxCommandEvent_getClientData 2710 +#define wxCommandEvent_GetExtraLong 2711 +#define wxCommandEvent_GetInt 2712 +#define wxCommandEvent_GetSelection 2713 +#define wxCommandEvent_GetString 2714 +#define wxCommandEvent_IsChecked 2715 +#define wxCommandEvent_IsSelection 2716 +#define wxCommandEvent_SetInt 2717 +#define wxCommandEvent_SetString 2718 +#define wxScrollEvent_GetOrientation 2719 +#define wxScrollEvent_GetPosition 2720 +#define wxScrollWinEvent_GetOrientation 2721 +#define wxScrollWinEvent_GetPosition 2722 +#define wxMouseEvent_AltDown 2723 +#define wxMouseEvent_Button 2724 +#define wxMouseEvent_ButtonDClick 2725 +#define wxMouseEvent_ButtonDown 2726 +#define wxMouseEvent_ButtonUp 2727 +#define wxMouseEvent_CmdDown 2728 +#define wxMouseEvent_ControlDown 2729 +#define wxMouseEvent_Dragging 2730 +#define wxMouseEvent_Entering 2731 +#define wxMouseEvent_GetButton 2732 +#define wxMouseEvent_GetPosition 2735 +#define wxMouseEvent_GetLogicalPosition 2736 +#define wxMouseEvent_GetLinesPerAction 2737 +#define wxMouseEvent_GetWheelRotation 2738 +#define wxMouseEvent_GetWheelDelta 2739 +#define wxMouseEvent_GetX 2740 +#define wxMouseEvent_GetY 2741 +#define wxMouseEvent_IsButton 2742 +#define wxMouseEvent_IsPageScroll 2743 +#define wxMouseEvent_Leaving 2744 +#define wxMouseEvent_LeftDClick 2745 +#define wxMouseEvent_LeftDown 2746 +#define wxMouseEvent_LeftIsDown 2747 +#define wxMouseEvent_LeftUp 2748 +#define wxMouseEvent_MetaDown 2749 +#define wxMouseEvent_MiddleDClick 2750 +#define wxMouseEvent_MiddleDown 2751 +#define wxMouseEvent_MiddleIsDown 2752 +#define wxMouseEvent_MiddleUp 2753 +#define wxMouseEvent_Moving 2754 +#define wxMouseEvent_RightDClick 2755 +#define wxMouseEvent_RightDown 2756 +#define wxMouseEvent_RightIsDown 2757 +#define wxMouseEvent_RightUp 2758 +#define wxMouseEvent_ShiftDown 2759 +#define wxSetCursorEvent_GetCursor 2760 +#define wxSetCursorEvent_GetX 2761 +#define wxSetCursorEvent_GetY 2762 +#define wxSetCursorEvent_HasCursor 2763 +#define wxSetCursorEvent_SetCursor 2764 +#define wxKeyEvent_AltDown 2765 +#define wxKeyEvent_CmdDown 2766 +#define wxKeyEvent_ControlDown 2767 +#define wxKeyEvent_GetKeyCode 2768 +#define wxKeyEvent_GetModifiers 2769 +#define wxKeyEvent_GetPosition 2772 +#define wxKeyEvent_GetRawKeyCode 2773 +#define wxKeyEvent_GetRawKeyFlags 2774 +#define wxKeyEvent_GetUnicodeKey 2775 +#define wxKeyEvent_GetX 2776 +#define wxKeyEvent_GetY 2777 +#define wxKeyEvent_HasModifiers 2778 +#define wxKeyEvent_MetaDown 2779 +#define wxKeyEvent_ShiftDown 2780 +#define wxSizeEvent_GetSize 2781 +#define wxMoveEvent_GetPosition 2782 +#define wxEraseEvent_GetDC 2783 +#define wxFocusEvent_GetWindow 2784 +#define wxChildFocusEvent_GetWindow 2785 +#define wxMenuEvent_GetMenu 2786 +#define wxMenuEvent_GetMenuId 2787 +#define wxMenuEvent_IsPopup 2788 +#define wxCloseEvent_CanVeto 2789 +#define wxCloseEvent_GetLoggingOff 2790 +#define wxCloseEvent_SetCanVeto 2791 +#define wxCloseEvent_SetLoggingOff 2792 +#define wxCloseEvent_Veto 2793 +#define wxShowEvent_SetShow 2794 +#define wxShowEvent_GetShow 2795 +#define wxIconizeEvent_Iconized 2796 +#define wxJoystickEvent_ButtonDown 2797 +#define wxJoystickEvent_ButtonIsDown 2798 +#define wxJoystickEvent_ButtonUp 2799 +#define wxJoystickEvent_GetButtonChange 2800 +#define wxJoystickEvent_GetButtonState 2801 +#define wxJoystickEvent_GetJoystick 2802 +#define wxJoystickEvent_GetPosition 2803 +#define wxJoystickEvent_GetZPosition 2804 +#define wxJoystickEvent_IsButton 2805 +#define wxJoystickEvent_IsMove 2806 +#define wxJoystickEvent_IsZMove 2807 +#define wxUpdateUIEvent_CanUpdate 2808 +#define wxUpdateUIEvent_Check 2809 +#define wxUpdateUIEvent_Enable 2810 +#define wxUpdateUIEvent_Show 2811 +#define wxUpdateUIEvent_GetChecked 2812 +#define wxUpdateUIEvent_GetEnabled 2813 +#define wxUpdateUIEvent_GetShown 2814 +#define wxUpdateUIEvent_GetSetChecked 2815 +#define wxUpdateUIEvent_GetSetEnabled 2816 +#define wxUpdateUIEvent_GetSetShown 2817 +#define wxUpdateUIEvent_GetSetText 2818 +#define wxUpdateUIEvent_GetText 2819 +#define wxUpdateUIEvent_GetMode 2820 +#define wxUpdateUIEvent_GetUpdateInterval 2821 +#define wxUpdateUIEvent_ResetUpdateTime 2822 +#define wxUpdateUIEvent_SetMode 2823 +#define wxUpdateUIEvent_SetText 2824 +#define wxUpdateUIEvent_SetUpdateInterval 2825 +#define wxMouseCaptureChangedEvent_GetCapturedWindow 2826 +#define wxPaletteChangedEvent_SetChangedWindow 2827 +#define wxPaletteChangedEvent_GetChangedWindow 2828 +#define wxQueryNewPaletteEvent_SetPaletteRealized 2829 +#define wxQueryNewPaletteEvent_GetPaletteRealized 2830 +#define wxNavigationKeyEvent_GetDirection 2831 +#define wxNavigationKeyEvent_SetDirection 2832 +#define wxNavigationKeyEvent_IsWindowChange 2833 +#define wxNavigationKeyEvent_SetWindowChange 2834 +#define wxNavigationKeyEvent_IsFromTab 2835 +#define wxNavigationKeyEvent_SetFromTab 2836 +#define wxNavigationKeyEvent_GetCurrentFocus 2837 +#define wxNavigationKeyEvent_SetCurrentFocus 2838 +#define wxHelpEvent_GetOrigin 2839 +#define wxHelpEvent_GetPosition 2840 +#define wxHelpEvent_SetOrigin 2841 +#define wxHelpEvent_SetPosition 2842 +#define wxContextMenuEvent_GetPosition 2843 +#define wxContextMenuEvent_SetPosition 2844 +#define wxIdleEvent_CanSend 2845 +#define wxIdleEvent_GetMode 2846 +#define wxIdleEvent_RequestMore 2847 +#define wxIdleEvent_MoreRequested 2848 +#define wxIdleEvent_SetMode 2849 +#define wxGridEvent_AltDown 2850 +#define wxGridEvent_ControlDown 2851 +#define wxGridEvent_GetCol 2852 +#define wxGridEvent_GetPosition 2853 +#define wxGridEvent_GetRow 2854 +#define wxGridEvent_MetaDown 2855 +#define wxGridEvent_Selecting 2856 +#define wxGridEvent_ShiftDown 2857 +#define wxNotifyEvent_Allow 2858 +#define wxNotifyEvent_IsAllowed 2859 +#define wxNotifyEvent_Veto 2860 +#define wxSashEvent_GetEdge 2861 +#define wxSashEvent_GetDragRect 2862 +#define wxSashEvent_GetDragStatus 2863 +#define wxListEvent_GetCacheFrom 2864 +#define wxListEvent_GetCacheTo 2865 +#define wxListEvent_GetKeyCode 2866 +#define wxListEvent_GetIndex 2867 +#define wxListEvent_GetColumn 2868 +#define wxListEvent_GetPoint 2869 +#define wxListEvent_GetLabel 2870 +#define wxListEvent_GetText 2871 +#define wxListEvent_GetImage 2872 +#define wxListEvent_GetData 2873 +#define wxListEvent_GetMask 2874 +#define wxListEvent_GetItem 2875 +#define wxListEvent_IsEditCancelled 2876 +#define wxDateEvent_GetDate 2877 +#define wxCalendarEvent_GetWeekDay 2878 +#define wxFileDirPickerEvent_GetPath 2879 +#define wxColourPickerEvent_GetColour 2880 +#define wxFontPickerEvent_GetFont 2881 +#define wxStyledTextEvent_GetPosition 2882 +#define wxStyledTextEvent_GetKey 2883 +#define wxStyledTextEvent_GetModifiers 2884 +#define wxStyledTextEvent_GetModificationType 2885 +#define wxStyledTextEvent_GetText 2886 +#define wxStyledTextEvent_GetLength 2887 +#define wxStyledTextEvent_GetLinesAdded 2888 +#define wxStyledTextEvent_GetLine 2889 +#define wxStyledTextEvent_GetFoldLevelNow 2890 +#define wxStyledTextEvent_GetFoldLevelPrev 2891 +#define wxStyledTextEvent_GetMargin 2892 +#define wxStyledTextEvent_GetMessage 2893 +#define wxStyledTextEvent_GetWParam 2894 +#define wxStyledTextEvent_GetLParam 2895 +#define wxStyledTextEvent_GetListType 2896 +#define wxStyledTextEvent_GetX 2897 +#define wxStyledTextEvent_GetY 2898 +#define wxStyledTextEvent_GetDragText 2899 +#define wxStyledTextEvent_GetDragAllowMove 2900 +#define wxStyledTextEvent_GetDragResult 2901 +#define wxStyledTextEvent_GetShift 2902 +#define wxStyledTextEvent_GetControl 2903 +#define wxStyledTextEvent_GetAlt 2904 +#define utils_wxGetKeyState 2905 +#define utils_wxGetMousePosition 2906 +#define utils_wxGetMouseState 2907 +#define utils_wxSetDetectableAutoRepeat 2908 +#define utils_wxBell 2909 +#define utils_wxFindMenuItemId 2910 +#define utils_wxGenericFindWindowAtPoint 2911 +#define utils_wxFindWindowAtPoint 2912 +#define utils_wxBeginBusyCursor 2913 +#define utils_wxEndBusyCursor 2914 +#define utils_wxIsBusy 2915 +#define utils_wxShutdown 2916 +#define utils_wxShell 2917 +#define utils_wxLaunchDefaultBrowser 2918 +#define utils_wxGetEmailAddress 2919 +#define utils_wxGetUserId 2920 +#define utils_wxGetHomeDir 2921 +#define utils_wxNewId 2922 +#define utils_wxRegisterId 2923 +#define utils_wxGetCurrentId 2924 +#define utils_wxGetOsDescription 2925 +#define utils_wxIsPlatformLittleEndian 2926 +#define utils_wxIsPlatform64Bit 2927 +#define gdicmn_wxDisplaySize 2928 +#define gdicmn_wxSetCursor 2929 +#define wxPrintout_new 2930 +#define wxPrintout_destruct 2931 +#define wxPrintout_GetDC 2932 +#define wxPrintout_GetPageSizeMM 2933 +#define wxPrintout_GetPageSizePixels 2934 +#define wxPrintout_GetPaperRectPixels 2935 +#define wxPrintout_GetPPIPrinter 2936 +#define wxPrintout_GetPPIScreen 2937 +#define wxPrintout_GetTitle 2938 +#define wxPrintout_IsPreview 2939 +#define wxPrintout_FitThisSizeToPaper 2940 +#define wxPrintout_FitThisSizeToPage 2941 +#define wxPrintout_FitThisSizeToPageMargins 2942 +#define wxPrintout_MapScreenSizeToPaper 2943 +#define wxPrintout_MapScreenSizeToPage 2944 +#define wxPrintout_MapScreenSizeToPageMargins 2945 +#define wxPrintout_MapScreenSizeToDevice 2946 +#define wxPrintout_GetLogicalPaperRect 2947 +#define wxPrintout_GetLogicalPageRect 2948 +#define wxPrintout_GetLogicalPageMarginsRect 2949 +#define wxPrintout_SetLogicalOrigin 2950 +#define wxPrintout_OffsetLogicalOrigin 2951 +#define wxStyledTextCtrl_new_2 2952 +#define wxStyledTextCtrl_new_0 2953 +#define wxStyledTextCtrl_destruct 2954 +#define wxStyledTextCtrl_Create 2955 +#define wxStyledTextCtrl_AddText 2956 +#define wxStyledTextCtrl_AddStyledText 2957 +#define wxStyledTextCtrl_InsertText 2958 +#define wxStyledTextCtrl_ClearAll 2959 +#define wxStyledTextCtrl_ClearDocumentStyle 2960 +#define wxStyledTextCtrl_GetLength 2961 +#define wxStyledTextCtrl_GetCharAt 2962 +#define wxStyledTextCtrl_GetCurrentPos 2963 +#define wxStyledTextCtrl_GetAnchor 2964 +#define wxStyledTextCtrl_GetStyleAt 2965 +#define wxStyledTextCtrl_Redo 2966 +#define wxStyledTextCtrl_SetUndoCollection 2967 +#define wxStyledTextCtrl_SelectAll 2968 +#define wxStyledTextCtrl_SetSavePoint 2969 +#define wxStyledTextCtrl_GetStyledText 2970 +#define wxStyledTextCtrl_CanRedo 2971 +#define wxStyledTextCtrl_MarkerLineFromHandle 2972 +#define wxStyledTextCtrl_MarkerDeleteHandle 2973 +#define wxStyledTextCtrl_GetUndoCollection 2974 +#define wxStyledTextCtrl_GetViewWhiteSpace 2975 +#define wxStyledTextCtrl_SetViewWhiteSpace 2976 +#define wxStyledTextCtrl_PositionFromPoint 2977 +#define wxStyledTextCtrl_PositionFromPointClose 2978 +#define wxStyledTextCtrl_GotoLine 2979 +#define wxStyledTextCtrl_GotoPos 2980 +#define wxStyledTextCtrl_SetAnchor 2981 +#define wxStyledTextCtrl_GetCurLine 2982 +#define wxStyledTextCtrl_GetEndStyled 2983 +#define wxStyledTextCtrl_ConvertEOLs 2984 +#define wxStyledTextCtrl_GetEOLMode 2985 +#define wxStyledTextCtrl_SetEOLMode 2986 +#define wxStyledTextCtrl_StartStyling 2987 +#define wxStyledTextCtrl_SetStyling 2988 +#define wxStyledTextCtrl_GetBufferedDraw 2989 +#define wxStyledTextCtrl_SetBufferedDraw 2990 +#define wxStyledTextCtrl_SetTabWidth 2991 +#define wxStyledTextCtrl_GetTabWidth 2992 +#define wxStyledTextCtrl_SetCodePage 2993 +#define wxStyledTextCtrl_MarkerDefine 2994 +#define wxStyledTextCtrl_MarkerSetForeground 2995 +#define wxStyledTextCtrl_MarkerSetBackground 2996 +#define wxStyledTextCtrl_MarkerAdd 2997 +#define wxStyledTextCtrl_MarkerDelete 2998 +#define wxStyledTextCtrl_MarkerDeleteAll 2999 +#define wxStyledTextCtrl_MarkerGet 3000 +#define wxStyledTextCtrl_MarkerNext 3001 +#define wxStyledTextCtrl_MarkerPrevious 3002 +#define wxStyledTextCtrl_MarkerDefineBitmap 3003 +#define wxStyledTextCtrl_MarkerAddSet 3004 +#define wxStyledTextCtrl_MarkerSetAlpha 3005 +#define wxStyledTextCtrl_SetMarginType 3006 +#define wxStyledTextCtrl_GetMarginType 3007 +#define wxStyledTextCtrl_SetMarginWidth 3008 +#define wxStyledTextCtrl_GetMarginWidth 3009 +#define wxStyledTextCtrl_SetMarginMask 3010 +#define wxStyledTextCtrl_GetMarginMask 3011 +#define wxStyledTextCtrl_SetMarginSensitive 3012 +#define wxStyledTextCtrl_GetMarginSensitive 3013 +#define wxStyledTextCtrl_StyleClearAll 3014 +#define wxStyledTextCtrl_StyleSetForeground 3015 +#define wxStyledTextCtrl_StyleSetBackground 3016 +#define wxStyledTextCtrl_StyleSetBold 3017 +#define wxStyledTextCtrl_StyleSetItalic 3018 +#define wxStyledTextCtrl_StyleSetSize 3019 +#define wxStyledTextCtrl_StyleSetFaceName 3020 +#define wxStyledTextCtrl_StyleSetEOLFilled 3021 +#define wxStyledTextCtrl_StyleResetDefault 3022 +#define wxStyledTextCtrl_StyleSetUnderline 3023 +#define wxStyledTextCtrl_StyleSetCase 3024 +#define wxStyledTextCtrl_StyleSetHotSpot 3025 +#define wxStyledTextCtrl_SetSelForeground 3026 +#define wxStyledTextCtrl_SetSelBackground 3027 +#define wxStyledTextCtrl_GetSelAlpha 3028 +#define wxStyledTextCtrl_SetSelAlpha 3029 +#define wxStyledTextCtrl_SetCaretForeground 3030 +#define wxStyledTextCtrl_CmdKeyAssign 3031 +#define wxStyledTextCtrl_CmdKeyClear 3032 +#define wxStyledTextCtrl_CmdKeyClearAll 3033 +#define wxStyledTextCtrl_SetStyleBytes 3034 +#define wxStyledTextCtrl_StyleSetVisible 3035 +#define wxStyledTextCtrl_GetCaretPeriod 3036 +#define wxStyledTextCtrl_SetCaretPeriod 3037 +#define wxStyledTextCtrl_SetWordChars 3038 +#define wxStyledTextCtrl_BeginUndoAction 3039 +#define wxStyledTextCtrl_EndUndoAction 3040 +#define wxStyledTextCtrl_IndicatorSetStyle 3041 +#define wxStyledTextCtrl_IndicatorGetStyle 3042 +#define wxStyledTextCtrl_IndicatorSetForeground 3043 +#define wxStyledTextCtrl_IndicatorGetForeground 3044 +#define wxStyledTextCtrl_SetWhitespaceForeground 3045 +#define wxStyledTextCtrl_SetWhitespaceBackground 3046 +#define wxStyledTextCtrl_GetStyleBits 3047 +#define wxStyledTextCtrl_SetLineState 3048 +#define wxStyledTextCtrl_GetLineState 3049 +#define wxStyledTextCtrl_GetMaxLineState 3050 +#define wxStyledTextCtrl_GetCaretLineVisible 3051 +#define wxStyledTextCtrl_SetCaretLineVisible 3052 +#define wxStyledTextCtrl_GetCaretLineBackground 3053 +#define wxStyledTextCtrl_SetCaretLineBackground 3054 +#define wxStyledTextCtrl_AutoCompShow 3055 +#define wxStyledTextCtrl_AutoCompCancel 3056 +#define wxStyledTextCtrl_AutoCompActive 3057 +#define wxStyledTextCtrl_AutoCompPosStart 3058 +#define wxStyledTextCtrl_AutoCompComplete 3059 +#define wxStyledTextCtrl_AutoCompStops 3060 +#define wxStyledTextCtrl_AutoCompSetSeparator 3061 +#define wxStyledTextCtrl_AutoCompGetSeparator 3062 +#define wxStyledTextCtrl_AutoCompSelect 3063 +#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3064 +#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3065 +#define wxStyledTextCtrl_AutoCompSetFillUps 3066 +#define wxStyledTextCtrl_AutoCompSetChooseSingle 3067 +#define wxStyledTextCtrl_AutoCompGetChooseSingle 3068 +#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3069 +#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3070 +#define wxStyledTextCtrl_UserListShow 3071 +#define wxStyledTextCtrl_AutoCompSetAutoHide 3072 +#define wxStyledTextCtrl_AutoCompGetAutoHide 3073 +#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3074 +#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3075 +#define wxStyledTextCtrl_RegisterImage 3076 +#define wxStyledTextCtrl_ClearRegisteredImages 3077 +#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3078 +#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3079 +#define wxStyledTextCtrl_AutoCompSetMaxWidth 3080 +#define wxStyledTextCtrl_AutoCompGetMaxWidth 3081 +#define wxStyledTextCtrl_AutoCompSetMaxHeight 3082 +#define wxStyledTextCtrl_AutoCompGetMaxHeight 3083 +#define wxStyledTextCtrl_SetIndent 3084 +#define wxStyledTextCtrl_GetIndent 3085 +#define wxStyledTextCtrl_SetUseTabs 3086 +#define wxStyledTextCtrl_GetUseTabs 3087 +#define wxStyledTextCtrl_SetLineIndentation 3088 +#define wxStyledTextCtrl_GetLineIndentation 3089 +#define wxStyledTextCtrl_GetLineIndentPosition 3090 +#define wxStyledTextCtrl_GetColumn 3091 +#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3092 +#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3093 +#define wxStyledTextCtrl_SetIndentationGuides 3094 +#define wxStyledTextCtrl_GetIndentationGuides 3095 +#define wxStyledTextCtrl_SetHighlightGuide 3096 +#define wxStyledTextCtrl_GetHighlightGuide 3097 +#define wxStyledTextCtrl_GetLineEndPosition 3098 +#define wxStyledTextCtrl_GetCodePage 3099 +#define wxStyledTextCtrl_GetCaretForeground 3100 +#define wxStyledTextCtrl_GetReadOnly 3101 +#define wxStyledTextCtrl_SetCurrentPos 3102 +#define wxStyledTextCtrl_SetSelectionStart 3103 +#define wxStyledTextCtrl_GetSelectionStart 3104 +#define wxStyledTextCtrl_SetSelectionEnd 3105 +#define wxStyledTextCtrl_GetSelectionEnd 3106 +#define wxStyledTextCtrl_SetPrintMagnification 3107 +#define wxStyledTextCtrl_GetPrintMagnification 3108 +#define wxStyledTextCtrl_SetPrintColourMode 3109 +#define wxStyledTextCtrl_GetPrintColourMode 3110 +#define wxStyledTextCtrl_FindText 3111 +#define wxStyledTextCtrl_FormatRange 3112 +#define wxStyledTextCtrl_GetFirstVisibleLine 3113 +#define wxStyledTextCtrl_GetLine 3114 +#define wxStyledTextCtrl_GetLineCount 3115 +#define wxStyledTextCtrl_SetMarginLeft 3116 +#define wxStyledTextCtrl_GetMarginLeft 3117 +#define wxStyledTextCtrl_SetMarginRight 3118 +#define wxStyledTextCtrl_GetMarginRight 3119 +#define wxStyledTextCtrl_GetModify 3120 +#define wxStyledTextCtrl_SetSelection 3121 +#define wxStyledTextCtrl_GetSelectedText 3122 +#define wxStyledTextCtrl_GetTextRange 3123 +#define wxStyledTextCtrl_HideSelection 3124 +#define wxStyledTextCtrl_LineFromPosition 3125 +#define wxStyledTextCtrl_PositionFromLine 3126 +#define wxStyledTextCtrl_LineScroll 3127 +#define wxStyledTextCtrl_EnsureCaretVisible 3128 +#define wxStyledTextCtrl_ReplaceSelection 3129 +#define wxStyledTextCtrl_SetReadOnly 3130 +#define wxStyledTextCtrl_CanPaste 3131 +#define wxStyledTextCtrl_CanUndo 3132 +#define wxStyledTextCtrl_EmptyUndoBuffer 3133 +#define wxStyledTextCtrl_Undo 3134 +#define wxStyledTextCtrl_Cut 3135 +#define wxStyledTextCtrl_Copy 3136 +#define wxStyledTextCtrl_Paste 3137 +#define wxStyledTextCtrl_Clear 3138 +#define wxStyledTextCtrl_SetText 3139 +#define wxStyledTextCtrl_GetText 3140 +#define wxStyledTextCtrl_GetTextLength 3141 +#define wxStyledTextCtrl_GetOvertype 3142 +#define wxStyledTextCtrl_SetCaretWidth 3143 +#define wxStyledTextCtrl_GetCaretWidth 3144 +#define wxStyledTextCtrl_SetTargetStart 3145 +#define wxStyledTextCtrl_GetTargetStart 3146 +#define wxStyledTextCtrl_SetTargetEnd 3147 +#define wxStyledTextCtrl_GetTargetEnd 3148 +#define wxStyledTextCtrl_ReplaceTarget 3149 +#define wxStyledTextCtrl_SearchInTarget 3150 +#define wxStyledTextCtrl_SetSearchFlags 3151 +#define wxStyledTextCtrl_GetSearchFlags 3152 +#define wxStyledTextCtrl_CallTipShow 3153 +#define wxStyledTextCtrl_CallTipCancel 3154 +#define wxStyledTextCtrl_CallTipActive 3155 +#define wxStyledTextCtrl_CallTipPosAtStart 3156 +#define wxStyledTextCtrl_CallTipSetHighlight 3157 +#define wxStyledTextCtrl_CallTipSetBackground 3158 +#define wxStyledTextCtrl_CallTipSetForeground 3159 +#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3160 +#define wxStyledTextCtrl_CallTipUseStyle 3161 +#define wxStyledTextCtrl_VisibleFromDocLine 3162 +#define wxStyledTextCtrl_DocLineFromVisible 3163 +#define wxStyledTextCtrl_WrapCount 3164 +#define wxStyledTextCtrl_SetFoldLevel 3165 +#define wxStyledTextCtrl_GetFoldLevel 3166 +#define wxStyledTextCtrl_GetLastChild 3167 +#define wxStyledTextCtrl_GetFoldParent 3168 +#define wxStyledTextCtrl_ShowLines 3169 +#define wxStyledTextCtrl_HideLines 3170 +#define wxStyledTextCtrl_GetLineVisible 3171 +#define wxStyledTextCtrl_SetFoldExpanded 3172 +#define wxStyledTextCtrl_GetFoldExpanded 3173 +#define wxStyledTextCtrl_ToggleFold 3174 +#define wxStyledTextCtrl_EnsureVisible 3175 +#define wxStyledTextCtrl_SetFoldFlags 3176 +#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3177 +#define wxStyledTextCtrl_SetTabIndents 3178 +#define wxStyledTextCtrl_GetTabIndents 3179 +#define wxStyledTextCtrl_SetBackSpaceUnIndents 3180 +#define wxStyledTextCtrl_GetBackSpaceUnIndents 3181 +#define wxStyledTextCtrl_SetMouseDwellTime 3182 +#define wxStyledTextCtrl_GetMouseDwellTime 3183 +#define wxStyledTextCtrl_WordStartPosition 3184 +#define wxStyledTextCtrl_WordEndPosition 3185 +#define wxStyledTextCtrl_SetWrapMode 3186 +#define wxStyledTextCtrl_GetWrapMode 3187 +#define wxStyledTextCtrl_SetWrapVisualFlags 3188 +#define wxStyledTextCtrl_GetWrapVisualFlags 3189 +#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3190 +#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3191 +#define wxStyledTextCtrl_SetWrapStartIndent 3192 +#define wxStyledTextCtrl_GetWrapStartIndent 3193 +#define wxStyledTextCtrl_SetLayoutCache 3194 +#define wxStyledTextCtrl_GetLayoutCache 3195 +#define wxStyledTextCtrl_SetScrollWidth 3196 +#define wxStyledTextCtrl_GetScrollWidth 3197 +#define wxStyledTextCtrl_TextWidth 3198 +#define wxStyledTextCtrl_GetEndAtLastLine 3199 +#define wxStyledTextCtrl_TextHeight 3200 +#define wxStyledTextCtrl_SetUseVerticalScrollBar 3201 +#define wxStyledTextCtrl_GetUseVerticalScrollBar 3202 +#define wxStyledTextCtrl_AppendText 3203 +#define wxStyledTextCtrl_GetTwoPhaseDraw 3204 +#define wxStyledTextCtrl_SetTwoPhaseDraw 3205 +#define wxStyledTextCtrl_TargetFromSelection 3206 +#define wxStyledTextCtrl_LinesJoin 3207 +#define wxStyledTextCtrl_LinesSplit 3208 +#define wxStyledTextCtrl_SetFoldMarginColour 3209 +#define wxStyledTextCtrl_SetFoldMarginHiColour 3210 +#define wxStyledTextCtrl_LineDown 3211 +#define wxStyledTextCtrl_LineDownExtend 3212 +#define wxStyledTextCtrl_LineUp 3213 +#define wxStyledTextCtrl_LineUpExtend 3214 +#define wxStyledTextCtrl_CharLeft 3215 +#define wxStyledTextCtrl_CharLeftExtend 3216 +#define wxStyledTextCtrl_CharRight 3217 +#define wxStyledTextCtrl_CharRightExtend 3218 +#define wxStyledTextCtrl_WordLeft 3219 +#define wxStyledTextCtrl_WordLeftExtend 3220 +#define wxStyledTextCtrl_WordRight 3221 +#define wxStyledTextCtrl_WordRightExtend 3222 +#define wxStyledTextCtrl_Home 3223 +#define wxStyledTextCtrl_HomeExtend 3224 +#define wxStyledTextCtrl_LineEnd 3225 +#define wxStyledTextCtrl_LineEndExtend 3226 +#define wxStyledTextCtrl_DocumentStart 3227 +#define wxStyledTextCtrl_DocumentStartExtend 3228 +#define wxStyledTextCtrl_DocumentEnd 3229 +#define wxStyledTextCtrl_DocumentEndExtend 3230 +#define wxStyledTextCtrl_PageUp 3231 +#define wxStyledTextCtrl_PageUpExtend 3232 +#define wxStyledTextCtrl_PageDown 3233 +#define wxStyledTextCtrl_PageDownExtend 3234 +#define wxStyledTextCtrl_EditToggleOvertype 3235 +#define wxStyledTextCtrl_Cancel 3236 +#define wxStyledTextCtrl_DeleteBack 3237 +#define wxStyledTextCtrl_Tab 3238 +#define wxStyledTextCtrl_BackTab 3239 +#define wxStyledTextCtrl_NewLine 3240 +#define wxStyledTextCtrl_FormFeed 3241 +#define wxStyledTextCtrl_VCHome 3242 +#define wxStyledTextCtrl_VCHomeExtend 3243 +#define wxStyledTextCtrl_ZoomIn 3244 +#define wxStyledTextCtrl_ZoomOut 3245 +#define wxStyledTextCtrl_DelWordLeft 3246 +#define wxStyledTextCtrl_DelWordRight 3247 +#define wxStyledTextCtrl_LineCut 3248 +#define wxStyledTextCtrl_LineDelete 3249 +#define wxStyledTextCtrl_LineTranspose 3250 +#define wxStyledTextCtrl_LineDuplicate 3251 +#define wxStyledTextCtrl_LowerCase 3252 +#define wxStyledTextCtrl_UpperCase 3253 +#define wxStyledTextCtrl_LineScrollDown 3254 +#define wxStyledTextCtrl_LineScrollUp 3255 +#define wxStyledTextCtrl_DeleteBackNotLine 3256 +#define wxStyledTextCtrl_HomeDisplay 3257 +#define wxStyledTextCtrl_HomeDisplayExtend 3258 +#define wxStyledTextCtrl_LineEndDisplay 3259 +#define wxStyledTextCtrl_LineEndDisplayExtend 3260 +#define wxStyledTextCtrl_HomeWrapExtend 3261 +#define wxStyledTextCtrl_LineEndWrap 3262 +#define wxStyledTextCtrl_LineEndWrapExtend 3263 +#define wxStyledTextCtrl_VCHomeWrap 3264 +#define wxStyledTextCtrl_VCHomeWrapExtend 3265 +#define wxStyledTextCtrl_LineCopy 3266 +#define wxStyledTextCtrl_MoveCaretInsideView 3267 +#define wxStyledTextCtrl_LineLength 3268 +#define wxStyledTextCtrl_BraceHighlight 3269 +#define wxStyledTextCtrl_BraceBadLight 3270 +#define wxStyledTextCtrl_BraceMatch 3271 +#define wxStyledTextCtrl_GetViewEOL 3272 +#define wxStyledTextCtrl_SetViewEOL 3273 +#define wxStyledTextCtrl_SetModEventMask 3274 +#define wxStyledTextCtrl_GetEdgeColumn 3275 +#define wxStyledTextCtrl_SetEdgeColumn 3276 +#define wxStyledTextCtrl_SetEdgeMode 3277 +#define wxStyledTextCtrl_GetEdgeMode 3278 +#define wxStyledTextCtrl_GetEdgeColour 3279 +#define wxStyledTextCtrl_SetEdgeColour 3280 +#define wxStyledTextCtrl_SearchAnchor 3281 +#define wxStyledTextCtrl_SearchNext 3282 +#define wxStyledTextCtrl_SearchPrev 3283 +#define wxStyledTextCtrl_LinesOnScreen 3284 +#define wxStyledTextCtrl_UsePopUp 3285 +#define wxStyledTextCtrl_SelectionIsRectangle 3286 +#define wxStyledTextCtrl_SetZoom 3287 +#define wxStyledTextCtrl_GetZoom 3288 +#define wxStyledTextCtrl_GetModEventMask 3289 +#define wxStyledTextCtrl_SetSTCFocus 3290 +#define wxStyledTextCtrl_GetSTCFocus 3291 +#define wxStyledTextCtrl_SetStatus 3292 +#define wxStyledTextCtrl_GetStatus 3293 +#define wxStyledTextCtrl_SetMouseDownCaptures 3294 +#define wxStyledTextCtrl_GetMouseDownCaptures 3295 +#define wxStyledTextCtrl_SetSTCCursor 3296 +#define wxStyledTextCtrl_GetSTCCursor 3297 +#define wxStyledTextCtrl_SetControlCharSymbol 3298 +#define wxStyledTextCtrl_GetControlCharSymbol 3299 +#define wxStyledTextCtrl_WordPartLeft 3300 +#define wxStyledTextCtrl_WordPartLeftExtend 3301 +#define wxStyledTextCtrl_WordPartRight 3302 +#define wxStyledTextCtrl_WordPartRightExtend 3303 +#define wxStyledTextCtrl_SetVisiblePolicy 3304 +#define wxStyledTextCtrl_DelLineLeft 3305 +#define wxStyledTextCtrl_DelLineRight 3306 +#define wxStyledTextCtrl_GetXOffset 3307 +#define wxStyledTextCtrl_ChooseCaretX 3308 +#define wxStyledTextCtrl_SetXCaretPolicy 3309 +#define wxStyledTextCtrl_SetYCaretPolicy 3310 +#define wxStyledTextCtrl_GetPrintWrapMode 3311 +#define wxStyledTextCtrl_SetHotspotActiveForeground 3312 +#define wxStyledTextCtrl_SetHotspotActiveBackground 3313 +#define wxStyledTextCtrl_SetHotspotActiveUnderline 3314 +#define wxStyledTextCtrl_SetHotspotSingleLine 3315 +#define wxStyledTextCtrl_ParaDownExtend 3316 +#define wxStyledTextCtrl_ParaUp 3317 +#define wxStyledTextCtrl_ParaUpExtend 3318 +#define wxStyledTextCtrl_PositionBefore 3319 +#define wxStyledTextCtrl_PositionAfter 3320 +#define wxStyledTextCtrl_CopyRange 3321 +#define wxStyledTextCtrl_CopyText 3322 +#define wxStyledTextCtrl_SetSelectionMode 3323 +#define wxStyledTextCtrl_GetSelectionMode 3324 +#define wxStyledTextCtrl_LineDownRectExtend 3325 +#define wxStyledTextCtrl_LineUpRectExtend 3326 +#define wxStyledTextCtrl_CharLeftRectExtend 3327 +#define wxStyledTextCtrl_CharRightRectExtend 3328 +#define wxStyledTextCtrl_HomeRectExtend 3329 +#define wxStyledTextCtrl_VCHomeRectExtend 3330 +#define wxStyledTextCtrl_LineEndRectExtend 3331 +#define wxStyledTextCtrl_PageUpRectExtend 3332 +#define wxStyledTextCtrl_PageDownRectExtend 3333 +#define wxStyledTextCtrl_StutteredPageUp 3334 +#define wxStyledTextCtrl_StutteredPageUpExtend 3335 +#define wxStyledTextCtrl_StutteredPageDown 3336 +#define wxStyledTextCtrl_StutteredPageDownExtend 3337 +#define wxStyledTextCtrl_WordLeftEnd 3338 +#define wxStyledTextCtrl_WordLeftEndExtend 3339 +#define wxStyledTextCtrl_WordRightEnd 3340 +#define wxStyledTextCtrl_WordRightEndExtend 3341 +#define wxStyledTextCtrl_SetWhitespaceChars 3342 +#define wxStyledTextCtrl_SetCharsDefault 3343 +#define wxStyledTextCtrl_AutoCompGetCurrent 3344 +#define wxStyledTextCtrl_Allocate 3345 +#define wxStyledTextCtrl_FindColumn 3346 +#define wxStyledTextCtrl_GetCaretSticky 3347 +#define wxStyledTextCtrl_SetCaretSticky 3348 +#define wxStyledTextCtrl_ToggleCaretSticky 3349 +#define wxStyledTextCtrl_SetPasteConvertEndings 3350 +#define wxStyledTextCtrl_GetPasteConvertEndings 3351 +#define wxStyledTextCtrl_SelectionDuplicate 3352 +#define wxStyledTextCtrl_SetCaretLineBackAlpha 3353 +#define wxStyledTextCtrl_GetCaretLineBackAlpha 3354 +#define wxStyledTextCtrl_StartRecord 3355 +#define wxStyledTextCtrl_StopRecord 3356 +#define wxStyledTextCtrl_SetLexer 3357 +#define wxStyledTextCtrl_GetLexer 3358 +#define wxStyledTextCtrl_Colourise 3359 +#define wxStyledTextCtrl_SetProperty 3360 +#define wxStyledTextCtrl_SetKeyWords 3361 +#define wxStyledTextCtrl_SetLexerLanguage 3362 +#define wxStyledTextCtrl_GetProperty 3363 +#define wxStyledTextCtrl_GetStyleBitsNeeded 3364 +#define wxStyledTextCtrl_GetCurrentLine 3365 +#define wxStyledTextCtrl_StyleSetSpec 3366 +#define wxStyledTextCtrl_StyleSetFont 3367 +#define wxStyledTextCtrl_StyleSetFontAttr 3368 +#define wxStyledTextCtrl_StyleSetCharacterSet 3369 +#define wxStyledTextCtrl_StyleSetFontEncoding 3370 +#define wxStyledTextCtrl_CmdKeyExecute 3371 +#define wxStyledTextCtrl_SetMargins 3372 +#define wxStyledTextCtrl_GetSelection 3373 +#define wxStyledTextCtrl_PointFromPosition 3374 +#define wxStyledTextCtrl_ScrollToLine 3375 +#define wxStyledTextCtrl_ScrollToColumn 3376 +#define wxStyledTextCtrl_SetVScrollBar 3377 +#define wxStyledTextCtrl_SetHScrollBar 3378 +#define wxStyledTextCtrl_GetLastKeydownProcessed 3379 +#define wxStyledTextCtrl_SetLastKeydownProcessed 3380 +#define wxStyledTextCtrl_SaveFile 3381 +#define wxStyledTextCtrl_LoadFile 3382 +#define wxStyledTextCtrl_DoDragOver 3383 +#define wxStyledTextCtrl_DoDropText 3384 +#define wxStyledTextCtrl_GetUseAntiAliasing 3385 +#define wxStyledTextCtrl_AddTextRaw 3386 +#define wxStyledTextCtrl_InsertTextRaw 3387 +#define wxStyledTextCtrl_GetCurLineRaw 3388 +#define wxStyledTextCtrl_GetLineRaw 3389 +#define wxStyledTextCtrl_GetSelectedTextRaw 3390 +#define wxStyledTextCtrl_GetTextRangeRaw 3391 +#define wxStyledTextCtrl_SetTextRaw 3392 +#define wxStyledTextCtrl_GetTextRaw 3393 +#define wxStyledTextCtrl_AppendTextRaw 3394 +#define wxArtProvider_GetBitmap 3395 +#define wxArtProvider_GetIcon 3396 +#define wxTreeEvent_GetKeyCode 3397 +#define wxTreeEvent_GetItem 3398 +#define wxTreeEvent_GetKeyEvent 3399 +#define wxTreeEvent_GetLabel 3400 +#define wxTreeEvent_GetOldItem 3401 +#define wxTreeEvent_GetPoint 3402 +#define wxTreeEvent_IsEditCancelled 3403 +#define wxTreeEvent_SetToolTip 3404 +#define wxNotebookEvent_GetOldSelection 3405 +#define wxNotebookEvent_GetSelection 3406 +#define wxNotebookEvent_SetOldSelection 3407 +#define wxNotebookEvent_SetSelection 3408 +#define wxFileDataObject_new 3409 +#define wxFileDataObject_AddFile 3410 +#define wxFileDataObject_GetFilenames 3411 +#define wxFileDataObject_destroy 3412 +#define wxTextDataObject_new 3413 +#define wxTextDataObject_GetTextLength 3414 +#define wxTextDataObject_GetText 3415 +#define wxTextDataObject_SetText 3416 +#define wxTextDataObject_destroy 3417 +#define wxBitmapDataObject_new_1_1 3418 +#define wxBitmapDataObject_new_1_0 3419 +#define wxBitmapDataObject_GetBitmap 3420 +#define wxBitmapDataObject_SetBitmap 3421 +#define wxBitmapDataObject_destroy 3422 +#define wxClipboard_new 3424 +#define wxClipboard_destruct 3425 +#define wxClipboard_AddData 3426 +#define wxClipboard_Clear 3427 +#define wxClipboard_Close 3428 +#define wxClipboard_Flush 3429 +#define wxClipboard_GetData 3430 +#define wxClipboard_IsOpened 3431 +#define wxClipboard_Open 3432 +#define wxClipboard_SetData 3433 +#define wxClipboard_UsePrimarySelection 3435 +#define wxClipboard_IsSupported 3436 +#define wxClipboard_Get 3437 +#define wxSpinEvent_GetPosition 3438 +#define wxSpinEvent_SetPosition 3439 +#define wxSplitterWindow_new_0 3440 +#define wxSplitterWindow_new_2 3441 +#define wxSplitterWindow_destruct 3442 +#define wxSplitterWindow_Create 3443 +#define wxSplitterWindow_GetMinimumPaneSize 3444 +#define wxSplitterWindow_GetSashGravity 3445 +#define wxSplitterWindow_GetSashPosition 3446 +#define wxSplitterWindow_GetSplitMode 3447 +#define wxSplitterWindow_GetWindow1 3448 +#define wxSplitterWindow_GetWindow2 3449 +#define wxSplitterWindow_Initialize 3450 +#define wxSplitterWindow_IsSplit 3451 +#define wxSplitterWindow_ReplaceWindow 3452 +#define wxSplitterWindow_SetSashGravity 3453 +#define wxSplitterWindow_SetSashPosition 3454 +#define wxSplitterWindow_SetSashSize 3455 +#define wxSplitterWindow_SetMinimumPaneSize 3456 +#define wxSplitterWindow_SetSplitMode 3457 +#define wxSplitterWindow_SplitHorizontally 3458 +#define wxSplitterWindow_SplitVertically 3459 +#define wxSplitterWindow_Unsplit 3460 +#define wxSplitterWindow_UpdateSize 3461 +#define wxSplitterEvent_GetSashPosition 3462 +#define wxSplitterEvent_GetX 3463 +#define wxSplitterEvent_GetY 3464 +#define wxSplitterEvent_GetWindowBeingRemoved 3465 +#define wxSplitterEvent_SetSashPosition 3466 +#define wxHtmlWindow_new_0 3467 +#define wxHtmlWindow_new_2 3468 +#define wxHtmlWindow_AppendToPage 3469 +#define wxHtmlWindow_GetOpenedAnchor 3470 +#define wxHtmlWindow_GetOpenedPage 3471 +#define wxHtmlWindow_GetOpenedPageTitle 3472 +#define wxHtmlWindow_GetRelatedFrame 3473 +#define wxHtmlWindow_HistoryBack 3474 +#define wxHtmlWindow_HistoryCanBack 3475 +#define wxHtmlWindow_HistoryCanForward 3476 +#define wxHtmlWindow_HistoryClear 3477 +#define wxHtmlWindow_HistoryForward 3478 +#define wxHtmlWindow_LoadFile 3479 +#define wxHtmlWindow_LoadPage 3480 +#define wxHtmlWindow_SelectAll 3481 +#define wxHtmlWindow_SelectionToText 3482 +#define wxHtmlWindow_SelectLine 3483 +#define wxHtmlWindow_SelectWord 3484 +#define wxHtmlWindow_SetBorders 3485 +#define wxHtmlWindow_SetFonts 3486 +#define wxHtmlWindow_SetPage 3487 +#define wxHtmlWindow_SetRelatedFrame 3488 +#define wxHtmlWindow_SetRelatedStatusBar 3489 +#define wxHtmlWindow_ToText 3490 +#define wxHtmlWindow_destroy 3491 +#define wxHtmlLinkEvent_GetLinkInfo 3492 +#define wxSystemSettings_GetColour 3493 +#define wxSystemSettings_GetFont 3494 +#define wxSystemSettings_GetMetric 3495 +#define wxSystemSettings_GetScreenType 3496 +#define wxSystemOptions_GetOption 3497 +#define wxSystemOptions_GetOptionInt 3498 +#define wxSystemOptions_HasOption 3499 +#define wxSystemOptions_IsFalse 3500 +#define wxSystemOptions_SetOption_2_1 3501 +#define wxSystemOptions_SetOption_2_0 3502 +#define wxAuiNotebookEvent_SetSelection 3503 +#define wxAuiNotebookEvent_GetSelection 3504 +#define wxAuiNotebookEvent_SetOldSelection 3505 +#define wxAuiNotebookEvent_GetOldSelection 3506 +#define wxAuiNotebookEvent_SetDragSource 3507 +#define wxAuiNotebookEvent_GetDragSource 3508 +#define wxAuiManagerEvent_SetManager 3509 +#define wxAuiManagerEvent_GetManager 3510 +#define wxAuiManagerEvent_SetPane 3511 +#define wxAuiManagerEvent_GetPane 3512 +#define wxAuiManagerEvent_SetButton 3513 +#define wxAuiManagerEvent_GetButton 3514 +#define wxAuiManagerEvent_SetDC 3515 +#define wxAuiManagerEvent_GetDC 3516 +#define wxAuiManagerEvent_Veto 3517 +#define wxAuiManagerEvent_GetVeto 3518 +#define wxAuiManagerEvent_SetCanVeto 3519 +#define wxAuiManagerEvent_CanVeto 3520 +#define wxLogNull_new 3521 +#define wxLogNull_destroy 3522 +#define wxTaskBarIcon_new 3523 +#define wxTaskBarIcon_destruct 3524 +#define wxTaskBarIcon_PopupMenu 3525 +#define wxTaskBarIcon_RemoveIcon 3526 +#define wxTaskBarIcon_SetIcon 3527 +#define wxLocale_new_0 3528 +#define wxLocale_new_2 3530 +#define wxLocale_destruct 3531 +#define wxLocale_Init 3533 +#define wxLocale_AddCatalog_1 3534 +#define wxLocale_AddCatalog_3 3535 +#define wxLocale_AddCatalogLookupPathPrefix 3536 +#define wxLocale_GetCanonicalName 3537 +#define wxLocale_GetLanguage 3538 +#define wxLocale_GetLanguageName 3539 +#define wxLocale_GetLocale 3540 +#define wxLocale_GetName 3541 +#define wxLocale_GetString_2 3542 +#define wxLocale_GetString_4 3543 +#define wxLocale_GetHeaderValue 3544 +#define wxLocale_GetSysName 3545 +#define wxLocale_GetSystemEncoding 3546 +#define wxLocale_GetSystemEncodingName 3547 +#define wxLocale_GetSystemLanguage 3548 +#define wxLocale_IsLoaded 3549 +#define wxLocale_IsOk 3550 +#define wxActivateEvent_GetActive 3551 +#define wxPopupWindow_new_2 3553 +#define wxPopupWindow_new_0 3554 +#define wxPopupWindow_destruct 3556 +#define wxPopupWindow_Create 3557 +#define wxPopupWindow_Position 3558 +#define wxPopupTransientWindow_new_0 3559 +#define wxPopupTransientWindow_new_2 3560 +#define wxPopupTransientWindow_destruct 3561 +#define wxPopupTransientWindow_Popup 3562 +#define wxPopupTransientWindow_Dismiss 3563 diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index f617aaf349..0ee52e3af2 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -500,7 +500,7 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) if(it != ptr2ref.end()) { wxeRefData *refd = it->second; if(refd->alloc_in_erl) { - if((refd->type == 1) && ((wxObject *)ptr)->IsKindOf(CLASSINFO(wxBufferedDC))) { + if((refd->type == 4) && ((wxObject *)ptr)->IsKindOf(CLASSINFO(wxBufferedDC))) { ((wxBufferedDC *)ptr)->m_dc = NULL; // Workaround } wxString msg; @@ -539,6 +539,17 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) refmap.erase((ErlDrvTermData) Ecmd.port); } + +wxeRefData * WxeApp::getRefData(void *ptr) { + ptrMap::iterator it = ptr2ref.find(ptr); + if(it != ptr2ref.end()) { + wxeRefData *refd = it->second; + return refd; + } + return NULL; +} + + wxeMemEnv * WxeApp::getMemEnv(ErlDrvTermData port) { return refmap[port]; } diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h index 5b23e1cbbd..57bf2e2dba 100644 --- a/lib/wx/c_src/wxe_impl.h +++ b/lib/wx/c_src/wxe_impl.h @@ -80,6 +80,7 @@ public: int getRef(void * ptr, wxeMemEnv *memenv); void * getPtr(char * bp, wxeMemEnv *memenv); void clearPtr(void *ptr); + wxeRefData * getRefData(void *ptr); void registerPid(char *ptr, ErlDrvTermData pid, wxeMemEnv *memenv); void init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller); diff --git a/lib/wx/c_src/wxe_memory.h b/lib/wx/c_src/wxe_memory.h index ec22183bfa..8a48c77154 100644 --- a/lib/wx/c_src/wxe_memory.h +++ b/lib/wx/c_src/wxe_memory.h @@ -47,7 +47,8 @@ class wxeRefData { int type; // 0 = wxWindow subclasses, 1 = wxObject subclasses // 2 = wxDialog subclasses, 3 = allocated wxObjects but not returned from new - // > 3 classes which lack virtual destr, or are supposed to be allocated on + // 4 = wxObjects that should always be deleted directly (wxDC derivates) + // > 4 classes which lack virtual destr, or are supposed to be allocated on // the stack bool alloc_in_erl; wxeMemEnv *memenv; diff --git a/lib/wx/configure.in b/lib/wx/configure.in index a96f1f2632..4c4d4f41a8 100755..100644 --- a/lib/wx/configure.in +++ b/lib/wx/configure.in @@ -677,6 +677,27 @@ if test "x$GCC" = xyes; then LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CXXFLAGS]) fi +dnl ---------------------------------------------------------------------- +dnl Enable -fsanitize= flags. +dnl ---------------------------------------------------------------------- + +m4_define(DEFAULT_SANITIZERS, [address,undefined]) +AC_ARG_ENABLE( + sanitizers, + AS_HELP_STRING( + [--enable-sanitizers@<:@=comma-separated list of sanitizers@:>@], + [Default=DEFAULT_SANITIZERS]), +[ +case "$enableval" in + no) sanitizers= ;; + yes) sanitizers="-fsanitize=DEFAULT_SANITIZERS" ;; + *) sanitizers="-fsanitize=$enableval" ;; +esac +CFLAGS="$CFLAGS $sanitizers" +CXXFLAGS="$CXXFLAGS $sanitizers" +LDFLAGS="$LDFLAGS $sanitizers" +]) + ############################################################################# dnl diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml index daa61fda1e..63eb047caa 100644 --- a/lib/wx/doc/src/notes.xml +++ b/lib/wx/doc/src/notes.xml @@ -31,6 +31,36 @@ <p>This document describes the changes made to the wxErlang application.</p> +<section><title>Wx 1.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fix delayed destroy for wxPaintDC objects which could + cause an eternal loop for modal dialogs.</p> <p>Fix + wxSL_LABELS compatibility between wxWidgets-2.8 and + wxWidgets-3.0 versions</p> + <p> + Own Id: OTP-11985</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add missing classes wxPopup[Transient]Window, + wxActivateEvent and wxTextCtrl:cahngeValue/2 function.</p> + <p> + Own Id: OTP-11986</p> + </item> + </list> + </section> + +</section> + <section><title>Wx 1.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl index ac852ce054..348daf64ce 100644 --- a/lib/wx/include/wx.hrl +++ b/lib/wx/include/wx.hrl @@ -165,6 +165,11 @@ -type wxHelpEventType() :: help | detailed_help. -type wxHelp() :: #wxHelp{}. %% Callback event: {@link wxHelpEvent} +-record(wxActivate,{type :: wxActivateEventType(), %% Callback event: {@link wxActivateEvent} + active :: boolean()}). +-type wxActivateEventType() :: activate | activate_app | hibernate. +-type wxActivate() :: #wxActivate{}. %% Callback event: {@link wxActivateEvent} + -record(wxStyledText,{type :: wxStyledTextEventType(), %% Callback event: {@link wxStyledTextEvent} position :: integer(), key :: integer(), @@ -316,8 +321,8 @@ -type wxTreeEventType() :: command_tree_begin_drag | command_tree_begin_rdrag | command_tree_begin_label_edit | command_tree_end_label_edit | command_tree_delete_item | command_tree_get_info | command_tree_set_info | command_tree_item_expanded | command_tree_item_expanding | command_tree_item_collapsed | command_tree_item_collapsing | command_tree_sel_changed | command_tree_sel_changing | command_tree_key_down | command_tree_item_activated | command_tree_item_right_click | command_tree_item_middle_click | command_tree_end_drag | command_tree_state_image_click | command_tree_item_gettooltip | command_tree_item_menu. -type wxTree() :: #wxTree{}. %% Callback event: {@link wxTreeEvent} --type event() :: wxAuiManager() | wxAuiNotebook() | wxCalendar() | wxChildFocus() | wxClipboardText() | wxClose() | wxColourPicker() | wxCommand() | wxContextMenu() | wxDate() | wxDisplayChanged() | wxErase() | wxFileDirPicker() | wxFocus() | wxFontPicker() | wxGrid() | wxHelp() | wxHtmlLink() | wxIconize() | wxIdle() | wxInitDialog() | wxJoystick() | wxKey() | wxList() | wxMaximize() | wxMenu() | wxMouse() | wxMouseCaptureChanged() | wxMove() | wxNavigationKey() | wxNotebook() | wxPaint() | wxPaletteChanged() | wxQueryNewPalette() | wxSash() | wxScroll() | wxScrollWin() | wxSetCursor() | wxShow() | wxSize() | wxSpin() | wxSplitter() | wxStyledText() | wxSysColourChanged() | wxTaskBarIcon() | wxTree() | wxUpdateUI() | wxWindowCreate() | wxWindowDestroy(). --type wxEventType() :: wxAuiManagerEventType() | wxAuiNotebookEventType() | wxCalendarEventType() | wxChildFocusEventType() | wxClipboardTextEventType() | wxCloseEventType() | wxColourPickerEventType() | wxCommandEventType() | wxContextMenuEventType() | wxDateEventType() | wxDisplayChangedEventType() | wxEraseEventType() | wxFileDirPickerEventType() | wxFocusEventType() | wxFontPickerEventType() | wxGridEventType() | wxHelpEventType() | wxHtmlLinkEventType() | wxIconizeEventType() | wxIdleEventType() | wxInitDialogEventType() | wxJoystickEventType() | wxKeyEventType() | wxListEventType() | wxMaximizeEventType() | wxMenuEventType() | wxMouseCaptureChangedEventType() | wxMouseEventType() | wxMoveEventType() | wxNavigationKeyEventType() | wxNotebookEventType() | wxPaintEventType() | wxPaletteChangedEventType() | wxQueryNewPaletteEventType() | wxSashEventType() | wxScrollEventType() | wxScrollWinEventType() | wxSetCursorEventType() | wxShowEventType() | wxSizeEventType() | wxSpinEventType() | wxSplitterEventType() | wxStyledTextEventType() | wxSysColourChangedEventType() | wxTaskBarIconEventType() | wxTreeEventType() | wxUpdateUIEventType() | wxWindowCreateEventType() | wxWindowDestroyEventType(). +-type event() :: wxActivate() | wxAuiManager() | wxAuiNotebook() | wxCalendar() | wxChildFocus() | wxClipboardText() | wxClose() | wxColourPicker() | wxCommand() | wxContextMenu() | wxDate() | wxDisplayChanged() | wxErase() | wxFileDirPicker() | wxFocus() | wxFontPicker() | wxGrid() | wxHelp() | wxHtmlLink() | wxIconize() | wxIdle() | wxInitDialog() | wxJoystick() | wxKey() | wxList() | wxMaximize() | wxMenu() | wxMouse() | wxMouseCaptureChanged() | wxMove() | wxNavigationKey() | wxNotebook() | wxPaint() | wxPaletteChanged() | wxQueryNewPalette() | wxSash() | wxScroll() | wxScrollWin() | wxSetCursor() | wxShow() | wxSize() | wxSpin() | wxSplitter() | wxStyledText() | wxSysColourChanged() | wxTaskBarIcon() | wxTree() | wxUpdateUI() | wxWindowCreate() | wxWindowDestroy(). +-type wxEventType() :: wxActivateEventType() | wxAuiManagerEventType() | wxAuiNotebookEventType() | wxCalendarEventType() | wxChildFocusEventType() | wxClipboardTextEventType() | wxCloseEventType() | wxColourPickerEventType() | wxCommandEventType() | wxContextMenuEventType() | wxDateEventType() | wxDisplayChangedEventType() | wxEraseEventType() | wxFileDirPickerEventType() | wxFocusEventType() | wxFontPickerEventType() | wxGridEventType() | wxHelpEventType() | wxHtmlLinkEventType() | wxIconizeEventType() | wxIdleEventType() | wxInitDialogEventType() | wxJoystickEventType() | wxKeyEventType() | wxListEventType() | wxMaximizeEventType() | wxMenuEventType() | wxMouseCaptureChangedEventType() | wxMouseEventType() | wxMoveEventType() | wxNavigationKeyEventType() | wxNotebookEventType() | wxPaintEventType() | wxPaletteChangedEventType() | wxQueryNewPaletteEventType() | wxSashEventType() | wxScrollEventType() | wxScrollWinEventType() | wxSetCursorEventType() | wxShowEventType() | wxSizeEventType() | wxSpinEventType() | wxSplitterEventType() | wxStyledTextEventType() | wxSysColourChangedEventType() | wxTaskBarIconEventType() | wxTreeEventType() | wxUpdateUIEventType() | wxWindowCreateEventType() | wxWindowDestroyEventType(). %% Hardcoded Records -record(wxMouseState, {x :: integer(), y :: integer(), @@ -2515,7 +2520,7 @@ -define(wxSL_RIGHT, 256). -define(wxSL_TOP, 128). -define(wxSL_LEFT, 64). --define(wxSL_LABELS, 32). +-define(wxSL_LABELS, wxe_util:get_const(wxSL_LABELS)). -define(wxSL_AUTOTICKS, ?wxSL_TICKS). -define(wxSL_TICKS, 16). -define(wxSL_VERTICAL, ?wxVERTICAL). diff --git a/lib/wx/src/gen/wxActivateEvent.erl b/lib/wx/src/gen/wxActivateEvent.erl new file mode 100644 index 0000000000..dc03866027 --- /dev/null +++ b/lib/wx/src/gen/wxActivateEvent.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2014. 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% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxactivateevent.html">wxActivateEvent</a>. +%% <dl><dt>Use {@link wxEvtHandler:connect/3.} with EventType:</dt> +%% <dd><em>activate</em>, <em>activate_app</em>, <em>hibernate</em></dd></dl> +%% See also the message variant {@link wxEvtHandler:wxActivate(). #wxActivate{}} event record type. +%% +%% <p>This class is derived (and can use functions) from: +%% <br />{@link wxEvent} +%% </p> +%% @type wxActivateEvent(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxActivateEvent). +-include("wxe.hrl"). +-export([getActive/1]). + +%% inherited exports +-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1, + resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]). + +-export_type([wxActivateEvent/0]). +%% @hidden +parent_class(wxEvent) -> true; +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxActivateEvent() :: wx:wx_object(). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxactivateevent.html#wxactivateeventgetactive">external documentation</a>. +-spec getActive(This) -> boolean() when + This::wxActivateEvent(). +getActive(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxActivateEvent), + wxe_util:call(?wxActivateEvent_GetActive, + <<ThisRef:32/?UI>>). + + %% From wxEvent +%% @hidden +stopPropagation(This) -> wxEvent:stopPropagation(This). +%% @hidden +skip(This, Options) -> wxEvent:skip(This, Options). +%% @hidden +skip(This) -> wxEvent:skip(This). +%% @hidden +shouldPropagate(This) -> wxEvent:shouldPropagate(This). +%% @hidden +resumePropagation(This,PropagationLevel) -> wxEvent:resumePropagation(This,PropagationLevel). +%% @hidden +isCommandEvent(This) -> wxEvent:isCommandEvent(This). +%% @hidden +getTimestamp(This) -> wxEvent:getTimestamp(This). +%% @hidden +getSkipped(This) -> wxEvent:getSkipped(This). +%% @hidden +getId(This) -> wxEvent:getId(This). diff --git a/lib/wx/src/gen/wxPopupTransientWindow.erl b/lib/wx/src/gen/wxPopupTransientWindow.erl new file mode 100644 index 0000000000..253d33e5ac --- /dev/null +++ b/lib/wx/src/gen/wxPopupTransientWindow.erl @@ -0,0 +1,506 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2014. 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% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopuptransientwindow.html">wxPopupTransientWindow</a>. +%% <p>This class is derived (and can use functions) from: +%% <br />{@link wxPopupWindow} +%% <br />{@link wxWindow} +%% <br />{@link wxEvtHandler} +%% </p> +%% @type wxPopupTransientWindow(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxPopupTransientWindow). +-include("wxe.hrl"). +-export([destroy/1,dismiss/1,new/0,new/1,new/2,popup/1,popup/2]). + +%% inherited exports +-export([cacheBestSize/2,captureMouse/1,center/1,center/2,centerOnParent/1, + centerOnParent/2,centre/1,centre/2,centreOnParent/1,centreOnParent/2, + clearBackground/1,clientToScreen/2,clientToScreen/3,close/1,close/2, + connect/2,connect/3,convertDialogToPixels/2,convertPixelsToDialog/2, + destroyChildren/1,disable/1,disconnect/1,disconnect/2,disconnect/3, + enable/1,enable/2,findWindow/2,fit/1,fitInside/1,freeze/1,getAcceleratorTable/1, + getBackgroundColour/1,getBackgroundStyle/1,getBestSize/1,getCaret/1, + getCharHeight/1,getCharWidth/1,getChildren/1,getClientSize/1,getContainingSizer/1, + getCursor/1,getDropTarget/1,getEventHandler/1,getExtraStyle/1,getFont/1, + getForegroundColour/1,getGrandParent/1,getHandle/1,getHelpText/1, + getId/1,getLabel/1,getMaxSize/1,getMinSize/1,getName/1,getParent/1, + getPosition/1,getRect/1,getScreenPosition/1,getScreenRect/1,getScrollPos/2, + getScrollRange/2,getScrollThumb/2,getSize/1,getSizer/1,getTextExtent/2, + getTextExtent/3,getToolTip/1,getUpdateRegion/1,getVirtualSize/1,getWindowStyleFlag/1, + getWindowVariant/1,hasCapture/1,hasScrollbar/2,hasTransparentBackground/1, + hide/1,inheritAttributes/1,initDialog/1,invalidateBestSize/1,isEnabled/1, + isExposed/2,isExposed/3,isExposed/5,isRetained/1,isShown/1,isTopLevel/1, + layout/1,lineDown/1,lineUp/1,lower/1,makeModal/1,makeModal/2,move/2, + move/3,move/4,moveAfterInTabOrder/2,moveBeforeInTabOrder/2,navigate/1, + navigate/2,pageDown/1,pageUp/1,parent_class/1,popEventHandler/1,popEventHandler/2, + popupMenu/2,popupMenu/3,popupMenu/4,position/3,raise/1,refresh/1,refresh/2, + refreshRect/2,refreshRect/3,releaseMouse/1,removeChild/2,reparent/2, + screenToClient/1,screenToClient/2,scrollLines/2,scrollPages/2,scrollWindow/3, + scrollWindow/4,setAcceleratorTable/2,setAutoLayout/2,setBackgroundColour/2, + setBackgroundStyle/2,setCaret/2,setClientSize/2,setClientSize/3,setContainingSizer/2, + setCursor/2,setDropTarget/2,setExtraStyle/2,setFocus/1,setFocusFromKbd/1, + setFont/2,setForegroundColour/2,setHelpText/2,setId/2,setLabel/2,setMaxSize/2, + setMinSize/2,setName/2,setOwnBackgroundColour/2,setOwnFont/2,setOwnForegroundColour/2, + setPalette/2,setScrollPos/3,setScrollPos/4,setScrollbar/5,setScrollbar/6, + setSize/2,setSize/3,setSize/5,setSize/6,setSizeHints/2,setSizeHints/3, + setSizeHints/4,setSizer/2,setSizer/3,setSizerAndFit/2,setSizerAndFit/3, + setThemeEnabled/2,setToolTip/2,setVirtualSize/2,setVirtualSize/3, + setVirtualSizeHints/2,setVirtualSizeHints/3,setVirtualSizeHints/4, + setWindowStyle/2,setWindowStyleFlag/2,setWindowVariant/2,shouldInheritColours/1, + show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1, + update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]). + +-export_type([wxPopupTransientWindow/0]). +%% @hidden +parent_class(wxPopupWindow) -> true; +parent_class(wxWindow) -> true; +parent_class(wxEvtHandler) -> true; +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxPopupTransientWindow() :: wx:wx_object(). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopuptransientwindow.html#wxpopuptransientwindowwxpopuptransientwindow">external documentation</a>. +-spec new() -> wxPopupTransientWindow(). +new() -> + wxe_util:construct(?wxPopupTransientWindow_new_0, + <<>>). + +%% @equiv new(Parent, []) +-spec new(Parent) -> wxPopupTransientWindow() when + Parent::wxWindow:wxWindow(). + +new(Parent) + when is_record(Parent, wx_ref) -> + new(Parent, []). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopuptransientwindow.html#wxpopuptransientwindowwxpopuptransientwindow">external documentation</a>. +-spec new(Parent, [Option]) -> wxPopupTransientWindow() when + Parent::wxWindow:wxWindow(), + Option :: {style, integer()}. +new(#wx_ref{type=ParentT,ref=ParentRef}, Options) + when is_list(Options) -> + ?CLASS(ParentT,wxWindow), + MOpts = fun({style, Style}, Acc) -> [<<1:32/?UI,Style:32/?UI>>|Acc]; + (BadOpt, _) -> erlang:error({badoption, BadOpt}) end, + BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)), + wxe_util:construct(?wxPopupTransientWindow_new_2, + <<ParentRef:32/?UI, 0:32,BinOpt/binary>>). + +%% @equiv popup(This, []) +-spec popup(This) -> ok when + This::wxPopupTransientWindow(). + +popup(This) + when is_record(This, wx_ref) -> + popup(This, []). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopuptransientwindow.html#wxpopuptransientwindowpopup">external documentation</a>. +-spec popup(This, [Option]) -> ok when + This::wxPopupTransientWindow(), + Option :: {focus, wxWindow:wxWindow()}. +popup(#wx_ref{type=ThisT,ref=ThisRef}, Options) + when is_list(Options) -> + ?CLASS(ThisT,wxPopupTransientWindow), + MOpts = fun({focus, #wx_ref{type=FocusT,ref=FocusRef}}, Acc) -> ?CLASS(FocusT,wxWindow),[<<1:32/?UI,FocusRef:32/?UI>>|Acc]; + (BadOpt, _) -> erlang:error({badoption, BadOpt}) end, + BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)), + wxe_util:cast(?wxPopupTransientWindow_Popup, + <<ThisRef:32/?UI, 0:32,BinOpt/binary>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopuptransientwindow.html#wxpopuptransientwindowdismiss">external documentation</a>. +-spec dismiss(This) -> ok when + This::wxPopupTransientWindow(). +dismiss(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxPopupTransientWindow), + wxe_util:cast(?wxPopupTransientWindow_Dismiss, + <<ThisRef:32/?UI>>). + +%% @doc Destroys this object, do not use object again +-spec destroy(This::wxPopupTransientWindow()) -> ok. +destroy(Obj=#wx_ref{type=Type}) -> + ?CLASS(Type,wxPopupTransientWindow), + wxe_util:destroy(?DESTROY_OBJECT,Obj), + ok. + %% From wxPopupWindow +%% @hidden +position(This,PtOrigin,Size) -> wxPopupWindow:position(This,PtOrigin,Size). + %% From wxWindow +%% @hidden +warpPointer(This,X,Y) -> wxWindow:warpPointer(This,X,Y). +%% @hidden +validate(This) -> wxWindow:validate(This). +%% @hidden +updateWindowUI(This, Options) -> wxWindow:updateWindowUI(This, Options). +%% @hidden +updateWindowUI(This) -> wxWindow:updateWindowUI(This). +%% @hidden +update(This) -> wxWindow:update(This). +%% @hidden +transferDataToWindow(This) -> wxWindow:transferDataToWindow(This). +%% @hidden +transferDataFromWindow(This) -> wxWindow:transferDataFromWindow(This). +%% @hidden +thaw(This) -> wxWindow:thaw(This). +%% @hidden +show(This, Options) -> wxWindow:show(This, Options). +%% @hidden +show(This) -> wxWindow:show(This). +%% @hidden +shouldInheritColours(This) -> wxWindow:shouldInheritColours(This). +%% @hidden +setWindowVariant(This,Variant) -> wxWindow:setWindowVariant(This,Variant). +%% @hidden +setWindowStyleFlag(This,Style) -> wxWindow:setWindowStyleFlag(This,Style). +%% @hidden +setWindowStyle(This,Style) -> wxWindow:setWindowStyle(This,Style). +%% @hidden +setVirtualSizeHints(This,MinW,MinH, Options) -> wxWindow:setVirtualSizeHints(This,MinW,MinH, Options). +%% @hidden +setVirtualSizeHints(This,MinW,MinH) -> wxWindow:setVirtualSizeHints(This,MinW,MinH). +%% @hidden +setVirtualSizeHints(This,MinSize) -> wxWindow:setVirtualSizeHints(This,MinSize). +%% @hidden +setVirtualSize(This,X,Y) -> wxWindow:setVirtualSize(This,X,Y). +%% @hidden +setVirtualSize(This,Size) -> wxWindow:setVirtualSize(This,Size). +%% @hidden +setToolTip(This,Tip) -> wxWindow:setToolTip(This,Tip). +%% @hidden +setThemeEnabled(This,EnableTheme) -> wxWindow:setThemeEnabled(This,EnableTheme). +%% @hidden +setSizerAndFit(This,Sizer, Options) -> wxWindow:setSizerAndFit(This,Sizer, Options). +%% @hidden +setSizerAndFit(This,Sizer) -> wxWindow:setSizerAndFit(This,Sizer). +%% @hidden +setSizer(This,Sizer, Options) -> wxWindow:setSizer(This,Sizer, Options). +%% @hidden +setSizer(This,Sizer) -> wxWindow:setSizer(This,Sizer). +%% @hidden +setSizeHints(This,MinW,MinH, Options) -> wxWindow:setSizeHints(This,MinW,MinH, Options). +%% @hidden +setSizeHints(This,MinW,MinH) -> wxWindow:setSizeHints(This,MinW,MinH). +%% @hidden +setSizeHints(This,MinSize) -> wxWindow:setSizeHints(This,MinSize). +%% @hidden +setSize(This,X,Y,Width,Height, Options) -> wxWindow:setSize(This,X,Y,Width,Height, Options). +%% @hidden +setSize(This,X,Y,Width,Height) -> wxWindow:setSize(This,X,Y,Width,Height). +%% @hidden +setSize(This,Width,Height) -> wxWindow:setSize(This,Width,Height). +%% @hidden +setSize(This,Rect) -> wxWindow:setSize(This,Rect). +%% @hidden +setScrollPos(This,Orient,Pos, Options) -> wxWindow:setScrollPos(This,Orient,Pos, Options). +%% @hidden +setScrollPos(This,Orient,Pos) -> wxWindow:setScrollPos(This,Orient,Pos). +%% @hidden +setScrollbar(This,Orient,Pos,ThumbVisible,Range, Options) -> wxWindow:setScrollbar(This,Orient,Pos,ThumbVisible,Range, Options). +%% @hidden +setScrollbar(This,Orient,Pos,ThumbVisible,Range) -> wxWindow:setScrollbar(This,Orient,Pos,ThumbVisible,Range). +%% @hidden +setPalette(This,Pal) -> wxWindow:setPalette(This,Pal). +%% @hidden +setName(This,Name) -> wxWindow:setName(This,Name). +%% @hidden +setLabel(This,Label) -> wxWindow:setLabel(This,Label). +%% @hidden +setId(This,Winid) -> wxWindow:setId(This,Winid). +%% @hidden +setHelpText(This,Text) -> wxWindow:setHelpText(This,Text). +%% @hidden +setForegroundColour(This,Colour) -> wxWindow:setForegroundColour(This,Colour). +%% @hidden +setFont(This,Font) -> wxWindow:setFont(This,Font). +%% @hidden +setFocusFromKbd(This) -> wxWindow:setFocusFromKbd(This). +%% @hidden +setFocus(This) -> wxWindow:setFocus(This). +%% @hidden +setExtraStyle(This,ExStyle) -> wxWindow:setExtraStyle(This,ExStyle). +%% @hidden +setDropTarget(This,DropTarget) -> wxWindow:setDropTarget(This,DropTarget). +%% @hidden +setOwnForegroundColour(This,Colour) -> wxWindow:setOwnForegroundColour(This,Colour). +%% @hidden +setOwnFont(This,Font) -> wxWindow:setOwnFont(This,Font). +%% @hidden +setOwnBackgroundColour(This,Colour) -> wxWindow:setOwnBackgroundColour(This,Colour). +%% @hidden +setMinSize(This,MinSize) -> wxWindow:setMinSize(This,MinSize). +%% @hidden +setMaxSize(This,MaxSize) -> wxWindow:setMaxSize(This,MaxSize). +%% @hidden +setCursor(This,Cursor) -> wxWindow:setCursor(This,Cursor). +%% @hidden +setContainingSizer(This,Sizer) -> wxWindow:setContainingSizer(This,Sizer). +%% @hidden +setClientSize(This,Width,Height) -> wxWindow:setClientSize(This,Width,Height). +%% @hidden +setClientSize(This,Size) -> wxWindow:setClientSize(This,Size). +%% @hidden +setCaret(This,Caret) -> wxWindow:setCaret(This,Caret). +%% @hidden +setBackgroundStyle(This,Style) -> wxWindow:setBackgroundStyle(This,Style). +%% @hidden +setBackgroundColour(This,Colour) -> wxWindow:setBackgroundColour(This,Colour). +%% @hidden +setAutoLayout(This,AutoLayout) -> wxWindow:setAutoLayout(This,AutoLayout). +%% @hidden +setAcceleratorTable(This,Accel) -> wxWindow:setAcceleratorTable(This,Accel). +%% @hidden +scrollWindow(This,Dx,Dy, Options) -> wxWindow:scrollWindow(This,Dx,Dy, Options). +%% @hidden +scrollWindow(This,Dx,Dy) -> wxWindow:scrollWindow(This,Dx,Dy). +%% @hidden +scrollPages(This,Pages) -> wxWindow:scrollPages(This,Pages). +%% @hidden +scrollLines(This,Lines) -> wxWindow:scrollLines(This,Lines). +%% @hidden +screenToClient(This,Pt) -> wxWindow:screenToClient(This,Pt). +%% @hidden +screenToClient(This) -> wxWindow:screenToClient(This). +%% @hidden +reparent(This,NewParent) -> wxWindow:reparent(This,NewParent). +%% @hidden +removeChild(This,Child) -> wxWindow:removeChild(This,Child). +%% @hidden +releaseMouse(This) -> wxWindow:releaseMouse(This). +%% @hidden +refreshRect(This,Rect, Options) -> wxWindow:refreshRect(This,Rect, Options). +%% @hidden +refreshRect(This,Rect) -> wxWindow:refreshRect(This,Rect). +%% @hidden +refresh(This, Options) -> wxWindow:refresh(This, Options). +%% @hidden +refresh(This) -> wxWindow:refresh(This). +%% @hidden +raise(This) -> wxWindow:raise(This). +%% @hidden +popupMenu(This,Menu,X,Y) -> wxWindow:popupMenu(This,Menu,X,Y). +%% @hidden +popupMenu(This,Menu, Options) -> wxWindow:popupMenu(This,Menu, Options). +%% @hidden +popupMenu(This,Menu) -> wxWindow:popupMenu(This,Menu). +%% @hidden +popEventHandler(This, Options) -> wxWindow:popEventHandler(This, Options). +%% @hidden +popEventHandler(This) -> wxWindow:popEventHandler(This). +%% @hidden +pageUp(This) -> wxWindow:pageUp(This). +%% @hidden +pageDown(This) -> wxWindow:pageDown(This). +%% @hidden +navigate(This, Options) -> wxWindow:navigate(This, Options). +%% @hidden +navigate(This) -> wxWindow:navigate(This). +%% @hidden +moveBeforeInTabOrder(This,Win) -> wxWindow:moveBeforeInTabOrder(This,Win). +%% @hidden +moveAfterInTabOrder(This,Win) -> wxWindow:moveAfterInTabOrder(This,Win). +%% @hidden +move(This,X,Y, Options) -> wxWindow:move(This,X,Y, Options). +%% @hidden +move(This,X,Y) -> wxWindow:move(This,X,Y). +%% @hidden +move(This,Pt) -> wxWindow:move(This,Pt). +%% @hidden +makeModal(This, Options) -> wxWindow:makeModal(This, Options). +%% @hidden +makeModal(This) -> wxWindow:makeModal(This). +%% @hidden +lower(This) -> wxWindow:lower(This). +%% @hidden +lineUp(This) -> wxWindow:lineUp(This). +%% @hidden +lineDown(This) -> wxWindow:lineDown(This). +%% @hidden +layout(This) -> wxWindow:layout(This). +%% @hidden +isTopLevel(This) -> wxWindow:isTopLevel(This). +%% @hidden +isShown(This) -> wxWindow:isShown(This). +%% @hidden +isRetained(This) -> wxWindow:isRetained(This). +%% @hidden +isExposed(This,X,Y,W,H) -> wxWindow:isExposed(This,X,Y,W,H). +%% @hidden +isExposed(This,X,Y) -> wxWindow:isExposed(This,X,Y). +%% @hidden +isExposed(This,Pt) -> wxWindow:isExposed(This,Pt). +%% @hidden +isEnabled(This) -> wxWindow:isEnabled(This). +%% @hidden +invalidateBestSize(This) -> wxWindow:invalidateBestSize(This). +%% @hidden +initDialog(This) -> wxWindow:initDialog(This). +%% @hidden +inheritAttributes(This) -> wxWindow:inheritAttributes(This). +%% @hidden +hide(This) -> wxWindow:hide(This). +%% @hidden +hasTransparentBackground(This) -> wxWindow:hasTransparentBackground(This). +%% @hidden +hasScrollbar(This,Orient) -> wxWindow:hasScrollbar(This,Orient). +%% @hidden +hasCapture(This) -> wxWindow:hasCapture(This). +%% @hidden +getWindowVariant(This) -> wxWindow:getWindowVariant(This). +%% @hidden +getWindowStyleFlag(This) -> wxWindow:getWindowStyleFlag(This). +%% @hidden +getVirtualSize(This) -> wxWindow:getVirtualSize(This). +%% @hidden +getUpdateRegion(This) -> wxWindow:getUpdateRegion(This). +%% @hidden +getToolTip(This) -> wxWindow:getToolTip(This). +%% @hidden +getTextExtent(This,String, Options) -> wxWindow:getTextExtent(This,String, Options). +%% @hidden +getTextExtent(This,String) -> wxWindow:getTextExtent(This,String). +%% @hidden +getSizer(This) -> wxWindow:getSizer(This). +%% @hidden +getSize(This) -> wxWindow:getSize(This). +%% @hidden +getScrollThumb(This,Orient) -> wxWindow:getScrollThumb(This,Orient). +%% @hidden +getScrollRange(This,Orient) -> wxWindow:getScrollRange(This,Orient). +%% @hidden +getScrollPos(This,Orient) -> wxWindow:getScrollPos(This,Orient). +%% @hidden +getScreenRect(This) -> wxWindow:getScreenRect(This). +%% @hidden +getScreenPosition(This) -> wxWindow:getScreenPosition(This). +%% @hidden +getRect(This) -> wxWindow:getRect(This). +%% @hidden +getPosition(This) -> wxWindow:getPosition(This). +%% @hidden +getParent(This) -> wxWindow:getParent(This). +%% @hidden +getName(This) -> wxWindow:getName(This). +%% @hidden +getMinSize(This) -> wxWindow:getMinSize(This). +%% @hidden +getMaxSize(This) -> wxWindow:getMaxSize(This). +%% @hidden +getLabel(This) -> wxWindow:getLabel(This). +%% @hidden +getId(This) -> wxWindow:getId(This). +%% @hidden +getHelpText(This) -> wxWindow:getHelpText(This). +%% @hidden +getHandle(This) -> wxWindow:getHandle(This). +%% @hidden +getGrandParent(This) -> wxWindow:getGrandParent(This). +%% @hidden +getForegroundColour(This) -> wxWindow:getForegroundColour(This). +%% @hidden +getFont(This) -> wxWindow:getFont(This). +%% @hidden +getExtraStyle(This) -> wxWindow:getExtraStyle(This). +%% @hidden +getEventHandler(This) -> wxWindow:getEventHandler(This). +%% @hidden +getDropTarget(This) -> wxWindow:getDropTarget(This). +%% @hidden +getCursor(This) -> wxWindow:getCursor(This). +%% @hidden +getContainingSizer(This) -> wxWindow:getContainingSizer(This). +%% @hidden +getClientSize(This) -> wxWindow:getClientSize(This). +%% @hidden +getChildren(This) -> wxWindow:getChildren(This). +%% @hidden +getCharWidth(This) -> wxWindow:getCharWidth(This). +%% @hidden +getCharHeight(This) -> wxWindow:getCharHeight(This). +%% @hidden +getCaret(This) -> wxWindow:getCaret(This). +%% @hidden +getBestSize(This) -> wxWindow:getBestSize(This). +%% @hidden +getBackgroundStyle(This) -> wxWindow:getBackgroundStyle(This). +%% @hidden +getBackgroundColour(This) -> wxWindow:getBackgroundColour(This). +%% @hidden +getAcceleratorTable(This) -> wxWindow:getAcceleratorTable(This). +%% @hidden +freeze(This) -> wxWindow:freeze(This). +%% @hidden +fitInside(This) -> wxWindow:fitInside(This). +%% @hidden +fit(This) -> wxWindow:fit(This). +%% @hidden +findWindow(This,Winid) -> wxWindow:findWindow(This,Winid). +%% @hidden +enable(This, Options) -> wxWindow:enable(This, Options). +%% @hidden +enable(This) -> wxWindow:enable(This). +%% @hidden +disable(This) -> wxWindow:disable(This). +%% @hidden +destroyChildren(This) -> wxWindow:destroyChildren(This). +%% @hidden +convertPixelsToDialog(This,Sz) -> wxWindow:convertPixelsToDialog(This,Sz). +%% @hidden +convertDialogToPixels(This,Sz) -> wxWindow:convertDialogToPixels(This,Sz). +%% @hidden +close(This, Options) -> wxWindow:close(This, Options). +%% @hidden +close(This) -> wxWindow:close(This). +%% @hidden +clientToScreen(This,X,Y) -> wxWindow:clientToScreen(This,X,Y). +%% @hidden +clientToScreen(This,Pt) -> wxWindow:clientToScreen(This,Pt). +%% @hidden +clearBackground(This) -> wxWindow:clearBackground(This). +%% @hidden +centreOnParent(This, Options) -> wxWindow:centreOnParent(This, Options). +%% @hidden +centreOnParent(This) -> wxWindow:centreOnParent(This). +%% @hidden +centre(This, Options) -> wxWindow:centre(This, Options). +%% @hidden +centre(This) -> wxWindow:centre(This). +%% @hidden +centerOnParent(This, Options) -> wxWindow:centerOnParent(This, Options). +%% @hidden +centerOnParent(This) -> wxWindow:centerOnParent(This). +%% @hidden +center(This, Options) -> wxWindow:center(This, Options). +%% @hidden +center(This) -> wxWindow:center(This). +%% @hidden +captureMouse(This) -> wxWindow:captureMouse(This). +%% @hidden +cacheBestSize(This,Size) -> wxWindow:cacheBestSize(This,Size). + %% From wxEvtHandler +%% @hidden +disconnect(This,EventType, Options) -> wxEvtHandler:disconnect(This,EventType, Options). +%% @hidden +disconnect(This,EventType) -> wxEvtHandler:disconnect(This,EventType). +%% @hidden +disconnect(This) -> wxEvtHandler:disconnect(This). +%% @hidden +connect(This,EventType, Options) -> wxEvtHandler:connect(This,EventType, Options). +%% @hidden +connect(This,EventType) -> wxEvtHandler:connect(This,EventType). diff --git a/lib/wx/src/gen/wxPopupWindow.erl b/lib/wx/src/gen/wxPopupWindow.erl new file mode 100644 index 0000000000..415185d574 --- /dev/null +++ b/lib/wx/src/gen/wxPopupWindow.erl @@ -0,0 +1,503 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2014. 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% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopupwindow.html">wxPopupWindow</a>. +%% <p>This class is derived (and can use functions) from: +%% <br />{@link wxWindow} +%% <br />{@link wxEvtHandler} +%% </p> +%% @type wxPopupWindow(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxPopupWindow). +-include("wxe.hrl"). +-export([create/2,create/3,destroy/1,new/0,new/1,new/2,position/3]). + +%% inherited exports +-export([cacheBestSize/2,captureMouse/1,center/1,center/2,centerOnParent/1, + centerOnParent/2,centre/1,centre/2,centreOnParent/1,centreOnParent/2, + clearBackground/1,clientToScreen/2,clientToScreen/3,close/1,close/2, + connect/2,connect/3,convertDialogToPixels/2,convertPixelsToDialog/2, + destroyChildren/1,disable/1,disconnect/1,disconnect/2,disconnect/3, + enable/1,enable/2,findWindow/2,fit/1,fitInside/1,freeze/1,getAcceleratorTable/1, + getBackgroundColour/1,getBackgroundStyle/1,getBestSize/1,getCaret/1, + getCharHeight/1,getCharWidth/1,getChildren/1,getClientSize/1,getContainingSizer/1, + getCursor/1,getDropTarget/1,getEventHandler/1,getExtraStyle/1,getFont/1, + getForegroundColour/1,getGrandParent/1,getHandle/1,getHelpText/1, + getId/1,getLabel/1,getMaxSize/1,getMinSize/1,getName/1,getParent/1, + getPosition/1,getRect/1,getScreenPosition/1,getScreenRect/1,getScrollPos/2, + getScrollRange/2,getScrollThumb/2,getSize/1,getSizer/1,getTextExtent/2, + getTextExtent/3,getToolTip/1,getUpdateRegion/1,getVirtualSize/1,getWindowStyleFlag/1, + getWindowVariant/1,hasCapture/1,hasScrollbar/2,hasTransparentBackground/1, + hide/1,inheritAttributes/1,initDialog/1,invalidateBestSize/1,isEnabled/1, + isExposed/2,isExposed/3,isExposed/5,isRetained/1,isShown/1,isTopLevel/1, + layout/1,lineDown/1,lineUp/1,lower/1,makeModal/1,makeModal/2,move/2, + move/3,move/4,moveAfterInTabOrder/2,moveBeforeInTabOrder/2,navigate/1, + navigate/2,pageDown/1,pageUp/1,parent_class/1,popEventHandler/1,popEventHandler/2, + popupMenu/2,popupMenu/3,popupMenu/4,raise/1,refresh/1,refresh/2,refreshRect/2, + refreshRect/3,releaseMouse/1,removeChild/2,reparent/2,screenToClient/1, + screenToClient/2,scrollLines/2,scrollPages/2,scrollWindow/3,scrollWindow/4, + setAcceleratorTable/2,setAutoLayout/2,setBackgroundColour/2,setBackgroundStyle/2, + setCaret/2,setClientSize/2,setClientSize/3,setContainingSizer/2,setCursor/2, + setDropTarget/2,setExtraStyle/2,setFocus/1,setFocusFromKbd/1,setFont/2, + setForegroundColour/2,setHelpText/2,setId/2,setLabel/2,setMaxSize/2, + setMinSize/2,setName/2,setOwnBackgroundColour/2,setOwnFont/2,setOwnForegroundColour/2, + setPalette/2,setScrollPos/3,setScrollPos/4,setScrollbar/5,setScrollbar/6, + setSize/2,setSize/3,setSize/5,setSize/6,setSizeHints/2,setSizeHints/3, + setSizeHints/4,setSizer/2,setSizer/3,setSizerAndFit/2,setSizerAndFit/3, + setThemeEnabled/2,setToolTip/2,setVirtualSize/2,setVirtualSize/3, + setVirtualSizeHints/2,setVirtualSizeHints/3,setVirtualSizeHints/4, + setWindowStyle/2,setWindowStyleFlag/2,setWindowVariant/2,shouldInheritColours/1, + show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1, + update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]). + +-export_type([wxPopupWindow/0]). +%% @hidden +parent_class(wxWindow) -> true; +parent_class(wxEvtHandler) -> true; +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxPopupWindow() :: wx:wx_object(). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopupwindow.html#wxpopupwindowwxpopupwindow">external documentation</a>. +-spec new() -> wxPopupWindow(). +new() -> + wxe_util:construct(?wxPopupWindow_new_0, + <<>>). + +%% @equiv new(Parent, []) +-spec new(Parent) -> wxPopupWindow() when + Parent::wxWindow:wxWindow(). + +new(Parent) + when is_record(Parent, wx_ref) -> + new(Parent, []). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopupwindow.html#wxpopupwindowwxpopupwindow">external documentation</a>. +-spec new(Parent, [Option]) -> wxPopupWindow() when + Parent::wxWindow:wxWindow(), + Option :: {flags, integer()}. +new(#wx_ref{type=ParentT,ref=ParentRef}, Options) + when is_list(Options) -> + ?CLASS(ParentT,wxWindow), + MOpts = fun({flags, Flags}, Acc) -> [<<1:32/?UI,Flags:32/?UI>>|Acc]; + (BadOpt, _) -> erlang:error({badoption, BadOpt}) end, + BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)), + wxe_util:construct(?wxPopupWindow_new_2, + <<ParentRef:32/?UI, 0:32,BinOpt/binary>>). + +%% @equiv create(This,Parent, []) +-spec create(This, Parent) -> boolean() when + This::wxPopupWindow(), Parent::wxWindow:wxWindow(). + +create(This,Parent) + when is_record(This, wx_ref),is_record(Parent, wx_ref) -> + create(This,Parent, []). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopupwindow.html#wxpopupwindowcreate">external documentation</a>. +-spec create(This, Parent, [Option]) -> boolean() when + This::wxPopupWindow(), Parent::wxWindow:wxWindow(), + Option :: {flags, integer()}. +create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options) + when is_list(Options) -> + ?CLASS(ThisT,wxPopupWindow), + ?CLASS(ParentT,wxWindow), + MOpts = fun({flags, Flags}, Acc) -> [<<1:32/?UI,Flags:32/?UI>>|Acc]; + (BadOpt, _) -> erlang:error({badoption, BadOpt}) end, + BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)), + wxe_util:call(?wxPopupWindow_Create, + <<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxpopupwindow.html#wxpopupwindowposition">external documentation</a>. +-spec position(This, PtOrigin, Size) -> ok when + This::wxPopupWindow(), PtOrigin::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}. +position(#wx_ref{type=ThisT,ref=ThisRef},{PtOriginX,PtOriginY},{SizeW,SizeH}) + when is_integer(PtOriginX),is_integer(PtOriginY),is_integer(SizeW),is_integer(SizeH) -> + ?CLASS(ThisT,wxPopupWindow), + wxe_util:cast(?wxPopupWindow_Position, + <<ThisRef:32/?UI,PtOriginX:32/?UI,PtOriginY:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>). + +%% @doc Destroys this object, do not use object again +-spec destroy(This::wxPopupWindow()) -> ok. +destroy(Obj=#wx_ref{type=Type}) -> + ?CLASS(Type,wxPopupWindow), + wxe_util:destroy(?DESTROY_OBJECT,Obj), + ok. + %% From wxWindow +%% @hidden +warpPointer(This,X,Y) -> wxWindow:warpPointer(This,X,Y). +%% @hidden +validate(This) -> wxWindow:validate(This). +%% @hidden +updateWindowUI(This, Options) -> wxWindow:updateWindowUI(This, Options). +%% @hidden +updateWindowUI(This) -> wxWindow:updateWindowUI(This). +%% @hidden +update(This) -> wxWindow:update(This). +%% @hidden +transferDataToWindow(This) -> wxWindow:transferDataToWindow(This). +%% @hidden +transferDataFromWindow(This) -> wxWindow:transferDataFromWindow(This). +%% @hidden +thaw(This) -> wxWindow:thaw(This). +%% @hidden +show(This, Options) -> wxWindow:show(This, Options). +%% @hidden +show(This) -> wxWindow:show(This). +%% @hidden +shouldInheritColours(This) -> wxWindow:shouldInheritColours(This). +%% @hidden +setWindowVariant(This,Variant) -> wxWindow:setWindowVariant(This,Variant). +%% @hidden +setWindowStyleFlag(This,Style) -> wxWindow:setWindowStyleFlag(This,Style). +%% @hidden +setWindowStyle(This,Style) -> wxWindow:setWindowStyle(This,Style). +%% @hidden +setVirtualSizeHints(This,MinW,MinH, Options) -> wxWindow:setVirtualSizeHints(This,MinW,MinH, Options). +%% @hidden +setVirtualSizeHints(This,MinW,MinH) -> wxWindow:setVirtualSizeHints(This,MinW,MinH). +%% @hidden +setVirtualSizeHints(This,MinSize) -> wxWindow:setVirtualSizeHints(This,MinSize). +%% @hidden +setVirtualSize(This,X,Y) -> wxWindow:setVirtualSize(This,X,Y). +%% @hidden +setVirtualSize(This,Size) -> wxWindow:setVirtualSize(This,Size). +%% @hidden +setToolTip(This,Tip) -> wxWindow:setToolTip(This,Tip). +%% @hidden +setThemeEnabled(This,EnableTheme) -> wxWindow:setThemeEnabled(This,EnableTheme). +%% @hidden +setSizerAndFit(This,Sizer, Options) -> wxWindow:setSizerAndFit(This,Sizer, Options). +%% @hidden +setSizerAndFit(This,Sizer) -> wxWindow:setSizerAndFit(This,Sizer). +%% @hidden +setSizer(This,Sizer, Options) -> wxWindow:setSizer(This,Sizer, Options). +%% @hidden +setSizer(This,Sizer) -> wxWindow:setSizer(This,Sizer). +%% @hidden +setSizeHints(This,MinW,MinH, Options) -> wxWindow:setSizeHints(This,MinW,MinH, Options). +%% @hidden +setSizeHints(This,MinW,MinH) -> wxWindow:setSizeHints(This,MinW,MinH). +%% @hidden +setSizeHints(This,MinSize) -> wxWindow:setSizeHints(This,MinSize). +%% @hidden +setSize(This,X,Y,Width,Height, Options) -> wxWindow:setSize(This,X,Y,Width,Height, Options). +%% @hidden +setSize(This,X,Y,Width,Height) -> wxWindow:setSize(This,X,Y,Width,Height). +%% @hidden +setSize(This,Width,Height) -> wxWindow:setSize(This,Width,Height). +%% @hidden +setSize(This,Rect) -> wxWindow:setSize(This,Rect). +%% @hidden +setScrollPos(This,Orient,Pos, Options) -> wxWindow:setScrollPos(This,Orient,Pos, Options). +%% @hidden +setScrollPos(This,Orient,Pos) -> wxWindow:setScrollPos(This,Orient,Pos). +%% @hidden +setScrollbar(This,Orient,Pos,ThumbVisible,Range, Options) -> wxWindow:setScrollbar(This,Orient,Pos,ThumbVisible,Range, Options). +%% @hidden +setScrollbar(This,Orient,Pos,ThumbVisible,Range) -> wxWindow:setScrollbar(This,Orient,Pos,ThumbVisible,Range). +%% @hidden +setPalette(This,Pal) -> wxWindow:setPalette(This,Pal). +%% @hidden +setName(This,Name) -> wxWindow:setName(This,Name). +%% @hidden +setLabel(This,Label) -> wxWindow:setLabel(This,Label). +%% @hidden +setId(This,Winid) -> wxWindow:setId(This,Winid). +%% @hidden +setHelpText(This,Text) -> wxWindow:setHelpText(This,Text). +%% @hidden +setForegroundColour(This,Colour) -> wxWindow:setForegroundColour(This,Colour). +%% @hidden +setFont(This,Font) -> wxWindow:setFont(This,Font). +%% @hidden +setFocusFromKbd(This) -> wxWindow:setFocusFromKbd(This). +%% @hidden +setFocus(This) -> wxWindow:setFocus(This). +%% @hidden +setExtraStyle(This,ExStyle) -> wxWindow:setExtraStyle(This,ExStyle). +%% @hidden +setDropTarget(This,DropTarget) -> wxWindow:setDropTarget(This,DropTarget). +%% @hidden +setOwnForegroundColour(This,Colour) -> wxWindow:setOwnForegroundColour(This,Colour). +%% @hidden +setOwnFont(This,Font) -> wxWindow:setOwnFont(This,Font). +%% @hidden +setOwnBackgroundColour(This,Colour) -> wxWindow:setOwnBackgroundColour(This,Colour). +%% @hidden +setMinSize(This,MinSize) -> wxWindow:setMinSize(This,MinSize). +%% @hidden +setMaxSize(This,MaxSize) -> wxWindow:setMaxSize(This,MaxSize). +%% @hidden +setCursor(This,Cursor) -> wxWindow:setCursor(This,Cursor). +%% @hidden +setContainingSizer(This,Sizer) -> wxWindow:setContainingSizer(This,Sizer). +%% @hidden +setClientSize(This,Width,Height) -> wxWindow:setClientSize(This,Width,Height). +%% @hidden +setClientSize(This,Size) -> wxWindow:setClientSize(This,Size). +%% @hidden +setCaret(This,Caret) -> wxWindow:setCaret(This,Caret). +%% @hidden +setBackgroundStyle(This,Style) -> wxWindow:setBackgroundStyle(This,Style). +%% @hidden +setBackgroundColour(This,Colour) -> wxWindow:setBackgroundColour(This,Colour). +%% @hidden +setAutoLayout(This,AutoLayout) -> wxWindow:setAutoLayout(This,AutoLayout). +%% @hidden +setAcceleratorTable(This,Accel) -> wxWindow:setAcceleratorTable(This,Accel). +%% @hidden +scrollWindow(This,Dx,Dy, Options) -> wxWindow:scrollWindow(This,Dx,Dy, Options). +%% @hidden +scrollWindow(This,Dx,Dy) -> wxWindow:scrollWindow(This,Dx,Dy). +%% @hidden +scrollPages(This,Pages) -> wxWindow:scrollPages(This,Pages). +%% @hidden +scrollLines(This,Lines) -> wxWindow:scrollLines(This,Lines). +%% @hidden +screenToClient(This,Pt) -> wxWindow:screenToClient(This,Pt). +%% @hidden +screenToClient(This) -> wxWindow:screenToClient(This). +%% @hidden +reparent(This,NewParent) -> wxWindow:reparent(This,NewParent). +%% @hidden +removeChild(This,Child) -> wxWindow:removeChild(This,Child). +%% @hidden +releaseMouse(This) -> wxWindow:releaseMouse(This). +%% @hidden +refreshRect(This,Rect, Options) -> wxWindow:refreshRect(This,Rect, Options). +%% @hidden +refreshRect(This,Rect) -> wxWindow:refreshRect(This,Rect). +%% @hidden +refresh(This, Options) -> wxWindow:refresh(This, Options). +%% @hidden +refresh(This) -> wxWindow:refresh(This). +%% @hidden +raise(This) -> wxWindow:raise(This). +%% @hidden +popupMenu(This,Menu,X,Y) -> wxWindow:popupMenu(This,Menu,X,Y). +%% @hidden +popupMenu(This,Menu, Options) -> wxWindow:popupMenu(This,Menu, Options). +%% @hidden +popupMenu(This,Menu) -> wxWindow:popupMenu(This,Menu). +%% @hidden +popEventHandler(This, Options) -> wxWindow:popEventHandler(This, Options). +%% @hidden +popEventHandler(This) -> wxWindow:popEventHandler(This). +%% @hidden +pageUp(This) -> wxWindow:pageUp(This). +%% @hidden +pageDown(This) -> wxWindow:pageDown(This). +%% @hidden +navigate(This, Options) -> wxWindow:navigate(This, Options). +%% @hidden +navigate(This) -> wxWindow:navigate(This). +%% @hidden +moveBeforeInTabOrder(This,Win) -> wxWindow:moveBeforeInTabOrder(This,Win). +%% @hidden +moveAfterInTabOrder(This,Win) -> wxWindow:moveAfterInTabOrder(This,Win). +%% @hidden +move(This,X,Y, Options) -> wxWindow:move(This,X,Y, Options). +%% @hidden +move(This,X,Y) -> wxWindow:move(This,X,Y). +%% @hidden +move(This,Pt) -> wxWindow:move(This,Pt). +%% @hidden +makeModal(This, Options) -> wxWindow:makeModal(This, Options). +%% @hidden +makeModal(This) -> wxWindow:makeModal(This). +%% @hidden +lower(This) -> wxWindow:lower(This). +%% @hidden +lineUp(This) -> wxWindow:lineUp(This). +%% @hidden +lineDown(This) -> wxWindow:lineDown(This). +%% @hidden +layout(This) -> wxWindow:layout(This). +%% @hidden +isTopLevel(This) -> wxWindow:isTopLevel(This). +%% @hidden +isShown(This) -> wxWindow:isShown(This). +%% @hidden +isRetained(This) -> wxWindow:isRetained(This). +%% @hidden +isExposed(This,X,Y,W,H) -> wxWindow:isExposed(This,X,Y,W,H). +%% @hidden +isExposed(This,X,Y) -> wxWindow:isExposed(This,X,Y). +%% @hidden +isExposed(This,Pt) -> wxWindow:isExposed(This,Pt). +%% @hidden +isEnabled(This) -> wxWindow:isEnabled(This). +%% @hidden +invalidateBestSize(This) -> wxWindow:invalidateBestSize(This). +%% @hidden +initDialog(This) -> wxWindow:initDialog(This). +%% @hidden +inheritAttributes(This) -> wxWindow:inheritAttributes(This). +%% @hidden +hide(This) -> wxWindow:hide(This). +%% @hidden +hasTransparentBackground(This) -> wxWindow:hasTransparentBackground(This). +%% @hidden +hasScrollbar(This,Orient) -> wxWindow:hasScrollbar(This,Orient). +%% @hidden +hasCapture(This) -> wxWindow:hasCapture(This). +%% @hidden +getWindowVariant(This) -> wxWindow:getWindowVariant(This). +%% @hidden +getWindowStyleFlag(This) -> wxWindow:getWindowStyleFlag(This). +%% @hidden +getVirtualSize(This) -> wxWindow:getVirtualSize(This). +%% @hidden +getUpdateRegion(This) -> wxWindow:getUpdateRegion(This). +%% @hidden +getToolTip(This) -> wxWindow:getToolTip(This). +%% @hidden +getTextExtent(This,String, Options) -> wxWindow:getTextExtent(This,String, Options). +%% @hidden +getTextExtent(This,String) -> wxWindow:getTextExtent(This,String). +%% @hidden +getSizer(This) -> wxWindow:getSizer(This). +%% @hidden +getSize(This) -> wxWindow:getSize(This). +%% @hidden +getScrollThumb(This,Orient) -> wxWindow:getScrollThumb(This,Orient). +%% @hidden +getScrollRange(This,Orient) -> wxWindow:getScrollRange(This,Orient). +%% @hidden +getScrollPos(This,Orient) -> wxWindow:getScrollPos(This,Orient). +%% @hidden +getScreenRect(This) -> wxWindow:getScreenRect(This). +%% @hidden +getScreenPosition(This) -> wxWindow:getScreenPosition(This). +%% @hidden +getRect(This) -> wxWindow:getRect(This). +%% @hidden +getPosition(This) -> wxWindow:getPosition(This). +%% @hidden +getParent(This) -> wxWindow:getParent(This). +%% @hidden +getName(This) -> wxWindow:getName(This). +%% @hidden +getMinSize(This) -> wxWindow:getMinSize(This). +%% @hidden +getMaxSize(This) -> wxWindow:getMaxSize(This). +%% @hidden +getLabel(This) -> wxWindow:getLabel(This). +%% @hidden +getId(This) -> wxWindow:getId(This). +%% @hidden +getHelpText(This) -> wxWindow:getHelpText(This). +%% @hidden +getHandle(This) -> wxWindow:getHandle(This). +%% @hidden +getGrandParent(This) -> wxWindow:getGrandParent(This). +%% @hidden +getForegroundColour(This) -> wxWindow:getForegroundColour(This). +%% @hidden +getFont(This) -> wxWindow:getFont(This). +%% @hidden +getExtraStyle(This) -> wxWindow:getExtraStyle(This). +%% @hidden +getEventHandler(This) -> wxWindow:getEventHandler(This). +%% @hidden +getDropTarget(This) -> wxWindow:getDropTarget(This). +%% @hidden +getCursor(This) -> wxWindow:getCursor(This). +%% @hidden +getContainingSizer(This) -> wxWindow:getContainingSizer(This). +%% @hidden +getClientSize(This) -> wxWindow:getClientSize(This). +%% @hidden +getChildren(This) -> wxWindow:getChildren(This). +%% @hidden +getCharWidth(This) -> wxWindow:getCharWidth(This). +%% @hidden +getCharHeight(This) -> wxWindow:getCharHeight(This). +%% @hidden +getCaret(This) -> wxWindow:getCaret(This). +%% @hidden +getBestSize(This) -> wxWindow:getBestSize(This). +%% @hidden +getBackgroundStyle(This) -> wxWindow:getBackgroundStyle(This). +%% @hidden +getBackgroundColour(This) -> wxWindow:getBackgroundColour(This). +%% @hidden +getAcceleratorTable(This) -> wxWindow:getAcceleratorTable(This). +%% @hidden +freeze(This) -> wxWindow:freeze(This). +%% @hidden +fitInside(This) -> wxWindow:fitInside(This). +%% @hidden +fit(This) -> wxWindow:fit(This). +%% @hidden +findWindow(This,Winid) -> wxWindow:findWindow(This,Winid). +%% @hidden +enable(This, Options) -> wxWindow:enable(This, Options). +%% @hidden +enable(This) -> wxWindow:enable(This). +%% @hidden +disable(This) -> wxWindow:disable(This). +%% @hidden +destroyChildren(This) -> wxWindow:destroyChildren(This). +%% @hidden +convertPixelsToDialog(This,Sz) -> wxWindow:convertPixelsToDialog(This,Sz). +%% @hidden +convertDialogToPixels(This,Sz) -> wxWindow:convertDialogToPixels(This,Sz). +%% @hidden +close(This, Options) -> wxWindow:close(This, Options). +%% @hidden +close(This) -> wxWindow:close(This). +%% @hidden +clientToScreen(This,X,Y) -> wxWindow:clientToScreen(This,X,Y). +%% @hidden +clientToScreen(This,Pt) -> wxWindow:clientToScreen(This,Pt). +%% @hidden +clearBackground(This) -> wxWindow:clearBackground(This). +%% @hidden +centreOnParent(This, Options) -> wxWindow:centreOnParent(This, Options). +%% @hidden +centreOnParent(This) -> wxWindow:centreOnParent(This). +%% @hidden +centre(This, Options) -> wxWindow:centre(This, Options). +%% @hidden +centre(This) -> wxWindow:centre(This). +%% @hidden +centerOnParent(This, Options) -> wxWindow:centerOnParent(This, Options). +%% @hidden +centerOnParent(This) -> wxWindow:centerOnParent(This). +%% @hidden +center(This, Options) -> wxWindow:center(This, Options). +%% @hidden +center(This) -> wxWindow:center(This). +%% @hidden +captureMouse(This) -> wxWindow:captureMouse(This). +%% @hidden +cacheBestSize(This,Size) -> wxWindow:cacheBestSize(This,Size). + %% From wxEvtHandler +%% @hidden +disconnect(This,EventType, Options) -> wxEvtHandler:disconnect(This,EventType, Options). +%% @hidden +disconnect(This,EventType) -> wxEvtHandler:disconnect(This,EventType). +%% @hidden +disconnect(This) -> wxEvtHandler:disconnect(This). +%% @hidden +connect(This,EventType, Options) -> wxEvtHandler:connect(This,EventType, Options). +%% @hidden +connect(This,EventType) -> wxEvtHandler:connect(This,EventType). diff --git a/lib/wx/src/gen/wxTextCtrl.erl b/lib/wx/src/gen/wxTextCtrl.erl index cb85652ceb..7e6852b9c8 100644 --- a/lib/wx/src/gen/wxTextCtrl.erl +++ b/lib/wx/src/gen/wxTextCtrl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. 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 @@ -29,8 +29,8 @@ -module(wxTextCtrl). -include("wxe.hrl"). --export([appendText/2,canCopy/1,canCut/1,canPaste/1,canRedo/1,canUndo/1,clear/1, - copy/1,create/3,create/4,cut/1,destroy/1,discardEdits/1,emulateKeyPress/2, +-export([appendText/2,canCopy/1,canCut/1,canPaste/1,canRedo/1,canUndo/1,changeValue/2, + clear/1,copy/1,create/3,create/4,cut/1,destroy/1,discardEdits/1,emulateKeyPress/2, getDefaultStyle/1,getInsertionPoint/1,getLastPosition/1,getLineLength/2, getLineText/2,getNumberOfLines/1,getRange/3,getSelection/1,getStringSelection/1, getStyle/3,getValue/1,isEditable/1,isModified/1,isMultiLine/1,isSingleLine/1, @@ -232,6 +232,16 @@ discardEdits(#wx_ref{type=ThisT,ref=ThisRef}) -> wxe_util:cast(?wxTextCtrl_DiscardEdits, <<ThisRef:32/?UI>>). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxtextctrl.html#wxtextctrlchangevalue">external documentation</a>. +-spec changeValue(This, Value) -> ok when + This::wxTextCtrl(), Value::unicode:chardata(). +changeValue(#wx_ref{type=ThisT,ref=ThisRef},Value) + when is_list(Value) -> + ?CLASS(ThisT,wxTextCtrl), + Value_UC = unicode:characters_to_binary([Value,0]), + wxe_util:cast(?wxTextCtrl_ChangeValue, + <<ThisRef:32/?UI,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((0+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>). + %% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxtextctrl.html#wxtextctrlemulatekeypress">external documentation</a>. -spec emulateKeyPress(This, Event) -> boolean() when This::wxTextCtrl(), Event::wxKeyEvent:wxKeyEvent(). diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl index e208b081e8..7d4db9ba97 100644 --- a/lib/wx/src/gen/wxe_debug.hrl +++ b/lib/wx/src/gen/wxe_debug.hrl @@ -1669,1665 +1669,1677 @@ wxdebug_table() -> {1824, {wxTextCtrl, create, 3}}, {1825, {wxTextCtrl, cut, 0}}, {1826, {wxTextCtrl, discardEdits, 0}}, - {1827, {wxTextCtrl, emulateKeyPress, 1}}, - {1828, {wxTextCtrl, getDefaultStyle, 0}}, - {1829, {wxTextCtrl, getInsertionPoint, 0}}, - {1830, {wxTextCtrl, getLastPosition, 0}}, - {1831, {wxTextCtrl, getLineLength, 1}}, - {1832, {wxTextCtrl, getLineText, 1}}, - {1833, {wxTextCtrl, getNumberOfLines, 0}}, - {1834, {wxTextCtrl, getRange, 2}}, - {1835, {wxTextCtrl, getSelection, 2}}, - {1836, {wxTextCtrl, getStringSelection, 0}}, - {1837, {wxTextCtrl, getStyle, 2}}, - {1838, {wxTextCtrl, getValue, 0}}, - {1839, {wxTextCtrl, isEditable, 0}}, - {1840, {wxTextCtrl, isModified, 0}}, - {1841, {wxTextCtrl, isMultiLine, 0}}, - {1842, {wxTextCtrl, isSingleLine, 0}}, - {1843, {wxTextCtrl, loadFile, 2}}, - {1844, {wxTextCtrl, markDirty, 0}}, - {1845, {wxTextCtrl, paste, 0}}, - {1846, {wxTextCtrl, positionToXY, 3}}, - {1847, {wxTextCtrl, redo, 0}}, - {1848, {wxTextCtrl, remove, 2}}, - {1849, {wxTextCtrl, replace, 3}}, - {1850, {wxTextCtrl, saveFile, 1}}, - {1851, {wxTextCtrl, setDefaultStyle, 1}}, - {1852, {wxTextCtrl, setEditable, 1}}, - {1853, {wxTextCtrl, setInsertionPoint, 1}}, - {1854, {wxTextCtrl, setInsertionPointEnd, 0}}, - {1856, {wxTextCtrl, setMaxLength, 1}}, - {1857, {wxTextCtrl, setSelection, 2}}, - {1858, {wxTextCtrl, setStyle, 3}}, - {1859, {wxTextCtrl, setValue, 1}}, - {1860, {wxTextCtrl, showPosition, 1}}, - {1861, {wxTextCtrl, undo, 0}}, - {1862, {wxTextCtrl, writeText, 1}}, - {1863, {wxTextCtrl, xYToPosition, 2}}, - {1866, {wxNotebook, new_0, 0}}, - {1867, {wxNotebook, new_3, 3}}, - {1868, {wxNotebook, destruct, 0}}, - {1869, {wxNotebook, addPage, 3}}, - {1870, {wxNotebook, advanceSelection, 1}}, - {1871, {wxNotebook, assignImageList, 1}}, - {1872, {wxNotebook, create, 3}}, - {1873, {wxNotebook, deleteAllPages, 0}}, - {1874, {wxNotebook, deletePage, 1}}, - {1875, {wxNotebook, removePage, 1}}, - {1876, {wxNotebook, getCurrentPage, 0}}, - {1877, {wxNotebook, getImageList, 0}}, - {1879, {wxNotebook, getPage, 1}}, - {1880, {wxNotebook, getPageCount, 0}}, - {1881, {wxNotebook, getPageImage, 1}}, - {1882, {wxNotebook, getPageText, 1}}, - {1883, {wxNotebook, getRowCount, 0}}, - {1884, {wxNotebook, getSelection, 0}}, - {1885, {wxNotebook, getThemeBackgroundColour, 0}}, - {1887, {wxNotebook, hitTest, 2}}, - {1889, {wxNotebook, insertPage, 4}}, - {1890, {wxNotebook, setImageList, 1}}, - {1891, {wxNotebook, setPadding, 1}}, - {1892, {wxNotebook, setPageSize, 1}}, - {1893, {wxNotebook, setPageImage, 2}}, - {1894, {wxNotebook, setPageText, 2}}, - {1895, {wxNotebook, setSelection, 1}}, - {1896, {wxNotebook, changeSelection, 1}}, - {1897, {wxChoicebook, new_0, 0}}, - {1898, {wxChoicebook, new_3, 3}}, - {1899, {wxChoicebook, addPage, 3}}, - {1900, {wxChoicebook, advanceSelection, 1}}, - {1901, {wxChoicebook, assignImageList, 1}}, - {1902, {wxChoicebook, create, 3}}, - {1903, {wxChoicebook, deleteAllPages, 0}}, - {1904, {wxChoicebook, deletePage, 1}}, - {1905, {wxChoicebook, removePage, 1}}, - {1906, {wxChoicebook, getCurrentPage, 0}}, - {1907, {wxChoicebook, getImageList, 0}}, - {1909, {wxChoicebook, getPage, 1}}, - {1910, {wxChoicebook, getPageCount, 0}}, - {1911, {wxChoicebook, getPageImage, 1}}, - {1912, {wxChoicebook, getPageText, 1}}, - {1913, {wxChoicebook, getSelection, 0}}, - {1914, {wxChoicebook, hitTest, 2}}, - {1915, {wxChoicebook, insertPage, 4}}, - {1916, {wxChoicebook, setImageList, 1}}, - {1917, {wxChoicebook, setPageSize, 1}}, - {1918, {wxChoicebook, setPageImage, 2}}, - {1919, {wxChoicebook, setPageText, 2}}, - {1920, {wxChoicebook, setSelection, 1}}, - {1921, {wxChoicebook, changeSelection, 1}}, - {1922, {wxChoicebook, 'Destroy', undefined}}, - {1923, {wxToolbook, new_0, 0}}, - {1924, {wxToolbook, new_3, 3}}, - {1925, {wxToolbook, addPage, 3}}, - {1926, {wxToolbook, advanceSelection, 1}}, - {1927, {wxToolbook, assignImageList, 1}}, - {1928, {wxToolbook, create, 3}}, - {1929, {wxToolbook, deleteAllPages, 0}}, - {1930, {wxToolbook, deletePage, 1}}, - {1931, {wxToolbook, removePage, 1}}, - {1932, {wxToolbook, getCurrentPage, 0}}, - {1933, {wxToolbook, getImageList, 0}}, - {1935, {wxToolbook, getPage, 1}}, - {1936, {wxToolbook, getPageCount, 0}}, - {1937, {wxToolbook, getPageImage, 1}}, - {1938, {wxToolbook, getPageText, 1}}, - {1939, {wxToolbook, getSelection, 0}}, - {1941, {wxToolbook, hitTest, 2}}, - {1942, {wxToolbook, insertPage, 4}}, - {1943, {wxToolbook, setImageList, 1}}, - {1944, {wxToolbook, setPageSize, 1}}, - {1945, {wxToolbook, setPageImage, 2}}, - {1946, {wxToolbook, setPageText, 2}}, - {1947, {wxToolbook, setSelection, 1}}, - {1948, {wxToolbook, changeSelection, 1}}, - {1949, {wxToolbook, 'Destroy', undefined}}, - {1950, {wxListbook, new_0, 0}}, - {1951, {wxListbook, new_3, 3}}, - {1952, {wxListbook, addPage, 3}}, - {1953, {wxListbook, advanceSelection, 1}}, - {1954, {wxListbook, assignImageList, 1}}, - {1955, {wxListbook, create, 3}}, - {1956, {wxListbook, deleteAllPages, 0}}, - {1957, {wxListbook, deletePage, 1}}, - {1958, {wxListbook, removePage, 1}}, - {1959, {wxListbook, getCurrentPage, 0}}, - {1960, {wxListbook, getImageList, 0}}, - {1962, {wxListbook, getPage, 1}}, - {1963, {wxListbook, getPageCount, 0}}, - {1964, {wxListbook, getPageImage, 1}}, - {1965, {wxListbook, getPageText, 1}}, - {1966, {wxListbook, getSelection, 0}}, - {1968, {wxListbook, hitTest, 2}}, - {1969, {wxListbook, insertPage, 4}}, - {1970, {wxListbook, setImageList, 1}}, - {1971, {wxListbook, setPageSize, 1}}, - {1972, {wxListbook, setPageImage, 2}}, - {1973, {wxListbook, setPageText, 2}}, - {1974, {wxListbook, setSelection, 1}}, - {1975, {wxListbook, changeSelection, 1}}, - {1976, {wxListbook, 'Destroy', undefined}}, - {1977, {wxTreebook, new_0, 0}}, - {1978, {wxTreebook, new_3, 3}}, - {1979, {wxTreebook, addPage, 3}}, - {1980, {wxTreebook, advanceSelection, 1}}, - {1981, {wxTreebook, assignImageList, 1}}, - {1982, {wxTreebook, create, 3}}, - {1983, {wxTreebook, deleteAllPages, 0}}, - {1984, {wxTreebook, deletePage, 1}}, - {1985, {wxTreebook, removePage, 1}}, - {1986, {wxTreebook, getCurrentPage, 0}}, - {1987, {wxTreebook, getImageList, 0}}, - {1989, {wxTreebook, getPage, 1}}, - {1990, {wxTreebook, getPageCount, 0}}, - {1991, {wxTreebook, getPageImage, 1}}, - {1992, {wxTreebook, getPageText, 1}}, - {1993, {wxTreebook, getSelection, 0}}, - {1994, {wxTreebook, expandNode, 2}}, - {1995, {wxTreebook, isNodeExpanded, 1}}, - {1997, {wxTreebook, hitTest, 2}}, - {1998, {wxTreebook, insertPage, 4}}, - {1999, {wxTreebook, insertSubPage, 4}}, - {2000, {wxTreebook, setImageList, 1}}, - {2001, {wxTreebook, setPageSize, 1}}, - {2002, {wxTreebook, setPageImage, 2}}, - {2003, {wxTreebook, setPageText, 2}}, - {2004, {wxTreebook, setSelection, 1}}, - {2005, {wxTreebook, changeSelection, 1}}, - {2006, {wxTreebook, 'Destroy', undefined}}, - {2009, {wxTreeCtrl, new_2, 2}}, - {2010, {wxTreeCtrl, new_0, 0}}, - {2012, {wxTreeCtrl, destruct, 0}}, - {2013, {wxTreeCtrl, addRoot, 2}}, - {2014, {wxTreeCtrl, appendItem, 3}}, - {2015, {wxTreeCtrl, assignImageList, 1}}, - {2016, {wxTreeCtrl, assignStateImageList, 1}}, - {2017, {wxTreeCtrl, collapse, 1}}, - {2018, {wxTreeCtrl, collapseAndReset, 1}}, - {2019, {wxTreeCtrl, create, 2}}, - {2020, {wxTreeCtrl, delete, 1}}, - {2021, {wxTreeCtrl, deleteAllItems, 0}}, - {2022, {wxTreeCtrl, deleteChildren, 1}}, - {2023, {wxTreeCtrl, editLabel, 1}}, - {2024, {wxTreeCtrl, ensureVisible, 1}}, - {2025, {wxTreeCtrl, expand, 1}}, - {2026, {wxTreeCtrl, getBoundingRect, 3}}, - {2028, {wxTreeCtrl, getChildrenCount, 2}}, - {2029, {wxTreeCtrl, getCount, 0}}, - {2030, {wxTreeCtrl, getEditControl, 0}}, - {2031, {wxTreeCtrl, getFirstChild, 2}}, - {2032, {wxTreeCtrl, getNextChild, 2}}, - {2033, {wxTreeCtrl, getFirstVisibleItem, 0}}, - {2034, {wxTreeCtrl, getImageList, 0}}, - {2035, {wxTreeCtrl, getIndent, 0}}, - {2036, {wxTreeCtrl, getItemBackgroundColour, 1}}, - {2037, {wxTreeCtrl, getItemData, 1}}, - {2038, {wxTreeCtrl, getItemFont, 1}}, - {2039, {wxTreeCtrl, getItemImage_1, 1}}, - {2040, {wxTreeCtrl, getItemImage_2, 2}}, - {2041, {wxTreeCtrl, getItemText, 1}}, - {2042, {wxTreeCtrl, getItemTextColour, 1}}, - {2043, {wxTreeCtrl, getLastChild, 1}}, - {2044, {wxTreeCtrl, getNextSibling, 1}}, - {2045, {wxTreeCtrl, getNextVisible, 1}}, - {2046, {wxTreeCtrl, getItemParent, 1}}, - {2047, {wxTreeCtrl, getPrevSibling, 1}}, - {2048, {wxTreeCtrl, getPrevVisible, 1}}, - {2049, {wxTreeCtrl, getRootItem, 0}}, - {2050, {wxTreeCtrl, getSelection, 0}}, - {2051, {wxTreeCtrl, getSelections, 1}}, - {2052, {wxTreeCtrl, getStateImageList, 0}}, - {2053, {wxTreeCtrl, hitTest, 2}}, - {2055, {wxTreeCtrl, insertItem, 4}}, - {2056, {wxTreeCtrl, isBold, 1}}, - {2057, {wxTreeCtrl, isExpanded, 1}}, - {2058, {wxTreeCtrl, isSelected, 1}}, - {2059, {wxTreeCtrl, isVisible, 1}}, - {2060, {wxTreeCtrl, itemHasChildren, 1}}, - {2061, {wxTreeCtrl, isTreeItemIdOk, 1}}, - {2062, {wxTreeCtrl, prependItem, 3}}, - {2063, {wxTreeCtrl, scrollTo, 1}}, - {2064, {wxTreeCtrl, selectItem_1, 1}}, - {2065, {wxTreeCtrl, selectItem_2, 2}}, - {2066, {wxTreeCtrl, setIndent, 1}}, - {2067, {wxTreeCtrl, setImageList, 1}}, - {2068, {wxTreeCtrl, setItemBackgroundColour, 2}}, - {2069, {wxTreeCtrl, setItemBold, 2}}, - {2070, {wxTreeCtrl, setItemData, 2}}, - {2071, {wxTreeCtrl, setItemDropHighlight, 2}}, - {2072, {wxTreeCtrl, setItemFont, 2}}, - {2073, {wxTreeCtrl, setItemHasChildren, 2}}, - {2074, {wxTreeCtrl, setItemImage_2, 2}}, - {2075, {wxTreeCtrl, setItemImage_3, 3}}, - {2076, {wxTreeCtrl, setItemText, 2}}, - {2077, {wxTreeCtrl, setItemTextColour, 2}}, - {2078, {wxTreeCtrl, setStateImageList, 1}}, - {2079, {wxTreeCtrl, setWindowStyle, 1}}, - {2080, {wxTreeCtrl, sortChildren, 1}}, - {2081, {wxTreeCtrl, toggle, 1}}, - {2082, {wxTreeCtrl, toggleItemSelection, 1}}, - {2083, {wxTreeCtrl, unselect, 0}}, - {2084, {wxTreeCtrl, unselectAll, 0}}, - {2085, {wxTreeCtrl, unselectItem, 1}}, - {2086, {wxScrollBar, new_0, 0}}, - {2087, {wxScrollBar, new_3, 3}}, - {2088, {wxScrollBar, destruct, 0}}, - {2089, {wxScrollBar, create, 3}}, - {2090, {wxScrollBar, getRange, 0}}, - {2091, {wxScrollBar, getPageSize, 0}}, - {2092, {wxScrollBar, getThumbPosition, 0}}, - {2093, {wxScrollBar, getThumbSize, 0}}, - {2094, {wxScrollBar, setThumbPosition, 1}}, - {2095, {wxScrollBar, setScrollbar, 5}}, - {2097, {wxSpinButton, new_2, 2}}, - {2098, {wxSpinButton, new_0, 0}}, - {2099, {wxSpinButton, create, 2}}, - {2100, {wxSpinButton, getMax, 0}}, - {2101, {wxSpinButton, getMin, 0}}, - {2102, {wxSpinButton, getValue, 0}}, - {2103, {wxSpinButton, setRange, 2}}, - {2104, {wxSpinButton, setValue, 1}}, - {2105, {wxSpinButton, 'Destroy', undefined}}, - {2106, {wxSpinCtrl, new_0, 0}}, - {2107, {wxSpinCtrl, new_2, 2}}, - {2109, {wxSpinCtrl, create, 2}}, - {2112, {wxSpinCtrl, setValue_1_1, 1}}, - {2113, {wxSpinCtrl, setValue_1_0, 1}}, - {2115, {wxSpinCtrl, getValue, 0}}, - {2117, {wxSpinCtrl, setRange, 2}}, - {2118, {wxSpinCtrl, setSelection, 2}}, - {2120, {wxSpinCtrl, getMin, 0}}, - {2122, {wxSpinCtrl, getMax, 0}}, - {2123, {wxSpinCtrl, 'Destroy', undefined}}, - {2124, {wxStaticText, new_0, 0}}, - {2125, {wxStaticText, new_4, 4}}, - {2126, {wxStaticText, create, 4}}, - {2127, {wxStaticText, getLabel, 0}}, - {2128, {wxStaticText, setLabel, 1}}, - {2129, {wxStaticText, wrap, 1}}, - {2130, {wxStaticText, 'Destroy', undefined}}, - {2131, {wxStaticBitmap, new_0, 0}}, - {2132, {wxStaticBitmap, new_4, 4}}, - {2133, {wxStaticBitmap, create, 4}}, - {2134, {wxStaticBitmap, getBitmap, 0}}, - {2135, {wxStaticBitmap, setBitmap, 1}}, - {2136, {wxStaticBitmap, 'Destroy', undefined}}, - {2137, {wxRadioBox, new, 7}}, - {2139, {wxRadioBox, destruct, 0}}, - {2140, {wxRadioBox, create, 7}}, - {2141, {wxRadioBox, enable_2, 2}}, - {2142, {wxRadioBox, enable_1, 1}}, - {2143, {wxRadioBox, getSelection, 0}}, - {2144, {wxRadioBox, getString, 1}}, - {2145, {wxRadioBox, setSelection, 1}}, - {2146, {wxRadioBox, show_2, 2}}, - {2147, {wxRadioBox, show_1, 1}}, - {2148, {wxRadioBox, getColumnCount, 0}}, - {2149, {wxRadioBox, getItemHelpText, 1}}, - {2150, {wxRadioBox, getItemToolTip, 1}}, - {2152, {wxRadioBox, getItemFromPoint, 1}}, - {2153, {wxRadioBox, getRowCount, 0}}, - {2154, {wxRadioBox, isItemEnabled, 1}}, - {2155, {wxRadioBox, isItemShown, 1}}, - {2156, {wxRadioBox, setItemHelpText, 2}}, - {2157, {wxRadioBox, setItemToolTip, 2}}, - {2158, {wxRadioButton, new_0, 0}}, - {2159, {wxRadioButton, new_4, 4}}, - {2160, {wxRadioButton, create, 4}}, - {2161, {wxRadioButton, getValue, 0}}, - {2162, {wxRadioButton, setValue, 1}}, - {2163, {wxRadioButton, 'Destroy', undefined}}, - {2165, {wxSlider, new_6, 6}}, - {2166, {wxSlider, new_0, 0}}, - {2167, {wxSlider, create, 6}}, - {2168, {wxSlider, getLineSize, 0}}, - {2169, {wxSlider, getMax, 0}}, - {2170, {wxSlider, getMin, 0}}, - {2171, {wxSlider, getPageSize, 0}}, - {2172, {wxSlider, getThumbLength, 0}}, - {2173, {wxSlider, getValue, 0}}, - {2174, {wxSlider, setLineSize, 1}}, - {2175, {wxSlider, setPageSize, 1}}, - {2176, {wxSlider, setRange, 2}}, - {2177, {wxSlider, setThumbLength, 1}}, - {2178, {wxSlider, setValue, 1}}, - {2179, {wxSlider, 'Destroy', undefined}}, - {2181, {wxDialog, new_4, 4}}, - {2182, {wxDialog, new_0, 0}}, - {2184, {wxDialog, destruct, 0}}, - {2185, {wxDialog, create, 4}}, - {2186, {wxDialog, createButtonSizer, 1}}, - {2187, {wxDialog, createStdDialogButtonSizer, 1}}, - {2188, {wxDialog, endModal, 1}}, - {2189, {wxDialog, getAffirmativeId, 0}}, - {2190, {wxDialog, getReturnCode, 0}}, - {2191, {wxDialog, isModal, 0}}, - {2192, {wxDialog, setAffirmativeId, 1}}, - {2193, {wxDialog, setReturnCode, 1}}, - {2194, {wxDialog, show, 1}}, - {2195, {wxDialog, showModal, 0}}, - {2196, {wxColourDialog, new_0, 0}}, - {2197, {wxColourDialog, new_2, 2}}, - {2198, {wxColourDialog, destruct, 0}}, - {2199, {wxColourDialog, create, 2}}, - {2200, {wxColourDialog, getColourData, 0}}, - {2201, {wxColourData, new_0, 0}}, - {2202, {wxColourData, new_1, 1}}, - {2203, {wxColourData, destruct, 0}}, - {2204, {wxColourData, getChooseFull, 0}}, - {2205, {wxColourData, getColour, 0}}, - {2207, {wxColourData, getCustomColour, 1}}, - {2208, {wxColourData, setChooseFull, 1}}, - {2209, {wxColourData, setColour, 1}}, - {2210, {wxColourData, setCustomColour, 2}}, - {2211, {wxPalette, new_0, 0}}, - {2212, {wxPalette, new_4, 4}}, - {2214, {wxPalette, destruct, 0}}, - {2215, {wxPalette, create, 4}}, - {2216, {wxPalette, getColoursCount, 0}}, - {2217, {wxPalette, getPixel, 3}}, - {2218, {wxPalette, getRGB, 4}}, - {2219, {wxPalette, isOk, 0}}, - {2223, {wxDirDialog, new, 2}}, - {2224, {wxDirDialog, destruct, 0}}, - {2225, {wxDirDialog, getPath, 0}}, - {2226, {wxDirDialog, getMessage, 0}}, - {2227, {wxDirDialog, setMessage, 1}}, - {2228, {wxDirDialog, setPath, 1}}, - {2232, {wxFileDialog, new, 2}}, - {2233, {wxFileDialog, destruct, 0}}, - {2234, {wxFileDialog, getDirectory, 0}}, - {2235, {wxFileDialog, getFilename, 0}}, - {2236, {wxFileDialog, getFilenames, 1}}, - {2237, {wxFileDialog, getFilterIndex, 0}}, - {2238, {wxFileDialog, getMessage, 0}}, - {2239, {wxFileDialog, getPath, 0}}, - {2240, {wxFileDialog, getPaths, 1}}, - {2241, {wxFileDialog, getWildcard, 0}}, - {2242, {wxFileDialog, setDirectory, 1}}, - {2243, {wxFileDialog, setFilename, 1}}, - {2244, {wxFileDialog, setFilterIndex, 1}}, - {2245, {wxFileDialog, setMessage, 1}}, - {2246, {wxFileDialog, setPath, 1}}, - {2247, {wxFileDialog, setWildcard, 1}}, - {2248, {wxPickerBase, setInternalMargin, 1}}, - {2249, {wxPickerBase, getInternalMargin, 0}}, - {2250, {wxPickerBase, setTextCtrlProportion, 1}}, - {2251, {wxPickerBase, setPickerCtrlProportion, 1}}, - {2252, {wxPickerBase, getTextCtrlProportion, 0}}, - {2253, {wxPickerBase, getPickerCtrlProportion, 0}}, - {2254, {wxPickerBase, hasTextCtrl, 0}}, - {2255, {wxPickerBase, getTextCtrl, 0}}, - {2256, {wxPickerBase, isTextCtrlGrowable, 0}}, - {2257, {wxPickerBase, setPickerCtrlGrowable, 1}}, - {2258, {wxPickerBase, setTextCtrlGrowable, 1}}, - {2259, {wxPickerBase, isPickerCtrlGrowable, 0}}, - {2260, {wxFilePickerCtrl, new_0, 0}}, - {2261, {wxFilePickerCtrl, new_3, 3}}, - {2262, {wxFilePickerCtrl, create, 3}}, - {2263, {wxFilePickerCtrl, getPath, 0}}, - {2264, {wxFilePickerCtrl, setPath, 1}}, - {2265, {wxFilePickerCtrl, 'Destroy', undefined}}, - {2266, {wxDirPickerCtrl, new_0, 0}}, - {2267, {wxDirPickerCtrl, new_3, 3}}, - {2268, {wxDirPickerCtrl, create, 3}}, - {2269, {wxDirPickerCtrl, getPath, 0}}, - {2270, {wxDirPickerCtrl, setPath, 1}}, - {2271, {wxDirPickerCtrl, 'Destroy', undefined}}, - {2272, {wxColourPickerCtrl, new_0, 0}}, - {2273, {wxColourPickerCtrl, new_3, 3}}, - {2274, {wxColourPickerCtrl, create, 3}}, - {2275, {wxColourPickerCtrl, getColour, 0}}, - {2276, {wxColourPickerCtrl, setColour_1_1, 1}}, - {2277, {wxColourPickerCtrl, setColour_1_0, 1}}, - {2278, {wxColourPickerCtrl, 'Destroy', undefined}}, - {2279, {wxDatePickerCtrl, new_0, 0}}, - {2280, {wxDatePickerCtrl, new_3, 3}}, - {2281, {wxDatePickerCtrl, getRange, 2}}, - {2282, {wxDatePickerCtrl, getValue, 0}}, - {2283, {wxDatePickerCtrl, setRange, 2}}, - {2284, {wxDatePickerCtrl, setValue, 1}}, - {2285, {wxDatePickerCtrl, 'Destroy', undefined}}, - {2286, {wxFontPickerCtrl, new_0, 0}}, - {2287, {wxFontPickerCtrl, new_3, 3}}, - {2288, {wxFontPickerCtrl, create, 3}}, - {2289, {wxFontPickerCtrl, getSelectedFont, 0}}, - {2290, {wxFontPickerCtrl, setSelectedFont, 1}}, - {2291, {wxFontPickerCtrl, getMaxPointSize, 0}}, - {2292, {wxFontPickerCtrl, setMaxPointSize, 1}}, - {2293, {wxFontPickerCtrl, 'Destroy', undefined}}, - {2296, {wxFindReplaceDialog, new_0, 0}}, - {2297, {wxFindReplaceDialog, new_4, 4}}, - {2298, {wxFindReplaceDialog, destruct, 0}}, - {2299, {wxFindReplaceDialog, create, 4}}, - {2300, {wxFindReplaceDialog, getData, 0}}, - {2301, {wxFindReplaceData, new_0, 0}}, - {2302, {wxFindReplaceData, new_1, 1}}, - {2303, {wxFindReplaceData, getFindString, 0}}, - {2304, {wxFindReplaceData, getReplaceString, 0}}, - {2305, {wxFindReplaceData, getFlags, 0}}, - {2306, {wxFindReplaceData, setFlags, 1}}, - {2307, {wxFindReplaceData, setFindString, 1}}, - {2308, {wxFindReplaceData, setReplaceString, 1}}, - {2309, {wxFindReplaceData, 'Destroy', undefined}}, - {2310, {wxMultiChoiceDialog, new_0, 0}}, - {2312, {wxMultiChoiceDialog, new_5, 5}}, - {2313, {wxMultiChoiceDialog, getSelections, 0}}, - {2314, {wxMultiChoiceDialog, setSelections, 1}}, - {2315, {wxMultiChoiceDialog, 'Destroy', undefined}}, - {2316, {wxSingleChoiceDialog, new_0, 0}}, - {2318, {wxSingleChoiceDialog, new_5, 5}}, - {2319, {wxSingleChoiceDialog, getSelection, 0}}, - {2320, {wxSingleChoiceDialog, getStringSelection, 0}}, - {2321, {wxSingleChoiceDialog, setSelection, 1}}, - {2322, {wxSingleChoiceDialog, 'Destroy', undefined}}, - {2323, {wxTextEntryDialog, new, 3}}, - {2324, {wxTextEntryDialog, getValue, 0}}, - {2325, {wxTextEntryDialog, setValue, 1}}, - {2326, {wxTextEntryDialog, 'Destroy', undefined}}, - {2327, {wxPasswordEntryDialog, new, 3}}, - {2328, {wxPasswordEntryDialog, 'Destroy', undefined}}, - {2329, {wxFontData, new_0, 0}}, - {2330, {wxFontData, new_1, 1}}, - {2331, {wxFontData, destruct, 0}}, - {2332, {wxFontData, enableEffects, 1}}, - {2333, {wxFontData, getAllowSymbols, 0}}, - {2334, {wxFontData, getColour, 0}}, - {2335, {wxFontData, getChosenFont, 0}}, - {2336, {wxFontData, getEnableEffects, 0}}, - {2337, {wxFontData, getInitialFont, 0}}, - {2338, {wxFontData, getShowHelp, 0}}, - {2339, {wxFontData, setAllowSymbols, 1}}, - {2340, {wxFontData, setChosenFont, 1}}, - {2341, {wxFontData, setColour, 1}}, - {2342, {wxFontData, setInitialFont, 1}}, - {2343, {wxFontData, setRange, 2}}, - {2344, {wxFontData, setShowHelp, 1}}, - {2348, {wxFontDialog, new_0, 0}}, - {2350, {wxFontDialog, new_2, 2}}, - {2352, {wxFontDialog, create, 2}}, - {2353, {wxFontDialog, getFontData, 0}}, - {2355, {wxFontDialog, 'Destroy', undefined}}, - {2356, {wxProgressDialog, new, 3}}, - {2357, {wxProgressDialog, destruct, 0}}, - {2358, {wxProgressDialog, resume, 0}}, - {2359, {wxProgressDialog, update_2, 2}}, - {2360, {wxProgressDialog, update_0, 0}}, - {2361, {wxMessageDialog, new, 3}}, - {2362, {wxMessageDialog, destruct, 0}}, - {2363, {wxPageSetupDialog, new, 2}}, - {2364, {wxPageSetupDialog, destruct, 0}}, - {2365, {wxPageSetupDialog, getPageSetupData, 0}}, - {2366, {wxPageSetupDialog, showModal, 0}}, - {2367, {wxPageSetupDialogData, new_0, 0}}, - {2368, {wxPageSetupDialogData, new_1_0, 1}}, - {2369, {wxPageSetupDialogData, new_1_1, 1}}, - {2370, {wxPageSetupDialogData, destruct, 0}}, - {2371, {wxPageSetupDialogData, enableHelp, 1}}, - {2372, {wxPageSetupDialogData, enableMargins, 1}}, - {2373, {wxPageSetupDialogData, enableOrientation, 1}}, - {2374, {wxPageSetupDialogData, enablePaper, 1}}, - {2375, {wxPageSetupDialogData, enablePrinter, 1}}, - {2376, {wxPageSetupDialogData, getDefaultMinMargins, 0}}, - {2377, {wxPageSetupDialogData, getEnableMargins, 0}}, - {2378, {wxPageSetupDialogData, getEnableOrientation, 0}}, - {2379, {wxPageSetupDialogData, getEnablePaper, 0}}, - {2380, {wxPageSetupDialogData, getEnablePrinter, 0}}, - {2381, {wxPageSetupDialogData, getEnableHelp, 0}}, - {2382, {wxPageSetupDialogData, getDefaultInfo, 0}}, - {2383, {wxPageSetupDialogData, getMarginTopLeft, 0}}, - {2384, {wxPageSetupDialogData, getMarginBottomRight, 0}}, - {2385, {wxPageSetupDialogData, getMinMarginTopLeft, 0}}, - {2386, {wxPageSetupDialogData, getMinMarginBottomRight, 0}}, - {2387, {wxPageSetupDialogData, getPaperId, 0}}, - {2388, {wxPageSetupDialogData, getPaperSize, 0}}, - {2390, {wxPageSetupDialogData, getPrintData, 0}}, - {2391, {wxPageSetupDialogData, isOk, 0}}, - {2392, {wxPageSetupDialogData, setDefaultInfo, 1}}, - {2393, {wxPageSetupDialogData, setDefaultMinMargins, 1}}, - {2394, {wxPageSetupDialogData, setMarginTopLeft, 1}}, - {2395, {wxPageSetupDialogData, setMarginBottomRight, 1}}, - {2396, {wxPageSetupDialogData, setMinMarginTopLeft, 1}}, - {2397, {wxPageSetupDialogData, setMinMarginBottomRight, 1}}, - {2398, {wxPageSetupDialogData, setPaperId, 1}}, - {2399, {wxPageSetupDialogData, setPaperSize_1_1, 1}}, - {2400, {wxPageSetupDialogData, setPaperSize_1_0, 1}}, - {2401, {wxPageSetupDialogData, setPrintData, 1}}, - {2402, {wxPrintDialog, new_2_0, 2}}, - {2403, {wxPrintDialog, new_2_1, 2}}, - {2404, {wxPrintDialog, destruct, 0}}, - {2405, {wxPrintDialog, getPrintDialogData, 0}}, - {2406, {wxPrintDialog, getPrintDC, 0}}, - {2407, {wxPrintDialogData, new_0, 0}}, - {2408, {wxPrintDialogData, new_1_1, 1}}, - {2409, {wxPrintDialogData, new_1_0, 1}}, - {2410, {wxPrintDialogData, destruct, 0}}, - {2411, {wxPrintDialogData, enableHelp, 1}}, - {2412, {wxPrintDialogData, enablePageNumbers, 1}}, - {2413, {wxPrintDialogData, enablePrintToFile, 1}}, - {2414, {wxPrintDialogData, enableSelection, 1}}, - {2415, {wxPrintDialogData, getAllPages, 0}}, - {2416, {wxPrintDialogData, getCollate, 0}}, - {2417, {wxPrintDialogData, getFromPage, 0}}, - {2418, {wxPrintDialogData, getMaxPage, 0}}, - {2419, {wxPrintDialogData, getMinPage, 0}}, - {2420, {wxPrintDialogData, getNoCopies, 0}}, - {2421, {wxPrintDialogData, getPrintData, 0}}, - {2422, {wxPrintDialogData, getPrintToFile, 0}}, - {2423, {wxPrintDialogData, getSelection, 0}}, - {2424, {wxPrintDialogData, getToPage, 0}}, - {2425, {wxPrintDialogData, isOk, 0}}, - {2426, {wxPrintDialogData, setCollate, 1}}, - {2427, {wxPrintDialogData, setFromPage, 1}}, - {2428, {wxPrintDialogData, setMaxPage, 1}}, - {2429, {wxPrintDialogData, setMinPage, 1}}, - {2430, {wxPrintDialogData, setNoCopies, 1}}, - {2431, {wxPrintDialogData, setPrintData, 1}}, - {2432, {wxPrintDialogData, setPrintToFile, 1}}, - {2433, {wxPrintDialogData, setSelection, 1}}, - {2434, {wxPrintDialogData, setToPage, 1}}, - {2435, {wxPrintData, new_0, 0}}, - {2436, {wxPrintData, new_1, 1}}, - {2437, {wxPrintData, destruct, 0}}, - {2438, {wxPrintData, getCollate, 0}}, - {2439, {wxPrintData, getBin, 0}}, - {2440, {wxPrintData, getColour, 0}}, - {2441, {wxPrintData, getDuplex, 0}}, - {2442, {wxPrintData, getNoCopies, 0}}, - {2443, {wxPrintData, getOrientation, 0}}, - {2444, {wxPrintData, getPaperId, 0}}, - {2445, {wxPrintData, getPrinterName, 0}}, - {2446, {wxPrintData, getQuality, 0}}, - {2447, {wxPrintData, isOk, 0}}, - {2448, {wxPrintData, setBin, 1}}, - {2449, {wxPrintData, setCollate, 1}}, - {2450, {wxPrintData, setColour, 1}}, - {2451, {wxPrintData, setDuplex, 1}}, - {2452, {wxPrintData, setNoCopies, 1}}, - {2453, {wxPrintData, setOrientation, 1}}, - {2454, {wxPrintData, setPaperId, 1}}, - {2455, {wxPrintData, setPrinterName, 1}}, - {2456, {wxPrintData, setQuality, 1}}, - {2459, {wxPrintPreview, new_2, 2}}, - {2460, {wxPrintPreview, new_3, 3}}, - {2462, {wxPrintPreview, destruct, 0}}, - {2463, {wxPrintPreview, getCanvas, 0}}, - {2464, {wxPrintPreview, getCurrentPage, 0}}, - {2465, {wxPrintPreview, getFrame, 0}}, - {2466, {wxPrintPreview, getMaxPage, 0}}, - {2467, {wxPrintPreview, getMinPage, 0}}, - {2468, {wxPrintPreview, getPrintout, 0}}, - {2469, {wxPrintPreview, getPrintoutForPrinting, 0}}, - {2470, {wxPrintPreview, isOk, 0}}, - {2471, {wxPrintPreview, paintPage, 2}}, - {2472, {wxPrintPreview, print, 1}}, - {2473, {wxPrintPreview, renderPage, 1}}, - {2474, {wxPrintPreview, setCanvas, 1}}, - {2475, {wxPrintPreview, setCurrentPage, 1}}, - {2476, {wxPrintPreview, setFrame, 1}}, - {2477, {wxPrintPreview, setPrintout, 1}}, - {2478, {wxPrintPreview, setZoom, 1}}, - {2479, {wxPreviewFrame, new, 3}}, - {2480, {wxPreviewFrame, destruct, 0}}, - {2481, {wxPreviewFrame, createControlBar, 0}}, - {2482, {wxPreviewFrame, createCanvas, 0}}, - {2483, {wxPreviewFrame, initialize, 0}}, - {2484, {wxPreviewFrame, onCloseWindow, 1}}, - {2485, {wxPreviewControlBar, new, 4}}, - {2486, {wxPreviewControlBar, destruct, 0}}, - {2487, {wxPreviewControlBar, createButtons, 0}}, - {2488, {wxPreviewControlBar, getPrintPreview, 0}}, - {2489, {wxPreviewControlBar, getZoomControl, 0}}, - {2490, {wxPreviewControlBar, setZoomControl, 1}}, - {2492, {wxPrinter, new, 1}}, - {2493, {wxPrinter, createAbortWindow, 2}}, - {2494, {wxPrinter, getAbort, 0}}, - {2495, {wxPrinter, getLastError, 0}}, - {2496, {wxPrinter, getPrintDialogData, 0}}, - {2497, {wxPrinter, print, 3}}, - {2498, {wxPrinter, printDialog, 1}}, - {2499, {wxPrinter, reportError, 3}}, - {2500, {wxPrinter, setup, 1}}, - {2501, {wxPrinter, 'Destroy', undefined}}, - {2502, {wxXmlResource, new_1, 1}}, - {2503, {wxXmlResource, new_2, 2}}, - {2504, {wxXmlResource, destruct, 0}}, - {2505, {wxXmlResource, attachUnknownControl, 3}}, - {2506, {wxXmlResource, clearHandlers, 0}}, - {2507, {wxXmlResource, compareVersion, 4}}, - {2508, {wxXmlResource, get, 0}}, - {2509, {wxXmlResource, getFlags, 0}}, - {2510, {wxXmlResource, getVersion, 0}}, - {2511, {wxXmlResource, getXRCID, 2}}, - {2512, {wxXmlResource, initAllHandlers, 0}}, - {2513, {wxXmlResource, load, 1}}, - {2514, {wxXmlResource, loadBitmap, 1}}, - {2515, {wxXmlResource, loadDialog_2, 2}}, - {2516, {wxXmlResource, loadDialog_3, 3}}, - {2517, {wxXmlResource, loadFrame_2, 2}}, - {2518, {wxXmlResource, loadFrame_3, 3}}, - {2519, {wxXmlResource, loadIcon, 1}}, - {2520, {wxXmlResource, loadMenu, 1}}, - {2521, {wxXmlResource, loadMenuBar_2, 2}}, - {2522, {wxXmlResource, loadMenuBar_1, 1}}, - {2523, {wxXmlResource, loadPanel_2, 2}}, - {2524, {wxXmlResource, loadPanel_3, 3}}, - {2525, {wxXmlResource, loadToolBar, 2}}, - {2526, {wxXmlResource, set, 1}}, - {2527, {wxXmlResource, setFlags, 1}}, - {2528, {wxXmlResource, unload, 1}}, - {2529, {wxXmlResource, xrcctrl, 3}}, - {2530, {wxHtmlEasyPrinting, new, 1}}, - {2531, {wxHtmlEasyPrinting, destruct, 0}}, - {2532, {wxHtmlEasyPrinting, getPrintData, 0}}, - {2533, {wxHtmlEasyPrinting, getPageSetupData, 0}}, - {2534, {wxHtmlEasyPrinting, previewFile, 1}}, - {2535, {wxHtmlEasyPrinting, previewText, 2}}, - {2536, {wxHtmlEasyPrinting, printFile, 1}}, - {2537, {wxHtmlEasyPrinting, printText, 2}}, - {2538, {wxHtmlEasyPrinting, pageSetup, 0}}, - {2539, {wxHtmlEasyPrinting, setFonts, 3}}, - {2540, {wxHtmlEasyPrinting, setHeader, 2}}, - {2541, {wxHtmlEasyPrinting, setFooter, 2}}, - {2543, {wxGLCanvas, new_2, 2}}, - {2544, {wxGLCanvas, new_3_1, 3}}, - {2545, {wxGLCanvas, new_3_0, 3}}, - {2546, {wxGLCanvas, getContext, 0}}, - {2548, {wxGLCanvas, setCurrent, 0}}, - {2549, {wxGLCanvas, swapBuffers, 0}}, - {2550, {wxGLCanvas, 'Destroy', undefined}}, - {2551, {wxAuiManager, new, 1}}, - {2552, {wxAuiManager, destruct, 0}}, - {2553, {wxAuiManager, addPane_2_1, 2}}, - {2554, {wxAuiManager, addPane_3, 3}}, - {2555, {wxAuiManager, addPane_2_0, 2}}, - {2556, {wxAuiManager, detachPane, 1}}, - {2557, {wxAuiManager, getAllPanes, 0}}, - {2558, {wxAuiManager, getArtProvider, 0}}, - {2559, {wxAuiManager, getDockSizeConstraint, 2}}, - {2560, {wxAuiManager, getFlags, 0}}, - {2561, {wxAuiManager, getManagedWindow, 0}}, - {2562, {wxAuiManager, getManager, 1}}, - {2563, {wxAuiManager, getPane_1_1, 1}}, - {2564, {wxAuiManager, getPane_1_0, 1}}, - {2565, {wxAuiManager, hideHint, 0}}, - {2566, {wxAuiManager, insertPane, 3}}, - {2567, {wxAuiManager, loadPaneInfo, 2}}, - {2568, {wxAuiManager, loadPerspective, 2}}, - {2569, {wxAuiManager, savePaneInfo, 1}}, - {2570, {wxAuiManager, savePerspective, 0}}, - {2571, {wxAuiManager, setArtProvider, 1}}, - {2572, {wxAuiManager, setDockSizeConstraint, 2}}, - {2573, {wxAuiManager, setFlags, 1}}, - {2574, {wxAuiManager, setManagedWindow, 1}}, - {2575, {wxAuiManager, showHint, 1}}, - {2576, {wxAuiManager, unInit, 0}}, - {2577, {wxAuiManager, update, 0}}, - {2578, {wxAuiPaneInfo, new_0, 0}}, - {2579, {wxAuiPaneInfo, new_1, 1}}, - {2580, {wxAuiPaneInfo, destruct, 0}}, - {2581, {wxAuiPaneInfo, bestSize_1, 1}}, - {2582, {wxAuiPaneInfo, bestSize_2, 2}}, - {2583, {wxAuiPaneInfo, bottom, 0}}, - {2584, {wxAuiPaneInfo, bottomDockable, 1}}, - {2585, {wxAuiPaneInfo, caption, 1}}, - {2586, {wxAuiPaneInfo, captionVisible, 1}}, - {2587, {wxAuiPaneInfo, centre, 0}}, - {2588, {wxAuiPaneInfo, centrePane, 0}}, - {2589, {wxAuiPaneInfo, closeButton, 1}}, - {2590, {wxAuiPaneInfo, defaultPane, 0}}, - {2591, {wxAuiPaneInfo, destroyOnClose, 1}}, - {2592, {wxAuiPaneInfo, direction, 1}}, - {2593, {wxAuiPaneInfo, dock, 0}}, - {2594, {wxAuiPaneInfo, dockable, 1}}, - {2595, {wxAuiPaneInfo, fixed, 0}}, - {2596, {wxAuiPaneInfo, float, 0}}, - {2597, {wxAuiPaneInfo, floatable, 1}}, - {2598, {wxAuiPaneInfo, floatingPosition_1, 1}}, - {2599, {wxAuiPaneInfo, floatingPosition_2, 2}}, - {2600, {wxAuiPaneInfo, floatingSize_1, 1}}, - {2601, {wxAuiPaneInfo, floatingSize_2, 2}}, - {2602, {wxAuiPaneInfo, gripper, 1}}, - {2603, {wxAuiPaneInfo, gripperTop, 1}}, - {2604, {wxAuiPaneInfo, hasBorder, 0}}, - {2605, {wxAuiPaneInfo, hasCaption, 0}}, - {2606, {wxAuiPaneInfo, hasCloseButton, 0}}, - {2607, {wxAuiPaneInfo, hasFlag, 1}}, - {2608, {wxAuiPaneInfo, hasGripper, 0}}, - {2609, {wxAuiPaneInfo, hasGripperTop, 0}}, - {2610, {wxAuiPaneInfo, hasMaximizeButton, 0}}, - {2611, {wxAuiPaneInfo, hasMinimizeButton, 0}}, - {2612, {wxAuiPaneInfo, hasPinButton, 0}}, - {2613, {wxAuiPaneInfo, hide, 0}}, - {2614, {wxAuiPaneInfo, isBottomDockable, 0}}, - {2615, {wxAuiPaneInfo, isDocked, 0}}, - {2616, {wxAuiPaneInfo, isFixed, 0}}, - {2617, {wxAuiPaneInfo, isFloatable, 0}}, - {2618, {wxAuiPaneInfo, isFloating, 0}}, - {2619, {wxAuiPaneInfo, isLeftDockable, 0}}, - {2620, {wxAuiPaneInfo, isMovable, 0}}, - {2621, {wxAuiPaneInfo, isOk, 0}}, - {2622, {wxAuiPaneInfo, isResizable, 0}}, - {2623, {wxAuiPaneInfo, isRightDockable, 0}}, - {2624, {wxAuiPaneInfo, isShown, 0}}, - {2625, {wxAuiPaneInfo, isToolbar, 0}}, - {2626, {wxAuiPaneInfo, isTopDockable, 0}}, - {2627, {wxAuiPaneInfo, layer, 1}}, - {2628, {wxAuiPaneInfo, left, 0}}, - {2629, {wxAuiPaneInfo, leftDockable, 1}}, - {2630, {wxAuiPaneInfo, maxSize_1, 1}}, - {2631, {wxAuiPaneInfo, maxSize_2, 2}}, - {2632, {wxAuiPaneInfo, maximizeButton, 1}}, - {2633, {wxAuiPaneInfo, minSize_1, 1}}, - {2634, {wxAuiPaneInfo, minSize_2, 2}}, - {2635, {wxAuiPaneInfo, minimizeButton, 1}}, - {2636, {wxAuiPaneInfo, movable, 1}}, - {2637, {wxAuiPaneInfo, name, 1}}, - {2638, {wxAuiPaneInfo, paneBorder, 1}}, - {2639, {wxAuiPaneInfo, pinButton, 1}}, - {2640, {wxAuiPaneInfo, position, 1}}, - {2641, {wxAuiPaneInfo, resizable, 1}}, - {2642, {wxAuiPaneInfo, right, 0}}, - {2643, {wxAuiPaneInfo, rightDockable, 1}}, - {2644, {wxAuiPaneInfo, row, 1}}, - {2645, {wxAuiPaneInfo, safeSet, 1}}, - {2646, {wxAuiPaneInfo, setFlag, 2}}, - {2647, {wxAuiPaneInfo, show, 1}}, - {2648, {wxAuiPaneInfo, toolbarPane, 0}}, - {2649, {wxAuiPaneInfo, top, 0}}, - {2650, {wxAuiPaneInfo, topDockable, 1}}, - {2651, {wxAuiPaneInfo, window, 1}}, - {2652, {wxAuiNotebook, new_0, 0}}, - {2653, {wxAuiNotebook, new_2, 2}}, - {2654, {wxAuiNotebook, addPage, 3}}, - {2655, {wxAuiNotebook, create, 2}}, - {2656, {wxAuiNotebook, deletePage, 1}}, - {2657, {wxAuiNotebook, getArtProvider, 0}}, - {2658, {wxAuiNotebook, getPage, 1}}, - {2659, {wxAuiNotebook, getPageBitmap, 1}}, - {2660, {wxAuiNotebook, getPageCount, 0}}, - {2661, {wxAuiNotebook, getPageIndex, 1}}, - {2662, {wxAuiNotebook, getPageText, 1}}, - {2663, {wxAuiNotebook, getSelection, 0}}, - {2664, {wxAuiNotebook, insertPage, 4}}, - {2665, {wxAuiNotebook, removePage, 1}}, - {2666, {wxAuiNotebook, setArtProvider, 1}}, - {2667, {wxAuiNotebook, setFont, 1}}, - {2668, {wxAuiNotebook, setPageBitmap, 2}}, - {2669, {wxAuiNotebook, setPageText, 2}}, - {2670, {wxAuiNotebook, setSelection, 1}}, - {2671, {wxAuiNotebook, setTabCtrlHeight, 1}}, - {2672, {wxAuiNotebook, setUniformBitmapSize, 1}}, - {2673, {wxAuiNotebook, 'Destroy', undefined}}, - {2674, {wxMDIParentFrame, new_0, 0}}, - {2675, {wxMDIParentFrame, new_4, 4}}, - {2676, {wxMDIParentFrame, destruct, 0}}, - {2677, {wxMDIParentFrame, activateNext, 0}}, - {2678, {wxMDIParentFrame, activatePrevious, 0}}, - {2679, {wxMDIParentFrame, arrangeIcons, 0}}, - {2680, {wxMDIParentFrame, cascade, 0}}, - {2681, {wxMDIParentFrame, create, 4}}, - {2682, {wxMDIParentFrame, getActiveChild, 0}}, - {2683, {wxMDIParentFrame, getClientWindow, 0}}, - {2684, {wxMDIParentFrame, tile, 1}}, - {2685, {wxMDIChildFrame, new_0, 0}}, - {2686, {wxMDIChildFrame, new_4, 4}}, - {2687, {wxMDIChildFrame, destruct, 0}}, - {2688, {wxMDIChildFrame, activate, 0}}, - {2689, {wxMDIChildFrame, create, 4}}, - {2690, {wxMDIChildFrame, maximize, 1}}, - {2691, {wxMDIChildFrame, restore, 0}}, - {2692, {wxMDIClientWindow, new_0, 0}}, - {2693, {wxMDIClientWindow, new_2, 2}}, - {2694, {wxMDIClientWindow, destruct, 0}}, - {2695, {wxMDIClientWindow, createClient, 2}}, - {2696, {wxLayoutAlgorithm, new, 0}}, - {2697, {wxLayoutAlgorithm, layoutFrame, 2}}, - {2698, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, - {2699, {wxLayoutAlgorithm, layoutWindow, 2}}, - {2700, {wxLayoutAlgorithm, 'Destroy', undefined}}, - {2701, {wxEvent, getId, 0}}, - {2702, {wxEvent, getSkipped, 0}}, - {2703, {wxEvent, getTimestamp, 0}}, - {2704, {wxEvent, isCommandEvent, 0}}, - {2705, {wxEvent, resumePropagation, 1}}, - {2706, {wxEvent, shouldPropagate, 0}}, - {2707, {wxEvent, skip, 1}}, - {2708, {wxEvent, stopPropagation, 0}}, - {2709, {wxCommandEvent, getClientData, 0}}, - {2710, {wxCommandEvent, getExtraLong, 0}}, - {2711, {wxCommandEvent, getInt, 0}}, - {2712, {wxCommandEvent, getSelection, 0}}, - {2713, {wxCommandEvent, getString, 0}}, - {2714, {wxCommandEvent, isChecked, 0}}, - {2715, {wxCommandEvent, isSelection, 0}}, - {2716, {wxCommandEvent, setInt, 1}}, - {2717, {wxCommandEvent, setString, 1}}, - {2718, {wxScrollEvent, getOrientation, 0}}, - {2719, {wxScrollEvent, getPosition, 0}}, - {2720, {wxScrollWinEvent, getOrientation, 0}}, - {2721, {wxScrollWinEvent, getPosition, 0}}, - {2722, {wxMouseEvent, altDown, 0}}, - {2723, {wxMouseEvent, button, 1}}, - {2724, {wxMouseEvent, buttonDClick, 1}}, - {2725, {wxMouseEvent, buttonDown, 1}}, - {2726, {wxMouseEvent, buttonUp, 1}}, - {2727, {wxMouseEvent, cmdDown, 0}}, - {2728, {wxMouseEvent, controlDown, 0}}, - {2729, {wxMouseEvent, dragging, 0}}, - {2730, {wxMouseEvent, entering, 0}}, - {2731, {wxMouseEvent, getButton, 0}}, - {2734, {wxMouseEvent, getPosition, 0}}, - {2735, {wxMouseEvent, getLogicalPosition, 1}}, - {2736, {wxMouseEvent, getLinesPerAction, 0}}, - {2737, {wxMouseEvent, getWheelRotation, 0}}, - {2738, {wxMouseEvent, getWheelDelta, 0}}, - {2739, {wxMouseEvent, getX, 0}}, - {2740, {wxMouseEvent, getY, 0}}, - {2741, {wxMouseEvent, isButton, 0}}, - {2742, {wxMouseEvent, isPageScroll, 0}}, - {2743, {wxMouseEvent, leaving, 0}}, - {2744, {wxMouseEvent, leftDClick, 0}}, - {2745, {wxMouseEvent, leftDown, 0}}, - {2746, {wxMouseEvent, leftIsDown, 0}}, - {2747, {wxMouseEvent, leftUp, 0}}, - {2748, {wxMouseEvent, metaDown, 0}}, - {2749, {wxMouseEvent, middleDClick, 0}}, - {2750, {wxMouseEvent, middleDown, 0}}, - {2751, {wxMouseEvent, middleIsDown, 0}}, - {2752, {wxMouseEvent, middleUp, 0}}, - {2753, {wxMouseEvent, moving, 0}}, - {2754, {wxMouseEvent, rightDClick, 0}}, - {2755, {wxMouseEvent, rightDown, 0}}, - {2756, {wxMouseEvent, rightIsDown, 0}}, - {2757, {wxMouseEvent, rightUp, 0}}, - {2758, {wxMouseEvent, shiftDown, 0}}, - {2759, {wxSetCursorEvent, getCursor, 0}}, - {2760, {wxSetCursorEvent, getX, 0}}, - {2761, {wxSetCursorEvent, getY, 0}}, - {2762, {wxSetCursorEvent, hasCursor, 0}}, - {2763, {wxSetCursorEvent, setCursor, 1}}, - {2764, {wxKeyEvent, altDown, 0}}, - {2765, {wxKeyEvent, cmdDown, 0}}, - {2766, {wxKeyEvent, controlDown, 0}}, - {2767, {wxKeyEvent, getKeyCode, 0}}, - {2768, {wxKeyEvent, getModifiers, 0}}, - {2771, {wxKeyEvent, getPosition, 0}}, - {2772, {wxKeyEvent, getRawKeyCode, 0}}, - {2773, {wxKeyEvent, getRawKeyFlags, 0}}, - {2774, {wxKeyEvent, getUnicodeKey, 0}}, - {2775, {wxKeyEvent, getX, 0}}, - {2776, {wxKeyEvent, getY, 0}}, - {2777, {wxKeyEvent, hasModifiers, 0}}, - {2778, {wxKeyEvent, metaDown, 0}}, - {2779, {wxKeyEvent, shiftDown, 0}}, - {2780, {wxSizeEvent, getSize, 0}}, - {2781, {wxMoveEvent, getPosition, 0}}, - {2782, {wxEraseEvent, getDC, 0}}, - {2783, {wxFocusEvent, getWindow, 0}}, - {2784, {wxChildFocusEvent, getWindow, 0}}, - {2785, {wxMenuEvent, getMenu, 0}}, - {2786, {wxMenuEvent, getMenuId, 0}}, - {2787, {wxMenuEvent, isPopup, 0}}, - {2788, {wxCloseEvent, canVeto, 0}}, - {2789, {wxCloseEvent, getLoggingOff, 0}}, - {2790, {wxCloseEvent, setCanVeto, 1}}, - {2791, {wxCloseEvent, setLoggingOff, 1}}, - {2792, {wxCloseEvent, veto, 1}}, - {2793, {wxShowEvent, setShow, 1}}, - {2794, {wxShowEvent, getShow, 0}}, - {2795, {wxIconizeEvent, iconized, 0}}, - {2796, {wxJoystickEvent, buttonDown, 1}}, - {2797, {wxJoystickEvent, buttonIsDown, 1}}, - {2798, {wxJoystickEvent, buttonUp, 1}}, - {2799, {wxJoystickEvent, getButtonChange, 0}}, - {2800, {wxJoystickEvent, getButtonState, 0}}, - {2801, {wxJoystickEvent, getJoystick, 0}}, - {2802, {wxJoystickEvent, getPosition, 0}}, - {2803, {wxJoystickEvent, getZPosition, 0}}, - {2804, {wxJoystickEvent, isButton, 0}}, - {2805, {wxJoystickEvent, isMove, 0}}, - {2806, {wxJoystickEvent, isZMove, 0}}, - {2807, {wxUpdateUIEvent, canUpdate, 1}}, - {2808, {wxUpdateUIEvent, check, 1}}, - {2809, {wxUpdateUIEvent, enable, 1}}, - {2810, {wxUpdateUIEvent, show, 1}}, - {2811, {wxUpdateUIEvent, getChecked, 0}}, - {2812, {wxUpdateUIEvent, getEnabled, 0}}, - {2813, {wxUpdateUIEvent, getShown, 0}}, - {2814, {wxUpdateUIEvent, getSetChecked, 0}}, - {2815, {wxUpdateUIEvent, getSetEnabled, 0}}, - {2816, {wxUpdateUIEvent, getSetShown, 0}}, - {2817, {wxUpdateUIEvent, getSetText, 0}}, - {2818, {wxUpdateUIEvent, getText, 0}}, - {2819, {wxUpdateUIEvent, getMode, 0}}, - {2820, {wxUpdateUIEvent, getUpdateInterval, 0}}, - {2821, {wxUpdateUIEvent, resetUpdateTime, 0}}, - {2822, {wxUpdateUIEvent, setMode, 1}}, - {2823, {wxUpdateUIEvent, setText, 1}}, - {2824, {wxUpdateUIEvent, setUpdateInterval, 1}}, - {2825, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, - {2826, {wxPaletteChangedEvent, setChangedWindow, 1}}, - {2827, {wxPaletteChangedEvent, getChangedWindow, 0}}, - {2828, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, - {2829, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, - {2830, {wxNavigationKeyEvent, getDirection, 0}}, - {2831, {wxNavigationKeyEvent, setDirection, 1}}, - {2832, {wxNavigationKeyEvent, isWindowChange, 0}}, - {2833, {wxNavigationKeyEvent, setWindowChange, 1}}, - {2834, {wxNavigationKeyEvent, isFromTab, 0}}, - {2835, {wxNavigationKeyEvent, setFromTab, 1}}, - {2836, {wxNavigationKeyEvent, getCurrentFocus, 0}}, - {2837, {wxNavigationKeyEvent, setCurrentFocus, 1}}, - {2838, {wxHelpEvent, getOrigin, 0}}, - {2839, {wxHelpEvent, getPosition, 0}}, - {2840, {wxHelpEvent, setOrigin, 1}}, - {2841, {wxHelpEvent, setPosition, 1}}, - {2842, {wxContextMenuEvent, getPosition, 0}}, - {2843, {wxContextMenuEvent, setPosition, 1}}, - {2844, {wxIdleEvent, canSend, 1}}, - {2845, {wxIdleEvent, getMode, 0}}, - {2846, {wxIdleEvent, requestMore, 1}}, - {2847, {wxIdleEvent, moreRequested, 0}}, - {2848, {wxIdleEvent, setMode, 1}}, - {2849, {wxGridEvent, altDown, 0}}, - {2850, {wxGridEvent, controlDown, 0}}, - {2851, {wxGridEvent, getCol, 0}}, - {2852, {wxGridEvent, getPosition, 0}}, - {2853, {wxGridEvent, getRow, 0}}, - {2854, {wxGridEvent, metaDown, 0}}, - {2855, {wxGridEvent, selecting, 0}}, - {2856, {wxGridEvent, shiftDown, 0}}, - {2857, {wxNotifyEvent, allow, 0}}, - {2858, {wxNotifyEvent, isAllowed, 0}}, - {2859, {wxNotifyEvent, veto, 0}}, - {2860, {wxSashEvent, getEdge, 0}}, - {2861, {wxSashEvent, getDragRect, 0}}, - {2862, {wxSashEvent, getDragStatus, 0}}, - {2863, {wxListEvent, getCacheFrom, 0}}, - {2864, {wxListEvent, getCacheTo, 0}}, - {2865, {wxListEvent, getKeyCode, 0}}, - {2866, {wxListEvent, getIndex, 0}}, - {2867, {wxListEvent, getColumn, 0}}, - {2868, {wxListEvent, getPoint, 0}}, - {2869, {wxListEvent, getLabel, 0}}, - {2870, {wxListEvent, getText, 0}}, - {2871, {wxListEvent, getImage, 0}}, - {2872, {wxListEvent, getData, 0}}, - {2873, {wxListEvent, getMask, 0}}, - {2874, {wxListEvent, getItem, 0}}, - {2875, {wxListEvent, isEditCancelled, 0}}, - {2876, {wxDateEvent, getDate, 0}}, - {2877, {wxCalendarEvent, getWeekDay, 0}}, - {2878, {wxFileDirPickerEvent, getPath, 0}}, - {2879, {wxColourPickerEvent, getColour, 0}}, - {2880, {wxFontPickerEvent, getFont, 0}}, - {2881, {wxStyledTextEvent, getPosition, 0}}, - {2882, {wxStyledTextEvent, getKey, 0}}, - {2883, {wxStyledTextEvent, getModifiers, 0}}, - {2884, {wxStyledTextEvent, getModificationType, 0}}, - {2885, {wxStyledTextEvent, getText, 0}}, - {2886, {wxStyledTextEvent, getLength, 0}}, - {2887, {wxStyledTextEvent, getLinesAdded, 0}}, - {2888, {wxStyledTextEvent, getLine, 0}}, - {2889, {wxStyledTextEvent, getFoldLevelNow, 0}}, - {2890, {wxStyledTextEvent, getFoldLevelPrev, 0}}, - {2891, {wxStyledTextEvent, getMargin, 0}}, - {2892, {wxStyledTextEvent, getMessage, 0}}, - {2893, {wxStyledTextEvent, getWParam, 0}}, - {2894, {wxStyledTextEvent, getLParam, 0}}, - {2895, {wxStyledTextEvent, getListType, 0}}, - {2896, {wxStyledTextEvent, getX, 0}}, - {2897, {wxStyledTextEvent, getY, 0}}, - {2898, {wxStyledTextEvent, getDragText, 0}}, - {2899, {wxStyledTextEvent, getDragAllowMove, 0}}, - {2900, {wxStyledTextEvent, getDragResult, 0}}, - {2901, {wxStyledTextEvent, getShift, 0}}, - {2902, {wxStyledTextEvent, getControl, 0}}, - {2903, {wxStyledTextEvent, getAlt, 0}}, - {2904, {utils, getKeyState, 1}}, - {2905, {utils, getMousePosition, 2}}, - {2906, {utils, getMouseState, 0}}, - {2907, {utils, setDetectableAutoRepeat, 1}}, - {2908, {utils, bell, 0}}, - {2909, {utils, findMenuItemId, 3}}, - {2910, {utils, genericFindWindowAtPoint, 1}}, - {2911, {utils, findWindowAtPoint, 1}}, - {2912, {utils, beginBusyCursor, 1}}, - {2913, {utils, endBusyCursor, 0}}, - {2914, {utils, isBusy, 0}}, - {2915, {utils, shutdown, 1}}, - {2916, {utils, shell, 1}}, - {2917, {utils, launchDefaultBrowser, 2}}, - {2918, {utils, getEmailAddress, 0}}, - {2919, {utils, getUserId, 0}}, - {2920, {utils, getHomeDir, 0}}, - {2921, {utils, newId, 0}}, - {2922, {utils, registerId, 1}}, - {2923, {utils, getCurrentId, 0}}, - {2924, {utils, getOsDescription, 0}}, - {2925, {utils, isPlatformLittleEndian, 0}}, - {2926, {utils, isPlatform64Bit, 0}}, - {2927, {gdicmn, displaySize, 2}}, - {2928, {gdicmn, setCursor, 1}}, - {2929, {wxPrintout, new, 1}}, - {2930, {wxPrintout, destruct, 0}}, - {2931, {wxPrintout, getDC, 0}}, - {2932, {wxPrintout, getPageSizeMM, 2}}, - {2933, {wxPrintout, getPageSizePixels, 2}}, - {2934, {wxPrintout, getPaperRectPixels, 0}}, - {2935, {wxPrintout, getPPIPrinter, 2}}, - {2936, {wxPrintout, getPPIScreen, 2}}, - {2937, {wxPrintout, getTitle, 0}}, - {2938, {wxPrintout, isPreview, 0}}, - {2939, {wxPrintout, fitThisSizeToPaper, 1}}, - {2940, {wxPrintout, fitThisSizeToPage, 1}}, - {2941, {wxPrintout, fitThisSizeToPageMargins, 2}}, - {2942, {wxPrintout, mapScreenSizeToPaper, 0}}, - {2943, {wxPrintout, mapScreenSizeToPage, 0}}, - {2944, {wxPrintout, mapScreenSizeToPageMargins, 1}}, - {2945, {wxPrintout, mapScreenSizeToDevice, 0}}, - {2946, {wxPrintout, getLogicalPaperRect, 0}}, - {2947, {wxPrintout, getLogicalPageRect, 0}}, - {2948, {wxPrintout, getLogicalPageMarginsRect, 1}}, - {2949, {wxPrintout, setLogicalOrigin, 2}}, - {2950, {wxPrintout, offsetLogicalOrigin, 2}}, - {2951, {wxStyledTextCtrl, new_2, 2}}, - {2952, {wxStyledTextCtrl, new_0, 0}}, - {2953, {wxStyledTextCtrl, destruct, 0}}, - {2954, {wxStyledTextCtrl, create, 2}}, - {2955, {wxStyledTextCtrl, addText, 1}}, - {2956, {wxStyledTextCtrl, addStyledText, 1}}, - {2957, {wxStyledTextCtrl, insertText, 2}}, - {2958, {wxStyledTextCtrl, clearAll, 0}}, - {2959, {wxStyledTextCtrl, clearDocumentStyle, 0}}, - {2960, {wxStyledTextCtrl, getLength, 0}}, - {2961, {wxStyledTextCtrl, getCharAt, 1}}, - {2962, {wxStyledTextCtrl, getCurrentPos, 0}}, - {2963, {wxStyledTextCtrl, getAnchor, 0}}, - {2964, {wxStyledTextCtrl, getStyleAt, 1}}, - {2965, {wxStyledTextCtrl, redo, 0}}, - {2966, {wxStyledTextCtrl, setUndoCollection, 1}}, - {2967, {wxStyledTextCtrl, selectAll, 0}}, - {2968, {wxStyledTextCtrl, setSavePoint, 0}}, - {2969, {wxStyledTextCtrl, getStyledText, 2}}, - {2970, {wxStyledTextCtrl, canRedo, 0}}, - {2971, {wxStyledTextCtrl, markerLineFromHandle, 1}}, - {2972, {wxStyledTextCtrl, markerDeleteHandle, 1}}, - {2973, {wxStyledTextCtrl, getUndoCollection, 0}}, - {2974, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, - {2975, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, - {2976, {wxStyledTextCtrl, positionFromPoint, 1}}, - {2977, {wxStyledTextCtrl, positionFromPointClose, 2}}, - {2978, {wxStyledTextCtrl, gotoLine, 1}}, - {2979, {wxStyledTextCtrl, gotoPos, 1}}, - {2980, {wxStyledTextCtrl, setAnchor, 1}}, - {2981, {wxStyledTextCtrl, getCurLine, 1}}, - {2982, {wxStyledTextCtrl, getEndStyled, 0}}, - {2983, {wxStyledTextCtrl, convertEOLs, 1}}, - {2984, {wxStyledTextCtrl, getEOLMode, 0}}, - {2985, {wxStyledTextCtrl, setEOLMode, 1}}, - {2986, {wxStyledTextCtrl, startStyling, 2}}, - {2987, {wxStyledTextCtrl, setStyling, 2}}, - {2988, {wxStyledTextCtrl, getBufferedDraw, 0}}, - {2989, {wxStyledTextCtrl, setBufferedDraw, 1}}, - {2990, {wxStyledTextCtrl, setTabWidth, 1}}, - {2991, {wxStyledTextCtrl, getTabWidth, 0}}, - {2992, {wxStyledTextCtrl, setCodePage, 1}}, - {2993, {wxStyledTextCtrl, markerDefine, 3}}, - {2994, {wxStyledTextCtrl, markerSetForeground, 2}}, - {2995, {wxStyledTextCtrl, markerSetBackground, 2}}, - {2996, {wxStyledTextCtrl, markerAdd, 2}}, - {2997, {wxStyledTextCtrl, markerDelete, 2}}, - {2998, {wxStyledTextCtrl, markerDeleteAll, 1}}, - {2999, {wxStyledTextCtrl, markerGet, 1}}, - {3000, {wxStyledTextCtrl, markerNext, 2}}, - {3001, {wxStyledTextCtrl, markerPrevious, 2}}, - {3002, {wxStyledTextCtrl, markerDefineBitmap, 2}}, - {3003, {wxStyledTextCtrl, markerAddSet, 2}}, - {3004, {wxStyledTextCtrl, markerSetAlpha, 2}}, - {3005, {wxStyledTextCtrl, setMarginType, 2}}, - {3006, {wxStyledTextCtrl, getMarginType, 1}}, - {3007, {wxStyledTextCtrl, setMarginWidth, 2}}, - {3008, {wxStyledTextCtrl, getMarginWidth, 1}}, - {3009, {wxStyledTextCtrl, setMarginMask, 2}}, - {3010, {wxStyledTextCtrl, getMarginMask, 1}}, - {3011, {wxStyledTextCtrl, setMarginSensitive, 2}}, - {3012, {wxStyledTextCtrl, getMarginSensitive, 1}}, - {3013, {wxStyledTextCtrl, styleClearAll, 0}}, - {3014, {wxStyledTextCtrl, styleSetForeground, 2}}, - {3015, {wxStyledTextCtrl, styleSetBackground, 2}}, - {3016, {wxStyledTextCtrl, styleSetBold, 2}}, - {3017, {wxStyledTextCtrl, styleSetItalic, 2}}, - {3018, {wxStyledTextCtrl, styleSetSize, 2}}, - {3019, {wxStyledTextCtrl, styleSetFaceName, 2}}, - {3020, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, - {3021, {wxStyledTextCtrl, styleResetDefault, 0}}, - {3022, {wxStyledTextCtrl, styleSetUnderline, 2}}, - {3023, {wxStyledTextCtrl, styleSetCase, 2}}, - {3024, {wxStyledTextCtrl, styleSetHotSpot, 2}}, - {3025, {wxStyledTextCtrl, setSelForeground, 2}}, - {3026, {wxStyledTextCtrl, setSelBackground, 2}}, - {3027, {wxStyledTextCtrl, getSelAlpha, 0}}, - {3028, {wxStyledTextCtrl, setSelAlpha, 1}}, - {3029, {wxStyledTextCtrl, setCaretForeground, 1}}, - {3030, {wxStyledTextCtrl, cmdKeyAssign, 3}}, - {3031, {wxStyledTextCtrl, cmdKeyClear, 2}}, - {3032, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, - {3033, {wxStyledTextCtrl, setStyleBytes, 2}}, - {3034, {wxStyledTextCtrl, styleSetVisible, 2}}, - {3035, {wxStyledTextCtrl, getCaretPeriod, 0}}, - {3036, {wxStyledTextCtrl, setCaretPeriod, 1}}, - {3037, {wxStyledTextCtrl, setWordChars, 1}}, - {3038, {wxStyledTextCtrl, beginUndoAction, 0}}, - {3039, {wxStyledTextCtrl, endUndoAction, 0}}, - {3040, {wxStyledTextCtrl, indicatorSetStyle, 2}}, - {3041, {wxStyledTextCtrl, indicatorGetStyle, 1}}, - {3042, {wxStyledTextCtrl, indicatorSetForeground, 2}}, - {3043, {wxStyledTextCtrl, indicatorGetForeground, 1}}, - {3044, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, - {3045, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, - {3046, {wxStyledTextCtrl, getStyleBits, 0}}, - {3047, {wxStyledTextCtrl, setLineState, 2}}, - {3048, {wxStyledTextCtrl, getLineState, 1}}, - {3049, {wxStyledTextCtrl, getMaxLineState, 0}}, - {3050, {wxStyledTextCtrl, getCaretLineVisible, 0}}, - {3051, {wxStyledTextCtrl, setCaretLineVisible, 1}}, - {3052, {wxStyledTextCtrl, getCaretLineBackground, 0}}, - {3053, {wxStyledTextCtrl, setCaretLineBackground, 1}}, - {3054, {wxStyledTextCtrl, autoCompShow, 2}}, - {3055, {wxStyledTextCtrl, autoCompCancel, 0}}, - {3056, {wxStyledTextCtrl, autoCompActive, 0}}, - {3057, {wxStyledTextCtrl, autoCompPosStart, 0}}, - {3058, {wxStyledTextCtrl, autoCompComplete, 0}}, - {3059, {wxStyledTextCtrl, autoCompStops, 1}}, - {3060, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, - {3061, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, - {3062, {wxStyledTextCtrl, autoCompSelect, 1}}, - {3063, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, - {3064, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, - {3065, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, - {3066, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, - {3067, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, - {3068, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, - {3069, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, - {3070, {wxStyledTextCtrl, userListShow, 2}}, - {3071, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, - {3072, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, - {3073, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, - {3074, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, - {3075, {wxStyledTextCtrl, registerImage, 2}}, - {3076, {wxStyledTextCtrl, clearRegisteredImages, 0}}, - {3077, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, - {3078, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, - {3079, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, - {3080, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, - {3081, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, - {3082, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, - {3083, {wxStyledTextCtrl, setIndent, 1}}, - {3084, {wxStyledTextCtrl, getIndent, 0}}, - {3085, {wxStyledTextCtrl, setUseTabs, 1}}, - {3086, {wxStyledTextCtrl, getUseTabs, 0}}, - {3087, {wxStyledTextCtrl, setLineIndentation, 2}}, - {3088, {wxStyledTextCtrl, getLineIndentation, 1}}, - {3089, {wxStyledTextCtrl, getLineIndentPosition, 1}}, - {3090, {wxStyledTextCtrl, getColumn, 1}}, - {3091, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, - {3092, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, - {3093, {wxStyledTextCtrl, setIndentationGuides, 1}}, - {3094, {wxStyledTextCtrl, getIndentationGuides, 0}}, - {3095, {wxStyledTextCtrl, setHighlightGuide, 1}}, - {3096, {wxStyledTextCtrl, getHighlightGuide, 0}}, - {3097, {wxStyledTextCtrl, getLineEndPosition, 1}}, - {3098, {wxStyledTextCtrl, getCodePage, 0}}, - {3099, {wxStyledTextCtrl, getCaretForeground, 0}}, - {3100, {wxStyledTextCtrl, getReadOnly, 0}}, - {3101, {wxStyledTextCtrl, setCurrentPos, 1}}, - {3102, {wxStyledTextCtrl, setSelectionStart, 1}}, - {3103, {wxStyledTextCtrl, getSelectionStart, 0}}, - {3104, {wxStyledTextCtrl, setSelectionEnd, 1}}, - {3105, {wxStyledTextCtrl, getSelectionEnd, 0}}, - {3106, {wxStyledTextCtrl, setPrintMagnification, 1}}, - {3107, {wxStyledTextCtrl, getPrintMagnification, 0}}, - {3108, {wxStyledTextCtrl, setPrintColourMode, 1}}, - {3109, {wxStyledTextCtrl, getPrintColourMode, 0}}, - {3110, {wxStyledTextCtrl, findText, 4}}, - {3111, {wxStyledTextCtrl, formatRange, 7}}, - {3112, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, - {3113, {wxStyledTextCtrl, getLine, 1}}, - {3114, {wxStyledTextCtrl, getLineCount, 0}}, - {3115, {wxStyledTextCtrl, setMarginLeft, 1}}, - {3116, {wxStyledTextCtrl, getMarginLeft, 0}}, - {3117, {wxStyledTextCtrl, setMarginRight, 1}}, - {3118, {wxStyledTextCtrl, getMarginRight, 0}}, - {3119, {wxStyledTextCtrl, getModify, 0}}, - {3120, {wxStyledTextCtrl, setSelection, 2}}, - {3121, {wxStyledTextCtrl, getSelectedText, 0}}, - {3122, {wxStyledTextCtrl, getTextRange, 2}}, - {3123, {wxStyledTextCtrl, hideSelection, 1}}, - {3124, {wxStyledTextCtrl, lineFromPosition, 1}}, - {3125, {wxStyledTextCtrl, positionFromLine, 1}}, - {3126, {wxStyledTextCtrl, lineScroll, 2}}, - {3127, {wxStyledTextCtrl, ensureCaretVisible, 0}}, - {3128, {wxStyledTextCtrl, replaceSelection, 1}}, - {3129, {wxStyledTextCtrl, setReadOnly, 1}}, - {3130, {wxStyledTextCtrl, canPaste, 0}}, - {3131, {wxStyledTextCtrl, canUndo, 0}}, - {3132, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, - {3133, {wxStyledTextCtrl, undo, 0}}, - {3134, {wxStyledTextCtrl, cut, 0}}, - {3135, {wxStyledTextCtrl, copy, 0}}, - {3136, {wxStyledTextCtrl, paste, 0}}, - {3137, {wxStyledTextCtrl, clear, 0}}, - {3138, {wxStyledTextCtrl, setText, 1}}, - {3139, {wxStyledTextCtrl, getText, 0}}, - {3140, {wxStyledTextCtrl, getTextLength, 0}}, - {3141, {wxStyledTextCtrl, getOvertype, 0}}, - {3142, {wxStyledTextCtrl, setCaretWidth, 1}}, - {3143, {wxStyledTextCtrl, getCaretWidth, 0}}, - {3144, {wxStyledTextCtrl, setTargetStart, 1}}, - {3145, {wxStyledTextCtrl, getTargetStart, 0}}, - {3146, {wxStyledTextCtrl, setTargetEnd, 1}}, - {3147, {wxStyledTextCtrl, getTargetEnd, 0}}, - {3148, {wxStyledTextCtrl, replaceTarget, 1}}, - {3149, {wxStyledTextCtrl, searchInTarget, 1}}, - {3150, {wxStyledTextCtrl, setSearchFlags, 1}}, - {3151, {wxStyledTextCtrl, getSearchFlags, 0}}, - {3152, {wxStyledTextCtrl, callTipShow, 2}}, - {3153, {wxStyledTextCtrl, callTipCancel, 0}}, - {3154, {wxStyledTextCtrl, callTipActive, 0}}, - {3155, {wxStyledTextCtrl, callTipPosAtStart, 0}}, - {3156, {wxStyledTextCtrl, callTipSetHighlight, 2}}, - {3157, {wxStyledTextCtrl, callTipSetBackground, 1}}, - {3158, {wxStyledTextCtrl, callTipSetForeground, 1}}, - {3159, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, - {3160, {wxStyledTextCtrl, callTipUseStyle, 1}}, - {3161, {wxStyledTextCtrl, visibleFromDocLine, 1}}, - {3162, {wxStyledTextCtrl, docLineFromVisible, 1}}, - {3163, {wxStyledTextCtrl, wrapCount, 1}}, - {3164, {wxStyledTextCtrl, setFoldLevel, 2}}, - {3165, {wxStyledTextCtrl, getFoldLevel, 1}}, - {3166, {wxStyledTextCtrl, getLastChild, 2}}, - {3167, {wxStyledTextCtrl, getFoldParent, 1}}, - {3168, {wxStyledTextCtrl, showLines, 2}}, - {3169, {wxStyledTextCtrl, hideLines, 2}}, - {3170, {wxStyledTextCtrl, getLineVisible, 1}}, - {3171, {wxStyledTextCtrl, setFoldExpanded, 2}}, - {3172, {wxStyledTextCtrl, getFoldExpanded, 1}}, - {3173, {wxStyledTextCtrl, toggleFold, 1}}, - {3174, {wxStyledTextCtrl, ensureVisible, 1}}, - {3175, {wxStyledTextCtrl, setFoldFlags, 1}}, - {3176, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, - {3177, {wxStyledTextCtrl, setTabIndents, 1}}, - {3178, {wxStyledTextCtrl, getTabIndents, 0}}, - {3179, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, - {3180, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, - {3181, {wxStyledTextCtrl, setMouseDwellTime, 1}}, - {3182, {wxStyledTextCtrl, getMouseDwellTime, 0}}, - {3183, {wxStyledTextCtrl, wordStartPosition, 2}}, - {3184, {wxStyledTextCtrl, wordEndPosition, 2}}, - {3185, {wxStyledTextCtrl, setWrapMode, 1}}, - {3186, {wxStyledTextCtrl, getWrapMode, 0}}, - {3187, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, - {3188, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, - {3189, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, - {3190, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, - {3191, {wxStyledTextCtrl, setWrapStartIndent, 1}}, - {3192, {wxStyledTextCtrl, getWrapStartIndent, 0}}, - {3193, {wxStyledTextCtrl, setLayoutCache, 1}}, - {3194, {wxStyledTextCtrl, getLayoutCache, 0}}, - {3195, {wxStyledTextCtrl, setScrollWidth, 1}}, - {3196, {wxStyledTextCtrl, getScrollWidth, 0}}, - {3197, {wxStyledTextCtrl, textWidth, 2}}, - {3198, {wxStyledTextCtrl, getEndAtLastLine, 0}}, - {3199, {wxStyledTextCtrl, textHeight, 1}}, - {3200, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, - {3201, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, - {3202, {wxStyledTextCtrl, appendText, 1}}, - {3203, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, - {3204, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, - {3205, {wxStyledTextCtrl, targetFromSelection, 0}}, - {3206, {wxStyledTextCtrl, linesJoin, 0}}, - {3207, {wxStyledTextCtrl, linesSplit, 1}}, - {3208, {wxStyledTextCtrl, setFoldMarginColour, 2}}, - {3209, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, - {3210, {wxStyledTextCtrl, lineDown, 0}}, - {3211, {wxStyledTextCtrl, lineDownExtend, 0}}, - {3212, {wxStyledTextCtrl, lineUp, 0}}, - {3213, {wxStyledTextCtrl, lineUpExtend, 0}}, - {3214, {wxStyledTextCtrl, charLeft, 0}}, - {3215, {wxStyledTextCtrl, charLeftExtend, 0}}, - {3216, {wxStyledTextCtrl, charRight, 0}}, - {3217, {wxStyledTextCtrl, charRightExtend, 0}}, - {3218, {wxStyledTextCtrl, wordLeft, 0}}, - {3219, {wxStyledTextCtrl, wordLeftExtend, 0}}, - {3220, {wxStyledTextCtrl, wordRight, 0}}, - {3221, {wxStyledTextCtrl, wordRightExtend, 0}}, - {3222, {wxStyledTextCtrl, home, 0}}, - {3223, {wxStyledTextCtrl, homeExtend, 0}}, - {3224, {wxStyledTextCtrl, lineEnd, 0}}, - {3225, {wxStyledTextCtrl, lineEndExtend, 0}}, - {3226, {wxStyledTextCtrl, documentStart, 0}}, - {3227, {wxStyledTextCtrl, documentStartExtend, 0}}, - {3228, {wxStyledTextCtrl, documentEnd, 0}}, - {3229, {wxStyledTextCtrl, documentEndExtend, 0}}, - {3230, {wxStyledTextCtrl, pageUp, 0}}, - {3231, {wxStyledTextCtrl, pageUpExtend, 0}}, - {3232, {wxStyledTextCtrl, pageDown, 0}}, - {3233, {wxStyledTextCtrl, pageDownExtend, 0}}, - {3234, {wxStyledTextCtrl, editToggleOvertype, 0}}, - {3235, {wxStyledTextCtrl, cancel, 0}}, - {3236, {wxStyledTextCtrl, deleteBack, 0}}, - {3237, {wxStyledTextCtrl, tab, 0}}, - {3238, {wxStyledTextCtrl, backTab, 0}}, - {3239, {wxStyledTextCtrl, newLine, 0}}, - {3240, {wxStyledTextCtrl, formFeed, 0}}, - {3241, {wxStyledTextCtrl, vCHome, 0}}, - {3242, {wxStyledTextCtrl, vCHomeExtend, 0}}, - {3243, {wxStyledTextCtrl, zoomIn, 0}}, - {3244, {wxStyledTextCtrl, zoomOut, 0}}, - {3245, {wxStyledTextCtrl, delWordLeft, 0}}, - {3246, {wxStyledTextCtrl, delWordRight, 0}}, - {3247, {wxStyledTextCtrl, lineCut, 0}}, - {3248, {wxStyledTextCtrl, lineDelete, 0}}, - {3249, {wxStyledTextCtrl, lineTranspose, 0}}, - {3250, {wxStyledTextCtrl, lineDuplicate, 0}}, - {3251, {wxStyledTextCtrl, lowerCase, 0}}, - {3252, {wxStyledTextCtrl, upperCase, 0}}, - {3253, {wxStyledTextCtrl, lineScrollDown, 0}}, - {3254, {wxStyledTextCtrl, lineScrollUp, 0}}, - {3255, {wxStyledTextCtrl, deleteBackNotLine, 0}}, - {3256, {wxStyledTextCtrl, homeDisplay, 0}}, - {3257, {wxStyledTextCtrl, homeDisplayExtend, 0}}, - {3258, {wxStyledTextCtrl, lineEndDisplay, 0}}, - {3259, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, - {3260, {wxStyledTextCtrl, homeWrapExtend, 0}}, - {3261, {wxStyledTextCtrl, lineEndWrap, 0}}, - {3262, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, - {3263, {wxStyledTextCtrl, vCHomeWrap, 0}}, - {3264, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, - {3265, {wxStyledTextCtrl, lineCopy, 0}}, - {3266, {wxStyledTextCtrl, moveCaretInsideView, 0}}, - {3267, {wxStyledTextCtrl, lineLength, 1}}, - {3268, {wxStyledTextCtrl, braceHighlight, 2}}, - {3269, {wxStyledTextCtrl, braceBadLight, 1}}, - {3270, {wxStyledTextCtrl, braceMatch, 1}}, - {3271, {wxStyledTextCtrl, getViewEOL, 0}}, - {3272, {wxStyledTextCtrl, setViewEOL, 1}}, - {3273, {wxStyledTextCtrl, setModEventMask, 1}}, - {3274, {wxStyledTextCtrl, getEdgeColumn, 0}}, - {3275, {wxStyledTextCtrl, setEdgeColumn, 1}}, - {3276, {wxStyledTextCtrl, setEdgeMode, 1}}, - {3277, {wxStyledTextCtrl, getEdgeMode, 0}}, - {3278, {wxStyledTextCtrl, getEdgeColour, 0}}, - {3279, {wxStyledTextCtrl, setEdgeColour, 1}}, - {3280, {wxStyledTextCtrl, searchAnchor, 0}}, - {3281, {wxStyledTextCtrl, searchNext, 2}}, - {3282, {wxStyledTextCtrl, searchPrev, 2}}, - {3283, {wxStyledTextCtrl, linesOnScreen, 0}}, - {3284, {wxStyledTextCtrl, usePopUp, 1}}, - {3285, {wxStyledTextCtrl, selectionIsRectangle, 0}}, - {3286, {wxStyledTextCtrl, setZoom, 1}}, - {3287, {wxStyledTextCtrl, getZoom, 0}}, - {3288, {wxStyledTextCtrl, getModEventMask, 0}}, - {3289, {wxStyledTextCtrl, setSTCFocus, 1}}, - {3290, {wxStyledTextCtrl, getSTCFocus, 0}}, - {3291, {wxStyledTextCtrl, setStatus, 1}}, - {3292, {wxStyledTextCtrl, getStatus, 0}}, - {3293, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, - {3294, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, - {3295, {wxStyledTextCtrl, setSTCCursor, 1}}, - {3296, {wxStyledTextCtrl, getSTCCursor, 0}}, - {3297, {wxStyledTextCtrl, setControlCharSymbol, 1}}, - {3298, {wxStyledTextCtrl, getControlCharSymbol, 0}}, - {3299, {wxStyledTextCtrl, wordPartLeft, 0}}, - {3300, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, - {3301, {wxStyledTextCtrl, wordPartRight, 0}}, - {3302, {wxStyledTextCtrl, wordPartRightExtend, 0}}, - {3303, {wxStyledTextCtrl, setVisiblePolicy, 2}}, - {3304, {wxStyledTextCtrl, delLineLeft, 0}}, - {3305, {wxStyledTextCtrl, delLineRight, 0}}, - {3306, {wxStyledTextCtrl, getXOffset, 0}}, - {3307, {wxStyledTextCtrl, chooseCaretX, 0}}, - {3308, {wxStyledTextCtrl, setXCaretPolicy, 2}}, - {3309, {wxStyledTextCtrl, setYCaretPolicy, 2}}, - {3310, {wxStyledTextCtrl, getPrintWrapMode, 0}}, - {3311, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, - {3312, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, - {3313, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, - {3314, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, - {3315, {wxStyledTextCtrl, paraDownExtend, 0}}, - {3316, {wxStyledTextCtrl, paraUp, 0}}, - {3317, {wxStyledTextCtrl, paraUpExtend, 0}}, - {3318, {wxStyledTextCtrl, positionBefore, 1}}, - {3319, {wxStyledTextCtrl, positionAfter, 1}}, - {3320, {wxStyledTextCtrl, copyRange, 2}}, - {3321, {wxStyledTextCtrl, copyText, 2}}, - {3322, {wxStyledTextCtrl, setSelectionMode, 1}}, - {3323, {wxStyledTextCtrl, getSelectionMode, 0}}, - {3324, {wxStyledTextCtrl, lineDownRectExtend, 0}}, - {3325, {wxStyledTextCtrl, lineUpRectExtend, 0}}, - {3326, {wxStyledTextCtrl, charLeftRectExtend, 0}}, - {3327, {wxStyledTextCtrl, charRightRectExtend, 0}}, - {3328, {wxStyledTextCtrl, homeRectExtend, 0}}, - {3329, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, - {3330, {wxStyledTextCtrl, lineEndRectExtend, 0}}, - {3331, {wxStyledTextCtrl, pageUpRectExtend, 0}}, - {3332, {wxStyledTextCtrl, pageDownRectExtend, 0}}, - {3333, {wxStyledTextCtrl, stutteredPageUp, 0}}, - {3334, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, - {3335, {wxStyledTextCtrl, stutteredPageDown, 0}}, - {3336, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, - {3337, {wxStyledTextCtrl, wordLeftEnd, 0}}, - {3338, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, - {3339, {wxStyledTextCtrl, wordRightEnd, 0}}, - {3340, {wxStyledTextCtrl, wordRightEndExtend, 0}}, - {3341, {wxStyledTextCtrl, setWhitespaceChars, 1}}, - {3342, {wxStyledTextCtrl, setCharsDefault, 0}}, - {3343, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, - {3344, {wxStyledTextCtrl, allocate, 1}}, - {3345, {wxStyledTextCtrl, findColumn, 2}}, - {3346, {wxStyledTextCtrl, getCaretSticky, 0}}, - {3347, {wxStyledTextCtrl, setCaretSticky, 1}}, - {3348, {wxStyledTextCtrl, toggleCaretSticky, 0}}, - {3349, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, - {3350, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, - {3351, {wxStyledTextCtrl, selectionDuplicate, 0}}, - {3352, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, - {3353, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, - {3354, {wxStyledTextCtrl, startRecord, 0}}, - {3355, {wxStyledTextCtrl, stopRecord, 0}}, - {3356, {wxStyledTextCtrl, setLexer, 1}}, - {3357, {wxStyledTextCtrl, getLexer, 0}}, - {3358, {wxStyledTextCtrl, colourise, 2}}, - {3359, {wxStyledTextCtrl, setProperty, 2}}, - {3360, {wxStyledTextCtrl, setKeyWords, 2}}, - {3361, {wxStyledTextCtrl, setLexerLanguage, 1}}, - {3362, {wxStyledTextCtrl, getProperty, 1}}, - {3363, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, - {3364, {wxStyledTextCtrl, getCurrentLine, 0}}, - {3365, {wxStyledTextCtrl, styleSetSpec, 2}}, - {3366, {wxStyledTextCtrl, styleSetFont, 2}}, - {3367, {wxStyledTextCtrl, styleSetFontAttr, 7}}, - {3368, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, - {3369, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, - {3370, {wxStyledTextCtrl, cmdKeyExecute, 1}}, - {3371, {wxStyledTextCtrl, setMargins, 2}}, - {3372, {wxStyledTextCtrl, getSelection, 2}}, - {3373, {wxStyledTextCtrl, pointFromPosition, 1}}, - {3374, {wxStyledTextCtrl, scrollToLine, 1}}, - {3375, {wxStyledTextCtrl, scrollToColumn, 1}}, - {3376, {wxStyledTextCtrl, setVScrollBar, 1}}, - {3377, {wxStyledTextCtrl, setHScrollBar, 1}}, - {3378, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, - {3379, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, - {3380, {wxStyledTextCtrl, saveFile, 1}}, - {3381, {wxStyledTextCtrl, loadFile, 1}}, - {3382, {wxStyledTextCtrl, doDragOver, 3}}, - {3383, {wxStyledTextCtrl, doDropText, 3}}, - {3384, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, - {3385, {wxStyledTextCtrl, addTextRaw, 1}}, - {3386, {wxStyledTextCtrl, insertTextRaw, 2}}, - {3387, {wxStyledTextCtrl, getCurLineRaw, 1}}, - {3388, {wxStyledTextCtrl, getLineRaw, 1}}, - {3389, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, - {3390, {wxStyledTextCtrl, getTextRangeRaw, 2}}, - {3391, {wxStyledTextCtrl, setTextRaw, 1}}, - {3392, {wxStyledTextCtrl, getTextRaw, 0}}, - {3393, {wxStyledTextCtrl, appendTextRaw, 1}}, - {3394, {wxArtProvider, getBitmap, 2}}, - {3395, {wxArtProvider, getIcon, 2}}, - {3396, {wxTreeEvent, getKeyCode, 0}}, - {3397, {wxTreeEvent, getItem, 0}}, - {3398, {wxTreeEvent, getKeyEvent, 0}}, - {3399, {wxTreeEvent, getLabel, 0}}, - {3400, {wxTreeEvent, getOldItem, 0}}, - {3401, {wxTreeEvent, getPoint, 0}}, - {3402, {wxTreeEvent, isEditCancelled, 0}}, - {3403, {wxTreeEvent, setToolTip, 1}}, - {3404, {wxNotebookEvent, getOldSelection, 0}}, - {3405, {wxNotebookEvent, getSelection, 0}}, - {3406, {wxNotebookEvent, setOldSelection, 1}}, - {3407, {wxNotebookEvent, setSelection, 1}}, - {3408, {wxFileDataObject, new, 0}}, - {3409, {wxFileDataObject, addFile, 1}}, - {3410, {wxFileDataObject, getFilenames, 0}}, - {3411, {wxFileDataObject, 'Destroy', undefined}}, - {3412, {wxTextDataObject, new, 1}}, - {3413, {wxTextDataObject, getTextLength, 0}}, - {3414, {wxTextDataObject, getText, 0}}, - {3415, {wxTextDataObject, setText, 1}}, - {3416, {wxTextDataObject, 'Destroy', undefined}}, - {3417, {wxBitmapDataObject, new_1_1, 1}}, - {3418, {wxBitmapDataObject, new_1_0, 1}}, - {3419, {wxBitmapDataObject, getBitmap, 0}}, - {3420, {wxBitmapDataObject, setBitmap, 1}}, - {3421, {wxBitmapDataObject, 'Destroy', undefined}}, - {3423, {wxClipboard, new, 0}}, - {3424, {wxClipboard, destruct, 0}}, - {3425, {wxClipboard, addData, 1}}, - {3426, {wxClipboard, clear, 0}}, - {3427, {wxClipboard, close, 0}}, - {3428, {wxClipboard, flush, 0}}, - {3429, {wxClipboard, getData, 1}}, - {3430, {wxClipboard, isOpened, 0}}, - {3431, {wxClipboard, open, 0}}, - {3432, {wxClipboard, setData, 1}}, - {3434, {wxClipboard, usePrimarySelection, 1}}, - {3435, {wxClipboard, isSupported, 1}}, - {3436, {wxClipboard, get, 0}}, - {3437, {wxSpinEvent, getPosition, 0}}, - {3438, {wxSpinEvent, setPosition, 1}}, - {3439, {wxSplitterWindow, new_0, 0}}, - {3440, {wxSplitterWindow, new_2, 2}}, - {3441, {wxSplitterWindow, destruct, 0}}, - {3442, {wxSplitterWindow, create, 2}}, - {3443, {wxSplitterWindow, getMinimumPaneSize, 0}}, - {3444, {wxSplitterWindow, getSashGravity, 0}}, - {3445, {wxSplitterWindow, getSashPosition, 0}}, - {3446, {wxSplitterWindow, getSplitMode, 0}}, - {3447, {wxSplitterWindow, getWindow1, 0}}, - {3448, {wxSplitterWindow, getWindow2, 0}}, - {3449, {wxSplitterWindow, initialize, 1}}, - {3450, {wxSplitterWindow, isSplit, 0}}, - {3451, {wxSplitterWindow, replaceWindow, 2}}, - {3452, {wxSplitterWindow, setSashGravity, 1}}, - {3453, {wxSplitterWindow, setSashPosition, 2}}, - {3454, {wxSplitterWindow, setSashSize, 1}}, - {3455, {wxSplitterWindow, setMinimumPaneSize, 1}}, - {3456, {wxSplitterWindow, setSplitMode, 1}}, - {3457, {wxSplitterWindow, splitHorizontally, 3}}, - {3458, {wxSplitterWindow, splitVertically, 3}}, - {3459, {wxSplitterWindow, unsplit, 1}}, - {3460, {wxSplitterWindow, updateSize, 0}}, - {3461, {wxSplitterEvent, getSashPosition, 0}}, - {3462, {wxSplitterEvent, getX, 0}}, - {3463, {wxSplitterEvent, getY, 0}}, - {3464, {wxSplitterEvent, getWindowBeingRemoved, 0}}, - {3465, {wxSplitterEvent, setSashPosition, 1}}, - {3466, {wxHtmlWindow, new_0, 0}}, - {3467, {wxHtmlWindow, new_2, 2}}, - {3468, {wxHtmlWindow, appendToPage, 1}}, - {3469, {wxHtmlWindow, getOpenedAnchor, 0}}, - {3470, {wxHtmlWindow, getOpenedPage, 0}}, - {3471, {wxHtmlWindow, getOpenedPageTitle, 0}}, - {3472, {wxHtmlWindow, getRelatedFrame, 0}}, - {3473, {wxHtmlWindow, historyBack, 0}}, - {3474, {wxHtmlWindow, historyCanBack, 0}}, - {3475, {wxHtmlWindow, historyCanForward, 0}}, - {3476, {wxHtmlWindow, historyClear, 0}}, - {3477, {wxHtmlWindow, historyForward, 0}}, - {3478, {wxHtmlWindow, loadFile, 1}}, - {3479, {wxHtmlWindow, loadPage, 1}}, - {3480, {wxHtmlWindow, selectAll, 0}}, - {3481, {wxHtmlWindow, selectionToText, 0}}, - {3482, {wxHtmlWindow, selectLine, 1}}, - {3483, {wxHtmlWindow, selectWord, 1}}, - {3484, {wxHtmlWindow, setBorders, 1}}, - {3485, {wxHtmlWindow, setFonts, 3}}, - {3486, {wxHtmlWindow, setPage, 1}}, - {3487, {wxHtmlWindow, setRelatedFrame, 2}}, - {3488, {wxHtmlWindow, setRelatedStatusBar, 1}}, - {3489, {wxHtmlWindow, toText, 0}}, - {3490, {wxHtmlWindow, 'Destroy', undefined}}, - {3491, {wxHtmlLinkEvent, getLinkInfo, 0}}, - {3492, {wxSystemSettings, getColour, 1}}, - {3493, {wxSystemSettings, getFont, 1}}, - {3494, {wxSystemSettings, getMetric, 2}}, - {3495, {wxSystemSettings, getScreenType, 0}}, - {3496, {wxSystemOptions, getOption, 1}}, - {3497, {wxSystemOptions, getOptionInt, 1}}, - {3498, {wxSystemOptions, hasOption, 1}}, - {3499, {wxSystemOptions, isFalse, 1}}, - {3500, {wxSystemOptions, setOption_2_1, 2}}, - {3501, {wxSystemOptions, setOption_2_0, 2}}, - {3502, {wxAuiNotebookEvent, setSelection, 1}}, - {3503, {wxAuiNotebookEvent, getSelection, 0}}, - {3504, {wxAuiNotebookEvent, setOldSelection, 1}}, - {3505, {wxAuiNotebookEvent, getOldSelection, 0}}, - {3506, {wxAuiNotebookEvent, setDragSource, 1}}, - {3507, {wxAuiNotebookEvent, getDragSource, 0}}, - {3508, {wxAuiManagerEvent, setManager, 1}}, - {3509, {wxAuiManagerEvent, getManager, 0}}, - {3510, {wxAuiManagerEvent, setPane, 1}}, - {3511, {wxAuiManagerEvent, getPane, 0}}, - {3512, {wxAuiManagerEvent, setButton, 1}}, - {3513, {wxAuiManagerEvent, getButton, 0}}, - {3514, {wxAuiManagerEvent, setDC, 1}}, - {3515, {wxAuiManagerEvent, getDC, 0}}, - {3516, {wxAuiManagerEvent, veto, 1}}, - {3517, {wxAuiManagerEvent, getVeto, 0}}, - {3518, {wxAuiManagerEvent, setCanVeto, 1}}, - {3519, {wxAuiManagerEvent, canVeto, 0}}, - {3520, {wxLogNull, new, 0}}, - {3521, {wxLogNull, 'Destroy', undefined}}, - {3522, {wxTaskBarIcon, new, 0}}, - {3523, {wxTaskBarIcon, destruct, 0}}, - {3524, {wxTaskBarIcon, popupMenu, 1}}, - {3525, {wxTaskBarIcon, removeIcon, 0}}, - {3526, {wxTaskBarIcon, setIcon, 2}}, - {3527, {wxLocale, new_0, 0}}, - {3529, {wxLocale, new_2, 2}}, - {3530, {wxLocale, destruct, 0}}, - {3532, {wxLocale, init, 1}}, - {3533, {wxLocale, addCatalog_1, 1}}, - {3534, {wxLocale, addCatalog_3, 3}}, - {3535, {wxLocale, addCatalogLookupPathPrefix, 1}}, - {3536, {wxLocale, getCanonicalName, 0}}, - {3537, {wxLocale, getLanguage, 0}}, - {3538, {wxLocale, getLanguageName, 1}}, - {3539, {wxLocale, getLocale, 0}}, - {3540, {wxLocale, getName, 0}}, - {3541, {wxLocale, getString_2, 2}}, - {3542, {wxLocale, getString_4, 4}}, - {3543, {wxLocale, getHeaderValue, 2}}, - {3544, {wxLocale, getSysName, 0}}, - {3545, {wxLocale, getSystemEncoding, 0}}, - {3546, {wxLocale, getSystemEncodingName, 0}}, - {3547, {wxLocale, getSystemLanguage, 0}}, - {3548, {wxLocale, isLoaded, 1}}, - {3549, {wxLocale, isOk, 0}}, + {1827, {wxTextCtrl, changeValue, 1}}, + {1828, {wxTextCtrl, emulateKeyPress, 1}}, + {1829, {wxTextCtrl, getDefaultStyle, 0}}, + {1830, {wxTextCtrl, getInsertionPoint, 0}}, + {1831, {wxTextCtrl, getLastPosition, 0}}, + {1832, {wxTextCtrl, getLineLength, 1}}, + {1833, {wxTextCtrl, getLineText, 1}}, + {1834, {wxTextCtrl, getNumberOfLines, 0}}, + {1835, {wxTextCtrl, getRange, 2}}, + {1836, {wxTextCtrl, getSelection, 2}}, + {1837, {wxTextCtrl, getStringSelection, 0}}, + {1838, {wxTextCtrl, getStyle, 2}}, + {1839, {wxTextCtrl, getValue, 0}}, + {1840, {wxTextCtrl, isEditable, 0}}, + {1841, {wxTextCtrl, isModified, 0}}, + {1842, {wxTextCtrl, isMultiLine, 0}}, + {1843, {wxTextCtrl, isSingleLine, 0}}, + {1844, {wxTextCtrl, loadFile, 2}}, + {1845, {wxTextCtrl, markDirty, 0}}, + {1846, {wxTextCtrl, paste, 0}}, + {1847, {wxTextCtrl, positionToXY, 3}}, + {1848, {wxTextCtrl, redo, 0}}, + {1849, {wxTextCtrl, remove, 2}}, + {1850, {wxTextCtrl, replace, 3}}, + {1851, {wxTextCtrl, saveFile, 1}}, + {1852, {wxTextCtrl, setDefaultStyle, 1}}, + {1853, {wxTextCtrl, setEditable, 1}}, + {1854, {wxTextCtrl, setInsertionPoint, 1}}, + {1855, {wxTextCtrl, setInsertionPointEnd, 0}}, + {1857, {wxTextCtrl, setMaxLength, 1}}, + {1858, {wxTextCtrl, setSelection, 2}}, + {1859, {wxTextCtrl, setStyle, 3}}, + {1860, {wxTextCtrl, setValue, 1}}, + {1861, {wxTextCtrl, showPosition, 1}}, + {1862, {wxTextCtrl, undo, 0}}, + {1863, {wxTextCtrl, writeText, 1}}, + {1864, {wxTextCtrl, xYToPosition, 2}}, + {1867, {wxNotebook, new_0, 0}}, + {1868, {wxNotebook, new_3, 3}}, + {1869, {wxNotebook, destruct, 0}}, + {1870, {wxNotebook, addPage, 3}}, + {1871, {wxNotebook, advanceSelection, 1}}, + {1872, {wxNotebook, assignImageList, 1}}, + {1873, {wxNotebook, create, 3}}, + {1874, {wxNotebook, deleteAllPages, 0}}, + {1875, {wxNotebook, deletePage, 1}}, + {1876, {wxNotebook, removePage, 1}}, + {1877, {wxNotebook, getCurrentPage, 0}}, + {1878, {wxNotebook, getImageList, 0}}, + {1880, {wxNotebook, getPage, 1}}, + {1881, {wxNotebook, getPageCount, 0}}, + {1882, {wxNotebook, getPageImage, 1}}, + {1883, {wxNotebook, getPageText, 1}}, + {1884, {wxNotebook, getRowCount, 0}}, + {1885, {wxNotebook, getSelection, 0}}, + {1886, {wxNotebook, getThemeBackgroundColour, 0}}, + {1888, {wxNotebook, hitTest, 2}}, + {1890, {wxNotebook, insertPage, 4}}, + {1891, {wxNotebook, setImageList, 1}}, + {1892, {wxNotebook, setPadding, 1}}, + {1893, {wxNotebook, setPageSize, 1}}, + {1894, {wxNotebook, setPageImage, 2}}, + {1895, {wxNotebook, setPageText, 2}}, + {1896, {wxNotebook, setSelection, 1}}, + {1897, {wxNotebook, changeSelection, 1}}, + {1898, {wxChoicebook, new_0, 0}}, + {1899, {wxChoicebook, new_3, 3}}, + {1900, {wxChoicebook, addPage, 3}}, + {1901, {wxChoicebook, advanceSelection, 1}}, + {1902, {wxChoicebook, assignImageList, 1}}, + {1903, {wxChoicebook, create, 3}}, + {1904, {wxChoicebook, deleteAllPages, 0}}, + {1905, {wxChoicebook, deletePage, 1}}, + {1906, {wxChoicebook, removePage, 1}}, + {1907, {wxChoicebook, getCurrentPage, 0}}, + {1908, {wxChoicebook, getImageList, 0}}, + {1910, {wxChoicebook, getPage, 1}}, + {1911, {wxChoicebook, getPageCount, 0}}, + {1912, {wxChoicebook, getPageImage, 1}}, + {1913, {wxChoicebook, getPageText, 1}}, + {1914, {wxChoicebook, getSelection, 0}}, + {1915, {wxChoicebook, hitTest, 2}}, + {1916, {wxChoicebook, insertPage, 4}}, + {1917, {wxChoicebook, setImageList, 1}}, + {1918, {wxChoicebook, setPageSize, 1}}, + {1919, {wxChoicebook, setPageImage, 2}}, + {1920, {wxChoicebook, setPageText, 2}}, + {1921, {wxChoicebook, setSelection, 1}}, + {1922, {wxChoicebook, changeSelection, 1}}, + {1923, {wxChoicebook, 'Destroy', undefined}}, + {1924, {wxToolbook, new_0, 0}}, + {1925, {wxToolbook, new_3, 3}}, + {1926, {wxToolbook, addPage, 3}}, + {1927, {wxToolbook, advanceSelection, 1}}, + {1928, {wxToolbook, assignImageList, 1}}, + {1929, {wxToolbook, create, 3}}, + {1930, {wxToolbook, deleteAllPages, 0}}, + {1931, {wxToolbook, deletePage, 1}}, + {1932, {wxToolbook, removePage, 1}}, + {1933, {wxToolbook, getCurrentPage, 0}}, + {1934, {wxToolbook, getImageList, 0}}, + {1936, {wxToolbook, getPage, 1}}, + {1937, {wxToolbook, getPageCount, 0}}, + {1938, {wxToolbook, getPageImage, 1}}, + {1939, {wxToolbook, getPageText, 1}}, + {1940, {wxToolbook, getSelection, 0}}, + {1942, {wxToolbook, hitTest, 2}}, + {1943, {wxToolbook, insertPage, 4}}, + {1944, {wxToolbook, setImageList, 1}}, + {1945, {wxToolbook, setPageSize, 1}}, + {1946, {wxToolbook, setPageImage, 2}}, + {1947, {wxToolbook, setPageText, 2}}, + {1948, {wxToolbook, setSelection, 1}}, + {1949, {wxToolbook, changeSelection, 1}}, + {1950, {wxToolbook, 'Destroy', undefined}}, + {1951, {wxListbook, new_0, 0}}, + {1952, {wxListbook, new_3, 3}}, + {1953, {wxListbook, addPage, 3}}, + {1954, {wxListbook, advanceSelection, 1}}, + {1955, {wxListbook, assignImageList, 1}}, + {1956, {wxListbook, create, 3}}, + {1957, {wxListbook, deleteAllPages, 0}}, + {1958, {wxListbook, deletePage, 1}}, + {1959, {wxListbook, removePage, 1}}, + {1960, {wxListbook, getCurrentPage, 0}}, + {1961, {wxListbook, getImageList, 0}}, + {1963, {wxListbook, getPage, 1}}, + {1964, {wxListbook, getPageCount, 0}}, + {1965, {wxListbook, getPageImage, 1}}, + {1966, {wxListbook, getPageText, 1}}, + {1967, {wxListbook, getSelection, 0}}, + {1969, {wxListbook, hitTest, 2}}, + {1970, {wxListbook, insertPage, 4}}, + {1971, {wxListbook, setImageList, 1}}, + {1972, {wxListbook, setPageSize, 1}}, + {1973, {wxListbook, setPageImage, 2}}, + {1974, {wxListbook, setPageText, 2}}, + {1975, {wxListbook, setSelection, 1}}, + {1976, {wxListbook, changeSelection, 1}}, + {1977, {wxListbook, 'Destroy', undefined}}, + {1978, {wxTreebook, new_0, 0}}, + {1979, {wxTreebook, new_3, 3}}, + {1980, {wxTreebook, addPage, 3}}, + {1981, {wxTreebook, advanceSelection, 1}}, + {1982, {wxTreebook, assignImageList, 1}}, + {1983, {wxTreebook, create, 3}}, + {1984, {wxTreebook, deleteAllPages, 0}}, + {1985, {wxTreebook, deletePage, 1}}, + {1986, {wxTreebook, removePage, 1}}, + {1987, {wxTreebook, getCurrentPage, 0}}, + {1988, {wxTreebook, getImageList, 0}}, + {1990, {wxTreebook, getPage, 1}}, + {1991, {wxTreebook, getPageCount, 0}}, + {1992, {wxTreebook, getPageImage, 1}}, + {1993, {wxTreebook, getPageText, 1}}, + {1994, {wxTreebook, getSelection, 0}}, + {1995, {wxTreebook, expandNode, 2}}, + {1996, {wxTreebook, isNodeExpanded, 1}}, + {1998, {wxTreebook, hitTest, 2}}, + {1999, {wxTreebook, insertPage, 4}}, + {2000, {wxTreebook, insertSubPage, 4}}, + {2001, {wxTreebook, setImageList, 1}}, + {2002, {wxTreebook, setPageSize, 1}}, + {2003, {wxTreebook, setPageImage, 2}}, + {2004, {wxTreebook, setPageText, 2}}, + {2005, {wxTreebook, setSelection, 1}}, + {2006, {wxTreebook, changeSelection, 1}}, + {2007, {wxTreebook, 'Destroy', undefined}}, + {2010, {wxTreeCtrl, new_2, 2}}, + {2011, {wxTreeCtrl, new_0, 0}}, + {2013, {wxTreeCtrl, destruct, 0}}, + {2014, {wxTreeCtrl, addRoot, 2}}, + {2015, {wxTreeCtrl, appendItem, 3}}, + {2016, {wxTreeCtrl, assignImageList, 1}}, + {2017, {wxTreeCtrl, assignStateImageList, 1}}, + {2018, {wxTreeCtrl, collapse, 1}}, + {2019, {wxTreeCtrl, collapseAndReset, 1}}, + {2020, {wxTreeCtrl, create, 2}}, + {2021, {wxTreeCtrl, delete, 1}}, + {2022, {wxTreeCtrl, deleteAllItems, 0}}, + {2023, {wxTreeCtrl, deleteChildren, 1}}, + {2024, {wxTreeCtrl, editLabel, 1}}, + {2025, {wxTreeCtrl, ensureVisible, 1}}, + {2026, {wxTreeCtrl, expand, 1}}, + {2027, {wxTreeCtrl, getBoundingRect, 3}}, + {2029, {wxTreeCtrl, getChildrenCount, 2}}, + {2030, {wxTreeCtrl, getCount, 0}}, + {2031, {wxTreeCtrl, getEditControl, 0}}, + {2032, {wxTreeCtrl, getFirstChild, 2}}, + {2033, {wxTreeCtrl, getNextChild, 2}}, + {2034, {wxTreeCtrl, getFirstVisibleItem, 0}}, + {2035, {wxTreeCtrl, getImageList, 0}}, + {2036, {wxTreeCtrl, getIndent, 0}}, + {2037, {wxTreeCtrl, getItemBackgroundColour, 1}}, + {2038, {wxTreeCtrl, getItemData, 1}}, + {2039, {wxTreeCtrl, getItemFont, 1}}, + {2040, {wxTreeCtrl, getItemImage_1, 1}}, + {2041, {wxTreeCtrl, getItemImage_2, 2}}, + {2042, {wxTreeCtrl, getItemText, 1}}, + {2043, {wxTreeCtrl, getItemTextColour, 1}}, + {2044, {wxTreeCtrl, getLastChild, 1}}, + {2045, {wxTreeCtrl, getNextSibling, 1}}, + {2046, {wxTreeCtrl, getNextVisible, 1}}, + {2047, {wxTreeCtrl, getItemParent, 1}}, + {2048, {wxTreeCtrl, getPrevSibling, 1}}, + {2049, {wxTreeCtrl, getPrevVisible, 1}}, + {2050, {wxTreeCtrl, getRootItem, 0}}, + {2051, {wxTreeCtrl, getSelection, 0}}, + {2052, {wxTreeCtrl, getSelections, 1}}, + {2053, {wxTreeCtrl, getStateImageList, 0}}, + {2054, {wxTreeCtrl, hitTest, 2}}, + {2056, {wxTreeCtrl, insertItem, 4}}, + {2057, {wxTreeCtrl, isBold, 1}}, + {2058, {wxTreeCtrl, isExpanded, 1}}, + {2059, {wxTreeCtrl, isSelected, 1}}, + {2060, {wxTreeCtrl, isVisible, 1}}, + {2061, {wxTreeCtrl, itemHasChildren, 1}}, + {2062, {wxTreeCtrl, isTreeItemIdOk, 1}}, + {2063, {wxTreeCtrl, prependItem, 3}}, + {2064, {wxTreeCtrl, scrollTo, 1}}, + {2065, {wxTreeCtrl, selectItem_1, 1}}, + {2066, {wxTreeCtrl, selectItem_2, 2}}, + {2067, {wxTreeCtrl, setIndent, 1}}, + {2068, {wxTreeCtrl, setImageList, 1}}, + {2069, {wxTreeCtrl, setItemBackgroundColour, 2}}, + {2070, {wxTreeCtrl, setItemBold, 2}}, + {2071, {wxTreeCtrl, setItemData, 2}}, + {2072, {wxTreeCtrl, setItemDropHighlight, 2}}, + {2073, {wxTreeCtrl, setItemFont, 2}}, + {2074, {wxTreeCtrl, setItemHasChildren, 2}}, + {2075, {wxTreeCtrl, setItemImage_2, 2}}, + {2076, {wxTreeCtrl, setItemImage_3, 3}}, + {2077, {wxTreeCtrl, setItemText, 2}}, + {2078, {wxTreeCtrl, setItemTextColour, 2}}, + {2079, {wxTreeCtrl, setStateImageList, 1}}, + {2080, {wxTreeCtrl, setWindowStyle, 1}}, + {2081, {wxTreeCtrl, sortChildren, 1}}, + {2082, {wxTreeCtrl, toggle, 1}}, + {2083, {wxTreeCtrl, toggleItemSelection, 1}}, + {2084, {wxTreeCtrl, unselect, 0}}, + {2085, {wxTreeCtrl, unselectAll, 0}}, + {2086, {wxTreeCtrl, unselectItem, 1}}, + {2087, {wxScrollBar, new_0, 0}}, + {2088, {wxScrollBar, new_3, 3}}, + {2089, {wxScrollBar, destruct, 0}}, + {2090, {wxScrollBar, create, 3}}, + {2091, {wxScrollBar, getRange, 0}}, + {2092, {wxScrollBar, getPageSize, 0}}, + {2093, {wxScrollBar, getThumbPosition, 0}}, + {2094, {wxScrollBar, getThumbSize, 0}}, + {2095, {wxScrollBar, setThumbPosition, 1}}, + {2096, {wxScrollBar, setScrollbar, 5}}, + {2098, {wxSpinButton, new_2, 2}}, + {2099, {wxSpinButton, new_0, 0}}, + {2100, {wxSpinButton, create, 2}}, + {2101, {wxSpinButton, getMax, 0}}, + {2102, {wxSpinButton, getMin, 0}}, + {2103, {wxSpinButton, getValue, 0}}, + {2104, {wxSpinButton, setRange, 2}}, + {2105, {wxSpinButton, setValue, 1}}, + {2106, {wxSpinButton, 'Destroy', undefined}}, + {2107, {wxSpinCtrl, new_0, 0}}, + {2108, {wxSpinCtrl, new_2, 2}}, + {2110, {wxSpinCtrl, create, 2}}, + {2113, {wxSpinCtrl, setValue_1_1, 1}}, + {2114, {wxSpinCtrl, setValue_1_0, 1}}, + {2116, {wxSpinCtrl, getValue, 0}}, + {2118, {wxSpinCtrl, setRange, 2}}, + {2119, {wxSpinCtrl, setSelection, 2}}, + {2121, {wxSpinCtrl, getMin, 0}}, + {2123, {wxSpinCtrl, getMax, 0}}, + {2124, {wxSpinCtrl, 'Destroy', undefined}}, + {2125, {wxStaticText, new_0, 0}}, + {2126, {wxStaticText, new_4, 4}}, + {2127, {wxStaticText, create, 4}}, + {2128, {wxStaticText, getLabel, 0}}, + {2129, {wxStaticText, setLabel, 1}}, + {2130, {wxStaticText, wrap, 1}}, + {2131, {wxStaticText, 'Destroy', undefined}}, + {2132, {wxStaticBitmap, new_0, 0}}, + {2133, {wxStaticBitmap, new_4, 4}}, + {2134, {wxStaticBitmap, create, 4}}, + {2135, {wxStaticBitmap, getBitmap, 0}}, + {2136, {wxStaticBitmap, setBitmap, 1}}, + {2137, {wxStaticBitmap, 'Destroy', undefined}}, + {2138, {wxRadioBox, new, 7}}, + {2140, {wxRadioBox, destruct, 0}}, + {2141, {wxRadioBox, create, 7}}, + {2142, {wxRadioBox, enable_2, 2}}, + {2143, {wxRadioBox, enable_1, 1}}, + {2144, {wxRadioBox, getSelection, 0}}, + {2145, {wxRadioBox, getString, 1}}, + {2146, {wxRadioBox, setSelection, 1}}, + {2147, {wxRadioBox, show_2, 2}}, + {2148, {wxRadioBox, show_1, 1}}, + {2149, {wxRadioBox, getColumnCount, 0}}, + {2150, {wxRadioBox, getItemHelpText, 1}}, + {2151, {wxRadioBox, getItemToolTip, 1}}, + {2153, {wxRadioBox, getItemFromPoint, 1}}, + {2154, {wxRadioBox, getRowCount, 0}}, + {2155, {wxRadioBox, isItemEnabled, 1}}, + {2156, {wxRadioBox, isItemShown, 1}}, + {2157, {wxRadioBox, setItemHelpText, 2}}, + {2158, {wxRadioBox, setItemToolTip, 2}}, + {2159, {wxRadioButton, new_0, 0}}, + {2160, {wxRadioButton, new_4, 4}}, + {2161, {wxRadioButton, create, 4}}, + {2162, {wxRadioButton, getValue, 0}}, + {2163, {wxRadioButton, setValue, 1}}, + {2164, {wxRadioButton, 'Destroy', undefined}}, + {2166, {wxSlider, new_6, 6}}, + {2167, {wxSlider, new_0, 0}}, + {2168, {wxSlider, create, 6}}, + {2169, {wxSlider, getLineSize, 0}}, + {2170, {wxSlider, getMax, 0}}, + {2171, {wxSlider, getMin, 0}}, + {2172, {wxSlider, getPageSize, 0}}, + {2173, {wxSlider, getThumbLength, 0}}, + {2174, {wxSlider, getValue, 0}}, + {2175, {wxSlider, setLineSize, 1}}, + {2176, {wxSlider, setPageSize, 1}}, + {2177, {wxSlider, setRange, 2}}, + {2178, {wxSlider, setThumbLength, 1}}, + {2179, {wxSlider, setValue, 1}}, + {2180, {wxSlider, 'Destroy', undefined}}, + {2182, {wxDialog, new_4, 4}}, + {2183, {wxDialog, new_0, 0}}, + {2185, {wxDialog, destruct, 0}}, + {2186, {wxDialog, create, 4}}, + {2187, {wxDialog, createButtonSizer, 1}}, + {2188, {wxDialog, createStdDialogButtonSizer, 1}}, + {2189, {wxDialog, endModal, 1}}, + {2190, {wxDialog, getAffirmativeId, 0}}, + {2191, {wxDialog, getReturnCode, 0}}, + {2192, {wxDialog, isModal, 0}}, + {2193, {wxDialog, setAffirmativeId, 1}}, + {2194, {wxDialog, setReturnCode, 1}}, + {2195, {wxDialog, show, 1}}, + {2196, {wxDialog, showModal, 0}}, + {2197, {wxColourDialog, new_0, 0}}, + {2198, {wxColourDialog, new_2, 2}}, + {2199, {wxColourDialog, destruct, 0}}, + {2200, {wxColourDialog, create, 2}}, + {2201, {wxColourDialog, getColourData, 0}}, + {2202, {wxColourData, new_0, 0}}, + {2203, {wxColourData, new_1, 1}}, + {2204, {wxColourData, destruct, 0}}, + {2205, {wxColourData, getChooseFull, 0}}, + {2206, {wxColourData, getColour, 0}}, + {2208, {wxColourData, getCustomColour, 1}}, + {2209, {wxColourData, setChooseFull, 1}}, + {2210, {wxColourData, setColour, 1}}, + {2211, {wxColourData, setCustomColour, 2}}, + {2212, {wxPalette, new_0, 0}}, + {2213, {wxPalette, new_4, 4}}, + {2215, {wxPalette, destruct, 0}}, + {2216, {wxPalette, create, 4}}, + {2217, {wxPalette, getColoursCount, 0}}, + {2218, {wxPalette, getPixel, 3}}, + {2219, {wxPalette, getRGB, 4}}, + {2220, {wxPalette, isOk, 0}}, + {2224, {wxDirDialog, new, 2}}, + {2225, {wxDirDialog, destruct, 0}}, + {2226, {wxDirDialog, getPath, 0}}, + {2227, {wxDirDialog, getMessage, 0}}, + {2228, {wxDirDialog, setMessage, 1}}, + {2229, {wxDirDialog, setPath, 1}}, + {2233, {wxFileDialog, new, 2}}, + {2234, {wxFileDialog, destruct, 0}}, + {2235, {wxFileDialog, getDirectory, 0}}, + {2236, {wxFileDialog, getFilename, 0}}, + {2237, {wxFileDialog, getFilenames, 1}}, + {2238, {wxFileDialog, getFilterIndex, 0}}, + {2239, {wxFileDialog, getMessage, 0}}, + {2240, {wxFileDialog, getPath, 0}}, + {2241, {wxFileDialog, getPaths, 1}}, + {2242, {wxFileDialog, getWildcard, 0}}, + {2243, {wxFileDialog, setDirectory, 1}}, + {2244, {wxFileDialog, setFilename, 1}}, + {2245, {wxFileDialog, setFilterIndex, 1}}, + {2246, {wxFileDialog, setMessage, 1}}, + {2247, {wxFileDialog, setPath, 1}}, + {2248, {wxFileDialog, setWildcard, 1}}, + {2249, {wxPickerBase, setInternalMargin, 1}}, + {2250, {wxPickerBase, getInternalMargin, 0}}, + {2251, {wxPickerBase, setTextCtrlProportion, 1}}, + {2252, {wxPickerBase, setPickerCtrlProportion, 1}}, + {2253, {wxPickerBase, getTextCtrlProportion, 0}}, + {2254, {wxPickerBase, getPickerCtrlProportion, 0}}, + {2255, {wxPickerBase, hasTextCtrl, 0}}, + {2256, {wxPickerBase, getTextCtrl, 0}}, + {2257, {wxPickerBase, isTextCtrlGrowable, 0}}, + {2258, {wxPickerBase, setPickerCtrlGrowable, 1}}, + {2259, {wxPickerBase, setTextCtrlGrowable, 1}}, + {2260, {wxPickerBase, isPickerCtrlGrowable, 0}}, + {2261, {wxFilePickerCtrl, new_0, 0}}, + {2262, {wxFilePickerCtrl, new_3, 3}}, + {2263, {wxFilePickerCtrl, create, 3}}, + {2264, {wxFilePickerCtrl, getPath, 0}}, + {2265, {wxFilePickerCtrl, setPath, 1}}, + {2266, {wxFilePickerCtrl, 'Destroy', undefined}}, + {2267, {wxDirPickerCtrl, new_0, 0}}, + {2268, {wxDirPickerCtrl, new_3, 3}}, + {2269, {wxDirPickerCtrl, create, 3}}, + {2270, {wxDirPickerCtrl, getPath, 0}}, + {2271, {wxDirPickerCtrl, setPath, 1}}, + {2272, {wxDirPickerCtrl, 'Destroy', undefined}}, + {2273, {wxColourPickerCtrl, new_0, 0}}, + {2274, {wxColourPickerCtrl, new_3, 3}}, + {2275, {wxColourPickerCtrl, create, 3}}, + {2276, {wxColourPickerCtrl, getColour, 0}}, + {2277, {wxColourPickerCtrl, setColour_1_1, 1}}, + {2278, {wxColourPickerCtrl, setColour_1_0, 1}}, + {2279, {wxColourPickerCtrl, 'Destroy', undefined}}, + {2280, {wxDatePickerCtrl, new_0, 0}}, + {2281, {wxDatePickerCtrl, new_3, 3}}, + {2282, {wxDatePickerCtrl, getRange, 2}}, + {2283, {wxDatePickerCtrl, getValue, 0}}, + {2284, {wxDatePickerCtrl, setRange, 2}}, + {2285, {wxDatePickerCtrl, setValue, 1}}, + {2286, {wxDatePickerCtrl, 'Destroy', undefined}}, + {2287, {wxFontPickerCtrl, new_0, 0}}, + {2288, {wxFontPickerCtrl, new_3, 3}}, + {2289, {wxFontPickerCtrl, create, 3}}, + {2290, {wxFontPickerCtrl, getSelectedFont, 0}}, + {2291, {wxFontPickerCtrl, setSelectedFont, 1}}, + {2292, {wxFontPickerCtrl, getMaxPointSize, 0}}, + {2293, {wxFontPickerCtrl, setMaxPointSize, 1}}, + {2294, {wxFontPickerCtrl, 'Destroy', undefined}}, + {2297, {wxFindReplaceDialog, new_0, 0}}, + {2298, {wxFindReplaceDialog, new_4, 4}}, + {2299, {wxFindReplaceDialog, destruct, 0}}, + {2300, {wxFindReplaceDialog, create, 4}}, + {2301, {wxFindReplaceDialog, getData, 0}}, + {2302, {wxFindReplaceData, new_0, 0}}, + {2303, {wxFindReplaceData, new_1, 1}}, + {2304, {wxFindReplaceData, getFindString, 0}}, + {2305, {wxFindReplaceData, getReplaceString, 0}}, + {2306, {wxFindReplaceData, getFlags, 0}}, + {2307, {wxFindReplaceData, setFlags, 1}}, + {2308, {wxFindReplaceData, setFindString, 1}}, + {2309, {wxFindReplaceData, setReplaceString, 1}}, + {2310, {wxFindReplaceData, 'Destroy', undefined}}, + {2311, {wxMultiChoiceDialog, new_0, 0}}, + {2313, {wxMultiChoiceDialog, new_5, 5}}, + {2314, {wxMultiChoiceDialog, getSelections, 0}}, + {2315, {wxMultiChoiceDialog, setSelections, 1}}, + {2316, {wxMultiChoiceDialog, 'Destroy', undefined}}, + {2317, {wxSingleChoiceDialog, new_0, 0}}, + {2319, {wxSingleChoiceDialog, new_5, 5}}, + {2320, {wxSingleChoiceDialog, getSelection, 0}}, + {2321, {wxSingleChoiceDialog, getStringSelection, 0}}, + {2322, {wxSingleChoiceDialog, setSelection, 1}}, + {2323, {wxSingleChoiceDialog, 'Destroy', undefined}}, + {2324, {wxTextEntryDialog, new, 3}}, + {2325, {wxTextEntryDialog, getValue, 0}}, + {2326, {wxTextEntryDialog, setValue, 1}}, + {2327, {wxTextEntryDialog, 'Destroy', undefined}}, + {2328, {wxPasswordEntryDialog, new, 3}}, + {2329, {wxPasswordEntryDialog, 'Destroy', undefined}}, + {2330, {wxFontData, new_0, 0}}, + {2331, {wxFontData, new_1, 1}}, + {2332, {wxFontData, destruct, 0}}, + {2333, {wxFontData, enableEffects, 1}}, + {2334, {wxFontData, getAllowSymbols, 0}}, + {2335, {wxFontData, getColour, 0}}, + {2336, {wxFontData, getChosenFont, 0}}, + {2337, {wxFontData, getEnableEffects, 0}}, + {2338, {wxFontData, getInitialFont, 0}}, + {2339, {wxFontData, getShowHelp, 0}}, + {2340, {wxFontData, setAllowSymbols, 1}}, + {2341, {wxFontData, setChosenFont, 1}}, + {2342, {wxFontData, setColour, 1}}, + {2343, {wxFontData, setInitialFont, 1}}, + {2344, {wxFontData, setRange, 2}}, + {2345, {wxFontData, setShowHelp, 1}}, + {2349, {wxFontDialog, new_0, 0}}, + {2351, {wxFontDialog, new_2, 2}}, + {2353, {wxFontDialog, create, 2}}, + {2354, {wxFontDialog, getFontData, 0}}, + {2356, {wxFontDialog, 'Destroy', undefined}}, + {2357, {wxProgressDialog, new, 3}}, + {2358, {wxProgressDialog, destruct, 0}}, + {2359, {wxProgressDialog, resume, 0}}, + {2360, {wxProgressDialog, update_2, 2}}, + {2361, {wxProgressDialog, update_0, 0}}, + {2362, {wxMessageDialog, new, 3}}, + {2363, {wxMessageDialog, destruct, 0}}, + {2364, {wxPageSetupDialog, new, 2}}, + {2365, {wxPageSetupDialog, destruct, 0}}, + {2366, {wxPageSetupDialog, getPageSetupData, 0}}, + {2367, {wxPageSetupDialog, showModal, 0}}, + {2368, {wxPageSetupDialogData, new_0, 0}}, + {2369, {wxPageSetupDialogData, new_1_0, 1}}, + {2370, {wxPageSetupDialogData, new_1_1, 1}}, + {2371, {wxPageSetupDialogData, destruct, 0}}, + {2372, {wxPageSetupDialogData, enableHelp, 1}}, + {2373, {wxPageSetupDialogData, enableMargins, 1}}, + {2374, {wxPageSetupDialogData, enableOrientation, 1}}, + {2375, {wxPageSetupDialogData, enablePaper, 1}}, + {2376, {wxPageSetupDialogData, enablePrinter, 1}}, + {2377, {wxPageSetupDialogData, getDefaultMinMargins, 0}}, + {2378, {wxPageSetupDialogData, getEnableMargins, 0}}, + {2379, {wxPageSetupDialogData, getEnableOrientation, 0}}, + {2380, {wxPageSetupDialogData, getEnablePaper, 0}}, + {2381, {wxPageSetupDialogData, getEnablePrinter, 0}}, + {2382, {wxPageSetupDialogData, getEnableHelp, 0}}, + {2383, {wxPageSetupDialogData, getDefaultInfo, 0}}, + {2384, {wxPageSetupDialogData, getMarginTopLeft, 0}}, + {2385, {wxPageSetupDialogData, getMarginBottomRight, 0}}, + {2386, {wxPageSetupDialogData, getMinMarginTopLeft, 0}}, + {2387, {wxPageSetupDialogData, getMinMarginBottomRight, 0}}, + {2388, {wxPageSetupDialogData, getPaperId, 0}}, + {2389, {wxPageSetupDialogData, getPaperSize, 0}}, + {2391, {wxPageSetupDialogData, getPrintData, 0}}, + {2392, {wxPageSetupDialogData, isOk, 0}}, + {2393, {wxPageSetupDialogData, setDefaultInfo, 1}}, + {2394, {wxPageSetupDialogData, setDefaultMinMargins, 1}}, + {2395, {wxPageSetupDialogData, setMarginTopLeft, 1}}, + {2396, {wxPageSetupDialogData, setMarginBottomRight, 1}}, + {2397, {wxPageSetupDialogData, setMinMarginTopLeft, 1}}, + {2398, {wxPageSetupDialogData, setMinMarginBottomRight, 1}}, + {2399, {wxPageSetupDialogData, setPaperId, 1}}, + {2400, {wxPageSetupDialogData, setPaperSize_1_1, 1}}, + {2401, {wxPageSetupDialogData, setPaperSize_1_0, 1}}, + {2402, {wxPageSetupDialogData, setPrintData, 1}}, + {2403, {wxPrintDialog, new_2_0, 2}}, + {2404, {wxPrintDialog, new_2_1, 2}}, + {2405, {wxPrintDialog, destruct, 0}}, + {2406, {wxPrintDialog, getPrintDialogData, 0}}, + {2407, {wxPrintDialog, getPrintDC, 0}}, + {2408, {wxPrintDialogData, new_0, 0}}, + {2409, {wxPrintDialogData, new_1_1, 1}}, + {2410, {wxPrintDialogData, new_1_0, 1}}, + {2411, {wxPrintDialogData, destruct, 0}}, + {2412, {wxPrintDialogData, enableHelp, 1}}, + {2413, {wxPrintDialogData, enablePageNumbers, 1}}, + {2414, {wxPrintDialogData, enablePrintToFile, 1}}, + {2415, {wxPrintDialogData, enableSelection, 1}}, + {2416, {wxPrintDialogData, getAllPages, 0}}, + {2417, {wxPrintDialogData, getCollate, 0}}, + {2418, {wxPrintDialogData, getFromPage, 0}}, + {2419, {wxPrintDialogData, getMaxPage, 0}}, + {2420, {wxPrintDialogData, getMinPage, 0}}, + {2421, {wxPrintDialogData, getNoCopies, 0}}, + {2422, {wxPrintDialogData, getPrintData, 0}}, + {2423, {wxPrintDialogData, getPrintToFile, 0}}, + {2424, {wxPrintDialogData, getSelection, 0}}, + {2425, {wxPrintDialogData, getToPage, 0}}, + {2426, {wxPrintDialogData, isOk, 0}}, + {2427, {wxPrintDialogData, setCollate, 1}}, + {2428, {wxPrintDialogData, setFromPage, 1}}, + {2429, {wxPrintDialogData, setMaxPage, 1}}, + {2430, {wxPrintDialogData, setMinPage, 1}}, + {2431, {wxPrintDialogData, setNoCopies, 1}}, + {2432, {wxPrintDialogData, setPrintData, 1}}, + {2433, {wxPrintDialogData, setPrintToFile, 1}}, + {2434, {wxPrintDialogData, setSelection, 1}}, + {2435, {wxPrintDialogData, setToPage, 1}}, + {2436, {wxPrintData, new_0, 0}}, + {2437, {wxPrintData, new_1, 1}}, + {2438, {wxPrintData, destruct, 0}}, + {2439, {wxPrintData, getCollate, 0}}, + {2440, {wxPrintData, getBin, 0}}, + {2441, {wxPrintData, getColour, 0}}, + {2442, {wxPrintData, getDuplex, 0}}, + {2443, {wxPrintData, getNoCopies, 0}}, + {2444, {wxPrintData, getOrientation, 0}}, + {2445, {wxPrintData, getPaperId, 0}}, + {2446, {wxPrintData, getPrinterName, 0}}, + {2447, {wxPrintData, getQuality, 0}}, + {2448, {wxPrintData, isOk, 0}}, + {2449, {wxPrintData, setBin, 1}}, + {2450, {wxPrintData, setCollate, 1}}, + {2451, {wxPrintData, setColour, 1}}, + {2452, {wxPrintData, setDuplex, 1}}, + {2453, {wxPrintData, setNoCopies, 1}}, + {2454, {wxPrintData, setOrientation, 1}}, + {2455, {wxPrintData, setPaperId, 1}}, + {2456, {wxPrintData, setPrinterName, 1}}, + {2457, {wxPrintData, setQuality, 1}}, + {2460, {wxPrintPreview, new_2, 2}}, + {2461, {wxPrintPreview, new_3, 3}}, + {2463, {wxPrintPreview, destruct, 0}}, + {2464, {wxPrintPreview, getCanvas, 0}}, + {2465, {wxPrintPreview, getCurrentPage, 0}}, + {2466, {wxPrintPreview, getFrame, 0}}, + {2467, {wxPrintPreview, getMaxPage, 0}}, + {2468, {wxPrintPreview, getMinPage, 0}}, + {2469, {wxPrintPreview, getPrintout, 0}}, + {2470, {wxPrintPreview, getPrintoutForPrinting, 0}}, + {2471, {wxPrintPreview, isOk, 0}}, + {2472, {wxPrintPreview, paintPage, 2}}, + {2473, {wxPrintPreview, print, 1}}, + {2474, {wxPrintPreview, renderPage, 1}}, + {2475, {wxPrintPreview, setCanvas, 1}}, + {2476, {wxPrintPreview, setCurrentPage, 1}}, + {2477, {wxPrintPreview, setFrame, 1}}, + {2478, {wxPrintPreview, setPrintout, 1}}, + {2479, {wxPrintPreview, setZoom, 1}}, + {2480, {wxPreviewFrame, new, 3}}, + {2481, {wxPreviewFrame, destruct, 0}}, + {2482, {wxPreviewFrame, createControlBar, 0}}, + {2483, {wxPreviewFrame, createCanvas, 0}}, + {2484, {wxPreviewFrame, initialize, 0}}, + {2485, {wxPreviewFrame, onCloseWindow, 1}}, + {2486, {wxPreviewControlBar, new, 4}}, + {2487, {wxPreviewControlBar, destruct, 0}}, + {2488, {wxPreviewControlBar, createButtons, 0}}, + {2489, {wxPreviewControlBar, getPrintPreview, 0}}, + {2490, {wxPreviewControlBar, getZoomControl, 0}}, + {2491, {wxPreviewControlBar, setZoomControl, 1}}, + {2493, {wxPrinter, new, 1}}, + {2494, {wxPrinter, createAbortWindow, 2}}, + {2495, {wxPrinter, getAbort, 0}}, + {2496, {wxPrinter, getLastError, 0}}, + {2497, {wxPrinter, getPrintDialogData, 0}}, + {2498, {wxPrinter, print, 3}}, + {2499, {wxPrinter, printDialog, 1}}, + {2500, {wxPrinter, reportError, 3}}, + {2501, {wxPrinter, setup, 1}}, + {2502, {wxPrinter, 'Destroy', undefined}}, + {2503, {wxXmlResource, new_1, 1}}, + {2504, {wxXmlResource, new_2, 2}}, + {2505, {wxXmlResource, destruct, 0}}, + {2506, {wxXmlResource, attachUnknownControl, 3}}, + {2507, {wxXmlResource, clearHandlers, 0}}, + {2508, {wxXmlResource, compareVersion, 4}}, + {2509, {wxXmlResource, get, 0}}, + {2510, {wxXmlResource, getFlags, 0}}, + {2511, {wxXmlResource, getVersion, 0}}, + {2512, {wxXmlResource, getXRCID, 2}}, + {2513, {wxXmlResource, initAllHandlers, 0}}, + {2514, {wxXmlResource, load, 1}}, + {2515, {wxXmlResource, loadBitmap, 1}}, + {2516, {wxXmlResource, loadDialog_2, 2}}, + {2517, {wxXmlResource, loadDialog_3, 3}}, + {2518, {wxXmlResource, loadFrame_2, 2}}, + {2519, {wxXmlResource, loadFrame_3, 3}}, + {2520, {wxXmlResource, loadIcon, 1}}, + {2521, {wxXmlResource, loadMenu, 1}}, + {2522, {wxXmlResource, loadMenuBar_2, 2}}, + {2523, {wxXmlResource, loadMenuBar_1, 1}}, + {2524, {wxXmlResource, loadPanel_2, 2}}, + {2525, {wxXmlResource, loadPanel_3, 3}}, + {2526, {wxXmlResource, loadToolBar, 2}}, + {2527, {wxXmlResource, set, 1}}, + {2528, {wxXmlResource, setFlags, 1}}, + {2529, {wxXmlResource, unload, 1}}, + {2530, {wxXmlResource, xrcctrl, 3}}, + {2531, {wxHtmlEasyPrinting, new, 1}}, + {2532, {wxHtmlEasyPrinting, destruct, 0}}, + {2533, {wxHtmlEasyPrinting, getPrintData, 0}}, + {2534, {wxHtmlEasyPrinting, getPageSetupData, 0}}, + {2535, {wxHtmlEasyPrinting, previewFile, 1}}, + {2536, {wxHtmlEasyPrinting, previewText, 2}}, + {2537, {wxHtmlEasyPrinting, printFile, 1}}, + {2538, {wxHtmlEasyPrinting, printText, 2}}, + {2539, {wxHtmlEasyPrinting, pageSetup, 0}}, + {2540, {wxHtmlEasyPrinting, setFonts, 3}}, + {2541, {wxHtmlEasyPrinting, setHeader, 2}}, + {2542, {wxHtmlEasyPrinting, setFooter, 2}}, + {2544, {wxGLCanvas, new_2, 2}}, + {2545, {wxGLCanvas, new_3_1, 3}}, + {2546, {wxGLCanvas, new_3_0, 3}}, + {2547, {wxGLCanvas, getContext, 0}}, + {2549, {wxGLCanvas, setCurrent, 0}}, + {2550, {wxGLCanvas, swapBuffers, 0}}, + {2551, {wxGLCanvas, 'Destroy', undefined}}, + {2552, {wxAuiManager, new, 1}}, + {2553, {wxAuiManager, destruct, 0}}, + {2554, {wxAuiManager, addPane_2_1, 2}}, + {2555, {wxAuiManager, addPane_3, 3}}, + {2556, {wxAuiManager, addPane_2_0, 2}}, + {2557, {wxAuiManager, detachPane, 1}}, + {2558, {wxAuiManager, getAllPanes, 0}}, + {2559, {wxAuiManager, getArtProvider, 0}}, + {2560, {wxAuiManager, getDockSizeConstraint, 2}}, + {2561, {wxAuiManager, getFlags, 0}}, + {2562, {wxAuiManager, getManagedWindow, 0}}, + {2563, {wxAuiManager, getManager, 1}}, + {2564, {wxAuiManager, getPane_1_1, 1}}, + {2565, {wxAuiManager, getPane_1_0, 1}}, + {2566, {wxAuiManager, hideHint, 0}}, + {2567, {wxAuiManager, insertPane, 3}}, + {2568, {wxAuiManager, loadPaneInfo, 2}}, + {2569, {wxAuiManager, loadPerspective, 2}}, + {2570, {wxAuiManager, savePaneInfo, 1}}, + {2571, {wxAuiManager, savePerspective, 0}}, + {2572, {wxAuiManager, setArtProvider, 1}}, + {2573, {wxAuiManager, setDockSizeConstraint, 2}}, + {2574, {wxAuiManager, setFlags, 1}}, + {2575, {wxAuiManager, setManagedWindow, 1}}, + {2576, {wxAuiManager, showHint, 1}}, + {2577, {wxAuiManager, unInit, 0}}, + {2578, {wxAuiManager, update, 0}}, + {2579, {wxAuiPaneInfo, new_0, 0}}, + {2580, {wxAuiPaneInfo, new_1, 1}}, + {2581, {wxAuiPaneInfo, destruct, 0}}, + {2582, {wxAuiPaneInfo, bestSize_1, 1}}, + {2583, {wxAuiPaneInfo, bestSize_2, 2}}, + {2584, {wxAuiPaneInfo, bottom, 0}}, + {2585, {wxAuiPaneInfo, bottomDockable, 1}}, + {2586, {wxAuiPaneInfo, caption, 1}}, + {2587, {wxAuiPaneInfo, captionVisible, 1}}, + {2588, {wxAuiPaneInfo, centre, 0}}, + {2589, {wxAuiPaneInfo, centrePane, 0}}, + {2590, {wxAuiPaneInfo, closeButton, 1}}, + {2591, {wxAuiPaneInfo, defaultPane, 0}}, + {2592, {wxAuiPaneInfo, destroyOnClose, 1}}, + {2593, {wxAuiPaneInfo, direction, 1}}, + {2594, {wxAuiPaneInfo, dock, 0}}, + {2595, {wxAuiPaneInfo, dockable, 1}}, + {2596, {wxAuiPaneInfo, fixed, 0}}, + {2597, {wxAuiPaneInfo, float, 0}}, + {2598, {wxAuiPaneInfo, floatable, 1}}, + {2599, {wxAuiPaneInfo, floatingPosition_1, 1}}, + {2600, {wxAuiPaneInfo, floatingPosition_2, 2}}, + {2601, {wxAuiPaneInfo, floatingSize_1, 1}}, + {2602, {wxAuiPaneInfo, floatingSize_2, 2}}, + {2603, {wxAuiPaneInfo, gripper, 1}}, + {2604, {wxAuiPaneInfo, gripperTop, 1}}, + {2605, {wxAuiPaneInfo, hasBorder, 0}}, + {2606, {wxAuiPaneInfo, hasCaption, 0}}, + {2607, {wxAuiPaneInfo, hasCloseButton, 0}}, + {2608, {wxAuiPaneInfo, hasFlag, 1}}, + {2609, {wxAuiPaneInfo, hasGripper, 0}}, + {2610, {wxAuiPaneInfo, hasGripperTop, 0}}, + {2611, {wxAuiPaneInfo, hasMaximizeButton, 0}}, + {2612, {wxAuiPaneInfo, hasMinimizeButton, 0}}, + {2613, {wxAuiPaneInfo, hasPinButton, 0}}, + {2614, {wxAuiPaneInfo, hide, 0}}, + {2615, {wxAuiPaneInfo, isBottomDockable, 0}}, + {2616, {wxAuiPaneInfo, isDocked, 0}}, + {2617, {wxAuiPaneInfo, isFixed, 0}}, + {2618, {wxAuiPaneInfo, isFloatable, 0}}, + {2619, {wxAuiPaneInfo, isFloating, 0}}, + {2620, {wxAuiPaneInfo, isLeftDockable, 0}}, + {2621, {wxAuiPaneInfo, isMovable, 0}}, + {2622, {wxAuiPaneInfo, isOk, 0}}, + {2623, {wxAuiPaneInfo, isResizable, 0}}, + {2624, {wxAuiPaneInfo, isRightDockable, 0}}, + {2625, {wxAuiPaneInfo, isShown, 0}}, + {2626, {wxAuiPaneInfo, isToolbar, 0}}, + {2627, {wxAuiPaneInfo, isTopDockable, 0}}, + {2628, {wxAuiPaneInfo, layer, 1}}, + {2629, {wxAuiPaneInfo, left, 0}}, + {2630, {wxAuiPaneInfo, leftDockable, 1}}, + {2631, {wxAuiPaneInfo, maxSize_1, 1}}, + {2632, {wxAuiPaneInfo, maxSize_2, 2}}, + {2633, {wxAuiPaneInfo, maximizeButton, 1}}, + {2634, {wxAuiPaneInfo, minSize_1, 1}}, + {2635, {wxAuiPaneInfo, minSize_2, 2}}, + {2636, {wxAuiPaneInfo, minimizeButton, 1}}, + {2637, {wxAuiPaneInfo, movable, 1}}, + {2638, {wxAuiPaneInfo, name, 1}}, + {2639, {wxAuiPaneInfo, paneBorder, 1}}, + {2640, {wxAuiPaneInfo, pinButton, 1}}, + {2641, {wxAuiPaneInfo, position, 1}}, + {2642, {wxAuiPaneInfo, resizable, 1}}, + {2643, {wxAuiPaneInfo, right, 0}}, + {2644, {wxAuiPaneInfo, rightDockable, 1}}, + {2645, {wxAuiPaneInfo, row, 1}}, + {2646, {wxAuiPaneInfo, safeSet, 1}}, + {2647, {wxAuiPaneInfo, setFlag, 2}}, + {2648, {wxAuiPaneInfo, show, 1}}, + {2649, {wxAuiPaneInfo, toolbarPane, 0}}, + {2650, {wxAuiPaneInfo, top, 0}}, + {2651, {wxAuiPaneInfo, topDockable, 1}}, + {2652, {wxAuiPaneInfo, window, 1}}, + {2653, {wxAuiNotebook, new_0, 0}}, + {2654, {wxAuiNotebook, new_2, 2}}, + {2655, {wxAuiNotebook, addPage, 3}}, + {2656, {wxAuiNotebook, create, 2}}, + {2657, {wxAuiNotebook, deletePage, 1}}, + {2658, {wxAuiNotebook, getArtProvider, 0}}, + {2659, {wxAuiNotebook, getPage, 1}}, + {2660, {wxAuiNotebook, getPageBitmap, 1}}, + {2661, {wxAuiNotebook, getPageCount, 0}}, + {2662, {wxAuiNotebook, getPageIndex, 1}}, + {2663, {wxAuiNotebook, getPageText, 1}}, + {2664, {wxAuiNotebook, getSelection, 0}}, + {2665, {wxAuiNotebook, insertPage, 4}}, + {2666, {wxAuiNotebook, removePage, 1}}, + {2667, {wxAuiNotebook, setArtProvider, 1}}, + {2668, {wxAuiNotebook, setFont, 1}}, + {2669, {wxAuiNotebook, setPageBitmap, 2}}, + {2670, {wxAuiNotebook, setPageText, 2}}, + {2671, {wxAuiNotebook, setSelection, 1}}, + {2672, {wxAuiNotebook, setTabCtrlHeight, 1}}, + {2673, {wxAuiNotebook, setUniformBitmapSize, 1}}, + {2674, {wxAuiNotebook, 'Destroy', undefined}}, + {2675, {wxMDIParentFrame, new_0, 0}}, + {2676, {wxMDIParentFrame, new_4, 4}}, + {2677, {wxMDIParentFrame, destruct, 0}}, + {2678, {wxMDIParentFrame, activateNext, 0}}, + {2679, {wxMDIParentFrame, activatePrevious, 0}}, + {2680, {wxMDIParentFrame, arrangeIcons, 0}}, + {2681, {wxMDIParentFrame, cascade, 0}}, + {2682, {wxMDIParentFrame, create, 4}}, + {2683, {wxMDIParentFrame, getActiveChild, 0}}, + {2684, {wxMDIParentFrame, getClientWindow, 0}}, + {2685, {wxMDIParentFrame, tile, 1}}, + {2686, {wxMDIChildFrame, new_0, 0}}, + {2687, {wxMDIChildFrame, new_4, 4}}, + {2688, {wxMDIChildFrame, destruct, 0}}, + {2689, {wxMDIChildFrame, activate, 0}}, + {2690, {wxMDIChildFrame, create, 4}}, + {2691, {wxMDIChildFrame, maximize, 1}}, + {2692, {wxMDIChildFrame, restore, 0}}, + {2693, {wxMDIClientWindow, new_0, 0}}, + {2694, {wxMDIClientWindow, new_2, 2}}, + {2695, {wxMDIClientWindow, destruct, 0}}, + {2696, {wxMDIClientWindow, createClient, 2}}, + {2697, {wxLayoutAlgorithm, new, 0}}, + {2698, {wxLayoutAlgorithm, layoutFrame, 2}}, + {2699, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, + {2700, {wxLayoutAlgorithm, layoutWindow, 2}}, + {2701, {wxLayoutAlgorithm, 'Destroy', undefined}}, + {2702, {wxEvent, getId, 0}}, + {2703, {wxEvent, getSkipped, 0}}, + {2704, {wxEvent, getTimestamp, 0}}, + {2705, {wxEvent, isCommandEvent, 0}}, + {2706, {wxEvent, resumePropagation, 1}}, + {2707, {wxEvent, shouldPropagate, 0}}, + {2708, {wxEvent, skip, 1}}, + {2709, {wxEvent, stopPropagation, 0}}, + {2710, {wxCommandEvent, getClientData, 0}}, + {2711, {wxCommandEvent, getExtraLong, 0}}, + {2712, {wxCommandEvent, getInt, 0}}, + {2713, {wxCommandEvent, getSelection, 0}}, + {2714, {wxCommandEvent, getString, 0}}, + {2715, {wxCommandEvent, isChecked, 0}}, + {2716, {wxCommandEvent, isSelection, 0}}, + {2717, {wxCommandEvent, setInt, 1}}, + {2718, {wxCommandEvent, setString, 1}}, + {2719, {wxScrollEvent, getOrientation, 0}}, + {2720, {wxScrollEvent, getPosition, 0}}, + {2721, {wxScrollWinEvent, getOrientation, 0}}, + {2722, {wxScrollWinEvent, getPosition, 0}}, + {2723, {wxMouseEvent, altDown, 0}}, + {2724, {wxMouseEvent, button, 1}}, + {2725, {wxMouseEvent, buttonDClick, 1}}, + {2726, {wxMouseEvent, buttonDown, 1}}, + {2727, {wxMouseEvent, buttonUp, 1}}, + {2728, {wxMouseEvent, cmdDown, 0}}, + {2729, {wxMouseEvent, controlDown, 0}}, + {2730, {wxMouseEvent, dragging, 0}}, + {2731, {wxMouseEvent, entering, 0}}, + {2732, {wxMouseEvent, getButton, 0}}, + {2735, {wxMouseEvent, getPosition, 0}}, + {2736, {wxMouseEvent, getLogicalPosition, 1}}, + {2737, {wxMouseEvent, getLinesPerAction, 0}}, + {2738, {wxMouseEvent, getWheelRotation, 0}}, + {2739, {wxMouseEvent, getWheelDelta, 0}}, + {2740, {wxMouseEvent, getX, 0}}, + {2741, {wxMouseEvent, getY, 0}}, + {2742, {wxMouseEvent, isButton, 0}}, + {2743, {wxMouseEvent, isPageScroll, 0}}, + {2744, {wxMouseEvent, leaving, 0}}, + {2745, {wxMouseEvent, leftDClick, 0}}, + {2746, {wxMouseEvent, leftDown, 0}}, + {2747, {wxMouseEvent, leftIsDown, 0}}, + {2748, {wxMouseEvent, leftUp, 0}}, + {2749, {wxMouseEvent, metaDown, 0}}, + {2750, {wxMouseEvent, middleDClick, 0}}, + {2751, {wxMouseEvent, middleDown, 0}}, + {2752, {wxMouseEvent, middleIsDown, 0}}, + {2753, {wxMouseEvent, middleUp, 0}}, + {2754, {wxMouseEvent, moving, 0}}, + {2755, {wxMouseEvent, rightDClick, 0}}, + {2756, {wxMouseEvent, rightDown, 0}}, + {2757, {wxMouseEvent, rightIsDown, 0}}, + {2758, {wxMouseEvent, rightUp, 0}}, + {2759, {wxMouseEvent, shiftDown, 0}}, + {2760, {wxSetCursorEvent, getCursor, 0}}, + {2761, {wxSetCursorEvent, getX, 0}}, + {2762, {wxSetCursorEvent, getY, 0}}, + {2763, {wxSetCursorEvent, hasCursor, 0}}, + {2764, {wxSetCursorEvent, setCursor, 1}}, + {2765, {wxKeyEvent, altDown, 0}}, + {2766, {wxKeyEvent, cmdDown, 0}}, + {2767, {wxKeyEvent, controlDown, 0}}, + {2768, {wxKeyEvent, getKeyCode, 0}}, + {2769, {wxKeyEvent, getModifiers, 0}}, + {2772, {wxKeyEvent, getPosition, 0}}, + {2773, {wxKeyEvent, getRawKeyCode, 0}}, + {2774, {wxKeyEvent, getRawKeyFlags, 0}}, + {2775, {wxKeyEvent, getUnicodeKey, 0}}, + {2776, {wxKeyEvent, getX, 0}}, + {2777, {wxKeyEvent, getY, 0}}, + {2778, {wxKeyEvent, hasModifiers, 0}}, + {2779, {wxKeyEvent, metaDown, 0}}, + {2780, {wxKeyEvent, shiftDown, 0}}, + {2781, {wxSizeEvent, getSize, 0}}, + {2782, {wxMoveEvent, getPosition, 0}}, + {2783, {wxEraseEvent, getDC, 0}}, + {2784, {wxFocusEvent, getWindow, 0}}, + {2785, {wxChildFocusEvent, getWindow, 0}}, + {2786, {wxMenuEvent, getMenu, 0}}, + {2787, {wxMenuEvent, getMenuId, 0}}, + {2788, {wxMenuEvent, isPopup, 0}}, + {2789, {wxCloseEvent, canVeto, 0}}, + {2790, {wxCloseEvent, getLoggingOff, 0}}, + {2791, {wxCloseEvent, setCanVeto, 1}}, + {2792, {wxCloseEvent, setLoggingOff, 1}}, + {2793, {wxCloseEvent, veto, 1}}, + {2794, {wxShowEvent, setShow, 1}}, + {2795, {wxShowEvent, getShow, 0}}, + {2796, {wxIconizeEvent, iconized, 0}}, + {2797, {wxJoystickEvent, buttonDown, 1}}, + {2798, {wxJoystickEvent, buttonIsDown, 1}}, + {2799, {wxJoystickEvent, buttonUp, 1}}, + {2800, {wxJoystickEvent, getButtonChange, 0}}, + {2801, {wxJoystickEvent, getButtonState, 0}}, + {2802, {wxJoystickEvent, getJoystick, 0}}, + {2803, {wxJoystickEvent, getPosition, 0}}, + {2804, {wxJoystickEvent, getZPosition, 0}}, + {2805, {wxJoystickEvent, isButton, 0}}, + {2806, {wxJoystickEvent, isMove, 0}}, + {2807, {wxJoystickEvent, isZMove, 0}}, + {2808, {wxUpdateUIEvent, canUpdate, 1}}, + {2809, {wxUpdateUIEvent, check, 1}}, + {2810, {wxUpdateUIEvent, enable, 1}}, + {2811, {wxUpdateUIEvent, show, 1}}, + {2812, {wxUpdateUIEvent, getChecked, 0}}, + {2813, {wxUpdateUIEvent, getEnabled, 0}}, + {2814, {wxUpdateUIEvent, getShown, 0}}, + {2815, {wxUpdateUIEvent, getSetChecked, 0}}, + {2816, {wxUpdateUIEvent, getSetEnabled, 0}}, + {2817, {wxUpdateUIEvent, getSetShown, 0}}, + {2818, {wxUpdateUIEvent, getSetText, 0}}, + {2819, {wxUpdateUIEvent, getText, 0}}, + {2820, {wxUpdateUIEvent, getMode, 0}}, + {2821, {wxUpdateUIEvent, getUpdateInterval, 0}}, + {2822, {wxUpdateUIEvent, resetUpdateTime, 0}}, + {2823, {wxUpdateUIEvent, setMode, 1}}, + {2824, {wxUpdateUIEvent, setText, 1}}, + {2825, {wxUpdateUIEvent, setUpdateInterval, 1}}, + {2826, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, + {2827, {wxPaletteChangedEvent, setChangedWindow, 1}}, + {2828, {wxPaletteChangedEvent, getChangedWindow, 0}}, + {2829, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, + {2830, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, + {2831, {wxNavigationKeyEvent, getDirection, 0}}, + {2832, {wxNavigationKeyEvent, setDirection, 1}}, + {2833, {wxNavigationKeyEvent, isWindowChange, 0}}, + {2834, {wxNavigationKeyEvent, setWindowChange, 1}}, + {2835, {wxNavigationKeyEvent, isFromTab, 0}}, + {2836, {wxNavigationKeyEvent, setFromTab, 1}}, + {2837, {wxNavigationKeyEvent, getCurrentFocus, 0}}, + {2838, {wxNavigationKeyEvent, setCurrentFocus, 1}}, + {2839, {wxHelpEvent, getOrigin, 0}}, + {2840, {wxHelpEvent, getPosition, 0}}, + {2841, {wxHelpEvent, setOrigin, 1}}, + {2842, {wxHelpEvent, setPosition, 1}}, + {2843, {wxContextMenuEvent, getPosition, 0}}, + {2844, {wxContextMenuEvent, setPosition, 1}}, + {2845, {wxIdleEvent, canSend, 1}}, + {2846, {wxIdleEvent, getMode, 0}}, + {2847, {wxIdleEvent, requestMore, 1}}, + {2848, {wxIdleEvent, moreRequested, 0}}, + {2849, {wxIdleEvent, setMode, 1}}, + {2850, {wxGridEvent, altDown, 0}}, + {2851, {wxGridEvent, controlDown, 0}}, + {2852, {wxGridEvent, getCol, 0}}, + {2853, {wxGridEvent, getPosition, 0}}, + {2854, {wxGridEvent, getRow, 0}}, + {2855, {wxGridEvent, metaDown, 0}}, + {2856, {wxGridEvent, selecting, 0}}, + {2857, {wxGridEvent, shiftDown, 0}}, + {2858, {wxNotifyEvent, allow, 0}}, + {2859, {wxNotifyEvent, isAllowed, 0}}, + {2860, {wxNotifyEvent, veto, 0}}, + {2861, {wxSashEvent, getEdge, 0}}, + {2862, {wxSashEvent, getDragRect, 0}}, + {2863, {wxSashEvent, getDragStatus, 0}}, + {2864, {wxListEvent, getCacheFrom, 0}}, + {2865, {wxListEvent, getCacheTo, 0}}, + {2866, {wxListEvent, getKeyCode, 0}}, + {2867, {wxListEvent, getIndex, 0}}, + {2868, {wxListEvent, getColumn, 0}}, + {2869, {wxListEvent, getPoint, 0}}, + {2870, {wxListEvent, getLabel, 0}}, + {2871, {wxListEvent, getText, 0}}, + {2872, {wxListEvent, getImage, 0}}, + {2873, {wxListEvent, getData, 0}}, + {2874, {wxListEvent, getMask, 0}}, + {2875, {wxListEvent, getItem, 0}}, + {2876, {wxListEvent, isEditCancelled, 0}}, + {2877, {wxDateEvent, getDate, 0}}, + {2878, {wxCalendarEvent, getWeekDay, 0}}, + {2879, {wxFileDirPickerEvent, getPath, 0}}, + {2880, {wxColourPickerEvent, getColour, 0}}, + {2881, {wxFontPickerEvent, getFont, 0}}, + {2882, {wxStyledTextEvent, getPosition, 0}}, + {2883, {wxStyledTextEvent, getKey, 0}}, + {2884, {wxStyledTextEvent, getModifiers, 0}}, + {2885, {wxStyledTextEvent, getModificationType, 0}}, + {2886, {wxStyledTextEvent, getText, 0}}, + {2887, {wxStyledTextEvent, getLength, 0}}, + {2888, {wxStyledTextEvent, getLinesAdded, 0}}, + {2889, {wxStyledTextEvent, getLine, 0}}, + {2890, {wxStyledTextEvent, getFoldLevelNow, 0}}, + {2891, {wxStyledTextEvent, getFoldLevelPrev, 0}}, + {2892, {wxStyledTextEvent, getMargin, 0}}, + {2893, {wxStyledTextEvent, getMessage, 0}}, + {2894, {wxStyledTextEvent, getWParam, 0}}, + {2895, {wxStyledTextEvent, getLParam, 0}}, + {2896, {wxStyledTextEvent, getListType, 0}}, + {2897, {wxStyledTextEvent, getX, 0}}, + {2898, {wxStyledTextEvent, getY, 0}}, + {2899, {wxStyledTextEvent, getDragText, 0}}, + {2900, {wxStyledTextEvent, getDragAllowMove, 0}}, + {2901, {wxStyledTextEvent, getDragResult, 0}}, + {2902, {wxStyledTextEvent, getShift, 0}}, + {2903, {wxStyledTextEvent, getControl, 0}}, + {2904, {wxStyledTextEvent, getAlt, 0}}, + {2905, {utils, getKeyState, 1}}, + {2906, {utils, getMousePosition, 2}}, + {2907, {utils, getMouseState, 0}}, + {2908, {utils, setDetectableAutoRepeat, 1}}, + {2909, {utils, bell, 0}}, + {2910, {utils, findMenuItemId, 3}}, + {2911, {utils, genericFindWindowAtPoint, 1}}, + {2912, {utils, findWindowAtPoint, 1}}, + {2913, {utils, beginBusyCursor, 1}}, + {2914, {utils, endBusyCursor, 0}}, + {2915, {utils, isBusy, 0}}, + {2916, {utils, shutdown, 1}}, + {2917, {utils, shell, 1}}, + {2918, {utils, launchDefaultBrowser, 2}}, + {2919, {utils, getEmailAddress, 0}}, + {2920, {utils, getUserId, 0}}, + {2921, {utils, getHomeDir, 0}}, + {2922, {utils, newId, 0}}, + {2923, {utils, registerId, 1}}, + {2924, {utils, getCurrentId, 0}}, + {2925, {utils, getOsDescription, 0}}, + {2926, {utils, isPlatformLittleEndian, 0}}, + {2927, {utils, isPlatform64Bit, 0}}, + {2928, {gdicmn, displaySize, 2}}, + {2929, {gdicmn, setCursor, 1}}, + {2930, {wxPrintout, new, 1}}, + {2931, {wxPrintout, destruct, 0}}, + {2932, {wxPrintout, getDC, 0}}, + {2933, {wxPrintout, getPageSizeMM, 2}}, + {2934, {wxPrintout, getPageSizePixels, 2}}, + {2935, {wxPrintout, getPaperRectPixels, 0}}, + {2936, {wxPrintout, getPPIPrinter, 2}}, + {2937, {wxPrintout, getPPIScreen, 2}}, + {2938, {wxPrintout, getTitle, 0}}, + {2939, {wxPrintout, isPreview, 0}}, + {2940, {wxPrintout, fitThisSizeToPaper, 1}}, + {2941, {wxPrintout, fitThisSizeToPage, 1}}, + {2942, {wxPrintout, fitThisSizeToPageMargins, 2}}, + {2943, {wxPrintout, mapScreenSizeToPaper, 0}}, + {2944, {wxPrintout, mapScreenSizeToPage, 0}}, + {2945, {wxPrintout, mapScreenSizeToPageMargins, 1}}, + {2946, {wxPrintout, mapScreenSizeToDevice, 0}}, + {2947, {wxPrintout, getLogicalPaperRect, 0}}, + {2948, {wxPrintout, getLogicalPageRect, 0}}, + {2949, {wxPrintout, getLogicalPageMarginsRect, 1}}, + {2950, {wxPrintout, setLogicalOrigin, 2}}, + {2951, {wxPrintout, offsetLogicalOrigin, 2}}, + {2952, {wxStyledTextCtrl, new_2, 2}}, + {2953, {wxStyledTextCtrl, new_0, 0}}, + {2954, {wxStyledTextCtrl, destruct, 0}}, + {2955, {wxStyledTextCtrl, create, 2}}, + {2956, {wxStyledTextCtrl, addText, 1}}, + {2957, {wxStyledTextCtrl, addStyledText, 1}}, + {2958, {wxStyledTextCtrl, insertText, 2}}, + {2959, {wxStyledTextCtrl, clearAll, 0}}, + {2960, {wxStyledTextCtrl, clearDocumentStyle, 0}}, + {2961, {wxStyledTextCtrl, getLength, 0}}, + {2962, {wxStyledTextCtrl, getCharAt, 1}}, + {2963, {wxStyledTextCtrl, getCurrentPos, 0}}, + {2964, {wxStyledTextCtrl, getAnchor, 0}}, + {2965, {wxStyledTextCtrl, getStyleAt, 1}}, + {2966, {wxStyledTextCtrl, redo, 0}}, + {2967, {wxStyledTextCtrl, setUndoCollection, 1}}, + {2968, {wxStyledTextCtrl, selectAll, 0}}, + {2969, {wxStyledTextCtrl, setSavePoint, 0}}, + {2970, {wxStyledTextCtrl, getStyledText, 2}}, + {2971, {wxStyledTextCtrl, canRedo, 0}}, + {2972, {wxStyledTextCtrl, markerLineFromHandle, 1}}, + {2973, {wxStyledTextCtrl, markerDeleteHandle, 1}}, + {2974, {wxStyledTextCtrl, getUndoCollection, 0}}, + {2975, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, + {2976, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, + {2977, {wxStyledTextCtrl, positionFromPoint, 1}}, + {2978, {wxStyledTextCtrl, positionFromPointClose, 2}}, + {2979, {wxStyledTextCtrl, gotoLine, 1}}, + {2980, {wxStyledTextCtrl, gotoPos, 1}}, + {2981, {wxStyledTextCtrl, setAnchor, 1}}, + {2982, {wxStyledTextCtrl, getCurLine, 1}}, + {2983, {wxStyledTextCtrl, getEndStyled, 0}}, + {2984, {wxStyledTextCtrl, convertEOLs, 1}}, + {2985, {wxStyledTextCtrl, getEOLMode, 0}}, + {2986, {wxStyledTextCtrl, setEOLMode, 1}}, + {2987, {wxStyledTextCtrl, startStyling, 2}}, + {2988, {wxStyledTextCtrl, setStyling, 2}}, + {2989, {wxStyledTextCtrl, getBufferedDraw, 0}}, + {2990, {wxStyledTextCtrl, setBufferedDraw, 1}}, + {2991, {wxStyledTextCtrl, setTabWidth, 1}}, + {2992, {wxStyledTextCtrl, getTabWidth, 0}}, + {2993, {wxStyledTextCtrl, setCodePage, 1}}, + {2994, {wxStyledTextCtrl, markerDefine, 3}}, + {2995, {wxStyledTextCtrl, markerSetForeground, 2}}, + {2996, {wxStyledTextCtrl, markerSetBackground, 2}}, + {2997, {wxStyledTextCtrl, markerAdd, 2}}, + {2998, {wxStyledTextCtrl, markerDelete, 2}}, + {2999, {wxStyledTextCtrl, markerDeleteAll, 1}}, + {3000, {wxStyledTextCtrl, markerGet, 1}}, + {3001, {wxStyledTextCtrl, markerNext, 2}}, + {3002, {wxStyledTextCtrl, markerPrevious, 2}}, + {3003, {wxStyledTextCtrl, markerDefineBitmap, 2}}, + {3004, {wxStyledTextCtrl, markerAddSet, 2}}, + {3005, {wxStyledTextCtrl, markerSetAlpha, 2}}, + {3006, {wxStyledTextCtrl, setMarginType, 2}}, + {3007, {wxStyledTextCtrl, getMarginType, 1}}, + {3008, {wxStyledTextCtrl, setMarginWidth, 2}}, + {3009, {wxStyledTextCtrl, getMarginWidth, 1}}, + {3010, {wxStyledTextCtrl, setMarginMask, 2}}, + {3011, {wxStyledTextCtrl, getMarginMask, 1}}, + {3012, {wxStyledTextCtrl, setMarginSensitive, 2}}, + {3013, {wxStyledTextCtrl, getMarginSensitive, 1}}, + {3014, {wxStyledTextCtrl, styleClearAll, 0}}, + {3015, {wxStyledTextCtrl, styleSetForeground, 2}}, + {3016, {wxStyledTextCtrl, styleSetBackground, 2}}, + {3017, {wxStyledTextCtrl, styleSetBold, 2}}, + {3018, {wxStyledTextCtrl, styleSetItalic, 2}}, + {3019, {wxStyledTextCtrl, styleSetSize, 2}}, + {3020, {wxStyledTextCtrl, styleSetFaceName, 2}}, + {3021, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, + {3022, {wxStyledTextCtrl, styleResetDefault, 0}}, + {3023, {wxStyledTextCtrl, styleSetUnderline, 2}}, + {3024, {wxStyledTextCtrl, styleSetCase, 2}}, + {3025, {wxStyledTextCtrl, styleSetHotSpot, 2}}, + {3026, {wxStyledTextCtrl, setSelForeground, 2}}, + {3027, {wxStyledTextCtrl, setSelBackground, 2}}, + {3028, {wxStyledTextCtrl, getSelAlpha, 0}}, + {3029, {wxStyledTextCtrl, setSelAlpha, 1}}, + {3030, {wxStyledTextCtrl, setCaretForeground, 1}}, + {3031, {wxStyledTextCtrl, cmdKeyAssign, 3}}, + {3032, {wxStyledTextCtrl, cmdKeyClear, 2}}, + {3033, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, + {3034, {wxStyledTextCtrl, setStyleBytes, 2}}, + {3035, {wxStyledTextCtrl, styleSetVisible, 2}}, + {3036, {wxStyledTextCtrl, getCaretPeriod, 0}}, + {3037, {wxStyledTextCtrl, setCaretPeriod, 1}}, + {3038, {wxStyledTextCtrl, setWordChars, 1}}, + {3039, {wxStyledTextCtrl, beginUndoAction, 0}}, + {3040, {wxStyledTextCtrl, endUndoAction, 0}}, + {3041, {wxStyledTextCtrl, indicatorSetStyle, 2}}, + {3042, {wxStyledTextCtrl, indicatorGetStyle, 1}}, + {3043, {wxStyledTextCtrl, indicatorSetForeground, 2}}, + {3044, {wxStyledTextCtrl, indicatorGetForeground, 1}}, + {3045, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, + {3046, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, + {3047, {wxStyledTextCtrl, getStyleBits, 0}}, + {3048, {wxStyledTextCtrl, setLineState, 2}}, + {3049, {wxStyledTextCtrl, getLineState, 1}}, + {3050, {wxStyledTextCtrl, getMaxLineState, 0}}, + {3051, {wxStyledTextCtrl, getCaretLineVisible, 0}}, + {3052, {wxStyledTextCtrl, setCaretLineVisible, 1}}, + {3053, {wxStyledTextCtrl, getCaretLineBackground, 0}}, + {3054, {wxStyledTextCtrl, setCaretLineBackground, 1}}, + {3055, {wxStyledTextCtrl, autoCompShow, 2}}, + {3056, {wxStyledTextCtrl, autoCompCancel, 0}}, + {3057, {wxStyledTextCtrl, autoCompActive, 0}}, + {3058, {wxStyledTextCtrl, autoCompPosStart, 0}}, + {3059, {wxStyledTextCtrl, autoCompComplete, 0}}, + {3060, {wxStyledTextCtrl, autoCompStops, 1}}, + {3061, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, + {3062, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, + {3063, {wxStyledTextCtrl, autoCompSelect, 1}}, + {3064, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, + {3065, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, + {3066, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, + {3067, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, + {3068, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, + {3069, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, + {3070, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, + {3071, {wxStyledTextCtrl, userListShow, 2}}, + {3072, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, + {3073, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, + {3074, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, + {3075, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, + {3076, {wxStyledTextCtrl, registerImage, 2}}, + {3077, {wxStyledTextCtrl, clearRegisteredImages, 0}}, + {3078, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, + {3079, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, + {3080, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, + {3081, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, + {3082, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, + {3083, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, + {3084, {wxStyledTextCtrl, setIndent, 1}}, + {3085, {wxStyledTextCtrl, getIndent, 0}}, + {3086, {wxStyledTextCtrl, setUseTabs, 1}}, + {3087, {wxStyledTextCtrl, getUseTabs, 0}}, + {3088, {wxStyledTextCtrl, setLineIndentation, 2}}, + {3089, {wxStyledTextCtrl, getLineIndentation, 1}}, + {3090, {wxStyledTextCtrl, getLineIndentPosition, 1}}, + {3091, {wxStyledTextCtrl, getColumn, 1}}, + {3092, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, + {3093, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, + {3094, {wxStyledTextCtrl, setIndentationGuides, 1}}, + {3095, {wxStyledTextCtrl, getIndentationGuides, 0}}, + {3096, {wxStyledTextCtrl, setHighlightGuide, 1}}, + {3097, {wxStyledTextCtrl, getHighlightGuide, 0}}, + {3098, {wxStyledTextCtrl, getLineEndPosition, 1}}, + {3099, {wxStyledTextCtrl, getCodePage, 0}}, + {3100, {wxStyledTextCtrl, getCaretForeground, 0}}, + {3101, {wxStyledTextCtrl, getReadOnly, 0}}, + {3102, {wxStyledTextCtrl, setCurrentPos, 1}}, + {3103, {wxStyledTextCtrl, setSelectionStart, 1}}, + {3104, {wxStyledTextCtrl, getSelectionStart, 0}}, + {3105, {wxStyledTextCtrl, setSelectionEnd, 1}}, + {3106, {wxStyledTextCtrl, getSelectionEnd, 0}}, + {3107, {wxStyledTextCtrl, setPrintMagnification, 1}}, + {3108, {wxStyledTextCtrl, getPrintMagnification, 0}}, + {3109, {wxStyledTextCtrl, setPrintColourMode, 1}}, + {3110, {wxStyledTextCtrl, getPrintColourMode, 0}}, + {3111, {wxStyledTextCtrl, findText, 4}}, + {3112, {wxStyledTextCtrl, formatRange, 7}}, + {3113, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, + {3114, {wxStyledTextCtrl, getLine, 1}}, + {3115, {wxStyledTextCtrl, getLineCount, 0}}, + {3116, {wxStyledTextCtrl, setMarginLeft, 1}}, + {3117, {wxStyledTextCtrl, getMarginLeft, 0}}, + {3118, {wxStyledTextCtrl, setMarginRight, 1}}, + {3119, {wxStyledTextCtrl, getMarginRight, 0}}, + {3120, {wxStyledTextCtrl, getModify, 0}}, + {3121, {wxStyledTextCtrl, setSelection, 2}}, + {3122, {wxStyledTextCtrl, getSelectedText, 0}}, + {3123, {wxStyledTextCtrl, getTextRange, 2}}, + {3124, {wxStyledTextCtrl, hideSelection, 1}}, + {3125, {wxStyledTextCtrl, lineFromPosition, 1}}, + {3126, {wxStyledTextCtrl, positionFromLine, 1}}, + {3127, {wxStyledTextCtrl, lineScroll, 2}}, + {3128, {wxStyledTextCtrl, ensureCaretVisible, 0}}, + {3129, {wxStyledTextCtrl, replaceSelection, 1}}, + {3130, {wxStyledTextCtrl, setReadOnly, 1}}, + {3131, {wxStyledTextCtrl, canPaste, 0}}, + {3132, {wxStyledTextCtrl, canUndo, 0}}, + {3133, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, + {3134, {wxStyledTextCtrl, undo, 0}}, + {3135, {wxStyledTextCtrl, cut, 0}}, + {3136, {wxStyledTextCtrl, copy, 0}}, + {3137, {wxStyledTextCtrl, paste, 0}}, + {3138, {wxStyledTextCtrl, clear, 0}}, + {3139, {wxStyledTextCtrl, setText, 1}}, + {3140, {wxStyledTextCtrl, getText, 0}}, + {3141, {wxStyledTextCtrl, getTextLength, 0}}, + {3142, {wxStyledTextCtrl, getOvertype, 0}}, + {3143, {wxStyledTextCtrl, setCaretWidth, 1}}, + {3144, {wxStyledTextCtrl, getCaretWidth, 0}}, + {3145, {wxStyledTextCtrl, setTargetStart, 1}}, + {3146, {wxStyledTextCtrl, getTargetStart, 0}}, + {3147, {wxStyledTextCtrl, setTargetEnd, 1}}, + {3148, {wxStyledTextCtrl, getTargetEnd, 0}}, + {3149, {wxStyledTextCtrl, replaceTarget, 1}}, + {3150, {wxStyledTextCtrl, searchInTarget, 1}}, + {3151, {wxStyledTextCtrl, setSearchFlags, 1}}, + {3152, {wxStyledTextCtrl, getSearchFlags, 0}}, + {3153, {wxStyledTextCtrl, callTipShow, 2}}, + {3154, {wxStyledTextCtrl, callTipCancel, 0}}, + {3155, {wxStyledTextCtrl, callTipActive, 0}}, + {3156, {wxStyledTextCtrl, callTipPosAtStart, 0}}, + {3157, {wxStyledTextCtrl, callTipSetHighlight, 2}}, + {3158, {wxStyledTextCtrl, callTipSetBackground, 1}}, + {3159, {wxStyledTextCtrl, callTipSetForeground, 1}}, + {3160, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, + {3161, {wxStyledTextCtrl, callTipUseStyle, 1}}, + {3162, {wxStyledTextCtrl, visibleFromDocLine, 1}}, + {3163, {wxStyledTextCtrl, docLineFromVisible, 1}}, + {3164, {wxStyledTextCtrl, wrapCount, 1}}, + {3165, {wxStyledTextCtrl, setFoldLevel, 2}}, + {3166, {wxStyledTextCtrl, getFoldLevel, 1}}, + {3167, {wxStyledTextCtrl, getLastChild, 2}}, + {3168, {wxStyledTextCtrl, getFoldParent, 1}}, + {3169, {wxStyledTextCtrl, showLines, 2}}, + {3170, {wxStyledTextCtrl, hideLines, 2}}, + {3171, {wxStyledTextCtrl, getLineVisible, 1}}, + {3172, {wxStyledTextCtrl, setFoldExpanded, 2}}, + {3173, {wxStyledTextCtrl, getFoldExpanded, 1}}, + {3174, {wxStyledTextCtrl, toggleFold, 1}}, + {3175, {wxStyledTextCtrl, ensureVisible, 1}}, + {3176, {wxStyledTextCtrl, setFoldFlags, 1}}, + {3177, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, + {3178, {wxStyledTextCtrl, setTabIndents, 1}}, + {3179, {wxStyledTextCtrl, getTabIndents, 0}}, + {3180, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, + {3181, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, + {3182, {wxStyledTextCtrl, setMouseDwellTime, 1}}, + {3183, {wxStyledTextCtrl, getMouseDwellTime, 0}}, + {3184, {wxStyledTextCtrl, wordStartPosition, 2}}, + {3185, {wxStyledTextCtrl, wordEndPosition, 2}}, + {3186, {wxStyledTextCtrl, setWrapMode, 1}}, + {3187, {wxStyledTextCtrl, getWrapMode, 0}}, + {3188, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, + {3189, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, + {3190, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, + {3191, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, + {3192, {wxStyledTextCtrl, setWrapStartIndent, 1}}, + {3193, {wxStyledTextCtrl, getWrapStartIndent, 0}}, + {3194, {wxStyledTextCtrl, setLayoutCache, 1}}, + {3195, {wxStyledTextCtrl, getLayoutCache, 0}}, + {3196, {wxStyledTextCtrl, setScrollWidth, 1}}, + {3197, {wxStyledTextCtrl, getScrollWidth, 0}}, + {3198, {wxStyledTextCtrl, textWidth, 2}}, + {3199, {wxStyledTextCtrl, getEndAtLastLine, 0}}, + {3200, {wxStyledTextCtrl, textHeight, 1}}, + {3201, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, + {3202, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, + {3203, {wxStyledTextCtrl, appendText, 1}}, + {3204, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, + {3205, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, + {3206, {wxStyledTextCtrl, targetFromSelection, 0}}, + {3207, {wxStyledTextCtrl, linesJoin, 0}}, + {3208, {wxStyledTextCtrl, linesSplit, 1}}, + {3209, {wxStyledTextCtrl, setFoldMarginColour, 2}}, + {3210, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, + {3211, {wxStyledTextCtrl, lineDown, 0}}, + {3212, {wxStyledTextCtrl, lineDownExtend, 0}}, + {3213, {wxStyledTextCtrl, lineUp, 0}}, + {3214, {wxStyledTextCtrl, lineUpExtend, 0}}, + {3215, {wxStyledTextCtrl, charLeft, 0}}, + {3216, {wxStyledTextCtrl, charLeftExtend, 0}}, + {3217, {wxStyledTextCtrl, charRight, 0}}, + {3218, {wxStyledTextCtrl, charRightExtend, 0}}, + {3219, {wxStyledTextCtrl, wordLeft, 0}}, + {3220, {wxStyledTextCtrl, wordLeftExtend, 0}}, + {3221, {wxStyledTextCtrl, wordRight, 0}}, + {3222, {wxStyledTextCtrl, wordRightExtend, 0}}, + {3223, {wxStyledTextCtrl, home, 0}}, + {3224, {wxStyledTextCtrl, homeExtend, 0}}, + {3225, {wxStyledTextCtrl, lineEnd, 0}}, + {3226, {wxStyledTextCtrl, lineEndExtend, 0}}, + {3227, {wxStyledTextCtrl, documentStart, 0}}, + {3228, {wxStyledTextCtrl, documentStartExtend, 0}}, + {3229, {wxStyledTextCtrl, documentEnd, 0}}, + {3230, {wxStyledTextCtrl, documentEndExtend, 0}}, + {3231, {wxStyledTextCtrl, pageUp, 0}}, + {3232, {wxStyledTextCtrl, pageUpExtend, 0}}, + {3233, {wxStyledTextCtrl, pageDown, 0}}, + {3234, {wxStyledTextCtrl, pageDownExtend, 0}}, + {3235, {wxStyledTextCtrl, editToggleOvertype, 0}}, + {3236, {wxStyledTextCtrl, cancel, 0}}, + {3237, {wxStyledTextCtrl, deleteBack, 0}}, + {3238, {wxStyledTextCtrl, tab, 0}}, + {3239, {wxStyledTextCtrl, backTab, 0}}, + {3240, {wxStyledTextCtrl, newLine, 0}}, + {3241, {wxStyledTextCtrl, formFeed, 0}}, + {3242, {wxStyledTextCtrl, vCHome, 0}}, + {3243, {wxStyledTextCtrl, vCHomeExtend, 0}}, + {3244, {wxStyledTextCtrl, zoomIn, 0}}, + {3245, {wxStyledTextCtrl, zoomOut, 0}}, + {3246, {wxStyledTextCtrl, delWordLeft, 0}}, + {3247, {wxStyledTextCtrl, delWordRight, 0}}, + {3248, {wxStyledTextCtrl, lineCut, 0}}, + {3249, {wxStyledTextCtrl, lineDelete, 0}}, + {3250, {wxStyledTextCtrl, lineTranspose, 0}}, + {3251, {wxStyledTextCtrl, lineDuplicate, 0}}, + {3252, {wxStyledTextCtrl, lowerCase, 0}}, + {3253, {wxStyledTextCtrl, upperCase, 0}}, + {3254, {wxStyledTextCtrl, lineScrollDown, 0}}, + {3255, {wxStyledTextCtrl, lineScrollUp, 0}}, + {3256, {wxStyledTextCtrl, deleteBackNotLine, 0}}, + {3257, {wxStyledTextCtrl, homeDisplay, 0}}, + {3258, {wxStyledTextCtrl, homeDisplayExtend, 0}}, + {3259, {wxStyledTextCtrl, lineEndDisplay, 0}}, + {3260, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, + {3261, {wxStyledTextCtrl, homeWrapExtend, 0}}, + {3262, {wxStyledTextCtrl, lineEndWrap, 0}}, + {3263, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, + {3264, {wxStyledTextCtrl, vCHomeWrap, 0}}, + {3265, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, + {3266, {wxStyledTextCtrl, lineCopy, 0}}, + {3267, {wxStyledTextCtrl, moveCaretInsideView, 0}}, + {3268, {wxStyledTextCtrl, lineLength, 1}}, + {3269, {wxStyledTextCtrl, braceHighlight, 2}}, + {3270, {wxStyledTextCtrl, braceBadLight, 1}}, + {3271, {wxStyledTextCtrl, braceMatch, 1}}, + {3272, {wxStyledTextCtrl, getViewEOL, 0}}, + {3273, {wxStyledTextCtrl, setViewEOL, 1}}, + {3274, {wxStyledTextCtrl, setModEventMask, 1}}, + {3275, {wxStyledTextCtrl, getEdgeColumn, 0}}, + {3276, {wxStyledTextCtrl, setEdgeColumn, 1}}, + {3277, {wxStyledTextCtrl, setEdgeMode, 1}}, + {3278, {wxStyledTextCtrl, getEdgeMode, 0}}, + {3279, {wxStyledTextCtrl, getEdgeColour, 0}}, + {3280, {wxStyledTextCtrl, setEdgeColour, 1}}, + {3281, {wxStyledTextCtrl, searchAnchor, 0}}, + {3282, {wxStyledTextCtrl, searchNext, 2}}, + {3283, {wxStyledTextCtrl, searchPrev, 2}}, + {3284, {wxStyledTextCtrl, linesOnScreen, 0}}, + {3285, {wxStyledTextCtrl, usePopUp, 1}}, + {3286, {wxStyledTextCtrl, selectionIsRectangle, 0}}, + {3287, {wxStyledTextCtrl, setZoom, 1}}, + {3288, {wxStyledTextCtrl, getZoom, 0}}, + {3289, {wxStyledTextCtrl, getModEventMask, 0}}, + {3290, {wxStyledTextCtrl, setSTCFocus, 1}}, + {3291, {wxStyledTextCtrl, getSTCFocus, 0}}, + {3292, {wxStyledTextCtrl, setStatus, 1}}, + {3293, {wxStyledTextCtrl, getStatus, 0}}, + {3294, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, + {3295, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, + {3296, {wxStyledTextCtrl, setSTCCursor, 1}}, + {3297, {wxStyledTextCtrl, getSTCCursor, 0}}, + {3298, {wxStyledTextCtrl, setControlCharSymbol, 1}}, + {3299, {wxStyledTextCtrl, getControlCharSymbol, 0}}, + {3300, {wxStyledTextCtrl, wordPartLeft, 0}}, + {3301, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, + {3302, {wxStyledTextCtrl, wordPartRight, 0}}, + {3303, {wxStyledTextCtrl, wordPartRightExtend, 0}}, + {3304, {wxStyledTextCtrl, setVisiblePolicy, 2}}, + {3305, {wxStyledTextCtrl, delLineLeft, 0}}, + {3306, {wxStyledTextCtrl, delLineRight, 0}}, + {3307, {wxStyledTextCtrl, getXOffset, 0}}, + {3308, {wxStyledTextCtrl, chooseCaretX, 0}}, + {3309, {wxStyledTextCtrl, setXCaretPolicy, 2}}, + {3310, {wxStyledTextCtrl, setYCaretPolicy, 2}}, + {3311, {wxStyledTextCtrl, getPrintWrapMode, 0}}, + {3312, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, + {3313, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, + {3314, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, + {3315, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, + {3316, {wxStyledTextCtrl, paraDownExtend, 0}}, + {3317, {wxStyledTextCtrl, paraUp, 0}}, + {3318, {wxStyledTextCtrl, paraUpExtend, 0}}, + {3319, {wxStyledTextCtrl, positionBefore, 1}}, + {3320, {wxStyledTextCtrl, positionAfter, 1}}, + {3321, {wxStyledTextCtrl, copyRange, 2}}, + {3322, {wxStyledTextCtrl, copyText, 2}}, + {3323, {wxStyledTextCtrl, setSelectionMode, 1}}, + {3324, {wxStyledTextCtrl, getSelectionMode, 0}}, + {3325, {wxStyledTextCtrl, lineDownRectExtend, 0}}, + {3326, {wxStyledTextCtrl, lineUpRectExtend, 0}}, + {3327, {wxStyledTextCtrl, charLeftRectExtend, 0}}, + {3328, {wxStyledTextCtrl, charRightRectExtend, 0}}, + {3329, {wxStyledTextCtrl, homeRectExtend, 0}}, + {3330, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, + {3331, {wxStyledTextCtrl, lineEndRectExtend, 0}}, + {3332, {wxStyledTextCtrl, pageUpRectExtend, 0}}, + {3333, {wxStyledTextCtrl, pageDownRectExtend, 0}}, + {3334, {wxStyledTextCtrl, stutteredPageUp, 0}}, + {3335, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, + {3336, {wxStyledTextCtrl, stutteredPageDown, 0}}, + {3337, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, + {3338, {wxStyledTextCtrl, wordLeftEnd, 0}}, + {3339, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, + {3340, {wxStyledTextCtrl, wordRightEnd, 0}}, + {3341, {wxStyledTextCtrl, wordRightEndExtend, 0}}, + {3342, {wxStyledTextCtrl, setWhitespaceChars, 1}}, + {3343, {wxStyledTextCtrl, setCharsDefault, 0}}, + {3344, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, + {3345, {wxStyledTextCtrl, allocate, 1}}, + {3346, {wxStyledTextCtrl, findColumn, 2}}, + {3347, {wxStyledTextCtrl, getCaretSticky, 0}}, + {3348, {wxStyledTextCtrl, setCaretSticky, 1}}, + {3349, {wxStyledTextCtrl, toggleCaretSticky, 0}}, + {3350, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, + {3351, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, + {3352, {wxStyledTextCtrl, selectionDuplicate, 0}}, + {3353, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, + {3354, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, + {3355, {wxStyledTextCtrl, startRecord, 0}}, + {3356, {wxStyledTextCtrl, stopRecord, 0}}, + {3357, {wxStyledTextCtrl, setLexer, 1}}, + {3358, {wxStyledTextCtrl, getLexer, 0}}, + {3359, {wxStyledTextCtrl, colourise, 2}}, + {3360, {wxStyledTextCtrl, setProperty, 2}}, + {3361, {wxStyledTextCtrl, setKeyWords, 2}}, + {3362, {wxStyledTextCtrl, setLexerLanguage, 1}}, + {3363, {wxStyledTextCtrl, getProperty, 1}}, + {3364, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, + {3365, {wxStyledTextCtrl, getCurrentLine, 0}}, + {3366, {wxStyledTextCtrl, styleSetSpec, 2}}, + {3367, {wxStyledTextCtrl, styleSetFont, 2}}, + {3368, {wxStyledTextCtrl, styleSetFontAttr, 7}}, + {3369, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, + {3370, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, + {3371, {wxStyledTextCtrl, cmdKeyExecute, 1}}, + {3372, {wxStyledTextCtrl, setMargins, 2}}, + {3373, {wxStyledTextCtrl, getSelection, 2}}, + {3374, {wxStyledTextCtrl, pointFromPosition, 1}}, + {3375, {wxStyledTextCtrl, scrollToLine, 1}}, + {3376, {wxStyledTextCtrl, scrollToColumn, 1}}, + {3377, {wxStyledTextCtrl, setVScrollBar, 1}}, + {3378, {wxStyledTextCtrl, setHScrollBar, 1}}, + {3379, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, + {3380, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, + {3381, {wxStyledTextCtrl, saveFile, 1}}, + {3382, {wxStyledTextCtrl, loadFile, 1}}, + {3383, {wxStyledTextCtrl, doDragOver, 3}}, + {3384, {wxStyledTextCtrl, doDropText, 3}}, + {3385, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, + {3386, {wxStyledTextCtrl, addTextRaw, 1}}, + {3387, {wxStyledTextCtrl, insertTextRaw, 2}}, + {3388, {wxStyledTextCtrl, getCurLineRaw, 1}}, + {3389, {wxStyledTextCtrl, getLineRaw, 1}}, + {3390, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, + {3391, {wxStyledTextCtrl, getTextRangeRaw, 2}}, + {3392, {wxStyledTextCtrl, setTextRaw, 1}}, + {3393, {wxStyledTextCtrl, getTextRaw, 0}}, + {3394, {wxStyledTextCtrl, appendTextRaw, 1}}, + {3395, {wxArtProvider, getBitmap, 2}}, + {3396, {wxArtProvider, getIcon, 2}}, + {3397, {wxTreeEvent, getKeyCode, 0}}, + {3398, {wxTreeEvent, getItem, 0}}, + {3399, {wxTreeEvent, getKeyEvent, 0}}, + {3400, {wxTreeEvent, getLabel, 0}}, + {3401, {wxTreeEvent, getOldItem, 0}}, + {3402, {wxTreeEvent, getPoint, 0}}, + {3403, {wxTreeEvent, isEditCancelled, 0}}, + {3404, {wxTreeEvent, setToolTip, 1}}, + {3405, {wxNotebookEvent, getOldSelection, 0}}, + {3406, {wxNotebookEvent, getSelection, 0}}, + {3407, {wxNotebookEvent, setOldSelection, 1}}, + {3408, {wxNotebookEvent, setSelection, 1}}, + {3409, {wxFileDataObject, new, 0}}, + {3410, {wxFileDataObject, addFile, 1}}, + {3411, {wxFileDataObject, getFilenames, 0}}, + {3412, {wxFileDataObject, 'Destroy', undefined}}, + {3413, {wxTextDataObject, new, 1}}, + {3414, {wxTextDataObject, getTextLength, 0}}, + {3415, {wxTextDataObject, getText, 0}}, + {3416, {wxTextDataObject, setText, 1}}, + {3417, {wxTextDataObject, 'Destroy', undefined}}, + {3418, {wxBitmapDataObject, new_1_1, 1}}, + {3419, {wxBitmapDataObject, new_1_0, 1}}, + {3420, {wxBitmapDataObject, getBitmap, 0}}, + {3421, {wxBitmapDataObject, setBitmap, 1}}, + {3422, {wxBitmapDataObject, 'Destroy', undefined}}, + {3424, {wxClipboard, new, 0}}, + {3425, {wxClipboard, destruct, 0}}, + {3426, {wxClipboard, addData, 1}}, + {3427, {wxClipboard, clear, 0}}, + {3428, {wxClipboard, close, 0}}, + {3429, {wxClipboard, flush, 0}}, + {3430, {wxClipboard, getData, 1}}, + {3431, {wxClipboard, isOpened, 0}}, + {3432, {wxClipboard, open, 0}}, + {3433, {wxClipboard, setData, 1}}, + {3435, {wxClipboard, usePrimarySelection, 1}}, + {3436, {wxClipboard, isSupported, 1}}, + {3437, {wxClipboard, get, 0}}, + {3438, {wxSpinEvent, getPosition, 0}}, + {3439, {wxSpinEvent, setPosition, 1}}, + {3440, {wxSplitterWindow, new_0, 0}}, + {3441, {wxSplitterWindow, new_2, 2}}, + {3442, {wxSplitterWindow, destruct, 0}}, + {3443, {wxSplitterWindow, create, 2}}, + {3444, {wxSplitterWindow, getMinimumPaneSize, 0}}, + {3445, {wxSplitterWindow, getSashGravity, 0}}, + {3446, {wxSplitterWindow, getSashPosition, 0}}, + {3447, {wxSplitterWindow, getSplitMode, 0}}, + {3448, {wxSplitterWindow, getWindow1, 0}}, + {3449, {wxSplitterWindow, getWindow2, 0}}, + {3450, {wxSplitterWindow, initialize, 1}}, + {3451, {wxSplitterWindow, isSplit, 0}}, + {3452, {wxSplitterWindow, replaceWindow, 2}}, + {3453, {wxSplitterWindow, setSashGravity, 1}}, + {3454, {wxSplitterWindow, setSashPosition, 2}}, + {3455, {wxSplitterWindow, setSashSize, 1}}, + {3456, {wxSplitterWindow, setMinimumPaneSize, 1}}, + {3457, {wxSplitterWindow, setSplitMode, 1}}, + {3458, {wxSplitterWindow, splitHorizontally, 3}}, + {3459, {wxSplitterWindow, splitVertically, 3}}, + {3460, {wxSplitterWindow, unsplit, 1}}, + {3461, {wxSplitterWindow, updateSize, 0}}, + {3462, {wxSplitterEvent, getSashPosition, 0}}, + {3463, {wxSplitterEvent, getX, 0}}, + {3464, {wxSplitterEvent, getY, 0}}, + {3465, {wxSplitterEvent, getWindowBeingRemoved, 0}}, + {3466, {wxSplitterEvent, setSashPosition, 1}}, + {3467, {wxHtmlWindow, new_0, 0}}, + {3468, {wxHtmlWindow, new_2, 2}}, + {3469, {wxHtmlWindow, appendToPage, 1}}, + {3470, {wxHtmlWindow, getOpenedAnchor, 0}}, + {3471, {wxHtmlWindow, getOpenedPage, 0}}, + {3472, {wxHtmlWindow, getOpenedPageTitle, 0}}, + {3473, {wxHtmlWindow, getRelatedFrame, 0}}, + {3474, {wxHtmlWindow, historyBack, 0}}, + {3475, {wxHtmlWindow, historyCanBack, 0}}, + {3476, {wxHtmlWindow, historyCanForward, 0}}, + {3477, {wxHtmlWindow, historyClear, 0}}, + {3478, {wxHtmlWindow, historyForward, 0}}, + {3479, {wxHtmlWindow, loadFile, 1}}, + {3480, {wxHtmlWindow, loadPage, 1}}, + {3481, {wxHtmlWindow, selectAll, 0}}, + {3482, {wxHtmlWindow, selectionToText, 0}}, + {3483, {wxHtmlWindow, selectLine, 1}}, + {3484, {wxHtmlWindow, selectWord, 1}}, + {3485, {wxHtmlWindow, setBorders, 1}}, + {3486, {wxHtmlWindow, setFonts, 3}}, + {3487, {wxHtmlWindow, setPage, 1}}, + {3488, {wxHtmlWindow, setRelatedFrame, 2}}, + {3489, {wxHtmlWindow, setRelatedStatusBar, 1}}, + {3490, {wxHtmlWindow, toText, 0}}, + {3491, {wxHtmlWindow, 'Destroy', undefined}}, + {3492, {wxHtmlLinkEvent, getLinkInfo, 0}}, + {3493, {wxSystemSettings, getColour, 1}}, + {3494, {wxSystemSettings, getFont, 1}}, + {3495, {wxSystemSettings, getMetric, 2}}, + {3496, {wxSystemSettings, getScreenType, 0}}, + {3497, {wxSystemOptions, getOption, 1}}, + {3498, {wxSystemOptions, getOptionInt, 1}}, + {3499, {wxSystemOptions, hasOption, 1}}, + {3500, {wxSystemOptions, isFalse, 1}}, + {3501, {wxSystemOptions, setOption_2_1, 2}}, + {3502, {wxSystemOptions, setOption_2_0, 2}}, + {3503, {wxAuiNotebookEvent, setSelection, 1}}, + {3504, {wxAuiNotebookEvent, getSelection, 0}}, + {3505, {wxAuiNotebookEvent, setOldSelection, 1}}, + {3506, {wxAuiNotebookEvent, getOldSelection, 0}}, + {3507, {wxAuiNotebookEvent, setDragSource, 1}}, + {3508, {wxAuiNotebookEvent, getDragSource, 0}}, + {3509, {wxAuiManagerEvent, setManager, 1}}, + {3510, {wxAuiManagerEvent, getManager, 0}}, + {3511, {wxAuiManagerEvent, setPane, 1}}, + {3512, {wxAuiManagerEvent, getPane, 0}}, + {3513, {wxAuiManagerEvent, setButton, 1}}, + {3514, {wxAuiManagerEvent, getButton, 0}}, + {3515, {wxAuiManagerEvent, setDC, 1}}, + {3516, {wxAuiManagerEvent, getDC, 0}}, + {3517, {wxAuiManagerEvent, veto, 1}}, + {3518, {wxAuiManagerEvent, getVeto, 0}}, + {3519, {wxAuiManagerEvent, setCanVeto, 1}}, + {3520, {wxAuiManagerEvent, canVeto, 0}}, + {3521, {wxLogNull, new, 0}}, + {3522, {wxLogNull, 'Destroy', undefined}}, + {3523, {wxTaskBarIcon, new, 0}}, + {3524, {wxTaskBarIcon, destruct, 0}}, + {3525, {wxTaskBarIcon, popupMenu, 1}}, + {3526, {wxTaskBarIcon, removeIcon, 0}}, + {3527, {wxTaskBarIcon, setIcon, 2}}, + {3528, {wxLocale, new_0, 0}}, + {3530, {wxLocale, new_2, 2}}, + {3531, {wxLocale, destruct, 0}}, + {3533, {wxLocale, init, 1}}, + {3534, {wxLocale, addCatalog_1, 1}}, + {3535, {wxLocale, addCatalog_3, 3}}, + {3536, {wxLocale, addCatalogLookupPathPrefix, 1}}, + {3537, {wxLocale, getCanonicalName, 0}}, + {3538, {wxLocale, getLanguage, 0}}, + {3539, {wxLocale, getLanguageName, 1}}, + {3540, {wxLocale, getLocale, 0}}, + {3541, {wxLocale, getName, 0}}, + {3542, {wxLocale, getString_2, 2}}, + {3543, {wxLocale, getString_4, 4}}, + {3544, {wxLocale, getHeaderValue, 2}}, + {3545, {wxLocale, getSysName, 0}}, + {3546, {wxLocale, getSystemEncoding, 0}}, + {3547, {wxLocale, getSystemEncodingName, 0}}, + {3548, {wxLocale, getSystemLanguage, 0}}, + {3549, {wxLocale, isLoaded, 1}}, + {3550, {wxLocale, isOk, 0}}, + {3551, {wxActivateEvent, getActive, 0}}, + {3553, {wxPopupWindow, new_2, 2}}, + {3554, {wxPopupWindow, new_0, 0}}, + {3556, {wxPopupWindow, destruct, 0}}, + {3557, {wxPopupWindow, create, 2}}, + {3558, {wxPopupWindow, position, 2}}, + {3559, {wxPopupTransientWindow, new_0, 0}}, + {3560, {wxPopupTransientWindow, new_2, 2}}, + {3561, {wxPopupTransientWindow, destruct, 0}}, + {3562, {wxPopupTransientWindow, popup, 1}}, + {3563, {wxPopupTransientWindow, dismiss, 0}}, {-1, {mod, func, -1}} ]. diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl index 97f9bd9695..82d0d265d7 100644 --- a/lib/wx/src/gen/wxe_funcs.hrl +++ b/lib/wx/src/gen/wxe_funcs.hrl @@ -1666,1662 +1666,1674 @@ -define(wxTextCtrl_Create, 1824). -define(wxTextCtrl_Cut, 1825). -define(wxTextCtrl_DiscardEdits, 1826). --define(wxTextCtrl_EmulateKeyPress, 1827). --define(wxTextCtrl_GetDefaultStyle, 1828). --define(wxTextCtrl_GetInsertionPoint, 1829). --define(wxTextCtrl_GetLastPosition, 1830). --define(wxTextCtrl_GetLineLength, 1831). --define(wxTextCtrl_GetLineText, 1832). --define(wxTextCtrl_GetNumberOfLines, 1833). --define(wxTextCtrl_GetRange, 1834). --define(wxTextCtrl_GetSelection, 1835). --define(wxTextCtrl_GetStringSelection, 1836). --define(wxTextCtrl_GetStyle, 1837). --define(wxTextCtrl_GetValue, 1838). --define(wxTextCtrl_IsEditable, 1839). --define(wxTextCtrl_IsModified, 1840). --define(wxTextCtrl_IsMultiLine, 1841). --define(wxTextCtrl_IsSingleLine, 1842). --define(wxTextCtrl_LoadFile, 1843). --define(wxTextCtrl_MarkDirty, 1844). --define(wxTextCtrl_Paste, 1845). --define(wxTextCtrl_PositionToXY, 1846). --define(wxTextCtrl_Redo, 1847). --define(wxTextCtrl_Remove, 1848). --define(wxTextCtrl_Replace, 1849). --define(wxTextCtrl_SaveFile, 1850). --define(wxTextCtrl_SetDefaultStyle, 1851). --define(wxTextCtrl_SetEditable, 1852). --define(wxTextCtrl_SetInsertionPoint, 1853). --define(wxTextCtrl_SetInsertionPointEnd, 1854). --define(wxTextCtrl_SetMaxLength, 1856). --define(wxTextCtrl_SetSelection, 1857). --define(wxTextCtrl_SetStyle, 1858). --define(wxTextCtrl_SetValue, 1859). --define(wxTextCtrl_ShowPosition, 1860). --define(wxTextCtrl_Undo, 1861). --define(wxTextCtrl_WriteText, 1862). --define(wxTextCtrl_XYToPosition, 1863). --define(wxNotebook_new_0, 1866). --define(wxNotebook_new_3, 1867). --define(wxNotebook_destruct, 1868). --define(wxNotebook_AddPage, 1869). --define(wxNotebook_AdvanceSelection, 1870). --define(wxNotebook_AssignImageList, 1871). --define(wxNotebook_Create, 1872). --define(wxNotebook_DeleteAllPages, 1873). --define(wxNotebook_DeletePage, 1874). --define(wxNotebook_RemovePage, 1875). --define(wxNotebook_GetCurrentPage, 1876). --define(wxNotebook_GetImageList, 1877). --define(wxNotebook_GetPage, 1879). --define(wxNotebook_GetPageCount, 1880). --define(wxNotebook_GetPageImage, 1881). --define(wxNotebook_GetPageText, 1882). --define(wxNotebook_GetRowCount, 1883). --define(wxNotebook_GetSelection, 1884). --define(wxNotebook_GetThemeBackgroundColour, 1885). --define(wxNotebook_HitTest, 1887). --define(wxNotebook_InsertPage, 1889). --define(wxNotebook_SetImageList, 1890). --define(wxNotebook_SetPadding, 1891). --define(wxNotebook_SetPageSize, 1892). --define(wxNotebook_SetPageImage, 1893). --define(wxNotebook_SetPageText, 1894). --define(wxNotebook_SetSelection, 1895). --define(wxNotebook_ChangeSelection, 1896). --define(wxChoicebook_new_0, 1897). --define(wxChoicebook_new_3, 1898). --define(wxChoicebook_AddPage, 1899). --define(wxChoicebook_AdvanceSelection, 1900). --define(wxChoicebook_AssignImageList, 1901). --define(wxChoicebook_Create, 1902). --define(wxChoicebook_DeleteAllPages, 1903). --define(wxChoicebook_DeletePage, 1904). --define(wxChoicebook_RemovePage, 1905). --define(wxChoicebook_GetCurrentPage, 1906). --define(wxChoicebook_GetImageList, 1907). --define(wxChoicebook_GetPage, 1909). --define(wxChoicebook_GetPageCount, 1910). --define(wxChoicebook_GetPageImage, 1911). --define(wxChoicebook_GetPageText, 1912). --define(wxChoicebook_GetSelection, 1913). --define(wxChoicebook_HitTest, 1914). --define(wxChoicebook_InsertPage, 1915). --define(wxChoicebook_SetImageList, 1916). --define(wxChoicebook_SetPageSize, 1917). --define(wxChoicebook_SetPageImage, 1918). --define(wxChoicebook_SetPageText, 1919). --define(wxChoicebook_SetSelection, 1920). --define(wxChoicebook_ChangeSelection, 1921). --define(wxChoicebook_destroy, 1922). --define(wxToolbook_new_0, 1923). --define(wxToolbook_new_3, 1924). --define(wxToolbook_AddPage, 1925). --define(wxToolbook_AdvanceSelection, 1926). --define(wxToolbook_AssignImageList, 1927). --define(wxToolbook_Create, 1928). --define(wxToolbook_DeleteAllPages, 1929). --define(wxToolbook_DeletePage, 1930). --define(wxToolbook_RemovePage, 1931). --define(wxToolbook_GetCurrentPage, 1932). --define(wxToolbook_GetImageList, 1933). --define(wxToolbook_GetPage, 1935). --define(wxToolbook_GetPageCount, 1936). --define(wxToolbook_GetPageImage, 1937). --define(wxToolbook_GetPageText, 1938). --define(wxToolbook_GetSelection, 1939). --define(wxToolbook_HitTest, 1941). --define(wxToolbook_InsertPage, 1942). --define(wxToolbook_SetImageList, 1943). --define(wxToolbook_SetPageSize, 1944). --define(wxToolbook_SetPageImage, 1945). --define(wxToolbook_SetPageText, 1946). --define(wxToolbook_SetSelection, 1947). --define(wxToolbook_ChangeSelection, 1948). --define(wxToolbook_destroy, 1949). --define(wxListbook_new_0, 1950). --define(wxListbook_new_3, 1951). --define(wxListbook_AddPage, 1952). --define(wxListbook_AdvanceSelection, 1953). --define(wxListbook_AssignImageList, 1954). --define(wxListbook_Create, 1955). --define(wxListbook_DeleteAllPages, 1956). --define(wxListbook_DeletePage, 1957). --define(wxListbook_RemovePage, 1958). --define(wxListbook_GetCurrentPage, 1959). --define(wxListbook_GetImageList, 1960). --define(wxListbook_GetPage, 1962). --define(wxListbook_GetPageCount, 1963). --define(wxListbook_GetPageImage, 1964). --define(wxListbook_GetPageText, 1965). --define(wxListbook_GetSelection, 1966). --define(wxListbook_HitTest, 1968). --define(wxListbook_InsertPage, 1969). --define(wxListbook_SetImageList, 1970). --define(wxListbook_SetPageSize, 1971). --define(wxListbook_SetPageImage, 1972). --define(wxListbook_SetPageText, 1973). --define(wxListbook_SetSelection, 1974). --define(wxListbook_ChangeSelection, 1975). --define(wxListbook_destroy, 1976). --define(wxTreebook_new_0, 1977). --define(wxTreebook_new_3, 1978). --define(wxTreebook_AddPage, 1979). --define(wxTreebook_AdvanceSelection, 1980). --define(wxTreebook_AssignImageList, 1981). --define(wxTreebook_Create, 1982). --define(wxTreebook_DeleteAllPages, 1983). --define(wxTreebook_DeletePage, 1984). --define(wxTreebook_RemovePage, 1985). --define(wxTreebook_GetCurrentPage, 1986). --define(wxTreebook_GetImageList, 1987). --define(wxTreebook_GetPage, 1989). --define(wxTreebook_GetPageCount, 1990). --define(wxTreebook_GetPageImage, 1991). --define(wxTreebook_GetPageText, 1992). --define(wxTreebook_GetSelection, 1993). --define(wxTreebook_ExpandNode, 1994). --define(wxTreebook_IsNodeExpanded, 1995). --define(wxTreebook_HitTest, 1997). --define(wxTreebook_InsertPage, 1998). --define(wxTreebook_InsertSubPage, 1999). --define(wxTreebook_SetImageList, 2000). --define(wxTreebook_SetPageSize, 2001). --define(wxTreebook_SetPageImage, 2002). --define(wxTreebook_SetPageText, 2003). --define(wxTreebook_SetSelection, 2004). --define(wxTreebook_ChangeSelection, 2005). --define(wxTreebook_destroy, 2006). --define(wxTreeCtrl_new_2, 2009). --define(wxTreeCtrl_new_0, 2010). --define(wxTreeCtrl_destruct, 2012). --define(wxTreeCtrl_AddRoot, 2013). --define(wxTreeCtrl_AppendItem, 2014). --define(wxTreeCtrl_AssignImageList, 2015). --define(wxTreeCtrl_AssignStateImageList, 2016). --define(wxTreeCtrl_Collapse, 2017). --define(wxTreeCtrl_CollapseAndReset, 2018). --define(wxTreeCtrl_Create, 2019). --define(wxTreeCtrl_Delete, 2020). --define(wxTreeCtrl_DeleteAllItems, 2021). --define(wxTreeCtrl_DeleteChildren, 2022). --define(wxTreeCtrl_EditLabel, 2023). --define(wxTreeCtrl_EnsureVisible, 2024). --define(wxTreeCtrl_Expand, 2025). --define(wxTreeCtrl_GetBoundingRect, 2026). --define(wxTreeCtrl_GetChildrenCount, 2028). --define(wxTreeCtrl_GetCount, 2029). --define(wxTreeCtrl_GetEditControl, 2030). --define(wxTreeCtrl_GetFirstChild, 2031). --define(wxTreeCtrl_GetNextChild, 2032). --define(wxTreeCtrl_GetFirstVisibleItem, 2033). --define(wxTreeCtrl_GetImageList, 2034). --define(wxTreeCtrl_GetIndent, 2035). --define(wxTreeCtrl_GetItemBackgroundColour, 2036). --define(wxTreeCtrl_GetItemData, 2037). --define(wxTreeCtrl_GetItemFont, 2038). --define(wxTreeCtrl_GetItemImage_1, 2039). --define(wxTreeCtrl_GetItemImage_2, 2040). --define(wxTreeCtrl_GetItemText, 2041). --define(wxTreeCtrl_GetItemTextColour, 2042). --define(wxTreeCtrl_GetLastChild, 2043). --define(wxTreeCtrl_GetNextSibling, 2044). --define(wxTreeCtrl_GetNextVisible, 2045). --define(wxTreeCtrl_GetItemParent, 2046). --define(wxTreeCtrl_GetPrevSibling, 2047). --define(wxTreeCtrl_GetPrevVisible, 2048). --define(wxTreeCtrl_GetRootItem, 2049). --define(wxTreeCtrl_GetSelection, 2050). --define(wxTreeCtrl_GetSelections, 2051). --define(wxTreeCtrl_GetStateImageList, 2052). --define(wxTreeCtrl_HitTest, 2053). --define(wxTreeCtrl_InsertItem, 2055). --define(wxTreeCtrl_IsBold, 2056). --define(wxTreeCtrl_IsExpanded, 2057). --define(wxTreeCtrl_IsSelected, 2058). --define(wxTreeCtrl_IsVisible, 2059). --define(wxTreeCtrl_ItemHasChildren, 2060). --define(wxTreeCtrl_IsTreeItemIdOk, 2061). --define(wxTreeCtrl_PrependItem, 2062). --define(wxTreeCtrl_ScrollTo, 2063). --define(wxTreeCtrl_SelectItem_1, 2064). --define(wxTreeCtrl_SelectItem_2, 2065). --define(wxTreeCtrl_SetIndent, 2066). --define(wxTreeCtrl_SetImageList, 2067). --define(wxTreeCtrl_SetItemBackgroundColour, 2068). --define(wxTreeCtrl_SetItemBold, 2069). --define(wxTreeCtrl_SetItemData, 2070). --define(wxTreeCtrl_SetItemDropHighlight, 2071). --define(wxTreeCtrl_SetItemFont, 2072). --define(wxTreeCtrl_SetItemHasChildren, 2073). --define(wxTreeCtrl_SetItemImage_2, 2074). --define(wxTreeCtrl_SetItemImage_3, 2075). --define(wxTreeCtrl_SetItemText, 2076). --define(wxTreeCtrl_SetItemTextColour, 2077). --define(wxTreeCtrl_SetStateImageList, 2078). --define(wxTreeCtrl_SetWindowStyle, 2079). --define(wxTreeCtrl_SortChildren, 2080). --define(wxTreeCtrl_Toggle, 2081). --define(wxTreeCtrl_ToggleItemSelection, 2082). --define(wxTreeCtrl_Unselect, 2083). --define(wxTreeCtrl_UnselectAll, 2084). --define(wxTreeCtrl_UnselectItem, 2085). --define(wxScrollBar_new_0, 2086). --define(wxScrollBar_new_3, 2087). --define(wxScrollBar_destruct, 2088). --define(wxScrollBar_Create, 2089). --define(wxScrollBar_GetRange, 2090). --define(wxScrollBar_GetPageSize, 2091). --define(wxScrollBar_GetThumbPosition, 2092). --define(wxScrollBar_GetThumbSize, 2093). --define(wxScrollBar_SetThumbPosition, 2094). --define(wxScrollBar_SetScrollbar, 2095). --define(wxSpinButton_new_2, 2097). --define(wxSpinButton_new_0, 2098). --define(wxSpinButton_Create, 2099). --define(wxSpinButton_GetMax, 2100). --define(wxSpinButton_GetMin, 2101). --define(wxSpinButton_GetValue, 2102). --define(wxSpinButton_SetRange, 2103). --define(wxSpinButton_SetValue, 2104). --define(wxSpinButton_destroy, 2105). --define(wxSpinCtrl_new_0, 2106). --define(wxSpinCtrl_new_2, 2107). --define(wxSpinCtrl_Create, 2109). --define(wxSpinCtrl_SetValue_1_1, 2112). --define(wxSpinCtrl_SetValue_1_0, 2113). --define(wxSpinCtrl_GetValue, 2115). --define(wxSpinCtrl_SetRange, 2117). --define(wxSpinCtrl_SetSelection, 2118). --define(wxSpinCtrl_GetMin, 2120). --define(wxSpinCtrl_GetMax, 2122). --define(wxSpinCtrl_destroy, 2123). --define(wxStaticText_new_0, 2124). --define(wxStaticText_new_4, 2125). --define(wxStaticText_Create, 2126). --define(wxStaticText_GetLabel, 2127). --define(wxStaticText_SetLabel, 2128). --define(wxStaticText_Wrap, 2129). --define(wxStaticText_destroy, 2130). --define(wxStaticBitmap_new_0, 2131). --define(wxStaticBitmap_new_4, 2132). --define(wxStaticBitmap_Create, 2133). --define(wxStaticBitmap_GetBitmap, 2134). --define(wxStaticBitmap_SetBitmap, 2135). --define(wxStaticBitmap_destroy, 2136). --define(wxRadioBox_new, 2137). --define(wxRadioBox_destruct, 2139). --define(wxRadioBox_Create, 2140). --define(wxRadioBox_Enable_2, 2141). --define(wxRadioBox_Enable_1, 2142). --define(wxRadioBox_GetSelection, 2143). --define(wxRadioBox_GetString, 2144). --define(wxRadioBox_SetSelection, 2145). --define(wxRadioBox_Show_2, 2146). --define(wxRadioBox_Show_1, 2147). --define(wxRadioBox_GetColumnCount, 2148). --define(wxRadioBox_GetItemHelpText, 2149). --define(wxRadioBox_GetItemToolTip, 2150). --define(wxRadioBox_GetItemFromPoint, 2152). --define(wxRadioBox_GetRowCount, 2153). --define(wxRadioBox_IsItemEnabled, 2154). --define(wxRadioBox_IsItemShown, 2155). --define(wxRadioBox_SetItemHelpText, 2156). --define(wxRadioBox_SetItemToolTip, 2157). --define(wxRadioButton_new_0, 2158). --define(wxRadioButton_new_4, 2159). --define(wxRadioButton_Create, 2160). --define(wxRadioButton_GetValue, 2161). --define(wxRadioButton_SetValue, 2162). --define(wxRadioButton_destroy, 2163). --define(wxSlider_new_6, 2165). --define(wxSlider_new_0, 2166). --define(wxSlider_Create, 2167). --define(wxSlider_GetLineSize, 2168). --define(wxSlider_GetMax, 2169). --define(wxSlider_GetMin, 2170). --define(wxSlider_GetPageSize, 2171). --define(wxSlider_GetThumbLength, 2172). --define(wxSlider_GetValue, 2173). --define(wxSlider_SetLineSize, 2174). --define(wxSlider_SetPageSize, 2175). --define(wxSlider_SetRange, 2176). --define(wxSlider_SetThumbLength, 2177). --define(wxSlider_SetValue, 2178). --define(wxSlider_destroy, 2179). --define(wxDialog_new_4, 2181). --define(wxDialog_new_0, 2182). --define(wxDialog_destruct, 2184). --define(wxDialog_Create, 2185). --define(wxDialog_CreateButtonSizer, 2186). --define(wxDialog_CreateStdDialogButtonSizer, 2187). --define(wxDialog_EndModal, 2188). --define(wxDialog_GetAffirmativeId, 2189). --define(wxDialog_GetReturnCode, 2190). --define(wxDialog_IsModal, 2191). --define(wxDialog_SetAffirmativeId, 2192). --define(wxDialog_SetReturnCode, 2193). --define(wxDialog_Show, 2194). --define(wxDialog_ShowModal, 2195). --define(wxColourDialog_new_0, 2196). --define(wxColourDialog_new_2, 2197). --define(wxColourDialog_destruct, 2198). --define(wxColourDialog_Create, 2199). --define(wxColourDialog_GetColourData, 2200). --define(wxColourData_new_0, 2201). --define(wxColourData_new_1, 2202). --define(wxColourData_destruct, 2203). --define(wxColourData_GetChooseFull, 2204). --define(wxColourData_GetColour, 2205). --define(wxColourData_GetCustomColour, 2207). --define(wxColourData_SetChooseFull, 2208). --define(wxColourData_SetColour, 2209). --define(wxColourData_SetCustomColour, 2210). --define(wxPalette_new_0, 2211). --define(wxPalette_new_4, 2212). --define(wxPalette_destruct, 2214). --define(wxPalette_Create, 2215). --define(wxPalette_GetColoursCount, 2216). --define(wxPalette_GetPixel, 2217). --define(wxPalette_GetRGB, 2218). --define(wxPalette_IsOk, 2219). --define(wxDirDialog_new, 2223). --define(wxDirDialog_destruct, 2224). --define(wxDirDialog_GetPath, 2225). --define(wxDirDialog_GetMessage, 2226). --define(wxDirDialog_SetMessage, 2227). --define(wxDirDialog_SetPath, 2228). --define(wxFileDialog_new, 2232). --define(wxFileDialog_destruct, 2233). --define(wxFileDialog_GetDirectory, 2234). --define(wxFileDialog_GetFilename, 2235). --define(wxFileDialog_GetFilenames, 2236). --define(wxFileDialog_GetFilterIndex, 2237). --define(wxFileDialog_GetMessage, 2238). --define(wxFileDialog_GetPath, 2239). --define(wxFileDialog_GetPaths, 2240). --define(wxFileDialog_GetWildcard, 2241). --define(wxFileDialog_SetDirectory, 2242). --define(wxFileDialog_SetFilename, 2243). --define(wxFileDialog_SetFilterIndex, 2244). --define(wxFileDialog_SetMessage, 2245). --define(wxFileDialog_SetPath, 2246). --define(wxFileDialog_SetWildcard, 2247). --define(wxPickerBase_SetInternalMargin, 2248). --define(wxPickerBase_GetInternalMargin, 2249). --define(wxPickerBase_SetTextCtrlProportion, 2250). --define(wxPickerBase_SetPickerCtrlProportion, 2251). --define(wxPickerBase_GetTextCtrlProportion, 2252). --define(wxPickerBase_GetPickerCtrlProportion, 2253). --define(wxPickerBase_HasTextCtrl, 2254). --define(wxPickerBase_GetTextCtrl, 2255). --define(wxPickerBase_IsTextCtrlGrowable, 2256). --define(wxPickerBase_SetPickerCtrlGrowable, 2257). --define(wxPickerBase_SetTextCtrlGrowable, 2258). --define(wxPickerBase_IsPickerCtrlGrowable, 2259). --define(wxFilePickerCtrl_new_0, 2260). --define(wxFilePickerCtrl_new_3, 2261). --define(wxFilePickerCtrl_Create, 2262). --define(wxFilePickerCtrl_GetPath, 2263). --define(wxFilePickerCtrl_SetPath, 2264). --define(wxFilePickerCtrl_destroy, 2265). --define(wxDirPickerCtrl_new_0, 2266). --define(wxDirPickerCtrl_new_3, 2267). --define(wxDirPickerCtrl_Create, 2268). --define(wxDirPickerCtrl_GetPath, 2269). --define(wxDirPickerCtrl_SetPath, 2270). --define(wxDirPickerCtrl_destroy, 2271). --define(wxColourPickerCtrl_new_0, 2272). --define(wxColourPickerCtrl_new_3, 2273). --define(wxColourPickerCtrl_Create, 2274). --define(wxColourPickerCtrl_GetColour, 2275). --define(wxColourPickerCtrl_SetColour_1_1, 2276). --define(wxColourPickerCtrl_SetColour_1_0, 2277). --define(wxColourPickerCtrl_destroy, 2278). --define(wxDatePickerCtrl_new_0, 2279). --define(wxDatePickerCtrl_new_3, 2280). --define(wxDatePickerCtrl_GetRange, 2281). --define(wxDatePickerCtrl_GetValue, 2282). --define(wxDatePickerCtrl_SetRange, 2283). --define(wxDatePickerCtrl_SetValue, 2284). --define(wxDatePickerCtrl_destroy, 2285). --define(wxFontPickerCtrl_new_0, 2286). --define(wxFontPickerCtrl_new_3, 2287). --define(wxFontPickerCtrl_Create, 2288). --define(wxFontPickerCtrl_GetSelectedFont, 2289). --define(wxFontPickerCtrl_SetSelectedFont, 2290). --define(wxFontPickerCtrl_GetMaxPointSize, 2291). --define(wxFontPickerCtrl_SetMaxPointSize, 2292). --define(wxFontPickerCtrl_destroy, 2293). --define(wxFindReplaceDialog_new_0, 2296). --define(wxFindReplaceDialog_new_4, 2297). --define(wxFindReplaceDialog_destruct, 2298). --define(wxFindReplaceDialog_Create, 2299). --define(wxFindReplaceDialog_GetData, 2300). --define(wxFindReplaceData_new_0, 2301). --define(wxFindReplaceData_new_1, 2302). --define(wxFindReplaceData_GetFindString, 2303). --define(wxFindReplaceData_GetReplaceString, 2304). --define(wxFindReplaceData_GetFlags, 2305). --define(wxFindReplaceData_SetFlags, 2306). --define(wxFindReplaceData_SetFindString, 2307). --define(wxFindReplaceData_SetReplaceString, 2308). --define(wxFindReplaceData_destroy, 2309). --define(wxMultiChoiceDialog_new_0, 2310). --define(wxMultiChoiceDialog_new_5, 2312). --define(wxMultiChoiceDialog_GetSelections, 2313). --define(wxMultiChoiceDialog_SetSelections, 2314). --define(wxMultiChoiceDialog_destroy, 2315). --define(wxSingleChoiceDialog_new_0, 2316). --define(wxSingleChoiceDialog_new_5, 2318). --define(wxSingleChoiceDialog_GetSelection, 2319). --define(wxSingleChoiceDialog_GetStringSelection, 2320). --define(wxSingleChoiceDialog_SetSelection, 2321). --define(wxSingleChoiceDialog_destroy, 2322). --define(wxTextEntryDialog_new, 2323). --define(wxTextEntryDialog_GetValue, 2324). --define(wxTextEntryDialog_SetValue, 2325). --define(wxTextEntryDialog_destroy, 2326). --define(wxPasswordEntryDialog_new, 2327). --define(wxPasswordEntryDialog_destroy, 2328). --define(wxFontData_new_0, 2329). --define(wxFontData_new_1, 2330). --define(wxFontData_destruct, 2331). --define(wxFontData_EnableEffects, 2332). --define(wxFontData_GetAllowSymbols, 2333). --define(wxFontData_GetColour, 2334). --define(wxFontData_GetChosenFont, 2335). --define(wxFontData_GetEnableEffects, 2336). --define(wxFontData_GetInitialFont, 2337). --define(wxFontData_GetShowHelp, 2338). --define(wxFontData_SetAllowSymbols, 2339). --define(wxFontData_SetChosenFont, 2340). --define(wxFontData_SetColour, 2341). --define(wxFontData_SetInitialFont, 2342). --define(wxFontData_SetRange, 2343). --define(wxFontData_SetShowHelp, 2344). --define(wxFontDialog_new_0, 2348). --define(wxFontDialog_new_2, 2350). --define(wxFontDialog_Create, 2352). --define(wxFontDialog_GetFontData, 2353). --define(wxFontDialog_destroy, 2355). --define(wxProgressDialog_new, 2356). --define(wxProgressDialog_destruct, 2357). --define(wxProgressDialog_Resume, 2358). --define(wxProgressDialog_Update_2, 2359). --define(wxProgressDialog_Update_0, 2360). --define(wxMessageDialog_new, 2361). --define(wxMessageDialog_destruct, 2362). --define(wxPageSetupDialog_new, 2363). --define(wxPageSetupDialog_destruct, 2364). --define(wxPageSetupDialog_GetPageSetupData, 2365). --define(wxPageSetupDialog_ShowModal, 2366). --define(wxPageSetupDialogData_new_0, 2367). --define(wxPageSetupDialogData_new_1_0, 2368). --define(wxPageSetupDialogData_new_1_1, 2369). --define(wxPageSetupDialogData_destruct, 2370). --define(wxPageSetupDialogData_EnableHelp, 2371). --define(wxPageSetupDialogData_EnableMargins, 2372). --define(wxPageSetupDialogData_EnableOrientation, 2373). --define(wxPageSetupDialogData_EnablePaper, 2374). --define(wxPageSetupDialogData_EnablePrinter, 2375). --define(wxPageSetupDialogData_GetDefaultMinMargins, 2376). --define(wxPageSetupDialogData_GetEnableMargins, 2377). --define(wxPageSetupDialogData_GetEnableOrientation, 2378). --define(wxPageSetupDialogData_GetEnablePaper, 2379). --define(wxPageSetupDialogData_GetEnablePrinter, 2380). --define(wxPageSetupDialogData_GetEnableHelp, 2381). --define(wxPageSetupDialogData_GetDefaultInfo, 2382). --define(wxPageSetupDialogData_GetMarginTopLeft, 2383). --define(wxPageSetupDialogData_GetMarginBottomRight, 2384). --define(wxPageSetupDialogData_GetMinMarginTopLeft, 2385). --define(wxPageSetupDialogData_GetMinMarginBottomRight, 2386). --define(wxPageSetupDialogData_GetPaperId, 2387). --define(wxPageSetupDialogData_GetPaperSize, 2388). --define(wxPageSetupDialogData_GetPrintData, 2390). --define(wxPageSetupDialogData_IsOk, 2391). --define(wxPageSetupDialogData_SetDefaultInfo, 2392). --define(wxPageSetupDialogData_SetDefaultMinMargins, 2393). --define(wxPageSetupDialogData_SetMarginTopLeft, 2394). --define(wxPageSetupDialogData_SetMarginBottomRight, 2395). --define(wxPageSetupDialogData_SetMinMarginTopLeft, 2396). --define(wxPageSetupDialogData_SetMinMarginBottomRight, 2397). --define(wxPageSetupDialogData_SetPaperId, 2398). --define(wxPageSetupDialogData_SetPaperSize_1_1, 2399). --define(wxPageSetupDialogData_SetPaperSize_1_0, 2400). --define(wxPageSetupDialogData_SetPrintData, 2401). --define(wxPrintDialog_new_2_0, 2402). --define(wxPrintDialog_new_2_1, 2403). --define(wxPrintDialog_destruct, 2404). --define(wxPrintDialog_GetPrintDialogData, 2405). --define(wxPrintDialog_GetPrintDC, 2406). --define(wxPrintDialogData_new_0, 2407). --define(wxPrintDialogData_new_1_1, 2408). --define(wxPrintDialogData_new_1_0, 2409). --define(wxPrintDialogData_destruct, 2410). --define(wxPrintDialogData_EnableHelp, 2411). --define(wxPrintDialogData_EnablePageNumbers, 2412). --define(wxPrintDialogData_EnablePrintToFile, 2413). --define(wxPrintDialogData_EnableSelection, 2414). --define(wxPrintDialogData_GetAllPages, 2415). --define(wxPrintDialogData_GetCollate, 2416). --define(wxPrintDialogData_GetFromPage, 2417). --define(wxPrintDialogData_GetMaxPage, 2418). --define(wxPrintDialogData_GetMinPage, 2419). --define(wxPrintDialogData_GetNoCopies, 2420). --define(wxPrintDialogData_GetPrintData, 2421). --define(wxPrintDialogData_GetPrintToFile, 2422). --define(wxPrintDialogData_GetSelection, 2423). --define(wxPrintDialogData_GetToPage, 2424). --define(wxPrintDialogData_IsOk, 2425). --define(wxPrintDialogData_SetCollate, 2426). --define(wxPrintDialogData_SetFromPage, 2427). --define(wxPrintDialogData_SetMaxPage, 2428). --define(wxPrintDialogData_SetMinPage, 2429). --define(wxPrintDialogData_SetNoCopies, 2430). --define(wxPrintDialogData_SetPrintData, 2431). --define(wxPrintDialogData_SetPrintToFile, 2432). --define(wxPrintDialogData_SetSelection, 2433). --define(wxPrintDialogData_SetToPage, 2434). --define(wxPrintData_new_0, 2435). --define(wxPrintData_new_1, 2436). --define(wxPrintData_destruct, 2437). --define(wxPrintData_GetCollate, 2438). --define(wxPrintData_GetBin, 2439). --define(wxPrintData_GetColour, 2440). --define(wxPrintData_GetDuplex, 2441). --define(wxPrintData_GetNoCopies, 2442). --define(wxPrintData_GetOrientation, 2443). --define(wxPrintData_GetPaperId, 2444). --define(wxPrintData_GetPrinterName, 2445). --define(wxPrintData_GetQuality, 2446). --define(wxPrintData_IsOk, 2447). --define(wxPrintData_SetBin, 2448). --define(wxPrintData_SetCollate, 2449). --define(wxPrintData_SetColour, 2450). --define(wxPrintData_SetDuplex, 2451). --define(wxPrintData_SetNoCopies, 2452). --define(wxPrintData_SetOrientation, 2453). --define(wxPrintData_SetPaperId, 2454). --define(wxPrintData_SetPrinterName, 2455). --define(wxPrintData_SetQuality, 2456). --define(wxPrintPreview_new_2, 2459). --define(wxPrintPreview_new_3, 2460). --define(wxPrintPreview_destruct, 2462). --define(wxPrintPreview_GetCanvas, 2463). --define(wxPrintPreview_GetCurrentPage, 2464). --define(wxPrintPreview_GetFrame, 2465). --define(wxPrintPreview_GetMaxPage, 2466). --define(wxPrintPreview_GetMinPage, 2467). --define(wxPrintPreview_GetPrintout, 2468). --define(wxPrintPreview_GetPrintoutForPrinting, 2469). --define(wxPrintPreview_IsOk, 2470). --define(wxPrintPreview_PaintPage, 2471). --define(wxPrintPreview_Print, 2472). --define(wxPrintPreview_RenderPage, 2473). --define(wxPrintPreview_SetCanvas, 2474). --define(wxPrintPreview_SetCurrentPage, 2475). --define(wxPrintPreview_SetFrame, 2476). --define(wxPrintPreview_SetPrintout, 2477). --define(wxPrintPreview_SetZoom, 2478). --define(wxPreviewFrame_new, 2479). --define(wxPreviewFrame_destruct, 2480). --define(wxPreviewFrame_CreateControlBar, 2481). --define(wxPreviewFrame_CreateCanvas, 2482). --define(wxPreviewFrame_Initialize, 2483). --define(wxPreviewFrame_OnCloseWindow, 2484). --define(wxPreviewControlBar_new, 2485). --define(wxPreviewControlBar_destruct, 2486). --define(wxPreviewControlBar_CreateButtons, 2487). --define(wxPreviewControlBar_GetPrintPreview, 2488). --define(wxPreviewControlBar_GetZoomControl, 2489). --define(wxPreviewControlBar_SetZoomControl, 2490). --define(wxPrinter_new, 2492). --define(wxPrinter_CreateAbortWindow, 2493). --define(wxPrinter_GetAbort, 2494). --define(wxPrinter_GetLastError, 2495). --define(wxPrinter_GetPrintDialogData, 2496). --define(wxPrinter_Print, 2497). --define(wxPrinter_PrintDialog, 2498). --define(wxPrinter_ReportError, 2499). --define(wxPrinter_Setup, 2500). --define(wxPrinter_destroy, 2501). --define(wxXmlResource_new_1, 2502). --define(wxXmlResource_new_2, 2503). --define(wxXmlResource_destruct, 2504). --define(wxXmlResource_AttachUnknownControl, 2505). --define(wxXmlResource_ClearHandlers, 2506). --define(wxXmlResource_CompareVersion, 2507). --define(wxXmlResource_Get, 2508). --define(wxXmlResource_GetFlags, 2509). --define(wxXmlResource_GetVersion, 2510). --define(wxXmlResource_GetXRCID, 2511). --define(wxXmlResource_InitAllHandlers, 2512). --define(wxXmlResource_Load, 2513). --define(wxXmlResource_LoadBitmap, 2514). --define(wxXmlResource_LoadDialog_2, 2515). --define(wxXmlResource_LoadDialog_3, 2516). --define(wxXmlResource_LoadFrame_2, 2517). --define(wxXmlResource_LoadFrame_3, 2518). --define(wxXmlResource_LoadIcon, 2519). --define(wxXmlResource_LoadMenu, 2520). --define(wxXmlResource_LoadMenuBar_2, 2521). --define(wxXmlResource_LoadMenuBar_1, 2522). --define(wxXmlResource_LoadPanel_2, 2523). --define(wxXmlResource_LoadPanel_3, 2524). --define(wxXmlResource_LoadToolBar, 2525). --define(wxXmlResource_Set, 2526). --define(wxXmlResource_SetFlags, 2527). --define(wxXmlResource_Unload, 2528). --define(wxXmlResource_xrcctrl, 2529). --define(wxHtmlEasyPrinting_new, 2530). --define(wxHtmlEasyPrinting_destruct, 2531). --define(wxHtmlEasyPrinting_GetPrintData, 2532). --define(wxHtmlEasyPrinting_GetPageSetupData, 2533). --define(wxHtmlEasyPrinting_PreviewFile, 2534). --define(wxHtmlEasyPrinting_PreviewText, 2535). --define(wxHtmlEasyPrinting_PrintFile, 2536). --define(wxHtmlEasyPrinting_PrintText, 2537). --define(wxHtmlEasyPrinting_PageSetup, 2538). --define(wxHtmlEasyPrinting_SetFonts, 2539). --define(wxHtmlEasyPrinting_SetHeader, 2540). --define(wxHtmlEasyPrinting_SetFooter, 2541). --define(wxGLCanvas_new_2, 2543). --define(wxGLCanvas_new_3_1, 2544). --define(wxGLCanvas_new_3_0, 2545). --define(wxGLCanvas_GetContext, 2546). --define(wxGLCanvas_SetCurrent, 2548). --define(wxGLCanvas_SwapBuffers, 2549). --define(wxGLCanvas_destroy, 2550). --define(wxAuiManager_new, 2551). --define(wxAuiManager_destruct, 2552). --define(wxAuiManager_AddPane_2_1, 2553). --define(wxAuiManager_AddPane_3, 2554). --define(wxAuiManager_AddPane_2_0, 2555). --define(wxAuiManager_DetachPane, 2556). --define(wxAuiManager_GetAllPanes, 2557). --define(wxAuiManager_GetArtProvider, 2558). --define(wxAuiManager_GetDockSizeConstraint, 2559). --define(wxAuiManager_GetFlags, 2560). --define(wxAuiManager_GetManagedWindow, 2561). --define(wxAuiManager_GetManager, 2562). --define(wxAuiManager_GetPane_1_1, 2563). --define(wxAuiManager_GetPane_1_0, 2564). --define(wxAuiManager_HideHint, 2565). --define(wxAuiManager_InsertPane, 2566). --define(wxAuiManager_LoadPaneInfo, 2567). --define(wxAuiManager_LoadPerspective, 2568). --define(wxAuiManager_SavePaneInfo, 2569). --define(wxAuiManager_SavePerspective, 2570). --define(wxAuiManager_SetArtProvider, 2571). --define(wxAuiManager_SetDockSizeConstraint, 2572). --define(wxAuiManager_SetFlags, 2573). --define(wxAuiManager_SetManagedWindow, 2574). --define(wxAuiManager_ShowHint, 2575). --define(wxAuiManager_UnInit, 2576). --define(wxAuiManager_Update, 2577). --define(wxAuiPaneInfo_new_0, 2578). --define(wxAuiPaneInfo_new_1, 2579). --define(wxAuiPaneInfo_destruct, 2580). --define(wxAuiPaneInfo_BestSize_1, 2581). --define(wxAuiPaneInfo_BestSize_2, 2582). --define(wxAuiPaneInfo_Bottom, 2583). --define(wxAuiPaneInfo_BottomDockable, 2584). --define(wxAuiPaneInfo_Caption, 2585). --define(wxAuiPaneInfo_CaptionVisible, 2586). --define(wxAuiPaneInfo_Centre, 2587). --define(wxAuiPaneInfo_CentrePane, 2588). --define(wxAuiPaneInfo_CloseButton, 2589). --define(wxAuiPaneInfo_DefaultPane, 2590). --define(wxAuiPaneInfo_DestroyOnClose, 2591). --define(wxAuiPaneInfo_Direction, 2592). --define(wxAuiPaneInfo_Dock, 2593). --define(wxAuiPaneInfo_Dockable, 2594). --define(wxAuiPaneInfo_Fixed, 2595). --define(wxAuiPaneInfo_Float, 2596). --define(wxAuiPaneInfo_Floatable, 2597). --define(wxAuiPaneInfo_FloatingPosition_1, 2598). --define(wxAuiPaneInfo_FloatingPosition_2, 2599). --define(wxAuiPaneInfo_FloatingSize_1, 2600). --define(wxAuiPaneInfo_FloatingSize_2, 2601). --define(wxAuiPaneInfo_Gripper, 2602). --define(wxAuiPaneInfo_GripperTop, 2603). --define(wxAuiPaneInfo_HasBorder, 2604). --define(wxAuiPaneInfo_HasCaption, 2605). --define(wxAuiPaneInfo_HasCloseButton, 2606). --define(wxAuiPaneInfo_HasFlag, 2607). --define(wxAuiPaneInfo_HasGripper, 2608). --define(wxAuiPaneInfo_HasGripperTop, 2609). --define(wxAuiPaneInfo_HasMaximizeButton, 2610). --define(wxAuiPaneInfo_HasMinimizeButton, 2611). --define(wxAuiPaneInfo_HasPinButton, 2612). --define(wxAuiPaneInfo_Hide, 2613). --define(wxAuiPaneInfo_IsBottomDockable, 2614). --define(wxAuiPaneInfo_IsDocked, 2615). --define(wxAuiPaneInfo_IsFixed, 2616). --define(wxAuiPaneInfo_IsFloatable, 2617). --define(wxAuiPaneInfo_IsFloating, 2618). --define(wxAuiPaneInfo_IsLeftDockable, 2619). --define(wxAuiPaneInfo_IsMovable, 2620). --define(wxAuiPaneInfo_IsOk, 2621). --define(wxAuiPaneInfo_IsResizable, 2622). --define(wxAuiPaneInfo_IsRightDockable, 2623). --define(wxAuiPaneInfo_IsShown, 2624). --define(wxAuiPaneInfo_IsToolbar, 2625). --define(wxAuiPaneInfo_IsTopDockable, 2626). --define(wxAuiPaneInfo_Layer, 2627). --define(wxAuiPaneInfo_Left, 2628). --define(wxAuiPaneInfo_LeftDockable, 2629). --define(wxAuiPaneInfo_MaxSize_1, 2630). --define(wxAuiPaneInfo_MaxSize_2, 2631). --define(wxAuiPaneInfo_MaximizeButton, 2632). --define(wxAuiPaneInfo_MinSize_1, 2633). --define(wxAuiPaneInfo_MinSize_2, 2634). --define(wxAuiPaneInfo_MinimizeButton, 2635). --define(wxAuiPaneInfo_Movable, 2636). --define(wxAuiPaneInfo_Name, 2637). --define(wxAuiPaneInfo_PaneBorder, 2638). --define(wxAuiPaneInfo_PinButton, 2639). --define(wxAuiPaneInfo_Position, 2640). --define(wxAuiPaneInfo_Resizable, 2641). --define(wxAuiPaneInfo_Right, 2642). --define(wxAuiPaneInfo_RightDockable, 2643). --define(wxAuiPaneInfo_Row, 2644). --define(wxAuiPaneInfo_SafeSet, 2645). --define(wxAuiPaneInfo_SetFlag, 2646). --define(wxAuiPaneInfo_Show, 2647). --define(wxAuiPaneInfo_ToolbarPane, 2648). --define(wxAuiPaneInfo_Top, 2649). --define(wxAuiPaneInfo_TopDockable, 2650). --define(wxAuiPaneInfo_Window, 2651). --define(wxAuiNotebook_new_0, 2652). --define(wxAuiNotebook_new_2, 2653). --define(wxAuiNotebook_AddPage, 2654). --define(wxAuiNotebook_Create, 2655). --define(wxAuiNotebook_DeletePage, 2656). --define(wxAuiNotebook_GetArtProvider, 2657). --define(wxAuiNotebook_GetPage, 2658). --define(wxAuiNotebook_GetPageBitmap, 2659). --define(wxAuiNotebook_GetPageCount, 2660). --define(wxAuiNotebook_GetPageIndex, 2661). --define(wxAuiNotebook_GetPageText, 2662). --define(wxAuiNotebook_GetSelection, 2663). --define(wxAuiNotebook_InsertPage, 2664). --define(wxAuiNotebook_RemovePage, 2665). --define(wxAuiNotebook_SetArtProvider, 2666). --define(wxAuiNotebook_SetFont, 2667). --define(wxAuiNotebook_SetPageBitmap, 2668). --define(wxAuiNotebook_SetPageText, 2669). --define(wxAuiNotebook_SetSelection, 2670). --define(wxAuiNotebook_SetTabCtrlHeight, 2671). --define(wxAuiNotebook_SetUniformBitmapSize, 2672). --define(wxAuiNotebook_destroy, 2673). --define(wxMDIParentFrame_new_0, 2674). --define(wxMDIParentFrame_new_4, 2675). --define(wxMDIParentFrame_destruct, 2676). --define(wxMDIParentFrame_ActivateNext, 2677). --define(wxMDIParentFrame_ActivatePrevious, 2678). --define(wxMDIParentFrame_ArrangeIcons, 2679). --define(wxMDIParentFrame_Cascade, 2680). --define(wxMDIParentFrame_Create, 2681). --define(wxMDIParentFrame_GetActiveChild, 2682). --define(wxMDIParentFrame_GetClientWindow, 2683). --define(wxMDIParentFrame_Tile, 2684). --define(wxMDIChildFrame_new_0, 2685). --define(wxMDIChildFrame_new_4, 2686). --define(wxMDIChildFrame_destruct, 2687). --define(wxMDIChildFrame_Activate, 2688). --define(wxMDIChildFrame_Create, 2689). --define(wxMDIChildFrame_Maximize, 2690). --define(wxMDIChildFrame_Restore, 2691). --define(wxMDIClientWindow_new_0, 2692). --define(wxMDIClientWindow_new_2, 2693). --define(wxMDIClientWindow_destruct, 2694). --define(wxMDIClientWindow_CreateClient, 2695). --define(wxLayoutAlgorithm_new, 2696). --define(wxLayoutAlgorithm_LayoutFrame, 2697). --define(wxLayoutAlgorithm_LayoutMDIFrame, 2698). --define(wxLayoutAlgorithm_LayoutWindow, 2699). --define(wxLayoutAlgorithm_destroy, 2700). --define(wxEvent_GetId, 2701). --define(wxEvent_GetSkipped, 2702). --define(wxEvent_GetTimestamp, 2703). --define(wxEvent_IsCommandEvent, 2704). --define(wxEvent_ResumePropagation, 2705). --define(wxEvent_ShouldPropagate, 2706). --define(wxEvent_Skip, 2707). --define(wxEvent_StopPropagation, 2708). --define(wxCommandEvent_getClientData, 2709). --define(wxCommandEvent_GetExtraLong, 2710). --define(wxCommandEvent_GetInt, 2711). --define(wxCommandEvent_GetSelection, 2712). --define(wxCommandEvent_GetString, 2713). --define(wxCommandEvent_IsChecked, 2714). --define(wxCommandEvent_IsSelection, 2715). --define(wxCommandEvent_SetInt, 2716). --define(wxCommandEvent_SetString, 2717). --define(wxScrollEvent_GetOrientation, 2718). --define(wxScrollEvent_GetPosition, 2719). --define(wxScrollWinEvent_GetOrientation, 2720). --define(wxScrollWinEvent_GetPosition, 2721). --define(wxMouseEvent_AltDown, 2722). --define(wxMouseEvent_Button, 2723). --define(wxMouseEvent_ButtonDClick, 2724). --define(wxMouseEvent_ButtonDown, 2725). --define(wxMouseEvent_ButtonUp, 2726). --define(wxMouseEvent_CmdDown, 2727). --define(wxMouseEvent_ControlDown, 2728). --define(wxMouseEvent_Dragging, 2729). --define(wxMouseEvent_Entering, 2730). --define(wxMouseEvent_GetButton, 2731). --define(wxMouseEvent_GetPosition, 2734). --define(wxMouseEvent_GetLogicalPosition, 2735). --define(wxMouseEvent_GetLinesPerAction, 2736). --define(wxMouseEvent_GetWheelRotation, 2737). --define(wxMouseEvent_GetWheelDelta, 2738). --define(wxMouseEvent_GetX, 2739). --define(wxMouseEvent_GetY, 2740). --define(wxMouseEvent_IsButton, 2741). --define(wxMouseEvent_IsPageScroll, 2742). --define(wxMouseEvent_Leaving, 2743). --define(wxMouseEvent_LeftDClick, 2744). --define(wxMouseEvent_LeftDown, 2745). --define(wxMouseEvent_LeftIsDown, 2746). --define(wxMouseEvent_LeftUp, 2747). --define(wxMouseEvent_MetaDown, 2748). --define(wxMouseEvent_MiddleDClick, 2749). --define(wxMouseEvent_MiddleDown, 2750). --define(wxMouseEvent_MiddleIsDown, 2751). --define(wxMouseEvent_MiddleUp, 2752). --define(wxMouseEvent_Moving, 2753). --define(wxMouseEvent_RightDClick, 2754). --define(wxMouseEvent_RightDown, 2755). --define(wxMouseEvent_RightIsDown, 2756). --define(wxMouseEvent_RightUp, 2757). --define(wxMouseEvent_ShiftDown, 2758). --define(wxSetCursorEvent_GetCursor, 2759). --define(wxSetCursorEvent_GetX, 2760). --define(wxSetCursorEvent_GetY, 2761). --define(wxSetCursorEvent_HasCursor, 2762). --define(wxSetCursorEvent_SetCursor, 2763). --define(wxKeyEvent_AltDown, 2764). --define(wxKeyEvent_CmdDown, 2765). --define(wxKeyEvent_ControlDown, 2766). --define(wxKeyEvent_GetKeyCode, 2767). --define(wxKeyEvent_GetModifiers, 2768). --define(wxKeyEvent_GetPosition, 2771). --define(wxKeyEvent_GetRawKeyCode, 2772). --define(wxKeyEvent_GetRawKeyFlags, 2773). --define(wxKeyEvent_GetUnicodeKey, 2774). --define(wxKeyEvent_GetX, 2775). --define(wxKeyEvent_GetY, 2776). --define(wxKeyEvent_HasModifiers, 2777). --define(wxKeyEvent_MetaDown, 2778). --define(wxKeyEvent_ShiftDown, 2779). --define(wxSizeEvent_GetSize, 2780). --define(wxMoveEvent_GetPosition, 2781). --define(wxEraseEvent_GetDC, 2782). --define(wxFocusEvent_GetWindow, 2783). --define(wxChildFocusEvent_GetWindow, 2784). --define(wxMenuEvent_GetMenu, 2785). --define(wxMenuEvent_GetMenuId, 2786). --define(wxMenuEvent_IsPopup, 2787). --define(wxCloseEvent_CanVeto, 2788). --define(wxCloseEvent_GetLoggingOff, 2789). --define(wxCloseEvent_SetCanVeto, 2790). --define(wxCloseEvent_SetLoggingOff, 2791). --define(wxCloseEvent_Veto, 2792). --define(wxShowEvent_SetShow, 2793). --define(wxShowEvent_GetShow, 2794). --define(wxIconizeEvent_Iconized, 2795). --define(wxJoystickEvent_ButtonDown, 2796). --define(wxJoystickEvent_ButtonIsDown, 2797). --define(wxJoystickEvent_ButtonUp, 2798). --define(wxJoystickEvent_GetButtonChange, 2799). --define(wxJoystickEvent_GetButtonState, 2800). --define(wxJoystickEvent_GetJoystick, 2801). --define(wxJoystickEvent_GetPosition, 2802). --define(wxJoystickEvent_GetZPosition, 2803). --define(wxJoystickEvent_IsButton, 2804). --define(wxJoystickEvent_IsMove, 2805). --define(wxJoystickEvent_IsZMove, 2806). --define(wxUpdateUIEvent_CanUpdate, 2807). --define(wxUpdateUIEvent_Check, 2808). --define(wxUpdateUIEvent_Enable, 2809). --define(wxUpdateUIEvent_Show, 2810). --define(wxUpdateUIEvent_GetChecked, 2811). --define(wxUpdateUIEvent_GetEnabled, 2812). --define(wxUpdateUIEvent_GetShown, 2813). --define(wxUpdateUIEvent_GetSetChecked, 2814). --define(wxUpdateUIEvent_GetSetEnabled, 2815). --define(wxUpdateUIEvent_GetSetShown, 2816). --define(wxUpdateUIEvent_GetSetText, 2817). --define(wxUpdateUIEvent_GetText, 2818). --define(wxUpdateUIEvent_GetMode, 2819). --define(wxUpdateUIEvent_GetUpdateInterval, 2820). --define(wxUpdateUIEvent_ResetUpdateTime, 2821). --define(wxUpdateUIEvent_SetMode, 2822). --define(wxUpdateUIEvent_SetText, 2823). --define(wxUpdateUIEvent_SetUpdateInterval, 2824). --define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2825). --define(wxPaletteChangedEvent_SetChangedWindow, 2826). --define(wxPaletteChangedEvent_GetChangedWindow, 2827). --define(wxQueryNewPaletteEvent_SetPaletteRealized, 2828). --define(wxQueryNewPaletteEvent_GetPaletteRealized, 2829). --define(wxNavigationKeyEvent_GetDirection, 2830). --define(wxNavigationKeyEvent_SetDirection, 2831). --define(wxNavigationKeyEvent_IsWindowChange, 2832). --define(wxNavigationKeyEvent_SetWindowChange, 2833). --define(wxNavigationKeyEvent_IsFromTab, 2834). --define(wxNavigationKeyEvent_SetFromTab, 2835). --define(wxNavigationKeyEvent_GetCurrentFocus, 2836). --define(wxNavigationKeyEvent_SetCurrentFocus, 2837). --define(wxHelpEvent_GetOrigin, 2838). --define(wxHelpEvent_GetPosition, 2839). --define(wxHelpEvent_SetOrigin, 2840). --define(wxHelpEvent_SetPosition, 2841). --define(wxContextMenuEvent_GetPosition, 2842). --define(wxContextMenuEvent_SetPosition, 2843). --define(wxIdleEvent_CanSend, 2844). --define(wxIdleEvent_GetMode, 2845). --define(wxIdleEvent_RequestMore, 2846). --define(wxIdleEvent_MoreRequested, 2847). --define(wxIdleEvent_SetMode, 2848). --define(wxGridEvent_AltDown, 2849). --define(wxGridEvent_ControlDown, 2850). --define(wxGridEvent_GetCol, 2851). --define(wxGridEvent_GetPosition, 2852). --define(wxGridEvent_GetRow, 2853). --define(wxGridEvent_MetaDown, 2854). --define(wxGridEvent_Selecting, 2855). --define(wxGridEvent_ShiftDown, 2856). --define(wxNotifyEvent_Allow, 2857). --define(wxNotifyEvent_IsAllowed, 2858). --define(wxNotifyEvent_Veto, 2859). --define(wxSashEvent_GetEdge, 2860). --define(wxSashEvent_GetDragRect, 2861). --define(wxSashEvent_GetDragStatus, 2862). --define(wxListEvent_GetCacheFrom, 2863). --define(wxListEvent_GetCacheTo, 2864). --define(wxListEvent_GetKeyCode, 2865). --define(wxListEvent_GetIndex, 2866). --define(wxListEvent_GetColumn, 2867). --define(wxListEvent_GetPoint, 2868). --define(wxListEvent_GetLabel, 2869). --define(wxListEvent_GetText, 2870). --define(wxListEvent_GetImage, 2871). --define(wxListEvent_GetData, 2872). --define(wxListEvent_GetMask, 2873). --define(wxListEvent_GetItem, 2874). --define(wxListEvent_IsEditCancelled, 2875). --define(wxDateEvent_GetDate, 2876). --define(wxCalendarEvent_GetWeekDay, 2877). --define(wxFileDirPickerEvent_GetPath, 2878). --define(wxColourPickerEvent_GetColour, 2879). --define(wxFontPickerEvent_GetFont, 2880). --define(wxStyledTextEvent_GetPosition, 2881). --define(wxStyledTextEvent_GetKey, 2882). --define(wxStyledTextEvent_GetModifiers, 2883). --define(wxStyledTextEvent_GetModificationType, 2884). --define(wxStyledTextEvent_GetText, 2885). --define(wxStyledTextEvent_GetLength, 2886). --define(wxStyledTextEvent_GetLinesAdded, 2887). --define(wxStyledTextEvent_GetLine, 2888). --define(wxStyledTextEvent_GetFoldLevelNow, 2889). --define(wxStyledTextEvent_GetFoldLevelPrev, 2890). --define(wxStyledTextEvent_GetMargin, 2891). --define(wxStyledTextEvent_GetMessage, 2892). --define(wxStyledTextEvent_GetWParam, 2893). --define(wxStyledTextEvent_GetLParam, 2894). --define(wxStyledTextEvent_GetListType, 2895). --define(wxStyledTextEvent_GetX, 2896). --define(wxStyledTextEvent_GetY, 2897). --define(wxStyledTextEvent_GetDragText, 2898). --define(wxStyledTextEvent_GetDragAllowMove, 2899). --define(wxStyledTextEvent_GetDragResult, 2900). --define(wxStyledTextEvent_GetShift, 2901). --define(wxStyledTextEvent_GetControl, 2902). --define(wxStyledTextEvent_GetAlt, 2903). --define(utils_wxGetKeyState, 2904). --define(utils_wxGetMousePosition, 2905). --define(utils_wxGetMouseState, 2906). --define(utils_wxSetDetectableAutoRepeat, 2907). --define(utils_wxBell, 2908). --define(utils_wxFindMenuItemId, 2909). --define(utils_wxGenericFindWindowAtPoint, 2910). --define(utils_wxFindWindowAtPoint, 2911). --define(utils_wxBeginBusyCursor, 2912). --define(utils_wxEndBusyCursor, 2913). --define(utils_wxIsBusy, 2914). --define(utils_wxShutdown, 2915). --define(utils_wxShell, 2916). --define(utils_wxLaunchDefaultBrowser, 2917). --define(utils_wxGetEmailAddress, 2918). --define(utils_wxGetUserId, 2919). --define(utils_wxGetHomeDir, 2920). --define(utils_wxNewId, 2921). --define(utils_wxRegisterId, 2922). --define(utils_wxGetCurrentId, 2923). --define(utils_wxGetOsDescription, 2924). --define(utils_wxIsPlatformLittleEndian, 2925). --define(utils_wxIsPlatform64Bit, 2926). --define(gdicmn_wxDisplaySize, 2927). --define(gdicmn_wxSetCursor, 2928). --define(wxPrintout_new, 2929). --define(wxPrintout_destruct, 2930). --define(wxPrintout_GetDC, 2931). --define(wxPrintout_GetPageSizeMM, 2932). --define(wxPrintout_GetPageSizePixels, 2933). --define(wxPrintout_GetPaperRectPixels, 2934). --define(wxPrintout_GetPPIPrinter, 2935). --define(wxPrintout_GetPPIScreen, 2936). --define(wxPrintout_GetTitle, 2937). --define(wxPrintout_IsPreview, 2938). --define(wxPrintout_FitThisSizeToPaper, 2939). --define(wxPrintout_FitThisSizeToPage, 2940). --define(wxPrintout_FitThisSizeToPageMargins, 2941). --define(wxPrintout_MapScreenSizeToPaper, 2942). --define(wxPrintout_MapScreenSizeToPage, 2943). --define(wxPrintout_MapScreenSizeToPageMargins, 2944). --define(wxPrintout_MapScreenSizeToDevice, 2945). --define(wxPrintout_GetLogicalPaperRect, 2946). --define(wxPrintout_GetLogicalPageRect, 2947). --define(wxPrintout_GetLogicalPageMarginsRect, 2948). --define(wxPrintout_SetLogicalOrigin, 2949). --define(wxPrintout_OffsetLogicalOrigin, 2950). --define(wxStyledTextCtrl_new_2, 2951). --define(wxStyledTextCtrl_new_0, 2952). --define(wxStyledTextCtrl_destruct, 2953). --define(wxStyledTextCtrl_Create, 2954). --define(wxStyledTextCtrl_AddText, 2955). --define(wxStyledTextCtrl_AddStyledText, 2956). --define(wxStyledTextCtrl_InsertText, 2957). --define(wxStyledTextCtrl_ClearAll, 2958). --define(wxStyledTextCtrl_ClearDocumentStyle, 2959). --define(wxStyledTextCtrl_GetLength, 2960). --define(wxStyledTextCtrl_GetCharAt, 2961). --define(wxStyledTextCtrl_GetCurrentPos, 2962). --define(wxStyledTextCtrl_GetAnchor, 2963). --define(wxStyledTextCtrl_GetStyleAt, 2964). --define(wxStyledTextCtrl_Redo, 2965). --define(wxStyledTextCtrl_SetUndoCollection, 2966). --define(wxStyledTextCtrl_SelectAll, 2967). --define(wxStyledTextCtrl_SetSavePoint, 2968). --define(wxStyledTextCtrl_GetStyledText, 2969). --define(wxStyledTextCtrl_CanRedo, 2970). --define(wxStyledTextCtrl_MarkerLineFromHandle, 2971). --define(wxStyledTextCtrl_MarkerDeleteHandle, 2972). --define(wxStyledTextCtrl_GetUndoCollection, 2973). --define(wxStyledTextCtrl_GetViewWhiteSpace, 2974). --define(wxStyledTextCtrl_SetViewWhiteSpace, 2975). --define(wxStyledTextCtrl_PositionFromPoint, 2976). --define(wxStyledTextCtrl_PositionFromPointClose, 2977). --define(wxStyledTextCtrl_GotoLine, 2978). --define(wxStyledTextCtrl_GotoPos, 2979). --define(wxStyledTextCtrl_SetAnchor, 2980). --define(wxStyledTextCtrl_GetCurLine, 2981). --define(wxStyledTextCtrl_GetEndStyled, 2982). --define(wxStyledTextCtrl_ConvertEOLs, 2983). --define(wxStyledTextCtrl_GetEOLMode, 2984). --define(wxStyledTextCtrl_SetEOLMode, 2985). --define(wxStyledTextCtrl_StartStyling, 2986). --define(wxStyledTextCtrl_SetStyling, 2987). --define(wxStyledTextCtrl_GetBufferedDraw, 2988). --define(wxStyledTextCtrl_SetBufferedDraw, 2989). --define(wxStyledTextCtrl_SetTabWidth, 2990). --define(wxStyledTextCtrl_GetTabWidth, 2991). --define(wxStyledTextCtrl_SetCodePage, 2992). --define(wxStyledTextCtrl_MarkerDefine, 2993). --define(wxStyledTextCtrl_MarkerSetForeground, 2994). --define(wxStyledTextCtrl_MarkerSetBackground, 2995). --define(wxStyledTextCtrl_MarkerAdd, 2996). --define(wxStyledTextCtrl_MarkerDelete, 2997). --define(wxStyledTextCtrl_MarkerDeleteAll, 2998). --define(wxStyledTextCtrl_MarkerGet, 2999). --define(wxStyledTextCtrl_MarkerNext, 3000). --define(wxStyledTextCtrl_MarkerPrevious, 3001). --define(wxStyledTextCtrl_MarkerDefineBitmap, 3002). --define(wxStyledTextCtrl_MarkerAddSet, 3003). --define(wxStyledTextCtrl_MarkerSetAlpha, 3004). --define(wxStyledTextCtrl_SetMarginType, 3005). --define(wxStyledTextCtrl_GetMarginType, 3006). --define(wxStyledTextCtrl_SetMarginWidth, 3007). --define(wxStyledTextCtrl_GetMarginWidth, 3008). --define(wxStyledTextCtrl_SetMarginMask, 3009). --define(wxStyledTextCtrl_GetMarginMask, 3010). --define(wxStyledTextCtrl_SetMarginSensitive, 3011). --define(wxStyledTextCtrl_GetMarginSensitive, 3012). --define(wxStyledTextCtrl_StyleClearAll, 3013). --define(wxStyledTextCtrl_StyleSetForeground, 3014). --define(wxStyledTextCtrl_StyleSetBackground, 3015). --define(wxStyledTextCtrl_StyleSetBold, 3016). --define(wxStyledTextCtrl_StyleSetItalic, 3017). --define(wxStyledTextCtrl_StyleSetSize, 3018). --define(wxStyledTextCtrl_StyleSetFaceName, 3019). --define(wxStyledTextCtrl_StyleSetEOLFilled, 3020). --define(wxStyledTextCtrl_StyleResetDefault, 3021). --define(wxStyledTextCtrl_StyleSetUnderline, 3022). --define(wxStyledTextCtrl_StyleSetCase, 3023). --define(wxStyledTextCtrl_StyleSetHotSpot, 3024). --define(wxStyledTextCtrl_SetSelForeground, 3025). --define(wxStyledTextCtrl_SetSelBackground, 3026). --define(wxStyledTextCtrl_GetSelAlpha, 3027). --define(wxStyledTextCtrl_SetSelAlpha, 3028). --define(wxStyledTextCtrl_SetCaretForeground, 3029). --define(wxStyledTextCtrl_CmdKeyAssign, 3030). --define(wxStyledTextCtrl_CmdKeyClear, 3031). --define(wxStyledTextCtrl_CmdKeyClearAll, 3032). --define(wxStyledTextCtrl_SetStyleBytes, 3033). --define(wxStyledTextCtrl_StyleSetVisible, 3034). --define(wxStyledTextCtrl_GetCaretPeriod, 3035). --define(wxStyledTextCtrl_SetCaretPeriod, 3036). --define(wxStyledTextCtrl_SetWordChars, 3037). --define(wxStyledTextCtrl_BeginUndoAction, 3038). --define(wxStyledTextCtrl_EndUndoAction, 3039). --define(wxStyledTextCtrl_IndicatorSetStyle, 3040). --define(wxStyledTextCtrl_IndicatorGetStyle, 3041). --define(wxStyledTextCtrl_IndicatorSetForeground, 3042). --define(wxStyledTextCtrl_IndicatorGetForeground, 3043). --define(wxStyledTextCtrl_SetWhitespaceForeground, 3044). --define(wxStyledTextCtrl_SetWhitespaceBackground, 3045). --define(wxStyledTextCtrl_GetStyleBits, 3046). --define(wxStyledTextCtrl_SetLineState, 3047). --define(wxStyledTextCtrl_GetLineState, 3048). --define(wxStyledTextCtrl_GetMaxLineState, 3049). --define(wxStyledTextCtrl_GetCaretLineVisible, 3050). --define(wxStyledTextCtrl_SetCaretLineVisible, 3051). --define(wxStyledTextCtrl_GetCaretLineBackground, 3052). --define(wxStyledTextCtrl_SetCaretLineBackground, 3053). --define(wxStyledTextCtrl_AutoCompShow, 3054). --define(wxStyledTextCtrl_AutoCompCancel, 3055). --define(wxStyledTextCtrl_AutoCompActive, 3056). --define(wxStyledTextCtrl_AutoCompPosStart, 3057). --define(wxStyledTextCtrl_AutoCompComplete, 3058). --define(wxStyledTextCtrl_AutoCompStops, 3059). --define(wxStyledTextCtrl_AutoCompSetSeparator, 3060). --define(wxStyledTextCtrl_AutoCompGetSeparator, 3061). --define(wxStyledTextCtrl_AutoCompSelect, 3062). --define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3063). --define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3064). --define(wxStyledTextCtrl_AutoCompSetFillUps, 3065). --define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3066). --define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3067). --define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3068). --define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3069). --define(wxStyledTextCtrl_UserListShow, 3070). --define(wxStyledTextCtrl_AutoCompSetAutoHide, 3071). --define(wxStyledTextCtrl_AutoCompGetAutoHide, 3072). --define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3073). --define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3074). --define(wxStyledTextCtrl_RegisterImage, 3075). --define(wxStyledTextCtrl_ClearRegisteredImages, 3076). --define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3077). --define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3078). --define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3079). --define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3080). --define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3081). --define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3082). --define(wxStyledTextCtrl_SetIndent, 3083). --define(wxStyledTextCtrl_GetIndent, 3084). --define(wxStyledTextCtrl_SetUseTabs, 3085). --define(wxStyledTextCtrl_GetUseTabs, 3086). --define(wxStyledTextCtrl_SetLineIndentation, 3087). --define(wxStyledTextCtrl_GetLineIndentation, 3088). --define(wxStyledTextCtrl_GetLineIndentPosition, 3089). --define(wxStyledTextCtrl_GetColumn, 3090). --define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3091). --define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3092). --define(wxStyledTextCtrl_SetIndentationGuides, 3093). --define(wxStyledTextCtrl_GetIndentationGuides, 3094). --define(wxStyledTextCtrl_SetHighlightGuide, 3095). --define(wxStyledTextCtrl_GetHighlightGuide, 3096). --define(wxStyledTextCtrl_GetLineEndPosition, 3097). --define(wxStyledTextCtrl_GetCodePage, 3098). --define(wxStyledTextCtrl_GetCaretForeground, 3099). --define(wxStyledTextCtrl_GetReadOnly, 3100). --define(wxStyledTextCtrl_SetCurrentPos, 3101). --define(wxStyledTextCtrl_SetSelectionStart, 3102). --define(wxStyledTextCtrl_GetSelectionStart, 3103). --define(wxStyledTextCtrl_SetSelectionEnd, 3104). --define(wxStyledTextCtrl_GetSelectionEnd, 3105). --define(wxStyledTextCtrl_SetPrintMagnification, 3106). --define(wxStyledTextCtrl_GetPrintMagnification, 3107). --define(wxStyledTextCtrl_SetPrintColourMode, 3108). --define(wxStyledTextCtrl_GetPrintColourMode, 3109). --define(wxStyledTextCtrl_FindText, 3110). --define(wxStyledTextCtrl_FormatRange, 3111). --define(wxStyledTextCtrl_GetFirstVisibleLine, 3112). --define(wxStyledTextCtrl_GetLine, 3113). --define(wxStyledTextCtrl_GetLineCount, 3114). --define(wxStyledTextCtrl_SetMarginLeft, 3115). --define(wxStyledTextCtrl_GetMarginLeft, 3116). --define(wxStyledTextCtrl_SetMarginRight, 3117). --define(wxStyledTextCtrl_GetMarginRight, 3118). --define(wxStyledTextCtrl_GetModify, 3119). --define(wxStyledTextCtrl_SetSelection, 3120). --define(wxStyledTextCtrl_GetSelectedText, 3121). --define(wxStyledTextCtrl_GetTextRange, 3122). --define(wxStyledTextCtrl_HideSelection, 3123). --define(wxStyledTextCtrl_LineFromPosition, 3124). --define(wxStyledTextCtrl_PositionFromLine, 3125). --define(wxStyledTextCtrl_LineScroll, 3126). --define(wxStyledTextCtrl_EnsureCaretVisible, 3127). --define(wxStyledTextCtrl_ReplaceSelection, 3128). --define(wxStyledTextCtrl_SetReadOnly, 3129). --define(wxStyledTextCtrl_CanPaste, 3130). --define(wxStyledTextCtrl_CanUndo, 3131). --define(wxStyledTextCtrl_EmptyUndoBuffer, 3132). --define(wxStyledTextCtrl_Undo, 3133). --define(wxStyledTextCtrl_Cut, 3134). --define(wxStyledTextCtrl_Copy, 3135). --define(wxStyledTextCtrl_Paste, 3136). --define(wxStyledTextCtrl_Clear, 3137). --define(wxStyledTextCtrl_SetText, 3138). --define(wxStyledTextCtrl_GetText, 3139). --define(wxStyledTextCtrl_GetTextLength, 3140). --define(wxStyledTextCtrl_GetOvertype, 3141). --define(wxStyledTextCtrl_SetCaretWidth, 3142). --define(wxStyledTextCtrl_GetCaretWidth, 3143). --define(wxStyledTextCtrl_SetTargetStart, 3144). --define(wxStyledTextCtrl_GetTargetStart, 3145). --define(wxStyledTextCtrl_SetTargetEnd, 3146). --define(wxStyledTextCtrl_GetTargetEnd, 3147). --define(wxStyledTextCtrl_ReplaceTarget, 3148). --define(wxStyledTextCtrl_SearchInTarget, 3149). --define(wxStyledTextCtrl_SetSearchFlags, 3150). --define(wxStyledTextCtrl_GetSearchFlags, 3151). --define(wxStyledTextCtrl_CallTipShow, 3152). --define(wxStyledTextCtrl_CallTipCancel, 3153). --define(wxStyledTextCtrl_CallTipActive, 3154). --define(wxStyledTextCtrl_CallTipPosAtStart, 3155). --define(wxStyledTextCtrl_CallTipSetHighlight, 3156). --define(wxStyledTextCtrl_CallTipSetBackground, 3157). --define(wxStyledTextCtrl_CallTipSetForeground, 3158). --define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3159). --define(wxStyledTextCtrl_CallTipUseStyle, 3160). --define(wxStyledTextCtrl_VisibleFromDocLine, 3161). --define(wxStyledTextCtrl_DocLineFromVisible, 3162). --define(wxStyledTextCtrl_WrapCount, 3163). --define(wxStyledTextCtrl_SetFoldLevel, 3164). --define(wxStyledTextCtrl_GetFoldLevel, 3165). --define(wxStyledTextCtrl_GetLastChild, 3166). --define(wxStyledTextCtrl_GetFoldParent, 3167). --define(wxStyledTextCtrl_ShowLines, 3168). --define(wxStyledTextCtrl_HideLines, 3169). --define(wxStyledTextCtrl_GetLineVisible, 3170). --define(wxStyledTextCtrl_SetFoldExpanded, 3171). --define(wxStyledTextCtrl_GetFoldExpanded, 3172). --define(wxStyledTextCtrl_ToggleFold, 3173). --define(wxStyledTextCtrl_EnsureVisible, 3174). --define(wxStyledTextCtrl_SetFoldFlags, 3175). --define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3176). --define(wxStyledTextCtrl_SetTabIndents, 3177). --define(wxStyledTextCtrl_GetTabIndents, 3178). --define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3179). --define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3180). --define(wxStyledTextCtrl_SetMouseDwellTime, 3181). --define(wxStyledTextCtrl_GetMouseDwellTime, 3182). --define(wxStyledTextCtrl_WordStartPosition, 3183). --define(wxStyledTextCtrl_WordEndPosition, 3184). --define(wxStyledTextCtrl_SetWrapMode, 3185). --define(wxStyledTextCtrl_GetWrapMode, 3186). --define(wxStyledTextCtrl_SetWrapVisualFlags, 3187). --define(wxStyledTextCtrl_GetWrapVisualFlags, 3188). --define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3189). --define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3190). --define(wxStyledTextCtrl_SetWrapStartIndent, 3191). --define(wxStyledTextCtrl_GetWrapStartIndent, 3192). --define(wxStyledTextCtrl_SetLayoutCache, 3193). --define(wxStyledTextCtrl_GetLayoutCache, 3194). --define(wxStyledTextCtrl_SetScrollWidth, 3195). --define(wxStyledTextCtrl_GetScrollWidth, 3196). --define(wxStyledTextCtrl_TextWidth, 3197). --define(wxStyledTextCtrl_GetEndAtLastLine, 3198). --define(wxStyledTextCtrl_TextHeight, 3199). --define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3200). --define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3201). --define(wxStyledTextCtrl_AppendText, 3202). --define(wxStyledTextCtrl_GetTwoPhaseDraw, 3203). --define(wxStyledTextCtrl_SetTwoPhaseDraw, 3204). --define(wxStyledTextCtrl_TargetFromSelection, 3205). --define(wxStyledTextCtrl_LinesJoin, 3206). --define(wxStyledTextCtrl_LinesSplit, 3207). --define(wxStyledTextCtrl_SetFoldMarginColour, 3208). --define(wxStyledTextCtrl_SetFoldMarginHiColour, 3209). --define(wxStyledTextCtrl_LineDown, 3210). --define(wxStyledTextCtrl_LineDownExtend, 3211). --define(wxStyledTextCtrl_LineUp, 3212). --define(wxStyledTextCtrl_LineUpExtend, 3213). --define(wxStyledTextCtrl_CharLeft, 3214). --define(wxStyledTextCtrl_CharLeftExtend, 3215). --define(wxStyledTextCtrl_CharRight, 3216). --define(wxStyledTextCtrl_CharRightExtend, 3217). --define(wxStyledTextCtrl_WordLeft, 3218). --define(wxStyledTextCtrl_WordLeftExtend, 3219). --define(wxStyledTextCtrl_WordRight, 3220). --define(wxStyledTextCtrl_WordRightExtend, 3221). --define(wxStyledTextCtrl_Home, 3222). --define(wxStyledTextCtrl_HomeExtend, 3223). --define(wxStyledTextCtrl_LineEnd, 3224). --define(wxStyledTextCtrl_LineEndExtend, 3225). --define(wxStyledTextCtrl_DocumentStart, 3226). --define(wxStyledTextCtrl_DocumentStartExtend, 3227). --define(wxStyledTextCtrl_DocumentEnd, 3228). --define(wxStyledTextCtrl_DocumentEndExtend, 3229). --define(wxStyledTextCtrl_PageUp, 3230). --define(wxStyledTextCtrl_PageUpExtend, 3231). --define(wxStyledTextCtrl_PageDown, 3232). --define(wxStyledTextCtrl_PageDownExtend, 3233). --define(wxStyledTextCtrl_EditToggleOvertype, 3234). --define(wxStyledTextCtrl_Cancel, 3235). --define(wxStyledTextCtrl_DeleteBack, 3236). --define(wxStyledTextCtrl_Tab, 3237). --define(wxStyledTextCtrl_BackTab, 3238). --define(wxStyledTextCtrl_NewLine, 3239). --define(wxStyledTextCtrl_FormFeed, 3240). --define(wxStyledTextCtrl_VCHome, 3241). --define(wxStyledTextCtrl_VCHomeExtend, 3242). --define(wxStyledTextCtrl_ZoomIn, 3243). --define(wxStyledTextCtrl_ZoomOut, 3244). --define(wxStyledTextCtrl_DelWordLeft, 3245). --define(wxStyledTextCtrl_DelWordRight, 3246). --define(wxStyledTextCtrl_LineCut, 3247). --define(wxStyledTextCtrl_LineDelete, 3248). --define(wxStyledTextCtrl_LineTranspose, 3249). --define(wxStyledTextCtrl_LineDuplicate, 3250). --define(wxStyledTextCtrl_LowerCase, 3251). --define(wxStyledTextCtrl_UpperCase, 3252). --define(wxStyledTextCtrl_LineScrollDown, 3253). --define(wxStyledTextCtrl_LineScrollUp, 3254). --define(wxStyledTextCtrl_DeleteBackNotLine, 3255). --define(wxStyledTextCtrl_HomeDisplay, 3256). --define(wxStyledTextCtrl_HomeDisplayExtend, 3257). --define(wxStyledTextCtrl_LineEndDisplay, 3258). --define(wxStyledTextCtrl_LineEndDisplayExtend, 3259). --define(wxStyledTextCtrl_HomeWrapExtend, 3260). --define(wxStyledTextCtrl_LineEndWrap, 3261). --define(wxStyledTextCtrl_LineEndWrapExtend, 3262). --define(wxStyledTextCtrl_VCHomeWrap, 3263). --define(wxStyledTextCtrl_VCHomeWrapExtend, 3264). --define(wxStyledTextCtrl_LineCopy, 3265). --define(wxStyledTextCtrl_MoveCaretInsideView, 3266). --define(wxStyledTextCtrl_LineLength, 3267). --define(wxStyledTextCtrl_BraceHighlight, 3268). --define(wxStyledTextCtrl_BraceBadLight, 3269). --define(wxStyledTextCtrl_BraceMatch, 3270). --define(wxStyledTextCtrl_GetViewEOL, 3271). --define(wxStyledTextCtrl_SetViewEOL, 3272). --define(wxStyledTextCtrl_SetModEventMask, 3273). --define(wxStyledTextCtrl_GetEdgeColumn, 3274). --define(wxStyledTextCtrl_SetEdgeColumn, 3275). --define(wxStyledTextCtrl_SetEdgeMode, 3276). --define(wxStyledTextCtrl_GetEdgeMode, 3277). --define(wxStyledTextCtrl_GetEdgeColour, 3278). --define(wxStyledTextCtrl_SetEdgeColour, 3279). --define(wxStyledTextCtrl_SearchAnchor, 3280). --define(wxStyledTextCtrl_SearchNext, 3281). --define(wxStyledTextCtrl_SearchPrev, 3282). --define(wxStyledTextCtrl_LinesOnScreen, 3283). --define(wxStyledTextCtrl_UsePopUp, 3284). --define(wxStyledTextCtrl_SelectionIsRectangle, 3285). --define(wxStyledTextCtrl_SetZoom, 3286). --define(wxStyledTextCtrl_GetZoom, 3287). --define(wxStyledTextCtrl_GetModEventMask, 3288). --define(wxStyledTextCtrl_SetSTCFocus, 3289). --define(wxStyledTextCtrl_GetSTCFocus, 3290). --define(wxStyledTextCtrl_SetStatus, 3291). --define(wxStyledTextCtrl_GetStatus, 3292). --define(wxStyledTextCtrl_SetMouseDownCaptures, 3293). --define(wxStyledTextCtrl_GetMouseDownCaptures, 3294). --define(wxStyledTextCtrl_SetSTCCursor, 3295). --define(wxStyledTextCtrl_GetSTCCursor, 3296). --define(wxStyledTextCtrl_SetControlCharSymbol, 3297). --define(wxStyledTextCtrl_GetControlCharSymbol, 3298). --define(wxStyledTextCtrl_WordPartLeft, 3299). --define(wxStyledTextCtrl_WordPartLeftExtend, 3300). --define(wxStyledTextCtrl_WordPartRight, 3301). --define(wxStyledTextCtrl_WordPartRightExtend, 3302). --define(wxStyledTextCtrl_SetVisiblePolicy, 3303). --define(wxStyledTextCtrl_DelLineLeft, 3304). --define(wxStyledTextCtrl_DelLineRight, 3305). --define(wxStyledTextCtrl_GetXOffset, 3306). --define(wxStyledTextCtrl_ChooseCaretX, 3307). --define(wxStyledTextCtrl_SetXCaretPolicy, 3308). --define(wxStyledTextCtrl_SetYCaretPolicy, 3309). --define(wxStyledTextCtrl_GetPrintWrapMode, 3310). --define(wxStyledTextCtrl_SetHotspotActiveForeground, 3311). --define(wxStyledTextCtrl_SetHotspotActiveBackground, 3312). --define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3313). --define(wxStyledTextCtrl_SetHotspotSingleLine, 3314). --define(wxStyledTextCtrl_ParaDownExtend, 3315). --define(wxStyledTextCtrl_ParaUp, 3316). --define(wxStyledTextCtrl_ParaUpExtend, 3317). --define(wxStyledTextCtrl_PositionBefore, 3318). --define(wxStyledTextCtrl_PositionAfter, 3319). --define(wxStyledTextCtrl_CopyRange, 3320). --define(wxStyledTextCtrl_CopyText, 3321). --define(wxStyledTextCtrl_SetSelectionMode, 3322). --define(wxStyledTextCtrl_GetSelectionMode, 3323). --define(wxStyledTextCtrl_LineDownRectExtend, 3324). --define(wxStyledTextCtrl_LineUpRectExtend, 3325). --define(wxStyledTextCtrl_CharLeftRectExtend, 3326). --define(wxStyledTextCtrl_CharRightRectExtend, 3327). --define(wxStyledTextCtrl_HomeRectExtend, 3328). --define(wxStyledTextCtrl_VCHomeRectExtend, 3329). --define(wxStyledTextCtrl_LineEndRectExtend, 3330). --define(wxStyledTextCtrl_PageUpRectExtend, 3331). --define(wxStyledTextCtrl_PageDownRectExtend, 3332). --define(wxStyledTextCtrl_StutteredPageUp, 3333). --define(wxStyledTextCtrl_StutteredPageUpExtend, 3334). --define(wxStyledTextCtrl_StutteredPageDown, 3335). --define(wxStyledTextCtrl_StutteredPageDownExtend, 3336). --define(wxStyledTextCtrl_WordLeftEnd, 3337). --define(wxStyledTextCtrl_WordLeftEndExtend, 3338). --define(wxStyledTextCtrl_WordRightEnd, 3339). --define(wxStyledTextCtrl_WordRightEndExtend, 3340). --define(wxStyledTextCtrl_SetWhitespaceChars, 3341). --define(wxStyledTextCtrl_SetCharsDefault, 3342). --define(wxStyledTextCtrl_AutoCompGetCurrent, 3343). --define(wxStyledTextCtrl_Allocate, 3344). --define(wxStyledTextCtrl_FindColumn, 3345). --define(wxStyledTextCtrl_GetCaretSticky, 3346). --define(wxStyledTextCtrl_SetCaretSticky, 3347). --define(wxStyledTextCtrl_ToggleCaretSticky, 3348). --define(wxStyledTextCtrl_SetPasteConvertEndings, 3349). --define(wxStyledTextCtrl_GetPasteConvertEndings, 3350). --define(wxStyledTextCtrl_SelectionDuplicate, 3351). --define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3352). --define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3353). --define(wxStyledTextCtrl_StartRecord, 3354). --define(wxStyledTextCtrl_StopRecord, 3355). --define(wxStyledTextCtrl_SetLexer, 3356). --define(wxStyledTextCtrl_GetLexer, 3357). --define(wxStyledTextCtrl_Colourise, 3358). --define(wxStyledTextCtrl_SetProperty, 3359). --define(wxStyledTextCtrl_SetKeyWords, 3360). --define(wxStyledTextCtrl_SetLexerLanguage, 3361). --define(wxStyledTextCtrl_GetProperty, 3362). --define(wxStyledTextCtrl_GetStyleBitsNeeded, 3363). --define(wxStyledTextCtrl_GetCurrentLine, 3364). --define(wxStyledTextCtrl_StyleSetSpec, 3365). --define(wxStyledTextCtrl_StyleSetFont, 3366). --define(wxStyledTextCtrl_StyleSetFontAttr, 3367). --define(wxStyledTextCtrl_StyleSetCharacterSet, 3368). --define(wxStyledTextCtrl_StyleSetFontEncoding, 3369). --define(wxStyledTextCtrl_CmdKeyExecute, 3370). --define(wxStyledTextCtrl_SetMargins, 3371). --define(wxStyledTextCtrl_GetSelection, 3372). --define(wxStyledTextCtrl_PointFromPosition, 3373). --define(wxStyledTextCtrl_ScrollToLine, 3374). --define(wxStyledTextCtrl_ScrollToColumn, 3375). --define(wxStyledTextCtrl_SetVScrollBar, 3376). --define(wxStyledTextCtrl_SetHScrollBar, 3377). --define(wxStyledTextCtrl_GetLastKeydownProcessed, 3378). --define(wxStyledTextCtrl_SetLastKeydownProcessed, 3379). --define(wxStyledTextCtrl_SaveFile, 3380). --define(wxStyledTextCtrl_LoadFile, 3381). --define(wxStyledTextCtrl_DoDragOver, 3382). --define(wxStyledTextCtrl_DoDropText, 3383). --define(wxStyledTextCtrl_GetUseAntiAliasing, 3384). --define(wxStyledTextCtrl_AddTextRaw, 3385). --define(wxStyledTextCtrl_InsertTextRaw, 3386). --define(wxStyledTextCtrl_GetCurLineRaw, 3387). --define(wxStyledTextCtrl_GetLineRaw, 3388). --define(wxStyledTextCtrl_GetSelectedTextRaw, 3389). --define(wxStyledTextCtrl_GetTextRangeRaw, 3390). --define(wxStyledTextCtrl_SetTextRaw, 3391). --define(wxStyledTextCtrl_GetTextRaw, 3392). --define(wxStyledTextCtrl_AppendTextRaw, 3393). --define(wxArtProvider_GetBitmap, 3394). --define(wxArtProvider_GetIcon, 3395). --define(wxTreeEvent_GetKeyCode, 3396). --define(wxTreeEvent_GetItem, 3397). --define(wxTreeEvent_GetKeyEvent, 3398). --define(wxTreeEvent_GetLabel, 3399). --define(wxTreeEvent_GetOldItem, 3400). --define(wxTreeEvent_GetPoint, 3401). --define(wxTreeEvent_IsEditCancelled, 3402). --define(wxTreeEvent_SetToolTip, 3403). --define(wxNotebookEvent_GetOldSelection, 3404). --define(wxNotebookEvent_GetSelection, 3405). --define(wxNotebookEvent_SetOldSelection, 3406). --define(wxNotebookEvent_SetSelection, 3407). --define(wxFileDataObject_new, 3408). --define(wxFileDataObject_AddFile, 3409). --define(wxFileDataObject_GetFilenames, 3410). --define(wxFileDataObject_destroy, 3411). --define(wxTextDataObject_new, 3412). --define(wxTextDataObject_GetTextLength, 3413). --define(wxTextDataObject_GetText, 3414). --define(wxTextDataObject_SetText, 3415). --define(wxTextDataObject_destroy, 3416). --define(wxBitmapDataObject_new_1_1, 3417). --define(wxBitmapDataObject_new_1_0, 3418). --define(wxBitmapDataObject_GetBitmap, 3419). --define(wxBitmapDataObject_SetBitmap, 3420). --define(wxBitmapDataObject_destroy, 3421). --define(wxClipboard_new, 3423). --define(wxClipboard_destruct, 3424). --define(wxClipboard_AddData, 3425). --define(wxClipboard_Clear, 3426). --define(wxClipboard_Close, 3427). --define(wxClipboard_Flush, 3428). --define(wxClipboard_GetData, 3429). --define(wxClipboard_IsOpened, 3430). --define(wxClipboard_Open, 3431). --define(wxClipboard_SetData, 3432). --define(wxClipboard_UsePrimarySelection, 3434). --define(wxClipboard_IsSupported, 3435). --define(wxClipboard_Get, 3436). --define(wxSpinEvent_GetPosition, 3437). --define(wxSpinEvent_SetPosition, 3438). --define(wxSplitterWindow_new_0, 3439). --define(wxSplitterWindow_new_2, 3440). --define(wxSplitterWindow_destruct, 3441). --define(wxSplitterWindow_Create, 3442). --define(wxSplitterWindow_GetMinimumPaneSize, 3443). --define(wxSplitterWindow_GetSashGravity, 3444). --define(wxSplitterWindow_GetSashPosition, 3445). --define(wxSplitterWindow_GetSplitMode, 3446). --define(wxSplitterWindow_GetWindow1, 3447). --define(wxSplitterWindow_GetWindow2, 3448). --define(wxSplitterWindow_Initialize, 3449). --define(wxSplitterWindow_IsSplit, 3450). --define(wxSplitterWindow_ReplaceWindow, 3451). --define(wxSplitterWindow_SetSashGravity, 3452). --define(wxSplitterWindow_SetSashPosition, 3453). --define(wxSplitterWindow_SetSashSize, 3454). --define(wxSplitterWindow_SetMinimumPaneSize, 3455). --define(wxSplitterWindow_SetSplitMode, 3456). --define(wxSplitterWindow_SplitHorizontally, 3457). --define(wxSplitterWindow_SplitVertically, 3458). --define(wxSplitterWindow_Unsplit, 3459). --define(wxSplitterWindow_UpdateSize, 3460). --define(wxSplitterEvent_GetSashPosition, 3461). --define(wxSplitterEvent_GetX, 3462). --define(wxSplitterEvent_GetY, 3463). --define(wxSplitterEvent_GetWindowBeingRemoved, 3464). --define(wxSplitterEvent_SetSashPosition, 3465). --define(wxHtmlWindow_new_0, 3466). --define(wxHtmlWindow_new_2, 3467). --define(wxHtmlWindow_AppendToPage, 3468). --define(wxHtmlWindow_GetOpenedAnchor, 3469). --define(wxHtmlWindow_GetOpenedPage, 3470). --define(wxHtmlWindow_GetOpenedPageTitle, 3471). --define(wxHtmlWindow_GetRelatedFrame, 3472). --define(wxHtmlWindow_HistoryBack, 3473). --define(wxHtmlWindow_HistoryCanBack, 3474). --define(wxHtmlWindow_HistoryCanForward, 3475). --define(wxHtmlWindow_HistoryClear, 3476). --define(wxHtmlWindow_HistoryForward, 3477). --define(wxHtmlWindow_LoadFile, 3478). --define(wxHtmlWindow_LoadPage, 3479). --define(wxHtmlWindow_SelectAll, 3480). --define(wxHtmlWindow_SelectionToText, 3481). --define(wxHtmlWindow_SelectLine, 3482). --define(wxHtmlWindow_SelectWord, 3483). --define(wxHtmlWindow_SetBorders, 3484). --define(wxHtmlWindow_SetFonts, 3485). --define(wxHtmlWindow_SetPage, 3486). --define(wxHtmlWindow_SetRelatedFrame, 3487). --define(wxHtmlWindow_SetRelatedStatusBar, 3488). --define(wxHtmlWindow_ToText, 3489). --define(wxHtmlWindow_destroy, 3490). --define(wxHtmlLinkEvent_GetLinkInfo, 3491). --define(wxSystemSettings_GetColour, 3492). --define(wxSystemSettings_GetFont, 3493). --define(wxSystemSettings_GetMetric, 3494). --define(wxSystemSettings_GetScreenType, 3495). --define(wxSystemOptions_GetOption, 3496). --define(wxSystemOptions_GetOptionInt, 3497). --define(wxSystemOptions_HasOption, 3498). --define(wxSystemOptions_IsFalse, 3499). --define(wxSystemOptions_SetOption_2_1, 3500). --define(wxSystemOptions_SetOption_2_0, 3501). --define(wxAuiNotebookEvent_SetSelection, 3502). --define(wxAuiNotebookEvent_GetSelection, 3503). --define(wxAuiNotebookEvent_SetOldSelection, 3504). --define(wxAuiNotebookEvent_GetOldSelection, 3505). --define(wxAuiNotebookEvent_SetDragSource, 3506). --define(wxAuiNotebookEvent_GetDragSource, 3507). --define(wxAuiManagerEvent_SetManager, 3508). --define(wxAuiManagerEvent_GetManager, 3509). --define(wxAuiManagerEvent_SetPane, 3510). --define(wxAuiManagerEvent_GetPane, 3511). --define(wxAuiManagerEvent_SetButton, 3512). --define(wxAuiManagerEvent_GetButton, 3513). --define(wxAuiManagerEvent_SetDC, 3514). --define(wxAuiManagerEvent_GetDC, 3515). --define(wxAuiManagerEvent_Veto, 3516). --define(wxAuiManagerEvent_GetVeto, 3517). --define(wxAuiManagerEvent_SetCanVeto, 3518). --define(wxAuiManagerEvent_CanVeto, 3519). --define(wxLogNull_new, 3520). --define(wxLogNull_destroy, 3521). --define(wxTaskBarIcon_new, 3522). --define(wxTaskBarIcon_destruct, 3523). --define(wxTaskBarIcon_PopupMenu, 3524). --define(wxTaskBarIcon_RemoveIcon, 3525). --define(wxTaskBarIcon_SetIcon, 3526). --define(wxLocale_new_0, 3527). --define(wxLocale_new_2, 3529). --define(wxLocale_destruct, 3530). --define(wxLocale_Init, 3532). --define(wxLocale_AddCatalog_1, 3533). --define(wxLocale_AddCatalog_3, 3534). --define(wxLocale_AddCatalogLookupPathPrefix, 3535). --define(wxLocale_GetCanonicalName, 3536). --define(wxLocale_GetLanguage, 3537). --define(wxLocale_GetLanguageName, 3538). --define(wxLocale_GetLocale, 3539). --define(wxLocale_GetName, 3540). --define(wxLocale_GetString_2, 3541). --define(wxLocale_GetString_4, 3542). --define(wxLocale_GetHeaderValue, 3543). --define(wxLocale_GetSysName, 3544). --define(wxLocale_GetSystemEncoding, 3545). --define(wxLocale_GetSystemEncodingName, 3546). --define(wxLocale_GetSystemLanguage, 3547). --define(wxLocale_IsLoaded, 3548). --define(wxLocale_IsOk, 3549). +-define(wxTextCtrl_ChangeValue, 1827). +-define(wxTextCtrl_EmulateKeyPress, 1828). +-define(wxTextCtrl_GetDefaultStyle, 1829). +-define(wxTextCtrl_GetInsertionPoint, 1830). +-define(wxTextCtrl_GetLastPosition, 1831). +-define(wxTextCtrl_GetLineLength, 1832). +-define(wxTextCtrl_GetLineText, 1833). +-define(wxTextCtrl_GetNumberOfLines, 1834). +-define(wxTextCtrl_GetRange, 1835). +-define(wxTextCtrl_GetSelection, 1836). +-define(wxTextCtrl_GetStringSelection, 1837). +-define(wxTextCtrl_GetStyle, 1838). +-define(wxTextCtrl_GetValue, 1839). +-define(wxTextCtrl_IsEditable, 1840). +-define(wxTextCtrl_IsModified, 1841). +-define(wxTextCtrl_IsMultiLine, 1842). +-define(wxTextCtrl_IsSingleLine, 1843). +-define(wxTextCtrl_LoadFile, 1844). +-define(wxTextCtrl_MarkDirty, 1845). +-define(wxTextCtrl_Paste, 1846). +-define(wxTextCtrl_PositionToXY, 1847). +-define(wxTextCtrl_Redo, 1848). +-define(wxTextCtrl_Remove, 1849). +-define(wxTextCtrl_Replace, 1850). +-define(wxTextCtrl_SaveFile, 1851). +-define(wxTextCtrl_SetDefaultStyle, 1852). +-define(wxTextCtrl_SetEditable, 1853). +-define(wxTextCtrl_SetInsertionPoint, 1854). +-define(wxTextCtrl_SetInsertionPointEnd, 1855). +-define(wxTextCtrl_SetMaxLength, 1857). +-define(wxTextCtrl_SetSelection, 1858). +-define(wxTextCtrl_SetStyle, 1859). +-define(wxTextCtrl_SetValue, 1860). +-define(wxTextCtrl_ShowPosition, 1861). +-define(wxTextCtrl_Undo, 1862). +-define(wxTextCtrl_WriteText, 1863). +-define(wxTextCtrl_XYToPosition, 1864). +-define(wxNotebook_new_0, 1867). +-define(wxNotebook_new_3, 1868). +-define(wxNotebook_destruct, 1869). +-define(wxNotebook_AddPage, 1870). +-define(wxNotebook_AdvanceSelection, 1871). +-define(wxNotebook_AssignImageList, 1872). +-define(wxNotebook_Create, 1873). +-define(wxNotebook_DeleteAllPages, 1874). +-define(wxNotebook_DeletePage, 1875). +-define(wxNotebook_RemovePage, 1876). +-define(wxNotebook_GetCurrentPage, 1877). +-define(wxNotebook_GetImageList, 1878). +-define(wxNotebook_GetPage, 1880). +-define(wxNotebook_GetPageCount, 1881). +-define(wxNotebook_GetPageImage, 1882). +-define(wxNotebook_GetPageText, 1883). +-define(wxNotebook_GetRowCount, 1884). +-define(wxNotebook_GetSelection, 1885). +-define(wxNotebook_GetThemeBackgroundColour, 1886). +-define(wxNotebook_HitTest, 1888). +-define(wxNotebook_InsertPage, 1890). +-define(wxNotebook_SetImageList, 1891). +-define(wxNotebook_SetPadding, 1892). +-define(wxNotebook_SetPageSize, 1893). +-define(wxNotebook_SetPageImage, 1894). +-define(wxNotebook_SetPageText, 1895). +-define(wxNotebook_SetSelection, 1896). +-define(wxNotebook_ChangeSelection, 1897). +-define(wxChoicebook_new_0, 1898). +-define(wxChoicebook_new_3, 1899). +-define(wxChoicebook_AddPage, 1900). +-define(wxChoicebook_AdvanceSelection, 1901). +-define(wxChoicebook_AssignImageList, 1902). +-define(wxChoicebook_Create, 1903). +-define(wxChoicebook_DeleteAllPages, 1904). +-define(wxChoicebook_DeletePage, 1905). +-define(wxChoicebook_RemovePage, 1906). +-define(wxChoicebook_GetCurrentPage, 1907). +-define(wxChoicebook_GetImageList, 1908). +-define(wxChoicebook_GetPage, 1910). +-define(wxChoicebook_GetPageCount, 1911). +-define(wxChoicebook_GetPageImage, 1912). +-define(wxChoicebook_GetPageText, 1913). +-define(wxChoicebook_GetSelection, 1914). +-define(wxChoicebook_HitTest, 1915). +-define(wxChoicebook_InsertPage, 1916). +-define(wxChoicebook_SetImageList, 1917). +-define(wxChoicebook_SetPageSize, 1918). +-define(wxChoicebook_SetPageImage, 1919). +-define(wxChoicebook_SetPageText, 1920). +-define(wxChoicebook_SetSelection, 1921). +-define(wxChoicebook_ChangeSelection, 1922). +-define(wxChoicebook_destroy, 1923). +-define(wxToolbook_new_0, 1924). +-define(wxToolbook_new_3, 1925). +-define(wxToolbook_AddPage, 1926). +-define(wxToolbook_AdvanceSelection, 1927). +-define(wxToolbook_AssignImageList, 1928). +-define(wxToolbook_Create, 1929). +-define(wxToolbook_DeleteAllPages, 1930). +-define(wxToolbook_DeletePage, 1931). +-define(wxToolbook_RemovePage, 1932). +-define(wxToolbook_GetCurrentPage, 1933). +-define(wxToolbook_GetImageList, 1934). +-define(wxToolbook_GetPage, 1936). +-define(wxToolbook_GetPageCount, 1937). +-define(wxToolbook_GetPageImage, 1938). +-define(wxToolbook_GetPageText, 1939). +-define(wxToolbook_GetSelection, 1940). +-define(wxToolbook_HitTest, 1942). +-define(wxToolbook_InsertPage, 1943). +-define(wxToolbook_SetImageList, 1944). +-define(wxToolbook_SetPageSize, 1945). +-define(wxToolbook_SetPageImage, 1946). +-define(wxToolbook_SetPageText, 1947). +-define(wxToolbook_SetSelection, 1948). +-define(wxToolbook_ChangeSelection, 1949). +-define(wxToolbook_destroy, 1950). +-define(wxListbook_new_0, 1951). +-define(wxListbook_new_3, 1952). +-define(wxListbook_AddPage, 1953). +-define(wxListbook_AdvanceSelection, 1954). +-define(wxListbook_AssignImageList, 1955). +-define(wxListbook_Create, 1956). +-define(wxListbook_DeleteAllPages, 1957). +-define(wxListbook_DeletePage, 1958). +-define(wxListbook_RemovePage, 1959). +-define(wxListbook_GetCurrentPage, 1960). +-define(wxListbook_GetImageList, 1961). +-define(wxListbook_GetPage, 1963). +-define(wxListbook_GetPageCount, 1964). +-define(wxListbook_GetPageImage, 1965). +-define(wxListbook_GetPageText, 1966). +-define(wxListbook_GetSelection, 1967). +-define(wxListbook_HitTest, 1969). +-define(wxListbook_InsertPage, 1970). +-define(wxListbook_SetImageList, 1971). +-define(wxListbook_SetPageSize, 1972). +-define(wxListbook_SetPageImage, 1973). +-define(wxListbook_SetPageText, 1974). +-define(wxListbook_SetSelection, 1975). +-define(wxListbook_ChangeSelection, 1976). +-define(wxListbook_destroy, 1977). +-define(wxTreebook_new_0, 1978). +-define(wxTreebook_new_3, 1979). +-define(wxTreebook_AddPage, 1980). +-define(wxTreebook_AdvanceSelection, 1981). +-define(wxTreebook_AssignImageList, 1982). +-define(wxTreebook_Create, 1983). +-define(wxTreebook_DeleteAllPages, 1984). +-define(wxTreebook_DeletePage, 1985). +-define(wxTreebook_RemovePage, 1986). +-define(wxTreebook_GetCurrentPage, 1987). +-define(wxTreebook_GetImageList, 1988). +-define(wxTreebook_GetPage, 1990). +-define(wxTreebook_GetPageCount, 1991). +-define(wxTreebook_GetPageImage, 1992). +-define(wxTreebook_GetPageText, 1993). +-define(wxTreebook_GetSelection, 1994). +-define(wxTreebook_ExpandNode, 1995). +-define(wxTreebook_IsNodeExpanded, 1996). +-define(wxTreebook_HitTest, 1998). +-define(wxTreebook_InsertPage, 1999). +-define(wxTreebook_InsertSubPage, 2000). +-define(wxTreebook_SetImageList, 2001). +-define(wxTreebook_SetPageSize, 2002). +-define(wxTreebook_SetPageImage, 2003). +-define(wxTreebook_SetPageText, 2004). +-define(wxTreebook_SetSelection, 2005). +-define(wxTreebook_ChangeSelection, 2006). +-define(wxTreebook_destroy, 2007). +-define(wxTreeCtrl_new_2, 2010). +-define(wxTreeCtrl_new_0, 2011). +-define(wxTreeCtrl_destruct, 2013). +-define(wxTreeCtrl_AddRoot, 2014). +-define(wxTreeCtrl_AppendItem, 2015). +-define(wxTreeCtrl_AssignImageList, 2016). +-define(wxTreeCtrl_AssignStateImageList, 2017). +-define(wxTreeCtrl_Collapse, 2018). +-define(wxTreeCtrl_CollapseAndReset, 2019). +-define(wxTreeCtrl_Create, 2020). +-define(wxTreeCtrl_Delete, 2021). +-define(wxTreeCtrl_DeleteAllItems, 2022). +-define(wxTreeCtrl_DeleteChildren, 2023). +-define(wxTreeCtrl_EditLabel, 2024). +-define(wxTreeCtrl_EnsureVisible, 2025). +-define(wxTreeCtrl_Expand, 2026). +-define(wxTreeCtrl_GetBoundingRect, 2027). +-define(wxTreeCtrl_GetChildrenCount, 2029). +-define(wxTreeCtrl_GetCount, 2030). +-define(wxTreeCtrl_GetEditControl, 2031). +-define(wxTreeCtrl_GetFirstChild, 2032). +-define(wxTreeCtrl_GetNextChild, 2033). +-define(wxTreeCtrl_GetFirstVisibleItem, 2034). +-define(wxTreeCtrl_GetImageList, 2035). +-define(wxTreeCtrl_GetIndent, 2036). +-define(wxTreeCtrl_GetItemBackgroundColour, 2037). +-define(wxTreeCtrl_GetItemData, 2038). +-define(wxTreeCtrl_GetItemFont, 2039). +-define(wxTreeCtrl_GetItemImage_1, 2040). +-define(wxTreeCtrl_GetItemImage_2, 2041). +-define(wxTreeCtrl_GetItemText, 2042). +-define(wxTreeCtrl_GetItemTextColour, 2043). +-define(wxTreeCtrl_GetLastChild, 2044). +-define(wxTreeCtrl_GetNextSibling, 2045). +-define(wxTreeCtrl_GetNextVisible, 2046). +-define(wxTreeCtrl_GetItemParent, 2047). +-define(wxTreeCtrl_GetPrevSibling, 2048). +-define(wxTreeCtrl_GetPrevVisible, 2049). +-define(wxTreeCtrl_GetRootItem, 2050). +-define(wxTreeCtrl_GetSelection, 2051). +-define(wxTreeCtrl_GetSelections, 2052). +-define(wxTreeCtrl_GetStateImageList, 2053). +-define(wxTreeCtrl_HitTest, 2054). +-define(wxTreeCtrl_InsertItem, 2056). +-define(wxTreeCtrl_IsBold, 2057). +-define(wxTreeCtrl_IsExpanded, 2058). +-define(wxTreeCtrl_IsSelected, 2059). +-define(wxTreeCtrl_IsVisible, 2060). +-define(wxTreeCtrl_ItemHasChildren, 2061). +-define(wxTreeCtrl_IsTreeItemIdOk, 2062). +-define(wxTreeCtrl_PrependItem, 2063). +-define(wxTreeCtrl_ScrollTo, 2064). +-define(wxTreeCtrl_SelectItem_1, 2065). +-define(wxTreeCtrl_SelectItem_2, 2066). +-define(wxTreeCtrl_SetIndent, 2067). +-define(wxTreeCtrl_SetImageList, 2068). +-define(wxTreeCtrl_SetItemBackgroundColour, 2069). +-define(wxTreeCtrl_SetItemBold, 2070). +-define(wxTreeCtrl_SetItemData, 2071). +-define(wxTreeCtrl_SetItemDropHighlight, 2072). +-define(wxTreeCtrl_SetItemFont, 2073). +-define(wxTreeCtrl_SetItemHasChildren, 2074). +-define(wxTreeCtrl_SetItemImage_2, 2075). +-define(wxTreeCtrl_SetItemImage_3, 2076). +-define(wxTreeCtrl_SetItemText, 2077). +-define(wxTreeCtrl_SetItemTextColour, 2078). +-define(wxTreeCtrl_SetStateImageList, 2079). +-define(wxTreeCtrl_SetWindowStyle, 2080). +-define(wxTreeCtrl_SortChildren, 2081). +-define(wxTreeCtrl_Toggle, 2082). +-define(wxTreeCtrl_ToggleItemSelection, 2083). +-define(wxTreeCtrl_Unselect, 2084). +-define(wxTreeCtrl_UnselectAll, 2085). +-define(wxTreeCtrl_UnselectItem, 2086). +-define(wxScrollBar_new_0, 2087). +-define(wxScrollBar_new_3, 2088). +-define(wxScrollBar_destruct, 2089). +-define(wxScrollBar_Create, 2090). +-define(wxScrollBar_GetRange, 2091). +-define(wxScrollBar_GetPageSize, 2092). +-define(wxScrollBar_GetThumbPosition, 2093). +-define(wxScrollBar_GetThumbSize, 2094). +-define(wxScrollBar_SetThumbPosition, 2095). +-define(wxScrollBar_SetScrollbar, 2096). +-define(wxSpinButton_new_2, 2098). +-define(wxSpinButton_new_0, 2099). +-define(wxSpinButton_Create, 2100). +-define(wxSpinButton_GetMax, 2101). +-define(wxSpinButton_GetMin, 2102). +-define(wxSpinButton_GetValue, 2103). +-define(wxSpinButton_SetRange, 2104). +-define(wxSpinButton_SetValue, 2105). +-define(wxSpinButton_destroy, 2106). +-define(wxSpinCtrl_new_0, 2107). +-define(wxSpinCtrl_new_2, 2108). +-define(wxSpinCtrl_Create, 2110). +-define(wxSpinCtrl_SetValue_1_1, 2113). +-define(wxSpinCtrl_SetValue_1_0, 2114). +-define(wxSpinCtrl_GetValue, 2116). +-define(wxSpinCtrl_SetRange, 2118). +-define(wxSpinCtrl_SetSelection, 2119). +-define(wxSpinCtrl_GetMin, 2121). +-define(wxSpinCtrl_GetMax, 2123). +-define(wxSpinCtrl_destroy, 2124). +-define(wxStaticText_new_0, 2125). +-define(wxStaticText_new_4, 2126). +-define(wxStaticText_Create, 2127). +-define(wxStaticText_GetLabel, 2128). +-define(wxStaticText_SetLabel, 2129). +-define(wxStaticText_Wrap, 2130). +-define(wxStaticText_destroy, 2131). +-define(wxStaticBitmap_new_0, 2132). +-define(wxStaticBitmap_new_4, 2133). +-define(wxStaticBitmap_Create, 2134). +-define(wxStaticBitmap_GetBitmap, 2135). +-define(wxStaticBitmap_SetBitmap, 2136). +-define(wxStaticBitmap_destroy, 2137). +-define(wxRadioBox_new, 2138). +-define(wxRadioBox_destruct, 2140). +-define(wxRadioBox_Create, 2141). +-define(wxRadioBox_Enable_2, 2142). +-define(wxRadioBox_Enable_1, 2143). +-define(wxRadioBox_GetSelection, 2144). +-define(wxRadioBox_GetString, 2145). +-define(wxRadioBox_SetSelection, 2146). +-define(wxRadioBox_Show_2, 2147). +-define(wxRadioBox_Show_1, 2148). +-define(wxRadioBox_GetColumnCount, 2149). +-define(wxRadioBox_GetItemHelpText, 2150). +-define(wxRadioBox_GetItemToolTip, 2151). +-define(wxRadioBox_GetItemFromPoint, 2153). +-define(wxRadioBox_GetRowCount, 2154). +-define(wxRadioBox_IsItemEnabled, 2155). +-define(wxRadioBox_IsItemShown, 2156). +-define(wxRadioBox_SetItemHelpText, 2157). +-define(wxRadioBox_SetItemToolTip, 2158). +-define(wxRadioButton_new_0, 2159). +-define(wxRadioButton_new_4, 2160). +-define(wxRadioButton_Create, 2161). +-define(wxRadioButton_GetValue, 2162). +-define(wxRadioButton_SetValue, 2163). +-define(wxRadioButton_destroy, 2164). +-define(wxSlider_new_6, 2166). +-define(wxSlider_new_0, 2167). +-define(wxSlider_Create, 2168). +-define(wxSlider_GetLineSize, 2169). +-define(wxSlider_GetMax, 2170). +-define(wxSlider_GetMin, 2171). +-define(wxSlider_GetPageSize, 2172). +-define(wxSlider_GetThumbLength, 2173). +-define(wxSlider_GetValue, 2174). +-define(wxSlider_SetLineSize, 2175). +-define(wxSlider_SetPageSize, 2176). +-define(wxSlider_SetRange, 2177). +-define(wxSlider_SetThumbLength, 2178). +-define(wxSlider_SetValue, 2179). +-define(wxSlider_destroy, 2180). +-define(wxDialog_new_4, 2182). +-define(wxDialog_new_0, 2183). +-define(wxDialog_destruct, 2185). +-define(wxDialog_Create, 2186). +-define(wxDialog_CreateButtonSizer, 2187). +-define(wxDialog_CreateStdDialogButtonSizer, 2188). +-define(wxDialog_EndModal, 2189). +-define(wxDialog_GetAffirmativeId, 2190). +-define(wxDialog_GetReturnCode, 2191). +-define(wxDialog_IsModal, 2192). +-define(wxDialog_SetAffirmativeId, 2193). +-define(wxDialog_SetReturnCode, 2194). +-define(wxDialog_Show, 2195). +-define(wxDialog_ShowModal, 2196). +-define(wxColourDialog_new_0, 2197). +-define(wxColourDialog_new_2, 2198). +-define(wxColourDialog_destruct, 2199). +-define(wxColourDialog_Create, 2200). +-define(wxColourDialog_GetColourData, 2201). +-define(wxColourData_new_0, 2202). +-define(wxColourData_new_1, 2203). +-define(wxColourData_destruct, 2204). +-define(wxColourData_GetChooseFull, 2205). +-define(wxColourData_GetColour, 2206). +-define(wxColourData_GetCustomColour, 2208). +-define(wxColourData_SetChooseFull, 2209). +-define(wxColourData_SetColour, 2210). +-define(wxColourData_SetCustomColour, 2211). +-define(wxPalette_new_0, 2212). +-define(wxPalette_new_4, 2213). +-define(wxPalette_destruct, 2215). +-define(wxPalette_Create, 2216). +-define(wxPalette_GetColoursCount, 2217). +-define(wxPalette_GetPixel, 2218). +-define(wxPalette_GetRGB, 2219). +-define(wxPalette_IsOk, 2220). +-define(wxDirDialog_new, 2224). +-define(wxDirDialog_destruct, 2225). +-define(wxDirDialog_GetPath, 2226). +-define(wxDirDialog_GetMessage, 2227). +-define(wxDirDialog_SetMessage, 2228). +-define(wxDirDialog_SetPath, 2229). +-define(wxFileDialog_new, 2233). +-define(wxFileDialog_destruct, 2234). +-define(wxFileDialog_GetDirectory, 2235). +-define(wxFileDialog_GetFilename, 2236). +-define(wxFileDialog_GetFilenames, 2237). +-define(wxFileDialog_GetFilterIndex, 2238). +-define(wxFileDialog_GetMessage, 2239). +-define(wxFileDialog_GetPath, 2240). +-define(wxFileDialog_GetPaths, 2241). +-define(wxFileDialog_GetWildcard, 2242). +-define(wxFileDialog_SetDirectory, 2243). +-define(wxFileDialog_SetFilename, 2244). +-define(wxFileDialog_SetFilterIndex, 2245). +-define(wxFileDialog_SetMessage, 2246). +-define(wxFileDialog_SetPath, 2247). +-define(wxFileDialog_SetWildcard, 2248). +-define(wxPickerBase_SetInternalMargin, 2249). +-define(wxPickerBase_GetInternalMargin, 2250). +-define(wxPickerBase_SetTextCtrlProportion, 2251). +-define(wxPickerBase_SetPickerCtrlProportion, 2252). +-define(wxPickerBase_GetTextCtrlProportion, 2253). +-define(wxPickerBase_GetPickerCtrlProportion, 2254). +-define(wxPickerBase_HasTextCtrl, 2255). +-define(wxPickerBase_GetTextCtrl, 2256). +-define(wxPickerBase_IsTextCtrlGrowable, 2257). +-define(wxPickerBase_SetPickerCtrlGrowable, 2258). +-define(wxPickerBase_SetTextCtrlGrowable, 2259). +-define(wxPickerBase_IsPickerCtrlGrowable, 2260). +-define(wxFilePickerCtrl_new_0, 2261). +-define(wxFilePickerCtrl_new_3, 2262). +-define(wxFilePickerCtrl_Create, 2263). +-define(wxFilePickerCtrl_GetPath, 2264). +-define(wxFilePickerCtrl_SetPath, 2265). +-define(wxFilePickerCtrl_destroy, 2266). +-define(wxDirPickerCtrl_new_0, 2267). +-define(wxDirPickerCtrl_new_3, 2268). +-define(wxDirPickerCtrl_Create, 2269). +-define(wxDirPickerCtrl_GetPath, 2270). +-define(wxDirPickerCtrl_SetPath, 2271). +-define(wxDirPickerCtrl_destroy, 2272). +-define(wxColourPickerCtrl_new_0, 2273). +-define(wxColourPickerCtrl_new_3, 2274). +-define(wxColourPickerCtrl_Create, 2275). +-define(wxColourPickerCtrl_GetColour, 2276). +-define(wxColourPickerCtrl_SetColour_1_1, 2277). +-define(wxColourPickerCtrl_SetColour_1_0, 2278). +-define(wxColourPickerCtrl_destroy, 2279). +-define(wxDatePickerCtrl_new_0, 2280). +-define(wxDatePickerCtrl_new_3, 2281). +-define(wxDatePickerCtrl_GetRange, 2282). +-define(wxDatePickerCtrl_GetValue, 2283). +-define(wxDatePickerCtrl_SetRange, 2284). +-define(wxDatePickerCtrl_SetValue, 2285). +-define(wxDatePickerCtrl_destroy, 2286). +-define(wxFontPickerCtrl_new_0, 2287). +-define(wxFontPickerCtrl_new_3, 2288). +-define(wxFontPickerCtrl_Create, 2289). +-define(wxFontPickerCtrl_GetSelectedFont, 2290). +-define(wxFontPickerCtrl_SetSelectedFont, 2291). +-define(wxFontPickerCtrl_GetMaxPointSize, 2292). +-define(wxFontPickerCtrl_SetMaxPointSize, 2293). +-define(wxFontPickerCtrl_destroy, 2294). +-define(wxFindReplaceDialog_new_0, 2297). +-define(wxFindReplaceDialog_new_4, 2298). +-define(wxFindReplaceDialog_destruct, 2299). +-define(wxFindReplaceDialog_Create, 2300). +-define(wxFindReplaceDialog_GetData, 2301). +-define(wxFindReplaceData_new_0, 2302). +-define(wxFindReplaceData_new_1, 2303). +-define(wxFindReplaceData_GetFindString, 2304). +-define(wxFindReplaceData_GetReplaceString, 2305). +-define(wxFindReplaceData_GetFlags, 2306). +-define(wxFindReplaceData_SetFlags, 2307). +-define(wxFindReplaceData_SetFindString, 2308). +-define(wxFindReplaceData_SetReplaceString, 2309). +-define(wxFindReplaceData_destroy, 2310). +-define(wxMultiChoiceDialog_new_0, 2311). +-define(wxMultiChoiceDialog_new_5, 2313). +-define(wxMultiChoiceDialog_GetSelections, 2314). +-define(wxMultiChoiceDialog_SetSelections, 2315). +-define(wxMultiChoiceDialog_destroy, 2316). +-define(wxSingleChoiceDialog_new_0, 2317). +-define(wxSingleChoiceDialog_new_5, 2319). +-define(wxSingleChoiceDialog_GetSelection, 2320). +-define(wxSingleChoiceDialog_GetStringSelection, 2321). +-define(wxSingleChoiceDialog_SetSelection, 2322). +-define(wxSingleChoiceDialog_destroy, 2323). +-define(wxTextEntryDialog_new, 2324). +-define(wxTextEntryDialog_GetValue, 2325). +-define(wxTextEntryDialog_SetValue, 2326). +-define(wxTextEntryDialog_destroy, 2327). +-define(wxPasswordEntryDialog_new, 2328). +-define(wxPasswordEntryDialog_destroy, 2329). +-define(wxFontData_new_0, 2330). +-define(wxFontData_new_1, 2331). +-define(wxFontData_destruct, 2332). +-define(wxFontData_EnableEffects, 2333). +-define(wxFontData_GetAllowSymbols, 2334). +-define(wxFontData_GetColour, 2335). +-define(wxFontData_GetChosenFont, 2336). +-define(wxFontData_GetEnableEffects, 2337). +-define(wxFontData_GetInitialFont, 2338). +-define(wxFontData_GetShowHelp, 2339). +-define(wxFontData_SetAllowSymbols, 2340). +-define(wxFontData_SetChosenFont, 2341). +-define(wxFontData_SetColour, 2342). +-define(wxFontData_SetInitialFont, 2343). +-define(wxFontData_SetRange, 2344). +-define(wxFontData_SetShowHelp, 2345). +-define(wxFontDialog_new_0, 2349). +-define(wxFontDialog_new_2, 2351). +-define(wxFontDialog_Create, 2353). +-define(wxFontDialog_GetFontData, 2354). +-define(wxFontDialog_destroy, 2356). +-define(wxProgressDialog_new, 2357). +-define(wxProgressDialog_destruct, 2358). +-define(wxProgressDialog_Resume, 2359). +-define(wxProgressDialog_Update_2, 2360). +-define(wxProgressDialog_Update_0, 2361). +-define(wxMessageDialog_new, 2362). +-define(wxMessageDialog_destruct, 2363). +-define(wxPageSetupDialog_new, 2364). +-define(wxPageSetupDialog_destruct, 2365). +-define(wxPageSetupDialog_GetPageSetupData, 2366). +-define(wxPageSetupDialog_ShowModal, 2367). +-define(wxPageSetupDialogData_new_0, 2368). +-define(wxPageSetupDialogData_new_1_0, 2369). +-define(wxPageSetupDialogData_new_1_1, 2370). +-define(wxPageSetupDialogData_destruct, 2371). +-define(wxPageSetupDialogData_EnableHelp, 2372). +-define(wxPageSetupDialogData_EnableMargins, 2373). +-define(wxPageSetupDialogData_EnableOrientation, 2374). +-define(wxPageSetupDialogData_EnablePaper, 2375). +-define(wxPageSetupDialogData_EnablePrinter, 2376). +-define(wxPageSetupDialogData_GetDefaultMinMargins, 2377). +-define(wxPageSetupDialogData_GetEnableMargins, 2378). +-define(wxPageSetupDialogData_GetEnableOrientation, 2379). +-define(wxPageSetupDialogData_GetEnablePaper, 2380). +-define(wxPageSetupDialogData_GetEnablePrinter, 2381). +-define(wxPageSetupDialogData_GetEnableHelp, 2382). +-define(wxPageSetupDialogData_GetDefaultInfo, 2383). +-define(wxPageSetupDialogData_GetMarginTopLeft, 2384). +-define(wxPageSetupDialogData_GetMarginBottomRight, 2385). +-define(wxPageSetupDialogData_GetMinMarginTopLeft, 2386). +-define(wxPageSetupDialogData_GetMinMarginBottomRight, 2387). +-define(wxPageSetupDialogData_GetPaperId, 2388). +-define(wxPageSetupDialogData_GetPaperSize, 2389). +-define(wxPageSetupDialogData_GetPrintData, 2391). +-define(wxPageSetupDialogData_IsOk, 2392). +-define(wxPageSetupDialogData_SetDefaultInfo, 2393). +-define(wxPageSetupDialogData_SetDefaultMinMargins, 2394). +-define(wxPageSetupDialogData_SetMarginTopLeft, 2395). +-define(wxPageSetupDialogData_SetMarginBottomRight, 2396). +-define(wxPageSetupDialogData_SetMinMarginTopLeft, 2397). +-define(wxPageSetupDialogData_SetMinMarginBottomRight, 2398). +-define(wxPageSetupDialogData_SetPaperId, 2399). +-define(wxPageSetupDialogData_SetPaperSize_1_1, 2400). +-define(wxPageSetupDialogData_SetPaperSize_1_0, 2401). +-define(wxPageSetupDialogData_SetPrintData, 2402). +-define(wxPrintDialog_new_2_0, 2403). +-define(wxPrintDialog_new_2_1, 2404). +-define(wxPrintDialog_destruct, 2405). +-define(wxPrintDialog_GetPrintDialogData, 2406). +-define(wxPrintDialog_GetPrintDC, 2407). +-define(wxPrintDialogData_new_0, 2408). +-define(wxPrintDialogData_new_1_1, 2409). +-define(wxPrintDialogData_new_1_0, 2410). +-define(wxPrintDialogData_destruct, 2411). +-define(wxPrintDialogData_EnableHelp, 2412). +-define(wxPrintDialogData_EnablePageNumbers, 2413). +-define(wxPrintDialogData_EnablePrintToFile, 2414). +-define(wxPrintDialogData_EnableSelection, 2415). +-define(wxPrintDialogData_GetAllPages, 2416). +-define(wxPrintDialogData_GetCollate, 2417). +-define(wxPrintDialogData_GetFromPage, 2418). +-define(wxPrintDialogData_GetMaxPage, 2419). +-define(wxPrintDialogData_GetMinPage, 2420). +-define(wxPrintDialogData_GetNoCopies, 2421). +-define(wxPrintDialogData_GetPrintData, 2422). +-define(wxPrintDialogData_GetPrintToFile, 2423). +-define(wxPrintDialogData_GetSelection, 2424). +-define(wxPrintDialogData_GetToPage, 2425). +-define(wxPrintDialogData_IsOk, 2426). +-define(wxPrintDialogData_SetCollate, 2427). +-define(wxPrintDialogData_SetFromPage, 2428). +-define(wxPrintDialogData_SetMaxPage, 2429). +-define(wxPrintDialogData_SetMinPage, 2430). +-define(wxPrintDialogData_SetNoCopies, 2431). +-define(wxPrintDialogData_SetPrintData, 2432). +-define(wxPrintDialogData_SetPrintToFile, 2433). +-define(wxPrintDialogData_SetSelection, 2434). +-define(wxPrintDialogData_SetToPage, 2435). +-define(wxPrintData_new_0, 2436). +-define(wxPrintData_new_1, 2437). +-define(wxPrintData_destruct, 2438). +-define(wxPrintData_GetCollate, 2439). +-define(wxPrintData_GetBin, 2440). +-define(wxPrintData_GetColour, 2441). +-define(wxPrintData_GetDuplex, 2442). +-define(wxPrintData_GetNoCopies, 2443). +-define(wxPrintData_GetOrientation, 2444). +-define(wxPrintData_GetPaperId, 2445). +-define(wxPrintData_GetPrinterName, 2446). +-define(wxPrintData_GetQuality, 2447). +-define(wxPrintData_IsOk, 2448). +-define(wxPrintData_SetBin, 2449). +-define(wxPrintData_SetCollate, 2450). +-define(wxPrintData_SetColour, 2451). +-define(wxPrintData_SetDuplex, 2452). +-define(wxPrintData_SetNoCopies, 2453). +-define(wxPrintData_SetOrientation, 2454). +-define(wxPrintData_SetPaperId, 2455). +-define(wxPrintData_SetPrinterName, 2456). +-define(wxPrintData_SetQuality, 2457). +-define(wxPrintPreview_new_2, 2460). +-define(wxPrintPreview_new_3, 2461). +-define(wxPrintPreview_destruct, 2463). +-define(wxPrintPreview_GetCanvas, 2464). +-define(wxPrintPreview_GetCurrentPage, 2465). +-define(wxPrintPreview_GetFrame, 2466). +-define(wxPrintPreview_GetMaxPage, 2467). +-define(wxPrintPreview_GetMinPage, 2468). +-define(wxPrintPreview_GetPrintout, 2469). +-define(wxPrintPreview_GetPrintoutForPrinting, 2470). +-define(wxPrintPreview_IsOk, 2471). +-define(wxPrintPreview_PaintPage, 2472). +-define(wxPrintPreview_Print, 2473). +-define(wxPrintPreview_RenderPage, 2474). +-define(wxPrintPreview_SetCanvas, 2475). +-define(wxPrintPreview_SetCurrentPage, 2476). +-define(wxPrintPreview_SetFrame, 2477). +-define(wxPrintPreview_SetPrintout, 2478). +-define(wxPrintPreview_SetZoom, 2479). +-define(wxPreviewFrame_new, 2480). +-define(wxPreviewFrame_destruct, 2481). +-define(wxPreviewFrame_CreateControlBar, 2482). +-define(wxPreviewFrame_CreateCanvas, 2483). +-define(wxPreviewFrame_Initialize, 2484). +-define(wxPreviewFrame_OnCloseWindow, 2485). +-define(wxPreviewControlBar_new, 2486). +-define(wxPreviewControlBar_destruct, 2487). +-define(wxPreviewControlBar_CreateButtons, 2488). +-define(wxPreviewControlBar_GetPrintPreview, 2489). +-define(wxPreviewControlBar_GetZoomControl, 2490). +-define(wxPreviewControlBar_SetZoomControl, 2491). +-define(wxPrinter_new, 2493). +-define(wxPrinter_CreateAbortWindow, 2494). +-define(wxPrinter_GetAbort, 2495). +-define(wxPrinter_GetLastError, 2496). +-define(wxPrinter_GetPrintDialogData, 2497). +-define(wxPrinter_Print, 2498). +-define(wxPrinter_PrintDialog, 2499). +-define(wxPrinter_ReportError, 2500). +-define(wxPrinter_Setup, 2501). +-define(wxPrinter_destroy, 2502). +-define(wxXmlResource_new_1, 2503). +-define(wxXmlResource_new_2, 2504). +-define(wxXmlResource_destruct, 2505). +-define(wxXmlResource_AttachUnknownControl, 2506). +-define(wxXmlResource_ClearHandlers, 2507). +-define(wxXmlResource_CompareVersion, 2508). +-define(wxXmlResource_Get, 2509). +-define(wxXmlResource_GetFlags, 2510). +-define(wxXmlResource_GetVersion, 2511). +-define(wxXmlResource_GetXRCID, 2512). +-define(wxXmlResource_InitAllHandlers, 2513). +-define(wxXmlResource_Load, 2514). +-define(wxXmlResource_LoadBitmap, 2515). +-define(wxXmlResource_LoadDialog_2, 2516). +-define(wxXmlResource_LoadDialog_3, 2517). +-define(wxXmlResource_LoadFrame_2, 2518). +-define(wxXmlResource_LoadFrame_3, 2519). +-define(wxXmlResource_LoadIcon, 2520). +-define(wxXmlResource_LoadMenu, 2521). +-define(wxXmlResource_LoadMenuBar_2, 2522). +-define(wxXmlResource_LoadMenuBar_1, 2523). +-define(wxXmlResource_LoadPanel_2, 2524). +-define(wxXmlResource_LoadPanel_3, 2525). +-define(wxXmlResource_LoadToolBar, 2526). +-define(wxXmlResource_Set, 2527). +-define(wxXmlResource_SetFlags, 2528). +-define(wxXmlResource_Unload, 2529). +-define(wxXmlResource_xrcctrl, 2530). +-define(wxHtmlEasyPrinting_new, 2531). +-define(wxHtmlEasyPrinting_destruct, 2532). +-define(wxHtmlEasyPrinting_GetPrintData, 2533). +-define(wxHtmlEasyPrinting_GetPageSetupData, 2534). +-define(wxHtmlEasyPrinting_PreviewFile, 2535). +-define(wxHtmlEasyPrinting_PreviewText, 2536). +-define(wxHtmlEasyPrinting_PrintFile, 2537). +-define(wxHtmlEasyPrinting_PrintText, 2538). +-define(wxHtmlEasyPrinting_PageSetup, 2539). +-define(wxHtmlEasyPrinting_SetFonts, 2540). +-define(wxHtmlEasyPrinting_SetHeader, 2541). +-define(wxHtmlEasyPrinting_SetFooter, 2542). +-define(wxGLCanvas_new_2, 2544). +-define(wxGLCanvas_new_3_1, 2545). +-define(wxGLCanvas_new_3_0, 2546). +-define(wxGLCanvas_GetContext, 2547). +-define(wxGLCanvas_SetCurrent, 2549). +-define(wxGLCanvas_SwapBuffers, 2550). +-define(wxGLCanvas_destroy, 2551). +-define(wxAuiManager_new, 2552). +-define(wxAuiManager_destruct, 2553). +-define(wxAuiManager_AddPane_2_1, 2554). +-define(wxAuiManager_AddPane_3, 2555). +-define(wxAuiManager_AddPane_2_0, 2556). +-define(wxAuiManager_DetachPane, 2557). +-define(wxAuiManager_GetAllPanes, 2558). +-define(wxAuiManager_GetArtProvider, 2559). +-define(wxAuiManager_GetDockSizeConstraint, 2560). +-define(wxAuiManager_GetFlags, 2561). +-define(wxAuiManager_GetManagedWindow, 2562). +-define(wxAuiManager_GetManager, 2563). +-define(wxAuiManager_GetPane_1_1, 2564). +-define(wxAuiManager_GetPane_1_0, 2565). +-define(wxAuiManager_HideHint, 2566). +-define(wxAuiManager_InsertPane, 2567). +-define(wxAuiManager_LoadPaneInfo, 2568). +-define(wxAuiManager_LoadPerspective, 2569). +-define(wxAuiManager_SavePaneInfo, 2570). +-define(wxAuiManager_SavePerspective, 2571). +-define(wxAuiManager_SetArtProvider, 2572). +-define(wxAuiManager_SetDockSizeConstraint, 2573). +-define(wxAuiManager_SetFlags, 2574). +-define(wxAuiManager_SetManagedWindow, 2575). +-define(wxAuiManager_ShowHint, 2576). +-define(wxAuiManager_UnInit, 2577). +-define(wxAuiManager_Update, 2578). +-define(wxAuiPaneInfo_new_0, 2579). +-define(wxAuiPaneInfo_new_1, 2580). +-define(wxAuiPaneInfo_destruct, 2581). +-define(wxAuiPaneInfo_BestSize_1, 2582). +-define(wxAuiPaneInfo_BestSize_2, 2583). +-define(wxAuiPaneInfo_Bottom, 2584). +-define(wxAuiPaneInfo_BottomDockable, 2585). +-define(wxAuiPaneInfo_Caption, 2586). +-define(wxAuiPaneInfo_CaptionVisible, 2587). +-define(wxAuiPaneInfo_Centre, 2588). +-define(wxAuiPaneInfo_CentrePane, 2589). +-define(wxAuiPaneInfo_CloseButton, 2590). +-define(wxAuiPaneInfo_DefaultPane, 2591). +-define(wxAuiPaneInfo_DestroyOnClose, 2592). +-define(wxAuiPaneInfo_Direction, 2593). +-define(wxAuiPaneInfo_Dock, 2594). +-define(wxAuiPaneInfo_Dockable, 2595). +-define(wxAuiPaneInfo_Fixed, 2596). +-define(wxAuiPaneInfo_Float, 2597). +-define(wxAuiPaneInfo_Floatable, 2598). +-define(wxAuiPaneInfo_FloatingPosition_1, 2599). +-define(wxAuiPaneInfo_FloatingPosition_2, 2600). +-define(wxAuiPaneInfo_FloatingSize_1, 2601). +-define(wxAuiPaneInfo_FloatingSize_2, 2602). +-define(wxAuiPaneInfo_Gripper, 2603). +-define(wxAuiPaneInfo_GripperTop, 2604). +-define(wxAuiPaneInfo_HasBorder, 2605). +-define(wxAuiPaneInfo_HasCaption, 2606). +-define(wxAuiPaneInfo_HasCloseButton, 2607). +-define(wxAuiPaneInfo_HasFlag, 2608). +-define(wxAuiPaneInfo_HasGripper, 2609). +-define(wxAuiPaneInfo_HasGripperTop, 2610). +-define(wxAuiPaneInfo_HasMaximizeButton, 2611). +-define(wxAuiPaneInfo_HasMinimizeButton, 2612). +-define(wxAuiPaneInfo_HasPinButton, 2613). +-define(wxAuiPaneInfo_Hide, 2614). +-define(wxAuiPaneInfo_IsBottomDockable, 2615). +-define(wxAuiPaneInfo_IsDocked, 2616). +-define(wxAuiPaneInfo_IsFixed, 2617). +-define(wxAuiPaneInfo_IsFloatable, 2618). +-define(wxAuiPaneInfo_IsFloating, 2619). +-define(wxAuiPaneInfo_IsLeftDockable, 2620). +-define(wxAuiPaneInfo_IsMovable, 2621). +-define(wxAuiPaneInfo_IsOk, 2622). +-define(wxAuiPaneInfo_IsResizable, 2623). +-define(wxAuiPaneInfo_IsRightDockable, 2624). +-define(wxAuiPaneInfo_IsShown, 2625). +-define(wxAuiPaneInfo_IsToolbar, 2626). +-define(wxAuiPaneInfo_IsTopDockable, 2627). +-define(wxAuiPaneInfo_Layer, 2628). +-define(wxAuiPaneInfo_Left, 2629). +-define(wxAuiPaneInfo_LeftDockable, 2630). +-define(wxAuiPaneInfo_MaxSize_1, 2631). +-define(wxAuiPaneInfo_MaxSize_2, 2632). +-define(wxAuiPaneInfo_MaximizeButton, 2633). +-define(wxAuiPaneInfo_MinSize_1, 2634). +-define(wxAuiPaneInfo_MinSize_2, 2635). +-define(wxAuiPaneInfo_MinimizeButton, 2636). +-define(wxAuiPaneInfo_Movable, 2637). +-define(wxAuiPaneInfo_Name, 2638). +-define(wxAuiPaneInfo_PaneBorder, 2639). +-define(wxAuiPaneInfo_PinButton, 2640). +-define(wxAuiPaneInfo_Position, 2641). +-define(wxAuiPaneInfo_Resizable, 2642). +-define(wxAuiPaneInfo_Right, 2643). +-define(wxAuiPaneInfo_RightDockable, 2644). +-define(wxAuiPaneInfo_Row, 2645). +-define(wxAuiPaneInfo_SafeSet, 2646). +-define(wxAuiPaneInfo_SetFlag, 2647). +-define(wxAuiPaneInfo_Show, 2648). +-define(wxAuiPaneInfo_ToolbarPane, 2649). +-define(wxAuiPaneInfo_Top, 2650). +-define(wxAuiPaneInfo_TopDockable, 2651). +-define(wxAuiPaneInfo_Window, 2652). +-define(wxAuiNotebook_new_0, 2653). +-define(wxAuiNotebook_new_2, 2654). +-define(wxAuiNotebook_AddPage, 2655). +-define(wxAuiNotebook_Create, 2656). +-define(wxAuiNotebook_DeletePage, 2657). +-define(wxAuiNotebook_GetArtProvider, 2658). +-define(wxAuiNotebook_GetPage, 2659). +-define(wxAuiNotebook_GetPageBitmap, 2660). +-define(wxAuiNotebook_GetPageCount, 2661). +-define(wxAuiNotebook_GetPageIndex, 2662). +-define(wxAuiNotebook_GetPageText, 2663). +-define(wxAuiNotebook_GetSelection, 2664). +-define(wxAuiNotebook_InsertPage, 2665). +-define(wxAuiNotebook_RemovePage, 2666). +-define(wxAuiNotebook_SetArtProvider, 2667). +-define(wxAuiNotebook_SetFont, 2668). +-define(wxAuiNotebook_SetPageBitmap, 2669). +-define(wxAuiNotebook_SetPageText, 2670). +-define(wxAuiNotebook_SetSelection, 2671). +-define(wxAuiNotebook_SetTabCtrlHeight, 2672). +-define(wxAuiNotebook_SetUniformBitmapSize, 2673). +-define(wxAuiNotebook_destroy, 2674). +-define(wxMDIParentFrame_new_0, 2675). +-define(wxMDIParentFrame_new_4, 2676). +-define(wxMDIParentFrame_destruct, 2677). +-define(wxMDIParentFrame_ActivateNext, 2678). +-define(wxMDIParentFrame_ActivatePrevious, 2679). +-define(wxMDIParentFrame_ArrangeIcons, 2680). +-define(wxMDIParentFrame_Cascade, 2681). +-define(wxMDIParentFrame_Create, 2682). +-define(wxMDIParentFrame_GetActiveChild, 2683). +-define(wxMDIParentFrame_GetClientWindow, 2684). +-define(wxMDIParentFrame_Tile, 2685). +-define(wxMDIChildFrame_new_0, 2686). +-define(wxMDIChildFrame_new_4, 2687). +-define(wxMDIChildFrame_destruct, 2688). +-define(wxMDIChildFrame_Activate, 2689). +-define(wxMDIChildFrame_Create, 2690). +-define(wxMDIChildFrame_Maximize, 2691). +-define(wxMDIChildFrame_Restore, 2692). +-define(wxMDIClientWindow_new_0, 2693). +-define(wxMDIClientWindow_new_2, 2694). +-define(wxMDIClientWindow_destruct, 2695). +-define(wxMDIClientWindow_CreateClient, 2696). +-define(wxLayoutAlgorithm_new, 2697). +-define(wxLayoutAlgorithm_LayoutFrame, 2698). +-define(wxLayoutAlgorithm_LayoutMDIFrame, 2699). +-define(wxLayoutAlgorithm_LayoutWindow, 2700). +-define(wxLayoutAlgorithm_destroy, 2701). +-define(wxEvent_GetId, 2702). +-define(wxEvent_GetSkipped, 2703). +-define(wxEvent_GetTimestamp, 2704). +-define(wxEvent_IsCommandEvent, 2705). +-define(wxEvent_ResumePropagation, 2706). +-define(wxEvent_ShouldPropagate, 2707). +-define(wxEvent_Skip, 2708). +-define(wxEvent_StopPropagation, 2709). +-define(wxCommandEvent_getClientData, 2710). +-define(wxCommandEvent_GetExtraLong, 2711). +-define(wxCommandEvent_GetInt, 2712). +-define(wxCommandEvent_GetSelection, 2713). +-define(wxCommandEvent_GetString, 2714). +-define(wxCommandEvent_IsChecked, 2715). +-define(wxCommandEvent_IsSelection, 2716). +-define(wxCommandEvent_SetInt, 2717). +-define(wxCommandEvent_SetString, 2718). +-define(wxScrollEvent_GetOrientation, 2719). +-define(wxScrollEvent_GetPosition, 2720). +-define(wxScrollWinEvent_GetOrientation, 2721). +-define(wxScrollWinEvent_GetPosition, 2722). +-define(wxMouseEvent_AltDown, 2723). +-define(wxMouseEvent_Button, 2724). +-define(wxMouseEvent_ButtonDClick, 2725). +-define(wxMouseEvent_ButtonDown, 2726). +-define(wxMouseEvent_ButtonUp, 2727). +-define(wxMouseEvent_CmdDown, 2728). +-define(wxMouseEvent_ControlDown, 2729). +-define(wxMouseEvent_Dragging, 2730). +-define(wxMouseEvent_Entering, 2731). +-define(wxMouseEvent_GetButton, 2732). +-define(wxMouseEvent_GetPosition, 2735). +-define(wxMouseEvent_GetLogicalPosition, 2736). +-define(wxMouseEvent_GetLinesPerAction, 2737). +-define(wxMouseEvent_GetWheelRotation, 2738). +-define(wxMouseEvent_GetWheelDelta, 2739). +-define(wxMouseEvent_GetX, 2740). +-define(wxMouseEvent_GetY, 2741). +-define(wxMouseEvent_IsButton, 2742). +-define(wxMouseEvent_IsPageScroll, 2743). +-define(wxMouseEvent_Leaving, 2744). +-define(wxMouseEvent_LeftDClick, 2745). +-define(wxMouseEvent_LeftDown, 2746). +-define(wxMouseEvent_LeftIsDown, 2747). +-define(wxMouseEvent_LeftUp, 2748). +-define(wxMouseEvent_MetaDown, 2749). +-define(wxMouseEvent_MiddleDClick, 2750). +-define(wxMouseEvent_MiddleDown, 2751). +-define(wxMouseEvent_MiddleIsDown, 2752). +-define(wxMouseEvent_MiddleUp, 2753). +-define(wxMouseEvent_Moving, 2754). +-define(wxMouseEvent_RightDClick, 2755). +-define(wxMouseEvent_RightDown, 2756). +-define(wxMouseEvent_RightIsDown, 2757). +-define(wxMouseEvent_RightUp, 2758). +-define(wxMouseEvent_ShiftDown, 2759). +-define(wxSetCursorEvent_GetCursor, 2760). +-define(wxSetCursorEvent_GetX, 2761). +-define(wxSetCursorEvent_GetY, 2762). +-define(wxSetCursorEvent_HasCursor, 2763). +-define(wxSetCursorEvent_SetCursor, 2764). +-define(wxKeyEvent_AltDown, 2765). +-define(wxKeyEvent_CmdDown, 2766). +-define(wxKeyEvent_ControlDown, 2767). +-define(wxKeyEvent_GetKeyCode, 2768). +-define(wxKeyEvent_GetModifiers, 2769). +-define(wxKeyEvent_GetPosition, 2772). +-define(wxKeyEvent_GetRawKeyCode, 2773). +-define(wxKeyEvent_GetRawKeyFlags, 2774). +-define(wxKeyEvent_GetUnicodeKey, 2775). +-define(wxKeyEvent_GetX, 2776). +-define(wxKeyEvent_GetY, 2777). +-define(wxKeyEvent_HasModifiers, 2778). +-define(wxKeyEvent_MetaDown, 2779). +-define(wxKeyEvent_ShiftDown, 2780). +-define(wxSizeEvent_GetSize, 2781). +-define(wxMoveEvent_GetPosition, 2782). +-define(wxEraseEvent_GetDC, 2783). +-define(wxFocusEvent_GetWindow, 2784). +-define(wxChildFocusEvent_GetWindow, 2785). +-define(wxMenuEvent_GetMenu, 2786). +-define(wxMenuEvent_GetMenuId, 2787). +-define(wxMenuEvent_IsPopup, 2788). +-define(wxCloseEvent_CanVeto, 2789). +-define(wxCloseEvent_GetLoggingOff, 2790). +-define(wxCloseEvent_SetCanVeto, 2791). +-define(wxCloseEvent_SetLoggingOff, 2792). +-define(wxCloseEvent_Veto, 2793). +-define(wxShowEvent_SetShow, 2794). +-define(wxShowEvent_GetShow, 2795). +-define(wxIconizeEvent_Iconized, 2796). +-define(wxJoystickEvent_ButtonDown, 2797). +-define(wxJoystickEvent_ButtonIsDown, 2798). +-define(wxJoystickEvent_ButtonUp, 2799). +-define(wxJoystickEvent_GetButtonChange, 2800). +-define(wxJoystickEvent_GetButtonState, 2801). +-define(wxJoystickEvent_GetJoystick, 2802). +-define(wxJoystickEvent_GetPosition, 2803). +-define(wxJoystickEvent_GetZPosition, 2804). +-define(wxJoystickEvent_IsButton, 2805). +-define(wxJoystickEvent_IsMove, 2806). +-define(wxJoystickEvent_IsZMove, 2807). +-define(wxUpdateUIEvent_CanUpdate, 2808). +-define(wxUpdateUIEvent_Check, 2809). +-define(wxUpdateUIEvent_Enable, 2810). +-define(wxUpdateUIEvent_Show, 2811). +-define(wxUpdateUIEvent_GetChecked, 2812). +-define(wxUpdateUIEvent_GetEnabled, 2813). +-define(wxUpdateUIEvent_GetShown, 2814). +-define(wxUpdateUIEvent_GetSetChecked, 2815). +-define(wxUpdateUIEvent_GetSetEnabled, 2816). +-define(wxUpdateUIEvent_GetSetShown, 2817). +-define(wxUpdateUIEvent_GetSetText, 2818). +-define(wxUpdateUIEvent_GetText, 2819). +-define(wxUpdateUIEvent_GetMode, 2820). +-define(wxUpdateUIEvent_GetUpdateInterval, 2821). +-define(wxUpdateUIEvent_ResetUpdateTime, 2822). +-define(wxUpdateUIEvent_SetMode, 2823). +-define(wxUpdateUIEvent_SetText, 2824). +-define(wxUpdateUIEvent_SetUpdateInterval, 2825). +-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2826). +-define(wxPaletteChangedEvent_SetChangedWindow, 2827). +-define(wxPaletteChangedEvent_GetChangedWindow, 2828). +-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2829). +-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2830). +-define(wxNavigationKeyEvent_GetDirection, 2831). +-define(wxNavigationKeyEvent_SetDirection, 2832). +-define(wxNavigationKeyEvent_IsWindowChange, 2833). +-define(wxNavigationKeyEvent_SetWindowChange, 2834). +-define(wxNavigationKeyEvent_IsFromTab, 2835). +-define(wxNavigationKeyEvent_SetFromTab, 2836). +-define(wxNavigationKeyEvent_GetCurrentFocus, 2837). +-define(wxNavigationKeyEvent_SetCurrentFocus, 2838). +-define(wxHelpEvent_GetOrigin, 2839). +-define(wxHelpEvent_GetPosition, 2840). +-define(wxHelpEvent_SetOrigin, 2841). +-define(wxHelpEvent_SetPosition, 2842). +-define(wxContextMenuEvent_GetPosition, 2843). +-define(wxContextMenuEvent_SetPosition, 2844). +-define(wxIdleEvent_CanSend, 2845). +-define(wxIdleEvent_GetMode, 2846). +-define(wxIdleEvent_RequestMore, 2847). +-define(wxIdleEvent_MoreRequested, 2848). +-define(wxIdleEvent_SetMode, 2849). +-define(wxGridEvent_AltDown, 2850). +-define(wxGridEvent_ControlDown, 2851). +-define(wxGridEvent_GetCol, 2852). +-define(wxGridEvent_GetPosition, 2853). +-define(wxGridEvent_GetRow, 2854). +-define(wxGridEvent_MetaDown, 2855). +-define(wxGridEvent_Selecting, 2856). +-define(wxGridEvent_ShiftDown, 2857). +-define(wxNotifyEvent_Allow, 2858). +-define(wxNotifyEvent_IsAllowed, 2859). +-define(wxNotifyEvent_Veto, 2860). +-define(wxSashEvent_GetEdge, 2861). +-define(wxSashEvent_GetDragRect, 2862). +-define(wxSashEvent_GetDragStatus, 2863). +-define(wxListEvent_GetCacheFrom, 2864). +-define(wxListEvent_GetCacheTo, 2865). +-define(wxListEvent_GetKeyCode, 2866). +-define(wxListEvent_GetIndex, 2867). +-define(wxListEvent_GetColumn, 2868). +-define(wxListEvent_GetPoint, 2869). +-define(wxListEvent_GetLabel, 2870). +-define(wxListEvent_GetText, 2871). +-define(wxListEvent_GetImage, 2872). +-define(wxListEvent_GetData, 2873). +-define(wxListEvent_GetMask, 2874). +-define(wxListEvent_GetItem, 2875). +-define(wxListEvent_IsEditCancelled, 2876). +-define(wxDateEvent_GetDate, 2877). +-define(wxCalendarEvent_GetWeekDay, 2878). +-define(wxFileDirPickerEvent_GetPath, 2879). +-define(wxColourPickerEvent_GetColour, 2880). +-define(wxFontPickerEvent_GetFont, 2881). +-define(wxStyledTextEvent_GetPosition, 2882). +-define(wxStyledTextEvent_GetKey, 2883). +-define(wxStyledTextEvent_GetModifiers, 2884). +-define(wxStyledTextEvent_GetModificationType, 2885). +-define(wxStyledTextEvent_GetText, 2886). +-define(wxStyledTextEvent_GetLength, 2887). +-define(wxStyledTextEvent_GetLinesAdded, 2888). +-define(wxStyledTextEvent_GetLine, 2889). +-define(wxStyledTextEvent_GetFoldLevelNow, 2890). +-define(wxStyledTextEvent_GetFoldLevelPrev, 2891). +-define(wxStyledTextEvent_GetMargin, 2892). +-define(wxStyledTextEvent_GetMessage, 2893). +-define(wxStyledTextEvent_GetWParam, 2894). +-define(wxStyledTextEvent_GetLParam, 2895). +-define(wxStyledTextEvent_GetListType, 2896). +-define(wxStyledTextEvent_GetX, 2897). +-define(wxStyledTextEvent_GetY, 2898). +-define(wxStyledTextEvent_GetDragText, 2899). +-define(wxStyledTextEvent_GetDragAllowMove, 2900). +-define(wxStyledTextEvent_GetDragResult, 2901). +-define(wxStyledTextEvent_GetShift, 2902). +-define(wxStyledTextEvent_GetControl, 2903). +-define(wxStyledTextEvent_GetAlt, 2904). +-define(utils_wxGetKeyState, 2905). +-define(utils_wxGetMousePosition, 2906). +-define(utils_wxGetMouseState, 2907). +-define(utils_wxSetDetectableAutoRepeat, 2908). +-define(utils_wxBell, 2909). +-define(utils_wxFindMenuItemId, 2910). +-define(utils_wxGenericFindWindowAtPoint, 2911). +-define(utils_wxFindWindowAtPoint, 2912). +-define(utils_wxBeginBusyCursor, 2913). +-define(utils_wxEndBusyCursor, 2914). +-define(utils_wxIsBusy, 2915). +-define(utils_wxShutdown, 2916). +-define(utils_wxShell, 2917). +-define(utils_wxLaunchDefaultBrowser, 2918). +-define(utils_wxGetEmailAddress, 2919). +-define(utils_wxGetUserId, 2920). +-define(utils_wxGetHomeDir, 2921). +-define(utils_wxNewId, 2922). +-define(utils_wxRegisterId, 2923). +-define(utils_wxGetCurrentId, 2924). +-define(utils_wxGetOsDescription, 2925). +-define(utils_wxIsPlatformLittleEndian, 2926). +-define(utils_wxIsPlatform64Bit, 2927). +-define(gdicmn_wxDisplaySize, 2928). +-define(gdicmn_wxSetCursor, 2929). +-define(wxPrintout_new, 2930). +-define(wxPrintout_destruct, 2931). +-define(wxPrintout_GetDC, 2932). +-define(wxPrintout_GetPageSizeMM, 2933). +-define(wxPrintout_GetPageSizePixels, 2934). +-define(wxPrintout_GetPaperRectPixels, 2935). +-define(wxPrintout_GetPPIPrinter, 2936). +-define(wxPrintout_GetPPIScreen, 2937). +-define(wxPrintout_GetTitle, 2938). +-define(wxPrintout_IsPreview, 2939). +-define(wxPrintout_FitThisSizeToPaper, 2940). +-define(wxPrintout_FitThisSizeToPage, 2941). +-define(wxPrintout_FitThisSizeToPageMargins, 2942). +-define(wxPrintout_MapScreenSizeToPaper, 2943). +-define(wxPrintout_MapScreenSizeToPage, 2944). +-define(wxPrintout_MapScreenSizeToPageMargins, 2945). +-define(wxPrintout_MapScreenSizeToDevice, 2946). +-define(wxPrintout_GetLogicalPaperRect, 2947). +-define(wxPrintout_GetLogicalPageRect, 2948). +-define(wxPrintout_GetLogicalPageMarginsRect, 2949). +-define(wxPrintout_SetLogicalOrigin, 2950). +-define(wxPrintout_OffsetLogicalOrigin, 2951). +-define(wxStyledTextCtrl_new_2, 2952). +-define(wxStyledTextCtrl_new_0, 2953). +-define(wxStyledTextCtrl_destruct, 2954). +-define(wxStyledTextCtrl_Create, 2955). +-define(wxStyledTextCtrl_AddText, 2956). +-define(wxStyledTextCtrl_AddStyledText, 2957). +-define(wxStyledTextCtrl_InsertText, 2958). +-define(wxStyledTextCtrl_ClearAll, 2959). +-define(wxStyledTextCtrl_ClearDocumentStyle, 2960). +-define(wxStyledTextCtrl_GetLength, 2961). +-define(wxStyledTextCtrl_GetCharAt, 2962). +-define(wxStyledTextCtrl_GetCurrentPos, 2963). +-define(wxStyledTextCtrl_GetAnchor, 2964). +-define(wxStyledTextCtrl_GetStyleAt, 2965). +-define(wxStyledTextCtrl_Redo, 2966). +-define(wxStyledTextCtrl_SetUndoCollection, 2967). +-define(wxStyledTextCtrl_SelectAll, 2968). +-define(wxStyledTextCtrl_SetSavePoint, 2969). +-define(wxStyledTextCtrl_GetStyledText, 2970). +-define(wxStyledTextCtrl_CanRedo, 2971). +-define(wxStyledTextCtrl_MarkerLineFromHandle, 2972). +-define(wxStyledTextCtrl_MarkerDeleteHandle, 2973). +-define(wxStyledTextCtrl_GetUndoCollection, 2974). +-define(wxStyledTextCtrl_GetViewWhiteSpace, 2975). +-define(wxStyledTextCtrl_SetViewWhiteSpace, 2976). +-define(wxStyledTextCtrl_PositionFromPoint, 2977). +-define(wxStyledTextCtrl_PositionFromPointClose, 2978). +-define(wxStyledTextCtrl_GotoLine, 2979). +-define(wxStyledTextCtrl_GotoPos, 2980). +-define(wxStyledTextCtrl_SetAnchor, 2981). +-define(wxStyledTextCtrl_GetCurLine, 2982). +-define(wxStyledTextCtrl_GetEndStyled, 2983). +-define(wxStyledTextCtrl_ConvertEOLs, 2984). +-define(wxStyledTextCtrl_GetEOLMode, 2985). +-define(wxStyledTextCtrl_SetEOLMode, 2986). +-define(wxStyledTextCtrl_StartStyling, 2987). +-define(wxStyledTextCtrl_SetStyling, 2988). +-define(wxStyledTextCtrl_GetBufferedDraw, 2989). +-define(wxStyledTextCtrl_SetBufferedDraw, 2990). +-define(wxStyledTextCtrl_SetTabWidth, 2991). +-define(wxStyledTextCtrl_GetTabWidth, 2992). +-define(wxStyledTextCtrl_SetCodePage, 2993). +-define(wxStyledTextCtrl_MarkerDefine, 2994). +-define(wxStyledTextCtrl_MarkerSetForeground, 2995). +-define(wxStyledTextCtrl_MarkerSetBackground, 2996). +-define(wxStyledTextCtrl_MarkerAdd, 2997). +-define(wxStyledTextCtrl_MarkerDelete, 2998). +-define(wxStyledTextCtrl_MarkerDeleteAll, 2999). +-define(wxStyledTextCtrl_MarkerGet, 3000). +-define(wxStyledTextCtrl_MarkerNext, 3001). +-define(wxStyledTextCtrl_MarkerPrevious, 3002). +-define(wxStyledTextCtrl_MarkerDefineBitmap, 3003). +-define(wxStyledTextCtrl_MarkerAddSet, 3004). +-define(wxStyledTextCtrl_MarkerSetAlpha, 3005). +-define(wxStyledTextCtrl_SetMarginType, 3006). +-define(wxStyledTextCtrl_GetMarginType, 3007). +-define(wxStyledTextCtrl_SetMarginWidth, 3008). +-define(wxStyledTextCtrl_GetMarginWidth, 3009). +-define(wxStyledTextCtrl_SetMarginMask, 3010). +-define(wxStyledTextCtrl_GetMarginMask, 3011). +-define(wxStyledTextCtrl_SetMarginSensitive, 3012). +-define(wxStyledTextCtrl_GetMarginSensitive, 3013). +-define(wxStyledTextCtrl_StyleClearAll, 3014). +-define(wxStyledTextCtrl_StyleSetForeground, 3015). +-define(wxStyledTextCtrl_StyleSetBackground, 3016). +-define(wxStyledTextCtrl_StyleSetBold, 3017). +-define(wxStyledTextCtrl_StyleSetItalic, 3018). +-define(wxStyledTextCtrl_StyleSetSize, 3019). +-define(wxStyledTextCtrl_StyleSetFaceName, 3020). +-define(wxStyledTextCtrl_StyleSetEOLFilled, 3021). +-define(wxStyledTextCtrl_StyleResetDefault, 3022). +-define(wxStyledTextCtrl_StyleSetUnderline, 3023). +-define(wxStyledTextCtrl_StyleSetCase, 3024). +-define(wxStyledTextCtrl_StyleSetHotSpot, 3025). +-define(wxStyledTextCtrl_SetSelForeground, 3026). +-define(wxStyledTextCtrl_SetSelBackground, 3027). +-define(wxStyledTextCtrl_GetSelAlpha, 3028). +-define(wxStyledTextCtrl_SetSelAlpha, 3029). +-define(wxStyledTextCtrl_SetCaretForeground, 3030). +-define(wxStyledTextCtrl_CmdKeyAssign, 3031). +-define(wxStyledTextCtrl_CmdKeyClear, 3032). +-define(wxStyledTextCtrl_CmdKeyClearAll, 3033). +-define(wxStyledTextCtrl_SetStyleBytes, 3034). +-define(wxStyledTextCtrl_StyleSetVisible, 3035). +-define(wxStyledTextCtrl_GetCaretPeriod, 3036). +-define(wxStyledTextCtrl_SetCaretPeriod, 3037). +-define(wxStyledTextCtrl_SetWordChars, 3038). +-define(wxStyledTextCtrl_BeginUndoAction, 3039). +-define(wxStyledTextCtrl_EndUndoAction, 3040). +-define(wxStyledTextCtrl_IndicatorSetStyle, 3041). +-define(wxStyledTextCtrl_IndicatorGetStyle, 3042). +-define(wxStyledTextCtrl_IndicatorSetForeground, 3043). +-define(wxStyledTextCtrl_IndicatorGetForeground, 3044). +-define(wxStyledTextCtrl_SetWhitespaceForeground, 3045). +-define(wxStyledTextCtrl_SetWhitespaceBackground, 3046). +-define(wxStyledTextCtrl_GetStyleBits, 3047). +-define(wxStyledTextCtrl_SetLineState, 3048). +-define(wxStyledTextCtrl_GetLineState, 3049). +-define(wxStyledTextCtrl_GetMaxLineState, 3050). +-define(wxStyledTextCtrl_GetCaretLineVisible, 3051). +-define(wxStyledTextCtrl_SetCaretLineVisible, 3052). +-define(wxStyledTextCtrl_GetCaretLineBackground, 3053). +-define(wxStyledTextCtrl_SetCaretLineBackground, 3054). +-define(wxStyledTextCtrl_AutoCompShow, 3055). +-define(wxStyledTextCtrl_AutoCompCancel, 3056). +-define(wxStyledTextCtrl_AutoCompActive, 3057). +-define(wxStyledTextCtrl_AutoCompPosStart, 3058). +-define(wxStyledTextCtrl_AutoCompComplete, 3059). +-define(wxStyledTextCtrl_AutoCompStops, 3060). +-define(wxStyledTextCtrl_AutoCompSetSeparator, 3061). +-define(wxStyledTextCtrl_AutoCompGetSeparator, 3062). +-define(wxStyledTextCtrl_AutoCompSelect, 3063). +-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3064). +-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3065). +-define(wxStyledTextCtrl_AutoCompSetFillUps, 3066). +-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3067). +-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3068). +-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3069). +-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3070). +-define(wxStyledTextCtrl_UserListShow, 3071). +-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3072). +-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3073). +-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3074). +-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3075). +-define(wxStyledTextCtrl_RegisterImage, 3076). +-define(wxStyledTextCtrl_ClearRegisteredImages, 3077). +-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3078). +-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3079). +-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3080). +-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3081). +-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3082). +-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3083). +-define(wxStyledTextCtrl_SetIndent, 3084). +-define(wxStyledTextCtrl_GetIndent, 3085). +-define(wxStyledTextCtrl_SetUseTabs, 3086). +-define(wxStyledTextCtrl_GetUseTabs, 3087). +-define(wxStyledTextCtrl_SetLineIndentation, 3088). +-define(wxStyledTextCtrl_GetLineIndentation, 3089). +-define(wxStyledTextCtrl_GetLineIndentPosition, 3090). +-define(wxStyledTextCtrl_GetColumn, 3091). +-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3092). +-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3093). +-define(wxStyledTextCtrl_SetIndentationGuides, 3094). +-define(wxStyledTextCtrl_GetIndentationGuides, 3095). +-define(wxStyledTextCtrl_SetHighlightGuide, 3096). +-define(wxStyledTextCtrl_GetHighlightGuide, 3097). +-define(wxStyledTextCtrl_GetLineEndPosition, 3098). +-define(wxStyledTextCtrl_GetCodePage, 3099). +-define(wxStyledTextCtrl_GetCaretForeground, 3100). +-define(wxStyledTextCtrl_GetReadOnly, 3101). +-define(wxStyledTextCtrl_SetCurrentPos, 3102). +-define(wxStyledTextCtrl_SetSelectionStart, 3103). +-define(wxStyledTextCtrl_GetSelectionStart, 3104). +-define(wxStyledTextCtrl_SetSelectionEnd, 3105). +-define(wxStyledTextCtrl_GetSelectionEnd, 3106). +-define(wxStyledTextCtrl_SetPrintMagnification, 3107). +-define(wxStyledTextCtrl_GetPrintMagnification, 3108). +-define(wxStyledTextCtrl_SetPrintColourMode, 3109). +-define(wxStyledTextCtrl_GetPrintColourMode, 3110). +-define(wxStyledTextCtrl_FindText, 3111). +-define(wxStyledTextCtrl_FormatRange, 3112). +-define(wxStyledTextCtrl_GetFirstVisibleLine, 3113). +-define(wxStyledTextCtrl_GetLine, 3114). +-define(wxStyledTextCtrl_GetLineCount, 3115). +-define(wxStyledTextCtrl_SetMarginLeft, 3116). +-define(wxStyledTextCtrl_GetMarginLeft, 3117). +-define(wxStyledTextCtrl_SetMarginRight, 3118). +-define(wxStyledTextCtrl_GetMarginRight, 3119). +-define(wxStyledTextCtrl_GetModify, 3120). +-define(wxStyledTextCtrl_SetSelection, 3121). +-define(wxStyledTextCtrl_GetSelectedText, 3122). +-define(wxStyledTextCtrl_GetTextRange, 3123). +-define(wxStyledTextCtrl_HideSelection, 3124). +-define(wxStyledTextCtrl_LineFromPosition, 3125). +-define(wxStyledTextCtrl_PositionFromLine, 3126). +-define(wxStyledTextCtrl_LineScroll, 3127). +-define(wxStyledTextCtrl_EnsureCaretVisible, 3128). +-define(wxStyledTextCtrl_ReplaceSelection, 3129). +-define(wxStyledTextCtrl_SetReadOnly, 3130). +-define(wxStyledTextCtrl_CanPaste, 3131). +-define(wxStyledTextCtrl_CanUndo, 3132). +-define(wxStyledTextCtrl_EmptyUndoBuffer, 3133). +-define(wxStyledTextCtrl_Undo, 3134). +-define(wxStyledTextCtrl_Cut, 3135). +-define(wxStyledTextCtrl_Copy, 3136). +-define(wxStyledTextCtrl_Paste, 3137). +-define(wxStyledTextCtrl_Clear, 3138). +-define(wxStyledTextCtrl_SetText, 3139). +-define(wxStyledTextCtrl_GetText, 3140). +-define(wxStyledTextCtrl_GetTextLength, 3141). +-define(wxStyledTextCtrl_GetOvertype, 3142). +-define(wxStyledTextCtrl_SetCaretWidth, 3143). +-define(wxStyledTextCtrl_GetCaretWidth, 3144). +-define(wxStyledTextCtrl_SetTargetStart, 3145). +-define(wxStyledTextCtrl_GetTargetStart, 3146). +-define(wxStyledTextCtrl_SetTargetEnd, 3147). +-define(wxStyledTextCtrl_GetTargetEnd, 3148). +-define(wxStyledTextCtrl_ReplaceTarget, 3149). +-define(wxStyledTextCtrl_SearchInTarget, 3150). +-define(wxStyledTextCtrl_SetSearchFlags, 3151). +-define(wxStyledTextCtrl_GetSearchFlags, 3152). +-define(wxStyledTextCtrl_CallTipShow, 3153). +-define(wxStyledTextCtrl_CallTipCancel, 3154). +-define(wxStyledTextCtrl_CallTipActive, 3155). +-define(wxStyledTextCtrl_CallTipPosAtStart, 3156). +-define(wxStyledTextCtrl_CallTipSetHighlight, 3157). +-define(wxStyledTextCtrl_CallTipSetBackground, 3158). +-define(wxStyledTextCtrl_CallTipSetForeground, 3159). +-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3160). +-define(wxStyledTextCtrl_CallTipUseStyle, 3161). +-define(wxStyledTextCtrl_VisibleFromDocLine, 3162). +-define(wxStyledTextCtrl_DocLineFromVisible, 3163). +-define(wxStyledTextCtrl_WrapCount, 3164). +-define(wxStyledTextCtrl_SetFoldLevel, 3165). +-define(wxStyledTextCtrl_GetFoldLevel, 3166). +-define(wxStyledTextCtrl_GetLastChild, 3167). +-define(wxStyledTextCtrl_GetFoldParent, 3168). +-define(wxStyledTextCtrl_ShowLines, 3169). +-define(wxStyledTextCtrl_HideLines, 3170). +-define(wxStyledTextCtrl_GetLineVisible, 3171). +-define(wxStyledTextCtrl_SetFoldExpanded, 3172). +-define(wxStyledTextCtrl_GetFoldExpanded, 3173). +-define(wxStyledTextCtrl_ToggleFold, 3174). +-define(wxStyledTextCtrl_EnsureVisible, 3175). +-define(wxStyledTextCtrl_SetFoldFlags, 3176). +-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3177). +-define(wxStyledTextCtrl_SetTabIndents, 3178). +-define(wxStyledTextCtrl_GetTabIndents, 3179). +-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3180). +-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3181). +-define(wxStyledTextCtrl_SetMouseDwellTime, 3182). +-define(wxStyledTextCtrl_GetMouseDwellTime, 3183). +-define(wxStyledTextCtrl_WordStartPosition, 3184). +-define(wxStyledTextCtrl_WordEndPosition, 3185). +-define(wxStyledTextCtrl_SetWrapMode, 3186). +-define(wxStyledTextCtrl_GetWrapMode, 3187). +-define(wxStyledTextCtrl_SetWrapVisualFlags, 3188). +-define(wxStyledTextCtrl_GetWrapVisualFlags, 3189). +-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3190). +-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3191). +-define(wxStyledTextCtrl_SetWrapStartIndent, 3192). +-define(wxStyledTextCtrl_GetWrapStartIndent, 3193). +-define(wxStyledTextCtrl_SetLayoutCache, 3194). +-define(wxStyledTextCtrl_GetLayoutCache, 3195). +-define(wxStyledTextCtrl_SetScrollWidth, 3196). +-define(wxStyledTextCtrl_GetScrollWidth, 3197). +-define(wxStyledTextCtrl_TextWidth, 3198). +-define(wxStyledTextCtrl_GetEndAtLastLine, 3199). +-define(wxStyledTextCtrl_TextHeight, 3200). +-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3201). +-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3202). +-define(wxStyledTextCtrl_AppendText, 3203). +-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3204). +-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3205). +-define(wxStyledTextCtrl_TargetFromSelection, 3206). +-define(wxStyledTextCtrl_LinesJoin, 3207). +-define(wxStyledTextCtrl_LinesSplit, 3208). +-define(wxStyledTextCtrl_SetFoldMarginColour, 3209). +-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3210). +-define(wxStyledTextCtrl_LineDown, 3211). +-define(wxStyledTextCtrl_LineDownExtend, 3212). +-define(wxStyledTextCtrl_LineUp, 3213). +-define(wxStyledTextCtrl_LineUpExtend, 3214). +-define(wxStyledTextCtrl_CharLeft, 3215). +-define(wxStyledTextCtrl_CharLeftExtend, 3216). +-define(wxStyledTextCtrl_CharRight, 3217). +-define(wxStyledTextCtrl_CharRightExtend, 3218). +-define(wxStyledTextCtrl_WordLeft, 3219). +-define(wxStyledTextCtrl_WordLeftExtend, 3220). +-define(wxStyledTextCtrl_WordRight, 3221). +-define(wxStyledTextCtrl_WordRightExtend, 3222). +-define(wxStyledTextCtrl_Home, 3223). +-define(wxStyledTextCtrl_HomeExtend, 3224). +-define(wxStyledTextCtrl_LineEnd, 3225). +-define(wxStyledTextCtrl_LineEndExtend, 3226). +-define(wxStyledTextCtrl_DocumentStart, 3227). +-define(wxStyledTextCtrl_DocumentStartExtend, 3228). +-define(wxStyledTextCtrl_DocumentEnd, 3229). +-define(wxStyledTextCtrl_DocumentEndExtend, 3230). +-define(wxStyledTextCtrl_PageUp, 3231). +-define(wxStyledTextCtrl_PageUpExtend, 3232). +-define(wxStyledTextCtrl_PageDown, 3233). +-define(wxStyledTextCtrl_PageDownExtend, 3234). +-define(wxStyledTextCtrl_EditToggleOvertype, 3235). +-define(wxStyledTextCtrl_Cancel, 3236). +-define(wxStyledTextCtrl_DeleteBack, 3237). +-define(wxStyledTextCtrl_Tab, 3238). +-define(wxStyledTextCtrl_BackTab, 3239). +-define(wxStyledTextCtrl_NewLine, 3240). +-define(wxStyledTextCtrl_FormFeed, 3241). +-define(wxStyledTextCtrl_VCHome, 3242). +-define(wxStyledTextCtrl_VCHomeExtend, 3243). +-define(wxStyledTextCtrl_ZoomIn, 3244). +-define(wxStyledTextCtrl_ZoomOut, 3245). +-define(wxStyledTextCtrl_DelWordLeft, 3246). +-define(wxStyledTextCtrl_DelWordRight, 3247). +-define(wxStyledTextCtrl_LineCut, 3248). +-define(wxStyledTextCtrl_LineDelete, 3249). +-define(wxStyledTextCtrl_LineTranspose, 3250). +-define(wxStyledTextCtrl_LineDuplicate, 3251). +-define(wxStyledTextCtrl_LowerCase, 3252). +-define(wxStyledTextCtrl_UpperCase, 3253). +-define(wxStyledTextCtrl_LineScrollDown, 3254). +-define(wxStyledTextCtrl_LineScrollUp, 3255). +-define(wxStyledTextCtrl_DeleteBackNotLine, 3256). +-define(wxStyledTextCtrl_HomeDisplay, 3257). +-define(wxStyledTextCtrl_HomeDisplayExtend, 3258). +-define(wxStyledTextCtrl_LineEndDisplay, 3259). +-define(wxStyledTextCtrl_LineEndDisplayExtend, 3260). +-define(wxStyledTextCtrl_HomeWrapExtend, 3261). +-define(wxStyledTextCtrl_LineEndWrap, 3262). +-define(wxStyledTextCtrl_LineEndWrapExtend, 3263). +-define(wxStyledTextCtrl_VCHomeWrap, 3264). +-define(wxStyledTextCtrl_VCHomeWrapExtend, 3265). +-define(wxStyledTextCtrl_LineCopy, 3266). +-define(wxStyledTextCtrl_MoveCaretInsideView, 3267). +-define(wxStyledTextCtrl_LineLength, 3268). +-define(wxStyledTextCtrl_BraceHighlight, 3269). +-define(wxStyledTextCtrl_BraceBadLight, 3270). +-define(wxStyledTextCtrl_BraceMatch, 3271). +-define(wxStyledTextCtrl_GetViewEOL, 3272). +-define(wxStyledTextCtrl_SetViewEOL, 3273). +-define(wxStyledTextCtrl_SetModEventMask, 3274). +-define(wxStyledTextCtrl_GetEdgeColumn, 3275). +-define(wxStyledTextCtrl_SetEdgeColumn, 3276). +-define(wxStyledTextCtrl_SetEdgeMode, 3277). +-define(wxStyledTextCtrl_GetEdgeMode, 3278). +-define(wxStyledTextCtrl_GetEdgeColour, 3279). +-define(wxStyledTextCtrl_SetEdgeColour, 3280). +-define(wxStyledTextCtrl_SearchAnchor, 3281). +-define(wxStyledTextCtrl_SearchNext, 3282). +-define(wxStyledTextCtrl_SearchPrev, 3283). +-define(wxStyledTextCtrl_LinesOnScreen, 3284). +-define(wxStyledTextCtrl_UsePopUp, 3285). +-define(wxStyledTextCtrl_SelectionIsRectangle, 3286). +-define(wxStyledTextCtrl_SetZoom, 3287). +-define(wxStyledTextCtrl_GetZoom, 3288). +-define(wxStyledTextCtrl_GetModEventMask, 3289). +-define(wxStyledTextCtrl_SetSTCFocus, 3290). +-define(wxStyledTextCtrl_GetSTCFocus, 3291). +-define(wxStyledTextCtrl_SetStatus, 3292). +-define(wxStyledTextCtrl_GetStatus, 3293). +-define(wxStyledTextCtrl_SetMouseDownCaptures, 3294). +-define(wxStyledTextCtrl_GetMouseDownCaptures, 3295). +-define(wxStyledTextCtrl_SetSTCCursor, 3296). +-define(wxStyledTextCtrl_GetSTCCursor, 3297). +-define(wxStyledTextCtrl_SetControlCharSymbol, 3298). +-define(wxStyledTextCtrl_GetControlCharSymbol, 3299). +-define(wxStyledTextCtrl_WordPartLeft, 3300). +-define(wxStyledTextCtrl_WordPartLeftExtend, 3301). +-define(wxStyledTextCtrl_WordPartRight, 3302). +-define(wxStyledTextCtrl_WordPartRightExtend, 3303). +-define(wxStyledTextCtrl_SetVisiblePolicy, 3304). +-define(wxStyledTextCtrl_DelLineLeft, 3305). +-define(wxStyledTextCtrl_DelLineRight, 3306). +-define(wxStyledTextCtrl_GetXOffset, 3307). +-define(wxStyledTextCtrl_ChooseCaretX, 3308). +-define(wxStyledTextCtrl_SetXCaretPolicy, 3309). +-define(wxStyledTextCtrl_SetYCaretPolicy, 3310). +-define(wxStyledTextCtrl_GetPrintWrapMode, 3311). +-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3312). +-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3313). +-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3314). +-define(wxStyledTextCtrl_SetHotspotSingleLine, 3315). +-define(wxStyledTextCtrl_ParaDownExtend, 3316). +-define(wxStyledTextCtrl_ParaUp, 3317). +-define(wxStyledTextCtrl_ParaUpExtend, 3318). +-define(wxStyledTextCtrl_PositionBefore, 3319). +-define(wxStyledTextCtrl_PositionAfter, 3320). +-define(wxStyledTextCtrl_CopyRange, 3321). +-define(wxStyledTextCtrl_CopyText, 3322). +-define(wxStyledTextCtrl_SetSelectionMode, 3323). +-define(wxStyledTextCtrl_GetSelectionMode, 3324). +-define(wxStyledTextCtrl_LineDownRectExtend, 3325). +-define(wxStyledTextCtrl_LineUpRectExtend, 3326). +-define(wxStyledTextCtrl_CharLeftRectExtend, 3327). +-define(wxStyledTextCtrl_CharRightRectExtend, 3328). +-define(wxStyledTextCtrl_HomeRectExtend, 3329). +-define(wxStyledTextCtrl_VCHomeRectExtend, 3330). +-define(wxStyledTextCtrl_LineEndRectExtend, 3331). +-define(wxStyledTextCtrl_PageUpRectExtend, 3332). +-define(wxStyledTextCtrl_PageDownRectExtend, 3333). +-define(wxStyledTextCtrl_StutteredPageUp, 3334). +-define(wxStyledTextCtrl_StutteredPageUpExtend, 3335). +-define(wxStyledTextCtrl_StutteredPageDown, 3336). +-define(wxStyledTextCtrl_StutteredPageDownExtend, 3337). +-define(wxStyledTextCtrl_WordLeftEnd, 3338). +-define(wxStyledTextCtrl_WordLeftEndExtend, 3339). +-define(wxStyledTextCtrl_WordRightEnd, 3340). +-define(wxStyledTextCtrl_WordRightEndExtend, 3341). +-define(wxStyledTextCtrl_SetWhitespaceChars, 3342). +-define(wxStyledTextCtrl_SetCharsDefault, 3343). +-define(wxStyledTextCtrl_AutoCompGetCurrent, 3344). +-define(wxStyledTextCtrl_Allocate, 3345). +-define(wxStyledTextCtrl_FindColumn, 3346). +-define(wxStyledTextCtrl_GetCaretSticky, 3347). +-define(wxStyledTextCtrl_SetCaretSticky, 3348). +-define(wxStyledTextCtrl_ToggleCaretSticky, 3349). +-define(wxStyledTextCtrl_SetPasteConvertEndings, 3350). +-define(wxStyledTextCtrl_GetPasteConvertEndings, 3351). +-define(wxStyledTextCtrl_SelectionDuplicate, 3352). +-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3353). +-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3354). +-define(wxStyledTextCtrl_StartRecord, 3355). +-define(wxStyledTextCtrl_StopRecord, 3356). +-define(wxStyledTextCtrl_SetLexer, 3357). +-define(wxStyledTextCtrl_GetLexer, 3358). +-define(wxStyledTextCtrl_Colourise, 3359). +-define(wxStyledTextCtrl_SetProperty, 3360). +-define(wxStyledTextCtrl_SetKeyWords, 3361). +-define(wxStyledTextCtrl_SetLexerLanguage, 3362). +-define(wxStyledTextCtrl_GetProperty, 3363). +-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3364). +-define(wxStyledTextCtrl_GetCurrentLine, 3365). +-define(wxStyledTextCtrl_StyleSetSpec, 3366). +-define(wxStyledTextCtrl_StyleSetFont, 3367). +-define(wxStyledTextCtrl_StyleSetFontAttr, 3368). +-define(wxStyledTextCtrl_StyleSetCharacterSet, 3369). +-define(wxStyledTextCtrl_StyleSetFontEncoding, 3370). +-define(wxStyledTextCtrl_CmdKeyExecute, 3371). +-define(wxStyledTextCtrl_SetMargins, 3372). +-define(wxStyledTextCtrl_GetSelection, 3373). +-define(wxStyledTextCtrl_PointFromPosition, 3374). +-define(wxStyledTextCtrl_ScrollToLine, 3375). +-define(wxStyledTextCtrl_ScrollToColumn, 3376). +-define(wxStyledTextCtrl_SetVScrollBar, 3377). +-define(wxStyledTextCtrl_SetHScrollBar, 3378). +-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3379). +-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3380). +-define(wxStyledTextCtrl_SaveFile, 3381). +-define(wxStyledTextCtrl_LoadFile, 3382). +-define(wxStyledTextCtrl_DoDragOver, 3383). +-define(wxStyledTextCtrl_DoDropText, 3384). +-define(wxStyledTextCtrl_GetUseAntiAliasing, 3385). +-define(wxStyledTextCtrl_AddTextRaw, 3386). +-define(wxStyledTextCtrl_InsertTextRaw, 3387). +-define(wxStyledTextCtrl_GetCurLineRaw, 3388). +-define(wxStyledTextCtrl_GetLineRaw, 3389). +-define(wxStyledTextCtrl_GetSelectedTextRaw, 3390). +-define(wxStyledTextCtrl_GetTextRangeRaw, 3391). +-define(wxStyledTextCtrl_SetTextRaw, 3392). +-define(wxStyledTextCtrl_GetTextRaw, 3393). +-define(wxStyledTextCtrl_AppendTextRaw, 3394). +-define(wxArtProvider_GetBitmap, 3395). +-define(wxArtProvider_GetIcon, 3396). +-define(wxTreeEvent_GetKeyCode, 3397). +-define(wxTreeEvent_GetItem, 3398). +-define(wxTreeEvent_GetKeyEvent, 3399). +-define(wxTreeEvent_GetLabel, 3400). +-define(wxTreeEvent_GetOldItem, 3401). +-define(wxTreeEvent_GetPoint, 3402). +-define(wxTreeEvent_IsEditCancelled, 3403). +-define(wxTreeEvent_SetToolTip, 3404). +-define(wxNotebookEvent_GetOldSelection, 3405). +-define(wxNotebookEvent_GetSelection, 3406). +-define(wxNotebookEvent_SetOldSelection, 3407). +-define(wxNotebookEvent_SetSelection, 3408). +-define(wxFileDataObject_new, 3409). +-define(wxFileDataObject_AddFile, 3410). +-define(wxFileDataObject_GetFilenames, 3411). +-define(wxFileDataObject_destroy, 3412). +-define(wxTextDataObject_new, 3413). +-define(wxTextDataObject_GetTextLength, 3414). +-define(wxTextDataObject_GetText, 3415). +-define(wxTextDataObject_SetText, 3416). +-define(wxTextDataObject_destroy, 3417). +-define(wxBitmapDataObject_new_1_1, 3418). +-define(wxBitmapDataObject_new_1_0, 3419). +-define(wxBitmapDataObject_GetBitmap, 3420). +-define(wxBitmapDataObject_SetBitmap, 3421). +-define(wxBitmapDataObject_destroy, 3422). +-define(wxClipboard_new, 3424). +-define(wxClipboard_destruct, 3425). +-define(wxClipboard_AddData, 3426). +-define(wxClipboard_Clear, 3427). +-define(wxClipboard_Close, 3428). +-define(wxClipboard_Flush, 3429). +-define(wxClipboard_GetData, 3430). +-define(wxClipboard_IsOpened, 3431). +-define(wxClipboard_Open, 3432). +-define(wxClipboard_SetData, 3433). +-define(wxClipboard_UsePrimarySelection, 3435). +-define(wxClipboard_IsSupported, 3436). +-define(wxClipboard_Get, 3437). +-define(wxSpinEvent_GetPosition, 3438). +-define(wxSpinEvent_SetPosition, 3439). +-define(wxSplitterWindow_new_0, 3440). +-define(wxSplitterWindow_new_2, 3441). +-define(wxSplitterWindow_destruct, 3442). +-define(wxSplitterWindow_Create, 3443). +-define(wxSplitterWindow_GetMinimumPaneSize, 3444). +-define(wxSplitterWindow_GetSashGravity, 3445). +-define(wxSplitterWindow_GetSashPosition, 3446). +-define(wxSplitterWindow_GetSplitMode, 3447). +-define(wxSplitterWindow_GetWindow1, 3448). +-define(wxSplitterWindow_GetWindow2, 3449). +-define(wxSplitterWindow_Initialize, 3450). +-define(wxSplitterWindow_IsSplit, 3451). +-define(wxSplitterWindow_ReplaceWindow, 3452). +-define(wxSplitterWindow_SetSashGravity, 3453). +-define(wxSplitterWindow_SetSashPosition, 3454). +-define(wxSplitterWindow_SetSashSize, 3455). +-define(wxSplitterWindow_SetMinimumPaneSize, 3456). +-define(wxSplitterWindow_SetSplitMode, 3457). +-define(wxSplitterWindow_SplitHorizontally, 3458). +-define(wxSplitterWindow_SplitVertically, 3459). +-define(wxSplitterWindow_Unsplit, 3460). +-define(wxSplitterWindow_UpdateSize, 3461). +-define(wxSplitterEvent_GetSashPosition, 3462). +-define(wxSplitterEvent_GetX, 3463). +-define(wxSplitterEvent_GetY, 3464). +-define(wxSplitterEvent_GetWindowBeingRemoved, 3465). +-define(wxSplitterEvent_SetSashPosition, 3466). +-define(wxHtmlWindow_new_0, 3467). +-define(wxHtmlWindow_new_2, 3468). +-define(wxHtmlWindow_AppendToPage, 3469). +-define(wxHtmlWindow_GetOpenedAnchor, 3470). +-define(wxHtmlWindow_GetOpenedPage, 3471). +-define(wxHtmlWindow_GetOpenedPageTitle, 3472). +-define(wxHtmlWindow_GetRelatedFrame, 3473). +-define(wxHtmlWindow_HistoryBack, 3474). +-define(wxHtmlWindow_HistoryCanBack, 3475). +-define(wxHtmlWindow_HistoryCanForward, 3476). +-define(wxHtmlWindow_HistoryClear, 3477). +-define(wxHtmlWindow_HistoryForward, 3478). +-define(wxHtmlWindow_LoadFile, 3479). +-define(wxHtmlWindow_LoadPage, 3480). +-define(wxHtmlWindow_SelectAll, 3481). +-define(wxHtmlWindow_SelectionToText, 3482). +-define(wxHtmlWindow_SelectLine, 3483). +-define(wxHtmlWindow_SelectWord, 3484). +-define(wxHtmlWindow_SetBorders, 3485). +-define(wxHtmlWindow_SetFonts, 3486). +-define(wxHtmlWindow_SetPage, 3487). +-define(wxHtmlWindow_SetRelatedFrame, 3488). +-define(wxHtmlWindow_SetRelatedStatusBar, 3489). +-define(wxHtmlWindow_ToText, 3490). +-define(wxHtmlWindow_destroy, 3491). +-define(wxHtmlLinkEvent_GetLinkInfo, 3492). +-define(wxSystemSettings_GetColour, 3493). +-define(wxSystemSettings_GetFont, 3494). +-define(wxSystemSettings_GetMetric, 3495). +-define(wxSystemSettings_GetScreenType, 3496). +-define(wxSystemOptions_GetOption, 3497). +-define(wxSystemOptions_GetOptionInt, 3498). +-define(wxSystemOptions_HasOption, 3499). +-define(wxSystemOptions_IsFalse, 3500). +-define(wxSystemOptions_SetOption_2_1, 3501). +-define(wxSystemOptions_SetOption_2_0, 3502). +-define(wxAuiNotebookEvent_SetSelection, 3503). +-define(wxAuiNotebookEvent_GetSelection, 3504). +-define(wxAuiNotebookEvent_SetOldSelection, 3505). +-define(wxAuiNotebookEvent_GetOldSelection, 3506). +-define(wxAuiNotebookEvent_SetDragSource, 3507). +-define(wxAuiNotebookEvent_GetDragSource, 3508). +-define(wxAuiManagerEvent_SetManager, 3509). +-define(wxAuiManagerEvent_GetManager, 3510). +-define(wxAuiManagerEvent_SetPane, 3511). +-define(wxAuiManagerEvent_GetPane, 3512). +-define(wxAuiManagerEvent_SetButton, 3513). +-define(wxAuiManagerEvent_GetButton, 3514). +-define(wxAuiManagerEvent_SetDC, 3515). +-define(wxAuiManagerEvent_GetDC, 3516). +-define(wxAuiManagerEvent_Veto, 3517). +-define(wxAuiManagerEvent_GetVeto, 3518). +-define(wxAuiManagerEvent_SetCanVeto, 3519). +-define(wxAuiManagerEvent_CanVeto, 3520). +-define(wxLogNull_new, 3521). +-define(wxLogNull_destroy, 3522). +-define(wxTaskBarIcon_new, 3523). +-define(wxTaskBarIcon_destruct, 3524). +-define(wxTaskBarIcon_PopupMenu, 3525). +-define(wxTaskBarIcon_RemoveIcon, 3526). +-define(wxTaskBarIcon_SetIcon, 3527). +-define(wxLocale_new_0, 3528). +-define(wxLocale_new_2, 3530). +-define(wxLocale_destruct, 3531). +-define(wxLocale_Init, 3533). +-define(wxLocale_AddCatalog_1, 3534). +-define(wxLocale_AddCatalog_3, 3535). +-define(wxLocale_AddCatalogLookupPathPrefix, 3536). +-define(wxLocale_GetCanonicalName, 3537). +-define(wxLocale_GetLanguage, 3538). +-define(wxLocale_GetLanguageName, 3539). +-define(wxLocale_GetLocale, 3540). +-define(wxLocale_GetName, 3541). +-define(wxLocale_GetString_2, 3542). +-define(wxLocale_GetString_4, 3543). +-define(wxLocale_GetHeaderValue, 3544). +-define(wxLocale_GetSysName, 3545). +-define(wxLocale_GetSystemEncoding, 3546). +-define(wxLocale_GetSystemEncodingName, 3547). +-define(wxLocale_GetSystemLanguage, 3548). +-define(wxLocale_IsLoaded, 3549). +-define(wxLocale_IsOk, 3550). +-define(wxActivateEvent_GetActive, 3551). +-define(wxPopupWindow_new_2, 3553). +-define(wxPopupWindow_new_0, 3554). +-define(wxPopupWindow_destruct, 3556). +-define(wxPopupWindow_Create, 3557). +-define(wxPopupWindow_Position, 3558). +-define(wxPopupTransientWindow_new_0, 3559). +-define(wxPopupTransientWindow_new_2, 3560). +-define(wxPopupTransientWindow_destruct, 3561). +-define(wxPopupTransientWindow_Popup, 3562). +-define(wxPopupTransientWindow_Dismiss, 3563). diff --git a/lib/wx/src/wx_object.erl b/lib/wx/src/wx_object.erl index 80f8937656..249ea1cee3 100644 --- a/lib/wx/src/wx_object.erl +++ b/lib/wx/src/wx_object.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2011. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. 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 @@ -102,6 +102,7 @@ %% API -export([start/3, start/4, start_link/3, start_link/4, + stop/1, stop/3, call/2, call/3, cast/2, reply/2, @@ -215,6 +216,42 @@ gen_response({ok, Pid}) -> gen_response(Reply) -> Reply. +%% @spec (Ref::wxObject()|atom()|pid()) -> ok +%% @doc Stops a generic wx_object server with reason 'normal'. +%% Invokes terminate(Reason,State) in the server. The call waits until +%% the process is terminated. If the process does not exist, an +%% exception is raised. +stop(Ref = #wx_ref{state=Pid}) when is_pid(Pid) -> + try + gen:stop(Pid) + catch _:ExitReason -> + erlang:error({ExitReason, {?MODULE, stop, [Ref]}}) + end; +stop(Name) when is_atom(Name) orelse is_pid(Name) -> + try + gen:stop(Name) + catch _:ExitReason -> + erlang:error({ExitReason, {?MODULE, stop, [Name]}}) + end. + +%% @spec (Ref::wxObject()|atom()|pid(), Reason::term(), Timeout::timeout()) -> ok +%% @doc Stops a generic wx_object server with the given Reason. +%% Invokes terminate(Reason,State) in the server. The call waits until +%% the process is terminated. If the call times out, or if the process +%% does not exist, an exception is raised. +stop(Ref = #wx_ref{state=Pid}, Reason, Timeout) when is_pid(Pid) -> + try + gen:stop(Pid, Reason, Timeout) + catch _:ExitReason -> + erlang:error({ExitReason, {?MODULE, stop, [Ref, Reason, Timeout]}}) + end; +stop(Name, Reason, Timeout) when is_atom(Name) orelse is_pid(Name) -> + try + gen:stop(Name, Reason, Timeout) + catch _:ExitReason -> + erlang:error({ExitReason, {?MODULE, stop, [Name, Reason, Timeout]}}) + end. + %% @spec (Ref::wxObject()|atom()|pid(), Request::term()) -> term() %% @doc Make a call to a wx_object server. %% The call waits until it gets a result. diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl index b375c9d515..b127e6b71d 100644 --- a/lib/wx/test/wx_class_SUITE.erl +++ b/lib/wx/test/wx_class_SUITE.erl @@ -50,7 +50,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [calendarCtrl, treeCtrl, notebook, staticBoxSizer, clipboard, helpFrame, htmlWindow, listCtrlSort, listCtrlVirtual, - radioBox, systemSettings, taskBarIcon, toolbar]. + radioBox, systemSettings, taskBarIcon, toolbar, popup]. groups() -> []. @@ -511,3 +511,50 @@ toolbar(Config) -> wxFrame:connect(Frame, command_menu_selected, [{callback, Add}, {id, 747}]), wxFrame:show(Frame), wx_test_lib:wx_destroy(Frame,Config). + + +popup(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); +popup(Config) -> + Wx = wx:new(), + Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"), + TB = wxFrame:createToolBar(Frame), + wxToolBar:addTool(TB, 747, "PressMe", wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}]), + [{shortHelp, "Press Me"}]), + + Log = fun(#wx{id=Id, event=Ev}, Obj) -> + io:format("Got ~p from ~p~n", [Id, Ev]), + wxEvent:skip(Obj) + end, + CreatePopup = fun() -> + Pop = wxPopupTransientWindow:new(Frame), + Panel = wxPanel:new(Pop), + Sz = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(Sz, wxButton:new(Panel, 42, [{label, "A button"}])), + wxSizer:add(Sz, Txt = wxStaticText:new(Panel, 43, "Some static text")), + wxSizer:add(Sz, wxButton:new(Panel, 44, [{label, "B button"}])), + wxPanel:setSizerAndFit(Panel, Sz), + wxSizer:setSizeHints(Sz, Pop), + wxWindow:connect(Pop, command_button_clicked, [{callback, Log}]), + wxWindow:connect(Txt, left_up, [{callback, Log}]), + wxWindow:connect(Txt, middle_up, [{callback, Log}]), + wxWindow:connect(Txt, right_up, [{callback, Log}]), + wxWindow:connect(Pop, show, [{callback, Log}]), + Pos = wx_misc:getMousePosition(), + wxPopupTransientWindow:position(Pop, Pos, {-1, -1}), + wxPopupTransientWindow:popup(Pop), + Pop + end, + wxFrame:connect(Frame, command_menu_selected, [{id, 747}]), + wxFrame:show(Frame), + + Pop = CreatePopup(), + Scale = case wx_test_lib:user_available(Config) of + true -> 25; + false -> 1 + end, + receive + #wx{} -> CreatePopup() + after 200*Scale -> + wxPopupTransientWindow:dismiss(Pop) + end, + wx_test_lib:wx_destroy(Frame,Config). diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl index 076f16ba16..2c6c59bb55 100644 --- a/lib/wx/test/wx_event_SUITE.erl +++ b/lib/wx/test/wx_event_SUITE.erl @@ -542,13 +542,14 @@ handler_clean(_Config) -> ?mt(wxFrame, Frame1), wxWindow:show(Frame1), ?m([_|_], lists:sort(wx_test_lib:flush())), - ?m({stop,_}, wx_obj_test:stop(Frame1, fun(_) -> normal end)), + ?m(ok, wx_obj_test:stop(Frame1)), ?m([{terminate,normal}], lists:sort(wx_test_lib:flush())), - Frame2 = wx_obj_test:start([{init, Init}]), + Terminate = fun({Frame,_}) -> wxWindow:destroy(Frame) end, + Frame2 = wx_obj_test:start([{init, Init}, {terminate, Terminate}]), wxWindow:show(Frame2), ?m([_|_], lists:sort(wx_test_lib:flush())), - ?m({stop,_}, wx_obj_test:stop(Frame2, fun(_) -> wxWindow:destroy(Frame2), normal end)), + ?m(ok, wx_obj_test:stop(Frame2)), ?m([{terminate,normal}], lists:sort(wx_test_lib:flush())), timer:sleep(104), ?m({[],[],[]}, white_box_check_event_handlers()), diff --git a/lib/wx/test/wx_obj_test.erl b/lib/wx/test/wx_obj_test.erl index f47f2fbc46..6c648c65f8 100644 --- a/lib/wx/test/wx_obj_test.erl +++ b/lib/wx/test/wx_obj_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2013. All Rights Reserved. +%% Copyright Ericsson AB 2011-2014. 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 @@ -18,7 +18,7 @@ -module(wx_obj_test). -include_lib("wx/include/wx.hrl"). --export([start/1, stop/2]). +-export([start/1, stop/1]). %% wx_object callbacks -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3, @@ -29,8 +29,8 @@ start(Opts) -> wx_object:start_link(?MODULE, [{parent, self()}| Opts], []). -stop(Object, Fun) -> - wx_object:call(Object, {stop, Fun}). +stop(Object) -> + wx_object:stop(Object). init(Opts) -> Parent = proplists:get_value(parent, Opts), @@ -61,8 +61,6 @@ handle_event(Event, State = #state{parent=Parent}) -> handle_call(What, From, State = #state{user_state=US}) when is_function(What) -> Result = What(US), {reply, {call, Result, From}, State}; -handle_call({stop, Fun}, From, State = #state{user_state=US}) -> - {stop, Fun(US), {stop, From}, State}; handle_call(What, From, State) -> {reply, {call, What, From}, State}. @@ -79,7 +77,13 @@ handle_info(What, State = #state{parent=Pid}) -> Pid ! {info, What}, {noreply, State}. -terminate(What, #state{parent=Pid}) -> +terminate(What, #state{parent=Pid, opts=Opts, user_state=US}) -> + case proplists:get_value(terminate, Opts) of + undefined -> + ok; + Terminate -> + Terminate(US) + end, Pid ! {terminate, What}, ok. diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk index 5523c20440..ee3d247553 100644 --- a/lib/wx/vsn.mk +++ b/lib/wx/vsn.mk @@ -1 +1 @@ -WX_VSN = 1.2 +WX_VSN = 1.3 diff --git a/lib/xmerl/doc/src/motorcycles2html.erl b/lib/xmerl/doc/src/motorcycles2html.erl index dfbd19e359..45c713e1ac 100644 --- a/lib/xmerl/doc/src/motorcycles2html.erl +++ b/lib/xmerl/doc/src/motorcycles2html.erl @@ -7,7 +7,7 @@ %%%------------------------------------------------------------------- -module(motorcycles2html). --include("xmerl.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). -import(xmerl_xs, [ xslapply/2, value_of/1, select/2, built_in_rules/2 ]). @@ -57,12 +57,12 @@ template(E) -> built_in_rules(fun template/1, E). %% sorts on the bike name element, unwraps the bike information and %% inserts a line feed and indentation on each bike element. sort_by_manufacturer(L) -> - Tuples=[X1||X1={H,T} <- L], + Tuples=[X1||X1={_,_} <- L], SortedTS = lists:keysort(1,Tuples), InsertRefName_UnWrap= fun([{[Name],V}|Rest],Name,F)-> [V|F(Rest,Name,F)]; - ([{[Name],V}|Rest],PreviousName,F) -> + ([{[Name],V}|Rest],_PreviousName,F) -> [["<a name=\"",Name,"\"></>"],V|F(Rest,Name,F)]; ([],_,_) -> [] end, @@ -71,7 +71,7 @@ sort_by_manufacturer(L) -> WS = "\n ", Fun=fun([H|T],Acc,F)-> F(T,[H,WS|Acc],F); - ([],Acc,F)-> + ([],Acc,_F)-> lists:reverse([WS|Acc]) end, if length(SortedRefed) > 0 -> @@ -96,13 +96,12 @@ remove_duplicates([A|L],Acc) -> end. make_ref([]) -> []; -make_ref([H]) when atom(H) -> +make_ref([H]) when is_atom(H) -> "<ul><a href=\"#"++atom_to_list(H)++"\">"++atom_to_list(H)++"</a></ul>"; -make_ref([H]) when list(H) -> +make_ref([H]) when is_list(H) -> "<ul><a href=\"#"++H++"\">\s"++H++"</a></ul>"; -make_ref([H|T]) when atom(H) -> +make_ref([H|T]) when is_atom(H) -> ["<ul><a href=\"#"++atom_to_list(H)++"\">\s"++atom_to_list(H)++",\n</a></ul>" |make_ref(T)]; -make_ref([H|T]) when list(H) -> +make_ref([H|T]) when is_list(H) -> ["<ul><a href=\"#"++H++"\">\s"++H++",\n</a></ul>"|make_ref(T)]. - |