diff options
Diffstat (limited to 'lib')
397 files changed, 58068 insertions, 9189 deletions
diff --git a/lib/.gitignore b/lib/.gitignore index a33916b3bf..340baf5269 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -128,6 +128,7 @@ /megaco/src/text/megaco_text_parser_v1.erl /megaco/src/text/megaco_text_parser_v2.erl /megaco/src/text/megaco_text_parser_v3.erl +/megaco/doc/html/mstone1.jpg # mnesia diff --git a/lib/appmon/src/appmon_web.erl b/lib/appmon/src/appmon_web.erl index e8a8422a80..fb7144246c 100644 --- a/lib/appmon/src/appmon_web.erl +++ b/lib/appmon/src/appmon_web.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2010. 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,12 +38,6 @@ %% webtool -export([configData/0]). - -%% The following directive caters for (significantly) faster native -%% code compilation of one function in this file by the HiPE compiler -%% on register-poor architectures like the x86. --compile([{hipe,[{regalloc,graph_color}]}]). - -behaviour(gen_server). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/appmon/vsn.mk b/lib/appmon/vsn.mk index cfcb5d3eb6..0675a4eb8b 100644 --- a/lib/appmon/vsn.mk +++ b/lib/appmon/vsn.mk @@ -1,19 +1 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2010. 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% - APPMON_VSN = 2.1.12 diff --git a/lib/asn1/c_src/asn1_erl_driver.c b/lib/asn1/c_src/asn1_erl_driver.c index fd284e5800..9dd3a0fd7d 100644 --- a/lib/asn1/c_src/asn1_erl_driver.c +++ b/lib/asn1/c_src/asn1_erl_driver.c @@ -1407,7 +1407,6 @@ int decode_partial(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_l int msg_index_val; int *msg_index, *tag_index, tmp_index; int tag_seq_length; - char tag_code; /* one of ASN1_SKIPPED, ASN1_OPTIONAL, ASN1_CHOOSEN */ int wanted_tag, next_tag; int buf_end_index = in_buf_len; int ret = 0, length, old_index; @@ -1600,7 +1599,7 @@ int get_value(char *out_buf, { int len, lenoflen, indef=0, skip_len; int ret=0; - int start_index, out_index = 0; + int start_index; /* printf("get_value 1\n\r"); */ if (in_buf[*msg_index] < 0x80){ /* short definite length */ diff --git a/lib/asn1/src/asn1.appup.src b/lib/asn1/src/asn1.appup.src index 753d308684..2d11eddfbf 100644 --- a/lib/asn1/src/asn1.appup.src +++ b/lib/asn1/src/asn1.appup.src @@ -1,111 +1,9 @@ {"%VSN%", - [ - {"1.6.8", - [ - {load_module, asn1rt, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []}, - {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []}, - {load_module, asn1rt_check, soft_purge, soft_purge, []}, - {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []}, - {apply, {asn1rt_driver_handler,unload_driver,[]}} - ] - }, - {"1.6.8.1", - [ - {load_module, asn1rt, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []}, - {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []}, - {load_module, asn1rt_check, soft_purge, soft_purge, []}, - {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []}, - {apply, {asn1rt_driver_handler,unload_driver,[]}} - ] - }, - {"1.6.9", - [ - {load_module, asn1rt, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []}, - {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []}, - {load_module, asn1rt_check, soft_purge, soft_purge, []}, - {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []}, - {apply, {asn1rt_driver_handler,unload_driver,[]}} - ] - }, - {"1.6.10", - [ - {load_module, asn1rt, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []}, - {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []}, - {load_module, asn1rt_check, soft_purge, soft_purge, []}, - {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []}, - {apply, {asn1rt_driver_handler,unload_driver,[]}} - ] - } +% This version does not change anything of the runtime modules +% Only changes in compile time modules and thus no need for upgrade on target +[ ], [ - {"1.6.8", - [ - {load_module, asn1rt, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []}, - {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []}, - {load_module, asn1rt_check, soft_purge, soft_purge, []}, - {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []}, - {apply, {asn1rt_driver_handler,unload_driver,[]}} - ] - }, - {"1.6.8.1", - [ - {load_module, asn1rt, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []}, - {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []}, - {load_module, asn1rt_check, soft_purge, soft_purge, []}, - {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []}, - {apply, {asn1rt_driver_handler,unload_driver,[]}} - ] - }, - {"1.6.9", - [ - {load_module, asn1rt, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []}, - {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []}, - {load_module, asn1rt_check, soft_purge, soft_purge, []}, - {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []}, - {apply, {asn1rt_driver_handler,unload_driver,[]}} - ] - }, - {"1.6.10", - [ - {load_module, asn1rt, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []}, - {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []}, - {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []}, - {load_module, asn1rt_check, soft_purge, soft_purge, []}, - {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []}, - {apply, {asn1rt_driver_handler,unload_driver,[]}} - ] - } ]}. diff --git a/lib/asn1/src/asn1_records.hrl b/lib/asn1/src/asn1_records.hrl index 8a428b744c..59a9acb7e7 100644 --- a/lib/asn1/src/asn1_records.hrl +++ b/lib/asn1/src/asn1_records.hrl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. 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% %% %% @@ -36,7 +36,8 @@ -record(module,{pos,name,defid,tagdefault='EXPLICIT',exports={exports,[]},imports={imports,[]}, extensiondefault=empty,typeorval}). --record('SEQUENCE',{pname=false,tablecinf=false,components=[]}). +-record('ExtensionAdditionGroup',{number}). +-record('SEQUENCE',{pname=false,tablecinf=false,extaddgroup,components=[]}). -record('SET',{pname=false,sorted=false,tablecinf=false,components=[]}). -record('ComponentType',{pos,name,typespec,prop,tags,textual_order}). -record('ObjectClassFieldType',{classname,class,fieldname,type}). diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index ae681a4a78..968468cb7f 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -1674,7 +1674,7 @@ create_pdec_inc_command(ModName, % [concat_sequential(lists:reverse(Comms), % [LastComm,CompAcc])|Acc] case lists:reverse(TagCommand) of - [Atom|Comms]�when is_atom(Atom) -> + [Atom|Comms] when is_atom(Atom) -> [concat_sequential(lists:reverse(Comms), [Atom,CompAcc])|Acc]; [[Command2,Tag2]|Comms] -> diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index 54a5c7e727..1c9f2c759a 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -3227,7 +3227,7 @@ check_ptype(_S,_PTDef,Ts) when is_record(Ts,objectclass) -> % check_type(S,Type,ObjSpec={{objectclassname,_},_}) -> -% check_class(S,ObjSpec); + % check_class(S,ObjSpec); check_type(_S,Type,Ts) when is_record(Type,typedef), (Type#typedef.checked==true) -> Ts; @@ -3357,6 +3357,7 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) -> merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))}; 'REAL' -> check_real(S,Constr), + TempNewDef#newt{tag=merge_tags(Tag,?TAG_PRIMITIVE(?N_REAL))}; {'BIT STRING',NamedNumberList} -> NewL = check_bitstring(S,NamedNumberList,Constr), @@ -5522,24 +5523,9 @@ check_sequence(S,Type,Comps) -> Components2 = maybe_automatic_tags(S,Components), %% check the table constraints from here. The outermost type %% is Type, the innermost is Comps (the list of components) - NewComps = - case check_each_component(S,Type,Components2) of - NewComponents when is_list(NewComponents) -> - check_unique_sequence_tags(S,NewComponents), - NewComponents; - Ret = {NewComponents,NewEcomps} -> - TagComps = NewComponents ++ - [Comp#'ComponentType'{prop='OPTIONAL'}|| Comp <- NewEcomps], - %% extension components are like optionals when it comes to tagging - check_unique_sequence_tags(S,TagComps), - Ret; - Ret = {Root1,NewE,Root2} -> - TagComps = Root1 ++ [Comp#'ComponentType'{prop='OPTIONAL'}|| Comp <- NewE]++Root2, - %% This is not correct handling if Extension - %% contains ExtensionAdditionGroups - check_unique_sequence_tags(S,TagComps), - Ret - end, + NewComps = check_each_component2(S,Type,Components2), + check_unique_sequence_tags(S,NewComps), + %% CRelInf is the "leading attribute" information %% necessary for code generating of the look up in the %% object set table, @@ -5553,12 +5539,45 @@ check_sequence(S,Type,Comps) -> %% the involved class removed, as the class of the object %% set. CompListWithTblInf = get_tableconstraint_info(S,Type,NewComps2), - - {CRelInf,CompListWithTblInf}; + %% If encoding rule is in the PER family the Root Components + %% after the second extension mark should be encoded before + %% all extensions i.e together with the first Root components + + NewComps3 = textual_order(CompListWithTblInf), + CompListTuple = + complist_as_tuple(is_erule_per(S#state.erule),NewComps3), + {CRelInf,CompListTuple}; Dupl -> - throw({error,{asn1,{duplicate_components,Dupl}}}) + throw({error,{asn1,{duplicate_components,Dupl}}}) end. +complist_as_tuple(Per,CompList) -> + complist_as_tuple(Per,CompList,[],[],[],root). + +complist_as_tuple(Per,[#'EXTENSIONMARK'{}|T],Acc,Ext,Acc2,root) -> + complist_as_tuple(Per,T,Acc,Ext,Acc2,ext); +complist_as_tuple(Per,[#'EXTENSIONMARK'{}|T],Acc,Ext,Acc2,ext) -> + complist_as_tuple(Per,T,Acc,Ext,Acc2,root2); +complist_as_tuple(_Per,[#'EXTENSIONMARK'{}|_T],_Acc,_Ext,_Acc2,root2) -> + throw({error,{asn1,{too_many_extension_marks}}}); +complist_as_tuple(Per,[C|T],Acc,Ext,Acc2,root) -> + complist_as_tuple(Per,T,[C|Acc],Ext,Acc2,root); +complist_as_tuple(Per,[C|T],Acc,Ext,Acc2,ext) -> + complist_as_tuple(Per,T,Acc,[C|Ext],Acc2,ext); +complist_as_tuple(Per,[C|T],Acc,Ext,Acc2,root2) -> + complist_as_tuple(Per,T,Acc,Ext,[C|Acc2],root2); +complist_as_tuple(_Per,[],Acc,_Ext,_Acc2,root) -> + lists:reverse(Acc); +complist_as_tuple(_Per,[],Acc,Ext,_Acc2,ext) -> + {lists:reverse(Acc),lists:reverse(Ext)}; +%%complist_as_tuple(_Per = true,[],Acc,Ext,Acc2,root2) -> +%% {lists:reverse(Acc)++lists:reverse(Acc2),lists:reverse(Ext)}; +complist_as_tuple(_Per,[],Acc,Ext,Acc2,root2) -> + {lists:reverse(Acc),lists:reverse(Ext),lists:reverse(Acc2)}. + +is_erule_per(Erule) -> + lists:member(Erule,[per,per_bin,uper_bin]). + expand_components(S, [{'COMPONENTS OF',Type}|T]) -> CompList = expand_components2(S,get_referenced_type(S,Type#type.def)), expand_components(S,CompList) ++ expand_components(S,T); @@ -5601,13 +5620,26 @@ take_only_rootset([#'EXTENSIONMARK'{}|_T])-> take_only_rootset([H|T]) -> [H|take_only_rootset(T)]. -check_unique_sequence_tags(S,[#'ComponentType'{prop=mandatory}|Rest]) -> - check_unique_sequence_tags(S,Rest); -check_unique_sequence_tags(S,[C|Rest]) when is_record(C,'ComponentType') -> +check_unique_sequence_tags(S,CompList) -> + TagComps = case complist_as_tuple(false,CompList) of + {R1,Ext,R2} -> + R1 ++ [C#'ComponentType'{prop='OPTIONAL'}|| + C = #'ComponentType'{} <- Ext]++R2; + {R1,Ext} -> + R1 ++ [C#'ComponentType'{prop='OPTIONAL'}|| + C = #'ComponentType'{} <- Ext]; + _ -> + CompList + end, + check_unique_sequence_tags0(S,TagComps). + +check_unique_sequence_tags0(S,[#'ComponentType'{prop=mandatory}|Rest]) -> + check_unique_sequence_tags0(S,Rest); +check_unique_sequence_tags0(S,[C=#'ComponentType'{}|Rest]) -> check_unique_sequence_tags1(S,Rest,[C]);% optional or default -check_unique_sequence_tags(S,[_ExtensionMarker|Rest]) -> - check_unique_sequence_tags(S,Rest); -check_unique_sequence_tags(_S,[]) -> +check_unique_sequence_tags0(S,[_ExtensionMarker|Rest]) -> + check_unique_sequence_tags0(S,Rest); +check_unique_sequence_tags0(_S,[]) -> true. check_unique_sequence_tags1(S,[C|Rest],Acc) when is_record(C,'ComponentType') -> @@ -5807,8 +5839,10 @@ get_least_tag(TagList) -> %% adds the textual order to the components to keep right order of %% components in the asn1-value. textual_order(Cs) -> - Fun = fun(C,Index) -> - {C#'ComponentType'{textual_order=Index},Index+1} + Fun = fun(C=#'ComponentType'{},Index) -> + {C#'ComponentType'{textual_order=Index},Index+1}; + (Other,Index) -> + {Other,Index} end, {NewCs,_} = textual_order(Cs,Fun,1), NewCs. @@ -5879,7 +5913,6 @@ check_selectiontype2(S,Name,TypeDef) -> error({type,Msg,S}) end. - check_restrictedstring(_S,_Def,_Constr) -> ok. @@ -5899,16 +5932,16 @@ check_choice(S,Type,Components) when is_list(Components) -> [] -> %% sort_canonical(Components), Components2 = maybe_automatic_tags(S,Components), - %NewComps = - case check_each_alternative(S,Type,Components2) of - {NewComponents,NewEcomps} -> - check_unique_tags(S,NewComponents ++ NewEcomps), - {NewComponents,NewEcomps}; - NewComponents -> - check_unique_tags(S,NewComponents), - NewComponents - end; - + NewComps = check_each_alternative2(S,Type,Components2), + %% ExtensionAdditionGroup markers i.e '[[' ']]' are not + %% significant for encoding/decoding a choice + %% therefore we remove them here + NewComps2 = lists:filter(fun(#'ExtensionAdditionGroup'{}) -> false; + ('ExtensionAdditionGroupEnd') -> false; + (_) -> true + end,NewComps), + check_unique_tags(S,NewComps2), + complist_as_tuple(is_erule_per(S#state.erule),NewComps2); Dupl -> throw({error,{asn1,{duplicate_choice_alternatives,Dupl}}}) end; @@ -6036,12 +6069,17 @@ check_unique2([_|T],Pos,Acc) -> check_unique2([],_,Acc) -> lists:reverse(Acc). -check_each_component(S,Type,Components) -> - check_each_component(S,Type,Components,[],[],[],root1). -check_each_component(S = #state{abscomppath=Path,recordtopname=TopName},Type, - [C|Ct],Acc,Extacc,Acc2,Ext) when is_record(C,'ComponentType') -> - #'ComponentType'{name=Cname,typespec=Ts,prop=Prop} = C, +%% Replaces check_each_component and does the same work except that +%% it keeps the complist as a flat list and does not create a tuple with root and +%% extensions separated +check_each_component2(S,Type,Components) -> + check_each_component2(S,Type,Components,[]). + +check_each_component2(S = #state{abscomppath=Path,recordtopname=TopName}, + Type, + [C = #'ComponentType'{name=Cname,typespec=Ts,prop=Prop}|Ct], + Acc) -> NewAbsCPath = case Ts#type.def of #'Externaltypereference'{} -> []; @@ -6058,75 +6096,48 @@ check_each_component(S = #state{abscomppath=Path,recordtopname=TopName},Type, DefaultValue -> {'DEFAULT',DefaultValue} end, NewC = C#'ComponentType'{typespec=CheckedTs,prop=NewProp,tags=NewTags}, - case Ext of - root1 -> - check_each_component(S,Type,Ct,[NewC|Acc],Extacc,Acc2,Ext); - ext -> - check_each_component(S,Type,Ct,Acc,[NewC|Extacc],Acc2,Ext); - root2 -> - check_each_component(S,Type,Ct,Acc,Extacc,[NewC|Acc2],Ext) - end; -check_each_component(S,Type,[_|Ct],Acc,Extacc,Acc2,root1) -> % skip 'EXTENSIONMARK' - check_each_component(S,Type,Ct,Acc,Extacc,Acc2,ext); -check_each_component(S,Type,[_|Ct],Acc,Extacc,Acc2,ext) -> % skip 'EXTENSIONMARK' - check_each_component(S,Type,Ct,Acc,Extacc,Acc2,root2); -check_each_component(_S,_,[_C|_Ct],_,_,_,root2) -> % 'EXTENSIONMARK' - throw({error,{asn1,{too_many_extension_marks}}}); -check_each_component(_S,_,[],Acc,Extacc,_,ext) -> - {lists:reverse(Acc),lists:reverse(Extacc)}; -check_each_component(_S,_,[],Acc1,ExtAcc,Acc2,root2) -> - {lists:reverse(Acc1),lists:reverse(ExtAcc),lists:reverse(Acc2)}; -check_each_component(_S,_,[],Acc,_,_,root1) -> + check_each_component2(S,Type,Ct,[NewC|Acc]); + +check_each_component2(S,Type,[OtherMarker|Ct],Acc) -> + %% let 'EXTENSIONMARK' and 'ExtensionAdditionGroup' markers pass through as is + check_each_component2(S,Type,Ct,[OtherMarker|Acc]); +check_each_component2(_S,_,[],Acc) -> lists:reverse(Acc). -%% check_each_alternative(S,Type,{Rlist,ExtList}) -> + +%% check_each_alternative2(S,Type,{Rlist,ExtList}) -> %% {check_each_alternative(S,Type,Rlist), %% check_each_alternative(S,Type,ExtList)}; -check_each_alternative(S,Type,[C|Ct]) -> - check_each_alternative(S,Type,[C|Ct],[],[],noext). +check_each_alternative2(S,Type,[C|Ct]) -> + check_each_alternative2(S,Type,[C|Ct],[]). -check_each_alternative(S=#state{abscomppath=Path,recordtopname=TopName},Type,[C|Ct], - Acc,Extacc,Ext) when is_record(C,'ComponentType') -> - #'ComponentType'{name=Cname,typespec=Ts,prop=_Prop} = C, +check_each_alternative2(S=#state{abscomppath=Path,recordtopname=TopName}, + Type, + [C = #'ComponentType'{name=Cname,typespec=Ts}|Ct], + Acc) -> NewAbsCPath = case Ts#type.def of #'Externaltypereference'{} -> []; _ -> [Cname|Path] end, - NewState = - S#state{abscomppath=NewAbsCPath,recordtopname=[Cname|TopName]}, - CheckedTs = check_type(NewState,Type,Ts), + CheckedTs = check_type(S#state{abscomppath=NewAbsCPath, + recordtopname=[Cname|TopName]},Type,Ts), NewTags = get_taglist(S,CheckedTs), + NewC = C#'ComponentType'{typespec=CheckedTs,tags=NewTags}, - case Ext of - noext -> - check_each_alternative(S,Type,Ct,[NewC|Acc],Extacc,Ext); - ext -> - check_each_alternative(S,Type,Ct,Acc,[NewC|Extacc],Ext) - end; + check_each_alternative2(S,Type,Ct,[NewC|Acc]); -check_each_alternative(S,Type,[_|Ct],Acc,Extacc,noext) -> % skip 'EXTENSIONMARK' - check_each_alternative(S,Type,Ct,Acc,Extacc,ext); -check_each_alternative(_S,_,[_C|_Ct],_,_,ext) -> % skip 'EXTENSIONMARK' - throw({error,{asn1,{too_many_extension_marks}}}); -check_each_alternative(_S,_,[],Acc,Extacc,ext) -> - {lists:reverse(Acc),lists:reverse(Extacc)}; -check_each_alternative(_S,_,[],Acc,_,noext) -> +check_each_alternative2(S,Type,[OtherMarker|Ct],Acc) -> + %% let 'EXTENSIONMARK' and 'ExtensionAdditionGroup' markers pass through as is + check_each_alternative2(S,Type,Ct,[OtherMarker|Acc]); +check_each_alternative2(_S,_,[],Acc) -> lists:reverse(Acc). + %% componentrelation_leadingattr/2 searches the structure for table %% constraints, if any is found componentrelation_leadingattr/5 is %% called. componentrelation_leadingattr(S,CompList) -> - Cs = - case CompList of - {Comp1, EComps, Comp2} -> - Comp1++EComps++Comp2; - {Components,EComponents} when is_list(Components) -> - Components ++ EComponents; - CompList when is_list(CompList) -> - CompList - end, %% get_simple_table_if_used/2 should find out whether there are any %% component relation constraints in the entire tree of Cs1 that @@ -6135,12 +6146,22 @@ componentrelation_leadingattr(S,CompList) -> %% componentrelation_leadingattr/6. The step when the leading %% attribute and the syntax tree is modified to support the code %% generating. - case get_simple_table_if_used(S,Cs) of + case get_simple_table_if_used(S,CompList) of [] -> {false,CompList}; - STList -> - componentrelation_leadingattr(S,Cs,Cs,STList,[],[]) + _ -> + componentrelation_leadingattr(S,CompList,CompList,[],[]) end. + +%%FIXME expand_ExtAddGroups([C#'ExtensionAdditionGroup'{components=ExtAdds}|T], +%% CurrPos,PosAcc,CompAcc) -> +%% expand_ExtAddGroups(T,CurrPos+ L = lenght(ExtAdds),[{CurrPos,L}|PosAcc],ExtAdds++CompAcc); +%% expand_ExtAddGroups([C|T],CurrPos,PosAcc,CompAcc) -> +%% expand_ExtAddGroups(T,CurrPos+ 1,PosAcc,[C|CompAcc]); +%% expand_ExtAddGroups([],_CurrPos,PosAcc,CompAcc) -> +%% {lists:reverse(PosAcc),lists:reverse(CompAcc)}. + + %% componentrelation_leadingattr/6 when all components are searched %% the new modified components are returned together with the "leading %% attribute" information, which later is stored in the tablecinf @@ -6150,11 +6171,12 @@ componentrelation_leadingattr(S,CompList) -> %% is used in code generating phase too, to recognice the proper %% components for "open type" encoding and to propagate the result of %% the object set lookup when needed. -componentrelation_leadingattr(_,[],_CompList,_,[],NewCompList) -> +componentrelation_leadingattr(_,[],_CompList,[],NewCompList) -> {false,lists:reverse(NewCompList)}; -componentrelation_leadingattr(_,[],_CompList,_,LeadingAttr,NewCompList) -> +componentrelation_leadingattr(_,[],_CompList,LeadingAttr,NewCompList) -> {lists:last(LeadingAttr),lists:reverse(NewCompList)}; %send all info in Ts later -componentrelation_leadingattr(S,[C|Cs],CompList,STList,Acc,CompAcc) -> + +componentrelation_leadingattr(S,[C= #'ComponentType'{}|Cs],CompList,Acc,CompAcc) -> {LAAcc,NewC} = case catch componentrelation1(S,C#'ComponentType'.typespec, [C#'ComponentType'.name]) of @@ -6205,7 +6227,7 @@ componentrelation_leadingattr(S,[C|Cs],CompList,STList,Acc,CompAcc) -> %% no constraint was found {[],C} end, - componentrelation_leadingattr(S,Cs,CompList,STList,LAAcc++Acc, + componentrelation_leadingattr(S,Cs,CompList,LAAcc++Acc, [NewC|CompAcc]). object_set_mod_name(_S,ObjSet) when is_atom(ObjSet) -> @@ -6228,11 +6250,9 @@ object_set_mod_name(S,#'Externaltypereference'{module=M,type=T}) -> %% generation of the look up functionality in the object set table are %% returned. get_simple_table_if_used(S,Cs) -> - CNames = lists:map(fun(#'ComponentType'{name=Name}) -> Name; - (_) -> [] %% in case of extension marks - end, - Cs), - RefedSimpleTable=any_component_relation(S,Cs,CNames,[],[]), + CNames = [Name||#'ComponentType'{name=Name}<-Cs], + JustComponents = [C || C = #'ComponentType'{}<-Cs], + RefedSimpleTable=any_component_relation(S,JustComponents,CNames,[],[]), get_simple_table_info(S,Cs,remove_doubles(RefedSimpleTable)). remove_doubles(L) -> @@ -6336,9 +6356,7 @@ simple_table_info(S,Type,_) -> %% beginning of the search. CNames holds the names of all components %% of the start level, this info is used if an outermost at-notation %% is found to check the validity of the at-list. -any_component_relation(S,[C|Cs],CNames,NamePath,Acc) -> - CName = C#'ComponentType'.name, - Type = C#'ComponentType'.typespec, +any_component_relation(S,[#'ComponentType'{name=CName,typespec=Type}|Cs],CNames,NamePath,Acc) -> CRelPath = case constraint_member(componentrelation,Type#type.constraint) of %% [{componentrelation,_,AtNotation}] -> @@ -6358,9 +6376,9 @@ any_component_relation(S,[C|Cs],CNames,NamePath,Acc) -> case {Type#type.inlined, asn1ct_gen:type(asn1ct_gen:get_inner(Type#type.def))} of {no,{constructed,bif}} -> + {InnerCs,NewNamePath} = case get_components(Type#type.def) of - {IC1,_IC2} -> {IC1 ++ IC1,[CName|NamePath]}; T when is_record(T,type) -> {T,NamePath}; IC -> {IC,[CName|NamePath]} end, @@ -6384,11 +6402,7 @@ any_component_relation(S,Type,CNames,NamePath,Acc) when is_record(Type,type) -> case {Type#type.inlined, asn1ct_gen:type(asn1ct_gen:get_inner(Type#type.def))} of {no,{constructed,bif}} -> - InnerCs = - case get_components(Type#type.def) of - {IC1,_IC2} -> IC1 ++ IC1; - IC -> IC - end, + InnerCs = get_components(Type#type.def), any_component_relation(S,InnerCs,CNames,NamePath,[]); _ -> [] @@ -6456,11 +6470,11 @@ get_components(Def) -> get_components(any,Def). get_components(_,#'SEQUENCE'{components=Cs}) -> - Cs; + tuple2complist(Cs); get_components(_,#'SET'{components=Cs}) -> - Cs; + tuple2complist(Cs); get_components(_,{'CHOICE',Cs}) -> - Cs; + tuple2complist(Cs); %do not step in inlined structures get_components(any,{'SEQUENCE OF',T = #type{def=_Def,inlined=no}}) -> % get_components(any,Def); @@ -6471,6 +6485,13 @@ get_components(any,{'SET OF',T = #type{def=_Def,inlined=no}}) -> get_components(_,_) -> []. +tuple2complist({R,E}) -> + R ++ E; +tuple2complist({R1,E,R2}) -> + R1 ++ E ++ R2; +tuple2complist(List) when is_list(List) -> + List. + get_choice_components(_S,{'CHOICE',Components}) when is_list(Components)-> Components; get_choice_components(_S,{'CHOICE',{C1,C2}}) when is_list(C1),is_list(C2) -> @@ -6731,8 +6752,7 @@ get_tableconstraint_info(S,Type,CheckedTs) -> get_tableconstraint_info(_S,_Type,[],Acc) -> lists:reverse(Acc); -get_tableconstraint_info(S,Type,[C|Cs],Acc) -> - CheckedTs = C#'ComponentType'.typespec, +get_tableconstraint_info(S,Type,[C=#'ComponentType'{typespec=CheckedTs}|Cs],Acc) -> AccComp = case CheckedTs#type.def of %% ObjectClassFieldType @@ -6768,7 +6788,9 @@ get_tableconstraint_info(S,Type,[C|Cs],Acc) -> _ -> C end, - get_tableconstraint_info(S,Type,Cs,[AccComp|Acc]). + get_tableconstraint_info(S,Type,Cs,[AccComp|Acc]); +get_tableconstraint_info(S,Type,[C|Cs],Acc) -> + get_tableconstraint_info(S,Type,Cs,[C|Acc]). get_referenced_fieldname([{_,FirstFieldname}]) -> {FirstFieldname,[]}; @@ -6850,7 +6872,9 @@ get_taglist(S,Type) when is_record(Type,type) -> [asn1ct_gen:def_to_tag(Tag)] end; get_taglist(S,{'CHOICE',{Rc,Ec}}) -> - get_taglist(S,{'CHOICE',Rc ++ Ec}); + get_taglist1(S,Rc ++ Ec); +get_taglist(S,{'CHOICE',{R1,E,R2}}) -> + get_taglist1(S,R1 ++ E ++ R2); get_taglist(S,{'CHOICE',Components}) -> get_taglist1(S,Components); %% ObjectClassFieldType OTP-4390 diff --git a/lib/asn1/src/asn1ct_constructed_ber.erl b/lib/asn1/src/asn1ct_constructed_ber.erl index 51a241ffbd..77b78dcac7 100644 --- a/lib/asn1/src/asn1ct_constructed_ber.erl +++ b/lib/asn1/src/asn1ct_constructed_ber.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. 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% %% %% @@ -71,13 +71,15 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) -> ok end, - {SeqOrSet,TableConsInfo,CompList} = + {SeqOrSet,TableConsInfo,CompList0} = case D#type.def of #'SEQUENCE'{tablecinf=TCI,components=CL} -> {'SEQUENCE',TCI,CL}; #'SET'{tablecinf=TCI,components=CL} -> {'SET',TCI,CL} end, + %% filter away extensionAdditiongroup markers + CompList = filter_complist(CompList0), Ext = extensible(CompList), CompList1 = case CompList of {Rl1,El,Rl2} -> Rl1 ++ El ++ Rl2; @@ -189,7 +191,11 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) -> gen_decode_sequence(Erules,Typename,D) when is_record(D,type) -> asn1ct_name:start(), asn1ct_name:new(tag), - #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def, + #'SEQUENCE'{tablecinf=TableConsInfo,components=CList0} = D#type.def, + + %% filter away extensionAdditiongroup markers + CList = filter_complist(CList0), + Ext = extensible(CList), {CompList,CompList2} = case CList of {Rl1,El,Rl2} -> {Rl1 ++ El ++ Rl2,CList}; @@ -369,7 +375,10 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) -> asn1ct_name:clear(), asn1ct_name:new(term), asn1ct_name:new(tag), - #'SET'{components=TCompList} = D#type.def, + #'SET'{components=TCompList0} = D#type.def, + + %% filter away extensionAdditiongroup markers + TCompList = filter_complist(TCompList0), Ext = extensible(TCompList), ToOptional = fun(mandatory) -> 'OPTIONAL'; @@ -1473,6 +1482,22 @@ extensible({RootList,ExtList}) -> {ext,length(RootList)+1,length(ExtList)}; extensible({_Rl1,_ExtL,_Rl2}) -> extensible. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% filter away ExtensionAdditionGroup start and end marks since these +%% have no significance for the BER encoding +%% +filter_complist(CompList) when is_list(CompList) -> + lists:filter(fun(#'ExtensionAdditionGroup'{}) -> + false; + ('ExtensionAdditionGroupEnd') -> + false; + (_) -> + true + end, CompList); +filter_complist({Root,Ext}) -> + {Root,filter_complist(Ext)}; +filter_complist({Root1,Ext,Root2}) -> + {Root1,filter_complist(Ext),Root2}. print_attribute_comment(InnerType,Pos,Prop) -> CommentLine = "%%-------------------------------------------------", diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index 2a1c0ebc6b..df430c4f88 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. 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% %% %% @@ -46,13 +46,24 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) -> asn1ct_name:start(), asn1ct_name:new(term), asn1ct_name:new(bytes), - {CompList,TableConsInfo} = + {ExtAddGroup,TmpCompList,TableConsInfo} = case D#type.def of - #'SEQUENCE'{tablecinf=TCI,components=CL} -> - {CL,TCI}; + #'SEQUENCE'{tablecinf=TCI,components=CL,extaddgroup=ExtAddGroup0} -> + {ExtAddGroup0,CL,TCI}; #'SET'{tablecinf=TCI,components=CL} -> - {CL,TCI} + {undefined,CL,TCI} end, + + CompList = case ExtAddGroup of + undefined -> + TmpCompList; + _ when is_integer(ExtAddGroup) -> + %% This is a fake SEQUENCE representing an ExtensionAdditionGroup + %% Reset the textual order so we get the right + %% index of the components + [Comp#'ComponentType'{textual_order=undefined}|| + Comp<-TmpCompList] + end, case Typename of ['EXTERNAL'] -> emit({{var,asn1ct_name:next(val)}, @@ -78,7 +89,7 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) -> ",",{var,asn1ct_name:curr(val)},"),",nl}) end, asn1ct_name:new(val), - Ext = extensible(CompList), + Ext = extensible_enc(CompList), case Ext of {ext,_,NumExt} when NumExt > 0 -> emit(["Extensions = ?RT_PER:fixextensions(",{asis,Ext}, @@ -188,9 +199,10 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) -> #'SEQUENCE'{tablecinf=TCI,components=CL} -> {add_textual_order(CL),TCI}; #'SET'{tablecinf=TCI,components=CL} -> - {add_textual_order(CL),TCI} +%% {add_textual_order(CL),TCI} + {CL,TCI} % the textual order is already taken care of end, - Ext = extensible(CompList), + Ext = extensible_dec(CompList), MaybeComma1 = case Ext of {ext,_Pos,_NumExt} -> gen_dec_extension_value("Bytes"), @@ -243,8 +255,9 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) -> {false,false,false} end end, + NewCompList = wrap_compList(CompList), {AccTerm,AccBytes} = - gen_dec_components_call(Erules,Typename,CompList,MaybeComma2,DecObjInf,Ext,length(Optionals)), + gen_dec_components_call(Erules,Typename,NewCompList,MaybeComma2,DecObjInf,Ext,length(Optionals)), case asn1ct_name:all(term) of [] -> emit(MaybeComma2); % no components at all _ -> emit({com,nl}) @@ -284,7 +297,10 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) -> emit(" {ASN11994Format,"); _ -> emit(["{{'",RecordName,"'"]), - mkvlist(textual_order(CompList,asn1ct_name:all(term))), + %% CompList is used here because we don't want + %% ExtensionAdditionGroups to be wrapped in SEQUENCES when + %% we are ordering the fields according to textual order + mkvlist(textual_order(to_encoding_order(CompList),asn1ct_name:all(term))), emit("},") end, emit({{var,asn1ct_name:curr(bytes)},"}"}), @@ -293,17 +309,12 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) -> textual_order([#'ComponentType'{textual_order=undefined}|_],TermList) -> TermList; textual_order(CompList,TermList) when is_list(CompList) -> - TermTuple = list_to_tuple(TermList), %% ['Term1','Term2',...'TermN'] - %% OrderList is ordered by canonical order of tags - TmpTuple = TermTuple, - OrderList = [Ix||#'ComponentType'{textual_order=Ix} <- CompList], - Fun = fun(X,{Tpl,Ix}) -> - - {setelement(X,Tpl,element(Ix,TermTuple)),Ix+1} - end, - {Ret,_} = lists:foldl(Fun,{TmpTuple,1},OrderList), -%% io:format("TermTuple: ~p~nOrderList: ~p~nRet: ~p~n",[TermTuple,OrderList,tuple_to_list(Ret)]), - tuple_to_list(Ret); + OrderList = [Ix||#'ComponentType'{textual_order=Ix} <- CompList], + [Term||{_,Term}<- + lists:sort(lists:zip(OrderList, + lists:sublist(TermList,length(OrderList))))]; + %% sublist is just because Termlist can sometimes be longer than + %% OrderList, which it really shouldn't textual_order({Root,Ext},TermList) -> textual_order(Root ++ Ext,TermList); textual_order({Root1,Ext,Root2},TermList) -> @@ -379,7 +390,7 @@ emit_opt_or_mand_check(Val,Term) -> gen_encode_choice(Erule,Typename,D) when is_record(D,type) -> {'CHOICE',CompList} = D#type.def, emit({"[",nl}), - Ext = extensible(CompList), + Ext = extensible_enc(CompList), gen_enc_choice(Erule,Typename,CompList,Ext), emit({nl,"].",nl}). @@ -388,7 +399,7 @@ gen_decode_choice(Erules,Typename,D) when is_record(D,type) -> asn1ct_name:clear(), asn1ct_name:new(bytes), {'CHOICE',CompList} = D#type.def, - Ext = extensible(CompList), + Ext = extensible_enc(CompList), gen_dec_choice(Erules,Typename,CompList,Ext), emit({".",nl}). @@ -558,12 +569,32 @@ mkvlist2([H|T]) -> mkvlist2([]) -> true. -extensible(CompList) when is_list(CompList) -> + +extensible_dec(CompList) when is_list(CompList) -> + noext; +extensible_dec({RootList,ExtList}) -> + {ext,length(RootList)+1,ext_length(ExtList)}; +extensible_dec({Rl1,Ext,Rl2}) -> + {ext,length(Rl1)+length(Rl2)+1,ext_length(Ext)}. + +extensible_enc(CompList) when is_list(CompList) -> noext; -extensible({RootList,ExtList}) -> - {ext,length(RootList)+1,length(ExtList)}; -extensible({Rl1,Ext,_Rl2}) -> - {ext,length(Rl1)+1,length(Ext)}. +extensible_enc({RootList,ExtList}) -> + {ext,length(RootList)+1,ext_length(ExtList)}; +extensible_enc({Rl1,Ext,_Rl2}) -> + {ext,length(Rl1)+1,ext_length(Ext)}. + +ext_length(ExtList) -> ext_length(ExtList,normal,0). +ext_length([{'ExtensionAdditionGroup',_Num}|T],_,Acc)-> + ext_length(T,group,Acc); +ext_length(['ExtensionAdditionGroupEnd'|T],group,Acc) -> + ext_length(T,normal,Acc+1); +ext_length([#'ComponentType'{}|T],State=group,Acc) -> + ext_length(T,State,Acc); +ext_length([#'ComponentType'{}|T],State=normal,Acc) -> + ext_length(T,State,Acc+1); +ext_length([],_,Acc) -> + Acc. gen_dec_extension_value(_) -> emit({"{Ext,",{next,bytes},"} = ?RT_PER:getext(",{curr,bytes},")"}), @@ -574,7 +605,11 @@ gen_dec_extension_value(_) -> %% there are optional components, start with 2 because first element %% is the record name -optionals({L1,_Ext,L2}) -> optionals(L1++L2,[],2); +optionals({L1,Ext,L2}) -> + Opt1 = optionals(L1,[],2), + ExtComps = length([C||C = #'ComponentType'{}<-Ext]), + Opt2 = optionals(L2,[],2+length(L1)+ExtComps), + Opt1 ++ Opt2; optionals({L,_Ext}) -> optionals(L,[],2); optionals(L) -> optionals(L,[],2). @@ -617,6 +652,13 @@ get_optionality_pos(TextPos,OptTable) -> no_num end. +to_encoding_order(Cs) when is_list(Cs) -> + Cs; +to_encoding_order(Cs = {_Root,_Ext}) -> + Cs; +to_encoding_order({R1,Ext,R2}) -> + {R1++R2,Ext}. + add_textual_order(Cs) when is_list(Cs) -> {NewCs,_} = add_textual_order1(Cs,1), NewCs; @@ -629,26 +671,20 @@ add_textual_order({R1,Ext,R2}) -> {NewExt,Num2} = add_textual_order1(Ext,Num1), {NewR2,_} = add_textual_order1(R2,Num2), {NewR1,NewExt,NewR2}. -add_textual_order1(Cs=[#'ComponentType'{textual_order=Int}|_],I) - when is_integer(Int) -> - {Cs,I}; +%%add_textual_order1(Cs=[#'ComponentType'{textual_order=Int}|_],I) +%% when is_integer(Int) -> +%% {Cs,I}; add_textual_order1(Cs,NumIn) -> - lists:mapfoldl(fun(C,Num) -> + lists:mapfoldl(fun(C=#'ComponentType'{},Num) -> {C#'ComponentType'{textual_order=Num}, - Num+1} + Num+1}; + (OtherMarker,Num) -> + {OtherMarker,Num} end, NumIn,Cs). gen_enc_components_call(Erule,TopType,{Root1,ExtList,Root2},MaybeComma,DynamicEnc,Ext) -> - Rpos = gen_enc_components_call1(Erule,TopType,Root1,1,MaybeComma,DynamicEnc,noext), - case Ext of - {ext,_,ExtNum} when ExtNum > 0 -> - emit([nl, - ",Extensions",nl]); - _ -> true - end, - Rpos2 = gen_enc_components_call1(Erule,TopType,ExtList,Rpos,MaybeComma,DynamicEnc,Ext), - gen_enc_components_call1(Erule,TopType,Root2,Rpos2,MaybeComma,DynamicEnc,noext); + gen_enc_components_call(Erule,TopType,{Root1++Root2,ExtList},MaybeComma,DynamicEnc,Ext); gen_enc_components_call(Erule,TopType,{CompList,ExtList},MaybeComma,DynamicEnc,Ext) -> %% The type has extensionmarker Rpos = gen_enc_components_call1(Erule,TopType,CompList,1,MaybeComma,DynamicEnc,noext), @@ -659,7 +695,8 @@ gen_enc_components_call(Erule,TopType,{CompList,ExtList},MaybeComma,DynamicEnc,E _ -> true end, %handle extensions - gen_enc_components_call1(Erule,TopType,ExtList,Rpos,MaybeComma,DynamicEnc,Ext); + NewExtList = wrap_extensionAdditionGroups(ExtList), + gen_enc_components_call1(Erule,TopType,NewExtList,Rpos,MaybeComma,DynamicEnc,Ext); gen_enc_components_call(Erule,TopType, CompList, MaybeComma, DynamicEnc, Ext) -> %% The type has no extensionmarker gen_enc_components_call1(Erule,TopType,CompList,1,MaybeComma,DynamicEnc,Ext). @@ -719,6 +756,26 @@ gen_enc_component_default(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext,DefaultVal NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)), gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext), emit({nl,"end"}). + +gen_enc_component_optional(Erule,TopType,Cname, + Type=#type{def=#'SEQUENCE'{ + extaddgroup=Number, + components=ExtGroupCompList}}, + Pos,DynamicEnc,Ext) when is_integer(Number) -> + emit({nl,"begin",nl}), + + asn1ct_name:new(tmpval), + ExtAddGroupTypeName = asn1ct_gen:list2name([Cname|TopType]), + emit({{curr,tmpval}," = {'",ExtAddGroupTypeName,"', "}), + ExtNames = [ExtName||#'ComponentType'{name=ExtName}<-ExtGroupCompList], + Elements = make_elements(Pos+1,"Val1",ExtNames), + emit({Elements,"},"}), + InnerType = asn1ct_gen:get_inner(Type#type.def), + emit({nl,"%% attribute number ",Pos," with type ", + InnerType,nl}), + NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)), + gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext), + emit({nl,"end"}); gen_enc_component_optional(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext) -> Element = make_element(Pos+1,"Val1",Cname), emit({"case ",Element," of",nl}), @@ -834,29 +891,7 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) -> _ -> true end. gen_dec_components_call(Erule,TopType,{Root1,ExtList,Root2},MaybeComma,DecInfObj,Ext,NumberOfOptionals) -> - %% The type has extensionmarker - OptTable = create_optionality_table(Root1 ++ Root2), - {Rpos,AccTerm,AccBytes} = - gen_dec_components_call1(Erule,TopType, Root1, 1, OptTable, - MaybeComma,DecInfObj, noext,[],[], - NumberOfOptionals), - emit([",",nl,"{Extensions,",{next,bytes},"} = "]), - emit(["?RT_PER:getextension(Ext,",{curr,bytes},"),",nl]), - asn1ct_name:new(bytes), - {Epos,AccTermE,AccBytesE} = - gen_dec_components_call1(Erule,TopType,ExtList,Rpos, OptTable, "", - DecInfObj,Ext,[],[],NumberOfOptionals), - case ExtList of - [] -> true; - _ -> emit([",",nl]) - end, - emit([{next,bytes},"= ?RT_PER:skipextensions(",{curr,bytes},",", - length(ExtList)+1,",Extensions),",nl]), - asn1ct_name:new(bytes), - {_RPos2,AccTerm2,AccBytes2} = - gen_dec_components_call1(Erule,TopType,Root2,Epos,OptTable, - "",DecInfObj,noext,[],[],NumberOfOptionals), - {AccTerm++AccTermE++AccTerm2,AccBytes++AccBytesE++AccBytes2}; + gen_dec_components_call(Erule,TopType,{Root1++Root2,ExtList},MaybeComma,DecInfObj,Ext,NumberOfOptionals); gen_dec_components_call(Erule,TopType,{CompList,ExtList},MaybeComma, DecInfObj,Ext,NumberOfOptionals) -> %% The type has extensionmarker @@ -868,8 +903,9 @@ gen_dec_components_call(Erule,TopType,{CompList,ExtList},MaybeComma, emit([",",nl,"{Extensions,",{next,bytes},"} = "]), emit(["?RT_PER:getextension(Ext,",{curr,bytes},"),",nl]), asn1ct_name:new(bytes), + NewExtList = wrap_extensionAdditionGroups(ExtList), {_Epos,AccTermE,AccBytesE} = - gen_dec_components_call1(Erule,TopType,ExtList,Rpos, OptTable, + gen_dec_components_call1(Erule,TopType,NewExtList,Rpos, OptTable, "",DecInfObj,Ext,[],[],NumberOfOptionals), case ExtList of [] -> true; @@ -942,8 +978,18 @@ gen_dec_components_call1(Erule,TopType, asn1ct_name:new(tmpterm), emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "}); _ -> - asn1ct_name:new(term), - emit({"{",{curr,term},",",{next,bytes},"} = "}) + case Type of + #type{def=#'SEQUENCE'{ + extaddgroup=Number1, + components=ExtGroupCompList1}} when is_integer(Number1)-> + emit({"{{_,"}), + emit_extaddgroupTerms(term,ExtGroupCompList1), + emit({"}"}); + _ -> + asn1ct_name:new(term), + emit({"{",{curr,term}}) + end, + emit({",",{next,bytes},"} = "}) end, case {Ext,Prop,is_optimized(Erule)} of @@ -967,11 +1013,24 @@ gen_dec_components_call1(Erule,TopType, {noext,mandatory} -> true; % generate nothing {noext,_} -> emit([";",nl,"0 ->"]), - gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext), + emit(["{"]), + gen_dec_component_no_val(Ext,Prop), + emit({",",{curr,bytes},"}",nl}), emit([nl,"end"]); _ -> emit([";",nl,"_ ->",nl]), - gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext), + emit(["{"]), + case Type of + #type{def=#'SEQUENCE'{ + extaddgroup=Number2, + components=ExtGroupCompList2}} when is_integer(Number2)-> + emit({"{extAddGroup,"}), + gen_dec_extaddGroup_no_val(Ext,ExtGroupCompList2), + emit({"}"}); + _ -> + gen_dec_component_no_val(Ext,Prop) + end, + emit({",",{curr,bytes},"}",nl}), emit([nl,"end"]) end, asn1ct_name:new(bytes), @@ -988,13 +1047,22 @@ gen_dec_components_call1(Erule,TopType, gen_dec_components_call1(_,_TopType,[],Pos,_OptTable,_,_,_,AccTerm,AccBytes,_NumberOfOptionals) -> {Pos,AccTerm,AccBytes}. - -gen_dec_component_no_val(_,_,_,{'DEFAULT',DefVal},_,_) -> - emit(["{",{asis,DefVal},",",{curr,bytes},"}",nl]); -gen_dec_component_no_val(_,_,_,'OPTIONAL',_,_) -> - emit({"{asn1_NOVALUE,",{curr,bytes},"}",nl}); -gen_dec_component_no_val(_,_,_,mandatory,_,{ext,_,_}) -> - emit({"{asn1_NOVALUE,",{curr,bytes},"}",nl}). +gen_dec_extaddGroup_no_val(Ext,[#'ComponentType'{prop=Prop}])-> + gen_dec_component_no_val(Ext,Prop), + ok; +gen_dec_extaddGroup_no_val(Ext,[#'ComponentType'{prop=Prop}|Rest])-> + gen_dec_component_no_val(Ext,Prop), + emit({","}), + gen_dec_extaddGroup_no_val(Ext,Rest); +gen_dec_extaddGroup_no_val(_, []) -> + ok. + +gen_dec_component_no_val(_,{'DEFAULT',DefVal}) -> + emit([{asis,DefVal}]); +gen_dec_component_no_val(_,'OPTIONAL') -> + emit({"asn1_NOVALUE"}); +gen_dec_component_no_val({ext,_,_},mandatory) -> + emit({"asn1_NOVALUE"}). gen_dec_line(Erule,TopType,Cname,Type,Pos,DecInfObj,Ext,Prop) -> @@ -1192,6 +1260,14 @@ gen_enc_choice_tag({C1,C2},_,_) -> N2 = get_name_list(C2), emit(["?RT_PER:set_choice(element(1,Val),", {asis,{N1,N2}},", ",{asis,{length(N1),length(N2)}},")"]); + +gen_enc_choice_tag({C1,C2,C3},_,_) -> + N1 = get_name_list(C1), + N2 = get_name_list(C2), + N3 = get_name_list(C3), + Root = N1 ++ N3, + emit(["?RT_PER:set_choice(element(1,Val),", + {asis,{Root,N2}},", ",{asis,{length(Root),length(N2)}},")"]); gen_enc_choice_tag(C,_,_) -> N = get_name_list(C), emit(["?RT_PER:set_choice(element(1,Val),", @@ -1208,6 +1284,8 @@ get_name_list([], Acc) -> gen_enc_choice2(Erule,TopType, {L1,L2}, Ext) -> gen_enc_choice2(Erule,TopType, L1 ++ L2, 0, Ext); +gen_enc_choice2(Erule,TopType, {L1,L2,L3}, Ext) -> + gen_enc_choice2(Erule,TopType, L1 ++ L3 ++ L2, 0, Ext); gen_enc_choice2(Erule,TopType, L, Ext) -> gen_enc_choice2(Erule,TopType, L, 0, Ext). @@ -1279,6 +1357,9 @@ gen_dec_choice1(Erule,TopType,CompList,noext) -> gen_dec_choice1(Erule,TopType,{RootList,ExtList},Ext) -> NewList = RootList ++ ExtList, gen_dec_choice1(Erule,TopType, NewList, Ext); +gen_dec_choice1(Erule,TopType,{RootList,ExtList,RootList2},Ext) -> + NewList = RootList ++ RootList2 ++ ExtList, + gen_dec_choice1(Erule,TopType, NewList, Ext); gen_dec_choice1(Erule,TopType,CompList,{ext,ExtPos,ExtNum}) -> emit({"{Choice,",{curr,bytes}, "} = ?RT_PER:getchoice(",{prev,bytes},",", @@ -1347,6 +1428,18 @@ gen_encode_prim_wrapper(CtgenMod,Erule,Cont,DoTag,Value) -> CtgenMod:gen_encode_prim(Erule,Cont,DoTag,Value). % erase(component_type). +make_elements(I,Val,ExtCnames) -> + make_elements(I,Val,ExtCnames,[]). + +make_elements(I,Val,[ExtCname],Acc)-> % the last one, no comma needed + Element = make_element(I,Val,ExtCname), + make_elements(I+1,Val,[],[Element|Acc]); +make_elements(I,Val,[ExtCname|Rest],Acc)-> + Element = make_element(I,Val,ExtCname), + make_elements(I+1,Val,Rest,[", ",Element|Acc]); +make_elements(_I,_,[],Acc) -> + lists:reverse(Acc). + make_element(I,Val,Cname) -> case tuple_notation_allowed() of true -> @@ -1355,6 +1448,55 @@ make_element(I,Val,Cname) -> io_lib:format("element(~w,~s)",[I,Val]) end. +emit_extaddgroupTerms(VarSeries,[_]) -> + asn1ct_name:new(VarSeries), + emit({curr,VarSeries}), + ok; +emit_extaddgroupTerms(VarSeries,[_|Rest]) -> + asn1ct_name:new(VarSeries), + emit({{curr,VarSeries},","}), + emit_extaddgroupTerms(VarSeries,Rest); +emit_extaddgroupTerms(_,[]) -> + ok. +wrap_compList({Root1,Ext,Root2}) -> + {Root1,wrap_extensionAdditionGroups(Ext),Root2}; +wrap_compList({Root1,Ext}) -> + {Root1,wrap_extensionAdditionGroups(Ext)}; +wrap_compList(CompList) -> + CompList. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Will convert all componentTypes following 'ExtensionAdditionGroup' +%% up to the matching 'ExtensionAdditionGroupEnd' into one componentType +%% of type SEQUENCE with the componentTypes as components +%% +wrap_extensionAdditionGroups(ExtCompList) -> + wrap_extensionAdditionGroups(ExtCompList,[],0). + +wrap_extensionAdditionGroups([{'ExtensionAdditionGroup',_Number}|Rest],Acc,0) -> + {ExtGroupCompList= + [#'ComponentType'{textual_order=TextPos}|_], + ['ExtensionAdditionGroupEnd'|Rest2]} = + lists:splitwith(fun(#'ComponentType'{}) -> true; + (_) -> false + end, + Rest), + wrap_extensionAdditionGroups(Rest2, + [#'ComponentType'{ + name='ExtAddGroup', % FIXME: handles ony one ExtAddGroup + typespec=#type{def=#'SEQUENCE'{ + extaddgroup=1,% FIXME: handles only one + components=ExtGroupCompList}}, + textual_order = TextPos, + prop='OPTIONAL'}|Acc],length(ExtGroupCompList)-1); +wrap_extensionAdditionGroups([H=#'ComponentType'{textual_order=Tord}|T],Acc,ExtAddGroupDiff) when is_integer(Tord) -> + wrap_extensionAdditionGroups(T,[H#'ComponentType'{ + textual_order=Tord - ExtAddGroupDiff}|Acc],ExtAddGroupDiff); +wrap_extensionAdditionGroups([H|T],Acc,ExtAddGroupDiff) -> + wrap_extensionAdditionGroups(T,[H|Acc],ExtAddGroupDiff); +wrap_extensionAdditionGroups([],Acc,_) -> + lists:reverse(Acc). + + tuple_notation_allowed() -> Options = get(encoding_options), not (lists:member(optimize,Options) orelse lists:member(uper_bin,Options)). diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index eab5fb4a2a..6b511a66da 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -536,14 +536,34 @@ gen_part_decode_funcs({primitive,bif},_TypeName, gen_part_decode_funcs(WhatKind,_TypeName,{_,Directive,_,_}) -> throw({error,{asn1,{"Not implemented yet",WhatKind," partial incomplete directive:",Directive}}}). + +extaddgroup2sequence(ExtList) -> + extaddgroup2sequence(ExtList,[]). + +extaddgroup2sequence([{'ExtensionAdditionGroup',Number0}|T],Acc) -> + Number = case Number0 of undefined -> 1; _ -> Number0 end, + {ExtGroupComps,['ExtensionAdditionGroupEnd'|T2]} = + lists:splitwith(fun(Elem) -> is_record(Elem,'ComponentType') end,T), + extaddgroup2sequence(T2,[#'ComponentType'{ + name='ExtAddGroup', + typespec=#type{def=#'SEQUENCE'{ + extaddgroup=Number, + components=ExtGroupComps}}, + prop='OPTIONAL'}|Acc]); +extaddgroup2sequence([C|T],Acc) -> + extaddgroup2sequence(T,[C|Acc]); +extaddgroup2sequence([],Acc) -> + lists:reverse(Acc). + + gen_types(Erules,Tname,{RootL1,ExtList,RootL2}) when is_list(RootL1), is_list(RootL2) -> gen_types(Erules,Tname,RootL1), - gen_types(Erules,Tname,ExtList), + gen_types(Erules,Tname,extaddgroup2sequence(ExtList)), gen_types(Erules,Tname,RootL2); gen_types(Erules,Tname,{RootList,ExtList}) when is_list(RootList) -> gen_types(Erules,Tname,RootList), - gen_types(Erules,Tname,ExtList); + gen_types(Erules,Tname,extaddgroup2sequence(ExtList)); gen_types(Erules,Tname,[{'EXTENSIONMARK',_,_}|Rest]) -> gen_types(Erules,Tname,Rest); gen_types(Erules,Tname,[ComponentType|Rest]) -> @@ -1543,19 +1563,18 @@ gen_record2(Name,SeqOrSet,Comps) -> gen_record2(_Name,_SeqOrSet,[],_Com,_Extension) -> true; -gen_record2(Name,SeqOrSet,[{'EXTENSIONMARK',_,_}|T],Com,Extension) -> - gen_record2(Name,SeqOrSet,T,Com,Extension); -gen_record2(_Name,_SeqOrSet,[H],Com,Extension) -> - #'ComponentType'{name=Cname} = H, +gen_record2(_Name,_SeqOrSet,[H = #'ComponentType'{name=Cname}],Com,Extension) -> emit(Com), emit({asis,Cname}), gen_record_default(H, Extension); -gen_record2(Name,SeqOrSet,[H|T],Com, Extension) -> - #'ComponentType'{name=Cname} = H, +gen_record2(Name,SeqOrSet,[H = #'ComponentType'{name=Cname}|T],Com, Extension) -> emit(Com), emit({asis,Cname}), gen_record_default(H, Extension), - gen_record2(Name,SeqOrSet,T,", ", Extension). + gen_record2(Name,SeqOrSet,T,", ", Extension); +gen_record2(Name,SeqOrSet,[_|T],Com,Extension) -> + %% skip EXTENSIONMARK, ExtensionAdditionGroup and other markers + gen_record2(Name,SeqOrSet,T,Com,Extension). gen_record_default(#'ComponentType'{prop='OPTIONAL'}, _)-> emit(" = asn1_NOVALUE"); diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl index 46d7ad6fdb..224a535e87 100644 --- a/lib/asn1/src/asn1ct_parser2.erl +++ b/lib/asn1/src/asn1ct_parser2.erl @@ -417,10 +417,22 @@ parse_BuiltinType([{'CHARACTER',_},{'STRING',_}|Rest]) -> {#type{def='CHARACTER STRING'},Rest}; parse_BuiltinType([{'CHOICE',_},{'{',_}|Rest]) -> - {AlternativeTypeLists,Rest2} = parse_AlternativeTypeLists(Rest,get(extensiondefault)), + {AlternativeTypeLists,Rest2} = parse_AlternativeTypeLists(Rest), + AlternativeTypeLists1 = + lists:filter(fun(#'ExtensionAdditionGroup'{}) -> false; + ('ExtensionAdditionGroupEnd') -> false; + (_) -> true + end,AlternativeTypeLists), case Rest2 of [{'}',_}|Rest3] -> - {#type{def={'CHOICE',AlternativeTypeLists}},Rest3}; + AlternativeTypeLists2 = + case {[Ext||Ext = #'EXTENSIONMARK'{} <- AlternativeTypeLists1], + get(extensiondefault)} of + {[],'IMPLIED'} -> AlternativeTypeLists1 ++ [#'EXTENSIONMARK'{}]; + _ -> AlternativeTypeLists1 + end, + + {#type{def={'CHOICE',AlternativeTypeLists2}},Rest3}; _ -> throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), [got,get_token(hd(Rest2)),expected,'}']}}) @@ -479,16 +491,19 @@ parse_BuiltinType([{'REAL',_}|Rest]) -> {#type{def='REAL'},Rest}; parse_BuiltinType([{'RELATIVE-OID',_}|Rest]) -> {#type{def='RELATIVE-OID'},Rest}; -parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'}',_}|Rest]) -> - {#type{def=#'SEQUENCE'{components=[{'EXTENSIONMARK',Line,undefined}]}}, +parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'}',_}|Rest]) -> + {#type{def=#'SEQUENCE'{components=[]}}, Rest}; +parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'}',_}|Rest]) -> + {#type{def=#'SEQUENCE'{components=[#'EXTENSIONMARK'{pos = Line}]}},Rest}; parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'!',_}|Rest]) -> {ExceptionIdentification,Rest2} = parse_ExceptionIdentification(Rest), case Rest2 of [{'}',_}|Rest3] -> - {#type{def=#'SEQUENCE'{components=[{'EXTENSIONMARK', - Line, - ExceptionIdentification}]}}, + {#type{def=#'SEQUENCE'{ + components=[#'EXTENSIONMARK'{ + pos = Line, + val = ExceptionIdentification}]}}, Rest3}; _ -> {ComponentTypeLists,Rest3}= @@ -537,13 +552,14 @@ parse_BuiltinType([{'SEQUENCE',_},{'OF',_}|Rest]) -> parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'}',_}|Rest]) -> - {#type{def=#'SET'{components=[{'EXTENSIONMARK',Line,undefined}]}},Rest}; + {#type{def=#'SET'{components=[#'EXTENSIONMARK'{pos = Line}]}},Rest}; parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'!',_}|Rest]) -> {ExceptionIdentification,Rest2} = parse_ExceptionIdentification(Rest), case Rest2 of [{'}',_}|Rest3] -> {#type{def=#'SET'{components= - [{'EXTENSIONMARK',Line,ExceptionIdentification}]}}, + [#'EXTENSIONMARK'{pos = Line, + val = ExceptionIdentification}]}}, Rest3}; _ -> throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), @@ -2323,101 +2339,197 @@ to_set(V) when is_list(V) -> to_set(V) -> ordsets:from_list([V]). +parse_AlternativeTypeLists(Tokens) -> + parse_AlternativeTypeLists(Tokens,[]). -parse_AlternativeTypeLists(Tokens,ExtensionDefault) -> - {AltTypeList,Rest1} = parse_AlternativeTypeList(Tokens), - {ExtensionAndException,Rest2} = - case Rest1 of - [{',',_},{'...',L1},{'!',_}|Rest12] -> - {_,Rest13} = parse_ExceptionIdentification(Rest12), - %% Exception info is currently thrown away - {[#'EXTENSIONMARK'{pos=L1}],Rest13}; - [{',',_},{'...',L1}|Rest12] -> - {[#'EXTENSIONMARK'{pos=L1}],Rest12}; - _ -> - {[],Rest1} - end, - {AltTypeList2,Rest5} = - case ExtensionAndException of - [] -> - {AltTypeList,Rest2}; - _ -> - {ExtensionAddition,Rest3} = - case Rest2 of - [{',',_}|Rest23] -> - parse_ExtensionAdditionAlternativeList(Rest23); - _ -> - {[],Rest2} - end, - {OptionalExtensionMarker,Rest4} = - case Rest3 of - [{',',_},{'...',L3}|Rest31] -> - {[#'EXTENSIONMARK'{pos=L3}],Rest31}; - _ -> - {[],Rest3} - end, - {AltTypeList ++ ExtensionAndException ++ - ExtensionAddition ++ OptionalExtensionMarker, Rest4} - end, - AltTypeList3 = - case [X || X=#'EXTENSIONMARK'{} <- AltTypeList2] of - [] when ExtensionDefault == 'IMPLIED' -> - AltTypeList2 ++ [#'EXTENSIONMARK'{}]; - _ -> - AltTypeList2 - end, - {AltTypeList3,Rest5}. - +parse_AlternativeTypeLists(Tokens = [{identifier,_,_}|_Rest0],Clist) -> + {CompList,Rest1} = parse_AlternativeTypeList(Tokens,[]), + parse_AlternativeTypeLists(Rest1,Clist++CompList); +parse_AlternativeTypeLists([{'...',L1},{'!',_}|Rest02],Clist0) -> + {_,Rest03} = parse_ExceptionIdentification(Rest02), + %% Exception info is currently thrown away + parse_AlternativeTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]); +parse_AlternativeTypeLists([{',',L1},{'...',_},{'!',_}|Rest02],Clist0) when Clist0 =/= []-> + {_,Rest03} = parse_ExceptionIdentification(Rest02), + %% Exception info is currently thrown away + parse_AlternativeTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]); + +parse_AlternativeTypeLists([{',',_},{'...',L1}|Rest02],Clist0) when Clist0 =/= []-> + parse_AlternativeTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]); +parse_AlternativeTypeLists([{'...',L1}|Rest02],Clist0) -> + parse_AlternativeTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]); +parse_AlternativeTypeLists(Tokens = [{'}',_L1}|_Rest02],Clist0) -> + {Clist0,Tokens}. + +parse_AlternativeTypeLists2(Tokens,Clist) -> + {ExtAdd,Rest} = parse_ExtensionAdditionAlternatives(Tokens,Clist), + {Clist2,Rest2} = parse_OptionalExtensionMarker(Rest,lists:flatten(ExtAdd)), + case Rest2 of + [{',',_}|Rest3] -> + {CompList,Rest4} = parse_AlternativeTypeList(Rest3,[]), + {Clist2 ++ CompList,Rest4}; + _ -> + {Clist2,Rest2} + end. -parse_AlternativeTypeList(Tokens) -> - parse_AlternativeTypeList(Tokens,[]). -parse_AlternativeTypeList(Tokens,Acc) -> - {NamedType,Rest} = parse_NamedType(Tokens), + +parse_AlternativeTypeList([{',',_},Id = {identifier,_,_}|Rest],Acc) when Acc =/= [] -> + {AlternativeType,Rest2} = parse_NamedType([Id|Rest]), + parse_AlternativeTypeList(Rest2,[AlternativeType|Acc]); +parse_AlternativeTypeList(Tokens = [{'}',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_AlternativeTypeList(Tokens = [{']',_},{']',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_AlternativeTypeList(Tokens = [{',',_},{'...',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_AlternativeTypeList(Tokens,[]) -> + {AlternativeType,Rest} = parse_NamedType(Tokens), + parse_AlternativeTypeList(Rest,[AlternativeType]); +parse_AlternativeTypeList(Tokens,_) -> + throw({asn1_error, + {get_line(hd(Tokens)),get(asn1_module), + [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], + expected,['}',', identifier']]}}). + +parse_ExtensionAdditionAlternatives(Tokens =[{',',_}|_],Clist) -> + {ExtAddList,Rest2} = parse_ExtensionAdditionAlternativesList(Tokens,[]), + {Clist++lists:flatten(ExtAddList),Rest2}; +parse_ExtensionAdditionAlternatives(Tokens,Clist) -> + %% Empty + {Clist,Tokens}. + +parse_ExtensionAdditionAlternativesList([{',',_},Id = {identifier,_,_}|Rest],Acc) -> + {AlternativeType,Rest2} = parse_NamedType([Id|Rest]), + parse_ExtensionAdditionAlternativesList(Rest2,[AlternativeType|Acc]); +parse_ExtensionAdditionAlternativesList([{',',_},C1 = {'[',_},C2 = {'[',_}|Rest],Acc) -> + {ExtAddGroup,Rest2} = parse_ExtensionAdditionAlternativesGroup([C1,C2|Rest],[]), + parse_ExtensionAdditionAlternativesList(Rest2,[ExtAddGroup|Acc]); +parse_ExtensionAdditionAlternativesList(Tokens = [{'}',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_ExtensionAdditionAlternativesList(Tokens = [{',',_},{'...',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_ExtensionAdditionAlternativesList(Tokens,_) -> + throw({asn1_error, + {get_line(hd(Tokens)),get(asn1_module), + [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], + expected,['}',', identifier']]}}). + + +parse_ExtensionAdditionAlternativesGroup([ {'[',_},{'[',_},_VsnNr = {number,_,Num},{':',_}|Rest],[]) -> + parse_ExtensionAdditionAlternativesGroup2(Rest,Num); +parse_ExtensionAdditionAlternativesGroup([ {'[',_},{'[',_}|Rest],[]) -> + parse_ExtensionAdditionAlternativesGroup2(Rest,undefined); +parse_ExtensionAdditionAlternativesGroup(Tokens,_) -> + throw({asn1_error, + {get_line(hd(Tokens)),get(asn1_module), + [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], + expected,['[[']]}}). + + +parse_ExtensionAdditionAlternativesGroup2(Tokens,Num) -> + {CompTypeList,Rest} = parse_AlternativeTypeList(Tokens,[]), case Rest of - [{',',_},Id = {identifier,_,_}|Rest2] -> - parse_AlternativeTypeList([Id|Rest2],[NamedType|Acc]); + [{']',_},{']',_}|Rest2] -> + {[{'ExtensionAdditionGroup',Num}|CompTypeList] ++ + ['ExtensionAdditionGroupEnd'],Rest2}; _ -> - {lists:reverse([NamedType|Acc]),Rest} - end. - + throw({asn1_error,{get_line(hd(Rest)),get(asn1_module), + [got,get_token(hd(Rest)),expected,[']]']]}}) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% parse_AlternativeTypeLists(Tokens,ExtensionDefault) -> +%% {AltTypeList,Rest1} = parse_AlternativeTypeList(Tokens), +%% {ExtensionAndException,Rest2} = +%% case Rest1 of +%% [{',',_},{'...',L1},{'!',_}|Rest12] -> +%% {_,Rest13} = parse_ExceptionIdentification(Rest12), +%% %% Exception info is currently thrown away +%% {[#'EXTENSIONMARK'{pos=L1}],Rest13}; +%% [{',',_},{'...',L1}|Rest12] -> +%% {[#'EXTENSIONMARK'{pos=L1}],Rest12}; +%% _ -> +%% {[],Rest1} +%% end, +%% {AltTypeList2,Rest5} = +%% case ExtensionAndException of +%% [] -> +%% {AltTypeList,Rest2}; +%% _ -> +%% {ExtensionAddition,Rest3} = +%% case Rest2 of +%% [{',',_}|Rest23] -> +%% parse_ExtensionAdditionAlternativeList(Rest23); +%% _ -> +%% {[],Rest2} +%% end, +%% {OptionalExtensionMarker,Rest4} = +%% case Rest3 of +%% [{',',_},{'...',L3}|Rest31] -> +%% {[#'EXTENSIONMARK'{pos=L3}],Rest31}; +%% _ -> +%% {[],Rest3} +%% end, +%% {AltTypeList ++ ExtensionAndException ++ +%% ExtensionAddition ++ OptionalExtensionMarker, Rest4} +%% end, +%% AltTypeList3 = +%% case [X || X=#'EXTENSIONMARK'{} <- AltTypeList2] of +%% [] when ExtensionDefault == 'IMPLIED' -> +%% AltTypeList2 ++ [#'EXTENSIONMARK'{}]; +%% _ -> +%% AltTypeList2 +%% end, +%% {AltTypeList3,Rest5}. -parse_ExtensionAdditionAlternativeList(Tokens) -> - parse_ExtensionAdditionAlternativeList(Tokens,[]). +%% parse_AlternativeTypeList(Tokens) -> +%% parse_AlternativeTypeList(Tokens,[]). + +%% parse_AlternativeTypeList(Tokens,Acc) -> +%% {NamedType,Rest} = parse_NamedType(Tokens), +%% case Rest of +%% [{',',_},Id = {identifier,_,_}|Rest2] -> +%% parse_AlternativeTypeList([Id|Rest2],[NamedType|Acc]); +%% _ -> +%% {lists:reverse([NamedType|Acc]),Rest} +%% end. + -parse_ExtensionAdditionAlternativeList(Tokens,Acc) -> - {Element,Rest0} = - case Tokens of - [{identifier,_,_}|_Rest] -> - parse_NamedType(Tokens); - [{'[',_},{'[',_}|_] -> - parse_ExtensionAdditionAlternatives(Tokens) - end, - case Rest0 of - [{',',_}|Rest01] -> - parse_ExtensionAdditionAlternativeList(Rest01,[Element|Acc]); - _ -> - {lists:reverse([Element|Acc]),Rest0} - end. -parse_ExtensionAdditionAlternatives([{'[',_},{'[',_}|Rest]) -> - parse_ExtensionAdditionAlternatives(Rest,[]); -parse_ExtensionAdditionAlternatives(Tokens) -> - throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), - [got,get_token(hd(Tokens)),expected,'[[']}}). +%% parse_ExtensionAdditionAlternativeList(Tokens) -> +%% parse_ExtensionAdditionAlternativeList(Tokens,[]). + +%% parse_ExtensionAdditionAlternativeList([{'[[',_}|Rest],Acc) -> +%% parse_ExtensionAdditionAlternativeList(Rest,Acc); +%% parse_ExtensionAdditionAlternativeList(Tokens = [{identifier,_,_}|_Rest],Acc) -> +%% {Element,Rest0} = parse_NamedType(Tokens); +%% case Rest0 of +%% [{',',_}|Rest01] -> +%% parse_ExtensionAdditionAlternativeList(Rest01,[Element|Acc]); +%% _ -> +%% {lists:reverse([Element|Acc]),Rest0} +%% end. -parse_ExtensionAdditionAlternatives([Id = {identifier,_,_}|Rest],Acc) -> - {NamedType, Rest2} = parse_NamedType([Id|Rest]), - case Rest2 of - [{',',_}|Rest21] -> - parse_ExtensionAdditionAlternatives(Rest21,[NamedType|Acc]); - [{']',_},{']',_}|Rest21] -> - {lists:reverse(Acc),Rest21}; - _ -> - throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), - [got,get_token(hd(Rest2)),expected,[',',']]']]}}) - end. +%% parse_ExtensionAdditionAlternatives([{'[[',_}|Rest]) -> +%% parse_ExtensionAdditionAlternatives(Rest,[]); +%% parse_ExtensionAdditionAlternatives(Tokens) -> +%% throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), +%% [got,get_token(hd(Tokens)),expected,'[[']}}). + +%% parse_ExtensionAdditionAlternatives([Id = {identifier,_,_}|Rest],Acc) -> +%% {NamedType, Rest2} = parse_NamedType([Id|Rest]), +%% case Rest2 of +%% [{',',_}|Rest21] -> +%% parse_ExtensionAdditionAlternatives(Rest21,[NamedType|Acc]); +%% [{']]',_}|Rest21] -> +%% {lists:reverse(Acc),Rest21}; +%% _ -> +%% throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), +%% [got,get_token(hd(Rest2)),expected,[',',']]']]}}) +%% end. parse_NamedType([{identifier,L1,Idname}|Rest]) -> {Type,Rest2} = parse_Type(Rest), @@ -2428,144 +2540,123 @@ parse_NamedType(Tokens) -> parse_ComponentTypeLists(Tokens) -> -% Resulting tuple {ComponentTypeList,Rest1} is returned - case Tokens of - [{identifier,_,_}|_Rest0] -> - {Clist,Rest01} = parse_ComponentTypeList(Tokens), - case Rest01 of - [{',',_}|Rest02] -> - parse_ComponentTypeLists(Rest02,Clist); % 5 - 13 - _ -> - {Clist,Rest01} - end; - [{'COMPONENTS',_},{'OF',_}|_Rest] -> - {Clist,Rest01} = parse_ComponentTypeList(Tokens), - case Rest01 of - [{',',_}|Rest02] -> - parse_ComponentTypeLists(Rest02,Clist); - _ -> - {Clist,Rest01} - end; + parse_ComponentTypeLists(Tokens,[]). + +parse_ComponentTypeLists(Tokens = [{identifier,_,_}|_Rest0],Clist) -> + {CompList,Rest1} = parse_ComponentTypeList(Tokens,[]), + parse_ComponentTypeLists(Rest1,Clist++CompList); +parse_ComponentTypeLists(Tokens = [{'COMPONENTS',_},{'OF',_}|_Rest],Clist) -> + {CompList,Rest1} = parse_ComponentTypeList(Tokens,[]), + parse_ComponentTypeLists(Rest1,Clist++CompList); +parse_ComponentTypeLists([{'...',L1},{'!',_}|Rest02],Clist0) -> + {_,Rest03} = parse_ExceptionIdentification(Rest02), + %% Exception info is currently thrown away + parse_ComponentTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]); +parse_ComponentTypeLists([{',',L1},{'...',_},{'!',_}|Rest02],Clist0) when Clist0 =/= []-> + {_,Rest03} = parse_ExceptionIdentification(Rest02), + %% Exception info is currently thrown away + parse_ComponentTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]); + + parse_ComponentTypeLists([{',',_},{'...',L1}|Rest02],Clist0) when Clist0 =/= []-> + parse_ComponentTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]); +parse_ComponentTypeLists([{'...',L1}|Rest02],Clist0) -> + parse_ComponentTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]); +parse_ComponentTypeLists(Tokens = [{'}',_L1}|_Rest02],Clist0) -> + {Clist0,Tokens}. + +parse_ComponentTypeLists2(Tokens,Clist) -> + {ExtAdd,Rest} = parse_ExtensionAdditions(Tokens,Clist), + {Clist2,Rest2} = parse_OptionalExtensionMarker(Rest,lists:flatten(ExtAdd)), + case Rest2 of + [{',',_}|Rest3] -> + {CompList,Rest4} = parse_ComponentTypeList(Rest3,[]), + {Clist2 ++ CompList,Rest4}; _ -> - parse_ComponentTypeLists(Tokens,[]) + {Clist2,Rest2} end. -parse_ComponentTypeLists([{'...',L1},{'!',_}|Rest],Clist1) -> - {_,Rest2} = parse_ExceptionIdentification(Rest), - %% Exception info is currently thrown away - parse_ComponentTypeLists2(Rest2,Clist1++[#'EXTENSIONMARK'{pos=L1}]); -parse_ComponentTypeLists([{'...',L1}|Rest],Clist1) -> %% first Extensionmark - parse_ComponentTypeLists2(Rest,Clist1++[#'EXTENSIONMARK'{pos=L1}]); -parse_ComponentTypeLists(Tokens,Clist1) -> - {Clist1,Tokens}. - - -parse_ComponentTypeLists2(Tokens,Clist1) -> - {ExtensionAddition,Rest2} = - case Tokens of - [{',',_}|Rest1] -> - parse_ExtensionAdditionList(Rest1); - _ -> - {[],Tokens} - end, - {OptionalExtensionMarker,Rest3} = - case Rest2 of - [{',',_},{'...',L2}|Rest21] -> - {[#'EXTENSIONMARK'{pos=L2}],Rest21}; - _ -> - {[],Rest2} - end, - {RootComponentTypeList,Rest4} = - case Rest3 of - [{',',_}|Rest31] -> - parse_ComponentTypeList(Rest31); - _ -> - {[],Rest3} - end, - {Clist1 ++ ExtensionAddition ++ OptionalExtensionMarker ++ RootComponentTypeList, Rest4}. - +parse_OptionalExtensionMarker([{',',_},{'...',L1}|Rest],Clist)-> + {Clist++[#'EXTENSIONMARK'{pos=L1}],Rest}; +parse_OptionalExtensionMarker(Tokens,Clist) -> + {Clist,Tokens}. -parse_ComponentTypeList(Tokens) -> - parse_ComponentTypeList(Tokens,[]). -parse_ComponentTypeList(Tokens,Acc) -> +parse_ComponentTypeList([{',',_},Id = {identifier,_,_}|Rest],Acc) when Acc =/= [] -> + {ComponentType,Rest2} = parse_ComponentType([Id|Rest]), + parse_ComponentTypeList(Rest2,[ComponentType|Acc]); +parse_ComponentTypeList([{',',_},C1={'COMPONENTS',_},C2={'OF',_}|Rest],Acc) when Acc =/= [] -> + {ComponentType,Rest2} = parse_ComponentType([C1,C2|Rest]), + parse_ComponentTypeList(Rest2,[ComponentType|Acc]); +parse_ComponentTypeList(Tokens = [{'}',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_ComponentTypeList(Tokens = [{']',_},{']',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_ComponentTypeList(Tokens = [{',',_},{'...',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_ComponentTypeList(Tokens,[]) -> {ComponentType,Rest} = parse_ComponentType(Tokens), + parse_ComponentTypeList(Rest,[ComponentType]); +parse_ComponentTypeList(Tokens,_) -> + throw({asn1_error, + {get_line(hd(Tokens)),get(asn1_module), + [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], + expected,['}',', identifier']]}}). + +parse_ExtensionAdditions(Tokens=[{',',_}|_],Clist) -> + {ExtAddList,Rest2} = parse_ExtensionAdditionList(Tokens,[]), + {Clist++ExtAddList,Rest2}; +parse_ExtensionAdditions(Tokens,Clist) -> + %% Empty + {Clist,Tokens}. + +parse_ExtensionAdditionList([{',',_},Id = {identifier,_,_}|Rest],Acc) -> + {ComponentType,Rest2} = parse_ComponentType([Id|Rest]), + parse_ExtensionAdditionList(Rest2,[ComponentType|Acc]); +parse_ExtensionAdditionList([{',',_},C1={'COMPONENTS',_},C2={'OF',_}|Rest],Acc) -> + {ComponentType,Rest2} = parse_ComponentType([C1,C2|Rest]), + parse_ExtensionAdditionList(Rest2,[ComponentType|Acc]); +parse_ExtensionAdditionList([{',',_},C1 = {'[',_},C2 = {'[',_}|Rest],Acc) -> + {ExtAddGroup,Rest2} = parse_ExtensionAdditionGroup([C1,C2|Rest],[]), + parse_ExtensionAdditionList(Rest2,[ExtAddGroup|Acc]); +parse_ExtensionAdditionList(Tokens = [{'}',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_ExtensionAdditionList(Tokens = [{',',_},{'...',_}|_],Acc) -> + {lists:reverse(Acc),Tokens}; +parse_ExtensionAdditionList(Tokens,_) -> + throw({asn1_error, + {get_line(hd(Tokens)),get(asn1_module), + [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], + expected,['}',', identifier']]}}). + + +parse_ExtensionAdditionGroup([ {'[',_},{'[',_},_VsnNr = {number,_,Num},{':',_}|Rest],[]) -> + parse_ExtensionAdditionGroup2(Rest,Num); +parse_ExtensionAdditionGroup([ {'[',_},{'[',_}|Rest],[]) -> + parse_ExtensionAdditionGroup2(Rest,undefined); +parse_ExtensionAdditionGroup(Tokens,_) -> + throw({asn1_error, + {get_line(hd(Tokens)),get(asn1_module), + [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], + expected,['[[']]}}). + + +parse_ExtensionAdditionGroup2(Tokens,Num) -> + {CompTypeList,Rest} = parse_ComponentTypeList(Tokens,[]), case Rest of - [{',',_},Id = {identifier,_,_}|Rest2] -> - parse_ComponentTypeList([Id|Rest2],[ComponentType|Acc]); - [{',',_},C1={'COMPONENTS',_},C2={'OF',_}|Rest2] -> - parse_ComponentTypeList([C1,C2|Rest2],[ComponentType|Acc]); -% _ -> -% {lists:reverse([ComponentType|Acc]),Rest} - [{'}',_}|_] -> - {lists:reverse([ComponentType|Acc]),Rest}; -% [{',',_},{'...',_},{'}',_}|_] -> -% {lists:reverse([ComponentType|Acc]),Rest}; - [{',',_},{'...',_}|_] ->%% here comes the dubble ellipse - {lists:reverse([ComponentType|Acc]),Rest}; + [{']',_},{']',_}|Rest2] -> + {[{'ExtensionAdditionGroup',Num}|CompTypeList] ++ + ['ExtensionAdditionGroupEnd'],Rest2}; _ -> - throw({asn1_error, - {get_line(hd(Tokens)),get(asn1_module), - [got,[get_token(hd(Rest)),get_token(hd(tl(Rest)))], - expected,['}',', identifier']]}}) - end. - - -parse_ExtensionAdditionList(Tokens) -> - parse_ExtensionAdditionList(Tokens,[]). - -parse_ExtensionAdditionList(Tokens,Acc) -> - {Element,Rest0} = - case Tokens of - [{identifier,_,_}|_Rest] -> - parse_ComponentType(Tokens); - [{'[',_},{'[',_}|_] -> - parse_ExtensionAdditions(Tokens); - [{'...',L1}|_Rest] -> - {#'EXTENSIONMARK'{pos=L1},Tokens}; - _ -> - throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), - [got,get_token(hd(Tokens)),expected, - [identifier,'[[']]}}) - end, - case Rest0 of - [{',',_}|Rest01] -> - parse_ExtensionAdditionList(Rest01,[Element|Acc]); - [{'...',_}|Rest01] -> - {lists:reverse([Element|Acc]),Rest01}; - _ -> - {lists:reverse([Element|Acc]),Rest0} + throw({asn1_error,{get_line(hd(Rest)),get(asn1_module), + [got,get_token(hd(Rest)),expected,[']]']]}}) end. -parse_ExtensionAdditions([{'[',_},{'[',_}|Rest]) -> - parse_ExtensionAdditions(Rest,[]); -parse_ExtensionAdditions(Tokens) -> - throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), - [got,get_token(hd(Tokens)),expected,'[[']}}). - -parse_ExtensionAdditions([_VsnNr = {number,_,_},{':',_}|Rest],Acc) -> - %% ignor version number for now - parse_ExtensionAdditions(Rest,Acc); -parse_ExtensionAdditions([Id = {identifier,_,_}|Rest],Acc) -> - {ComponentType, Rest2} = parse_ComponentType([Id|Rest]), - case Rest2 of - [{',',_}|Rest21] -> - parse_ExtensionAdditions(Rest21,[ComponentType|Acc]); - [{']',_},{']',_}|Rest21] -> - {lists:reverse(Acc),Rest21}; - _ -> - throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), - [got,get_token(hd(Rest2)),expected,[',',']]']]}}) - end; -parse_ExtensionAdditions(Tokens,_) -> - throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), - [got,get_token(hd(Tokens)),expected,identifier]}}). parse_ComponentType([{'COMPONENTS',_},{'OF',_}|Rest]) -> {Type,Rest2} = parse_Type(Rest), {{'COMPONENTS OF',Type},Rest2}; parse_ComponentType(Tokens) -> - {NamedType,Rest} = parse_NamedType(Tokens), + Result = {NamedType,Rest} = parse_NamedType(Tokens), case Rest of [{'OPTIONAL',_}|Rest2] -> {NamedType#'ComponentType'{prop='OPTIONAL'},Rest2}; @@ -2573,7 +2664,7 @@ parse_ComponentType(Tokens) -> {Value,Rest21} = parse_Value(Rest2), {NamedType#'ComponentType'{prop={'DEFAULT',Value}},Rest21}; _ -> - {NamedType,Rest} + Result end. diff --git a/lib/asn1/src/asn1ct_tok.erl b/lib/asn1/src/asn1ct_tok.erl index f0ce31bdb2..85199c65ec 100644 --- a/lib/asn1/src/asn1ct_tok.erl +++ b/lib/asn1/src/asn1ct_tok.erl @@ -21,7 +21,7 @@ %% Tokenize ASN.1 code (input to parser generated with yecc) --export([get_name/2,tokenise/2, file/1]). +-export([get_name/2,tokenise/4, file/1]). file(File) -> @@ -29,12 +29,9 @@ file(File) -> {error, Reason} -> {error,{File,file:format_error(Reason)}}; {ok,Stream} -> - process0(Stream) + process(Stream,0,[]) end. -process0(Stream) -> - process(Stream,0,[]). - process(Stream,Lno,R) -> process(io:get_line(Stream, ''), Stream,Lno+1,R). @@ -45,131 +42,128 @@ process(eof, Stream,Lno,R) -> process(L, Stream,Lno,R) when is_list(L) -> %%io:format('read:~s',[L]), - case catch tokenise(L,Lno) of + case catch tokenise(Stream,L,Lno,[]) of {'ERR',Reason} -> io:format("Tokeniser error on line: ~w ~w~n",[Lno,Reason]), exit(0); - {multiline_comment,NestingLevel} -> - {RestL,Lno2} = process_skip_multiline_comment(Stream,Lno,NestingLevel), - process(RestL,Stream,Lno2,R); - T -> + {NewLno,T} -> %%io:format('toks:~w~n',[T]), - process(Stream,Lno,[T|R]) + process(Stream,NewLno,[T|R]) end. -process_skip_multiline_comment(Stream,Lno,NestingLevel) -> - process_skip_multiline_comment(io:get_line(Stream, ''), - Stream, Lno + 1, NestingLevel). -process_skip_multiline_comment(eof,_Stream,Lno,_NestingLevel) -> - io:format("Tokeniser error on line: ~w, premature end of multiline comment~n",[Lno]), - exit(0); -process_skip_multiline_comment(Line,Stream,Lno,NestingLevel) -> - case catch skip_multiline_comment(Line,NestingLevel) of - {multiline_comment,NestingLevel2} -> - process_skip_multiline_comment(Stream,Lno,NestingLevel2); - T -> - {T,Lno} - end. - -tokenise([H|T],Lno) when $a =< H , H =< $z -> +tokenise(Stream,[H|T],Lno,R) when $a =< H , H =< $z -> {X, T1} = get_name(T, [H]), - [{identifier,Lno, list_to_atom(X)}|tokenise(T1,Lno)]; + tokenise(Stream,T1,Lno,[{identifier,Lno, list_to_atom(X)}|R]); -tokenise([$&,H|T],Lno) when $A =< H , H =< $Z -> +tokenise(Stream,[$&,H|T],Lno,R) when $A =< H , H =< $Z -> {Y, T1} = get_name(T, [H]), X = list_to_atom(Y), - [{typefieldreference, Lno, X} | tokenise(T1, Lno)]; + tokenise(Stream,T1,Lno,[{typefieldreference, Lno, X} | R]); -tokenise([$&,H|T],Lno) when $a =< H , H =< $z -> +tokenise(Stream,[$&,H|T],Lno,R) when $a =< H , H =< $z -> {Y, T1} = get_name(T, [H]), X = list_to_atom(Y), - [{valuefieldreference, Lno, X} | tokenise(T1, Lno)]; + tokenise(Stream,T1,Lno,[{valuefieldreference, Lno, X} | R]); -tokenise([H|T],Lno) when $A =< H , H =< $Z -> +tokenise(Stream,[H|T],Lno,R) when $A =< H , H =< $Z -> {Y, T1} = get_name(T, [H]), X = list_to_atom(Y), case reserved_word(X) of true -> - [{X,Lno}|tokenise(T1,Lno)]; + tokenise(Stream,T1,Lno,[{X,Lno}|R]); false -> - [{typereference,Lno,X}|tokenise(T1,Lno)]; + tokenise(Stream,T1,Lno,[{typereference,Lno,X}|R]); rstrtype -> - [{restrictedcharacterstringtype,Lno,X}|tokenise(T1,Lno)] + tokenise(Stream,T1,Lno,[{restrictedcharacterstringtype,Lno,X}|R]) end; -tokenise([$-,H|T],Lno) when $0 =< H , H =< $9 -> +tokenise(Stream,[$-,H|T],Lno,R) when $0 =< H , H =< $9 -> {X, T1} = get_number(T, [H]), - [{number,Lno,-1 * list_to_integer(X)}|tokenise(T1,Lno)]; + tokenise(Stream,T1,Lno,[{number,Lno,-1 * list_to_integer(X)}|R]); -tokenise([H|T],Lno) when $0 =< H , H =< $9 -> +tokenise(Stream,[H|T],Lno,R) when $0 =< H , H =< $9 -> {X, T1} = get_number(T, [H]), - [{number,Lno,list_to_integer(X)}|tokenise(T1,Lno)]; + tokenise(Stream,T1,Lno,[{number,Lno,list_to_integer(X)}|R]); -tokenise([$-,$-|T],Lno) -> - tokenise(skip_comment(T),Lno); +tokenise(Stream,[$-,$-|T],Lno,R) -> + tokenise(Stream,skip_comment(T),Lno,R); -tokenise([$/,$*|T],Lno) -> - tokenise(skip_multiline_comment(T,0),Lno); +tokenise(Stream,[$/,$*|T],Lno,R) -> + {NewLno,T1} = skip_multiline_comment(Stream,T,Lno,0), + tokenise(Stream,T1,NewLno,R); -tokenise([$:,$:,$=|T],Lno) -> - [{'::=',Lno}|tokenise(T,Lno)]; +tokenise(Stream,[$:,$:,$=|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'::=',Lno}|R]); -tokenise([$'|T],Lno) -> +tokenise(Stream,[$'|T],Lno,R) -> case catch collect_quoted(T,Lno,[]) of {'ERR',_} -> throw({'ERR','bad_quote'}); {Thing, T1} -> - [Thing|tokenise(T1,Lno)] + tokenise(Stream,T1,Lno,[Thing|R]) end; -tokenise([$"|T],Lno) -> - collect_string(T,Lno); +tokenise(Stream,[$"|T],Lno,R) -> + {Str,T1} = collect_string(T,Lno), + tokenise(Stream,T1,Lno,[Str|R]); + +tokenise(Stream,[${|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'{',Lno}|R]); + +tokenise(Stream,[$}|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'}',Lno}|R]); -tokenise([${|T],Lno) -> - [{'{',Lno}|tokenise(T,Lno)]; +%% tokenise(Stream,[$],$]|T],Lno,R) -> +%% tokenise(Stream,T,Lno,[{']]',Lno}|R]); -tokenise([$}|T],Lno) -> - [{'}',Lno}|tokenise(T,Lno)]; +%% Even though x.680 specify '[[' and ']]' as lexical items +%% it does not work to have them as such since the single [ and ] can +%% be used beside each other in the SYNTAX OF in x.681 +%% the solution chosen here , i.e. to have them as separate lexical items +%% will not detect the cases where there is white space between them +%% which would be an error in the use in ExtensionAdditionGroups -tokenise([$]|T],Lno) -> - [{']',Lno}|tokenise(T,Lno)]; +%% tokenise(Stream,[$[,$[|T],Lno,R) -> +%% tokenise(Stream,T,Lno,[{'[[',Lno}|R]); -tokenise([$[|T],Lno) -> - [{'[',Lno}|tokenise(T,Lno)]; +tokenise(Stream,[$]|T],Lno,R) -> + tokenise(Stream,T,Lno,[{']',Lno}|R]); -tokenise([$,|T],Lno) -> - [{',',Lno}|tokenise(T,Lno)]; +tokenise(Stream,[$[|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'[',Lno}|R]); -tokenise([$(|T],Lno) -> - [{'(',Lno}|tokenise(T,Lno)]; -tokenise([$)|T],Lno) -> - [{')',Lno}|tokenise(T,Lno)]; +tokenise(Stream,[$,|T],Lno,R) -> + tokenise(Stream,T,Lno,[{',',Lno}|R]); -tokenise([$.,$.,$.|T],Lno) -> - [{'...',Lno}|tokenise(T,Lno)]; +tokenise(Stream,[$(|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'(',Lno}|R]); +tokenise(Stream,[$)|T],Lno,R) -> + tokenise(Stream,T,Lno,[{')',Lno}|R]); -tokenise([$.,$.|T],Lno) -> - [{'..',Lno}|tokenise(T,Lno)]; +tokenise(Stream,[$.,$.,$.|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'...',Lno}|R]); -tokenise([$.|T],Lno) -> - [{'.',Lno}|tokenise(T,Lno)]; -tokenise([$^|T],Lno) -> - [{'^',Lno}|tokenise(T,Lno)]; -tokenise([$!|T],Lno) -> - [{'!',Lno}|tokenise(T,Lno)]; -tokenise([$||T],Lno) -> - [{'|',Lno}|tokenise(T,Lno)]; +tokenise(Stream,[$.,$.|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'..',Lno}|R]); +tokenise(Stream,[$.|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'.',Lno}|R]); +tokenise(Stream,[$^|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'^',Lno}|R]); +tokenise(Stream,[$!|T],Lno,R) -> + tokenise(Stream,T,Lno,[{'!',Lno}|R]); +tokenise(Stream,[$||T],Lno,R) -> + tokenise(Stream,T,Lno,[{'|',Lno}|R]); -tokenise([H|T],Lno) -> +tokenise(Stream,[H|T],Lno,R) -> case white_space(H) of true -> - tokenise(T,Lno); + tokenise(Stream,T,Lno,R); false -> - [{list_to_atom([H]),Lno}|tokenise(T,Lno)] + tokenise(Stream,T,Lno,[{list_to_atom([H]),Lno}|R]) end; -tokenise([],_) -> - []. +tokenise(_Stream,[],Lno,R) -> + {Lno,lists:reverse(R)}. collect_string(L,Lno) -> @@ -181,7 +175,7 @@ collect_string([],_,_) -> collect_string([H|T],Lno,Str) -> case H of $" -> - [{cstring,1,lists:reverse(Str)}|tokenise(T,Lno)]; + {{cstring,1,lists:reverse(Str)},T}; Ch -> collect_string(T,Lno,[Ch|Str]) end. @@ -252,17 +246,23 @@ skip_comment([_|T]) -> skip_comment(T). -skip_multiline_comment([],L) -> - throw({multiline_comment,L}); -skip_multiline_comment([$*,$/|T],0) -> - T; -skip_multiline_comment([$*,$/|T],Level) -> - skip_multiline_comment(T,Level - 1); -skip_multiline_comment([$/,$*|T],Level) -> - skip_multiline_comment(T,Level + 1); -skip_multiline_comment([_|T],Level) -> - skip_multiline_comment(T,Level). - +skip_multiline_comment(Stream,[],Lno,Level) -> + case io:get_line(Stream,'') of + eof -> + io:format("Tokeniser error on line: ~w~n" + "premature end of multiline comment~n",[Lno]), + exit(0); + Line -> + skip_multiline_comment(Stream,Line,Lno+1,Level) + end; +skip_multiline_comment(_Stream,[$*,$/|T],Lno,0) -> + {Lno,T}; +skip_multiline_comment(Stream,[$*,$/|T],Lno,Level) -> + skip_multiline_comment(Stream,T,Lno,Level - 1); +skip_multiline_comment(Stream,[$/,$*|T],Lno,Level) -> + skip_multiline_comment(Stream,T,Lno,Level + 1); +skip_multiline_comment(Stream,[_|T],Lno,Level) -> + skip_multiline_comment(Stream,T,Lno,Level). collect_quoted([$',$B|T],Lno, L) -> case check_bin(L) of diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile index 5014eb902b..e8f65ec70b 100644 --- a/lib/asn1/test/Makefile +++ b/lib/asn1/test/Makefile @@ -189,27 +189,16 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) $(RELSYSDIR) - $(INSTALL_DATA) asn1.spec $(EMAKEFILE) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR) - chmod -f -R u+w $(RELSYSDIR) - @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + $(INSTALL_DIR) $(RELSYSDIR)/asn1_SUITE_data $(INSTALL_DIR) $(RELSYSDIR)/asn1_bin_SUITE_data - @(cd asn1_SUITE_data; tar cf - *) | (cd $(RELSYSDIR)/asn1_bin_SUITE_data; tar xf -) $(INSTALL_DIR) $(RELSYSDIR)/asn1_bin_v2_SUITE_data - @(cd asn1_SUITE_data; tar cf - *) | (cd $(RELSYSDIR)/asn1_bin_v2_SUITE_data; tar xf -) - + $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR) + $(INSTALL_DATA) asn1.spec $(INSTALL_PROGS) $(RELSYSDIR) + chmod -f -R u+w $(RELSYSDIR) + cd asn1_SUITE_data; tar cfh $(RELSYSDIR)/asn1_SUITE_data.tar * + cd $(RELSYSDIR)/asn1_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar + cd $(RELSYSDIR)/asn1_bin_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar + cd $(RELSYSDIR)/asn1_bin_v2_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar + rm $(RELSYSDIR)/asn1_SUITE_data.tar release_docs_spec: - - - - - - - - - - - - - - diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src index ca73d259af..f0228546a5 100644 --- a/lib/asn1/test/asn1_SUITE.erl.src +++ b/lib/asn1/test/asn1_SUITE.erl.src @@ -74,6 +74,7 @@ all(suite) -> [compile,parse,default_per,default_ber,default_per_opt,per, testSeqTypeRefPrim, testSeqTypeRefSeq, testSeqTypeRefSet, testSeqOf, testSeqOfIndefinite, testSeqOfCho, testSeqOfExternal, testSetDefault, testSetExtension, + testExtensionAdditionGroup, testSetExternal, testSeqOfTag, testSetOptional, testSetPrim, testSetTag, testSetTypeRefCho, testSetTypeRefPrim, testSetTypeRefSeq, testSetTypeRefSet, testSetOf, testSetOfCho, @@ -95,7 +96,7 @@ all(suite) -> [compile,parse,default_per,default_ber,default_per_opt,per, testSSLspecs, testNortel,test_undecoded_rest, test_inline, testTcapsystem, testNBAPsystem, test_compile_options,testDoubleEllipses, test_modified_x420, - testX420, test_x691,ticket_6143 + testX420, test_x691,ticket_6143, testExtensionAdditionGroup ] ++ common() ++ particular(). %all(suite) -> [test_inline,testNBAPsystem,test_compile_options,ticket_6143]. @@ -1036,7 +1037,6 @@ testSetExtension_cases(Rules) -> ?line testSetExtension:main(Rules). - testSetExternal(suite) -> []; testSetExternal(Config) -> ?line true = code:add_patha(?config(priv_dir,Config)), @@ -2292,6 +2292,21 @@ ticket_6143(suite) -> []; ticket_6143(Config) -> ?line ok = test_compile_options:ticket_6143(Config). +testExtensionAdditionGroup(suite) -> []; +testExtensionAdditionGroup(Config) -> + ?line DataDir = ?config(data_dir,Config), + ?line PrivDir = ?config(priv_dir,Config), + ?line Path = code:get_path(), + ?line code:add_patha(PrivDir), + DoIt = fun(Erule) -> + ?line ok = asn1ct:compile(filename:join(DataDir,"Extension-Addition-Group"),[Erule,{outdir,PrivDir}]), + ?line {ok,_M} = compile:file(filename:join(DataDir,"extensionAdditionGroup"),[{i,PrivDir},{outdir,PrivDir},debug_info]), + ?line ok = extensionAdditionGroup:run(Erule) + end, + ?line [DoIt(Rule)|| Rule <- [per_bin,uper_bin,ber_bin]], + ?line code:set_path(Path). + + % parse_modules() -> % ["ImportsFrom"]. diff --git a/lib/asn1/test/asn1_SUITE_data/AA2.asn1db b/lib/asn1/test/asn1_SUITE_data/AA2.asn1db Binary files differindex 3bf2c1b89d..163dbb032d 100644 --- a/lib/asn1/test/asn1_SUITE_data/AA2.asn1db +++ b/lib/asn1/test/asn1_SUITE_data/AA2.asn1db diff --git a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn new file mode 100644 index 0000000000..b985c970ac --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn @@ -0,0 +1,66 @@ +-- +-- %CopyrightBegin% +-- +-- Copyright Ericsson AB 2001-2010. 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% + +Extension-Addition-Group DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- fetched from ITU-T Rec. X691 (07/2002) + +Ax ::= SEQUENCE { + a INTEGER (250..253), + b BOOLEAN, + c CHOICE { + d INTEGER, + ..., + + [[ + e BOOLEAN, + f IA5String + ]], + ... + }, + ..., + [[ + g NumericString (SIZE(3)), + h BOOLEAN OPTIONAL + ]] +, + ..., + i BMPString OPTIONAL, + j PrintableString OPTIONAL + +} + +-- valAx Ax ::= { a 253, b TRUE, c e: TRUE, g "123", h TRUE } +Ax2 ::= SEQUENCE { + a INTEGER (250..253), + b BOOLEAN, + ..., + ug NumericString + +} +END + +-- The value { a 253, b TRUE, c e: TRUE, g "123", h TRUE } +-- is encoded in PER as +-- Hexadecimal view +-- 9E000180 010291A4 + +-- is encoded in Unaligned PER as +-- 9E000600 040A4690 diff --git a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl new file mode 100644 index 0000000000..79e200f561 --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl @@ -0,0 +1,43 @@ +%%%------------------------------------------------------------------- +%%% File : extensionAdditionGroup.erl +%%% Author : Kenneth Lundin +%%% Description : +%%% +%%% Created : 18 May 2010 by kenneth +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2010. 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(extensionAdditionGroup). +-include("Extension-Addition-Group.hrl"). + + +-compile(export_all). + +run(Erule) -> + Val = #'Ax'{a=253, b = true, c= {e,true}, g="123", h = true}, + io:format("~p:~p~n",[Erule,Val]), + {ok,List}= asn1rt:encode('Extension-Addition-Group','Ax',Val), + Enc = iolist_to_binary(List), + io:format("~p~n",[Enc]), + {ok,Val2} = asn1rt:decode('Extension-Addition-Group','Ax',Enc), + io:format("~p~n",[Val2]), + case Val2 of + Val -> ok; + _ -> exit({expected,Val, got, Val2}) + end. diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl index 83f38c5e6d..5e027cdedb 100644 --- a/lib/asn1/test/test_compile_options.erl +++ b/lib/asn1/test/test_compile_options.erl @@ -132,7 +132,7 @@ verbose(Config) when is_list(Config) -> ?line ok = asn1ct:compile(Asn1File, [{i,DataDir},{outdir,OutDir},noobj,verbose]), ?line test_server:capture_stop(), ?line [Line0|_] = test_server:capture_get(), - ?line lists:prefix("Erlang ASN.1 version", Line0), + ?line true = lists:prefix("Erlang ASN.1 version", Line0), %% Test non-verbose compile ?line test_server:capture_start(), diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk index b7e91e42a0..c0393f84fe 100644 --- a/lib/asn1/vsn.mk +++ b/lib/asn1/vsn.mk @@ -1,323 +1,2 @@ #next version number to use is 1.6.15 | 1.7 | 2.0 ASN1_VSN = 1.6.14 - -TICKETS = OTP-8565 \ - OTP-8516 - -TICKETS_1.6.14 = \ - OTP-8565 \ - OTP-8516 - -TICKETS_1.6.13 = \ - OTP-8463 - -TICKETS_1.6.12 = \ - OTP-8256 - -TICKETS_1.6.11 = \ - OTP-8136 \ - OTP-8047 \ - OTP-8046 \ - OTP-8043 \ - OTP-7972 - -TICKETS_1.6.10 = \ - OTP-7954 \ - OTP-7953 - -TICKETS_1.6.10 = \ - OTP-7954 \ - OTP-7953 - -TICKETS_1.6.9 = \ - OTP-7909 \ - OTP-7904 - -TICKETS_1.6.8.1 = \ - OTP-7900 \ - OTP-7910 - -TICKETS_1.6.8 = \ - OTP-7876 - -TICKETS_1.6.7 = \ - OTP-7801 \ - OTP-7806 - -TICKETS_1.6.6 = \ - OTP-7759 \ - OTP-7763 - -TICKETS_1.6.5 = \ - OTP-7734 - -TICKETS_1.6.4 = \ - OTP-7708 - -TICKETS_1.6.3 = \ - OTP-7681 \ - OTP-7678 - -TICKETS_1.6.2 = \ - OTP-7608 - -TICKETS_1.6.1 = \ - OTP-7602 \ - OTP-7533 \ - OTP-7476 \ - OTP-7334 \ - OTP-7332 \ - OTP-7322 \ - OTP-7306 \ - OTP-7299 \ - OTP-7295 \ - OTP-7204 \ - OTP-7174 \ - OTP-7166 - -TICKETS_1.6 = \ - OTP-7407 \ - OTP-7403 \ - OTP-7400 \ - OTP-7375 \ - OTP-7374 \ - OTP-7335 - -TICKETS_1.5.2 = \ - OTP-7263 \ - OTP-7264 \ - OTP-7268 \ - OTP-7269 \ - OTP-7273 - -TICKETS_1.5.1 = \ - OTP-7149 \ - OTP-7151 \ - OTP-7154 \ - OTP-7155 \ - OTP-7169 \ - OTP-7171 \ - OTP-7193 \ - OTP-7199 - -TICKETS_1.5 = \ - OTP-6835 \ - OTP-6882 - -TICKETS_1.4.7 = \ - OTP-6828 - -TICKETS_1.4.6 = \ - OTP-5067 \ - OTP-6763 \ - OTP-6769 \ - OTP-6770 \ - OTP-6786 - -TICKETS_1.4.5 = \ - OTP-6493 \ - OTP-6601 \ - OTP-6695 \ - OTP-6698 \ - OTP-6702 \ - OTP-6707 \ - OTP-6717 - -TICKETS_1.4.4.14 = \ - OTP-6462 \ - OTP-6506 - -TICKETS_1.4.4.13 = \ - OTP-6405 - -TICKETS_1.4.4.12 = \ - OTP-6314 - -TICKETS_1.4.4.11 = \ - OTP-6143 - -TICKETS_1.4.4.10 = \ - OTP-6111 \ - OTP-5932 - -TICKETS_1.4.4.9 = \ - OTP-5783 \ - OTP-5788 \ - OTP-5812 \ - OTP-5831 \ - OPT-5832 - -TICKETS_1.4.4.8 = \ - OTP-5687 \ - OTP-5688 \ - OTP-5689 \ - OTP-5701 \ - OTP-5710 - -TICKETS_1.4.4.7 = \ - OTP-5477 \ - OTP-5509 \ - OTP-5511 \ - OTP-5602 \ - OTP-5616 - -TICKETS_1.4.4.6 = \ - OTP-5457 \ - OTP-5466 - -TICKETS_1.4.4.5 = \ - OTP-5302 \ - OTP-5378 - -TICKETS_1.4.4.4 = \ - OTP-5240 \ - OTP-5243 - -TICKETS_1.4.4.3 = \ - OTP-5103 \ - OTP-5104 - -TICKETS_1.4.4.2 = \ - OTP-5022 - -TICKETS_1.4.4.1 = \ - OTP-4970 - -TICKETS_1.4.4 = \ - OTP-4893 \ - OTP-4894 \ - OTP-4895 \ - OTP-4917 \ - OTP-4918 \ - OTP-4919 \ - OTP-4944 \ - OTP-4953 \ - OTP-4955 \ - OTP-4957 \ - OTP-4965 - -TICKETS_1.4.3.1 = \ - OTP-4866 \ - OTP-4869 \ - OTP-4872 - -TICKETS_1.4.3 = \ - OTP-4832 \ - OTP-4833 \ - OTP-4835 \ - OTP-4856 - -TICKETS_1.4.2.1 = \ - OTP-4773 \ - OTP-4791 \ - OTP-4792 \ - OTP-4797 \ - OTP-4798 \ - OTP-4799 \ - OTP-4809 - -# OTP R9C -TICKETS_1.4.2 = \ - OTP-4693 \ - OTP-4744 - -TICKETS_1.4.1.1 = \ - OTP-4663 \ - OTP-4665 \ - OTP-4666 - -TICKETS_1.4.1 = \ - OTP-4559 \ - OTP-4560 \ - OTP-4590 \ - OTP-4591 \ - OTP-4592 \ - OTP-4631 \ - OTP-4633 - -TICKETS_1.4 = \ - OTP-3304 - -TICKETS_1.3.3.1 = \ - OTP-4353 \ - OTP-4354 \ - OTP-4390 \ - OTP-4395 - -TICKETS_1.3.3 = \ - OTP-4381 \ - OTP-4358 \ - OTP-4355 \ - OTP-4275 \ - OTP-4248 \ - OTP-4247 \ - OTP-4242 \ - OTP-4235 \ - OTP-4234 \ - OTP-4232 \ - OTP-4200 \ - OTP-4161 \ - OTP-4129 - -TICKETS_1.3.2 = \ - OTP-4094 \ - OTP-4103 \ - OTP-3980 \ - OTP-4073 - -TICKETS_1.3.1.1 = \ - OTP-4037 \ - OTP-4057 \ - OTP-4058 - -TICKETS_1.3.1 = \ - OTP-4025 \ - OTP-4026 - -TICKETS_1.3 = \ - OTP-3463 \ - OTP-3659 \ - OTP-3978 \ - OTP-3979 \ - OTP-3981 \ - OTP-3982 \ - OTP-3983 \ - OTP-3985 \ - OTP-3988 \ - OTP-3984 \ - OTP-3994 - -TICKETS_1.2.9.6 = \ - OTP-3830 - -TICKETS_1.2.9.5 = \ - OTP-3713 \ - OTP-3796 \ - OTP-3811 - -TICKETS_1.2.9.3 = \ - OTP-3700 \ - OTP-3701 - -TICKETS_1.2.9.2 = \ - OTP-xxxx - -TICKETS_1.2.9.1 = \ - OTP-xxxx - -TICKETS_1.2.9 = \ - OTP-3569 \ - OTP-3573 - -TICKETS_1.2.8 = \ - OTP-3496 - -TICKETS_1.2.7 = \ - OTP-3395 - -TICKETS_1.2.6 = \ - OTP-3352 - -TICKETS_1.2.5 = \ - OTP-3341 - diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index f8ae7202e6..3684ff462f 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -384,11 +384,14 @@ maybe_log_timestamp() -> [{"<i>~s</i>",[log_timestamp({MS,S,US})]}]}) end. -log_timestamp(Now) -> - put(log_timestamp,Now), - {_,{H,M,S}} = calendar:now_to_local_time(Now), - lists:flatten(io_lib:format("~2.2.0w:~2.2.0w:~2.2.0w", - [H,M,S])). +log_timestamp({MS,S,US}) -> + put(log_timestamp, {MS,S,US}), + {{Year,Month,Day}, {Hour,Min,Sec}} = + calendar:now_to_local_time({MS,S,US}), + MilliSec = trunc(US/1000), + lists:flatten(io_lib:format("~4.10.0B-~2.10.0B-~2.10.0B " + "~2.10.0B:~2.10.0B:~2.10.0B.~3.10.0B", + [Year,Month,Day,Hour,Min,Sec,MilliSec])). %%%----------------------------------------------------------------- %%% The logger server diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile index 3fb0d627a0..e3dc78ed75 100644 --- a/lib/common_test/test/Makefile +++ b/lib/common_test/test/Makefile @@ -92,7 +92,7 @@ release_spec: opt release_tests_spec: $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR) - $(INSTALL_PROGRAM) common_test.spec $(RELSYSDIR) + $(INSTALL_DATA) common_test.spec $(RELSYSDIR) chmod -f -R u+w $(RELSYSDIR) @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index ed7a9144a8..26da3ecad2 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -824,6 +824,10 @@ foldl_transform(St, [T|Ts]) -> {'EXIT',R} -> Es = [{St#compile.ifile,[{none,compile,{parse_transform,T,R}}]}], {error,St#compile{errors=St#compile.errors ++ Es}}; + {warning, Forms, Ws} -> + foldl_transform( + St#compile{code=Forms, + warnings=St#compile.warnings ++ Ws}, Ts); Forms -> foldl_transform(St#compile{code=Forms}, Ts) end; diff --git a/lib/cosEvent/vsn.mk b/lib/cosEvent/vsn.mk index 9f326b39b6..9c00a17100 100644 --- a/lib/cosEvent/vsn.mk +++ b/lib/cosEvent/vsn.mk @@ -1,15 +1 @@ - COSEVENT_VSN = 2.1.9 - -TICKETS = OTP-8543 - -TICKETS_2.1.8 = OTP-8355 \ - OTP-8409 - -TICKETS_2.1.7 = OTP-8201 - -TICKETS_2.1.6 = OTP-7987 - -TICKETS_2.1.5 = OTP-7837 - -TICKETS_2.1.4 = OTP-7595 diff --git a/lib/cosEventDomain/vsn.mk b/lib/cosEventDomain/vsn.mk index dceee34181..bd21133fe5 100644 --- a/lib/cosEventDomain/vsn.mk +++ b/lib/cosEventDomain/vsn.mk @@ -1,15 +1 @@ - COSEVENTDOMAIN_VSN = 1.1.9 - -TICKETS = OTP-8543 - -TICKETS_1.1.8 = OTP-8353 \ - OTP-8355 - -TICKETS_1.1.7 = OTP-8201 - -TICKETS_1.1.6 = OTP-7987 - -TICKETS_1.1.5 = OTP-7837 - -TICKETS_1.1.4 = OTP-7595 diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk index 2700ecb3e3..ef8ee53c5e 100644 --- a/lib/cosFileTransfer/vsn.mk +++ b/lib/cosFileTransfer/vsn.mk @@ -1,16 +1 @@ COSFILETRANSFER_VSN = 1.1.10 - -TICKETS = \ - OTP-8355 \ - OTP-8374 - - -TICKETS_1.1.9 = OTP-8201 - -TICKETS_1.1.8 = OTP-7987 - -TICKETS_1.1.7 = OTP-7837 - -TICKETS_1.1.6 = \ - OTP-7595 \ - OTP-7599
\ No newline at end of file diff --git a/lib/cosNotification/vsn.mk b/lib/cosNotification/vsn.mk index a19facffd5..c03f0ef161 100644 --- a/lib/cosNotification/vsn.mk +++ b/lib/cosNotification/vsn.mk @@ -1,18 +1 @@ COSNOTIFICATION_VSN = 1.1.14 - -TICKETS = OTP-8489 \ - OTP-8543 - -TICKETS_1.1.13 = OTP-8353 \ - OTP-8354 \ - OTP-8355 - -TICKETS_1.1.12 = OTP-8201 - -TICKETS_1.1.11 = OTP-7987 - -TICKETS_1.1.10 = OTP-7837 - -TICKETS_1.1.9 = OTP-7595 - -TICKETS_1.1.8 = OTP-7553 diff --git a/lib/cosProperty/vsn.mk b/lib/cosProperty/vsn.mk index 3d594a8329..ca9a7ca77e 100644 --- a/lib/cosProperty/vsn.mk +++ b/lib/cosProperty/vsn.mk @@ -1,13 +1 @@ COSPROPERTY_VSN = 1.1.12 - -TICKETS = OTP-8543 - -TICKETS_1.1.11 = OTP-8355 - -TICKETS_1.1.10 = OTP-8201 - -TICKETS_1.1.9 = OTP-7987 - -TICKETS_1.1.8 = OTP-7837 - -TICKETS_1.1.7 = OTP-7595 diff --git a/lib/cosTime/vsn.mk b/lib/cosTime/vsn.mk index 9d8057e8db..429613fb61 100644 --- a/lib/cosTime/vsn.mk +++ b/lib/cosTime/vsn.mk @@ -1,13 +1 @@ COSTIME_VSN = 1.1.9 - -TICKETS = OTP-8543 - -TICKETS_1.1.8 = OTP-8355 - -TICKETS_1.1.7 = OTP-8201 - -TICKETS_1.1.6 = OTP-7987 - -TICKETS_1.1.5 = OTP-7837 - -TICKETS_1.1.4 = OTP-7595 diff --git a/lib/cosTransactions/vsn.mk b/lib/cosTransactions/vsn.mk index 34775be7e4..82e46f51dd 100644 --- a/lib/cosTransactions/vsn.mk +++ b/lib/cosTransactions/vsn.mk @@ -1,14 +1 @@ COSTRANSACTIONS_VSN = 1.2.10 - -TICKETS = OTP-8489 \ - OTP-8543 - -TICKETS_1.2.9 = OTP-8355 - -TICKETS_1.2.8 = OTP-8201 - -TICKETS_1.2.7 = OTP-7987 - -TICKETS_1.2.6 = OTP-7837 - -TICKETS_1.2.5 = OTP-7595 diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in index e728db18eb..040adcfd09 100644 --- a/lib/crypto/c_src/Makefile.in +++ b/lib/crypto/c_src/Makefile.in @@ -68,13 +68,13 @@ RELSYSDIR = $(RELEASE_PATH)/lib/crypto-$(VSN) # ---------------------------------------------------- # Misc Macros # ---------------------------------------------------- -OBJS = $(OBJDIR)/crypto.o +OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o NIF_MAKEFILE = $(PRIVDIR)/Makefile ifeq ($(findstring win32,$(TARGET)), win32) -NIF_LIB = $(LIBDIR)/crypto.dll +NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).dll else -NIF_LIB = $(LIBDIR)/crypto.so +NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).so endif ifeq ($(HOST_OS),) @@ -102,20 +102,30 @@ $(OBJDIR): $(LIBDIR): -@mkdir -p $(LIBDIR) -$(OBJDIR)/%.o: %.c +$(OBJDIR)/%$(TYPEMARKER).o: %.c $(INSTALL_DIR) $(OBJDIR) $(CC) -c -o $@ $(ALL_CFLAGS) $< -$(LIBDIR)/crypto.so: $(OBJS) +$(LIBDIR)/crypto$(TYPEMARKER).so: $(OBJS) $(INSTALL_DIR) $(LIBDIR) $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(CRYPTO_LINK_LIB) -$(LIBDIR)/crypto.dll: $(OBJS) +$(LIBDIR)/crypto$(TYPEMARKER).dll: $(OBJS) $(INSTALL_DIR) $(LIBDIR) $(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(OBJS) -llibeay32 clean: - rm -f $(NIF_LIB) $(OBJS) +ifeq ($(findstring win32,$(TARGET)), win32) + rm -f $(LIBDIR)/crypto.dll + rm -f $(LIBDIR)/crypto.debug.dll +else + rm -f $(LIBDIR)/crypto.so + rm -f $(LIBDIR)/crypto.debug.so + rm -f $(LIBDIR)/crypto.valgrind.so +endif + rm -f $(OBJDIR)/crypto.o + rm -f $(OBJDIR)/crypto.debug.o + rm -f $(OBJDIR)/crypto.valgrind.o rm -f core *~ docs: diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 68079f06c7..85614a84c2 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -64,8 +64,8 @@ # define ERL_VALGRIND_ASSERT_MEM_DEFINED(ptr,size) \ ((void) ((VALGRIND_CHECK_MEM_IS_DEFINED(ptr,size) == 0) ? 1 : \ - (fprintf(stderr,"\r\n####### VALGRIND_ASSSERT(%p,%d) failed at %s:%d\r\n",\ - (ptr),(size), __FILE__, __LINE__), abort(), 0))) + (fprintf(stderr,"\r\n####### VALGRIND_ASSSERT(%p,%ld) failed at %s:%d\r\n",\ + (ptr),(long)(size), __FILE__, __LINE__), abort(), 0))) #else # define ERL_VALGRIND_MAKE_MEM_DEFINED(ptr,size) # define ERL_VALGRIND_ASSERT_MEM_DEFINED(ptr,size) @@ -706,12 +706,13 @@ static int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Lo,Hi) */ - BIGNUM *bn_from, *bn_to, *bn_rand; + BIGNUM *bn_from = NULL, *bn_to, *bn_rand; unsigned char* data; unsigned dlen; ERL_NIF_TERM ret; if (!get_bn_from_mpint(env, argv[0], &bn_from) || !get_bn_from_mpint(env, argv[1], &bn_rand)) { + if (bn_from) BN_free(bn_from); return enif_make_badarg(env); } @@ -770,7 +771,7 @@ static int inspect_mpint(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifBinary* bin) static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (DigestType,Data,Signature,Key=[P, Q, G, Y]) */ ErlNifBinary data_bin, sign_bin; - BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_y; + BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL; unsigned char hmacbuf[SHA_DIGEST_LENGTH]; ERL_NIF_TERM head, tail; DSA *dsa; @@ -786,6 +787,11 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv || !enif_get_list_cell(env, tail, &head, &tail) || !get_bn_from_mpint(env, head, &dsa_y) || !enif_is_empty_list(env,tail)) { + badarg: + if (dsa_p) BN_free(dsa_p); + if (dsa_q) BN_free(dsa_q); + if (dsa_g) BN_free(dsa_g); + if (dsa_y) BN_free(dsa_y); return enif_make_badarg(env); } if (argv[0] == atom_sha && inspect_mpint(env, argv[1], &data_bin)) { @@ -796,7 +802,7 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv memcpy(hmacbuf, data_bin.data, SHA_DIGEST_LENGTH); } else { - return enif_make_badarg(env); + goto badarg; } dsa = DSA_new(); @@ -950,7 +956,7 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N RC4(rc4_key, data.size, data.data, enif_make_new_binary(env, data.size, &new_data)); - return enif_make_tuple2(env,argv[0],new_data); + return enif_make_tuple2(env,new_state,new_data); } static ERL_NIF_TERM rc2_40_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -1119,7 +1125,7 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER enif_alloc_binary(RSA_size(rsa), &ret_bin); if (argv[3] == atom_true) { - ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,data_len); + ERL_VALGRIND_ASSERT_MEM_DEFINED(data_bin.data,data_bin.size); i = RSA_public_encrypt(data_bin.size, data_bin.data, ret_bin.data, rsa, padding); if (i > 0) { @@ -1139,6 +1145,7 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER return enif_make_binary(env,&ret_bin); } else { + enif_release_binary(&ret_bin); return atom_error; } } @@ -1167,7 +1174,7 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE enif_alloc_binary(RSA_size(rsa), &ret_bin); if (argv[3] == atom_true) { - ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,data_len); + ERL_VALGRIND_ASSERT_MEM_DEFINED(data_bin.data,data_bin.size); i = RSA_private_encrypt(data_bin.size, data_bin.data, ret_bin.data, rsa, padding); if (i > 0) { @@ -1187,6 +1194,7 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE return enif_make_binary(env,&ret_bin); } else { + enif_release_binary(&ret_bin); return atom_error; } } @@ -1266,7 +1274,7 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ || !enif_get_list_cell(env, tail, &head, &tail) || !get_bn_from_mpint(env, head, &dh_params->g) || !enif_is_empty_list(env, tail)) { - + DH_free(dh_params); return enif_make_badarg(env); } @@ -1293,7 +1301,7 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */ DH* dh_params = DH_new(); - BIGNUM* pubkey; + BIGNUM* pubkey = NULL; int i; ErlNifBinary ret_bin; ERL_NIF_TERM ret, head, tail; @@ -1321,6 +1329,7 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T ret = atom_error; } } + if (pubkey) BN_free(pubkey); DH_free(dh_params); return ret; } diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 19fa495b7d..71fd91cafd 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -93,22 +93,42 @@ -define(CRYPTO_NIF_VSN,101). on_load() -> - LibName = "crypto", + LibBaseName = "crypto", PrivDir = code:priv_dir(crypto), - Lib1 = filename:join([PrivDir, "lib", LibName]), - Status = case erlang:load_nif(Lib1, ?CRYPTO_NIF_VSN) of + LibName = case erlang:system_info(build_type) of + opt -> + LibBaseName; + Type -> + LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type), + case (filelib:wildcard( + filename:join( + [PrivDir, + "lib", + LibTypeName ++ "*"])) /= []) orelse + (filelib:wildcard( + filename:join( + [PrivDir, + "lib", + erlang:system_info(system_architecture), + LibTypeName ++ "*"])) /= []) of + true -> LibTypeName; + false -> LibBaseName + end + end, + Lib = filename:join([PrivDir, "lib", LibName]), + Status = case erlang:load_nif(Lib, ?CRYPTO_NIF_VSN) of ok -> ok; {error, {load_failed, _}}=Error1 -> - LibDir2 = + ArchLibDir = filename:join([PrivDir, "lib", erlang:system_info(system_architecture)]), Candidate = - filelib:wildcard(filename:join([LibDir2,LibName ++ "*" ])), + filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])), case Candidate of [] -> Error1; _ -> - Lib2 = filename:join([LibDir2, LibName]), - erlang:load_nif(Lib2, ?CRYPTO_NIF_VSN) + ArchLib = filename:join([ArchLibDir, LibName]), + erlang:load_nif(ArchLib, ?CRYPTO_NIF_VSN) end; Error1 -> Error1 end, @@ -119,7 +139,6 @@ on_load() -> "OpenSSL might not be installed on this system.~n",[E,Str]), Status end. - nif_stub_error(Line) -> erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 576949d38d..06b284d50d 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -54,6 +54,7 @@ dh/1, exor_test/1, rc4_test/1, + rc4_stream_test/1, blowfish_cfb64/1, smp/1, cleanup/1]). @@ -89,6 +90,7 @@ all(suite) -> dh, exor_test, rc4_test, + rc4_stream_test, mod_exp_test, blowfish_cfb64, smp], @@ -979,6 +981,21 @@ rc4_test(Config) when is_list(Config) -> CT2 = binary_to_list(crypto:rc4_encrypt(K, R2)), ok. +rc4_stream_test(doc) -> + ["Test rc4 stream encryption ."]; +rc4_stream_test(suite) -> + []; +rc4_stream_test(Config) when is_list(Config) -> + CT1 = <<"hej">>, + CT2 = <<" p� dig">>, + K = "apaapa", + State0 = crypto:rc4_set_key(K), + {State1, R1} = crypto:rc4_encrypt_with_state(State0, CT1), + {_State2, R2} = crypto:rc4_encrypt_with_state(State1, CT2), + R = list_to_binary([R1, R2]), + <<71,112,14,44,140,33,212,144,155,47>> = R, + ok. + blowfish_cfb64(doc) -> ["Test Blowfish encrypt/decrypt."]; blowfish_cfb64(suite) -> []; blowfish_cfb64(Config) when is_list(Config) -> @@ -1029,7 +1046,7 @@ worker_loop(0, _) -> worker_loop(N, Config) -> Funcs = { md5, md5_update, md5_mac, md5_mac_io, sha, sha_update, des_cbc, aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test, - rsa_verify_test, exor_test, rc4_test, mod_exp_test }, + rsa_verify_test, exor_test, rc4_test, rc4_stream_test, mod_exp_test }, F = element(random:uniform(size(Funcs)),Funcs), %%io:format("worker ~p calling ~p\n",[self(),F]), diff --git a/lib/debugger/test/Makefile b/lib/debugger/test/Makefile new file mode 100644 index 0000000000..ac929038f7 --- /dev/null +++ b/lib/debugger/test/Makefile @@ -0,0 +1,106 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1998-2010. 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_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES= \ + andor_SUITE \ + bs_bincomp_SUITE \ + bs_construct_SUITE \ + bs_match_bin_SUITE \ + bs_match_int_SUITE \ + bs_match_misc_SUITE \ + bs_match_tail_SUITE \ + bs_utf_SUITE \ + bug_SUITE \ + erl_eval_SUITE \ + dbg_ui_SUITE \ + debugger_SUITE \ + int_SUITE \ + int_break_SUITE \ + int_eval_SUITE \ + guard_SUITE \ + exception_SUITE \ + fun_SUITE \ + lc_SUITE \ + record_SUITE \ + trycatch_SUITE \ + test_lib \ + cleanup + +ERL_FILES= $(MODULES:%=%.erl) + +TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) +INSTALL_PROGS= $(TARGET_FILES) + +EMAKEFILE=Emakefile + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/debugger_test + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +ERL_MAKE_FLAGS += +ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include + +EBIN = . + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +make_emakefile: + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ + > $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' \ + >> $(EMAKEFILE) + +tests debug opt: make_emakefile + erl $(ERL_MAKE_FLAGS) -make + +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) $(GEN_FILES) + rm -f core + +docs: + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + +release_tests_spec: make_emakefile + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR) + $(INSTALL_DATA) debugger.spec $(RELSYSDIR) + chmod -f -R u+w $(RELSYSDIR) + @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + +release_docs_spec: diff --git a/lib/debugger/test/andor_SUITE.erl b/lib/debugger/test/andor_SUITE.erl new file mode 100644 index 0000000000..3482a22a34 --- /dev/null +++ b/lib/debugger/test/andor_SUITE.erl @@ -0,0 +1,305 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2010. 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(andor_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + t_andalso/1,t_orelse/1,inside/1,overlap/1, + combined/1,in_case/1]). + +-include("test_server.hrl"). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + ?line Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +cases() -> + [t_andalso,t_orelse,inside,overlap,combined,in_case]. + +t_andalso(Config) when is_list(Config) -> + Bs = [true,false], + Ps = [{X,Y} || X <- Bs, Y <- Bs], + lists:foreach(fun (P) -> t_andalso_1(P) end, Ps), + + ?line true = true andalso true, + ?line false = true andalso false, + ?line false = false andalso true, + ?line false = false andalso false, + + ?line false = false andalso glurf, + ?line false = false andalso exit(exit_now), + + ?line true = not id(false) andalso not id(false), + ?line false = not id(false) andalso not id(true), + ?line false = not id(true) andalso not id(false), + ?line false = not id(true) andalso not id(true), + + ?line {'EXIT',{badarg,_}} = (catch not id(glurf) andalso id(true)), + ?line {'EXIT',{badarg,_}} = (catch not id(false) andalso not id(glurf)), + ?line false = id(false) andalso not id(glurf), + ?line false = false andalso not id(glurf), + + ok. + +t_orelse(Config) when is_list(Config) -> + Bs = [true,false], + Ps = [{X,Y} || X <- Bs, Y <- Bs], + lists:foreach(fun (P) -> t_orelse_1(P) end, Ps), + + ?line true = true orelse true, + ?line true = true orelse false, + ?line true = false orelse true, + ?line false = false orelse false, + + ?line true = true orelse glurf, + ?line true = true orelse exit(exit_now), + + ?line true = not id(false) orelse not id(false), + ?line true = not id(false) orelse not id(true), + ?line true = not id(true) orelse not id(false), + ?line false = not id(true) orelse not id(true), + + ?line {'EXIT',{badarg,_}} = (catch not id(glurf) orelse id(true)), + ?line {'EXIT',{badarg,_}} = (catch not id(true) orelse not id(glurf)), + ?line true = id(true) orelse not id(glurf), + ?line true = true orelse not id(glurf), + + ok. + +t_andalso_1({X,Y}) -> + io:fwrite("~w andalso ~w: ",[X,Y]), + V1 = echo(X) andalso echo(Y), + V1 = if + X andalso Y -> true; + true -> false + end, + check(V1, X and Y). + +t_orelse_1({X,Y}) -> + io:fwrite("~w orelse ~w: ",[X,Y]), + V1 = echo(X) orelse echo(Y), + V1 = if + X orelse Y -> true; + true -> false + end, + check(V1, X or Y). + +inside(Config) when is_list(Config) -> + ?line true = inside(-8, 1), + ?line false = inside(-53.5, -879798), + ?line false = inside(1.0, -879), + ?line false = inside(59, -879), + ?line false = inside(-11, 1.0), + ?line false = inside(100, 0.2), + ?line false = inside(100, 1.2), + ?line false = inside(-53.5, 4), + ?line false = inside(1.0, 5.3), + ?line false = inside(59, 879), + ok. + +inside(Xm, Ym) -> + X = -10.0, + Y = -2.0, + W = 20.0, + H = 4.0, + Res = inside(Xm, Ym, X, Y, W, H), + Res = if + X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H -> true; + true -> false + end, + case not id(Res) of + Outside -> + Outside = if + not(X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H) -> true; + true -> false + end + end, + {Res,Xm,Ym,X,Y,W,H} = inside_guard(Xm, Ym, X, Y, W, H), + io:format("~p =< ~p andalso ~p < ~p andalso ~p =< ~p andalso ~p < ~p ==> ~p", + [X,Xm,Xm,X+W,Y,Ym,Ym,Y+H,Res]), + Res. + +inside(Xm, Ym, X, Y, W, H) -> + X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H. + +inside_guard(Xm, Ym, X, Y, W, H) when X =< Xm andalso Xm < X+W + andalso Y =< Ym andalso Ym < Y+H -> + {true,Xm,Ym,X,Y,W,H}; +inside_guard(Xm, Ym, X, Y, W, H) -> + {false,Xm,Ym,X,Y,W,H}. + +overlap(Config) when is_list(Config) -> + ?line true = overlap(7.0, 2.0, 8.0, 0.5), + ?line true = overlap(7.0, 2.0, 8.0, 2.5), + ?line true = overlap(7.0, 2.0, 5.3, 2), + ?line true = overlap(7.0, 2.0, 0.0, 100.0), + + ?line false = overlap(-1, 2, -35, 0.5), + ?line false = overlap(-1, 2, 777, 0.5), + ?line false = overlap(-1, 2, 2, 10), + ?line false = overlap(2, 10, 12, 55.3), + ok. + +overlap(Pos1, Len1, Pos2, Len2) -> + Res = case Pos1 of + Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2) + orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) -> + true; + Pos1 -> false + end, + Res = (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2) + orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1), + Res = case Pos1 of + Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2) + orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) -> + true; + Pos1 -> false + end, + id(Res). + + +-define(COMB(A,B,C), (A andalso B orelse C)). + +combined(Config) when is_list(Config) -> + ?line false = comb(false, false, false), + ?line true = comb(false, false, true), + ?line false = comb(false, true, false), + ?line true = comb(false, true, true), + + ?line false = comb(true, false, false), + ?line true = comb(true, true, false), + ?line true = comb(true, false, true), + ?line true = comb(true, true, true), + + ?line false = comb(false, blurf, false), + ?line true = comb(false, blurf, true), + ?line true = comb(true, true, blurf), + + ?line false = ?COMB(false, false, false), + ?line true = ?COMB(false, false, true), + ?line false = ?COMB(false, true, false), + ?line true = ?COMB(false, true, true), + + ?line false = ?COMB(true, false, false), + ?line true = ?COMB(true, true, false), + ?line true = ?COMB(true, false, true), + ?line true = ?COMB(true, true, true), + + ?line false = ?COMB(false, blurf, false), + ?line true = ?COMB(false, blurf, true), + ?line true = ?COMB(true, true, blurf), + + ok. +-undef(COMB). + +comb(A, B, C) -> + Res = A andalso B orelse C, + Res = if + A andalso B orelse C -> true; + true -> false + end, + NotRes = if + not(A andalso B orelse C) -> true; + true -> false + end, + NotRes = id(not Res), + Res = A andalso B orelse C, + Res = if + A andalso B orelse C -> true; + true -> false + end, + NotRes = id(not Res), + Res = if + A andalso B orelse C -> true; + true -> false + end, + id(Res). + +%% Test that a boolean expression in a case expression is properly +%% optimized (in particular, that the error behaviour is correct). +in_case(Config) when is_list(Config) -> + ?line edge_rings = in_case_1(1, 1, 1, 1, 1), + ?line not_loop = in_case_1(0.5, 1, 1, 1, 1), + ?line loop = in_case_1(0.5, 0.9, 1.1, 1, 4), + ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, 0)), + ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, nan)), + ?line {'EXIT',{badarg,_}} = (catch in_case_1(1, 1, 1, blurf, 1)), + ?line {'EXIT',{badarith,_}} = (catch in_case_1([nan], 1, 1, 1, 1)), + ok. + +in_case_1(LenUp, LenDw, LenN, Rotation, Count) -> + Res = in_case_1_body(LenUp, LenDw, LenN, Rotation, Count), + Res = in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count), + Res. + +in_case_1_body(LenUp, LenDw, LenN, Rotation, Count) -> + case (LenUp/Count > 0.707) and (LenN/Count > 0.707) and + (abs(Rotation) > 0.707) of + true -> + edge_rings; + false -> + case (LenUp >= 1) or (LenDw >= 1) or + (LenN =< 1) or (Count < 4) of + true -> + not_loop; + false -> + loop + end + end. + +in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count) -> + case (LenUp/Count > 0.707) andalso (LenN/Count > 0.707) andalso + (abs(Rotation) > 0.707) of + true -> edge_rings; + false when LenUp >= 1 orelse LenDw >= 1 orelse + LenN =< 1 orelse Count < 4 -> not_loop; + false -> loop + end. + +check(V1, V0) -> + if V1 /= V0 -> + io:fwrite("error: ~w.\n", [V1]), + ?t:fail(); + true -> + io:fwrite("ok: ~w.\n", [V1]) + end. + +echo(X) -> + io:fwrite("eval(~w); ",[X]), + X. + +id(I) -> I. diff --git a/lib/debugger/test/bs_bincomp_SUITE.erl b/lib/debugger/test/bs_bincomp_SUITE.erl new file mode 100644 index 0000000000..8ca2b36f1c --- /dev/null +++ b/lib/debugger/test/bs_bincomp_SUITE.erl @@ -0,0 +1,106 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2010. 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% +%% + +%% +%% Originally based on Per Gustafsson's test suite. +%% + +-module(bs_bincomp_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + byte_aligned/1,bit_aligned/1,extended_byte_aligned/1, + extended_bit_aligned/1,mixed/1]). + +-include("test_server.hrl"). + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +all(suite) -> + [byte_aligned,bit_aligned,extended_byte_aligned, + extended_bit_aligned,mixed]. + + +byte_aligned(Config) when is_list(Config) -> + ?line <<"abcdefg">> = << <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>, + ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> = + << <<X:32/little>> || <<X:32>> <= <<1:32,2:32,3:32,4:32>> >>, + ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> = + << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>, + ok. + +bit_aligned(Config) when is_list(Config) -> + ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = + << <<(X+32):7>> || <<X>> <= <<"ABCDEFG">> >>, + ?line <<"ABCDEFG">> = + << <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> >>, + ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> = + << <<X:31/little>> || <<X:31>> <= <<1:31,2:31,3:31,4:31>> >>, + ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> = + << <<X:31/little>> || <<X:15>> <= <<1:15,2:15,3:15,4:15>> >>, + ok. + +extended_byte_aligned(Config) when is_list(Config) -> + ?line <<"abcdefg">> = << <<(X+32)>> || X <- "ABCDEFG" >>, + ?line "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>], + ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> = + << <<X:32/little>> || X <- [1,2,3,4] >>, + ?line [256,512,768,1024] = + [X || <<X:16/little>> <= <<1:16,2:16,3:16,4:16>>], + ok. + +extended_bit_aligned(Config) when is_list(Config) -> + ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = + << <<(X+32):7>> || X <- "ABCDEFG" >>, + ?line "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>], + ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> = + << <<X:31/little>> || X <- [1,2,3,4] >>, + ?line [256,512,768,1024] = + [X || <<X:15/little>> <= <<1:15,2:15,3:15,4:15>>], + ok. + +mixed(Config) when is_list(Config) -> + ?line <<2,3,3,4,4,5,5,6>> = + << <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>> >>, + ?line <<2,3,3,4,4,5,5,6>> = + << <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, Y <- [1,2] >>, + ?line <<2,3,3,4,4,5,5,6>> = + << <<(X+Y)>> || X <- [1,2,3,4], Y <- [1,2] >>, + ?line [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>>], + ?line [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X>> <= <<1,2,3,4>>, Y <- [1,2]], + ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + << <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>> >>, + ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + << <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2] >>, + ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + << <<(X+Y):3>> || X <- [1,2,3,4], Y <- [1,2] >>, + ?line [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>>], + ?line [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2]], + ok. diff --git a/lib/debugger/test/bs_construct_SUITE.erl b/lib/debugger/test/bs_construct_SUITE.erl new file mode 100644 index 0000000000..efc125c582 --- /dev/null +++ b/lib/debugger/test/bs_construct_SUITE.erl @@ -0,0 +1,432 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2010. 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(bs_construct_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + test1/1, test2/1, test3/1, test4/1, test5/1, testf/1, not_used/1, in_guard/1, + coerce_to_float/1]). + +-include("test_server.hrl"). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [test1, test2, test3, test4, test5, testf, + not_used, in_guard, coerce_to_float]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +big(1) -> + 57285702734876389752897683. + +i(X) -> X. + +r(L) -> + lists:reverse(L). + +-define(T(B, L), {B, ??B, L}). +-define(N(B), {B, ??B, unknown}). + +-define(FAIL(Expr), ?line {'EXIT',{badarg,_}} = (catch Expr)). + +l(I_13, I_big1) -> + [ + ?T(<<-43>>, + [256-43]), + ?T(<<56>>, + [56]), + ?T(<<1,2>>, + [1, 2]), + ?T(<<4:4, 7:4>>, + [4*16+7]), + ?T(<<777:16/big>>, + [3, 9]), + ?T(<<777:16/little>>, + [9, 3]), + ?T(<<0.0:32/float>>, + [0,0,0,0]), + ?T(<<0.125:32/float>>, + [62,0,0,0]), + ?T(<<0.125:32/little-float>>, + [0,0,0,62]), + ?T(<<I_big1:32>>, + [138, 99, 0, 147]), + ?T(<<57285702734876389752897684:32>>, + [138, 99, 0, 148]), + ?T(<<I_big1:32/little>>, + r([138, 99, 0, 147])), + ?T(<<-1:17/unit:8>>, + lists:duplicate(17, 255)), + + ?T(<<I_13>>, + [13]), + + ?T(<<4:8/unit:2,5:2/unit:8>>, + [0, 4, 0, 5]), + + ?T(<<1:1, 0:6, 1:1>>, + [129]), + ?T(<<1:1/little, 0:6/little, 1:1/little>>, + [129]), + + ?T(<<<<1,2>>/binary>>, + [1, 2]), + ?T(<<<<1,2>>:1/binary>>, + [1]), + ?T(<<4,3,<<1,2>>:1/binary>>, + [4,3,1]), + + ?T(<<(256*45+47)>>, + [47]), + + ?T(<<57:0>>, + []), + + ?T(<<"apa">>, + "apa"), + + ?T(<<1:3,"string",9:5>>, + [46,110,142,77,45,204,233]), + + ?T(<<>>, + []), + + ?T(<<37.98:64/native-float>>, + native_3798()), + + ?T(<<32978297842987249827298387697777669766334937:128/native-integer>>, + native_bignum()) + + ]. + +native_3798() -> + case <<1:16/native>> of + <<0,1>> -> [64,66,253,112,163,215,10,61]; + <<1,0>> -> [61,10,215,163,112,253,66,64] + end. + +native_bignum() -> + case <<1:16/native>> of + <<0,1>> -> [129,205,18,177,1,213,170,101,39,231,109,128,176,11,73,217]; + <<1,0>> -> [217,73,11,176,128,109,231,39,101,170,213,1,177,18,205,129] + end. + +evaluate(Str, Vars) -> + {ok,Tokens,_} = + erl_scan:string(Str ++ " . "), + {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + case erl_eval:expr(Expr, Vars) of + {value, Result, _} -> + Result + end. + +eval_list([], _Vars) -> + []; +eval_list([{C_bin, Str, Bytes} | Rest], Vars) -> + case catch evaluate(Str, Vars) of + {'EXIT', Error} -> + io:format("Evaluation error: ~p, ~p, ~p~n", [Str, Vars, Error]), + exit(Error); + E_bin -> + [{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)] + end. + +one_test({C_bin, E_bin, Str, Bytes}) when list(Bytes) -> + io:format(" ~s, ~p~n", [Str, Bytes]), + Bin = list_to_binary(Bytes), + if + C_bin == Bin -> + ok; + true -> + io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n", + [Str, Bytes, binary_to_list(C_bin)]), + test_server:fail(comp) + end, + if + E_bin == Bin -> + ok; + true -> + io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n", + [Str, Bytes, binary_to_list(E_bin)]), + test_server:fail(comp) + end; +one_test({C_bin, E_bin, Str, Result}) -> + io:format(" ~s ~p~n", [Str, C_bin]), + if + C_bin == E_bin -> + ok; + true -> + Arbitrary = case Result of + unknown -> + size(C_bin); + _ -> + Result + end, + case equal_lists(binary_to_list(C_bin), + binary_to_list(E_bin), + Arbitrary) of + false -> + io:format("ERROR: Compiled not equal to interpreted:" + "~n ~p, ~p.~n", + [binary_to_list(C_bin), binary_to_list(E_bin)]), + test_server:fail(comp); + 0 -> + ok; + %% For situations where the final bits may not matter, like + %% for floats: + N when integer(N) -> + io:format("Info: compiled and interpreted differ in the" + " last bytes:~n ~p, ~p.~n", + [binary_to_list(C_bin), binary_to_list(E_bin)]), + ok + end + end. + +equal_lists([], [], _) -> + 0; +equal_lists([], _, _) -> + false; +equal_lists(_, [], _) -> + false; +equal_lists([A|AR], [A|BR], R) -> + equal_lists(AR, BR, R); +equal_lists(A, B, R) -> + if + length(A) /= length(B) -> + false; + length(A) =< R -> + R; + true -> + false + end. + +%%% Simple working cases +test1(suite) -> []; +test1(Config) when list(Config) -> + ?line I_13 = i(13), + ?line I_big1 = big(1), + ?line Vars = [{'I_13', I_13}, + {'I_big1', I_big1}], + ?line lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1), Vars)). + +%%% Misc + +%%% <<A:S, A:(N-S)>> +comp(N, A, S) -> + M1 = (1 bsl S) - 1, + M2 = (1 bsl (N-S)) - 1, + [((A band M1) bsl (N-S)) bor (A band M2)]. + +gen(N, S, A) -> + [?T(<<A:S, A:(N-S)>>, comp(N, A, S))]. + +gen_l(N, S, A) -> + [?T(<<A:S/little, A:(N-S)/little>>, comp(N, A, S))]. + +test2(suite) -> []; +test2(Config) when list(Config) -> + ?line test2(0, 8, 2#10101010101010101), + ?line test2(0, 8, 2#1111111111). + +test2(End, End, _) -> + ok; +test2(I, End, A) -> + test2(I, A), + test2(I+1, End, A). + +test2(S, A) -> + N = 8, + Vars = [{'A',A}, {'N',N}, {'S',S}], + io:format("Vars: ~p\n", [Vars]), + lists:foreach(fun one_test/1, eval_list(gen(N, S, A), Vars)), + lists:foreach(fun one_test/1, eval_list(gen_l(N, S, A), Vars)). + +%%% Tests without facit + +t3() -> + [?N(<<4711:13, 9876:13, 3:6>>), + ?N(<<4.57:64/float>>), + ?N(<<4.57:32/float>>), + + ?N(<<>>) + ]. + +test3(suite) -> []; +test3(Config) when list(Config) -> + ?line Vars = [], + ?line lists:foreach(fun one_test/1, eval_list(t3(), Vars)). + +gen_u(N, S, A) -> + [?N(<<A:S, A:(N-S)>>)]. + +gen_u_l(N, S, A) -> + [?N(<<A:S/little, A:(N-S)/little>>)]. + +test4(suite) -> []; +test4(Config) when list(Config) -> + ?line test4(0, 16, 2#10101010101010101), + ?line test4(0, 16, 2#1111111111). + +test4(End, End, _) -> + ok; +test4(I, End, A) -> + test4(I, A), + test4(I+1, End, A). + +test4(S, A) -> + N = 16, + Vars = [{'A', A}, {'N', 16}, {'S', S}], + lists:foreach(fun one_test/1, eval_list(gen_u(N, S, A), Vars)), + lists:foreach(fun one_test/1, eval_list(gen_u_l(N, S, A), Vars)). + +gen_b(N, S, A) -> + [?T(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>, + binary_to_list(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>))]. + +test5(suite) -> []; +test5(doc) -> ["OTP-3995"]; +test5(Config) when list(Config) -> + ?line test5(0, 8, <<73>>), + ?line test5(0, 8, <<68>>). + +test5(End, End, _) -> + ok; +test5(I, End, A) -> + test5(I, A), + test5(I+1, End, A). + +test5(S, A) -> + N = 8, + Vars = [{'A', A}, {'N', 8}, {'S', S}], + lists:foreach(fun one_test/1, eval_list(gen_b(N, S, A), Vars)). + +%%% Failure cases +testf(suite) -> []; +testf(Config) when list(Config) -> + ?FAIL(<<3.14>>), + ?FAIL(<<<<1,2>>>>), + + ?FAIL(<<2.71/binary>>), + ?FAIL(<<24334/binary>>), + ?FAIL(<<24334344294788947129487129487219847/binary>>), + + ?FAIL(<<<<1,2,3>>/float>>), + + %% Negative field widths. + testf_1(-8, <<1,2,3,4,5>>), + + ?FAIL(<<42:(-16)>>), + ?FAIL(<<3.14:(-8)/float>>), + ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>), + ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>), + ?FAIL(<<<<23,56,0,2>>:(anka)>>), + + ok. + +testf_1(W, B) -> + ?FAIL(<<42:W>>), + ?FAIL(<<3.14:W/float>>), + ?FAIL(<<B:W/binary>>). + +not_used(doc) -> + "Test that constructed binaries that are not used will still give an exception."; +not_used(Config) when is_list(Config) -> + ?line ok = not_used1(3, <<"dum">>), + ?line ?FAIL(not_used1(3, "dum")), + ?line ?FAIL(not_used2(444, -2)), + ?line ?FAIL(not_used2(444, anka)), + ?line ?FAIL(not_used3(444)), + ok. + +not_used1(I, BinString) -> + <<I:32,BinString/binary>>, + ok. + +not_used2(I, Sz) -> + <<I:Sz>>, + ok. + +not_used3(I) -> + <<I:(-8)>>, + ok. + +in_guard(Config) when list(Config) -> + ?line 1 = in_guard(<<16#74ad:16>>, 16#e95, 5), + ?line 2 = in_guard(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>), + ?line 3 = in_guard(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415), + nope = in_guard(<<1>>, 42, b), + nope = in_guard(<<1>>, a, b), + nope = in_guard(<<1,2>>, 1, 1), + nope = in_guard(<<4,5>>, 1, 2.71), + nope = in_guard(<<4,5>>, 1, <<12,13>>), + ok. + +in_guard(Bin, A, B) when <<A:13,B:3>> == Bin -> 1; +in_guard(Bin, A, B) when <<A:16,B/binary>> == Bin -> 2; +in_guard(Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3; +in_guard(Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> cant_happen; +in_guard(_, _, _) -> nope. + +-define(COF(Int0), + ?line (fun(Int) -> + true = <<Int:32/float>> =:= <<(float(Int)):32/float>>, + true = <<Int:64/float>> =:= <<(float(Int)):64/float>> + end)(nonliteral(Int0)), + ?line true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>, + ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). + +-define(COF64(Int0), + ?line (fun(Int) -> + true = <<Int:64/float>> =:= <<(float(Int)):64/float>> + end)(nonliteral(Int0)), + ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). + +nonliteral(X) -> X. + +coerce_to_float(Config) when list(Config) -> + ?COF(0), + ?COF(-1), + ?COF(1), + ?COF(42), + ?COF(255), + ?COF(-255), + ?COF(38474), + ?COF(387498738948729893849444444443), + ?COF(-37489378937773899999999999999993), + ?COF64(298748888888888888888888888883478264866528467367364766666666666666663), + ?COF64(-367546729879999999999947826486652846736736476555566666663), + ok. diff --git a/lib/debugger/test/bs_match_bin_SUITE.erl b/lib/debugger/test/bs_match_bin_SUITE.erl new file mode 100644 index 0000000000..3966dc41ef --- /dev/null +++ b/lib/debugger/test/bs_match_bin_SUITE.erl @@ -0,0 +1,114 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2010. 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(bs_match_bin_SUITE). + +-author('[email protected]'). +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + byte_split_binary/1,bit_split_binary/1]). + +-include("test_server.hrl"). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [byte_split_binary,bit_split_binary]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +byte_split_binary(doc) -> "Tries to split a binary at all byte-aligned positions."; +byte_split_binary(suite) -> []; +byte_split_binary(Config) when list(Config) -> + ?line L = lists:seq(0, 57), + ?line B = mkbin(L), + ?line byte_split(L, B, size(B)). + +byte_split(L, B, Pos) when Pos >= 0 -> + ?line Sz1 = Pos, + ?line Sz2 = size(B) - Pos, + ?line <<B1:Sz1/binary,B2:Sz2/binary>> = B, + ?line B1 = list_to_binary(lists:sublist(L, 1, Pos)), + ?line B2 = list_to_binary(lists:nthtail(Pos, L)), + ?line byte_split(L, B, Pos-1); +byte_split(_L, _B, _) -> ok. + +bit_split_binary(doc) -> "Tries to split a binary at all positions."; +bit_split_binary(suite) -> []; +bit_split_binary(Config) when list(Config) -> + Fun = fun(Bin, List, SkipBef, N) -> + ?line SkipAft = 8*size(Bin) - N - SkipBef, + io:format("~p, ~p, ~p", [SkipBef,N,SkipAft]), + ?line <<_I1:SkipBef,OutBin:N/binary-unit:1,_I2:SkipAft>> = Bin, + ?line OutBin = make_bin_from_list(List, N) + end, + ?line bit_split_binary1(Fun, erlang:md5(<<1,2,3>>)), + ok. + +bit_split_binary1(Action, Bin) -> + BitList = bits_to_list(binary_to_list(Bin), 16#80), + bit_split_binary2(Action, Bin, BitList, 0). + +bit_split_binary2(Action, Bin, [_|T]=List, Bef) -> + bit_split_binary3(Action, Bin, List, Bef, size(Bin)*8), + bit_split_binary2(Action, Bin, T, Bef+1); +bit_split_binary2(_Action, _Bin, [], _Bef) -> ok. + +bit_split_binary3(Action, Bin, List, Bef, Aft) when Bef =< Aft -> + Action(Bin, List, Bef, (Aft-Bef) div 8 * 8), + bit_split_binary3(Action, Bin, List, Bef, Aft-8); +bit_split_binary3(_, _, _, _, _) -> ok. + +make_bin_from_list(_List, 0) -> + mkbin([]); +make_bin_from_list(List, N) -> + list_to_binary([make_int(List, 8, 0), + make_bin_from_list(lists:nthtail(8, List), N-8)]). + + +make_int(_List, 0, Acc) -> Acc; +make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H). + +bits_to_list([_H|T], 0) -> bits_to_list(T, 16#80); +bits_to_list([H|_]=List, Mask) -> + [case H band Mask of + 0 -> 0; + _ -> 1 + end|bits_to_list(List, Mask bsr 1)]; +bits_to_list([], _) -> []. + + +mkbin(L) when list(L) -> list_to_binary(L). diff --git a/lib/debugger/test/bs_match_int_SUITE.erl b/lib/debugger/test/bs_match_int_SUITE.erl new file mode 100644 index 0000000000..1159ac9ef8 --- /dev/null +++ b/lib/debugger/test/bs_match_int_SUITE.erl @@ -0,0 +1,230 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2010. 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(bs_match_int_SUITE). + +-author('[email protected]'). +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + integer/1,signed_integer/1,dynamic/1,more_dynamic/1,mml/1]). + +-include("test_server.hrl"). + +-import(lists, [seq/2]). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [integer,signed_integer,dynamic,more_dynamic,mml]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(4)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +integer(suite) -> []; +integer(Config) when list(Config) -> + ?line 0 = get_int(mkbin([])), + ?line 0 = get_int(mkbin([0])), + ?line 42 = get_int(mkbin([42])), + ?line 255 = get_int(mkbin([255])), + ?line 256 = get_int(mkbin([1,0])), + ?line 257 = get_int(mkbin([1,1])), + ?line 258 = get_int(mkbin([1,2])), + ?line 258 = get_int(mkbin([1,2])), + ?line 65534 = get_int(mkbin([255,254])), + ?line 16776455 = get_int(mkbin([255,253,7])), + ?line 4245492555 = get_int(mkbin([253,13,19,75])), + ?line Eight = [200,1,19,128,222,42,97,111], + ?line cmp128(Eight, uint(Eight)), + ?line fun_clause(catch get_int(mkbin(seq(1,5)))), + ok. + +get_int(<<I:0>>) -> I; +get_int(<<I:8>>) -> I; +get_int(<<I:16>>) -> I; +get_int(<<I:24>>) -> I; +get_int(<<I:32>>) -> I. + +cmp128(<<I:128>>, I) -> equal; +cmp128(_B, _I) -> not_equal. + +signed_integer(suite) -> []; +signed_integer(Config) when list(Config) -> + ?line {no_match,_} = sint(mkbin([])), + ?line {no_match,_} = sint(mkbin([1,2,3])), + ?line 127 = sint(mkbin([127])), + ?line -1 = sint(mkbin([255])), + ?line -128 = sint(mkbin([128])), + ?line 42 = sint(mkbin([42,255])), + ?line 127 = sint(mkbin([127,255])). + +sint(Bin) -> + case Bin of + <<I:8/signed>> -> I; + <<I:8/signed,_:3,_:5>> -> I; + Other -> {no_match,Other} + end. + +uint(L) -> uint(L, 0). +uint([H|T], Acc) -> uint(T, Acc bsl 8 bor H); +uint([], Acc) -> Acc. + +dynamic(Config) when list(Config) -> + dynamic(mkbin([255]), 8), + dynamic(mkbin([255,255]), 16), + dynamic(mkbin([255,255,255]), 24), + dynamic(mkbin([255,255,255,255]), 32), + ok. + +dynamic(Bin, S1) when S1 >= 0 -> + S2 = size(Bin) * 8 - S1, + dynamic(Bin, S1, S2, (1 bsl S1) - 1, (1 bsl S2) - 1), + dynamic(Bin, S1-1); +dynamic(_Bin, _) -> ok. + +dynamic(Bin, S1, S2, A, B) -> +% io:format("~p ~p ~p ~p\n", [S1,S2,A,B]), + case Bin of + <<A:S1,B:S2>> -> + io:format("~p ~p ~p ~p\n", [S1,S2,A,B]), + ok; + _Other -> + erlang:error(badmatch, [Bin,S1,S2,A,B]) + end. + +more_dynamic(doc) -> "Extract integers at different alignments and of different sizes."; +more_dynamic(Config) when list(Config) -> + + % Unsigned big-endian numbers. + Unsigned = fun(Bin, List, SkipBef, N) -> + SkipAft = 8*size(Bin) - N - SkipBef, + <<_I1:SkipBef,Int:N,_I2:SkipAft>> = Bin, + Int = make_int(List, N, 0) + end, + ?line more_dynamic1(Unsigned, funny_binary(42)), + + % Signed big-endian numbers. + Signed = fun(Bin, List, SkipBef, N) -> + SkipAft = 8*size(Bin) - N - SkipBef, + <<_I1:SkipBef,Int:N/signed,_I2:SkipAft>> = Bin, + case make_signed_int(List, N) of + Int -> ok; + Other -> + io:format("Bin = ~p,", [Bin]), + io:format("SkipBef = ~p, N = ~p", [SkipBef,N]), + io:format("Expected ~p, got ~p", [Int,Other]), + ?t:fail() + end + end, + ?line more_dynamic1(Signed, funny_binary(43)), + + % Unsigned little-endian numbers. + UnsLittle = fun(Bin, List, SkipBef, N) -> + SkipAft = 8*size(Bin) - N - SkipBef, + <<_I1:SkipBef,Int:N/little,_I2:SkipAft>> = Bin, + Int = make_int(big_to_little(List, N), N, 0) + end, + ?line more_dynamic1(UnsLittle, funny_binary(44)), + + % Signed little-endian numbers. + SignLittle = fun(Bin, List, SkipBef, N) -> + SkipAft = 8*size(Bin) - N - SkipBef, + <<_I1:SkipBef,Int:N/signed-little,_I2:SkipAft>> = Bin, + Little = big_to_little(List, N), + Int = make_signed_int(Little, N) + end, + ?line more_dynamic1(SignLittle, funny_binary(45)), + + ok. + +funny_binary(N) -> + B0 = erlang:md5([N]), + {B1,_B2} = split_binary(B0, size(B0) div 2), + B1. + +more_dynamic1(Action, Bin) -> + BitList = bits_to_list(binary_to_list(Bin), 16#80), + more_dynamic2(Action, Bin, BitList, 0). + +more_dynamic2(Action, Bin, [_|T]=List, Bef) -> + more_dynamic3(Action, Bin, List, Bef, size(Bin)*8), + more_dynamic2(Action, Bin, T, Bef+1); +more_dynamic2(_Action, _Bin, [], _Bef) -> ok. + +more_dynamic3(Action, Bin, List, Bef, Aft) when Bef =< Aft -> +%% io:format("~p, ~p", [Bef,Aft-Bef]), + Action(Bin, List, Bef, Aft-Bef), + more_dynamic3(Action, Bin, List, Bef, Aft-1); +more_dynamic3(_, _, _, _, _) -> ok. + +big_to_little(List, N) -> big_to_little(List, N, []). + +big_to_little([B0,B1,B2,B3,B4,B5,B6,B7|T], N, Acc) when N >= 8 -> + big_to_little(T, N-8, [B0,B1,B2,B3,B4,B5,B6,B7|Acc]); +big_to_little(List, N, Acc) -> lists:sublist(List, 1, N) ++ Acc. + +make_signed_int(_List, 0) -> 0; +make_signed_int([0|_T]=List, N) -> make_int(List, N, 0); +make_signed_int([1|_T]=List0, N) -> + List1 = reversed_sublist(List0, N, []), + List2 = two_complement_and_reverse(List1, 1, []), + -make_int(List2, length(List2), 0). + +reversed_sublist(_List, 0, Acc) -> Acc; +reversed_sublist([H|T], N, Acc) -> reversed_sublist(T, N-1, [H|Acc]). + +two_complement_and_reverse([H|T], Carry, Acc) -> + Sum = 1-H+Carry, + two_complement_and_reverse(T, Sum div 2, [Sum rem 2|Acc]); +two_complement_and_reverse([], Carry, Acc) -> [Carry|Acc]. + +make_int(_List, 0, Acc) -> Acc; +make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H). + +bits_to_list([_H|T], 0) -> bits_to_list(T, 16#80); +bits_to_list([H|_]=List, Mask) -> + [case H band Mask of + 0 -> 0; + _ -> 1 + end|bits_to_list(List, Mask bsr 1)]; +bits_to_list([], _) -> []. + +fun_clause({'EXIT',{function_clause,_}}) -> ok. +mkbin(L) when list(L) -> list_to_binary(L). + +mml(Config) when list(Config) -> + ?line single_byte_binary = mml_choose(<<42>>), + ?line multi_byte_binary = mml_choose(<<42,43>>). + +mml_choose(<<_A:8>>) -> single_byte_binary; +mml_choose(<<_A:8, _T/binary>>) -> multi_byte_binary. diff --git a/lib/debugger/test/bs_match_misc_SUITE.erl b/lib/debugger/test/bs_match_misc_SUITE.erl new file mode 100644 index 0000000000..5e1160a8e9 --- /dev/null +++ b/lib/debugger/test/bs_match_misc_SUITE.erl @@ -0,0 +1,152 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2010. 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(bs_match_misc_SUITE). + +-author('[email protected]'). +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1]). + +-include("test_server.hrl"). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [bound_var,bound_tail,t_float,little_float,sean]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +bound_var(doc) -> "Test matching of bound variables."; +bound_var(Config) when list(Config) -> + ?line ok = bound_var(42, 13, <<42,13>>), + ?line nope = bound_var(42, 13, <<42,255>>), + ?line nope = bound_var(42, 13, <<154,255>>), + ok. + +bound_var(A, B, <<A:8,B:8>>) -> ok; +bound_var(_, _, _) -> nope. + +bound_tail(doc) -> "Test matching of a bound tail."; +bound_tail(Config) when list(Config) -> + ?line ok = bound_tail(<<>>, <<13,14>>), + ?line ok = bound_tail(<<2,3>>, <<1,1,2,3>>), + ?line nope = bound_tail(<<2,3>>, <<1,1,2,7>>), + ?line nope = bound_tail(<<2,3>>, <<1,1,2,3,4>>), + ?line nope = bound_tail(<<2,3>>, <<>>), + ok. + +bound_tail(T, <<_:16,T/binary>>) -> ok; +bound_tail(_, _) -> nope. + +t_float(Config) when list(Config) -> + F = f1(), + G = f_one(), + + ?line G = match_float(<<63,128,0,0>>, 32, 0), + ?line G = match_float(<<63,240,0,0,0,0,0,0>>, 64, 0), + + ?line fcmp(F, match_float(<<F:32/float>>, 32, 0)), + ?line fcmp(F, match_float(<<F:64/float>>, 64, 0)), + ?line fcmp(F, match_float(<<1:1,F:32/float,127:7>>, 32, 1)), + ?line fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), + ?line fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)), + ?line fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), + ok. + + +fcmp(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok. + +match_float(Bin0, Fsz, I) -> + Bin = make_sub_bin(Bin0), + Bsz = size(Bin) * 8, + Tsz = Bsz - Fsz - I, + <<_:I,F:Fsz/float,_:Tsz>> = Bin, + F. + +little_float(Config) when list(Config) -> + F = f2(), + G = f_one(), + + ?line G = match_float_little(<<0,0,0,0,0,0,240,63>>, 64, 0), + ?line G = match_float_little(<<0,0,128,63>>, 32, 0), + + ?line fcmp(F, match_float_little(<<F:32/float-little>>, 32, 0)), + ?line fcmp(F, match_float_little(<<F:64/float-little>>, 64, 0)), + ?line fcmp(F, match_float_little(<<1:1,F:32/float-little,127:7>>, 32, 1)), + ?line fcmp(F, match_float_little(<<1:1,F:64/float-little,127:7>>, 64, 1)), + ?line fcmp(F, match_float_little(<<1:13,F:32/float-little,127:3>>, 32, 13)), + ?line fcmp(F, match_float_little(<<1:13,F:64/float-little,127:3>>, 64, 13)), + + ok. + +match_float_little(Bin0, Fsz, I) -> + Bin = make_sub_bin(Bin0), + Bsz = size(Bin) * 8, + Tsz = Bsz - Fsz - I, + <<_:I,F:Fsz/float-little,_:Tsz>> = Bin, + F. + + +make_sub_bin(Bin0) -> + Sz = size(Bin0), + Bin1 = <<37,Bin0/binary,38,39>>, + <<_:8,Bin:Sz/binary,_:8,_:8>> = Bin1, + Bin. + +f1() -> + 3.1415. + +f2() -> + 2.7133. + +f_one() -> + 1.0. + +sean(Config) when list(Config) -> + ?line small = sean1(<<>>), + ?line small = sean1(<<1>>), + ?line small = sean1(<<1,2>>), + ?line small = sean1(<<1,2,3>>), + ?line large = sean1(<<1,2,3,4>>), + + ?line small = sean1(<<4>>), + ?line small = sean1(<<4,5>>), + ?line small = sean1(<<4,5,6>>), + ?line {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)), + ok. + +sean1(<<B/binary>>) when size(B) < 4 -> small; +sean1(<<1, _B/binary>>) -> large. diff --git a/lib/debugger/test/bs_match_tail_SUITE.erl b/lib/debugger/test/bs_match_tail_SUITE.erl new file mode 100644 index 0000000000..7fa16b3c6a --- /dev/null +++ b/lib/debugger/test/bs_match_tail_SUITE.erl @@ -0,0 +1,106 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2010. 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(bs_match_tail_SUITE). + +-author('[email protected]'). +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + aligned/1,unaligned/1,zero_tail/1]). + +-include("test_server.hrl"). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [aligned,unaligned,zero_tail]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +aligned(doc) -> "Test aligned tails."; +aligned(Config) when list(Config) -> + ?line Tail1 = mkbin([]), + ?line {258,Tail1} = al_get_tail_used(mkbin([1,2])), + ?line Tail2 = mkbin(lists:seq(1, 127)), + ?line {35091,Tail2} = al_get_tail_used(mkbin([137,19|Tail2])), + + ?line 64896 = al_get_tail_unused(mkbin([253,128])), + ?line 64895 = al_get_tail_unused(mkbin([253,127|lists:seq(42, 255)])), + + ?line Tail3 = mkbin(lists:seq(0, 19)), + ?line {0,Tail1} = get_dyn_tail_used(Tail1, 0), + ?line {0,Tail3} = get_dyn_tail_used(mkbin([Tail3]), 0), + ?line {73,Tail3} = get_dyn_tail_used(mkbin([73|Tail3]), 8), + + ?line 0 = get_dyn_tail_unused(mkbin([]), 0), + ?line 233 = get_dyn_tail_unused(mkbin([233]), 8), + ?line 23 = get_dyn_tail_unused(mkbin([23,22,2]), 8), + ok. + +al_get_tail_used(<<A:16,T/binary>>) -> {A,T}. +al_get_tail_unused(<<A:16,_T/binary>>) -> A. + +unaligned(doc) -> "Test that an non-aligned tail cannot be matched out."; +unaligned(Config) when list(Config) -> + ?line {'EXIT',{function_clause,_}} = (catch get_tail_used(mkbin([42]))), + ?line {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_used(mkbin([137]), 3)), + ?line {'EXIT',{function_clause,_}} = (catch get_tail_unused(mkbin([42,33]))), + ?line {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_unused(mkbin([44]), 7)), + ok. + +get_tail_used(<<A:1,T/binary>>) -> {A,T}. + +get_tail_unused(<<A:15,_/binary>>) -> A. + +get_dyn_tail_used(Bin, Sz) -> + <<A:Sz,T/binary>> = Bin, + {A,T}. + +get_dyn_tail_unused(Bin, Sz) -> + <<A:Sz,_T/binary>> = Bin, + A. + +zero_tail(doc) -> "Test that zero tails are tested correctly."; +zero_tail(Config) when list(Config) -> + ?line 7 = (catch test_zero_tail(mkbin([7]))), + ?line {'EXIT',{function_clause,_}} = (catch test_zero_tail(mkbin([1,2]))), + ?line {'EXIT',{function_clause,_}} = (catch test_zero_tail2(mkbin([1,2,3]))), + ok. + +test_zero_tail(<<A:8>>) -> A. + +test_zero_tail2(<<_A:4,_B:4>>) -> ok. + +mkbin(L) when list(L) -> list_to_binary(L). diff --git a/lib/debugger/test/bs_utf_SUITE.erl b/lib/debugger/test/bs_utf_SUITE.erl new file mode 100644 index 0000000000..3d69d2a101 --- /dev/null +++ b/lib/debugger/test/bs_utf_SUITE.erl @@ -0,0 +1,292 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2010. 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(bs_utf_SUITE). + +-export([all/1,init_all/1,finish_all/1, + init_per_testcase/2,fin_per_testcase/2, + utf8_roundtrip/1,unused_utf_char/1,utf16_roundtrip/1, + utf32_roundtrip/1,guard/1,extreme_tripping/1]). + +-include("test_server.hrl"). +-compile([no_jopt,time]). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [utf8_roundtrip,unused_utf_char,utf16_roundtrip, + utf32_roundtrip,guard,extreme_tripping]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +utf8_roundtrip(Config) when is_list(Config) -> + ?line [utf8_roundtrip_1(P) || P <- utf_data()], + ok. + +utf8_roundtrip_1({Str,Bin,Bin}) -> + ?line Str = utf8_to_list(Bin), + ?line Bin = list_to_utf8(Str), + ?line [ok = utf8_guard(C, <<42,C/utf8>>) || C <- Str], + ?line [error = utf8_guard(C, <<C/utf8>>) || C <- Str], + ok. + +utf8_guard(C, Bin) when <<42,C/utf8>> =:= Bin -> ok; +utf8_guard(_, _) -> error. + +utf8_to_list(<<C/utf8,T/binary>>) -> + [C|utf8_to_list(T)]; +utf8_to_list(<<>>) -> []. + +list_to_utf8(L) -> + list_to_utf8(L, <<>>). + +list_to_utf8([H|T], Bin) -> + list_to_utf8(T, <<Bin/binary,H/utf8>>); +list_to_utf8([], Bin) -> Bin. + +unused_utf_char(Config) when is_list(Config) -> + [true = utf8_len(Utf8) =:= length(Str) || + {Str,Utf8} <- utf_data()], + ok. + +utf8_len(B) -> + utf8_len(B, 0). + +utf8_len(<<_/utf8,T/binary>>, N) -> + utf8_len(T, N+1); +utf8_len(<<>>, N) -> N. + +utf16_roundtrip(Config) when is_list(Config) -> + ?line {Str,Big,Big,Little,Little} = utf16_data(), + ?line 4 = utf16_big_len(Big), + ?line 4 = utf16_little_len(Little), + ?line Str = big_utf16_to_list(Big), + ?line Str = little_utf16_to_list(Little), + + ?line Big = list_to_big_utf16(Str), + ?line Little = list_to_little_utf16(Str), + + ok. + +utf16_big_len(B) -> + utf16_big_len(B, 0). + +utf16_big_len(<<_/utf16,T/binary>>, N) -> + utf16_big_len(T, N+1); +utf16_big_len(<<>>, N) -> N. + +utf16_little_len(B) -> + utf16_little_len(B, 0). + +utf16_little_len(<<_/little-utf16,T/binary>>, N) -> + utf16_little_len(T, N+1); +utf16_little_len(<<>>, N) -> N. + +list_to_big_utf16(List) -> + list_to_big_utf16(List, <<>>). + +list_to_big_utf16([H|T], Bin) -> + list_to_big_utf16(T, <<Bin/binary,H/utf16>>); +list_to_big_utf16([], Bin) -> Bin. + +list_to_little_utf16(List) -> + list_to_little_utf16(List, <<>>). + +list_to_little_utf16([H|T], Bin) -> + list_to_little_utf16(T, <<Bin/binary,H/little-utf16>>); +list_to_little_utf16([], Bin) -> Bin. + +big_utf16_to_list(<<H/utf16,T/binary>>) -> + [H|big_utf16_to_list(T)]; +big_utf16_to_list(<<>>) -> []. + +little_utf16_to_list(<<H/little-utf16,T/binary>>) -> + [H|little_utf16_to_list(T)]; +little_utf16_to_list(<<>>) -> []. + +utf32_roundtrip(Config) when is_list(Config) -> + ?line {Str,Big,Big,Little,Little} = utf32_data(), + ?line 4 = utf32_big_len(Big), + ?line 4 = utf32_little_len(Little), + ?line Str = big_utf32_to_list(Big), + ?line Str = little_utf32_to_list(Little), + + ?line Big = list_to_big_utf32(Str), + ?line Little = list_to_little_utf32(Str), + + ok. + +utf32_big_len(B) -> + utf32_big_len(B, 0). + +utf32_big_len(<<_/utf32,T/binary>>, N) -> + utf32_big_len(T, N+1); +utf32_big_len(<<>>, N) -> N. + +utf32_little_len(B) -> + utf32_little_len(B, 0). + +utf32_little_len(<<_/little-utf32,T/binary>>, N) -> + utf32_little_len(T, N+1); +utf32_little_len(<<>>, N) -> N. + +list_to_big_utf32(List) -> + list_to_big_utf32(List, <<>>). + +list_to_big_utf32([H|T], Bin) -> + list_to_big_utf32(T, <<Bin/binary,H/utf32>>); +list_to_big_utf32([], Bin) -> Bin. + +list_to_little_utf32(List) -> + list_to_little_utf32(List, <<>>). + +list_to_little_utf32([H|T], Bin) -> + list_to_little_utf32(T, <<Bin/binary,H/little-utf32>>); +list_to_little_utf32([], Bin) -> Bin. + +big_utf32_to_list(<<H/utf32,T/binary>>) -> + [H|big_utf32_to_list(T)]; +big_utf32_to_list(<<>>) -> []. + +little_utf32_to_list(<<H/little-utf32,T/binary>>) -> + [H|little_utf32_to_list(T)]; +little_utf32_to_list(<<>>) -> []. + + +guard(Config) when is_list(Config) -> + ?line error = do_guard(16#D800), + ok. + +do_guard(C) when byte_size(<<C/utf8>>) =/= 42 -> ok; +do_guard(C) when byte_size(<<C/utf16>>) =/= 42 -> ok; +do_guard(C) when byte_size(<<C/utf32>>) =/= 42 -> ok; +do_guard(_) -> error. + +%% The purpose of this test is to make sure that +%% the delayed creation of sub-binaries works. + +extreme_tripping(Config) when is_list(Config) -> + ?line Unicode = lists:seq(0, 1024), + ?line Utf8 = unicode_to_utf8(Unicode, <<>>), + ?line Utf16 = utf8_to_utf16(Utf8, <<>>), + ?line Utf32 = utf8_to_utf32(Utf8, <<>>), + ?line Utf32 = utf16_to_utf32(Utf16, <<>>), + ?line Utf8 = utf32_to_utf8(Utf32, <<>>), + ?line Unicode = utf32_to_unicode(Utf32), + ok. + +unicode_to_utf8([C|T], Bin) -> + unicode_to_utf8(T, <<Bin/bytes,C/utf8>>); +unicode_to_utf8([], Bin) -> Bin. + +utf8_to_utf16(<<C/utf8,T/binary>>, Bin) -> + utf8_to_utf16(T, <<Bin/bytes,C/utf16>>); +utf8_to_utf16(<<>>, Bin) -> Bin. + +utf16_to_utf32(<<C/utf16,T/binary>>, Bin) -> + utf16_to_utf32(T, <<Bin/bytes,C/utf32>>); +utf16_to_utf32(<<>>, Bin) -> Bin. + +utf8_to_utf32(<<C/utf8,T/binary>>, Bin) -> + utf8_to_utf32(T, <<Bin/bytes,C/utf32>>); +utf8_to_utf32(<<>>, Bin) -> Bin. + +utf32_to_utf8(<<C/utf32,T/binary>>, Bin) -> + utf32_to_utf8(T, <<Bin/bytes,C/utf8>>); +utf32_to_utf8(<<>>, Bin) -> Bin. + +utf32_to_unicode(<<C/utf32,T/binary>>) -> + [C|utf32_to_unicode(T)]; +utf32_to_unicode(<<>>) -> []. + +utf_data() -> +%% From RFC-3629. + + %% Give the compiler a change to do some constant propagation. + NotIdentical = 16#2262, + + [ + %% "A<NOT IDENTICAL TO><ALPHA>." + {[16#0041,NotIdentical,16#0391,16#002E], + <<16#0041/utf8,NotIdentical/utf8,16#0391/utf8,16#002E/utf8>>, + <<16#41,16#E2,16#89,16#A2,16#CE,16#91,16#2E>>}, + + %% Korean "hangugeo" (meaning "the Korean language") + {[16#D55C,16#AD6D,16#C5B4], + <<16#D55C/utf8,16#AD6D/utf8,16#C5B4/utf8>>, + <<16#ED,16#95,16#9C,16#EA,16#B5,16#AD,16#EC,16#96,16#B4>>}, + + %% Japanese "nihongo" (meaning "the Japanese language"). + {[16#65E5,16#672C,16#8A9E], + <<16#65E5/utf8,16#672C/utf8,16#8A9E/utf8>>, + <<16#E6,16#97,16#A5,16#E6,16#9C,16#AC,16#E8,16#AA,16#9E>>} + ]. + +utf16_data() -> + %% Example from RFC-2781. "*=Ra", where "*" represents a + %% hypothetical Ra hieroglyph (code point 16#12345). + + %% Give the compiler a change to do some constant propagation. + RaHieroglyph = 16#12345, + + %% First as a list of Unicode characters. + {[RaHieroglyph,16#3D,16#52,16#61], + + %% Big endian (the two binaries should be equal). + <<RaHieroglyph/big-utf16,16#3D/big-utf16,16#52/big-utf16,16#61/big-utf16>>, + <<16#D8,16#08,16#DF,16#45,16#00,16#3D,16#00,16#52,16#00,16#61>>, + + %% Little endian (the two binaries should be equal). + <<RaHieroglyph/little-utf16,16#3D/little-utf16, + 16#52/little-utf16,16#61/little-utf16>>, + <<16#08,16#D8,16#45,16#DF,16#3D,16#00,16#52,16#00,16#61,16#00>>}. + +utf32_data() -> + %% "A<NOT IDENTICAL TO><ALPHA>." + NotIdentical = 16#2262, + {[16#0041,NotIdentical,16#0391,16#002E], + + %% Big endian. + <<16#0041/utf32,NotIdentical/utf32,16#0391/utf32,16#002E/utf32>>, + <<16#41:32,NotIdentical:32,16#0391:32,16#2E:32>>, + + %% Little endian. + <<16#0041/little-utf32,NotIdentical/little-utf32, + 16#0391/little-utf32,16#002E/little-utf32>>, + <<16#41:32/little,NotIdentical:32/little, + 16#0391:32/little,16#2E:32/little>>}. diff --git a/lib/debugger/test/bug_SUITE.erl b/lib/debugger/test/bug_SUITE.erl new file mode 100644 index 0000000000..cf732c8115 --- /dev/null +++ b/lib/debugger/test/bug_SUITE.erl @@ -0,0 +1,79 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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(bug_SUITE). + +-include("test_server.hrl"). + +-export([all/1]). + +-export([ticket_tests/1]). + +-export([otp2163/1, otp4845/1]). + +all(suite) -> [ticket_tests]. + +ticket_tests(doc) -> ["Tests tickets regarding bugs"]; +ticket_tests(suite) -> [otp2163, otp4845]. + +otp2163(doc) -> ["BIF exit reason"]; +otp2163(suite) -> []; +otp2163(Config) when list(Config) -> + ?line DataDir = ?config(data_dir, Config), + + %% First compile and get the expected results: + + ?line FileName = filename:join(DataDir, "otp2163"), + ?line {module,otp2163} = code:load_abs(FileName), + + ?line {'EXIT',{badarg,[ApplyRes|_]}} = (catch otp2163:apply_test()), + ?line {'EXIT',{badarg,[ListRes|_]}} = (catch otp2163:list_to_atom_test()), + + %% Then interpret, and check if the results are OK. + ?line {module,otp2163} = int:i(FileName), + + ?line ok = io:format("Expecting ~p", [ApplyRes]), + ?line {'EXIT',{badarg,[ApplyRes|_]}} = (catch otp2163:apply_test()), + ?line ok = io:format("Expecting ~p", [ListRes]), + ?line {'EXIT',{badarg,[ListRes|_]}} = (catch otp2163:list_to_atom_test()), + ok. + + +otp4845(doc) -> ["BIF not loading and not bug compatible, OTP-4845 OTP-4859"]; +otp4845(suite) -> []; +otp4845(Config) when list(Config) -> + ?line DataDir = ?config(data_dir, Config), + + %% First compile and get the expected results: + + ?line FileName = filename:join(DataDir, "otp4845"), + ?line {module,otp4845} = code:load_abs(FileName), + + ?line CompiledRes = (catch otp4845:test()), + ?line ok = io:format("Compiled ~p", [CompiledRes]), + + %% Then interpret, and check if the results are OK. + ?line {module,otp4845} = int:i(FileName), + + ?line IntRes = (catch otp4845:test()), + ?line ok = io:format("Interpreted ~p", [IntRes]), + + ?line CompiledRes = IntRes, + ok. diff --git a/lib/debugger/test/bug_SUITE_data/Makefile.src b/lib/debugger/test/bug_SUITE_data/Makefile.src new file mode 100644 index 0000000000..792b3299e1 --- /dev/null +++ b/lib/debugger/test/bug_SUITE_data/Makefile.src @@ -0,0 +1,25 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2010. 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% +# +all: otp2163.@EMULATOR@ otp4845.@EMULATOR@ +EFLAGS=+debug_info + +otp2163.@EMULATOR@: otp2163.erl + erlc $(EFLAGS) otp2163.erl +otp4845.@EMULATOR@: otp4845.erl + erlc $(EFLAGS) otp4845.erl diff --git a/lib/debugger/test/bug_SUITE_data/otp2163.erl b/lib/debugger/test/bug_SUITE_data/otp2163.erl new file mode 100644 index 0000000000..4e3c487ef7 --- /dev/null +++ b/lib/debugger/test/bug_SUITE_data/otp2163.erl @@ -0,0 +1,60 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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% +%% + +%% +%%% Purpose : Test OTP-2163 + +-module(otp2163). + + +-export([apply_test/0, list_to_atom_test/0, error/1]). +-export([test/0]). + +apply_test() -> + M = {}, + apply(M,dummy,[]). + +list_to_atom_test() -> + list_to_atom(id({1,2})). + +id(I) -> I. + +%% OTP-4845 OTP 4859 +-record(sune, {a,sd,g,s}). +-record(error, {a,sd,g,s}). + +test() -> + sune = error(#sune{}), + {false,false} = error(false), + {true,true} = error(true), + error(#error{}). + +error(X) -> + if + is_record(X, sune) -> + sune; + X -> + {true, X}; + not X -> + {false, X}; + not is_record(X, error) -> + error; + true -> + ok + end. diff --git a/lib/debugger/test/bug_SUITE_data/otp4845.erl b/lib/debugger/test/bug_SUITE_data/otp4845.erl new file mode 100644 index 0000000000..18ca08b977 --- /dev/null +++ b/lib/debugger/test/bug_SUITE_data/otp4845.erl @@ -0,0 +1,52 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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% +%% + +%% +%%% Purpose : Test OTP-4845 + +-module(otp4845). + + +%%-export([error/1]). +-export([test/0]). + +%% OTP-4845 OTP 4859 +-record(sune, {a,sd,g,s}). +-record(error, {a,sd,g,s}). + +test() -> + R1 = error(#sune{}), + R2 = error(false), + R3 = error(true), + R4 = error(#error{}), + {R1,R2,R3,R4}. + +error(X) -> + if + is_record(X, sune) -> + sune; + X -> + {true, X}; + not X -> + {false, X}; + not is_record(X, error) -> + error; + true -> + ok + end. diff --git a/lib/debugger/test/cleanup.erl b/lib/debugger/test/cleanup.erl new file mode 100644 index 0000000000..59b4c35ac7 --- /dev/null +++ b/lib/debugger/test/cleanup.erl @@ -0,0 +1,45 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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(cleanup). + +-export([all/1, cleanup/1]). + +-include("test_server.hrl"). + +all(suite) -> {req, [interpreter], [cleanup]}. + +cleanup(suite) -> []; +cleanup(_) -> + ?line Mods = int:interpreted(), + ?line ok = int:n(Mods), + case whereis(interpret) of + undefined -> + ok; + Pid -> + exit(Pid, kill) + end, + case whereis(int_db) of + undefined -> + ok; + Pid2 -> + exit(Pid2, kill) + end, + ok. diff --git a/lib/debugger/test/dbg_ui_SUITE.erl b/lib/debugger/test/dbg_ui_SUITE.erl new file mode 100644 index 0000000000..629aac9fd6 --- /dev/null +++ b/lib/debugger/test/dbg_ui_SUITE.erl @@ -0,0 +1,288 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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(dbg_ui_SUITE). + + +-include("test_server.hrl"). + + +% Test server specific exports +-export([all/1]). +-export([function_tests/1]). + + +% Test cases must be exported. +-export ([dbg_ui/1]). + + + + + +% Manual test suites/cases exports +-export([manual_tests/1]). +-export([start1/1, interpret1/1, quit1/1, + start2/1, interpret2/1, break2/1, options2/1, quit2/1, + interpret3/1, all_step3/1,all_next3/1,save3/1,restore3/1,finish3/1, + killinit3/1, killone3/1, killall3/1, deleteone3/1, deleteall3/1, + viewbreak4/1, delete4/1, + attach5/1, normal5/1, exit5/1, options5/1, + distsetup6/1, all_step6/1, all_next6/1]). + + + + +-export([init_per_testcase/2, fin_per_testcase/2]). + + + +init_per_testcase(_Func, Config) -> + Dog=test_server:timetrap(60*1000), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog). + + +all (suite)-> + {req, [debugger], [function_tests, manual_tests]}. + + +function_tests (doc) -> + ["Tests documented functions"]; + +function_tests (suite) -> + [dbg_ui]. + + + +dbg_ui (doc) -> + ["Debugger GUI"]; + +dbg_ui (suite) -> + []; + +dbg_ui (_Config) -> + case os:getenv("DISPLAY") of + false -> + {skipped,"No display"}; + Other when list(Other) -> +% ?line {ok, Pid} = debugger:start (), +% ?line ok = is_pid (Pid), +% ?line true = erlang:is_process_alive(Pid), +% ?line ok = debugger:stop(), +% ?line false = erlang:is_process_alive(Pid) + {skipped,"Gunilla: Workaround"} + end. + + + + + + +%% check/2 - returns the result for the specified testcase. +%% pass - means the user has run the case, and it passed +%% fail - means the user has run the case, and it failed +%% unknown - means the user has (tried to) run the case, and the result is unclear. +%% skip - means the user has not yet run the case. + +check(Case, Config) -> + + ?line DataDir = ?config(data_dir, Config), + ?line ResultFileName = filename:join([DataDir, "manual_results.erl"]), + case file:consult(ResultFileName) of + {ok, Results} -> + ?line io:format("Results: ~p~n",[Results]), + case Results of + [] -> + no_result; + %% Incomplete "sanity" check of file contents. + [{_Key,_Value}|_Rest] -> + case lists:keysearch(Case, 1, Results) of + {value, {Case, Value}} -> + Value; % pass, fail, unknown + false -> + no_result; % skip + _Otherwise -> + {error, "Contents of results file not valid"} + end; + _Otherwise2 -> + {error, "Contents of results file not valid"} + end; + _Otherwise3 -> + {error, "Problems reading results file"} + end. + + + + + + +-define(MAN_CASE(Name,Doc, Description), + Name(doc) -> [Doc]; + Name(suite) -> []; + Name(Config) -> + ?line io:format("Checking ~p~n",[Name]), + ?line io:format("Config = ~p~n",[Config]), + case check(Name, Config) of + pass -> + ?line ok; + fail -> + ?line test_server:fail("Manual test failed"); + unknown -> + ?line {skipped, "Manual test result unknown"}; + + no_result -> + ?line {skipped, Description}; + + {error, _Reason} -> +%% Text = lists:flatten( +%% io_lib:format("[File problem: ~s]~s", +%% [Reason,Description])), + ?line {skipped, Description} + end + ). + + + + +manual_tests(doc) -> ["Manual tests"]; +manual_tests(suite) -> [start1, interpret1, quit1, + start2, interpret2, break2, options2, + interpret3, all_step3,all_next3,save3,restore3,finish3, + killinit3, killone3, killall3, deleteone3, deleteall3, + viewbreak4, delete4, + attach5, normal5, exit5, options5, + distsetup6, all_step6, all_next6 + ]. + + + + + + +%% SET 1 +?MAN_CASE(start1, "Start the debugger from the toolbar", + "Before proceeding with the test cases, please move or remove +the directory .erlang_tools/debugger in your home directory. Next, +please start the debugger from the toolbar"). + +?MAN_CASE(interpret1, "Interpreting modules", + "In this test case and all of the ones following, the source code +files to use can be found in the test data directory for this debugger test + suite (probably in +/clearcase/otp/tools/debugger/test/dbg_ui_SUITE_data/manual_data/src ). +Interpret one module"). + +?MAN_CASE(quit1, "Quit the debugger", +"Quit the debugger using File->Exit in the main window"). + + +%% SET 2 +?MAN_CASE(start2, "Start the debugger from the shell", +"Start the debugger from the shell. Use debugger:start()"). + +?MAN_CASE(interpret2, "Interpret all modules", +"Interpret all modules"). + +?MAN_CASE(break2, "Set break points", +"Set break points"). + +?MAN_CASE(options2, "Set options to attach on break", +"Set options to attach on break"). + +?MAN_CASE(quit2, "Quit the debugger", +"Quit the debugger using the close box in the main window title frame"). + + +%% SET3 +?MAN_CASE(interpret3, "Test attach options", +"Start the debugger and interpret the modules [test, lists1, ordsets1]. Close the Interpret dialog. Set Attach on First Call and Attach on Break."). + +?MAN_CASE(all_step3, "Click Step through all evaluation", +"In the shell, call test:test1(). Use the Step button, the Process->Step menu item and the ctrl-s shortcut to step through the *entire* execution of the call. (Approx 36 steps). Then close the Attach window. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}"). + +?MAN_CASE(all_next3,"Click Next through all evaluation", +"Again call test:test1() in the shell. This time Use the Next button, the Process->Next menu and the ctrl-n shortcut to quickly step over the execution of the four lines in the test1-function. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}"). + +?MAN_CASE(save3, "Save the debugger state", +"Use File->Save Settings to save the debugger state with the name 'three.state'"). + +?MAN_CASE(restore3,"Quit the debugger, restart and restore the state", +"Quit the debugger. Start it again. Use File->Load Settings to restore the state saved in 'three.state'. Check that the Attach-options are the same as what you set them to in the interpret3 test case. Check that the three modules [test,lists1,ordsets1] are interpreted."). + + +?MAN_CASE(finish3, "Finish the current function body", +"Call the fucntion test:test1() from the shell. Press Finish to evaluate the remaining lines in the function. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}"). + +?MAN_CASE(killinit3,"Set up for killing and clearing processes", +"Call test:test2() from the shell. Set a break point at the last line of test:test2. Click Continue. This should open three new attach windows. One for each spawn called in test:test2/0. "). + +?MAN_CASE(killone3, "Kill a process and clear it", +"In one of the newly openend Attach windows: select Process->Kill. A message should appear above the Code Area in the Attach window. Use Windows->Monitor to verify that the Monitor window also shows that the process has been killed. In the Monitor window: select Edit->Clear. This should do two things: 1) close/remove the window of the killed process. 2) Remove the entry of the killed process from the monitor window."). + +?MAN_CASE(killall3,"KIll all processes, and clear them", +"In the Monitor window: Select Edit->Kill All. Verify that all processes have been killed (in their respective windows and in the monitor window). Windows will be raised as their processes die. Next select, Edit->Clear. All attach windows should now be closed. Their entris should also disappear from the monitor window. The shell should have reported: ** exited: killed **"). + +?MAN_CASE(deleteone3,"Delete/uniterpret one module", +"In the Monitor window: Select Module->test->Delete. This should remove the breakpoints set in the test module, and the test module should disappear from the Module menu."). + +?MAN_CASE(deleteall3,"Delete/uniterpret all modules", +"In the Monitor window: Select Module->Delete All Modules. This should remove all modules from the Module menu. "). + +%% SET 4 + + + +?MAN_CASE(viewbreak4, "Test the View window", +"Restore the settings from the three.state file again. In the Monitor window: Use Module->test->View to view the source code of the test module. In the View window, select Break->Line Break and set a break at line 53. Check that it appears in the View window and in the Monitor Window Break-menu. Also in the View window, select Break->Function Break and set a break at function test:test4. Check that the break (at line 59) appears in the View Window and in the Monitor Window Break-menu."). + +?MAN_CASE(delete4, "Remove breaks", +"Use the Break->Delete All function in the View window to remove all breaks in the test module. Check that they are all removed. Close the View window."). + +%% SET 5 + +?MAN_CASE(attach5,"Set attach options", +"Set the attach options to only attach on exit"). + +?MAN_CASE(normal5, "Test normal exit", +"Call test:test12(normal) in the shell. This should return the atom 'done', and no windows should be opened."). + +?MAN_CASE(exit5, "Test abnormal exit", +"Call test:test12(crash) in the shell. This should give the error message ** exited: crash **, and an attach window should be opened highlighting the last line in the test12-function."). + +?MAN_CASE(options5, "Experiment with the frames in the attach window", +"Try all possible configurations of the [Button, Evaluator, Bindings, Trace] Frames in the attach window and see that the expected frames are shown/hidden."). + + +%% SET 6 (Distribution) + +?MAN_CASE(distsetup6,"Set up distribution", +"Start two erlang systems [foo,bar] (with option -sname), make them aware of eachother using net_adm:ping/1. Start the debugger on foo. Interpret the modules [test, lists1, ordsets1]. Set attach on First call. "). + + + + +?MAN_CASE(all_step6, "Click Step through all evaluation", +"In the bar shell, call test:test1().This should open an attach window. Use the Step button, the Process->Step menu item and the ctrl-s shortcut to step through the *entire* execution of the call. (Approx 36 steps). Then close the Attach window. The result printed in the bar shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}"). + +?MAN_CASE(all_next6,"Click Next through all evaluation", +"Again, in the bar shell, call test:test1(). This time Use the Next button, the Process->Next menu and the ctrl-n shortcut to quickly step over the execution of the four lines in the test1-function. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}"). diff --git a/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl new file mode 100644 index 0000000000..0214983c11 --- /dev/null +++ b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl @@ -0,0 +1,469 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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% +%% + +%% +%% Purpose : Basic lists processing functions. + +-module(lists1). + + +-export([member/2, append/2, append/1, subtract/2, reverse/1, reverse/2, + nth/2, nthtail/2, prefix/2, suffix/2, last/1, + seq/2, seq/3, sum/1, duplicate/2, min/1, max/1, sublist/2, sublist/3, + delete/2, sort/1, merge/2, concat/1, + flatten/1, flatten/2, flat_length/1, flatlength/1, + keymember/3, keysearch/3, keydelete/3, keyreplace/4, + keysort/2, keymerge/3, keymap/3, keymap/4]). + +-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,zf/2, + mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2]). +-export([all/3,any/3,map/3,flatmap/3,foldl/4,foldr/4,filter/3,zf/3, + mapfoldl/4,mapfoldr/4,foreach/3]). + +%% member(X, L) -> (true | false) +%% test if X is a member of the list L + +member(X, [X|_]) -> true; +member(X, [_|Y]) -> + member(X, Y); +member(X, []) -> false. + +%% append(X, Y) appends lists X and Y + +append(L1, L2) -> L1 ++ L2. + +%% append(L) appends the list of lists L + +append([E]) -> E; +append([H|T]) -> H ++ append(T); +append([]) -> []. + +%% subtract(List1, List2) subtract elements in List2 form List1. + +subtract(L1, L2) -> L1 -- L2. + +%% reverse(L) reverse all elements in the list L + +reverse(X) -> reverse(X, []). + +reverse([H|T], Y) -> + reverse(T, [H|Y]); +reverse([], X) -> X. + +%% nth(N, L) returns the N`th element of the list L +%% nthtail(N, L) returns the N`th tail of the list L + +nth(1, [H|T]) -> H; +nth(N, [_|T]) when N > 1 -> + nth(N - 1, T). + +nthtail(1, [H|T]) -> T; +nthtail(N, [H|T]) when N > 1 -> + nthtail(N - 1, T); +nthtail(0, L) when list(L) -> L. + +%% prefix(Prefix, List) -> (true | false) + +prefix([X|PreTail], [X|Tail]) -> + prefix(PreTail, Tail); +prefix([], List) -> true; +prefix(_,_) -> false. + + +%% suffix(Suffix, List) -> (true | false) + +suffix(Suffix, Suffix) -> true; +suffix(Suffix, [_|Tail]) -> + suffix(Suffix, Tail); +suffix(Suffix, []) -> false. + +%% last(List) returns the last element in a list. + +last([E]) -> E; +last([E|Es]) -> + last(Es). + +%% seq(Min, Max) -> [Min,Min+1, ..., Max] +%% seq(Min, Max, Incr) -> [Min,Min+Incr, ..., Max] +%% returns the sequence Min..Max +%% Min <= Max and Min and Max must be integers + +seq(Min, Max) when integer(Min), integer(Max), Min =< Max -> + seq(Min, Max, 1, []). + +seq(Min, Max, Incr) -> + seq(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []). + +seq(Min, Min, I, L) -> [Min|L]; +seq(Min, Max, I, L) -> seq(Min, Max-I, I, [Max|L]). + +%% sum(L) suns the sum of the elements in L + +sum(L) -> sum(L, 0). +sum([H|T], Sum) -> sum(T, Sum + H); +sum([], Sum) -> Sum. + +%% duplicate(N, X) -> [X,X,X,.....,X] (N times) +%% return N copies of X + +duplicate(N, X) when integer(N), N >= 0 -> duplicate(N, X, []). + +duplicate(0, _, L) -> L; +duplicate(N, X, L) -> duplicate(N-1, X, [X|L]). + + +%% min(L) -> returns the minimum element of the list L + +min([H|T]) -> min(T, H). + +min([H|T], Min) when H < Min -> min(T, H); +min([_|T], Min) -> min(T, Min); +min([], Min) -> Min. + +%% max(L) -> returns the maximum element of the list L + +max([H|T]) -> max(T, H). + +max([H|T], Max) when H > Max -> max(T, H); +max([_|T], Max) -> max(T, Max); +max([], Max) -> Max. + +%% sublist(List, Start, Length) +%% Returns the sub-list starting at Start of length Length. + +sublist(List, S, L) when L >= 0 -> + sublist(nthtail(S-1, List), L). + +sublist([H|T], L) when L > 0 -> + [H|sublist(T, L-1)]; +sublist(List, L) -> []. + +%% delete(Item, List) -> List' +%% Delete the first occurance of Item from the list L. + +delete(Item, [Item|Rest]) -> Rest; +delete(Item, [H|Rest]) -> + [H|delete(Item, Rest)]; +delete(Item, []) -> []. + +%% sort(L) -> sorts the list L + +sort([X]) -> [X]; +sort([]) -> []; +sort(X) -> split_and_sort(X, [], []). + +split_and_sort([A,B|T], X, Y) -> + split_and_sort(T, [A|X], [B|Y]); +split_and_sort([H], X, Y) -> + split_and_sort([], [H|X], Y); +split_and_sort([], X, Y) -> + merge(sort(X), sort(Y), []). + +%% merge(X, Y) -> L +%% merges two sorted lists X and Y + +merge(X, Y) -> merge(X, Y, []). + +merge([H1|T1], [H2|T2], L) when H1 < H2 -> + merge(T1, [H2|T2], [H1|L]); +merge(T1, [H2|T2], L) -> + merge(T1, T2, [H2|L]); +merge([H|T], T2, L) -> + merge(T, T2, [H|L]); +merge([], [], L) -> + reverse(L). + +%% concat(L) concatinate the list representation of the elements +%% in L - the elements in L can be atoms, integers of strings. +%% Returns a list of characters. + +concat(List) -> + flatmap(fun thing_to_list/1, List). + +thing_to_list(X) when integer(X) -> integer_to_list(X); +thing_to_list(X) when float(X) -> float_to_list(X); +thing_to_list(X) when atom(X) -> atom_to_list(X); +thing_to_list(X) when list(X) -> X. %Assumed to be a string + +%% flatten(List) +%% flatten(List, Tail) +%% Flatten a list, adding optional tail. + +flatten(List) -> + flatten(List, [], []). + +flatten(List, Tail) -> + flatten(List, [], Tail). + +flatten([H|T], Cont, Tail) when list(H) -> + flatten(H, [T|Cont], Tail); +flatten([H|T], Cont, Tail) -> + [H|flatten(T, Cont, Tail)]; +flatten([], [H|Cont], Tail) -> + flatten(H, Cont, Tail); +flatten([], [], Tail) -> + Tail. + +%% flat_length(List) (undocumented can be rmove later) +%% Calculate the length of a list of lists. + +flat_length(List) -> flatlength(List). + +%% flatlength(List) +%% Calculate the length of a list of lists. + +flatlength(List) -> + flatlength(List, 0). + +flatlength([H|T], L) when list(H) -> + flatlength(H, flatlength(T, L)); +flatlength([H|T], L) -> + flatlength(T, L + 1); +flatlength([], L) -> L. + +%% keymember(Key, Index, [Tuple]) +%% keysearch(Key, Index, [Tuple]) +%% keydelete(Key, Index, [Tuple]) +%% keyreplace(Key, Index, [Tuple], NewTuple) +%% keysort(Index, [Tuple]) +%% keymerge(Index, [Tuple], [Tuple]) +%% keymap(Function, Index, [Tuple]) +%% keymap(Function, ExtraArgs, Index, [Tuple]) + +keymember(Key, N, [T|Ts]) when element(N, T) == Key -> true; +keymember(Key, N, [T|Ts]) -> + keymember(Key, N, Ts); +keymember(Key, N, []) -> false. + +keysearch(Key, N, [H|T]) when element(N, H) == Key -> + {value, H}; +keysearch(Key, N, [H|T]) -> + keysearch(Key, N, T); +keysearch(Key, N, []) -> false. + +keydelete(Key, N, [H|T]) when element(N, H) == Key -> T; +keydelete(Key, N, [H|T]) -> + [H|keydelete(Key, N, T)]; +keydelete(Key, N, []) -> []. + +keyreplace(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key -> + [New|Tail]; +keyreplace(Key, Pos, [H|T], New) -> + [H|keyreplace(Key, Pos, T, New)]; +keyreplace(Key, Pos, [], New) -> []. + +keysort(Index, [X]) -> [X]; +keysort(Index, []) -> []; +keysort(Index, X) -> split_and_keysort(X, [], [], Index). + +split_and_keysort([A,B|T], X, Y, Index) -> + split_and_keysort(T, [A|X], [B|Y], Index); +split_and_keysort([H], X, Y, Index) -> + split_and_keysort([], [H|X], Y, Index); +split_and_keysort([], X, Y, Index) -> + keymerge(Index, keysort(Index, X), keysort(Index, Y), []). + +keymerge(Index, X, Y) -> keymerge(Index, X, Y, []). + +keymerge(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) -> + keymerge(I, T1, [H2|T2], [H1|L]); +keymerge(Index, T1, [H2|T2], L) -> + keymerge(Index,T1, T2, [H2|L]); +keymerge(Index,[H|T], T2, L) -> + keymerge(Index,T, T2, [H|L]); +keymerge(Index, [], [], L) -> + reverse(L). + +keymap(Fun, Index, [Tup|Tail]) -> + [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)]; +keymap( _, _ , []) -> []. + +keymap(Fun, ExtraArgs, Index, [Tup|Tail]) -> + [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))| + keymap(Fun, ExtraArgs, Index, Tail)]; +keymap( _, _ , _, []) -> []. + +%% all(Predicate, List) +%% any(Predicate, List) +%% map(Function, List) +%% flatmap(Function, List) +%% foldl(Function, First, List) +%% foldr(Function, Last, List) +%% filter(Predicate, List) +%% zf(Function, List) +%% mapfoldl(Function, First, List) +%% mapfoldr(Function, Last, List) +%% foreach(Function, List) +%% takewhile(Predicate, List) +%% dropwhile(Predicate, List) +%% splitwith(Predicate, List) +%% for list programming. Function here is either a 'fun' or a tuple +%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke! +%% +%% N.B. Unless where the functions actually needs it only foreach/2/3, +%% which is meant to be used for its side effects, has a defined order +%% of evaluation. +%% +%% There are also versions with an extra argument, ExtraArgs, which is a +%% list of extra arguments to each call. + +all(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> all(Pred, Tail); + false -> false + end; +all(Pred, []) -> true. + +any(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> true; + false -> any(Pred, Tail) + end; +any(Pred, []) -> false. + +map(F, List) -> [ F(E) || E <- List ]. + +flatmap(F, [Hd|Tail]) -> + F(Hd) ++ flatmap(F, Tail); +flatmap(F, []) -> []. + +foldl(F, Accu, [Hd|Tail]) -> + foldl(F, F(Hd, Accu), Tail); +foldl(F, Accu, []) -> Accu. + +foldr(F, Accu, [Hd|Tail]) -> + F(Hd, foldr(F, Accu, Tail)); +foldr(F, Accu, []) -> Accu. + +filter(Pred, List) -> [ E || E <- List, Pred(E) ]. + +zf(F, [Hd|Tail]) -> + case F(Hd) of + true -> + [Hd|zf(F, Tail)]; + {true,Val} -> + [Val|zf(F, Tail)]; + false -> + zf(F, Tail) + end; +zf(F, []) -> []. + +foreach(F, [Hd|Tail]) -> + F(Hd), + foreach(F, Tail); +foreach(F, []) -> ok. + +mapfoldl(F, Accu0, [Hd|Tail]) -> + {R,Accu1} = F(Hd, Accu0), + {Rs,Accu2} = mapfoldl(F, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl(F, Accu, []) -> {[],Accu}. + +mapfoldr(F, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr(F, Accu0, Tail), + {R,Accu2} = F(Hd, Accu1), + {[R|Rs],Accu2}; +mapfoldr(F, Accu, []) -> {[],Accu}. + +takewhile(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> [Hd|takewhile(Pred, Tail)]; + false -> [] + end; +takewhile(Pred, []) -> []. + +dropwhile(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> dropwhile(Pred, Tail); + false -> [Hd|Tail] + end; +dropwhile(Pred, []) -> []. + +splitwith(Pred, List) -> splitwith(Pred, List, []). + +splitwith(Pred, [Hd|Tail], Taken) -> + case Pred(Hd) of + true -> splitwith(Pred, Tail, [Hd|Taken]); + false -> {reverse(Taken), [Hd|Tail]} + end; +splitwith(Pred, [], Taken) -> {reverse(Taken),[]}. + +%% Versions of the above functions with extra arguments. + +all(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> all(Pred, Eas, Tail); + false -> false + end; +all(Pred, Eas, []) -> true. + +any(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> true; + false -> any(Pred, Eas, Tail) + end; +any(Pred, Eas, []) -> false. + +map(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ]. + +flatmap(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]) ++ flatmap(F, Eas, Tail); +flatmap(F, Eas, []) -> []. + +foldl(F, Eas, Accu, [Hd|Tail]) -> + foldl(F, Eas, apply(F, [Hd,Accu|Eas]), Tail); +foldl(F, Eas, Accu, []) -> Accu. + +foldr(F, Eas, Accu, [Hd|Tail]) -> + apply(F, [Hd,foldr(F, Eas, Accu, Tail)|Eas]); +foldr(F, Eas, Accu, []) -> + Accu. + +filter(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ]. + +zf(F, Eas, [Hd|Tail]) -> + case apply(F, [Hd|Eas]) of + true -> + [Hd|zf(F, Eas, Tail)]; + {true,Val} -> + [Val|zf(F, Eas, Tail)]; + false -> + zf(F, Eas, Tail) + end; +zf(F, Eas, []) -> []. + +foreach(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]), + foreach(F, Eas, Tail); +foreach(F, Eas, []) -> ok. + +mapfoldl(F, Eas, Accu0, [Hd|Tail]) -> + {R,Accu1} = apply(F, [Hd,Accu0|Eas]), + {Rs,Accu2} = mapfoldl(F, Eas, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl(F, Eas, Accu, []) -> {[],Accu}. + +mapfoldr(F, Eas, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr(F, Eas, Accu0, Tail), + {R,Accu2} = apply(F, [Hd,Accu1|Eas]), + {[R|Rs],Accu2}; +mapfoldr(F, Eas, Accu, []) -> {[],Accu}. + +%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with +%% extra arguments as this going to be discontinued. diff --git a/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/ordsets1.erl b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/ordsets1.erl new file mode 100644 index 0000000000..ea72150bca --- /dev/null +++ b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/ordsets1.erl @@ -0,0 +1,188 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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% +%% + +%% +%% Purpose : Functions for manipulating sets as ordered lists. + +%% As yet some of these are not very efficiently written. + +-module(ordsets1). + +-export([new_set/0,is_set/1,set_to_list/1,list_to_set/1]). +-export([is_element/2,add_element/2,del_element/2]). +-export([union/2,union/1,intersection/2,intersection/1]). +-export([subtract/2,subset/2]). + +%% new_set() +%% Return a new empty ordered set. + +new_set() -> + []. + +%% is_set(Set) +%% Return 'true' if Set is an ordered set of elements, else 'false'. + +is_set([E|Es]) -> + is_set(Es, E); +is_set([]) -> + true. + +is_set([E2|Es], E1) when E1 < E2 -> + is_set(Es, E2); +is_set([E2|Es], E1) -> + false; +is_set([], E1) -> + true. + +%% set_to_list(OrdSet) +%% Return the elements in OrdSet as a list. + +set_to_list(S) -> + S. + +%% list_to_set(List) +%% Build an ordered set from the elements in List. + +list_to_set([E|Es]) -> + add_element(E, list_to_set(Es)); +list_to_set([]) -> + []. + +%% is_element(Element, OrdSet) +%% Return 'true' if Element is an element of OrdSet, else 'false'. + +is_element(E, [H|Es]) when E < H -> + false; +is_element(E, [H|Es]) when E == H -> + true; +is_element(E, [H|Es]) when E > H -> + is_element(E, Es); +is_element(E, []) -> + false. + +%% add_element(Element, OrdSet) +%% Return OrdSet with Element inserted in it. + +add_element(E, [H|Es]) when E < H -> + [E,H|Es]; +add_element(E, [H|Es]) when E == H -> + [H|Es]; +add_element(E, [H|Es]) when E > H -> + [H|add_element(E, Es)]; +add_element(E, []) -> + [E]. + +%% del_element(Element, OrdSet) +%% Return OrdSet but with Element removed. + +del_element(E, [H|Es]) when E < H -> + [H|Es]; +del_element(E, [H|Es]) when E == H -> + Es; +del_element(E, [H|Es]) when E > H -> + [H|del_element(E, Es)]; +del_element(E, []) -> + []. + +%% union(Set1, Set2) +%% Return the union of Set1 and Set2. + +union([H1|Es1], [H2|Es2]) when H1 < H2 -> + [H1|union(Es1, [H2|Es2])]; +union([H1|Es1], [H2|Es2]) when H1 == H2 -> + [H1|union(Es1, Es2)]; +union([H1|Es1], [H2|Es2]) when H1 > H2 -> + [H2|union([H1|Es1], Es2)]; +union([], Es2) -> + Es2; +union(Es1, []) -> + Es1. + +%% union(OrdSets) +%% Return the union of the list of sets. + +union([S1,S2|Ss]) -> + union1(union(S1,S2), Ss); +union([S]) -> + S; +union([]) -> + []. + +union1(S1, [S2|Ss]) -> + union1(union(S1, S2), Ss); +union1(S1, []) -> + S1. + +%% intersection(Set1, Set2) +%% Return the intersection of Set1 and Set2. + +intersection([H1|Es1], [H2|Es2]) when H1 < H2 -> + intersection(Es1, [H2|Es2]); +intersection([H1|Es1], [H2|Es2]) when H1 == H2 -> + [H1|intersection(Es1, Es2)]; +intersection([H1|Es1], [H2|Es2]) when H1 > H2 -> + intersection([H1|Es1], Es2); +intersection([], Es2) -> + []; +intersection(Es1, []) -> + []. + +%% intersection(OrdSets) +%% Return the intersection of the list of sets. + +intersection([S1,S2|Ss]) -> + intersection1(intersection(S1,S2), Ss); +intersection([S]) -> + S; +intersection([]) -> + []. + +intersection1(S1, [S2|Ss]) -> + intersection1(intersection(S1, S2), Ss); +intersection1(S1, []) -> + S1. + +%% subtract(Set1, Set2) +%% Return all and only the elements of Set1 which are not also in Set2. + +subtract([H1|Es1], [H2|Es2]) when H1 < H2 -> + [H1|subtract(Es1, [H2|Es2])]; +subtract([H1|Es1], [H2|Es2]) when H1 == H2 -> + subtract(Es1, Es2); +subtract([H1|Es1], [H2|Es2]) when H1 > H2 -> + subtract([H1|Es1], Es2); +subtract([], Es2) -> + []; +subtract(Es1, []) -> + Es1. + +%% subset(Set1, Set2) +%% Return 'true' when every element of Set1 is also a member of Set2, +%% else 'false'. + +subset([H1|Es1], [H2|Es2]) when H1 < H2 -> %H1 not in Set2 + false; +subset([H1|Es1], [H2|Es2]) when H1 == H2 -> + subset(Es1, Es2); +subset([H1|Es1], [H2|Es2]) when H1 > H2 -> + subset([H1|Es1], Es2); +subset([], Es2) -> + true; +subset(Es1, []) -> + false. diff --git a/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/test.erl b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/test.erl new file mode 100644 index 0000000000..a48a7e112f --- /dev/null +++ b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/test.erl @@ -0,0 +1,157 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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(test). + +%%-compile(export_all). +-export([test1/0, + test2/0, + test3/0, + test4/0, + test5/0, + test6/1, + test7/0, + test8/1, + test9/0, + test10/0, + test11/0, + test12/1 + ]). + + +-export([test9_server/1]). + + +test1() -> + R1 = lists1:reverse("retep"), + R2 = ordsets1:list_to_set([b,c,a,2,4,1]), + R3 = lists1:reverse("nilo"), + {R1,R2, R3}. + +test2() -> + R1 = spawn(lists1,reverse,["retep"]), + R2 = spawn(ordsets1,list_to_set,[[b,c,a,2,4,1]]), + R3 = spawn(lists1,reverse,["nilo"]), + {R1,R2, R3}. + + +test3() -> + A = a, + Pid = spawn(?MODULE, test1,[]), + B = b, + {A, B, Pid}. + +test4() -> + Pid = spawn(?MODULE, test1,[]), + A = a, + B = b, + {A, B, Pid}. +test5() -> + L1 = [a,b,c], + L = length(L1), + A = a, + B = b, + {A, B, L, L1}. + + + +test6(0) -> + ok; +test6(N) when N>0 -> + spawn(lists1,reverse,["adolfiparisrorsirapifloda"]), + test6(N-1). + + +test7() -> + CurDirReturn = file:get_cwd(), + {ok, CurDir} = CurDirReturn, + DirListReturn = file:list_dir(CurDir), + {ok, DirList} = DirListReturn, + io:format("~w~n",[DirList]). + + +test8(List) -> + %% foo + %%bar + %% foo + %%bar + %% foo + %%bar + %% foo + %%bar + + L2 = [gamma|List], + {L2, List}. + +test9() -> + S1 = spawn(?MODULE, test9_server,[self()]), + S2 = spawn(?MODULE, test9_server,[bongo]), + S3 = spawn(?MODULE, test9_server,[42]), + + test9_loop(S1,S2,S3). + +test9_loop(S1,S2,S3) -> + receive + {S1, hej} -> + io:format("S1 ~n"), + test9_loop(S1,S2,S3); + {S2, hej} -> + io:format("S2 ~n"), + test9_loop(S1,S2,S3); + {S3, hej} -> + io:format("S3 ~n"), + test9_loop(S1,S2,S3) + end. + + +test9_server(Pid) -> + io:format("started server: ~p~n",[Pid]), + test9_server1(Pid). + +test9_server1(Pid) -> + Pad = {pad, Pid}, + test9_server2(Pad). + +test9_server2(Pad) -> + {pad, Pid} = Pad, + Pid ! {self(), hej}. + + + + + +test10() -> + receive + X -> + done + after 20000 -> + timeout + end. + +test11() -> + receive + X -> + done + end. + +test12(normal) -> + done; +test12(crash) -> + exit(crash). diff --git a/lib/debugger/test/debugger.spec b/lib/debugger/test/debugger.spec new file mode 100644 index 0000000000..cc8a5aff37 --- /dev/null +++ b/lib/debugger/test/debugger.spec @@ -0,0 +1 @@ +{topcase, {dir, "../debugger_test"}}. diff --git a/lib/debugger/test/debugger_SUITE.erl b/lib/debugger/test/debugger_SUITE.erl new file mode 100644 index 0000000000..4bd9057f98 --- /dev/null +++ b/lib/debugger/test/debugger_SUITE.erl @@ -0,0 +1,123 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2010. 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(debugger_SUITE). + +%% Test break points. + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + app_test/1,erts_debug/1,encrypted_debug_info/1, + no_abstract_code/1]). + +all(suite) -> + [app_test,erts_debug,no_abstract_code,encrypted_debug_info]. + +init_per_testcase(_Case, Config) -> + Dog=test_server:timetrap(?t:minutes(0.5)), + [{watchdog, Dog}|Config]. +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +app_test(Config) when is_list(Config) -> + ?line ?t:app_test(debugger), + ok. + +erts_debug(Config) when is_list(Config) -> + c:l(erts_debug), + ok. + +no_abstract_code(Config) when is_list(Config) -> + ?line PrivDir = ?config(priv_dir, Config), + ?line Simple = filename:join(PrivDir, "simple"), + ?line Source = Simple ++ ".erl", + ?line BeamFile = Simple ++ ".beam", + ?line simple_file(Source), + + %% Compile module without abstract code. + CompileFlags = [{outdir,PrivDir}], + ?line {ok,_} = compile:file(Source, CompileFlags), + ?line error = int:i(Simple), + + %% Cleanup. + ?line ok = file:delete(Source), + ?line ok = file:delete(BeamFile), + + ok. + +encrypted_debug_info(Config) when is_list(Config) -> + try begin crypto:start(), crypto:info(), crypto:stop(), ok end of + ok -> + encrypted_debug_info_1(Config) + catch + error:_ -> + {skip,"The crypto application is missing or broken"} + end. + +encrypted_debug_info_1(Config) -> + ?line PrivDir = ?config(priv_dir, Config), + ?line Simple = filename:join(PrivDir, "simple"), + ?line Source = Simple ++ ".erl", + ?line BeamFile = Simple ++ ".beam", + ?line simple_file(Source), + + %% Compile module. + Key = "_This a Crypto Key_", + CompileFlags = [{outdir,PrivDir},debug_info,{debug_info_key,Key}], + ?line {ok,_} = compile:file(Source, CompileFlags), + + %% Interpret module + ?line ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)), + ?line {module,simple} = int:i(Simple), + + %% Remove key. + ?line {ok,_} = beam_lib:clear_crypto_key_fun(), + ?line error = int:i(Simple), + + %% Cleanup. + ?line ok = file:delete(Source), + ?line ok = file:delete(BeamFile), + + ok. + +simple_crypto_fun(Key) -> + fun(init) -> ok; + ({debug_info, des3_cbc, simple, _}) -> Key + end. + + +simple_file(File) -> + simple_file(File, simple). + +simple_file(File, Module) -> + simple_file(File, Module, member). + +simple_file(File, Module, F) -> + B = list_to_binary(["-module(", atom_to_list(Module), "). " + "-export([t/0]). " + "t() -> " + " t([]). " + "t(L) -> " + " lists:", + atom_to_list(F), "(a, L). "]), + ok = file:write_file(File, B). diff --git a/lib/debugger/test/debugger_test.erl b/lib/debugger/test/debugger_test.erl new file mode 100644 index 0000000000..a64bed5db1 --- /dev/null +++ b/lib/debugger/test/debugger_test.erl @@ -0,0 +1,154 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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% +%% + +%% +%%%---------------------------------------------------------------------- +%%% Purpose : This is the test module to be used in with the test cases +%%% in the debugger test document. +%%%---------------------------------------------------------------------- + +-module(debugger_test). + + +-export ([installation_ok/0, + list/0, + fac/1, + c_break/1]). + + +-define (INT_DIR, "misc"). % The directory of the Interpreter directory +-define (INT, "interpreter"). % The Interpreter directory name. +-define (DBG, "debugger"). % Debugger name + + +%%% installation_ok /0 +%%% + +installation_ok () -> + debugger_ok (), + interpreter_ok (). + + + +%%% debugger_ok /0 +%%% + +debugger_ok () -> + L = code:get_path (), + + case debugger_in_codepath (L) of + {true, Msg} -> + out_put (Msg); + + Other -> + out_put (Other) + end. + + + +%%% debugger_in_codepath /2 +%%% + +debugger_in_codepath ([]) -> + Msg = io_lib:format ("False: ~s not in code path", [?DBG]), + lists:flatten (Msg); + +debugger_in_codepath ([Path | T]) -> + case string:str (Path, ?DBG) =/= 0 of + true -> + Msg = io_lib:format ("Ok: ~s in code path (~s)", [?DBG, Path]), + Msg1 = lists:flatten (Msg), + {true, Msg1}; + + _Other -> + debugger_in_codepath (T) + end. + + + +%%% interpreter_ok /0 +%%% + +interpreter_ok () -> + Root_dir = code:root_dir (), + Misc_dir = filename:join (Root_dir, ?INT_DIR), + + In_misc = case file:list_dir (Misc_dir) of + {ok, L} -> + lists:member (?INT, L); + + Other -> + Other + end, + + case In_misc of + true -> + Msg = io_lib:format ("Ok: ~s is in ~s", [?INT, ?INT_DIR]), + Msg1 = lists:flatten (Msg), + out_put (Msg1); + + Other1 -> + Msg = io_lib:format ("Error: interpreter in misc - ~s", [Other1]), + Msg1 = lists:flatten (Msg), + out_put (Msg1) + end. + + + +%%% list /0 +%%% + +list () -> + A = [1, 2, 3, 4, 5], + B = [a, b, c, d, e], + lists:append (A, B). + + + +%%% fac /1 +%%% + +fac (0) -> + 1; + + +fac (N) -> + N * fac (N - 1). + + + +%%% c_break /1 +%%% + +c_break (Bindings) -> + case int:get_binding ('N', Bindings) of + {value, 3} -> + true; + + _Other -> + false + end. + + + +%%% out_put /1 +%%% + +out_put (X) -> + io:format ("~n~p~n", [X]). diff --git a/lib/debugger/test/debugger_testdoc.fm5 b/lib/debugger/test/debugger_testdoc.fm5 Binary files differnew file mode 100644 index 0000000000..56882b8bd5 --- /dev/null +++ b/lib/debugger/test/debugger_testdoc.fm5 diff --git a/lib/debugger/test/erl_eval_SUITE.erl b/lib/debugger/test/erl_eval_SUITE.erl new file mode 100644 index 0000000000..fd4d28b2c7 --- /dev/null +++ b/lib/debugger/test/erl_eval_SUITE.erl @@ -0,0 +1,1388 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2010. 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(erl_eval_SUITE). +-export([all/1]). + +-export([guard_1/1, guard_2/1, + match_pattern/1, + match_bin/1, + string_plusplus/1, + pattern_expr/1, + guard_3/1, guard_4/1, + lc/1, + simple_cases/1, + unary_plus/1, + apply_atom/1, + otp_5269/1, + otp_6539/1, + otp_6543/1, + otp_6787/1, + otp_6977/1, + otp_7550/1, + otp_8133/1, + funs/1, + try_catch/1, + eval_expr_5/1]). + +%% +%% Define to run outside of test server +%% +%%-define(STANDALONE,1). + +-import(lists,[concat/1, sort/1]). + +-export([count_down/2, count_down_fun/0, do_apply/2, + local_func/3, local_func_value/2]). + +-ifdef(STANDALONE). +-define(config(A,B),config(A,B)). +-export([config/2]). +-define(line, noop, ). +config(priv_dir,_) -> + ".". +-else. +-include("test_server.hrl"). +-export([init_per_testcase/2, fin_per_testcase/2]). +% Default timetrap timeout (set in init_per_testcase). +-define(default_timeout, ?t:minutes(1)). +init_per_testcase(_Case, Config) -> + ?line Dog = ?t:timetrap(?default_timeout), + [{watchdog, Dog} | Config]. +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. +-endif. + +all(doc) -> + ["Test cases for the 'erl_eval' module."]; +all(suite) -> + [guard_1, guard_2, match_pattern, string_plusplus, pattern_expr, + match_bin, guard_3, guard_4, + lc, simple_cases, unary_plus, apply_atom, otp_5269, otp_6539, otp_6543, + otp_6787, otp_6977, otp_7550, otp_8133, funs, try_catch, eval_expr_5]. + +guard_1(doc) -> + ["(OTP-2405)"]; +guard_1(suite) -> + []; +guard_1(Config) when is_list(Config) -> + ?line {ok,Tokens ,_} = + erl_scan:string("if a+4 == 4 -> yes; true -> no end. "), + ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + ?line no = guard_1_compiled(), + ?line {value, no, []} = erl_eval:expr(Expr, []), + ok. + +guard_1_compiled() -> + if a+4 == 4 -> yes; true -> no end. + +guard_2(doc) -> + ["Similar to guard_1, but type-correct"]; +guard_2(suite) -> + []; +guard_2(Config) when is_list(Config) -> + ?line {ok,Tokens ,_} = + erl_scan:string("if 6+4 == 4 -> yes; true -> no end. "), + ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + ?line no = guard_2_compiled(), + ?line {value, no, []} = erl_eval:expr(Expr, []), + ok. + +guard_2_compiled() -> + if 6+4 == 4 -> yes; true -> no end. + +string_plusplus(doc) -> + ["OTP-3069: syntactic sugar string ++ ..."]; +string_plusplus(suite) -> + []; +string_plusplus(Config) when is_list(Config) -> + ?line check(fun() -> case "abc" of "ab" ++ L -> L end end, + "case \"abc\" of \"ab\" ++ L -> L end. ", + "c"), + ?line check(fun() -> case "abcde" of "ab" ++ "cd" ++ L -> L end end, + "case \"abcde\" of \"ab\" ++ \"cd\" ++ L -> L end. ", + "e"), + ?line check(fun() -> case "abc" of [97, 98] ++ L -> L end end, + "case \"abc\" of [97, 98] ++ L -> L end. ", + "c"), + ok. + +match_pattern(doc) -> + ["OTP-2983: match operator in pattern"]; +match_pattern(suite) -> + []; +match_pattern(Config) when is_list(Config) -> + ?line check(fun() -> case {a, b} of {a, _X}=Y -> {x,Y} end end, + "case {a, b} of {a, X}=Y -> {x,Y} end. ", + {x, {a, b}}), + ?line check(fun() -> case {a, b} of Y={a, _X} -> {x,Y} end end, + "case {a, b} of Y={a, X} -> {x,Y} end. ", + {x, {a, b}}), + ?line check(fun() -> case {a, b} of Y={a, _X}=Z -> {Z,Y} end end, + "case {a, b} of Y={a, X}=Z -> {Z,Y} end. ", + {{a, b}, {a, b}}), + ?line check(fun() -> A = 4, B = 28, <<13:(A+(X=B))>>, X end, + "begin A = 4, B = 28, <<13:(A+(X=B))>>, X end.", + 28), + ok. + +match_bin(doc) -> + ["binary match problems"]; +match_bin(suite) -> + []; +match_bin(Config) when is_list(Config) -> + ?line check(fun() -> <<"abc">> = <<"abc">> end, + "<<\"abc\">> = <<\"abc\">>. ", + <<"abc">>), + ?line check(fun() -> + <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>, + {Size,B,Rest} + end, + "begin <<Size,B:Size/binary,Rest/binary>> = <<2,\"AB\",\"CD\">>, " + "{Size,B,Rest} end. ", + {2,<<"AB">>,<<"CD">>}), + ok. + +pattern_expr(doc) -> + ["OTP-3144: compile-time expressions in pattern"]; +pattern_expr(suite) -> + []; +pattern_expr(Config) when is_list(Config) -> + ?line check(fun() -> case 4 of 2+2 -> ok end end, + "case 4 of 2+2 -> ok end. ", + ok), + ?line check(fun() -> case 2 of +2 -> ok end end, + "case 2 of +2 -> ok end. ", + ok), + ok. + +guard_3(doc) -> + ["OTP-4518."]; +guard_3(suite) -> + []; +guard_3(Config) when is_list(Config) -> + ?line check(fun() -> if false -> false; true -> true end end, + "if false -> false; true -> true end.", + true), + ?line check(fun() -> if <<"hej">> == <<"hopp">> -> true; + true -> false end end, + "begin if <<\"hej\">> == <<\"hopp\">> -> true; + true -> false end end.", + false), + ?line check(fun() -> if <<"hej">> == <<"hej">> -> true; + true -> false end end, + "begin if <<\"hej\">> == <<\"hej\">> -> true; + true -> false end end.", + true), + ok. + +guard_4(doc) -> + ["OTP-4885."]; +guard_4(suite) -> + []; +guard_4(Config) when is_list(Config) -> + ?line check(fun() -> if {erlang,'+'}(3,a) -> true ; true -> false end end, + "if {erlang,'+'}(3,a) -> true ; true -> false end.", + false), + ?line check(fun() -> if {erlang,is_integer}(3) -> true ; true -> false end + end, + "if {erlang,is_integer}(3) -> true ; true -> false end.", + true), + ?line check(fun() -> [X || X <- [1,2,3], erlang:is_integer(X)] end, + "[X || X <- [1,2,3], erlang:is_integer(X)].", + [1,2,3]), + ?line check(fun() -> if is_atom(is_integer(a)) -> true ; true -> false end + end, + "if is_atom(is_integer(a)) -> true ; true -> false end.", + true), + ?line check(fun() -> if {erlang,is_atom}({erlang,is_integer}(a)) -> true; + true -> false end end, + "if {erlang,is_atom}({erlang,is_integer}(a)) -> true; " + "true -> false end.", + true), + ?line check(fun() -> if is_atom(3+a) -> true ; true -> false end end, + "if is_atom(3+a) -> true ; true -> false end.", + false), + ?line check(fun() -> if erlang:is_atom(3+a) -> true ; true -> false end + end, + "if erlang:is_atom(3+a) -> true ; true -> false end.", + false), + ok. + + +lc(doc) -> + ["OTP-4518."]; +lc(suite) -> + []; +lc(Config) when is_list(Config) -> + ?line check(fun() -> X = 32, [X || X <- [1,2,3]] end, + "begin X = 32, [X || X <- [1,2,3]] end.", + [1,2,3]), + ?line check(fun() -> X = 32, + [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end, + %% "binsize variable" ^ + "begin X = 32, + [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end.", + [1,2]), + ?line check(fun() -> Y = 13,[X || {X,Y} <- [{1,2}]] end, + "begin Y = 13,[X || {X,Y} <- [{1,2}]] end.", + [1]), + ?line error_check("begin [A || X <- [{1,2}], 1 == A] end.", + {unbound_var,'A'}), + ?line error_check("begin X = 32, + [{Y,W} || X <- [1,2,32,Y=4], Z <- [1,2,W=3]] end.", + {unbound_var,'Y'}), + ?line error_check("begin X = 32,<<A:B>> = <<100:X>> end.", + {unbound_var,'B'}), + ?line check(fun() -> [X || X <- [1,2,3,4], not (X < 2)] end, + "begin [X || X <- [1,2,3,4], not (X < 2)] end.", + [2,3,4]), + ?line check(fun() -> [X || X <- [true,false], X] end, + "[X || X <- [true,false], X].", [true]), + ok. + +simple_cases(doc) -> + ["Simple cases, just to cover some code."]; +simple_cases(suite) -> + []; +simple_cases(Config) when is_list(Config) -> + ?line check(fun() -> A = $C end, "A = $C.", $C), + %% ?line check(fun() -> A = 3.14 end, "A = 3.14.", 3.14), + ?line check(fun() -> self() ! a, A = receive a -> true end end, + "begin self() ! a, A = receive a -> true end end.", + true), + ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c, + receive b -> b end, + {messages, [a,c]} = + erlang:process_info(self(), messages), + c:flush() end, + "begin c:flush(), self() ! a, self() ! b, self() ! c," + "receive b -> b end," + "{messages, [a,c]} =" + " erlang:process_info(self(), messages), c:flush() end.", + ok), + ?line check(fun() -> self() ! a, A = receive a -> true + after 0 -> false end end, + "begin self() ! a, A = receive a -> true" + " after 0 -> false end end.", + true), + ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c, + receive b -> b after 0 -> true end, + {messages, [a,c]} = + erlang:process_info(self(), messages), + c:flush() end, + "begin c:flush(), self() ! a, self() ! b, self() ! c," + "receive b -> b after 0 -> true end," + "{messages, [a,c]} =" + " erlang:process_info(self(), messages), c:flush() end.", + ok), + ?line check(fun() -> receive _ -> true after 10 -> false end end, + "receive _ -> true after 10 -> false end.", + false), + ?line check(fun() -> F = fun(A) -> A end, true = 3 == F(3) end, + "begin F = fun(A) -> A end, true = 3 == F(3) end.", + true), + ?line check(fun() -> F = fun(A) -> A end, true = 3 == apply(F, [3]) end, + "begin F = fun(A) -> A end, true = 3 == apply(F,[3]) end.", + true), + ?line check(fun() -> catch throw(a) end, "catch throw(a).", a), + ?line check(fun() -> catch a end, "catch a.", a), + ?line check(fun() -> 4 == 3 end, "4 == 3.", false), + ?line check(fun() -> not true end, "not true.", false), + ?line check(fun() -> -3 end, "-3.", -3), + + ?line error_check("3.0 = 4.0.", {badmatch,4.0}), + ?line check(fun() -> <<(3.0+2.0):32/float>> = <<5.0:32/float>> end, + "<<(3.0+2.0):32/float>> = <<5.0:32/float>>.", + <<5.0:32/float>>), + + ?line check(fun() -> false andalso kludd end, "false andalso kludd.", + false), + ?line check(fun() -> true andalso true end, "true andalso true.", + true), + ?line check(fun() -> true andalso false end, "true andalso false.", + false), + ?line check(fun() -> true andalso kludd end, "true andalso kludd.", + kludd), + ?line error_check("kladd andalso kludd.", {badarg,kladd}), + + ?line check(fun() -> if false andalso kludd -> a; true -> b end end, + "if false andalso kludd -> a; true -> b end.", + b), + ?line check(fun() -> if true andalso true -> a; true -> b end end, + "if true andalso true -> a; true -> b end.", + a), + ?line check(fun() -> if true andalso false -> a; true -> b end end, + "if true andalso false -> a; true -> b end.", + b), + + ?line check(fun() -> true orelse kludd end, + "true orelse kludd.", true), + ?line check(fun() -> false orelse false end, + "false orelse false.", false), + ?line check(fun() -> false orelse true end, + "false orelse true.", true), + ?line check(fun() -> false orelse kludd end, + "false orelse kludd.", kludd), + ?line error_check("kladd orelse kludd.", {badarg,kladd}), + ?line error_check("[X || X <- [1,2,3], begin 1 end].",{bad_filter,1}), + ?line error_check("[X || X <- a].",{bad_generator,a}), + + ?line check(fun() -> if true orelse kludd -> a; true -> b end end, + "if true orelse kludd -> a; true -> b end.", a), + ?line check(fun() -> if false orelse false -> a; true -> b end end, + "if false orelse false -> a; true -> b end.", b), + ?line check(fun() -> if false orelse true -> a; true -> b end end, + "if false orelse true -> a; true -> b end.", a), + + ?line check(fun() -> [X || X <- [1,2,3], X+2] end, + "[X || X <- [1,2,3], X+2].", []), + + ?line check(fun() -> [X || X <- [1,2,3], [X] == [X || X <- [2]]] end, + "[X || X <- [1,2,3], [X] == [X || X <- [2]]].", + [2]), + ?line check(fun() -> F = fun(1) -> ett; (2) -> zwei end, + ett = F(1), zwei = F(2) end, + "begin F = fun(1) -> ett; (2) -> zwei end, + ett = F(1), zwei = F(2) end.", + zwei), + ?line check(fun() -> F = fun(X) when X == 1 -> ett; + (X) when X == 2 -> zwei end, + ett = F(1), zwei = F(2) end, + "begin F = fun(X) when X == 1 -> ett; + (X) when X == 2 -> zwei end, + ett = F(1), zwei = F(2) end.", + zwei), + ?line error_check("begin F = fun(1) -> ett end, zwei = F(2) end.", + function_clause), + ?line check(fun() -> if length([1]) == 1 -> yes; + true -> no end end, + "if length([1]) == 1 -> yes; + true -> no end.", + yes), + ?line check(fun() -> if is_integer(3) -> true; true -> false end end, + "if is_integer(3) -> true; true -> false end.", true), + ?line check(fun() -> if integer(3) -> true; true -> false end end, + "if integer(3) -> true; true -> false end.", true), + ?line check(fun() -> if is_float(3) -> true; true -> false end end, + "if is_float(3) -> true; true -> false end.", false), + ?line check(fun() -> if float(3) -> true; true -> false end end, + "if float(3) -> true; true -> false end.", false), + ?line check(fun() -> if is_number(3) -> true; true -> false end end, + "if is_number(3) -> true; true -> false end.", true), + ?line check(fun() -> if number(3) -> true; true -> false end end, + "if number(3) -> true; true -> false end.", true), + ?line check(fun() -> if is_atom(a) -> true; true -> false end end, + "if is_atom(a) -> true; true -> false end.", true), + ?line check(fun() -> if atom(a) -> true; true -> false end end, + "if atom(a) -> true; true -> false end.", true), + ?line check(fun() -> if is_list([]) -> true; true -> false end end, + "if is_list([]) -> true; true -> false end.", true), + ?line check(fun() -> if list([]) -> true; true -> false end end, + "if list([]) -> true; true -> false end.", true), + ?line check(fun() -> if is_tuple({}) -> true; true -> false end end, + "if is_tuple({}) -> true; true -> false end.", true), + ?line check(fun() -> if tuple({}) -> true; true -> false end end, + "if tuple({}) -> true; true -> false end.", true), + ?line check(fun() -> if is_pid(self()) -> true; true -> false end end, + "if is_pid(self()) -> true; true -> false end.", true), + ?line check(fun() -> if pid(self()) -> true; true -> false end end, + "if pid(self()) -> true; true -> false end.", true), + ?line check(fun() -> R = make_ref(), if is_reference(R) -> true; + true -> false end end, + "begin R = make_ref(), if is_reference(R) -> true;" + "true -> false end end.", true), + ?line check(fun() -> R = make_ref(), if reference(R) -> true; + true -> false end end, + "begin R = make_ref(), if reference(R) -> true;" + "true -> false end end.", true), + ?line check(fun() -> if is_port(a) -> true; true -> false end end, + "if is_port(a) -> true; true -> false end.", false), + ?line check(fun() -> if port(a) -> true; true -> false end end, + "if port(a) -> true; true -> false end.", false), + ?line check(fun() -> if is_function(a) -> true; true -> false end end, + "if is_function(a) -> true; true -> false end.", false), + ?line check(fun() -> if function(a) -> true; true -> false end end, + "if function(a) -> true; true -> false end.", false), + ?line check(fun() -> if is_binary(<<>>) -> true; true -> false end end, + "if is_binary(<<>>) -> true; true -> false end.", true), + ?line check(fun() -> if binary(<<>>) -> true; true -> false end end, + "if binary(<<>>) -> true; true -> false end.", true), + ?line check(fun() -> if is_integer(a) == true -> yes; + true -> no end end, + "if is_integer(a) == true -> yes; + true -> no end.", + no), + ?line check(fun() -> if [] -> true; true -> false end end, + "if [] -> true; true -> false end.", false), + ?line error_check("if lists:member(1,[1]) -> true; true -> false end.", + illegal_guard_expr), + ?line error_check("if false -> true end.", if_clause), + ?line check(fun() -> if a+b -> true; true -> false end end, + "if a + b -> true; true -> false end.", false), + ?line check(fun() -> if + b -> true; true -> false end end, + "if + b -> true; true -> false end.", false), + ?line error_check("case foo of bar -> true end.", {case_clause,foo}), + ?line error_check("case 4 of 2+a -> true; _ -> false end.", + illegal_pattern), + ?line error_check("case 4 of +a -> true; _ -> false end.", + illegal_pattern), + ?line check(fun() -> case a of + X when X == b -> one; + X when X == a -> two + end end, + "begin case a of + X when X == b -> one; + X when X == a -> two + end end.", two), + ?line error_check("3 = 4.", {badmatch,4}), + ?line error_check("a = 3.", {badmatch,3}), + %% ?line error_check("3.1 = 2.7.",{badmatch,2.7}), + ?line error_check("$c = 4.", {badmatch,4}), + ?line check(fun() -> $c = $c end, "$c = $c.", $c), + ?line check(fun() -> _ = bar end, "_ = bar.", bar), + ?line check(fun() -> A = 14, A = 14 end, + "begin A = 14, A = 14 end.", 14), + ?line error_check("begin A = 14, A = 16 end.", {badmatch,16}), + ?line error_check("\"hej\" = \"san\".", {badmatch,"san"}), + ?line check(fun() -> "hej" = "hej" end, + "\"hej\" = \"hej\".", "hej"), + ?line error_check("[] = [a].", {badmatch,[a]}), + ?line check(fun() -> [] = [] end, "[] = [].", []), + ?line error_check("[a] = [].", {badmatch,[]}), + ?line error_check("{a,b} = 34.", {badmatch,34}), + ?line check(fun() -> <<X:7>> = <<8:7>>, X end, + "begin <<X:7>> = <<8:7>>, X end.", 8), + ?line error_check("<<34:32>> = \"hej\".", {badmatch,"hej"}), + ?line check(fun() -> trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end, + "begin trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end.", 0), + ?line check(fun() -> (2#101 band 2#10101) bor (2#110 bxor 2#010) end, + "(2#101 band 2#10101) bor (2#110 bxor 2#010).", 5), + ?line check(fun() -> (2#1 bsl 4) + (2#10000 bsr 3) end, + "(2#1 bsl 4) + (2#10000 bsr 3).", 18), + ?line check(fun() -> ((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2) end, + "((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2).", false), + ?line check(fun() -> (a /= b) or (2 > 4) or (3 >= 3) end, + "(a /= b) or (2 > 4) or (3 >= 3).", true), + ?line check(fun() -> "hej" ++ "san" =/= "hejsan" -- "san" end, + "\"hej\" ++ \"san\" =/= \"hejsan\" -- \"san\".", true), + ?line check(fun() -> (bnot 1) < -0 end, "(bnot (+1)) < -0.", true), + ok. + +unary_plus(doc) -> + ["OTP-4929. Unary plus rejects non-numbers."]; +unary_plus(suite) -> + []; +unary_plus(Config) when is_list(Config) -> + ?line check(fun() -> F = fun(X) -> + X end, + true = -1 == F(-1) end, + "begin F = fun(X) -> + X end," + " true = -1 == F(-1) end.", true, ['F'], none, none), + ?line error_check("+a.", badarith), + ok. + +apply_atom(doc) -> + ["OTP-5064. Can no longer apply atoms."]; +apply_atom(suite) -> + []; +apply_atom(Config) when is_list(Config) -> + ?line error_check("[X || X <- [[1],[2]], + begin L = length, L(X) =:= 1 end].", + {badfun,length}), + ok. + +otp_5269(doc) -> + ["OTP-5269. Bugs in the bit syntax."]; +otp_5269(suite) -> + []; +otp_5269(Config) when is_list(Config) -> + ?line check(fun() -> L = 8, + F = fun(<<A:L,B:A>>) -> B end, + F(<<16:8, 7:16>>) + end, + "begin + L = 8, F = fun(<<A:L,B:A>>) -> B end, F(<<16:8, 7:16>>) + end.", + 7), + ?line check(fun() -> L = 8, + F = fun(<<L:L,B:L>>) -> B end, + F(<<16:8, 7:16>>) + end, + "begin + L = 8, F = fun(<<L:L,B:L>>) -> B end, F(<<16:8, 7:16>>) + end.", + 7), + ?line check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end, + "begin L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end.", + 7), + ?line error_check("begin L = 8, <<L:L,B:L>> = <<16:8, 7:16>> end.", + {badmatch,<<16:8,7:16>>}), + + ?line error_check("begin <<L:16,L:L>> = <<16:16,8:16>>, L end.", + {badmatch, <<16:16,8:16>>}), + ?line check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end, + "begin U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end.", + 32), + ?line check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end, + "begin U = 8, [U || <<U:U>> <- [<<32:8>>]] end.", + [32]), + ?line error_check("(fun({3,<<A:32,A:32>>}) -> a end) + ({3,<<17:32,19:32>>}).", + function_clause), + ?line check(fun() -> [X || <<A:8, + B:A>> <- [<<16:8,19:16>>], + <<X:8>> <- [<<B:8>>]] end, + "[X || <<A:8, + B:A>> <- [<<16:8,19:16>>], + <<X:8>> <- [<<B:8>>]].", + [19]), + ok. + +otp_6539(doc) -> + ["OTP-6539. try/catch bugs."]; +otp_6539(suite) -> + []; +otp_6539(Config) when is_list(Config) -> + ?line check(fun() -> + F = fun(A,B) -> + try A+B + catch _:_ -> dontthinkso + end + end, + lists:zipwith(F, [1,2], [2,3]) + end, + "begin + F = fun(A,B) -> + try A+B + catch _:_ -> dontthinkso + end + end, + lists:zipwith(F, [1,2], [2,3]) + end.", + [3, 5]), + ok. + +otp_6543(doc) -> + ["OTP-6543. bitlevel binaries."]; +otp_6543(suite) -> + []; +otp_6543(Config) when is_list(Config) -> + ?line check(fun() -> + << <<X>> || <<X>> <- [1,2,3] >> + end, + "<< <<X>> || <<X>> <- [1,2,3] >>.", + <<>>), + ?line check(fun() -> + << <<X>> || X <- [1,2,3] >> + end, + "<< <<X>> || X <- [1,2,3] >>.", + <<1,2,3>>), + ?line check(fun() -> + << <<X:8>> || <<X:2>> <= <<"hej">> >> + end, + "<< <<X:8>> || <<X:2>> <= <<\"hej\">> >>.", + <<1,2,2,0,1,2,1,1,1,2,2,2>>), + ?line check(fun() -> + << <<X:8>> || + <<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >> + end, + "<< <<X:8>> || + <<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >>.", + <<7,3>>), + ?line check(fun() -> <<34:18/big>> end, + "<<34:18/big>>.", + <<0,8,2:2>>), + ?line check(fun() -> <<34:18/big-unit:2>> end, + "<<34:18/big-unit:2>>.", + <<0,0,0,2,2:4>>), + ?line check(fun() -> <<34:18/little>> end, + "<<34:18/little>>.", + <<34,0,0:2>>), + ?line case eval_string("<<34:18/native>>.") of + <<0,8,2:2>> -> ok; + <<34,0,0:2>> -> ok + end, + ?line check(fun() -> <<34:18/big-signed>> end, + "<<34:18/big-signed>>.", + <<0,8,2:2>>), + ?line check(fun() -> <<34:18/little-signed>> end, + "<<34:18/little-signed>>.", + <<34,0,0:2>>), + ?line case eval_string("<<34:18/native-signed>>.") of + <<0,8,2:2>> -> ok; + <<34,0,0:2>> -> ok + end, + ?line check(fun() -> <<34:18/big-unsigned>> end, + "<<34:18/big-unsigned>>.", + <<0,8,2:2>>), + ?line check(fun() -> <<34:18/little-unsigned>> end, + "<<34:18/little-unsigned>>.", + <<34,0,0:2>>), + ?line case eval_string("<<34:18/native-unsigned>>.") of + <<0,8,2:2>> -> ok; + <<34,0,0:2>> -> ok + end, + ?line check(fun() -> <<3.14:32/float-big>> end, + "<<3.14:32/float-big>>.", + <<64,72,245,195>>), + ?line check(fun() -> <<3.14:32/float-little>> end, + "<<3.14:32/float-little>>.", + <<195,245,72,64>>), + ?line case eval_string("<<3.14:32/float-native>>.") of + <<64,72,245,195>> -> ok; + <<195,245,72,64>> -> ok + end, + ?line error_check("<<(<<17,3:2>>)/binary>>.", badarg), + ?line check(fun() -> <<(<<17,3:2>>)/bitstring>> end, + "<<(<<17,3:2>>)/bitstring>>.", + <<17,3:2>>), + ?line check(fun() -> <<(<<17,3:2>>):10/bitstring>> end, + "<<(<<17,3:2>>):10/bitstring>>.", + <<17,3:2>>), + ?line check(fun() -> <<<<344:17>>/binary-unit:17>> end, + "<<<<344:17>>/binary-unit:17>>.", + <<344:17>>), + + ?line check(fun() -> <<X:18/big>> = <<34:18/big>>, X end, + "begin <<X:18/big>> = <<34:18/big>>, X end.", + 34), + ?line check(fun() -> <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end, + "begin <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end.", + 34), + ?line check(fun() -> <<X:18/little>> = <<34:18/little>>, X end, + "begin <<X:18/little>> = <<34:18/little>>, X end.", + 34), + ?line check(fun() -> <<X:18/native>> = <<34:18/native>>, X end, + "begin <<X:18/native>> = <<34:18/native>>, X end.", + 34), + ?line check(fun() -> <<X:18/big-signed>> = <<34:18/big-signed>>, X end, + "begin <<X:18/big-signed>> = <<34:18/big-signed>>, X end.", + 34), + ?line check(fun() -> <<X:18/little-signed>> = <<34:18/little-signed>>, + X end, + "begin <<X:18/little-signed>> = <<34:18/little-signed>>, + X end.", + 34), + ?line check(fun() -> <<X:18/native-signed>> = <<34:18/native-signed>>, + X end, + "begin <<X:18/native-signed>> = <<34:18/native-signed>>, + X end.", + 34), + ?line check(fun() -> <<X:18/big-unsigned>> = <<34:18/big-unsigned>>, + X end, + "begin <<X:18/big-unsigned>> = <<34:18/big-unsigned>>, + X end.", + 34), + ?line check(fun() -> + <<X:18/little-unsigned>> = <<34:18/little-unsigned>>, + X end, + "begin <<X:18/little-unsigned>> = <<34:18/little-unsigned>>, + X end.", + 34), + ?line check(fun() -> + <<X:18/native-unsigned>> = <<34:18/native-unsigned>>, + X end, + "begin <<X:18/native-unsigned>> = <<34:18/native-unsigned>>, + X end.", + 34), + ?line check(fun() -> <<X:32/float-big>> = <<2.0:32/float-big>>, X end, + "begin <<X:32/float-big>> = <<2.0:32/float-big>>, + X end.", + 2.0), + ?line check(fun() -> <<X:32/float-little>> = <<2.0:32/float-little>>, + X end, + "begin <<X:32/float-little>> = <<2.0:32/float-little>>, + X end.", + 2.0), + ?line check(fun() -> <<X:32/float-native>> = <<2.0:32/float-native>>, + X end, + "begin <<X:32/float-native>> = <<2.0:32/float-native>>, + X end.", + 2.0), + + ?line check( + fun() -> + [X || <<"hej",X:8>> <= <<"hej",8,"san",9,"hej",17,"hej">>] + end, + "[X || <<\"hej\",X:8>> <= + <<\"hej\",8,\"san\",9,\"hej\",17,\"hej\">>].", + [8,17]), + ?line check( + fun() -> + L = 8, << <<B:32>> || <<L:L,B:L>> <= <<16:8, 7:16>> >> + end, + "begin L = 8, << <<B:32>> || <<L:L,B:L>> <= <<16:8, 7:16>> >> + end.", + <<0,0,0,7>>), + %% Test the Value part of a binary segment. + %% "Old" bugs have been fixed (partial_eval is called on Value). + ?line check(fun() -> [ 3 || <<17/float>> <= <<17.0/float>>] end, + "[ 3 || <<17/float>> <= <<17.0/float>>].", + [3]), + ?line check(fun() -> [ 3 || <<17/float>> <- [<<17.0/float>>]] end, + "[ 3 || <<17/float>> <- [<<17.0/float>>]].", + [3]), + ?line check(fun() -> [ X || <<17/float,X:3>> <= <<17.0/float,2:3>>] end, + "[ X || <<17/float,X:3>> <= <<17.0/float,2:3>>].", + [2]), + ?line check(fun() -> + [ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>] + end, + "[ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>].", + [foo]), + ?line check(fun() -> + [ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]] + end, + "[ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]].", + [foo]), + ?line error_check("[ foo || <<(1 bsl 1024)/float>> <- + [<<(1 bsl 1024)/float>>]].", + badarg), + ?line check(fun() -> + [ foo || <<(1 bsl 1024)/float>> <- [<<(1 bsl 1023)/float>>]] + end, + "[ foo || <<(1 bsl 1024)/float>> <- + [<<(1 bsl 1023)/float>>]].", + []), + ?line check(fun() -> + [ foo || <<(1 bsl 1024)/float>> <= <<(1 bsl 1023)/float>>] + end, + "[ foo || <<(1 bsl 1024)/float>> <= + <<(1 bsl 1023)/float>>].", + []), + ?line check(fun() -> + L = 8, + [{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>] + end, + "begin L = 8, + [{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>] + end.", + [{32,7.0}]), + ?line check(fun() -> + L = 8, + [{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]] + end, + "begin L = 8, + [{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]] + end.", + [{32,7.0}]), + ?line check(fun() -> + [foo || <<"s">> <= <<"st">>] + end, + "[foo || <<\"s\">> <= <<\"st\">>].", + [foo]), + ?line check(fun() -> <<_:32>> = <<17:32>> end, + "<<_:32>> = <<17:32>>.", + <<17:32>>), + ?line check(fun() -> [foo || <<_:32>> <= <<17:32,20:32>>] end, + "[foo || <<_:32>> <= <<17:32,20:32>>].", + [foo,foo]), + + ?line check(fun() -> << <<X:32>> || X <- [1,2,3], X > 1 >> end, + "<< <<X:32>> || X <- [1,2,3], X > 1 >>.", + <<0,0,0,2,0,0,0,3>>), + ?line error_check("[X || <<X>> <= [a,b]].",{bad_generator,[a,b]}), + ok. + +otp_6787(doc) -> + ["OTP-6787. bitlevel binaries."]; +otp_6787(suite) -> + []; +otp_6787(Config) when is_list(Config) -> + ?line check( + fun() -> <<16:(1024*1024)>> = <<16:(1024*1024)>> end, + "<<16:(1024*1024)>> = <<16:(1024*1024)>>.", + <<16:1048576>>), + ok. + +otp_6977(doc) -> + ["OTP-6977. ++ bug."]; +otp_6977(suite) -> + []; +otp_6977(Config) when is_list(Config) -> + ?line check( + fun() -> (fun([$X] ++ _) -> ok end)("X") end, + "(fun([$X] ++ _) -> ok end)(\"X\").", + ok), + ok. + +otp_7550(doc) -> + ["OTP-7550. Support for UTF-8, UTF-16, UTF-32."]; +otp_7550(Config) when is_list(Config) -> + + %% UTF-8. + ?line check( + fun() -> <<65>> = <<65/utf8>> end, + "<<65>> = <<65/utf8>>.", + <<65>>), + ?line check( + fun() -> <<350/utf8>> = <<197,158>> end, + "<<350/utf8>> = <<197,158>>.", + <<197,158>>), + ?line check( + fun() -> <<$b,$j,$\303,$\266,$r,$n>> = <<"bj\366rn"/utf8>> end, + "<<$b,$j,$\303,$\266,$r,$n>> = <<\"bj\366rn\"/utf8>>.", + <<$b,$j,$\303,$\266,$r,$n>>), + + %% UTF-16. + ?line check( + fun() -> <<0,65>> = <<65/utf16>> end, + "<<0,65>> = <<65/utf16>>.", + <<0,65>>), + ?line check( + fun() -> <<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>> end, + "<<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>>.", + <<16#D8,16#08,16#DF,16#45>>), + ?line check( + fun() -> <<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>> end, + "<<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>>.", + <<16#08,16#D8,16#45,16#DF>>), + + ?line check( + fun() -> <<350/utf16>> = <<1,94>> end, + "<<350/utf16>> = <<1,94>>.", + <<1,94>>), + ?line check( + fun() -> <<350/little-utf16>> = <<94,1>> end, + "<<350/little-utf16>> = <<94,1>>.", + <<94,1>>), + ?line check( + fun() -> <<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>> end, + "<<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>>.", + <<16#D8,16#08,16#DF,16#45>>), + ?line check( + fun() -> <<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>> end, + "<<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>>.", + <<16#08,16#D8,16#45,16#DF>>), + + %% UTF-32. + ?line check( + fun() -> <<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>> end, + "<<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>>.", + <<16#0,16#01,16#23,16#45>>), + ?line check( + fun() -> <<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>> end, + "<<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>>.", + <<16#0,16#01,16#23,16#45>>), + ?line check( + fun() -> <<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>> end, + "<<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>>.", + <<16#45,16#23,16#01,16#00>>), + ?line check( + fun() -> <<16#12345/little-utf32>> end, + "<<16#12345/little-utf32>>.", + <<16#45,16#23,16#01,16#00>>), + + %% Mixed. + ?line check( + fun() -> <<16#41,16#12345/utf32,16#0391:16,16#2E:8>> end, + "<<16#41,16#12345/utf32,16#0391:16,16#2E:8>>.", + <<16#41,16#00,16#01,16#23,16#45,16#03,16#91,16#2E>>), + ok. + + +otp_8133(doc) -> + ["OTP-8133. Bit comprehension bug."]; +otp_8133(suite) -> + []; +otp_8133(Config) when is_list(Config) -> + ?line check( + fun() -> + E = fun(N) -> + if + is_integer(N) -> <<N/integer>>; + true -> throw(foo) + end + end, + try << << (E(V))/binary >> || V <- [1,2,3,a] >> + catch foo -> ok + end + end, + "begin + E = fun(N) -> + if is_integer(N) -> <<N/integer>>; + true -> throw(foo) + end + end, + try << << (E(V))/binary >> || V <- [1,2,3,a] >> + catch foo -> ok + end + end.", + ok), + ?line check( + fun() -> + E = fun(N) -> + if + is_integer(N) -> <<N/integer>>; + true -> erlang:error(foo) + end + end, + try << << (E(V))/binary >> || V <- [1,2,3,a] >> + catch error:foo -> ok + end + end, + "begin + E = fun(N) -> + if is_integer(N) -> <<N/integer>>; + true -> erlang:error(foo) + end + end, + try << << (E(V))/binary >> || V <- [1,2,3,a] >> + catch error:foo -> ok + end + end.", + ok), + ok. + +funs(doc) -> + ["Simple cases, just to cover some code."]; +funs(suite) -> + []; +funs(Config) when is_list(Config) -> + do_funs(none, none), + do_funs(lfh(), none), + do_funs(lfh(), efh()), + + ?line error_check("nix:foo().", {access_not_allowed,nix}, lfh(), efh()), + ?line error_check("bar().", undef, none, none), + + ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, + F1(F1, 1000) end, + "begin F1 = fun(F,N) -> count_down(F, N) end," + "F1(F1,1000) end.", + 0, ['F1'], lfh(), none), + + ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, + F1(F1, 1000) end, + "begin F1 = fun(F,N) -> count_down(F, N) end," + "F1(F1,1000) end.", + 0, ['F1'], lfh_value(), none), + + ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, + F1(F1, 1000) end, + "begin F1 = fun(F,N) -> count_down(F, N) end," + "F1(F1,1000) end.", + 0, ['F1'], lfh_value_extra(), none), + + ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, + F1(F1, 1000) end, + "begin F1 = fun(F,N) -> count_down(F, N) end," + "F1(F1,1000) end.", + 0, ['F1'], {?MODULE,local_func_value}, none), + %% This is not documented, and only for backward compatibility (good!). + B0 = erl_eval:new_bindings(), + ?line check(fun() -> is_function(?MODULE:count_down_fun()) end, + "begin is_function(count_down_fun()) end.", + true, [], {?MODULE,local_func,[B0]},none), + + EF = fun({timer,sleep}, As) when length(As) == 1 -> exit({got_it,sleep}); + ({M,F}, As) -> apply(M, F, As) + end, + EFH = {value, EF}, + ?line error_check("apply(timer, sleep, [1]).", got_it, none, EFH), + ?line error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.", + got_it, none, EFH), + ?line error_check("fun c/1.", undef), + ?line error_check("fun a:b/0().", undef), + + MaxArgs = 20, + ?line [true] = + lists:usort([run_many_args(SAs) || SAs <- many_args(MaxArgs)]), + ?line {'EXIT',{{argument_limit,_},_}} = + (catch run_many_args(many_args1(MaxArgs+1))), + ok. + +run_many_args({S, As}) -> + apply(eval_string(S), As) =:= As. + +many_args(N) -> + [many_args1(I) || I <- lists:seq(1, N)]. + +many_args1(N) -> + F = fun(L, P) -> + tl(lists:flatten([","++P++integer_to_list(E) || E <- L])) + end, + L = lists:seq(1, N), + T = F(L, "V"), + S = lists:flatten(io_lib:format("fun(~s) -> [~s] end.", [T, T])), + {S, L}. + +do_funs(LFH, EFH) -> + %% LFH is not really used by these examples... + + %% These tests do not prove that tail recursive functions really + %% work (that the process does not grow); one should also run them + %% manually with 1000 replaced by 1000000. + + M = atom_to_list(?MODULE), + ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, + F1(F1, 1000) end, + concat(["begin F1 = fun(F,N) -> ", M, + ":count_down(F, N) end, F1(F1,1000) end."]), + 0, ['F1'], LFH, EFH), + ?line check(fun() -> F1 = fun(F,N) -> apply(?MODULE,count_down,[F,N]) + end, F1(F1, 1000) end, + concat(["begin F1 = fun(F,N) -> apply(", M, + ",count_down,[F, N]) end, F1(F1,1000) end."]), + 0, ['F1'], LFH, EFH), + ?line check(fun() -> F1 = fun(F,N) -> {?MODULE,count_down}(F,N) + end, F1(F1, 1000) end, + concat(["begin F1 = fun(F,N) -> {", M, + ",count_down}(F, N) end, F1(F1,1000) end."]), + 0, ['F1'], LFH, EFH), + ?line check(fun() -> F = fun(F,N) when N > 0 -> apply(F,[F,N-1]); + (_F,0) -> ok end, + F(F, 1000) + end, + "begin F = fun(F,N) when N > 0 -> apply(F,[F,N-1]);" + "(_F,0) -> ok end," + "F(F, 1000) end.", + ok, ['F'], LFH, EFH), + ?line check(fun() -> F = fun(F,N) when N > 0 -> + apply(erlang,apply,[F,[F,N-1]]); + (_F,0) -> ok end, + F(F, 1000) + end, + "begin F = fun(F,N) when N > 0 ->" + "apply(erlang,apply,[F,[F,N-1]]);" + "(_F,0) -> ok end," + "F(F, 1000) end.", + ok, ['F'], LFH, EFH), + ?line check(fun() -> F = count_down_fun(), + SF = fun(SF, F1, N) -> F(SF, F1, N) end, + SF(SF, F, 1000) end, + concat(["begin F = ", M, ":count_down_fun()," + "SF = fun(SF, F1, N) -> F(SF, F1, N) end," + "SF(SF, F, 1000) end."]), + ok, ['F','SF'], LFH, EFH), + + + ?line check(fun() -> F = fun(X) -> A = 1+X, {X,A} end, + true = {2,3} == F(2) end, + "begin F = fun(X) -> A = 1+X, {X,A} end, + true = {2,3} == F(2) end.", true, ['F'], LFH, EFH), + ?line check(fun() -> F = fun(X) -> {erlang,'+'}(X,2) end, + true = 3 == F(1) end, + "begin F = fun(X) -> {erlang,'+'}(X,2) end," + " true = 3 == F(1) end.", true, ['F'], + LFH, EFH), + ?line check(fun() -> F = fun(X) -> byte_size(X) end, + ?MODULE:do_apply(F,<<"hej">>) end, + concat(["begin F = fun(X) -> size(X) end,", + M,":do_apply(F,<<\"hej\">>) end."]), + 3, ['F'], LFH, EFH), + + ?line check(fun() -> F1 = fun(X, Z) -> {X,Z} end, + Z = 5, + F2 = fun(X, Y) -> F1(Z,{X,Y}) end, + F3 = fun(X, Y) -> {a,F1(Z,{X,Y})} end, + {5,{x,y}} = F2(x,y), + {a,{5,{y,x}}} = F3(y,x), + {5,{5,y}} = F2(Z,y), + true = {5,{x,5}} == F2(x,Z) end, + "begin F1 = fun(X, Z) -> {X,Z} end, + Z = 5, + F2 = fun(X, Y) -> F1(Z,{X,Y}) end, + F3 = fun(X, Y) -> {a,F1(Z,{X,Y})} end, + {5,{x,y}} = F2(x,y), + {a,{5,{y,x}}} = F3(y,x), + {5,{5,y}} = F2(Z,y), + true = {5,{x,5}} == F2(x,Z) end.", + true, ['F1','Z','F2','F3'], LFH, EFH), + ?line check(fun() -> F = fun(X) -> byte_size(X) end, + F2 = fun(Y) -> F(Y) end, + ?MODULE:do_apply(F2,<<"hej">>) end, + concat(["begin F = fun(X) -> size(X) end,", + "F2 = fun(Y) -> F(Y) end,", + M,":do_apply(F2,<<\"hej\">>) end."]), + 3, ['F','F2'], LFH, EFH), + ?line check(fun() -> Z = 5, F = fun(X) -> {Z,X} end, + F2 = fun(Z) -> F(Z) end, F2(3) end, + "begin Z = 5, F = fun(X) -> {Z,X} end, + F2 = fun(Z) -> F(Z) end, F2(3) end.", + {5,3},['F','F2','Z'], LFH, EFH), + ?line check(fun() -> F = fun(Z) -> Z end, + F2 = fun(X) -> F(X), Z = {X,X}, Z end, + {1,1} = F2(1), Z = 7, Z end, + "begin F = fun(Z) -> Z end, + F2 = fun(X) -> F(X), Z = {X,X}, Z end, + {1,1} = F2(1), Z = 7, Z end.", 7, ['F','F2','Z'], + LFH, EFH), + ?line check(fun() -> F = fun(F, N) -> [?MODULE:count_down(F,N) || X <-[1]] + end, F(F,2) end, + concat(["begin F = fun(F, N) -> [", M, + ":count_down(F,N) || X <-[1]] end, F(F,2) end."]), + [[[0]]], ['F'], LFH, EFH), + ok. + +count_down(F, N) when N > 0 -> + F(F, N-1); +count_down(_F, N) -> + N. + +count_down_fun() -> + fun(SF,F,N) when N > 0 -> SF(SF,F,N-1); + (_SF,_F,_N) -> ok + end. + +do_apply(F, V) -> + F(V). + +lfh() -> + {eval, fun(F, As, Bs) -> local_func(F, As, Bs) end}. + +local_func(F, As0, Bs0) when is_atom(F) -> + {As,Bs} = erl_eval:expr_list(As0, Bs0, {eval,lfh()}), + case erlang:function_exported(?MODULE, F, length(As)) of + true -> + {value,apply(?MODULE, F, As),Bs}; + false -> + {value,apply(shell_default, F, As),Bs} + end. + +lfh_value_extra() -> + %% Not documented. + {value, fun(F, As) -> local_func_value(F, As) end, []}. + +lfh_value() -> + {value, fun(F, As) -> local_func_value(F, As) end}. + +local_func_value(F, As) when is_atom(F) -> + case erlang:function_exported(?MODULE, F, length(As)) of + true -> + apply(?MODULE, F, As); + false -> + apply(shell_default, F, As) + end. + +efh() -> + {value, fun(F, As) -> external_func(F, As) end}. + +external_func({M,_}, _As) when M == nix -> + exit({{access_not_allowed,M},[mfa]}); +external_func(F, As) when is_function(F) -> + apply(F, As); +external_func({M,F}, As) -> + apply(M, F, As). + + + +try_catch(doc) -> + ["Test try-of-catch-after-end statement"]; +try_catch(suite) -> + []; +try_catch(Config) when is_list(Config) -> + %% Match in of with catch + ?line check(fun() -> try 1 of 1 -> 2 catch _:_ -> 3 end end, + "try 1 of 1 -> 2 catch _:_ -> 3 end.", 2), + ?line check(fun() -> try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end, + "try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 2), + ?line check(fun() -> try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end, + "try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 4), + %% Just after + ?line check(fun () -> X = try 1 after put(try_catch, 2) end, + {X,get(try_catch)} end, + "begin X = try 1 after put(try_catch, 2) end, " + "{X,get(try_catch)} end.", {1,2}), + %% Match in of with after + ?line check(fun() -> X = try 1 of 1 -> 2 after put(try_catch, 3) end, + {X,get(try_catch)} end, + "begin X = try 1 of 1 -> 2 after put(try_catch, 3) end, " + "{X,get(try_catch)} end.", {2,3}), + ?line check(fun() -> X = try 1 of 1 -> 2; 3 -> 4 + after put(try_catch, 5) end, + {X,get(try_catch)} end, + "begin X = try 1 of 1 -> 2; 3 -> 4 " + " after put(try_catch, 5) end, " + " {X,get(try_catch)} end.", {2,5}), + ?line check(fun() -> X = try 3 of 1 -> 2; 3 -> 4 + after put(try_catch, 5) end, + {X,get(try_catch)} end, + "begin X = try 3 of 1 -> 2; 3 -> 4 " + " after put(try_catch, 5) end, " + " {X,get(try_catch)} end.", {4,5}), + %% Nomatch in of + ?line error_check("try 1 of 2 -> 3 catch _:_ -> 4 end.", + {try_clause,1}), + %% Nomatch in of with after + ?line check(fun () -> {'EXIT',{{try_clause,1},_}} = + begin catch try 1 of 2 -> 3 + after put(try_catch, 4) end end, + get(try_catch) end, + "begin {'EXIT',{{try_clause,1},_}} = " + " begin catch try 1 of 2 -> 3 " + " after put(try_catch, 4) end end, " + " get(try_catch) end. ", 4), + %% Exception in try + ?line check(fun () -> try 1=2 catch error:{badmatch,2} -> 3 end end, + "try 1=2 catch error:{badmatch,2} -> 3 end.", 3), + ?line check(fun () -> try 1=2 of 3 -> 4 + catch error:{badmatch,2} -> 5 end end, + "try 1=2 of 3 -> 4 " + "catch error:{badmatch,2} -> 5 end.", 5), + %% Exception in try with after + ?line check(fun () -> X = try 1=2 + catch error:{badmatch,2} -> 3 + after put(try_catch, 4) end, + {X,get(try_catch)} end, + "begin X = try 1=2 " + " catch error:{badmatch,2} -> 3 " + " after put(try_catch, 4) end, " + " {X,get(try_catch)} end. ", {3,4}), + ?line check(fun () -> X = try 1=2 of 3 -> 4 + catch error:{badmatch,2} -> 5 + after put(try_catch, 6) end, + {X,get(try_catch)} end, + "begin X = try 1=2 of 3 -> 4" + " catch error:{badmatch,2} -> 5 " + " after put(try_catch, 6) end, " + " {X,get(try_catch)} end. ", {5,6}), + %% Uncaught exception + ?line error_check("try 1=2 catch error:undefined -> 3 end. ", + {badmatch,2}), + ?line error_check("try 1=2 of 3 -> 4 catch error:undefined -> 5 end. ", + {badmatch,2}), + %% Uncaught exception with after + ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = + begin catch try 1=2 + after put(try_catch, 3) end end, + get(try_catch) end, + "begin {'EXIT',{{badmatch,2},_}} = " + " begin catch try 1=2 " + " after put(try_catch, 3) end end, " + " get(try_catch) end. ", 3), + ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = + begin catch try 1=2 of 3 -> 4 + after put(try_catch, 5) end end, + get(try_catch) end, + "begin {'EXIT',{{badmatch,2},_}} = " + " begin catch try 1=2 of 3 -> 4" + " after put(try_catch, 5) end end, " + " get(try_catch) end. ", 5), + ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = + begin catch try 1=2 catch error:undefined -> 3 + after put(try_catch, 4) end end, + get(try_catch) end, + "begin {'EXIT',{{badmatch,2},_}} = " + " begin catch try 1=2 catch error:undefined -> 3 " + " after put(try_catch, 4) end end, " + " get(try_catch) end. ", 4), + ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = + begin catch try 1=2 of 3 -> 4 + catch error:undefined -> 5 + after put(try_catch, 6) end end, + get(try_catch) end, + "begin {'EXIT',{{badmatch,2},_}} = " + " begin catch try 1=2 of 3 -> 4 " + " catch error:undefined -> 5 " + " after put(try_catch, 6) end end, " + " get(try_catch) end. ", 6), + ok. + + +eval_expr_5(doc) -> + ["(OTP-7933)"]; +eval_expr_5(suite) -> + []; +eval_expr_5(Config) when is_list(Config) -> + ?line {ok,Tokens ,_} = + erl_scan:string("if a+4 == 4 -> yes; true -> no end. "), + ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + ?line {value, no, []} = erl_eval:expr(Expr, [], none, none, none), + ?line no = erl_eval:expr(Expr, [], none, none, value), + try + erl_eval:expr(Expr, [], none, none, 4711), + ?line function_clause = should_never_reach_here + catch + error:function_clause -> + ok + end. + +%% Check the string in different contexts: as is; in fun; from compiled code. +check(F, String, Result) -> + check1(F, String, Result), + FunString = concat(["fun() -> ", no_final_dot(String), " end(). "]), + check1(F, FunString, Result), + CompileString = concat(["hd(lists:map(fun(_) -> ", no_final_dot(String), + " end, [foo])). "]), + check1(F, CompileString, Result). + +check1(F, String, Result) -> + Result = F(), + case catch parse_and_run(String) of + {value, Result, _} -> + ok; + Other -> + test_server:fail({eval, Other, Result}) + end. + +check(F, String, Result, BoundVars, LFH, EFH) -> + Result = F(), + case catch parse_and_run(String, LFH, EFH) of + {value, Result, Bs} -> + %% We just assume that Bs is an orddict... + Keys = orddict:fetch_keys(Bs), + case sort(BoundVars) == Keys of + true -> + ok; + false -> + test_server:fail({check, BoundVars, Keys}) + end, + ok; + Other -> + test_server:fail({check, Other, Result}) + end. + +error_check(String, Result) -> + case catch parse_and_run(String) of + {'EXIT', {Result,_}} -> + ok; + Other -> + test_server:fail({eval, Other, Result}) + end. + +error_check(String, Result, LFH, EFH) -> + case catch parse_and_run(String, LFH, EFH) of + {'EXIT', {Result,_}} -> + ok; + Other -> + test_server:fail({eval, Other, Result}) + end. + +eval_string(String) -> + {value, Result, _} = parse_and_run(String), + Result. + +parse_and_run(String) -> + {ok,Tokens,_} = erl_scan:string(String), + {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + erl_eval:expr(Expr, []). + +parse_and_run(String, LFH, EFH) -> + {ok,Tokens,_} = erl_scan:string(String), + {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + erl_eval:expr(Expr, [], LFH, EFH). + +no_final_dot(S) -> + case lists:reverse(S) of + " ." ++ R -> lists:reverse(R); + "." ++ R -> lists:reverse(R); + _ -> S + end. diff --git a/lib/debugger/test/exception_SUITE.erl b/lib/debugger/test/exception_SUITE.erl new file mode 100644 index 0000000000..a74a93fd22 --- /dev/null +++ b/lib/debugger/test/exception_SUITE.erl @@ -0,0 +1,256 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2010. 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(exception_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + badmatch/1,pending_errors/1,nil_arith/1]). + +-export([bad_guy/2]). + +-include("test_server.hrl"). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [badmatch, pending_errors, nil_arith]. + +-define(try_match(E), + catch ?MODULE:bar(), + {'EXIT', {{badmatch, nomatch}, _}} = (catch E = nomatch)). + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +badmatch(doc) -> "Test that deliberately bad matches are reported correctly."; +badmatch(suite) -> []; +badmatch(Config) when list(Config) -> + ?line ?try_match(a), + ?line ?try_match(42), + ?line ?try_match({a, b, c}), + ?line ?try_match([]), + ?line ?try_match(1.0), + ok. + +pending_errors(doc) -> + ["Test various exceptions, in the presence of a previous error suppressed ", + "in a guard."]; +pending_errors(suite) -> []; +pending_errors(Config) when list(Config) -> + ?line pending(e_badmatch, {badmatch, b}), + ?line pending(x, function_clause), + ?line pending(e_case, {case_clause, xxx}), + ?line pending(e_if, if_clause), + ?line pending(e_badarith, badarith), + ?line pending(e_undef, undef), + ?line pending(e_timeoutval, timeout_value), + ?line pending(e_badarg, badarg), + ?line pending(e_badarg_spawn, badarg), + ok. + +bad_guy(pe_badarith, Other) when Other+1 == 0 -> % badarith (suppressed) + ok; +bad_guy(pe_badarg, Other) when length(Other) > 0 -> % badarg (suppressed) + ok; +bad_guy(_, e_case) -> + case xxx of + ok -> ok + end; % case_clause +bad_guy(_, e_if) -> + if + a == b -> ok + end; % if_clause +bad_guy(_, e_badarith) -> + 1+b; % badarith +bad_guy(_, e_undef) -> + non_existing_module:foo(); % undef +bad_guy(_, e_timeoutval) -> + receive + after arne -> % timeout_value + ok + end; +bad_guy(_, e_badarg) -> + node(xxx); % badarg +bad_guy(_, e_badarg_spawn) -> + spawn({}, {}, {}); % badarg +bad_guy(_, e_badmatch) -> + a = b. % badmatch + +pending(Arg, Expected) -> + pending(pe_badarith, Arg, Expected), + pending(pe_badarg, Arg, Expected). + +pending(First, Second, Expected) -> + pending_catched(First, Second, Expected), + pending_exit_message([First, Second], Expected). + +pending_catched(First, Second, Expected) -> + ok = io:format("Catching bad_guy(~p, ~p)", [First, Second]), + case catch bad_guy(First, Second) of + {'EXIT', Reason} -> + pending(Reason, bad_guy, [First, Second], Expected); + Other -> + test_server:fail({not_exit, Other}) + end. + +pending_exit_message(Args, Expected) -> + ok = io:format("Trapping EXITs from spawn_link(~p, ~p, ~p)", + [?MODULE, bad_guy, Args]), + process_flag(trap_exit, true), + Pid = spawn_link(?MODULE, bad_guy, Args), + receive + {'EXIT', Pid, Reason} -> + pending(Reason, bad_guy, Args, Expected); + Other -> + test_server:fail({unexpected_message, Other}) + after 10000 -> + test_server:fail(timeout) + end, + process_flag(trap_exit, false). + +pending({badarg,[{erlang,Bif,BifArgs},{?MODULE,Func,Arity}|_]}, Func, Args, _Code) + when atom(Bif), list(BifArgs), length(Args) == Arity -> %Threaded code. + ok; +pending({badarg,[{erlang,Bif,BifArgs},{?MODULE,Func,Args}|_]}, Func, Args, _Code) + when atom(Bif), list(BifArgs) -> %From interpreted code. + ok; +pending({undef,[{non_existing_module,foo,[]}|_]}, _, _, _) -> + ok; +pending({function_clause,[{?MODULE,Func,Args}|_]}, Func, Args, _Code) -> + ok; +pending({Code,[{?MODULE,Func,Arity}|_]}, Func, Args, Code) when length(Args) == Arity -> %Threaded code + ok; +pending({Code,[{?MODULE,Func,Args}|_]}, Func, Args, Code) -> %From interpreted code. + ok; +pending(Reason, Func, Args, Code) -> + test_server:fail({bad_exit_reason,Reason,{Func,Args,Code}}). + +nil_arith(doc) -> + "Test that doing arithmetics on [] gives a badarith EXIT and not a crash."; +nil_arith(suite) -> + []; +nil_arith(Config) when list(Config) -> + ?line ba_plus_minus_times([], []), + + ?line ba_plus_minus_times([], 0), + ?line ba_plus_minus_times([], 42), + ?line ba_plus_minus_times([], 38724978123478923784), + ?line ba_plus_minus_times([], 38.72), + + ?line ba_plus_minus_times(0, []), + ?line ba_plus_minus_times(334, []), + ?line ba_plus_minus_times(387249797813478923784, []), + ?line ba_plus_minus_times(344.22, []), + + ?line ba_div_rem([], []), + + ?line ba_div_rem([], 0), + ?line ba_div_rem([], 1), + ?line ba_div_rem([], 42), + ?line ba_div_rem([], 38724978123478923784), + ?line ba_div_rem(344.22, []), + + ?line ba_div_rem(0, []), + ?line ba_div_rem(1, []), + ?line ba_div_rem(334, []), + ?line ba_div_rem(387249797813478923784, []), + ?line ba_div_rem(344.22, []), + + ?line ba_div_rem(344.22, 0.0), + ?line ba_div_rem(1, 0.0), + ?line ba_div_rem(392873498733971, 0.0), + + ?line ba_bop([], []), + ?line ba_bop(0, []), + ?line ba_bop(42, []), + ?line ba_bop(-42342742987343, []), + ?line ba_bop(238.342, []), + ?line ba_bop([], 0), + ?line ba_bop([], -243), + ?line ba_bop([], 243), + ?line ba_bop([], 2438724982478933), + ?line ba_bop([], 3987.37), + + ?line ba_bnot([]), + ?line ba_bnot(23.33), + + ?line ba_shift([], []), + ?line ba_shift([], 0), + ?line ba_shift([], 4), + ?line ba_shift([], -4), + ?line ba_shift([], 2343333333333), + ?line ba_shift([], -333333333), + ?line ba_shift([], 234.00), + ?line ba_shift(23, []), + ?line ba_shift(0, []), + ?line ba_shift(-3433443433433323, []), + ?line ba_shift(433443433433323, []), + ?line ba_shift(343.93, []), + ok. + +ba_plus_minus_times(A, B) -> + io:format("~p + ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A + B), + io:format("~p - ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A - B), + io:format("~p * ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A * B). + +ba_div_rem(A, B) -> + io:format("~p / ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A / B), + io:format("~p div ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A div B), + io:format("~p rem ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A rem B). + +ba_bop(A, B) -> + io:format("~p band ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A band B), + io:format("~p bor ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A bor B), + io:format("~p bxor ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A bxor B). + +ba_shift(A, B) -> + io:format("~p bsl ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A bsl B), + io:format("~p bsr ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A bsr B). + +ba_bnot(A) -> + io:format("bnot ~p", [A]), + {'EXIT', {badarith, _}} = (catch bnot A). diff --git a/lib/debugger/test/fun_SUITE.erl b/lib/debugger/test/fun_SUITE.erl new file mode 100644 index 0000000000..721048b6b6 --- /dev/null +++ b/lib/debugger/test/fun_SUITE.erl @@ -0,0 +1,233 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2010. 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(fun_SUITE). + +-export([all/1, + init_per_testcase/2,end_per_testcase/2, + init_all/1,finish_all/1, + good_call/1,bad_apply/1,bad_fun_call/1,badarity/1, + ext_badarity/1,otp_6061/1]). +-export([nothing/0]). + +-include("test_server.hrl"). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [good_call,bad_apply,bad_fun_call,badarity,ext_badarity,otp_6061]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +end_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +good_call(Config) when is_list(Config) -> + ?line F = fun() -> ok end, + ?line ok = F(), + ?line FF = fun ?MODULE:nothing/0, + ?line ok = FF(), + ok. + +bad_apply(doc) -> + "Test that the correct EXIT code is returned for all types of bad funs."; +bad_apply(suite) -> []; +bad_apply(Config) when is_list(Config) -> + ?line bad_apply_fc(42, [0]), + ?line bad_apply_fc(xx, [1]), + ?line bad_apply_fc({}, [2]), + ?line bad_apply_fc({1}, [3]), + ?line bad_apply_fc({1,2,3}, [4]), + ?line bad_apply_fc({1,2,3}, [5]), + ?line bad_apply_fc({1,2,3,4}, [6]), + ?line bad_apply_fc({1,2,3,4,5,6}, [7]), + ?line bad_apply_fc({1,2,3,4,5}, [8]), + ?line bad_apply_badarg({1,2}, [9]), + ok. + +bad_apply_fc(Fun, Args) -> + Res = (catch apply(Fun, Args)), + erlang:garbage_collect(), + erlang:yield(), + case Res of + {'EXIT',{{badfun,Fun},_Where}} -> + ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]); + Other -> + ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]), + ?t:fail({bad_result,Other}) + end. + +bad_apply_badarg(Fun, Args) -> + Res = (catch apply(Fun, Args)), + erlang:garbage_collect(), + erlang:yield(), + case Res of + {'EXIT',{{badfun,Fun},_Where}} -> + ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]); + Other -> + ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]), + ?t:fail({bad_result, Other}) + end. + +bad_fun_call(doc) -> + "Try directly calling bad funs."; +bad_fun_call(suite) -> []; +bad_fun_call(Config) when is_list(Config) -> + ?line bad_call_fc(42), + ?line bad_call_fc(xx), + ?line bad_call_fc({}), + ?line bad_call_fc({1}), + ?line bad_call_fc({1,2,3}), + ?line bad_call_fc({1,2,3}), + ?line bad_call_fc({1,2,3,4}), + ?line bad_call_fc({1,2,3,4,5,6}), + ?line bad_call_fc({1,2,3,4,5}), + ?line bad_call_fc({1,2}), + ok. + +bad_call_fc(Fun) -> + Args = [some,stupid,args], + Res = (catch Fun(Args)), + case Res of + {'EXIT',{{badfun,Fun},_Where}} -> + ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]); + Other -> + ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]), + ?t:fail({bad_result,Other}) + end. + +%% Call and apply valid external funs with wrong number of arguments. + +badarity(Config) when is_list(Config) -> + ?line Fun = fun() -> ok end, + ?line Stupid = {stupid,arguments}, + ?line Args = [some,{stupid,arguments},here], + + %% Simple call. + + ?line Res = (catch Fun(some, Stupid, here)), + erlang:garbage_collect(), + erlang:yield(), + case Res of + {'EXIT',{{badarity,{Fun,Args}},[_|_]}} -> + ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]); + _ -> + ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]), + ?line ?t:fail({bad_result,Res}) + end, + + %% Apply. + + ?line Res2 = (catch apply(Fun, Args)), + erlang:garbage_collect(), + erlang:yield(), + case Res2 of + {'EXIT',{{badarity,{Fun,Args}},[_|_]}} -> + ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]); + _ -> + ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]), + ?line ?t:fail({bad_result,Res2}) + end, + ok. + +%% Call and apply valid external funs with wrong number of arguments. + +ext_badarity(Config) when is_list(Config) -> + ?line Fun = fun ?MODULE:nothing/0, + ?line Stupid = {stupid,arguments}, + ?line Args = [some,{stupid,arguments},here], + + %% Simple call. + + ?line Res = (catch Fun(some, Stupid, here)), + erlang:garbage_collect(), + erlang:yield(), + case Res of + {'EXIT',{{badarity,{Fun,Args}},_}} -> + ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]); + _ -> + ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]), + ?line ?t:fail({bad_result,Res}) + end, + + %% Apply. + + ?line Res2 = (catch apply(Fun, Args)), + erlang:garbage_collect(), + erlang:yield(), + case Res2 of + {'EXIT',{{badarity,{Fun,Args}},_}} -> + ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]); + _ -> + ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]), + ?line ?t:fail({bad_result,Res2}) + end, + ok. + +nothing() -> + ok. + +otp_6061(suite) -> + []; +otp_6061(doc) -> + ["Test handling of fun expression referring to uninterpreted code"]; +otp_6061(Config) when is_list(Config) -> + + ?line OrigFlag = process_flag(trap_exit, true), + + ?line Self = self(), + ?line Pid = spawn_link(fun() -> test_otp_6061(Self) end), + + receive + working -> + ?line ok; + not_working -> + ?line ?t:fail(not_working); + {'EXIT', Pid, Reason} -> + ?line ?t:fail({crash, Reason}) + after + 5000 -> + ?line ?t:fail(timeout) + end, + + ?line process_flag(trap_exit, OrigFlag), + + ok. + +test_otp_6061(Starter) -> + Passes = [2], + PassesF = [fun() -> Starter ! not_working end, + fun() -> Starter ! working end, + fun() -> Starter ! not_working end], + lists:foreach(fun(P)->(lists:nth(P,PassesF))() end,Passes). diff --git a/lib/debugger/test/guard_SUITE.erl b/lib/debugger/test/guard_SUITE.erl new file mode 100644 index 0000000000..b5269989c8 --- /dev/null +++ b/lib/debugger/test/guard_SUITE.erl @@ -0,0 +1,1479 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2010. 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(guard_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + bad_arith/1,bad_tuple/1,test_heap_guards/1,guard_bifs/1, + type_tests/1,const_guard/1, + const_cond/1,basic_not/1,complex_not/1, + semicolon/1,complex_semicolon/1,comma/1, + or_guard/1,more_or_guards/1, + complex_or_guards/1,and_guard/1, + xor_guard/1,more_xor_guards/1, + old_guard_tests/1, + build_in_guard/1,gbif/1, + t_is_boolean/1,is_function_2/1, + tricky/1,rel_ops/1, + basic_andalso_orelse/1,traverse_dcd/1, + check_qlc_hrl/1]). + +-include("test_server.hrl"). + +-export([init/4]). +-import(lists, [member/2]). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [bad_arith,bad_tuple,test_heap_guards,guard_bifs,type_tests,const_guard, + const_cond,basic_not,complex_not, + semicolon,complex_semicolon, + comma,or_guard,more_or_guards, + complex_or_guards,and_guard, + xor_guard,more_xor_guards, + build_in_guard,old_guard_tests,gbif, + t_is_boolean,is_function_2,tricky,rel_ops, + basic_andalso_orelse,traverse_dcd,check_qlc_hrl]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + ?line Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +bad_arith(doc) -> "Test that a bad arithmetic operation in a guard works correctly."; +bad_arith(suite) -> []; +bad_arith(Config) when list(Config) -> + ?line 5 = bad_arith1(2, 3), + ?line 10 = bad_arith1(1, infinity), + ?line 10 = bad_arith1(infinity, 1), + ?line 42 = bad_div(24, 0), + ok. + +bad_arith1(T1, T2) when T1+T2 < 10 -> + T1+T2; +bad_arith1(_, _) -> + 10. + +bad_div(A, B) when A/B > 0 -> + A/B; +bad_div(A, B) when A div B > 0 -> + A div B; +bad_div(_A, _B) -> + 42. + +bad_tuple(doc) -> "Test that bad arguments to element/2 are handled correctly."; +bad_tuple(suite) -> []; +bad_tuple(Config) when list(Config) -> + ?line error = bad_tuple1(a), + ?line error = bad_tuple1({a, b}), + ?line x = bad_tuple1({x, b}), + ?line y = bad_tuple1({a, b, y}), + ok. + +bad_tuple1(T) when element(1, T) == x -> x; +bad_tuple1(T) when element(3, T) == y -> y; +bad_tuple1(_) -> error. + +test_heap_guards(doc) -> ""; +test_heap_guards(suite) -> []; +test_heap_guards(Config) when list(Config) -> + ?line process_flag(trap_exit, true), + ?line Tuple = {a, tuple, is, built, here, xxx}, + ?line List = [a, list, is, built, here], + + ?line try_fun(fun a_case/1, [Tuple], [Tuple]), + ?line try_fun(fun a_case/1, [List], [List, List]), + ?line try_fun(fun a_case/1, [a], [a]), + + ?line try_fun(fun an_if/1, [Tuple], [Tuple]), + ?line try_fun(fun an_if/1, [List], [List, List]), + ?line try_fun(fun an_if/1, [a], [a]), + + ?line try_fun(fun receive_test/1, [Tuple], [Tuple]), + ?line try_fun(fun receive_test/1, [List], [List, List]), + ?line try_fun(fun receive_test/1, [a], [a]), + ok. + +a_case(V) -> + case V of + T when T == {a, tuple, is, built, here, xxx} -> + [T]; + L when L == [a, list, is, built, here] -> + [L, L]; + a -> + [a] + end. + +an_if(V) -> + if + V == {a, tuple, is, built, here, xxx} -> + [V]; + V == [a, list, is, built, here] -> + [V, V]; + V == a -> + [a] + end. + +receive_test(V) -> + self() ! V, + a_receive(). + +a_receive() -> + receive + T when T == {a, tuple, is, built, here, xxx} -> + [T]; + L when L == [a, list, is, built, here] -> + [L, L]; + a -> + [a] + end. + +try_fun(Fun, Args, Result) -> + try_fun(16, Fun, Args, Result, []). + +try_fun(0, _, _, _, _) -> + ok; +try_fun(Iter, Fun, Args, Result, Filler) -> + Pid = spawn_link(?MODULE, init, [self(),Fun,Args,list_to_tuple(Filler)]), + receive + {'EXIT',Pid,{result,Result}} -> + ?line try_fun(Iter-1, Fun, Args, Result, [0|Filler]); + {'EXIT',Pid,{result,Other}} -> + ?line io:format("Expected ~p; got ~p~n", [Result,Other]), + ?line test_server:fail(); + Other -> + ?line test_server:fail({unexpected_message,Other}) + end. + +init(_ReplyTo, Fun, Args, Filler) -> + Result = {result, apply(Fun, Args)}, + dummy(Filler), + io:format("~p: result = ~p\n", [?LINE,Result]), + exit(Result). + +dummy(_) -> + ok. + +guard_bifs(doc) -> "Test all guard bifs with nasty (but legal arguments)."; +guard_bifs(suite) -> []; +guard_bifs(Config) when list(Config) -> + ?line Big = -237849247829874297658726487367328971246284736473821617265433, + ?line Float = 387924.874, + + %% Succeding use of guard bifs. + + ?line try_gbif('abs/1', Big, -Big), + ?line try_gbif('float/1', Big, float(Big)), + ?line try_gbif('trunc/1', Float, 387924.0), + ?line try_gbif('round/1', Float, 387925.0), + ?line try_gbif('length/1', [], 0), + + ?line try_gbif('length/1', [a], 1), + ?line try_gbif('length/1', [a, b], 2), + ?line try_gbif('length/1', lists:seq(0, 31), 32), + + ?line try_gbif('hd/1', [a], a), + ?line try_gbif('hd/1', [a, b], a), + + ?line try_gbif('tl/1', [a], []), + ?line try_gbif('tl/1', [a, b], [b]), + ?line try_gbif('tl/1', [a, b, c], [b, c]), + + ?line try_gbif('size/1', {}, 0), + ?line try_gbif('size/1', {a}, 1), + ?line try_gbif('size/1', {a, b}, 2), + ?line try_gbif('size/1', {a, b, c}, 3), + ?line try_gbif('size/1', list_to_binary([]), 0), + ?line try_gbif('size/1', list_to_binary([1]), 1), + ?line try_gbif('size/1', list_to_binary([1, 2]), 2), + ?line try_gbif('size/1', list_to_binary([1, 2, 3]), 3), + + ?line try_gbif('element/2', {x}, {1, x}), + ?line try_gbif('element/2', {x, y}, {1, x}), + ?line try_gbif('element/2', {x, y}, {2, y}), + + ?line try_gbif('self/0', 0, self()), + ?line try_gbif('node/0', 0, node()), + ?line try_gbif('node/1', self(), node()), + + %% Failing use of guard bifs. + + ?line try_fail_gbif('abs/1', Big, 1), + ?line try_fail_gbif('abs/1', [], 1), + + ?line try_fail_gbif('float/1', Big, 42), + ?line try_fail_gbif('float/1', [], 42), + + ?line try_fail_gbif('trunc/1', Float, 0.0), + ?line try_fail_gbif('trunc/1', [], 0.0), + + ?line try_fail_gbif('round/1', Float, 1.0), + ?line try_fail_gbif('round/1', [], a), + + ?line try_fail_gbif('length/1', [], 1), + ?line try_fail_gbif('length/1', [a], 0), + ?line try_fail_gbif('length/1', a, 0), + ?line try_fail_gbif('length/1', {a}, 0), + + ?line try_fail_gbif('hd/1', [], 0), + ?line try_fail_gbif('hd/1', [a], x), + ?line try_fail_gbif('hd/1', x, x), + + ?line try_fail_gbif('tl/1', [], 0), + ?line try_fail_gbif('tl/1', [a], x), + ?line try_fail_gbif('tl/1', x, x), + + ?line try_fail_gbif('size/1', {}, 1), + ?line try_fail_gbif('size/1', [], 0), + ?line try_fail_gbif('size/1', [a], 1), + + ?line try_fail_gbif('element/2', {}, {1, x}), + ?line try_fail_gbif('element/2', {x}, {1, y}), + ?line try_fail_gbif('element/2', [], {1, z}), + + ?line try_fail_gbif('self/0', 0, list_to_pid("<0.0.0>")), + ?line try_fail_gbif('node/0', 0, xxxx), + ?line try_fail_gbif('node/1', self(), xxx), + ?line try_fail_gbif('node/1', yyy, xxx), + ok. + +try_gbif(Id, X, Y) -> + case guard_bif(Id, X, Y) of + {Id, X, Y} -> + io:format("guard_bif(~p, ~p, ~p) -- ok", [Id, X, Y]); + Other -> + ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n", + [Id, X, Y, Other]), + ?line test_server:fail() + end. + +try_fail_gbif(Id, X, Y) -> + case catch guard_bif(Id, X, Y) of + {'EXIT', {function_clause,{?MODULE,guard_bif,[Id,X,Y]}}} -> %Jam + io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]); + {'EXIT', {function_clause,[{?MODULE,guard_bif,[Id,X,Y]}|_]}} -> %Beam + io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]); + Other -> + ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n", + [Id, X, Y, Other]), + ?line test_server:fail() + end. + +guard_bif('abs/1', X, Y) when abs(X) == Y -> + {'abs/1', X, Y}; +guard_bif('float/1', X, Y) when float(X) == Y -> + {'float/1', X, Y}; +guard_bif('trunc/1', X, Y) when trunc(X) == Y -> + {'trunc/1', X, Y}; +guard_bif('round/1', X, Y) when round(X) == Y -> + {'round/1', X, Y}; +guard_bif('length/1', X, Y) when length(X) == Y -> + {'length/1', X, Y}; +guard_bif('hd/1', X, Y) when hd(X) == Y -> + {'hd/1', X, Y}; +guard_bif('tl/1', X, Y) when tl(X) == Y -> + {'tl/1', X, Y}; +guard_bif('size/1', X, Y) when size(X) == Y -> + {'size/1', X, Y}; +guard_bif('element/2', X, {Pos, Expected}) when element(Pos, X) == Expected -> + {'element/2', X, {Pos, Expected}}; +guard_bif('self/0', X, Y) when self() == Y -> + {'self/0', X, Y}; +guard_bif('node/0', X, Y) when node() == Y -> + {'node/0', X, Y}; +guard_bif('node/1', X, Y) when node(X) == Y -> + {'node/1', X, Y}. + +type_tests(doc) -> "Test the type tests."; +type_tests(suite) -> []; +type_tests(Config) when list(Config) -> + ?line Types = all_types(), + ?line Tests = type_test_desc(), + ?line put(errors, 0), + ?line put(violations, 0), + ?line type_tests(Tests, Types), + ?line case {get(errors), get(violations)} of + {0, 0} -> + ok; + {0, N} -> + {comment, integer_to_list(N) ++ " standard violation(s)"}; + {Errors, Violations} -> + io:format("~p sub test(s) failed, ~p violation(s)", + [Errors, Violations]), + ?line test_server:fail() + end. + +type_tests([{Test, AllowedTypes}| T], AllTypes) -> + type_tests(Test, AllTypes, AllowedTypes), + type_tests(T, AllTypes); +type_tests([], _) -> + ok. + +type_tests(Test, [Type|T], Allowed) -> + {TypeTag, Value} = Type, + case member(TypeTag, Allowed) of + true -> + case catch type_test(Test, Value) of + Test -> + ok; + _Other -> + io:format("Test ~p(~p) failed", [Test, Value]), + put(errors, get(errors) + 1) + end; + false -> + case catch type_test(Test, Value) of + {'EXIT', {function_clause, {?MODULE, type_test, [Test, Value]}}} -> + ok; + {'EXIT', {function_clause,[{?MODULE,type_test,[Test,Value]}|_]}} -> + ok; + {'EXIT',Other} -> + ?line test_server:fail({unexpected_error_reason,Other}); + tuple when function(Value) -> + io:format("Standard violation: Test ~p(~p) should fail", + [Test, Value]), + put(violations, get(violations) + 1); + _Other -> + io:format("Test ~p(~p) succeeded (should fail)", [Test, Value]), + put(errors, get(errors) + 1) + end + end, + type_tests(Test, T, Allowed); +type_tests(_, [], _) -> + ok. + +all_types() -> + [{small, 42}, + {big, 392742928742947293873938792874019287447829874290742}, + {float, 3.14156}, + {nil, []}, + {cons, [a]}, + {tuple, {a, b}}, + {atom, xxxx}, + {ref, make_ref()}, + {pid, self()}, + {port, open_port({spawn, efile}, [])}, + {function, fun(X) -> X+1, "" end}, + {binary, list_to_binary([])}]. + +type_test_desc() -> + [{integer, [small, big]}, + {float, [float]}, + {number, [small, big, float]}, + {atom, [atom]}, + {list, [cons, nil]}, + {nonempty_list, [cons]}, + {nil, [nil]}, + {tuple, [tuple]}, + {pid, [pid]}, + {port, [port]}, + {reference, [ref]}, + {function, [function]}]. + +type_test(integer, X) when integer(X) -> + integer; +type_test(float, X) when float(X) -> + float; +type_test(number, X) when number(X) -> + number; +type_test(atom, X) when atom(X) -> + atom; +type_test(list, X) when list(X) -> + list; +type_test(nonempty_list, [_]) -> + nonempty_list; +type_test(nil, []) -> + nil; +type_test(tuple, X) when tuple(X) -> + tuple; +type_test(pid, X) when pid(X) -> + pid; +type_test(reference, X) when reference(X) -> + reference; +type_test(port, X) when port(X) -> + port; +type_test(binary, X) when binary(X) -> + binary; +type_test(function, X) when function(X) -> + function. + +const_guard(Config) when is_list(Config) -> + ?line if + (0 == 0) and ((0 == 0) or (0 == 0)) -> + ok + end. + + +const_cond(Config) when is_list(Config) -> + ?line ok = const_cond({}, 0), + ?line ok = const_cond({a}, 1), + ?line error = const_cond({a,b}, 3), + ?line error = const_cond({a}, 0), + ?line error = const_cond({a,b}, 1), + ok. + +const_cond(T, Sz) -> + case T of + _X when false -> never; + _X when tuple(T), eq == eq, size(T) == Sz -> ok; + _X when tuple(T), eq == leq, size(T) =< Sz -> ok; + _X -> error + end. + +basic_not(Config) when is_list(Config) -> + True = id(true), + False = id(false), + Glurf = id(glurf), + A = id(5), + B = id(37.5), + C = id(-1), + D = id(5), + ATuple = {False,True,Glurf}, + + ?line check(fun() -> if not false -> ok; true -> error end end, ok), + ?line check(fun() -> if not true -> ok; true -> error end end, error), + ?line check(fun() -> if not False -> ok; true -> error end end, ok), + ?line check(fun() -> if not True -> ok; true -> error end end, error), + + ?line check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt), + ?line check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt), + ?line check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq), + + ?line check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge; + not (7 == 453) -> ne; true -> eq end end, le), + ?line check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge; + not (7 == -8) -> ne; true -> eq end end, ge), + ?line check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge; + not (7 == 7) -> ne; true -> eq end end, le), + + ?line check(fun() -> if not (A > B) -> le; not (A < B) -> ge; + not (A == B) -> ne; true -> eq end end, le), + ?line check(fun() -> if not (A > C) -> le; not (A < C) -> ge; + not (A == C) -> ne; true -> eq end end, ge), + ?line check(fun() -> if not (A > D) -> le; not (A < D) -> ge; + not (A == D) -> ne; true -> eq end end, le), + + ?line check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok), + ?line check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error), + ?line check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error), + + ?line check(fun() -> if not glurf -> ok; true -> error end end, error), + ?line check(fun() -> if not Glurf -> ok; true -> error end end, error), + + ok. + +complex_not(Config) when is_list(Config) -> + ATuple = id({false,true,gurka}), + ?line check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok), + ?line check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error), + + ?line check(fun() -> if not(element(3, ATuple) == gurka) -> ok; + true -> error end end, error), + ?line check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok; + true -> error end end, ok), + + ?line check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok; + true -> error end end, ok), + ?line check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok; + true -> error end end, error), + + ?line check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok; + true -> error end end, error), + + %% orelse + ?line check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok; + true -> error end end, error), + + ok. + +semicolon(Config) when is_list(Config) -> + + %% True/false combined using ';' (literal atoms). + + ?line check(fun() -> if true; false -> ok end end, ok), + ?line check(fun() -> if false; true -> ok end end, ok), + ?line check(fun() -> if true; true -> ok end end, ok), + ?line check(fun() -> if false; false -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if false; false -> ok end), + exit + end, exit), + + %% True/false combined used ';'. + + True = id(true), + False = id(false), + + ?line check(fun() -> if True; False -> ok end end, ok), + ?line check(fun() -> if False; True -> ok end end, ok), + ?line check(fun() -> if True; True -> ok end end, ok), + ?line check(fun() -> if False; False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if False; False -> ok end), + exit + end, exit), + + %% Combine true/false with a non-boolean value. + Glurf = id(glurf), + + + ?line check(fun() -> if True; Glurf -> ok end end, ok), + ?line check(fun() -> if Glurf; True -> ok end end, ok), + ?line check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if False; Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf; False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end), + exit + end, exit), + + %% Combine true/false with errors. + + ATuple = id({false,true,gurka}), + + ?line check(fun() -> if True; element(42, ATuple) -> ok end end, ok), + ?line check(fun() -> if element(42, ATuple); True -> ok end end, ok), + ?line check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> if False; element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> if element(42, ATuple); + False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if element(42, ATuple); + element(42, ATuple) -> ok end), + exit + end, exit), + + ok. + +complex_semicolon(Config) when is_list(Config) -> + ?line ok = csemi1(int, {blurf}), + ?line ok = csemi1(string, {blurf}), + ?line ok = csemi1(float, [a]), + ?line error = csemi1(35, 42), + + %% 2 + ?line ok = csemi2({}, {a,b,c}), + ?line ok = csemi2({1,3.5}, {a,b,c}), + ?line ok = csemi2(dum, {a,b,c}), + + ?line ok = csemi2({45,-19.3}, {}), + ?line ok = csemi2({45,-19.3}, {dum}), + ?line ok = csemi2({45,-19.3}, {dum,dum}), + + ?line error = csemi2({45}, {dum}), + ?line error = csemi2([], {dum}), + ?line error = csemi2({dum}, []), + ?line error = csemi2([], []), + + %% 3 + ?line csemi3(fun csemi3a/4), + ?line csemi3(fun csemi3b/4), + ?line csemi3(fun csemi3c/4), + + %% 4 + ?line csemi4(fun csemi4a/4), + ?line csemi4(fun csemi4b/4), + ?line csemi4(fun csemi4c/4), + ?line csemi4(fun csemi4d/4), + + %% 4, 'orelse' instead of 'or' + ?line csemi4_orelse(fun csemi4_orelse_a/4), + ?line csemi4_orelse(fun csemi4_orelse_b/4), + ?line csemi4_orelse(fun csemi4_orelse_c/4), + ?line csemi4_orelse(fun csemi4_orelse_d/4), + + ok. + +csemi1(Type, Val) when is_list(Val), Type == float; + Type == int; Type == string -> ok; +csemi1(_, _) -> error. + +csemi2(A, B) when size(A) > 1; size(B) > 2 -> ok; +csemi2(_, _) -> error. + +csemi3(Csemi3) -> + ok = Csemi3({}, {a,b,c}, [0], [0]), + ok = Csemi3({1,3.5}, {a,b,c}, -1, -1), + ok = Csemi3(dum, {a,b,c}, 0.0, 0.0), + ok = Csemi3(dum, {c}, b, a), + ok = Csemi3(dum, <<1,2,3>>, 0.0, 0.0), + ok = Csemi3(<<3.5/float>>, {a,b,c}, -1, -1), + + ok = Csemi3({45,-19.3}, {}, [], []), + ok = Csemi3({45,-19.3}, {dum}, 42, 42), + ok = Csemi3({45,-19.3}, {dum,dum}, 33, 33), + + ok = Csemi3({45}, {dum}, 1.0, 0), + ok = Csemi3([a], {dum}, 1.0, 0), + ok = Csemi3({dum}, [], 1.0, 0), + ok = Csemi3([], [], 1.0, 0), + ok = Csemi3(blurf, {dum}, 1.0, 0), + ok = Csemi3({a}, blurf, 1.0, 0), + ok = Csemi3([a], [dum], 1.0, 0), + ok = Csemi3({dum}, [], 1.0, 0), + ok = Csemi3([], [], 1.0, 0), + + error = Csemi3({45}, {dum}, 0, 0), + error = Csemi3([a], {dum}, 0, 0), + error = Csemi3({dum}, [], 0, 0), + error = Csemi3([], [], 0, 0), + ok. + +csemi3a(A, B, X, Y) when X > Y; size(A) > 1; size(B) > 2 -> ok; +csemi3a(_, _, _, _) -> error. + +csemi3b(A, B, X, Y) when size(A) > 1; X > Y; size(B) > 2 -> ok; +csemi3b(_, _, _, _) -> error. + +csemi3c(A, B, X, Y) when size(A) > 1; size(B) > 2; X > Y -> ok; +csemi3c(_, _, _, _) -> error. + + +csemi4(Test) -> + ok = Test({a,b}, 2, {c,d}, 2), + ok = Test({1,2,3}, 0, [], 0), + ok = Test({}, 2, blurf, 0), + ok = Test({}, 2, {1}, 2), + + error = Test([], 4, {}, 0), + error = Test({}, 0, [a,b], 4), + error = Test({}, 0, [a,b], 0), + error = Test([], 0, {}, 0), + error = Test({}, 0, {}, 0), + + ok. + +csemi4a(A, X, B, Y) when (size(A) > 1) or (X > 1); + (size(B) > 1) or (Y > 1) -> ok; +csemi4a(_, _, _, _) -> error. + +csemi4b(A, X, B, Y) when (X > 1) or (size(A) > 1); + (size(B) > 1) or (Y > 1) -> ok; +csemi4b(_, _, _, _) -> error. + +csemi4c(A, X, B, Y) when (size(A) > 1) or (X > 1); + (Y > 1) or (size(B) > 1) -> ok; +csemi4c(_, _, _, _) -> error. + +csemi4d(A, X, B, Y) when (X > 1) or (size(A) > 1); + (Y > 1) or (size(B) > 1) -> ok; +csemi4d(_, _, _, _) -> error. + + +csemi4_orelse(Test) -> + ok = Test({a,b}, 2, {c,d}, 2), + ok = Test({1,2,3}, 0, [], 0), + ok = Test({}, 2, blurf, 0), + ok = Test({}, 2, {1}, 2), + + ?line error = Test([], 1, {}, 0), + + ok. + +csemi4_orelse_a(A, X, B, Y) when (size(A) > 1) orelse (X > 1); + (size(B) > 1) orelse (Y > 1) -> ok; +csemi4_orelse_a(_, _, _, _) -> error. + +csemi4_orelse_b(A, X, B, Y) when (X > 1) orelse (size(A) > 1); + (size(B) > 1) orelse (Y > 1) -> ok; +csemi4_orelse_b(_, _, _, _) -> error. + +csemi4_orelse_c(A, X, B, Y) when (size(A) > 1) orelse (X > 1); + (Y > 1) orelse (size(B) > 1) -> ok; +csemi4_orelse_c(_, _, _, _) -> error. + +csemi4_orelse_d(A, X, B, Y) when (X > 1) or (size(A) > 1); + (Y > 1) or (size(B) > 1) -> ok; +csemi4_orelse_d(_, _, _, _) -> error. + + +comma(Config) when is_list(Config) -> + + %% ',' combinations of literal true/false. + + ?line check(fun() -> if true, false -> ok; true -> error end end, error), + ?line check(fun() -> if false, true -> ok; true -> error end end, error), + ?line check(fun() -> if true, true -> ok end end, ok), + ?line check(fun() -> if false, false -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if true, false -> ok; + false, true -> ok; + false, false -> ok + end), + exit + end, exit), + + %% ',' combinations of true/false in variables. + + True = id(true), + False = id(false), + + ?line check(fun() -> if True, False -> ok; true -> error end end, error), + ?line check(fun() -> if False, True -> ok; true -> error end end, error), + ?line check(fun() -> if True, True -> ok end end, ok), + ?line check(fun() -> if False, False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True, False -> ok; + False, True -> ok; + False, False -> ok + end), + exit + end, exit), + + %% ',' combinations of true/false, and non-boolean in variables. + + Glurf = id(glurf), + + ?line check(fun() -> if True, Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf, True -> ok; true -> error end end, error), + ?line check(fun() -> if True, True -> ok end end, ok), + ?line check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True, Glurf -> ok; + Glurf, True -> ok; + Glurf, Glurf -> ok + end), + exit + end, exit), + + %% ',' combinations of true/false with errors. + ATuple = id({a,b,c}), + + ?line check(fun() -> if True, element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> if element(42, ATuple), True -> ok; + true -> error end end, error), + ?line check(fun() -> if True, True -> ok end end, ok), + ?line check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True, element(42, ATuple) -> ok; + element(42, ATuple), True -> ok; + element(42, ATuple), element(42, ATuple) -> ok + end), + exit + end, exit), + + ok. + +or_guard(Config) when is_list(Config) -> + True = id(true), + False = id(false), + Glurf = id(glurf), + + %% 'or' combinations of literal true/false. + ?line check(fun() -> if true or false -> ok end end, ok), + ?line check(fun() -> if false or true -> ok end end, ok), + ?line check(fun() -> if true or true -> ok end end, ok), + ?line check(fun() -> if false or false -> ok; true -> error end end, error), + + ?line check(fun() -> if glurf or true -> ok; true -> error end end, error), + ?line check(fun() -> if true or glurf -> ok; true -> error end end, error), + ?line check(fun() -> if glurf or glurf -> ok; true -> error end end, error), + + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if false or false -> ok end), + exit + end, exit), + + + %% 'or' combinations using variables containing true/false. + ?line check(fun() -> if True or False -> ok end end, ok), + ?line check(fun() -> if False or True -> ok end end, ok), + ?line check(fun() -> if True or True -> ok end end, ok), + ?line check(fun() -> if False or False -> ok; true -> error end end, error), + + ?line check(fun() -> if True or Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf or True -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error), + + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if False or False -> ok end), + exit + end, exit), + + ok. + +more_or_guards(Config) when is_list(Config) -> + True = id(true), + False = id(false), + ATuple = id({false,true,gurka}), + + ?line check(fun() -> + if element(42, ATuple) or False -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if False or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(18, ATuple) or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if True or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(42, ATuple) or True -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(1, ATuple) or element(42, ATuple) or True -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(1, ATuple) or True or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if + (<<False:8>> == <<0>>) or element(2, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if + element(2, ATuple) or (<<True:8>> == <<1>>) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(2, ATuple) or element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if + element(1, ATuple) or + element(2, ATuple) or + element(19, ATuple) -> ok; + true -> error end + end, error), + ok. + +complex_or_guards(Config) when is_list(Config) -> + %% complex_or_1/2 + ?line ok = complex_or_1({a,b,c,d}, {1,2,3}), + ?line ok = complex_or_1({a,b,c,d}, {1}), + ?line ok = complex_or_1({a}, {1,2,3}), + ?line error = complex_or_1({a}, {1}), + + ?line error = complex_or_1(1, 2), + ?line error = complex_or_1([], {a,b,c,d}), + ?line error = complex_or_1({a,b,c,d}, []), + + + %% complex_or_2/1 + ?line ok = complex_or_2({true,{}}), + ?line ok = complex_or_2({false,{a}}), + ?line ok = complex_or_2({false,{a,b,c}}), + ?line ok = complex_or_2({true,{a,b,c,d}}), + + ?line error = complex_or_2({blurf,{a,b,c}}), + + ?line error = complex_or_2({true}), + ?line error = complex_or_2({true,no_tuple}), + ?line error = complex_or_2({true,[]}), + + %% complex_or_3/2 + ?line ok = complex_or_3({true}, {}), + ?line ok = complex_or_3({false}, {a}), + ?line ok = complex_or_3({false}, {a,b,c}), + ?line ok = complex_or_3({true}, {a,b,c,d}), + ?line ok = complex_or_3({false}, <<1,2,3>>), + ?line ok = complex_or_3({true}, <<1,2,3,4>>), + + ?line error = complex_or_3(blurf, {a,b,c}), + + ?line error = complex_or_3({false}, <<1,2,3,4>>), + ?line error = complex_or_3([], <<1,2>>), + ?line error = complex_or_3({true}, 45), + ?line error = complex_or_3(<<>>, <<>>), + + %% complex_or_4/2 + ?line ok = complex_or_4(<<1,2,3>>, {true}), + ?line ok = complex_or_4(<<1,2,3>>, {false}), + ?line ok = complex_or_4(<<1,2,3>>, {true}), + ?line ok = complex_or_4({1,2,3}, {true}), + ?line error = complex_or_4({1,2,3,4}, {false}), + + ?line error = complex_or_4(<<1,2,3,4>>, []), + ?line error = complex_or_4([], {true}), + + %% complex_or_5/2 + ?line ok = complex_or_5(<<1>>, {false}), + ?line ok = complex_or_5(<<1,2,3>>, {true}), + ?line ok = complex_or_5(<<1,2,3,4>>, {false}), + ?line ok = complex_or_5({1,2,3}, {false}), + ?line ok = complex_or_5({1,2,3,4}, {false}), + + ?line error = complex_or_5(blurf, {false}), + ?line error = complex_or_5(<<1>>, klarf), + ?line error = complex_or_5(blurf, klarf), + + %% complex_or_6/2 + ?line ok = complex_or_6({true,true}, {1,2,3,4}), + ?line ok = complex_or_6({true,true}, <<1,2,3,4>>), + ?line ok = complex_or_6({false,false}, <<1,2,3,4>>), + ?line ok = complex_or_6({false,true}, <<1>>), + ?line ok = complex_or_6({true,false}, {1}), + ?line ok = complex_or_6({true,true}, {1}), + + ?line error = complex_or_6({false,false}, {1}), + + ?line error = complex_or_6({true}, {1,2,3,4}), + ?line error = complex_or_6({}, {1,2,3,4}), + ?line error = complex_or_6([], {1,2,3,4}), + ?line error = complex_or_6([], {1,2,3,4}), + ?line error = complex_or_6({true,false}, klurf), + + ok. + +complex_or_1(A, B) -> + if + ((3 < size(A)) and (size(A) < 9)) or + ((2 < size(B)) and (size(B) < 7)) -> ok; + true -> error + end. + +complex_or_2(Tuple) -> + if + element(1, Tuple) or not (size(element(2, Tuple)) > 3) -> ok; + true -> error + end. + +complex_or_3(A, B) -> + if + not (size(B) > 3) or element(1, A) -> ok; + true -> error + end. + +complex_or_4(A, B) -> + if + not (is_tuple(A) and (size(A) > 3)) or element(1, B) -> ok; + true -> error + end. + +complex_or_5(A, B) -> + if + not (is_tuple(A) or (size(A) > 3)) or not element(1, B) -> ok; + true -> error + end. + +complex_or_6(A, B) -> + if + not (not element(1, A) and not element(2, A)) or + not (not (size(B) > 3)) -> ok; + true -> error + end. + +and_guard(Config) when is_list(Config) -> + + %% 'and' combinations of literal true/false. + + ?line check(fun() -> if true and false -> ok; true -> error end end, error), + ?line check(fun() -> if false and true -> ok; true -> error end end, error), + ?line check(fun() -> if true and true -> ok end end, ok), + ?line check(fun() -> if false and false -> ok; true -> error end end, error), + + ?line check(fun() -> if glurf and true -> ok; true -> error end end, error), + ?line check(fun() -> if true and glurf -> ok; true -> error end end, error), + ?line check(fun() -> if glurf and glurf -> ok; true -> error end end, error), + + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if true and false -> ok; + false and true -> ok; + false and false -> ok + end), + exit + end, exit), + + %% 'and' combinations of true/false in variables. + + True = id(true), + False = id(false), + + ?line check(fun() -> if True and False -> ok; true -> error end end, error), + ?line check(fun() -> if False and True -> ok; true -> error end end, error), + ?line check(fun() -> if True and True -> ok end end, ok), + ?line check(fun() -> if False and False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True and False -> ok; + False and True -> ok; + False and False -> ok + end), + exit + end, exit), + + %% 'and' combinations of true/false and a non-boolean in variables. + + Glurf = id(glurf), + + ?line check(fun() -> if True and Glurf -> ok; true -> error end end, error), + ?line check(fun() -> if Glurf and True -> ok; true -> error end end, error), + ?line check(fun() -> if True and True -> ok end end, ok), + ?line check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True and Glurf -> ok; + Glurf and True -> ok; + Glurf and Glurf -> ok + end), + exit + end, exit), + + %% 'and' combinations of true/false with errors. + ATuple = id({a,b,c}), + + ?line check(fun() -> if True and element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> if element(42, ATuple) and True -> ok; + true -> error end end, error), + ?line check(fun() -> if True and True -> ok end end, ok), + ?line check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok; + true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True and element(42, ATuple) -> ok; + element(42, ATuple) and True -> ok; + element(42, ATuple) and element(42, ATuple) -> ok + end), + exit + end, exit), + + ?line ok = relprod({'Set',a,b}, {'Set',a,b}), + + ok. + +relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set'), (erlang:size(R2) =:= 3) and (erlang:element(1,R2) =:= 'Set') -> + ok. + + +xor_guard(Config) when is_list(Config) -> + + %% 'xor' combinations of literal true/false. + ?line check(fun() -> if true xor false -> ok end end, ok), + ?line check(fun() -> if false xor true -> ok end end, ok), + ?line check(fun() -> if true xor true -> ok; true -> error end end, error), + ?line check(fun() -> if false xor false -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end), + exit + end, exit), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end), + exit + end, exit), + + + %% 'xor' combinations using variables containing true/false. + + True = id(true), + False = id(false), + + ?line check(fun() -> if True xor False -> ok end end, ok), + ?line check(fun() -> if False xor True -> ok end end, ok), + ?line check(fun() -> if True xor True -> ok; true -> error end end, error), + ?line check(fun() -> if False xor False -> ok; true -> error end end, error), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end), + exit + end, exit), + ?line check(fun() -> + {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end), + exit + end, exit), + + ok. + +more_xor_guards(Config) when is_list(Config) -> + True = id(true), + False = id(false), + ATuple = id({false,true,gurka}), + + ?line check(fun() -> + if element(42, ATuple) xor False -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if False xor element(42, ATuple) xor False -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(18, ATuple) xor element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if True xor element(42, ATuple) -> ok; + true -> error end + end, error), + + ?line check(fun() -> + if element(42, ATuple) xor True -> ok; + true -> error end + end, error), + ok. + +build_in_guard(Config) when is_list(Config) -> + SubBin = <<5.0/float>>, + ?line B = <<1,SubBin/binary,3.5/float>>, + ?line if + B =:= <<1,SubBin/binary,3.5/float>> -> ok + end. + +old_guard_tests(Config) when list(Config) -> + %% Check that all the old guard tests are still recognized. + ?line list = og(Config), + ?line atom = og(an_atom), + ?line binary = og(<<1,2>>), + ?line float = og(3.14), + ?line integer = og(43), + ?line a_function = og(fun() -> ok end), + ?line pid = og(self()), + ?line reference = og(make_ref()), + ?line tuple = og({}), + + ?line number = on(45.333), + ?line number = on(-19), + ok. + +og(V) when atom(V) -> atom; +og(V) when binary(V) -> binary; +og(V) when float(V) -> float; +og(V) when integer(V) -> integer; +og(V) when function(V) -> a_function; +og(V) when list(V) -> list; +og(V) when pid(V) -> pid; +og(V) when port(V) -> port; +og(V) when reference(V) -> reference; +og(V) when tuple(V) -> tuple; +og(_) -> what. + +on(V) when number(V) -> number; +on(_) -> not_number. + +gbif(Config) when is_list(Config) -> + ?line error = gbif_1(1, {false,true}), + ?line ok = gbif_1(2, {false,true}), + ok. + +gbif_1(P, T) when element(P, T) -> ok; +gbif_1(_, _) -> error. + + +t_is_boolean(Config) when is_list(Config) -> + ?line true = is_boolean(true), + ?line true = is_boolean(false), + ?line true = is_boolean(id(true)), + ?line true = is_boolean(id(false)), + + ?line false = is_boolean(glurf), + ?line false = is_boolean(id(glurf)), + + ?line false = is_boolean([]), + ?line false = is_boolean(id([])), + ?line false = is_boolean(42), + ?line false = is_boolean(id(-42)), + + ?line false = is_boolean(math:pi()), + ?line false = is_boolean(384793478934378924978439789873478934897), + + ?line false = is_boolean(id(self())), + ?line false = is_boolean(id({x,y,z})), + ?line false = is_boolean(id([a,b,c])), + ?line false = is_boolean(id(make_ref())), + ?line false = is_boolean(id(<<1,2,3>>)), + + ?line ok = bool(true), + ?line ok = bool(false), + ?line ok = bool(id(true)), + ?line ok = bool(id(false)), + + ?line error = bool(glurf), + ?line error = bool(id(glurf)), + + ?line error = bool([]), + ?line error = bool(id([])), + ?line error = bool(42), + ?line error = bool(id(-42)), + + ?line error = bool(math:pi()), + ?line error = bool(384793478934378924978439789873478934897), + + ?line error = bool(id(self())), + ?line error = bool(id({x,y,z})), + ?line error = bool(id([a,b,c])), + ?line error = bool(id(make_ref())), + ?line error = bool(id(<<1,2,3>>)), + + ok. + +bool(X) when is_boolean(X) -> ok; +bool(_) -> error. + + +is_function_2(Config) when is_list(Config) -> + true = is_function(id(fun ?MODULE:all/1), 1), + true = is_function(id(fun() -> ok end), 0), + false = is_function(id(fun ?MODULE:all/1), 0), + false = is_function(id(fun() -> ok end), 1), + + F = fun(_) -> ok end, + if + is_function(F, 1) -> ok + end. + +tricky(Config) when is_list(Config) -> + ?line not_ok = tricky_1(1, 2), + ?line not_ok = tricky_1(1, blurf), + ?line not_ok = tricky_1(foo, 2), + ?line not_ok = tricky_1(a, b), + + ?line false = rb(100000, [1], 42), + ?line true = rb(100000, [], 42), + ?line true = rb(555, [a,b,c], 19), + ok. + +tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok; +tricky_1(_, _) -> not_ok. + +%% From dets_v9:read_buckets/11, simplified. + +rb(Size, ToRead, SoFar) when SoFar + Size < 81920; ToRead == [] -> true; +rb(_, _, _) -> false. + + +-define(T(Op,A,B), + ok = if A Op B -> ok; true -> error end, + ok = if not (A Op B) -> error; true -> ok end, + (fun(X, Y, True, False) -> + ok = if X Op Y -> ok; true -> error end, + ok = if False; X Op Y; False -> ok; true -> error end, + ok = if X Op Y, True -> ok; true -> error end, + ok = if not (X Op Y) -> error; true -> ok end, + ok = if False; not (X Op Y); False -> error; true -> ok end + end)(id(A), id(B), id(true), id(false))). + +-define(F(Op,A,B), + ok = if A Op B -> error; true -> ok end, + ok = if not (A Op B) -> ok; true -> error end, + (fun(X, Y, True, False) -> + ok = if X Op Y -> error; true -> ok end, + ok = if False; X Op Y; False -> error; true -> ok end, + ok = if not (X Op Y); False -> ok; true -> error end, + ok = if not (X Op Y), True -> ok; true -> error end + end)(id(A), id(B), id(true), id(false))). + + +rel_ops(Config) when is_list(Config) -> + ?line ?T(=/=, 1, 1.0), + ?line ?F(=/=, 2, 2), + ?line ?F(=/=, {a}, {a}), + + ?line ?F(/=, a, a), + ?line ?F(/=, 0, 0.0), + ?line ?T(/=, 0, 1), + ?line ?F(/=, {a}, {a}), + + ?line ?T(==, 1, 1.0), + ?line ?F(==, a, {}), + + ?line ?F(=:=, 1, 1.0), + ?line ?T(=:=, 42.0, 42.0), + + ?line ?F(>, a, b), + ?line ?T(>, 42, 1.0), + ?line ?F(>, 42, 42.0), + + ?line ?T(<, a, b), + ?line ?F(<, 42, 1.0), + ?line ?F(<, 42, 42.0), + + ?line ?T(=<, 1.5, 5), + ?line ?F(=<, -9, -100.344), + ?line ?T(=<, 42, 42.0), + + ?line ?T(>=, 42, 42.0), + ?line ?F(>=, a, b), + ?line ?T(>=, 1.0, 0), + + ok. + +-undef(TestOp). + +basic_andalso_orelse(Config) when is_list(Config) -> + ?line T = id({type,integers,23,42}), + ?line 65 = if + ((element(1, T) =:= type) andalso (size(T) =:= 4) andalso + element(2, T) == integers) -> + element(3, T) + element(4, T); + true -> error + end, + ?line 65 = case [] of + [] when ((element(1, T) =:= type) andalso (size(T) =:= 4) andalso + element(2, T) == integers) -> + element(3, T) + element(4, T) + end, + + ?line 42 = basic_rt({type,integers,40,2}), + ?line 5.0 = basic_rt({vector,{3.0,4.0}}), + ?line 20 = basic_rt(['+',3,7]), + ?line {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}), + ?line 12 = basic_rt({klurf,4}), + + ?line error = basic_rt({type,integers,40,2,3}), + ?line error = basic_rt({kalle,integers,40,2}), + ?line error = basic_rt({kalle,integers,40,2}), + ?line error = basic_rt({1,2}), + ?line error = basic_rt([]), + + RelProdBody = + fun(R1, R2) -> + if + (erlang:size(R1) =:= 3) andalso (erlang:element(1,R1) =:= 'Set'), + (erlang:size(R2) =:= 3) andalso (erlang:element(1,R2) =:= 'Set') -> + ok + end + end, + + ?line ok = RelProdBody({'Set',a,b}, {'Set',a,b}), + ok. + +basic_rt(T) when is_tuple(T) andalso size(T) =:= 4 andalso element(1, T) =:= type andalso + element(2, T) == integers -> + element(3, T) + element(4, T); +basic_rt(T) when is_tuple(T) andalso size(T) =:= 2 andalso element(1, T) =:= vector -> + {X,Y} = element(2, T), + if + is_float(X), is_float(Y) -> + math:sqrt(X*X+Y*Y) + end; +basic_rt(['+',A,B]) -> + 2*id(A+B); +basic_rt({R1,R2}) when erlang:size(R1) =:= 3 andalso erlang:element(1,R1) =:= 'Set', + erlang:size(R2) =:= 3 andalso erlang:element(1,R2) =:= 'Set' -> + R1 = id(R1), + R2 = id(R2), + R1; +basic_rt(T) when is_tuple(T) andalso size(T) =:= 2 andalso element(1, T) =:= klurf -> + 3*id(element(2, T)); +basic_rt(_) -> + error. + +traverse_dcd(Config) when is_list(Config) -> + L0 = [{log_header,dcd_log,"1.0",a,b,c},{log_header,dcd_log,"2.0",a,b,c}, + {log_header,dcd_log,"0.0",a,b,c},blurf], + {cont,[{log_header,dcd_log,"0.0",a,b,c},blurf],log,funny} = + traverse_dcd({cont,L0}, log, funny), + L1 = [{log_header,dcd_log,"1.0"}], + {cont,L1,log,funny} = traverse_dcd({cont,L1}, log, funny), + L2 = [{a,tuple}], + {cont,L2,log,funny} = traverse_dcd({cont,L2}, log, funny), + ok. + +%% The function starts out with 3 arguments in {x,0}, {x,1}, {x,2}. +%% The outer match of a two tuple will places the first element in {x,3} and +%% second in {x,4}. The guard for the first clause must make ensure that all of those +%% registers are restored befor entering the second clause. +%% +%% (From mnesia_checkpoint.erl, modified.) + +traverse_dcd({Cont,[LogH|Rest]},Log,Fun) + when is_tuple(LogH) andalso size(LogH) =:= 6 andalso element(1, LogH) =:= log_header +andalso erlang:element(2,LogH) == dcd_log, +is_tuple(LogH) andalso size(LogH) =:= 6 andalso element(1, LogH) =:= log_header +andalso erlang:element(3,LogH) >= "1.0" -> + traverse_dcd({Cont,Rest},Log,Fun); +traverse_dcd({Cont,Recs},Log,Fun) -> + {Cont,Recs,Log,Fun}. + + +check_qlc_hrl(Config) when is_list(Config) -> + St = {r1,false,dum}, + ?line foo = cqlc(qlc, q, [{lc,1,2,3}], St), + ?line foo = cqlc(qlc, q, [{lc,1,2,3},b], St), + ?line St = cqlc(qlc, q, [], St), + ?line St = cqlc(qlc, blurf, [{lc,1,2,3},b], St), + ?line St = cqlc(q, q, [{lc,1,2,3},b], St), + ?line St = cqlc(qlc, q, [{lc,1,2,3},b,c], St), + ?line St = cqlc(qlc, q, [a,b], St), + ?line {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}), + ok. + +%% From erl_lint.erl; original name was check_qlc_hrl/4. +cqlc(M, F, As, St) -> + Arity = length(As), + case As of + [{lc,_L,_E,_Qs}|_] when M =:= qlc, F =:= q, + Arity < 3, + not (((element(1, St) =:= r1) orelse fail) and (size(St) =:= 3) and element(2, St)) -> + foo; + _ -> + St + end. + + + +%% Call this function to turn off constant propagation. +id(I) -> I. + +check(F, Result) -> + case F() of + Result -> ok; + Other -> + io:format("Expected: ~p\n", [Result]), + io:format(" Got: ~p\n", [Other]), + test_server:fail() + end. diff --git a/lib/debugger/test/int_SUITE.erl b/lib/debugger/test/int_SUITE.erl new file mode 100644 index 0000000000..0326325888 --- /dev/null +++ b/lib/debugger/test/int_SUITE.erl @@ -0,0 +1,277 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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(int_SUITE). +-include("test_server.hrl"). + +%% Test server specific exports +-export([all/1]). +-export([init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([interpret/1, guards/1, list_suite/1, interpretable/1]). +-export([append/1, append_1/1, append_2/1, member/1, reverse/1]). + +%% Default timetrap timeout (set in init_per_testcase) +-define(default_timeout, ?t:minutes(1)). + +init_per_testcase(interpretable, Config) -> + ?line Dog=test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]; +init_per_testcase(_Case, Config) -> + + %% Interpret some existing and non-existing modules + ?line DataDir = ?config(data_dir, Config), + ?line {module, lists1} = int:i(filename:join([DataDir,lists1])), + ?line {module, guards} = int:i(filename:join([DataDir,guards])), + + ?line Dog=test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + +end_per_testcase(interpretable, Config) -> + ?line Dog=?config(watchdog, Config), + ?line test_server:timetrap_cancel(Dog), + ok; +end_per_testcase(_Case, Config) -> + + %% Quit interpreting + ?line ok = int:n(lists1), + ?line ok = int:n(guards), + + ?line Dog=?config(watchdog, Config), + ?line test_server:timetrap_cancel(Dog), + ?line ok. + +all(suite)-> + [interpret, guards, list_suite, interpretable]. + +interpret(suite) -> + []; +interpret(doc) -> + ["Interpreting modules"]; +interpret(Config) when is_list(Config) -> + ?line int:n(int:interpreted()), + + %% Interpret some existing and non-existing modules + ?line DataDir = ?config(data_dir, Config), + ?line {module, lists1} = int:i(filename:join([DataDir,lists1])), + ?line {module, ordsets1} = int:i(filename:join([DataDir,ordsets1])), + ?line error = int:i(non_existent_module), + + %% Check that the interpreter has the right view. + ?line ExpectedResult = lists:sort([lists1, ordsets1]), + ?line Result = int:interpreted(), + ?line ExpectedResult = lists:sort(Result), + + %% Uniterpret the modules. + ?line ok = int:n(non_existent_module), + ?line ok = int:n(lists1), + ?line [ordsets1] = int:interpreted(), + ?line ok = int:n("ordsets1"), + ?line [] = int:interpreted(), + + ok. + +guards(suite) -> + []; +guards(doc) -> + "Evaluate guards."; +guards(Config) when is_list(Config) -> + ok = guards:guards(). + + +list_suite(suite) -> + [append, reverse, member]. + +append(doc) -> + ["Tests lists1:append/1 & lists1:append/2"]; +append(suite) -> + [append_1, append_2]. + +append_1(suite) -> + []; +append_1(doc) -> + []; +append_1(Config) when is_list(Config) -> + ?line test_server:format("In append_1~n"), + ?line test_server:format("code:which(lists1)=~p~n", + [code:which(lists1)]), + ?line test_server:format("lists1:append([a],[b])=~p~n", + [spawn_eval(lists1,append,[[a],[b]])]), + + ?line "abcdef"=spawn_eval(lists1,append,[["abc","def"]]), + ?line [hej, du,[glade, [bagare]]]= + spawn_eval(lists1,append,[[[hej], [du], [[glade, [bagare]]]]]), + ?line [10, [elem]]=spawn_eval(lists1,append,[[[10], [[elem]]]]), + ok. + +append_2(suite) -> + []; +append_2(doc) -> + []; +append_2(Config) when is_list(Config) -> + ?line test_server:format("In append_2~n"), + ?line test_server:format("code:which(lists1)=~p~n", + [code:which(lists1)]), + + ?line "abcdef"=spawn_eval(lists1,append,["abc", "def"]), + ?line [hej, du]=spawn_eval(lists1,append,[[hej], [du]]), + ?line [10, [elem]]=spawn_eval(lists1,append,[[10], [[elem]]]), + ok. + +reverse(suite) -> + []; +reverse(doc) -> + []; +reverse(Config) when is_list(Config) -> + ?line ok=reverse_test(0), + ?line ok=reverse_test(1), + ?line ok=reverse_test(2), + ?line ok=reverse_test(537), + ok. + +reverse_test(0) -> + case spawn_eval(lists1,reverse,[[]]) of + [] -> + ok; + _Other -> + error + end; +reverse_test(Num) -> + List=spawn_eval(lists1,reverse, + [['The Element'|lists1:duplicate(Num, 'Ele')]]), + case spawn_eval(lists1,reverse,[List]) of + ['The Element'|_Rest] -> + ok; + _Other -> + error + end. + +member(suite) -> + []; +member(doc) -> + ["Tests the lists1:member() implementation. The function " + "is `non-blocking', and only processes 2000 elements " + "at a time.", + "This test case depends on lists1:reverse() to work, " + "wich is tested in a separate test case."]; +member(Config) when list(Config) -> + ?line ok=member_test(0), + ?line ok=member_test(1), + ?line ok=member_test(100), + ?line ok=member_test(537), + ok. + +member_test(0) -> + case spawn_eval(lists1,member,['The Element', []]) of + false -> + ok; + true -> + {error, 'Found (!?)'} + end; +member_test(Num) -> + List=spawn_eval(lists1,reverse, + [['The Element'|spawn_eval(lists1,duplicate, + [Num, 'Elem'])]]), + case spawn_eval(lists1,member,['The Element', List]) of + true -> + ok; + false -> + {error, not_found} + end. + +spawn_eval(M,F,A) -> + Self = self(), + spawn(fun() -> evaluator(Self, M,F,A) end), + receive + Result -> + Result + end. + +evaluator(Pid, M,F,A) -> + Pid ! (catch apply(M,F,A)). + +interpretable(suite) -> + []; +interpretable(doc) -> + ["Test int:interpretable/1"]; +interpretable(Config) when is_list(Config) -> + + %% First make sure that 'lists1' is not loaded + case code:is_loaded(lists1) of + {file, _Loaded} -> + ?line code:purge(lists1), + ?line code:delete(lists1), + ?line code:purge(lists1); + false -> ignore + end, + + %% true + ?line DataDir = filename:dirname(?config(data_dir, Config)), + ?line true = code:add_patha(DataDir), + ?line true = int:interpretable(lists1), + ?line true = int:interpretable(filename:join([DataDir,lists1])), + ?line true = code:del_path(DataDir), + + %% {error, no_src} + ?line PrivDir = filename:join(?config(priv_dir, Config), ""), + ?line {ok, _} = file:copy(filename:join([DataDir,"lists1.beam"]), + filename:join([PrivDir,"lists1.beam"])), + ?line true = code:add_patha(PrivDir), + + ?line {error, no_src} = int:interpretable(lists1), + ?line ok = file:delete(filename:join([PrivDir,"lists1.beam"])), + + %% {error, no_beam} + Src = filename:join([PrivDir,"lists1.erl"]), + ?line {ok, _} = file:copy(filename:join([DataDir,"lists1.erl"]), + Src), + ?line {error, no_beam} = int:interpretable(Src), + + %% {error, no_debug_info} + ?line {ok, _} = compile:file(Src, [{outdir,PrivDir}]), + ?line {error, no_debug_info} = int:interpretable(Src), + ?line {error, no_debug_info} = int:interpretable(lists1), + ?line ok = file:delete(Src), + ?line true = code:del_path(PrivDir), + + %% {error, badarg} + ?line {error, badarg} = int:interpretable(pride), + ?line {error, badarg} = int:interpretable("prejudice.erl"), + + %% {error, {app,App}} + ?line {error, {app,_}} = int:interpretable(file), + ?line {error, {app,_}} = int:interpretable(lists), + ?line {error, {app,_}} = int:interpretable(gs), + ?line case int:interpretable(dbg_ieval) of + {error, {app,_}} -> + ok; + {error, badarg} -> + case code:which(dbg_ieval) of + cover_compiled -> + ok; + Other1 -> + ?line ?t:fail({unexpected_result, Other1}) + end; + Other2 -> + ?line ?t:fail({unexpected_result, Other2}) + end, + + ok. diff --git a/lib/debugger/test/int_SUITE_data/Makefile.src b/lib/debugger/test/int_SUITE_data/Makefile.src new file mode 100644 index 0000000000..95b96b5d00 --- /dev/null +++ b/lib/debugger/test/int_SUITE_data/Makefile.src @@ -0,0 +1,39 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2010. 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% +# +EFLAGS=+debug_info +all: guards.@EMULATOR@ lists1.@EMULATOR@ my_lists.@EMULATOR@ \ + ordsets1.@EMULATOR@ test.@EMULATOR@ test1.@EMULATOR@ + +guards.@EMULATOR@: guards.erl + erlc $(EFLAGS) guards.erl + +lists1.@EMULATOR@: lists1.erl + erlc $(EFLAGS) lists1.erl + +my_lists.@EMULATOR@: my_lists.erl + erlc $(EFLAGS) my_lists.erl + +ordsets1.@EMULATOR@: ordsets1.erl + erlc $(EFLAGS) ordsets1.erl + +test.@EMULATOR@: test.erl + erlc $(EFLAGS) test.erl + +test1.@EMULATOR@: test1.erl + erlc $(EFLAGS) test1.erl diff --git a/lib/debugger/test/int_SUITE_data/guards.erl b/lib/debugger/test/int_SUITE_data/guards.erl new file mode 100644 index 0000000000..c847bb6a8c --- /dev/null +++ b/lib/debugger/test/int_SUITE_data/guards.erl @@ -0,0 +1,108 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2010. 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(guards). + +-export([guards/0]). + +guards() -> + ok = t(), + ok = f(), + ok = ct(1), + ok = multi(1), + ok = multi(2), + ok = multi(3). + +%% The following tests are always true. +t() when integer(42) -> + ok; +t() when float(2.0) -> + ok; +t() when number(7) -> + ok; +t() when number(3.14) -> + ok; +t() when atom(error) -> + ok; +t() when list([a]) -> + ok; +t() when tuple({}) -> + ok; +t() when tuple({1, 2}) -> + ok. + +%% The following tests are always false. +f() when integer(a) -> + ok; +f() when float(b) -> + ok; +f() when number(c) -> + ok; +f() when atom(42) -> + ok; +f() when list(33) -> + ok; +f() when list({}) -> + ok; +f() when list({1, 2}) -> + ok; +f() when tuple(33) -> + ok; +f() when tuple([a]) -> + ok; +f() when tuple([]) -> + ok; +f() when tuple(35) -> + ok; +f() -> + ok. + +%% The following tests are always true. +ct(X) -> + case X of + Y when integer(42) -> + ok; + Y when float(2.0) -> + ok; + Y when number(7) -> + ok; + Y when number(3.14) -> + ok; + Y when atom(error) -> + ok; + Y when list([a]) -> + ok; + Y when tuple({}) -> + ok; + Y when tuple({1, 2}) -> + ok + end. + +multi(X) -> + case X of + Y when float(Y) ; integer(Y) -> + ok; + Y when Y > 1, Y < 10 ; atom(Y) -> + ok; + Y when Y == 4, number(Y) ; list(Y) -> + pannkaka; + Y when Y==3 ; Y==5 ; Y==6 -> + ok + end. diff --git a/lib/debugger/test/int_SUITE_data/lists1.erl b/lib/debugger/test/int_SUITE_data/lists1.erl new file mode 100644 index 0000000000..0214983c11 --- /dev/null +++ b/lib/debugger/test/int_SUITE_data/lists1.erl @@ -0,0 +1,469 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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% +%% + +%% +%% Purpose : Basic lists processing functions. + +-module(lists1). + + +-export([member/2, append/2, append/1, subtract/2, reverse/1, reverse/2, + nth/2, nthtail/2, prefix/2, suffix/2, last/1, + seq/2, seq/3, sum/1, duplicate/2, min/1, max/1, sublist/2, sublist/3, + delete/2, sort/1, merge/2, concat/1, + flatten/1, flatten/2, flat_length/1, flatlength/1, + keymember/3, keysearch/3, keydelete/3, keyreplace/4, + keysort/2, keymerge/3, keymap/3, keymap/4]). + +-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,zf/2, + mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2]). +-export([all/3,any/3,map/3,flatmap/3,foldl/4,foldr/4,filter/3,zf/3, + mapfoldl/4,mapfoldr/4,foreach/3]). + +%% member(X, L) -> (true | false) +%% test if X is a member of the list L + +member(X, [X|_]) -> true; +member(X, [_|Y]) -> + member(X, Y); +member(X, []) -> false. + +%% append(X, Y) appends lists X and Y + +append(L1, L2) -> L1 ++ L2. + +%% append(L) appends the list of lists L + +append([E]) -> E; +append([H|T]) -> H ++ append(T); +append([]) -> []. + +%% subtract(List1, List2) subtract elements in List2 form List1. + +subtract(L1, L2) -> L1 -- L2. + +%% reverse(L) reverse all elements in the list L + +reverse(X) -> reverse(X, []). + +reverse([H|T], Y) -> + reverse(T, [H|Y]); +reverse([], X) -> X. + +%% nth(N, L) returns the N`th element of the list L +%% nthtail(N, L) returns the N`th tail of the list L + +nth(1, [H|T]) -> H; +nth(N, [_|T]) when N > 1 -> + nth(N - 1, T). + +nthtail(1, [H|T]) -> T; +nthtail(N, [H|T]) when N > 1 -> + nthtail(N - 1, T); +nthtail(0, L) when list(L) -> L. + +%% prefix(Prefix, List) -> (true | false) + +prefix([X|PreTail], [X|Tail]) -> + prefix(PreTail, Tail); +prefix([], List) -> true; +prefix(_,_) -> false. + + +%% suffix(Suffix, List) -> (true | false) + +suffix(Suffix, Suffix) -> true; +suffix(Suffix, [_|Tail]) -> + suffix(Suffix, Tail); +suffix(Suffix, []) -> false. + +%% last(List) returns the last element in a list. + +last([E]) -> E; +last([E|Es]) -> + last(Es). + +%% seq(Min, Max) -> [Min,Min+1, ..., Max] +%% seq(Min, Max, Incr) -> [Min,Min+Incr, ..., Max] +%% returns the sequence Min..Max +%% Min <= Max and Min and Max must be integers + +seq(Min, Max) when integer(Min), integer(Max), Min =< Max -> + seq(Min, Max, 1, []). + +seq(Min, Max, Incr) -> + seq(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []). + +seq(Min, Min, I, L) -> [Min|L]; +seq(Min, Max, I, L) -> seq(Min, Max-I, I, [Max|L]). + +%% sum(L) suns the sum of the elements in L + +sum(L) -> sum(L, 0). +sum([H|T], Sum) -> sum(T, Sum + H); +sum([], Sum) -> Sum. + +%% duplicate(N, X) -> [X,X,X,.....,X] (N times) +%% return N copies of X + +duplicate(N, X) when integer(N), N >= 0 -> duplicate(N, X, []). + +duplicate(0, _, L) -> L; +duplicate(N, X, L) -> duplicate(N-1, X, [X|L]). + + +%% min(L) -> returns the minimum element of the list L + +min([H|T]) -> min(T, H). + +min([H|T], Min) when H < Min -> min(T, H); +min([_|T], Min) -> min(T, Min); +min([], Min) -> Min. + +%% max(L) -> returns the maximum element of the list L + +max([H|T]) -> max(T, H). + +max([H|T], Max) when H > Max -> max(T, H); +max([_|T], Max) -> max(T, Max); +max([], Max) -> Max. + +%% sublist(List, Start, Length) +%% Returns the sub-list starting at Start of length Length. + +sublist(List, S, L) when L >= 0 -> + sublist(nthtail(S-1, List), L). + +sublist([H|T], L) when L > 0 -> + [H|sublist(T, L-1)]; +sublist(List, L) -> []. + +%% delete(Item, List) -> List' +%% Delete the first occurance of Item from the list L. + +delete(Item, [Item|Rest]) -> Rest; +delete(Item, [H|Rest]) -> + [H|delete(Item, Rest)]; +delete(Item, []) -> []. + +%% sort(L) -> sorts the list L + +sort([X]) -> [X]; +sort([]) -> []; +sort(X) -> split_and_sort(X, [], []). + +split_and_sort([A,B|T], X, Y) -> + split_and_sort(T, [A|X], [B|Y]); +split_and_sort([H], X, Y) -> + split_and_sort([], [H|X], Y); +split_and_sort([], X, Y) -> + merge(sort(X), sort(Y), []). + +%% merge(X, Y) -> L +%% merges two sorted lists X and Y + +merge(X, Y) -> merge(X, Y, []). + +merge([H1|T1], [H2|T2], L) when H1 < H2 -> + merge(T1, [H2|T2], [H1|L]); +merge(T1, [H2|T2], L) -> + merge(T1, T2, [H2|L]); +merge([H|T], T2, L) -> + merge(T, T2, [H|L]); +merge([], [], L) -> + reverse(L). + +%% concat(L) concatinate the list representation of the elements +%% in L - the elements in L can be atoms, integers of strings. +%% Returns a list of characters. + +concat(List) -> + flatmap(fun thing_to_list/1, List). + +thing_to_list(X) when integer(X) -> integer_to_list(X); +thing_to_list(X) when float(X) -> float_to_list(X); +thing_to_list(X) when atom(X) -> atom_to_list(X); +thing_to_list(X) when list(X) -> X. %Assumed to be a string + +%% flatten(List) +%% flatten(List, Tail) +%% Flatten a list, adding optional tail. + +flatten(List) -> + flatten(List, [], []). + +flatten(List, Tail) -> + flatten(List, [], Tail). + +flatten([H|T], Cont, Tail) when list(H) -> + flatten(H, [T|Cont], Tail); +flatten([H|T], Cont, Tail) -> + [H|flatten(T, Cont, Tail)]; +flatten([], [H|Cont], Tail) -> + flatten(H, Cont, Tail); +flatten([], [], Tail) -> + Tail. + +%% flat_length(List) (undocumented can be rmove later) +%% Calculate the length of a list of lists. + +flat_length(List) -> flatlength(List). + +%% flatlength(List) +%% Calculate the length of a list of lists. + +flatlength(List) -> + flatlength(List, 0). + +flatlength([H|T], L) when list(H) -> + flatlength(H, flatlength(T, L)); +flatlength([H|T], L) -> + flatlength(T, L + 1); +flatlength([], L) -> L. + +%% keymember(Key, Index, [Tuple]) +%% keysearch(Key, Index, [Tuple]) +%% keydelete(Key, Index, [Tuple]) +%% keyreplace(Key, Index, [Tuple], NewTuple) +%% keysort(Index, [Tuple]) +%% keymerge(Index, [Tuple], [Tuple]) +%% keymap(Function, Index, [Tuple]) +%% keymap(Function, ExtraArgs, Index, [Tuple]) + +keymember(Key, N, [T|Ts]) when element(N, T) == Key -> true; +keymember(Key, N, [T|Ts]) -> + keymember(Key, N, Ts); +keymember(Key, N, []) -> false. + +keysearch(Key, N, [H|T]) when element(N, H) == Key -> + {value, H}; +keysearch(Key, N, [H|T]) -> + keysearch(Key, N, T); +keysearch(Key, N, []) -> false. + +keydelete(Key, N, [H|T]) when element(N, H) == Key -> T; +keydelete(Key, N, [H|T]) -> + [H|keydelete(Key, N, T)]; +keydelete(Key, N, []) -> []. + +keyreplace(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key -> + [New|Tail]; +keyreplace(Key, Pos, [H|T], New) -> + [H|keyreplace(Key, Pos, T, New)]; +keyreplace(Key, Pos, [], New) -> []. + +keysort(Index, [X]) -> [X]; +keysort(Index, []) -> []; +keysort(Index, X) -> split_and_keysort(X, [], [], Index). + +split_and_keysort([A,B|T], X, Y, Index) -> + split_and_keysort(T, [A|X], [B|Y], Index); +split_and_keysort([H], X, Y, Index) -> + split_and_keysort([], [H|X], Y, Index); +split_and_keysort([], X, Y, Index) -> + keymerge(Index, keysort(Index, X), keysort(Index, Y), []). + +keymerge(Index, X, Y) -> keymerge(Index, X, Y, []). + +keymerge(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) -> + keymerge(I, T1, [H2|T2], [H1|L]); +keymerge(Index, T1, [H2|T2], L) -> + keymerge(Index,T1, T2, [H2|L]); +keymerge(Index,[H|T], T2, L) -> + keymerge(Index,T, T2, [H|L]); +keymerge(Index, [], [], L) -> + reverse(L). + +keymap(Fun, Index, [Tup|Tail]) -> + [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)]; +keymap( _, _ , []) -> []. + +keymap(Fun, ExtraArgs, Index, [Tup|Tail]) -> + [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))| + keymap(Fun, ExtraArgs, Index, Tail)]; +keymap( _, _ , _, []) -> []. + +%% all(Predicate, List) +%% any(Predicate, List) +%% map(Function, List) +%% flatmap(Function, List) +%% foldl(Function, First, List) +%% foldr(Function, Last, List) +%% filter(Predicate, List) +%% zf(Function, List) +%% mapfoldl(Function, First, List) +%% mapfoldr(Function, Last, List) +%% foreach(Function, List) +%% takewhile(Predicate, List) +%% dropwhile(Predicate, List) +%% splitwith(Predicate, List) +%% for list programming. Function here is either a 'fun' or a tuple +%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke! +%% +%% N.B. Unless where the functions actually needs it only foreach/2/3, +%% which is meant to be used for its side effects, has a defined order +%% of evaluation. +%% +%% There are also versions with an extra argument, ExtraArgs, which is a +%% list of extra arguments to each call. + +all(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> all(Pred, Tail); + false -> false + end; +all(Pred, []) -> true. + +any(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> true; + false -> any(Pred, Tail) + end; +any(Pred, []) -> false. + +map(F, List) -> [ F(E) || E <- List ]. + +flatmap(F, [Hd|Tail]) -> + F(Hd) ++ flatmap(F, Tail); +flatmap(F, []) -> []. + +foldl(F, Accu, [Hd|Tail]) -> + foldl(F, F(Hd, Accu), Tail); +foldl(F, Accu, []) -> Accu. + +foldr(F, Accu, [Hd|Tail]) -> + F(Hd, foldr(F, Accu, Tail)); +foldr(F, Accu, []) -> Accu. + +filter(Pred, List) -> [ E || E <- List, Pred(E) ]. + +zf(F, [Hd|Tail]) -> + case F(Hd) of + true -> + [Hd|zf(F, Tail)]; + {true,Val} -> + [Val|zf(F, Tail)]; + false -> + zf(F, Tail) + end; +zf(F, []) -> []. + +foreach(F, [Hd|Tail]) -> + F(Hd), + foreach(F, Tail); +foreach(F, []) -> ok. + +mapfoldl(F, Accu0, [Hd|Tail]) -> + {R,Accu1} = F(Hd, Accu0), + {Rs,Accu2} = mapfoldl(F, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl(F, Accu, []) -> {[],Accu}. + +mapfoldr(F, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr(F, Accu0, Tail), + {R,Accu2} = F(Hd, Accu1), + {[R|Rs],Accu2}; +mapfoldr(F, Accu, []) -> {[],Accu}. + +takewhile(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> [Hd|takewhile(Pred, Tail)]; + false -> [] + end; +takewhile(Pred, []) -> []. + +dropwhile(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> dropwhile(Pred, Tail); + false -> [Hd|Tail] + end; +dropwhile(Pred, []) -> []. + +splitwith(Pred, List) -> splitwith(Pred, List, []). + +splitwith(Pred, [Hd|Tail], Taken) -> + case Pred(Hd) of + true -> splitwith(Pred, Tail, [Hd|Taken]); + false -> {reverse(Taken), [Hd|Tail]} + end; +splitwith(Pred, [], Taken) -> {reverse(Taken),[]}. + +%% Versions of the above functions with extra arguments. + +all(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> all(Pred, Eas, Tail); + false -> false + end; +all(Pred, Eas, []) -> true. + +any(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> true; + false -> any(Pred, Eas, Tail) + end; +any(Pred, Eas, []) -> false. + +map(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ]. + +flatmap(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]) ++ flatmap(F, Eas, Tail); +flatmap(F, Eas, []) -> []. + +foldl(F, Eas, Accu, [Hd|Tail]) -> + foldl(F, Eas, apply(F, [Hd,Accu|Eas]), Tail); +foldl(F, Eas, Accu, []) -> Accu. + +foldr(F, Eas, Accu, [Hd|Tail]) -> + apply(F, [Hd,foldr(F, Eas, Accu, Tail)|Eas]); +foldr(F, Eas, Accu, []) -> + Accu. + +filter(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ]. + +zf(F, Eas, [Hd|Tail]) -> + case apply(F, [Hd|Eas]) of + true -> + [Hd|zf(F, Eas, Tail)]; + {true,Val} -> + [Val|zf(F, Eas, Tail)]; + false -> + zf(F, Eas, Tail) + end; +zf(F, Eas, []) -> []. + +foreach(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]), + foreach(F, Eas, Tail); +foreach(F, Eas, []) -> ok. + +mapfoldl(F, Eas, Accu0, [Hd|Tail]) -> + {R,Accu1} = apply(F, [Hd,Accu0|Eas]), + {Rs,Accu2} = mapfoldl(F, Eas, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl(F, Eas, Accu, []) -> {[],Accu}. + +mapfoldr(F, Eas, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr(F, Eas, Accu0, Tail), + {R,Accu2} = apply(F, [Hd,Accu1|Eas]), + {[R|Rs],Accu2}; +mapfoldr(F, Eas, Accu, []) -> {[],Accu}. + +%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with +%% extra arguments as this going to be discontinued. diff --git a/lib/debugger/test/int_SUITE_data/my_lists.erl b/lib/debugger/test/int_SUITE_data/my_lists.erl new file mode 100644 index 0000000000..98eb4396e3 --- /dev/null +++ b/lib/debugger/test/int_SUITE_data/my_lists.erl @@ -0,0 +1,5681 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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% +%% + +%% +%%% A rather large file to test the attach delay. +%%% Use only the ordinary lists commands. + +-module(my_lists). + + +-export([member/2, append/2, append/1, subtract/2, reverse/1, reverse/2, + nth/2, nthtail/2, prefix/2, suffix/2, last/1, + seq/2, seq/3, sum/1, duplicate/2, min/1, max/1, sublist/2, sublist/3, + delete/2, sort/1, merge/2, concat/1, + flatten/1, flatten/2, flat_length/1, flatlength/1, + keymember/3, keysearch/3, keydelete/3, keyreplace/4, + keysort/2, keymerge/3, keymap/3, keymap/4]). + +-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,zf/2, + mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2]). +-export([all/3,any/3,map/3,flatmap/3,foldl/4,foldr/4,filter/3,zf/3, + mapfoldl/4,mapfoldr/4,foreach/3]). + +%% member(X, L) -> (true | false) +%% test if X is a member of the list L + +member(X, [X|_]) -> true; +member(X, [_|Y]) -> + member(X, Y); +member(X, []) -> false. + +%% append(X, Y) appends lists X and Y + +append(L1, L2) -> L1 ++ L2. + +%% append(L) appends the list of lists L + +append([E]) -> E; +append([H|T]) -> H ++ append(T); +append([]) -> []. + +%% subtract(List1, List2) subtract elements in List2 form List1. + +subtract(L1, L2) -> L1 -- L2. + +%% reverse(L) reverse all elements in the list L + +reverse(X) -> reverse(X, []). + +reverse([H|T], Y) -> + reverse(T, [H|Y]); +reverse([], X) -> X. + +%% nth(N, L) returns the N`th element of the list L +%% nthtail(N, L) returns the N`th tail of the list L + +nth(1, [H|T]) -> H; +nth(N, [_|T]) when N > 1 -> + nth(N - 1, T). + +nthtail(1, [H|T]) -> T; +nthtail(N, [H|T]) when N > 1 -> + nthtail(N - 1, T); +nthtail(0, L) when list(L) -> L. + +%% prefix(Prefix, List) -> (true | false) + +prefix([X|PreTail], [X|Tail]) -> + prefix(PreTail, Tail); +prefix([], List) -> true; +prefix(_,_) -> false. + + +%% suffix(Suffix, List) -> (true | false) + +suffix(Suffix, Suffix) -> true; +suffix(Suffix, [_|Tail]) -> + suffix(Suffix, Tail); +suffix(Suffix, []) -> false. + +%% last(List) returns the last element in a list. + +last([E]) -> E; +last([E|Es]) -> + last(Es). + +%% seq(Min, Max) -> [Min,Min+1, ..., Max] +%% seq(Min, Max, Incr) -> [Min,Min+Incr, ..., Max] +%% returns the sequence Min..Max +%% Min <= Max and Min and Max must be integers + +seq(Min, Max) when integer(Min), integer(Max), Min =< Max -> + seq(Min, Max, 1, []). + +seq(Min, Max, Incr) -> + seq(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []). + +seq(Min, Min, I, L) -> [Min|L]; +seq(Min, Max, I, L) -> seq(Min, Max-I, I, [Max|L]). + +%% sum(L) suns the sum of the elements in L + +sum(L) -> sum(L, 0). +sum([H|T], Sum) -> sum(T, Sum + H); +sum([], Sum) -> Sum. + +%% duplicate(N, X) -> [X,X,X,.....,X] (N times) +%% return N copies of X + +duplicate(N, X) when integer(N), N >= 0 -> duplicate(N, X, []). + +duplicate(0, _, L) -> L; +duplicate(N, X, L) -> duplicate(N-1, X, [X|L]). + + +%% min(L) -> returns the minimum element of the list L + +min([H|T]) -> min(T, H). + +min([H|T], Min) when H < Min -> min(T, H); +min([_|T], Min) -> min(T, Min); +min([], Min) -> Min. + +%% max(L) -> returns the maximum element of the list L + +max([H|T]) -> max(T, H). + +max([H|T], Max) when H > Max -> max(T, H); +max([_|T], Max) -> max(T, Max); +max([], Max) -> Max. + +%% sublist(List, Start, Length) +%% Returns the sub-list starting at Start of length Length. + +sublist(List, S, L) when L >= 0 -> + sublist(nthtail(S-1, List), L). + +sublist([H|T], L) when L > 0 -> + [H|sublist(T, L-1)]; +sublist(List, L) -> []. + +%% delete(Item, List) -> List' +%% Delete the first occurance of Item from the list L. + +delete(Item, [Item|Rest]) -> Rest; +delete(Item, [H|Rest]) -> + [H|delete(Item, Rest)]; +delete(Item, []) -> []. + +%% sort(L) -> sorts the list L + +sort([X]) -> [X]; +sort([]) -> []; +sort(X) -> split_and_sort(X, [], []). + +split_and_sort([A,B|T], X, Y) -> + split_and_sort(T, [A|X], [B|Y]); +split_and_sort([H], X, Y) -> + split_and_sort([], [H|X], Y); +split_and_sort([], X, Y) -> + merge(sort(X), sort(Y), []). + +%% merge(X, Y) -> L +%% merges two sorted lists X and Y + +merge(X, Y) -> merge(X, Y, []). + +merge([H1|T1], [H2|T2], L) when H1 < H2 -> + merge(T1, [H2|T2], [H1|L]); +merge(T1, [H2|T2], L) -> + merge(T1, T2, [H2|L]); +merge([H|T], T2, L) -> + merge(T, T2, [H|L]); +merge([], [], L) -> + reverse(L). + +%% concat(L) concatinate the list representation of the elements +%% in L - the elements in L can be atoms, integers of strings. +%% Returns a list of characters. + +concat(List) -> + flatmap(fun thing_to_list/1, List). + +thing_to_list(X) when integer(X) -> integer_to_list(X); +thing_to_list(X) when float(X) -> float_to_list(X); +thing_to_list(X) when atom(X) -> atom_to_list(X); +thing_to_list(X) when list(X) -> X. %Assumed to be a string + +%% flatten(List) +%% flatten(List, Tail) +%% Flatten a list, adding optional tail. + +flatten(List) -> + flatten(List, [], []). + +flatten(List, Tail) -> + flatten(List, [], Tail). + +flatten([H|T], Cont, Tail) when list(H) -> + flatten(H, [T|Cont], Tail); +flatten([H|T], Cont, Tail) -> + [H|flatten(T, Cont, Tail)]; +flatten([], [H|Cont], Tail) -> + flatten(H, Cont, Tail); +flatten([], [], Tail) -> + Tail. + +%% flat_length(List) (undocumented can be rmove later) +%% Calculate the length of a list of lists. + +flat_length(List) -> flatlength(List). + +%% flatlength(List) +%% Calculate the length of a list of lists. + +flatlength(List) -> + flatlength(List, 0). + +flatlength([H|T], L) when list(H) -> + flatlength(H, flatlength(T, L)); +flatlength([H|T], L) -> + flatlength(T, L + 1); +flatlength([], L) -> L. + +%% keymember(Key, Index, [Tuple]) +%% keysearch(Key, Index, [Tuple]) +%% keydelete(Key, Index, [Tuple]) +%% keyreplace(Key, Index, [Tuple], NewTuple) +%% keysort(Index, [Tuple]) +%% keymerge(Index, [Tuple], [Tuple]) +%% keymap(Function, Index, [Tuple]) +%% keymap(Function, ExtraArgs, Index, [Tuple]) + +keymember(Key, N, [T|Ts]) when element(N, T) == Key -> true; +keymember(Key, N, [T|Ts]) -> + keymember(Key, N, Ts); +keymember(Key, N, []) -> false. + +keysearch(Key, N, [H|T]) when element(N, H) == Key -> + {value, H}; +keysearch(Key, N, [H|T]) -> + keysearch(Key, N, T); +keysearch(Key, N, []) -> false. + +keydelete(Key, N, [H|T]) when element(N, H) == Key -> T; +keydelete(Key, N, [H|T]) -> + [H|keydelete(Key, N, T)]; +keydelete(Key, N, []) -> []. + +keyreplace(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key -> + [New|Tail]; +keyreplace(Key, Pos, [H|T], New) -> + [H|keyreplace(Key, Pos, T, New)]; +keyreplace(Key, Pos, [], New) -> []. + +keysort(Index, [X]) -> [X]; +keysort(Index, []) -> []; +keysort(Index, X) -> split_and_keysort(X, [], [], Index). + +split_and_keysort([A,B|T], X, Y, Index) -> + split_and_keysort(T, [A|X], [B|Y], Index); +split_and_keysort([H], X, Y, Index) -> + split_and_keysort([], [H|X], Y, Index); +split_and_keysort([], X, Y, Index) -> + keymerge(Index, keysort(Index, X), keysort(Index, Y), []). + +keymerge(Index, X, Y) -> keymerge(Index, X, Y, []). + +keymerge(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) -> + keymerge(I, T1, [H2|T2], [H1|L]); +keymerge(Index, T1, [H2|T2], L) -> + keymerge(Index,T1, T2, [H2|L]); +keymerge(Index,[H|T], T2, L) -> + keymerge(Index,T, T2, [H|L]); +keymerge(Index, [], [], L) -> + reverse(L). + +keymap(Fun, Index, [Tup|Tail]) -> + [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)]; +keymap( _, _ , []) -> []. + +keymap(Fun, ExtraArgs, Index, [Tup|Tail]) -> + [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))| + keymap(Fun, ExtraArgs, Index, Tail)]; +keymap( _, _ , _, []) -> []. + +%% all(Predicate, List) +%% any(Predicate, List) +%% map(Function, List) +%% flatmap(Function, List) +%% foldl(Function, First, List) +%% foldr(Function, Last, List) +%% filter(Predicate, List) +%% zf(Function, List) +%% mapfoldl(Function, First, List) +%% mapfoldr(Function, Last, List) +%% foreach(Function, List) +%% takewhile(Predicate, List) +%% dropwhile(Predicate, List) +%% splitwith(Predicate, List) +%% for list programming. Function here is either a 'fun' or a tuple +%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke! +%% +%% N.B. Unless where the functions actually needs it only foreach/2/3, +%% which is meant to be used for its side effects, has a defined order +%% of evaluation. +%% +%% There are also versions with an extra argument, ExtraArgs, which is a +%% list of extra arguments to each call. + +all(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> all(Pred, Tail); + false -> false + end; +all(Pred, []) -> true. + +any(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> true; + false -> any(Pred, Tail) + end; +any(Pred, []) -> false. + +map(F, List) -> [ F(E) || E <- List ]. + +flatmap(F, [Hd|Tail]) -> + F(Hd) ++ flatmap(F, Tail); +flatmap(F, []) -> []. + +foldl(F, Accu, [Hd|Tail]) -> + foldl(F, F(Hd, Accu), Tail); +foldl(F, Accu, []) -> Accu. + +foldr(F, Accu, [Hd|Tail]) -> + F(Hd, foldr(F, Accu, Tail)); +foldr(F, Accu, []) -> Accu. + +filter(Pred, List) -> [ E || E <- List, Pred(E) ]. + +zf(F, [Hd|Tail]) -> + case F(Hd) of + true -> + [Hd|zf(F, Tail)]; + {true,Val} -> + [Val|zf(F, Tail)]; + false -> + zf(F, Tail) + end; +zf(F, []) -> []. + +foreach(F, [Hd|Tail]) -> + F(Hd), + foreach(F, Tail); +foreach(F, []) -> ok. + +mapfoldl(F, Accu0, [Hd|Tail]) -> + {R,Accu1} = F(Hd, Accu0), + {Rs,Accu2} = mapfoldl(F, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl(F, Accu, []) -> {[],Accu}. + +mapfoldr(F, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr(F, Accu0, Tail), + {R,Accu2} = F(Hd, Accu1), + {[R|Rs],Accu2}; +mapfoldr(F, Accu, []) -> {[],Accu}. + +takewhile(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> [Hd|takewhile(Pred, Tail)]; + false -> [] + end; +takewhile(Pred, []) -> []. + +dropwhile(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> dropwhile(Pred, Tail); + false -> [Hd|Tail] + end; +dropwhile(Pred, []) -> []. + +splitwith(Pred, List) -> splitwith(Pred, List, []). + +splitwith(Pred, [Hd|Tail], Taken) -> + case Pred(Hd) of + true -> splitwith(Pred, Tail, [Hd|Taken]); + false -> {reverse(Taken), [Hd|Tail]} + end; +splitwith(Pred, [], Taken) -> {reverse(Taken),[]}. + +%% Versions of the above functions with extra arguments. + +all(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> all(Pred, Eas, Tail); + false -> false + end; +all(Pred, Eas, []) -> true. + +any(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> true; + false -> any(Pred, Eas, Tail) + end; +any(Pred, Eas, []) -> false. + +map(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ]. + +flatmap(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]) ++ flatmap(F, Eas, Tail); +flatmap(F, Eas, []) -> []. + +foldl(F, Eas, Accu, [Hd|Tail]) -> + foldl(F, Eas, apply(F, [Hd,Accu|Eas]), Tail); +foldl(F, Eas, Accu, []) -> Accu. + +foldr(F, Eas, Accu, [Hd|Tail]) -> + apply(F, [Hd,foldr(F, Eas, Accu, Tail)|Eas]); +foldr(F, Eas, Accu, []) -> + Accu. + +filter(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ]. + +zf(F, Eas, [Hd|Tail]) -> + case apply(F, [Hd|Eas]) of + true -> + [Hd|zf(F, Eas, Tail)]; + {true,Val} -> + [Val|zf(F, Eas, Tail)]; + false -> + zf(F, Eas, Tail) + end; +zf(F, Eas, []) -> []. + +foreach(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]), + foreach(F, Eas, Tail); +foreach(F, Eas, []) -> ok. + +mapfoldl(F, Eas, Accu0, [Hd|Tail]) -> + {R,Accu1} = apply(F, [Hd,Accu0|Eas]), + {Rs,Accu2} = mapfoldl(F, Eas, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl(F, Eas, Accu, []) -> {[],Accu}. + +mapfoldr(F, Eas, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr(F, Eas, Accu0, Tail), + {R,Accu2} = apply(F, [Hd,Accu1|Eas]), + {[R|Rs],Accu2}; +mapfoldr(F, Eas, Accu, []) -> {[],Accu}. + +%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with +%% extra arguments as this going to be discontinued. + + + + + +%%% +++++++++++++++++++++++++++++++++++++++ +%%% +%%% Same as above but with "_1" added to the function names +%%% + + +%% member_1(X, L) -> (true | false) +%% test if X is a member of the list L + +%member_1(X, [X|_]) -> true; +%member_1(X, [_|Y]) -> +% member_1(X, Y); +%member_1(X, []) -> false. + +member_1(X, L) when list(L) -> + case erlang:member_1(X, L) of + L1 when list(L1) -> + receive after 1 -> ok end, + member_1(X, L1); + Boolean -> + Boolean + end. + +%% append_1(X, Y) appends lists X and Y + +append_1(L1, L2) -> L1 ++ L2. + +%% append_1(L) appends the list of lists L + +append_1([E]) -> E; +append_1([H|T]) -> H ++ append_1(T); +append_1([]) -> []. + +%% subtract_1(List1, List2) subtract elements in List2 form List1. + +subtract_1(L1, L2) -> L1 -- L2. + +%% reverse_1(L) reverse all elements in the list L + +reverse_1(X) -> reverse_1(X, []). + +%reverse_1([H|T], Y) -> +% reverse_1(T, [H|Y]); +%reverse_1([], X) -> X. + +reverse_1(List0, Result0) when list(List0) -> + case erlang:reverse_1(List0, Result0) of + {List, Result} -> + receive after 1 -> ok end, + reverse_1(List, Result); + Result -> + Result + end. + + +%% nth_1(N, L) returns the N`th element of the list L +%% nthtail_1(N, L) returns the N`th tail of the list L + +nth_1(1, [H|T]) -> H; +nth_1(N, [_|T]) when N > 1 -> + nth_1(N - 1, T). + +nthtail_1(1, [H|T]) -> T; +nthtail_1(N, [H|T]) when N > 1 -> + nthtail_1(N - 1, T); +nthtail_1(0, L) when list(L) -> L. + +%% prefix_1(Prefix, List) -> (true | false) + +prefix_1([X|PreTail], [X|Tail]) -> + prefix_1(PreTail, Tail); +prefix_1([], List) -> true; +prefix_1(_,_) -> false. + + +%% suffix_1(Suffix, List) -> (true | false) + +suffix_1(Suffix, Suffix) -> true; +suffix_1(Suffix, [_|Tail]) -> + suffix_1(Suffix, Tail); +suffix_1(Suffix, []) -> false. + +%% last(List) returns the last element in a list. + +last_1([E]) -> E; +last_1([E|Es]) -> + last_1(Es). + +%% seq(Min, Max) -> [Min,Min+1, ..., Max] +%% seq(Min, Max, Incr) -> [Min,Min+Incr, ..., Max] +%% returns the sequence Min..Max +%% Min <= Max and Min and Max must be integers + +seq_1(Min, Max) when integer(Min), integer(Max), Min =< Max -> + seq_1(Min, Max, 1, []). + +seq_1(Min, Max, Incr) -> + seq_1(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []). + +seq_1(Min, Min, I, L) -> [Min|L]; +seq_1(Min, Max, I, L) -> seq_1(Min, Max-I, I, [Max|L]). + +%% sum(L) suns the sum of the elements in L + +sum_1(L) -> sum_1(L, 0). +sum_1([H|T], Sum) -> sum_1(T, Sum + H); +sum_1([], Sum) -> Sum. + +%% duplicate(N, X) -> [X,X,X,.....,X] (N times) +%% return N copies of X + +duplicate_1(N, X) when integer(N), N >= 0 -> duplicate_1(N, X, []). + +duplicate_1(0, _, L) -> L; +duplicate_1(N, X, L) -> duplicate_1(N-1, X, [X|L]). + + +%% min(L) -> returns the minimum element of the list L + +min_1([H|T]) -> min_1(T, H). + +min_1([H|T], Min) when H < Min -> min_1(T, H); +min_1([_|T], Min) -> min_1(T, Min); +min_1([], Min) -> Min. + +%% max(L) -> returns the maximum element of the list L + +max_1([H|T]) -> max_1(T, H). + +max_1([H|T], Max) when H > Max -> max_1(T, H); +max_1([_|T], Max) -> max_1(T, Max); +max_1([], Max) -> Max. + +%% sublist(List, Start, Length) +%% Returns the sub-list starting at Start of length Length. + +sublist_1(List, S, L) when L >= 0 -> + sublist_1(nthtail_1(S-1, List), L). + +sublist_1([H|T], L) when L > 0 -> + [H|sublist_1(T, L-1)]; +sublist_1(List, L) -> []. + +%% delete(Item, List) -> List' +%% Delete the first occurance of Item from the list L. + +delete_1(Item, [Item|Rest]) -> Rest; +delete_1(Item, [H|Rest]) -> + [H|delete_1(Item, Rest)]; +delete_1(Item, []) -> []. + +%% sort(L) -> sorts the list L + +sort_1([X]) -> [X]; +sort_1([]) -> []; +sort_1(X) -> split_and_sort_1(X, [], []). + +split_and_sort_1([A,B|T], X, Y) -> + split_and_sort_1(T, [A|X], [B|Y]); +split_and_sort_1([H], X, Y) -> + split_and_sort_1([], [H|X], Y); +split_and_sort_1([], X, Y) -> + merge_1(sort_1(X), sort_1(Y), []). + +%% merge(X, Y) -> L +%% merges two sorted lists X and Y + +merge_1(X, Y) -> merge_1(X, Y, []). + +merge_1([H1|T1], [H2|T2], L) when H1 < H2 -> + merge_1(T1, [H2|T2], [H1|L]); +merge_1(T1, [H2|T2], L) -> + merge_1(T1, T2, [H2|L]); +merge_1([H|T], T2, L) -> + merge_1(T, T2, [H|L]); +merge_1([], [], L) -> + reverse_1(L). + +%% concat(L) concatinate the list representation of the elements +%% in L - the elements in L can be atoms, integers of strings. +%% Returns a list of characters. + +concat_1(List) -> + flatmap_1(fun thing_to_list/1, List). + +thing_to_list_1(X) when integer(X) -> integer_to_list(X); +thing_to_list_1(X) when float(X) -> float_to_list(X); +thing_to_list_1(X) when atom(X) -> atom_to_list(X); +thing_to_list_1(X) when list(X) -> X. %Assumed to be a string + +%% flatten(List) +%% flatten(List, Tail) +%% Flatten a list, adding optional tail. + +flatten_1(List) -> + flatten_1(List, [], []). + +flatten_1(List, Tail) -> + flatten_1(List, [], Tail). + +flatten_1([H|T], Cont, Tail) when list(H) -> + flatten_1(H, [T|Cont], Tail); +flatten_1([H|T], Cont, Tail) -> + [H|flatten_1(T, Cont, Tail)]; +flatten_1([], [H|Cont], Tail) -> + flatten_1(H, Cont, Tail); +flatten_1([], [], Tail) -> + Tail. + +%% flat_length(List) (undocumented can be rmove later) +%% Calculate the length of a list of lists. + +flat_length_1(List) -> flatlength_1(List). + +%% flatlength(List) +%% Calculate the length of a list of lists. + +flatlength_1(List) -> + flatlength_1(List, 0). + +flatlength_1([H|T], L) when list(H) -> + flatlength_1(H, flatlength_1(T, L)); +flatlength_1([H|T], L) -> + flatlength_1(T, L + 1); +flatlength_1([], L) -> L. + +%% keymember(Key, Index, [Tuple]) +%% keysearch(Key, Index, [Tuple]) +%% keydelete(Key, Index, [Tuple]) +%% keyreplace(Key, Index, [Tuple], NewTuple) +%% keysort(Index, [Tuple]) +%% keymerge(Index, [Tuple], [Tuple]) +%% keymap(Function, Index, [Tuple]) +%% keymap(Function, ExtraArgs, Index, [Tuple]) + +keymember_1(Key, N, [T|Ts]) when element(N, T) == Key -> true; +keymember_1(Key, N, [T|Ts]) -> + keymember_1(Key, N, Ts); +keymember_1(Key, N, []) -> false. + +keysearch_1(Key, N, [H|T]) when element(N, H) == Key -> + {value, H}; +keysearch_1(Key, N, [H|T]) -> + keysearch_1(Key, N, T); +keysearch_1(Key, N, []) -> false. + +keydelete_1(Key, N, [H|T]) when element(N, H) == Key -> T; +keydelete_1(Key, N, [H|T]) -> + [H|keydelete_1(Key, N, T)]; +keydelete_1(Key, N, []) -> []. + +keyreplace_1(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key -> + [New|Tail]; +keyreplace_1(Key, Pos, [H|T], New) -> + [H|keyreplace_1(Key, Pos, T, New)]; +keyreplace_1(Key, Pos, [], New) -> []. + +keysort_1(Index, [X]) -> [X]; +keysort_1(Index, []) -> []; +keysort_1(Index, X) -> split_and_keysort_1(X, [], [], Index). + +split_and_keysort_1([A,B|T], X, Y, Index) -> + split_and_keysort_1(T, [A|X], [B|Y], Index); +split_and_keysort_1([H], X, Y, Index) -> + split_and_keysort_1([], [H|X], Y, Index); +split_and_keysort_1([], X, Y, Index) -> + keymerge_1(Index, keysort_1(Index, X), keysort_1(Index, Y), []). + +keymerge_1(Index, X, Y) -> keymerge_1(Index, X, Y, []). + +keymerge_1(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) -> + keymerge_1(I, T1, [H2|T2], [H1|L]); +keymerge_1(Index, T1, [H2|T2], L) -> + keymerge_1(Index,T1, T2, [H2|L]); +keymerge_1(Index,[H|T], T2, L) -> + keymerge_1(Index,T, T2, [H|L]); +keymerge_1(Index, [], [], L) -> + reverse_1(L). + +keymap_1(Fun, Index, [Tup|Tail]) -> + [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap_1(Fun, Index, Tail)]; +keymap_1( _, _ , []) -> []. + +keymap_1(Fun, ExtraArgs, Index, [Tup|Tail]) -> + [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))| + keymap_1(Fun, ExtraArgs, Index, Tail)]; +keymap_1( _, _ , _, []) -> []. + +%% all(Predicate, List) +%% any(Predicate, List) +%% map(Function, List) +%% flatmap(Function, List) +%% foldl(Function, First, List) +%% foldr(Function, Last, List) +%% filter(Predicate, List) +%% zf(Function, List) +%% mapfoldl(Function, First, List) +%% mapfoldr(Function, Last, List) +%% foreach(Function, List) +%% takewhile(Predicate, List) +%% dropwhile(Predicate, List) +%% splitwith(Predicate, List) +%% for list programming. Function here is either a 'fun' or a tuple +%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke! +%% +%% N.B. Unless where the functions actually needs it only foreach/2/3, +%% which is meant to be used for its side effects, has a defined order +%% of evaluation. +%% +%% There are also versions with an extra argument, ExtraArgs, which is a +%% list of extra arguments to each call. + +all_1(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> all_1(Pred, Tail); + false -> false + end; +all_1(Pred, []) -> true. + +any_1(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> true; + false -> any_1(Pred, Tail) + end; +any_1(Pred, []) -> false. + +map_1(F, List) -> [ F(E) || E <- List ]. + +flatmap_1(F, [Hd|Tail]) -> + F(Hd) ++ flatmap_1(F, Tail); +flatmap_1(F, []) -> []. + +foldl_1(F, Accu, [Hd|Tail]) -> + foldl_1(F, F(Hd, Accu), Tail); +foldl_1(F, Accu, []) -> Accu. + +foldr_1(F, Accu, [Hd|Tail]) -> + F(Hd, foldr_1(F, Accu, Tail)); +foldr_1(F, Accu, []) -> Accu. + +filter_1(Pred, List) -> [ E || E <- List, Pred(E) ]. + +zF(F, [Hd|Tail]) -> + case F(Hd) of + true -> + [Hd|zF(F, Tail)]; + {true,Val} -> + [Val|zF(F, Tail)]; + false -> + zF(F, Tail) + end; +zF(F, []) -> []. + +foreach_1(F, [Hd|Tail]) -> + F(Hd), + foreach_1(F, Tail); +foreach_1(F, []) -> ok. + +mapfoldl_1(F, Accu0, [Hd|Tail]) -> + {R,Accu1} = F(Hd, Accu0), + {Rs,Accu2} = mapfoldl_1(F, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl_1(F, Accu, []) -> {[],Accu}. + +mapfoldr_1(F, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr_1(F, Accu0, Tail), + {R,Accu2} = F(Hd, Accu1), + {[R|Rs],Accu2}; +mapfoldr_1(F, Accu, []) -> {[],Accu}. + +takewhile_1(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> [Hd|takewhile_1(Pred, Tail)]; + false -> [] + end; +takewhile_1(Pred, []) -> []. + +dropwhile_1(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> dropwhile_1(Pred, Tail); + false -> [Hd|Tail] + end; +dropwhile_1(Pred, []) -> []. + +splitwith_1(Pred, List) -> splitwith_1(Pred, List, []). + +splitwith_1(Pred, [Hd|Tail], Taken) -> + case Pred(Hd) of + true -> splitwith_1(Pred, Tail, [Hd|Taken]); + false -> {reverse_1(Taken), [Hd|Tail]} + end; +splitwith_1(Pred, [], Taken) -> {reverse_1(Taken),[]}. + +%% Versions of the above functions with extra arguments. + +all_1(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> all_1(Pred, Eas, Tail); + false -> false + end; +all_1(Pred, Eas, []) -> true. + +any_1(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> true; + false -> any_1(Pred, Eas, Tail) + end; +any_1(Pred, Eas, []) -> false. + +map_1(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ]. + +flatmap_1(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]) ++ flatmap_1(F, Eas, Tail); +flatmap_1(F, Eas, []) -> []. + +foldl_1(F, Eas, Accu, [Hd|Tail]) -> + foldl_1(F, Eas, apply(F, [Hd,Accu|Eas]), Tail); +foldl_1(F, Eas, Accu, []) -> Accu. + +foldr_1(F, Eas, Accu, [Hd|Tail]) -> + apply(F, [Hd,foldr_1(F, Eas, Accu, Tail)|Eas]); +foldr_1(F, Eas, Accu, []) -> + Accu. + +filter_1(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ]. + +zF(F, Eas, [Hd|Tail]) -> + case apply(F, [Hd|Eas]) of + true -> + [Hd|zF(F, Eas, Tail)]; + {true,Val} -> + [Val|zF(F, Eas, Tail)]; + false -> + zF(F, Eas, Tail) + end; +zF(F, Eas, []) -> []. + +foreach_1(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]), + foreach_1(F, Eas, Tail); +foreach_1(F, Eas, []) -> ok. + +mapfoldl_1(F, Eas, Accu0, [Hd|Tail]) -> + {R,Accu1} = apply(F, [Hd,Accu0|Eas]), + {Rs,Accu2} = mapfoldl_1(F, Eas, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl_1(F, Eas, Accu, []) -> {[],Accu}. + +mapfoldr_1(F, Eas, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr_1(F, Eas, Accu0, Tail), + {R,Accu2} = apply(F, [Hd,Accu1|Eas]), + {[R|Rs],Accu2}; +mapfoldr_1(F, Eas, Accu, []) -> {[],Accu}. + +%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with +%% extra arguments as this going to be discontinued. + + + + + + +%%% +++++++++++++++++++++ +%%% +%%% "_2" + + + + + +%% member_2(X, L) -> _2(true | false) +%% test if X is a member of the list L + +%member_2(X, [X|_]) -> true; +%member_2(X, [_|Y]) -> +% member_2(X, Y); +%member_2(X, []) -> false. + +member_2(X, L) when list(L) -> + case erlang:member_2(X, L) of + L1 when list(L1) -> + receive after 1 -> ok end, + member_2(X, L1); + Boolean -> + Boolean + end. + +%% append_2(X, Y) appends lists X and Y + +append_2(L1, L2) -> L1 ++ L2. + +%% append_2(L) appends the list of lists L + +append_2([E]) -> E; +append_2([H|T]) -> H ++ append_2(T); +append_2([]) -> []. + +%% subtract_2(List1, List2) subtract elements in List2 form List1. + +subtract_2(L1, L2) -> L1 -- L2. + +%% reverse_2(L) reverse all elements in the list L + +reverse_2(X) -> reverse_2(X, []). + +%reverse_2([H|T], Y) -> +% reverse_2(T, [H|Y]); +%reverse_2([], X) -> X. + +reverse_2(List0, Result0) when list(List0) -> + case erlang:reverse_2(List0, Result0) of + {List, Result} -> + receive after 1 -> ok end, + reverse_2(List, Result); + Result -> + Result + end. + + +%% nth_2(N, L) returns the N`th element of the list L +%% nthtail_2(N, L) returns the N`th tail of the list L + +nth_2(1, [H|T]) -> H; +nth_2(N, [_|T]) when N > 1 -> + nth_2(N - 1, T). + +nthtail_2(1, [H|T]) -> T; +nthtail_2(N, [H|T]) when N > 1 -> + nthtail_2(N - 1, T); +nthtail_2(0, L) when list(L) -> L. + +%% prefix_2(Prefix, List) -> _2(true | false) + +prefix_2([X|PreTail], [X|Tail]) -> + prefix_2(PreTail, Tail); +prefix_2([], List) -> true; +prefix_2(_,_) -> false. + + +%% suffix_2(Suffix, List) -> _2(true | false) + +suffix_2(Suffix, Suffix) -> true; +suffix_2(Suffix, [_|Tail]) -> + suffix_2(Suffix, Tail); +suffix_2(Suffix, []) -> false. + +%% last_2(List) returns the last element in a list. + +last_2([E]) -> E; +last_2([E|Es]) -> + last_2(Es). + +%% seq_2(Min, Max) -> [Min,Min+1, ..., Max] +%% seq_2(Min, Max, Incr) -> [Min,Min+Incr, ..., Max] +%% returns the sequence Min..Max +%% Min <= Max and Min and Max must be integers + +seq_2(Min, Max) when integer(Min), integer(Max), Min =< Max -> + seq_2(Min, Max, 1, []). + +seq_2(Min, Max, Incr) -> + seq_2(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []). + +seq_2(Min, Min, I, L) -> [Min|L]; +seq_2(Min, Max, I, L) -> seq_2(Min, Max-I, I, [Max|L]). + +%% sum_2(L) suns the sum of the elements in L + +sum_2(L) -> sum_2(L, 0). +sum_2([H|T], Sum) -> sum_2(T, Sum + H); +sum_2([], Sum) -> Sum. + +%% duplicate_2(N, X) -> [X,X,X,.....,X] _2(N times) +%% return N copies of X + +duplicate_2(N, X) when integer(N), N >= 0 -> duplicate_2(N, X, []). + +duplicate_2(0, _, L) -> L; +duplicate_2(N, X, L) -> duplicate_2(N-1, X, [X|L]). + + +%% min_2(L) -> returns the minimum element of the list L + +min_2([H|T]) -> min_2(T, H). + +min_2([H|T], Min) when H < Min -> min_2(T, H); +min_2([_|T], Min) -> min_2(T, Min); +min_2([], Min) -> Min. + +%% max_2(L) -> returns the maximum element of the list L + +max_2([H|T]) -> max_2(T, H). + +max_2([H|T], Max) when H > Max -> max_2(T, H); +max_2([_|T], Max) -> max_2(T, Max); +max_2([], Max) -> Max. + +%% sublist(List, Start, Length) +%% Returns the sub-list starting at Start of length Length. + +sublist_2(List, S, L) when L >= 0 -> + sublist_2(nthtail_2(S-1, List), L). + +sublist_2([H|T], L) when L > 0 -> + [H|sublist_2(T, L-1)]; +sublist_2(List, L) -> []. + +%% delete_2(Item, List) -> List' +%% Delete the first occurance of Item from the list L. + +delete_2(Item, [Item|Rest]) -> Rest; +delete_2(Item, [H|Rest]) -> + [H|delete_2(Item, Rest)]; +delete_2(Item, []) -> []. + +%% sort_2(L) -> sorts the list L + +sort_2([X]) -> [X]; +sort_2([]) -> []; +sort_2(X) -> split_and_sort_2(X, [], []). + +split_and_sort_2([A,B|T], X, Y) -> + split_and_sort_2(T, [A|X], [B|Y]); +split_and_sort_2([H], X, Y) -> + split_and_sort_2([], [H|X], Y); +split_and_sort_2([], X, Y) -> + merge_2(sort_2(X), sort_2(Y), []). + +%% merge_2(X, Y) -> L +%% merges two sorted lists X and Y + +merge_2(X, Y) -> merge_2(X, Y, []). + +merge_2([H1|T1], [H2|T2], L) when H1 < H2 -> + merge_2(T1, [H2|T2], [H1|L]); +merge_2(T1, [H2|T2], L) -> + merge_2(T1, T2, [H2|L]); +merge_2([H|T], T2, L) -> + merge_2(T, T2, [H|L]); +merge_2([], [], L) -> + reverse_2(L). + +%% concat_2(L) concatinate the list representation of the elements +%% in L - the elements in L can be atoms, integers of strings. +%% Returns a list of characters. + +concat_2(List) -> + flatmap_2(fun thing_to_list/1, List). + +thing_to_list_2(X) when integer(X) -> integer_to_list(X); +thing_to_list_2(X) when float(X) -> float_to_list(X); +thing_to_list_2(X) when atom(X) -> atom_to_list(X); +thing_to_list_2(X) when list(X) -> X. %Assumed to be a string + +%% flatten_2(List) +%% flatten_2(List, Tail) +%% Flatten a list, adding optional tail. + +flatten_2(List) -> + flatten_2(List, [], []). + +flatten_2(List, Tail) -> + flatten_2(List, [], Tail). + +flatten_2([H|T], Cont, Tail) when list(H) -> + flatten_2(H, [T|Cont], Tail); +flatten_2([H|T], Cont, Tail) -> + [H|flatten_2(T, Cont, Tail)]; +flatten_2([], [H|Cont], Tail) -> + flatten_2(H, Cont, Tail); +flatten_2([], [], Tail) -> + Tail. + +%% flat_length_2(List) _2(undocumented can be rmove later) +%% Calculate the length of a list of lists. + +flat_length_2(List) -> flatlength_2(List). + +%% flatlength_2(List) +%% Calculate the length of a list of lists. + +flatlength_2(List) -> + flatlength_2(List, 0). + +flatlength_2([H|T], L) when list(H) -> + flatlength_2(H, flatlength_2(T, L)); +flatlength_2([H|T], L) -> + flatlength_2(T, L + 1); +flatlength_2([], L) -> L. + +%% keymember_2(Key, Index, [Tuple]) +%% keysearch_2(Key, Index, [Tuple]) +%% keydelete_2(Key, Index, [Tuple]) +%% keyreplace_2(Key, Index, [Tuple], NewTuple) +%% keysort_2(Index, [Tuple]) +%% keymerge_2(Index, [Tuple], [Tuple]) +%% keymap_2(Function, Index, [Tuple]) +%% keymap_2(Function, ExtraArgs, Index, [Tuple]) + +keymember_2(Key, N, [T|Ts]) when element(N, T) == Key -> true; +keymember_2(Key, N, [T|Ts]) -> + keymember_2(Key, N, Ts); +keymember_2(Key, N, []) -> false. + +keysearch_2(Key, N, [H|T]) when element(N, H) == Key -> + {value, H}; +keysearch_2(Key, N, [H|T]) -> + keysearch_2(Key, N, T); +keysearch_2(Key, N, []) -> false. + +keydelete_2(Key, N, [H|T]) when element(N, H) == Key -> T; +keydelete_2(Key, N, [H|T]) -> + [H|keydelete_2(Key, N, T)]; +keydelete_2(Key, N, []) -> []. + +keyreplace_2(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key -> + [New|Tail]; +keyreplace_2(Key, Pos, [H|T], New) -> + [H|keyreplace_2(Key, Pos, T, New)]; +keyreplace_2(Key, Pos, [], New) -> []. + +keysort_2(Index, [X]) -> [X]; +keysort_2(Index, []) -> []; +keysort_2(Index, X) -> split_and_keysort_2(X, [], [], Index). + +split_and_keysort_2([A,B|T], X, Y, Index) -> + split_and_keysort_2(T, [A|X], [B|Y], Index); +split_and_keysort_2([H], X, Y, Index) -> + split_and_keysort_2([], [H|X], Y, Index); +split_and_keysort_2([], X, Y, Index) -> + keymerge_2(Index, keysort_2(Index, X), keysort_2(Index, Y), []). + +keymerge_2(Index, X, Y) -> keymerge_2(Index, X, Y, []). + +keymerge_2(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) -> + keymerge_2(I, T1, [H2|T2], [H1|L]); +keymerge_2(Index, T1, [H2|T2], L) -> + keymerge_2(Index,T1, T2, [H2|L]); +keymerge_2(Index,[H|T], T2, L) -> + keymerge_2(Index,T, T2, [H|L]); +keymerge_2(Index, [], [], L) -> + reverse_2(L). + +keymap_2(Fun, Index, [Tup|Tail]) -> + [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap_2(Fun, Index, Tail)]; +keymap_2( _, _ , []) -> []. + +keymap_2(Fun, ExtraArgs, Index, [Tup|Tail]) -> + [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))| + keymap_2(Fun, ExtraArgs, Index, Tail)]; +keymap_2( _, _ , _, []) -> []. + +%% all_2(Predicate, List) +%% any_2(Predicate, List) +%% map_2(Function, List) +%% flatmap_2(Function, List) +%% foldl_2(Function, First, List) +%% foldr_2(Function, Last, List) +%% filter_2(Predicate, List) +%% zF(Function, List) +%% mapfoldl_2(Function, First, List) +%% mapfoldr_2(Function, Last, List) +%% foreach_2(Function, List) +%% takewhile_2(Predicate, List) +%% dropwhile_2(Predicate, List) +%% splitwith_2(Predicate, List) +%% for list programming. Function here is either a 'fun' or a tuple +%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke! +%% +%% N.B. Unless where the functions actually needs it only foreach/2/3, +%% which is meant to be used for its side effects, has a defined order +%% of evaluation. +%% +%% There are also versions with an extra argument, ExtraArgs, which is a +%% list of extra arguments to each call. + +all_2(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> all_2(Pred, Tail); + false -> false + end; +all_2(Pred, []) -> true. + +any_2(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> true; + false -> any_2(Pred, Tail) + end; +any_2(Pred, []) -> false. + +map_2(F, List) -> [ F(E) || E <- List ]. + +flatmap_2(F, [Hd|Tail]) -> + F(Hd) ++ flatmap_2(F, Tail); +flatmap_2(F, []) -> []. + +foldl_2(F, Accu, [Hd|Tail]) -> + foldl_2(F, F(Hd, Accu), Tail); +foldl_2(F, Accu, []) -> Accu. + +foldr_2(F, Accu, [Hd|Tail]) -> + F(Hd, foldr_2(F, Accu, Tail)); +foldr_2(F, Accu, []) -> Accu. + +filter_2(Pred, List) -> [ E || E <- List, Pred(E) ]. + +zF_2(F, [Hd|Tail]) -> + case F(Hd) of + true -> + [Hd|zF_2(F, Tail)]; + {true,Val} -> + [Val|zF_2(F, Tail)]; + false -> + zF_2(F, Tail) + end; +zF_2(F, []) -> []. + +foreach_2(F, [Hd|Tail]) -> + F(Hd), + foreach_2(F, Tail); +foreach_2(F, []) -> ok. + +mapfoldl_2(F, Accu0, [Hd|Tail]) -> + {R,Accu1} = F(Hd, Accu0), + {Rs,Accu2} = mapfoldl_2(F, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl_2(F, Accu, []) -> {[],Accu}. + +mapfoldr_2(F, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr_2(F, Accu0, Tail), + {R,Accu2} = F(Hd, Accu1), + {[R|Rs],Accu2}; +mapfoldr_2(F, Accu, []) -> {[],Accu}. + +takewhile_2(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> [Hd|takewhile_2(Pred, Tail)]; + false -> [] + end; +takewhile_2(Pred, []) -> []. + +dropwhile_2(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> dropwhile_2(Pred, Tail); + false -> [Hd|Tail] + end; +dropwhile_2(Pred, []) -> []. + +splitwith_2(Pred, List) -> splitwith_2(Pred, List, []). + +splitwith_2(Pred, [Hd|Tail], Taken) -> + case Pred(Hd) of + true -> splitwith_2(Pred, Tail, [Hd|Taken]); + false -> {reverse_2(Taken), [Hd|Tail]} + end; +splitwith_2(Pred, [], Taken) -> {reverse_2(Taken),[]}. + +%% Versions of the above functions with extra arguments. + +all_2(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> all_2(Pred, Eas, Tail); + false -> false + end; +all_2(Pred, Eas, []) -> true. + +any_2(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> true; + false -> any_2(Pred, Eas, Tail) + end; +any_2(Pred, Eas, []) -> false. + +map_2(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ]. + +flatmap_2(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]) ++ flatmap_2(F, Eas, Tail); +flatmap_2(F, Eas, []) -> []. + +foldl_2(F, Eas, Accu, [Hd|Tail]) -> + foldl_2(F, Eas, apply(F, [Hd,Accu|Eas]), Tail); +foldl_2(F, Eas, Accu, []) -> Accu. + +foldr_2(F, Eas, Accu, [Hd|Tail]) -> + apply(F, [Hd,foldr_2(F, Eas, Accu, Tail)|Eas]); +foldr_2(F, Eas, Accu, []) -> + Accu. + +filter_2(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ]. + +zF_2(F, Eas, [Hd|Tail]) -> + case apply(F, [Hd|Eas]) of + true -> + [Hd|zF_2(F, Eas, Tail)]; + {true,Val} -> + [Val|zF_2(F, Eas, Tail)]; + false -> + zF_2(F, Eas, Tail) + end; +zF_2(F, Eas, []) -> []. + +foreach_2(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]), + foreach_2(F, Eas, Tail); +foreach_2(F, Eas, []) -> ok. + +mapfoldl_2(F, Eas, Accu0, [Hd|Tail]) -> + {R,Accu1} = apply(F, [Hd,Accu0|Eas]), + {Rs,Accu2} = mapfoldl_2(F, Eas, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl_2(F, Eas, Accu, []) -> {[],Accu}. + +mapfoldr_2(F, Eas, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr_2(F, Eas, Accu0, Tail), + {R,Accu2} = apply(F, [Hd,Accu1|Eas]), + {[R|Rs],Accu2}; +mapfoldr_2(F, Eas, Accu, []) -> {[],Accu}. + +%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with +%% extra arguments as this going to be discontinued. + + + + + +%%% +++++++++++++++++++ +%%% +%%% With "_3" + + + + +%% member_3(X, L) -> _3(true | false) +%% test if X is a member of the list L + +%member_3(X, [X|_]) -> true; +%member_3(X, [_|Y]) -> +% member_3(X, Y); +%member_3(X, []) -> false. + +member_3(X, L) when list(L) -> + case erlang:member(X, L) of + L1 when list(L1) -> + receive after 1 -> ok end, + member_3(X, L1); + Boolean -> + Boolean + end. + +%% append_3(X, Y) appends lists X and Y + +append_3(L1, L2) -> L1 ++ L2. + +%% append_3(L) appends the list of lists L + +append_3([E]) -> E; +append_3([H|T]) -> H ++ append_3(T); +append_3([]) -> []. + +%% subtract_3(List1, List2) subtract elements in List2 form List1. + +subtract_3(L1, L2) -> L1 -- L2. + +%% reverse_3(L) reverse all elements in the list L + +reverse_3(X) -> reverse_3(X, []). + +%reverse_3([H|T], Y) -> +% reverse_3(T, [H|Y]); +%reverse_3([], X) -> X. + +reverse_3(List0, Result0) when list(List0) -> + case erlang:reverse_3(List0, Result0) of + {List, Result} -> + receive after 1 -> ok end, + reverse_3(List, Result); + Result -> + Result + end. + + +%% nth_3(N, L) returns the N`th element of the list L +%% nthtail_3(N, L) returns the N`th tail of the list L + +nth_3(1, [H|T]) -> H; +nth_3(N, [_|T]) when N > 1 -> + nth_3(N - 1, T). + +nthtail_3(1, [H|T]) -> T; +nthtail_3(N, [H|T]) when N > 1 -> + nthtail_3(N - 1, T); +nthtail_3(0, L) when list(L) -> L. + +%% prefix_3(Prefix, List) -> _3(true | false) + +prefix_3([X|PreTail], [X|Tail]) -> + prefix_3(PreTail, Tail); +prefix_3([], List) -> true; +prefix_3(_,_) -> false. + + +%% suffix_3(Suffix, List) -> _3(true | false) + +suffix_3(Suffix, Suffix) -> true; +suffix_3(Suffix, [_|Tail]) -> + suffix_3(Suffix, Tail); +suffix_3(Suffix, []) -> false. + +%% last_3(List) returns the last element in a list. + +last_3([E]) -> E; +last_3([E|Es]) -> + last_3(Es). + +%% seq_3(Min, Max) -> [Min,Min+1, ..., Max] +%% seq_3(Min, Max, Incr) -> [Min,Min+Incr, ..., Max] +%% returns the sequence Min..Max +%% Min <= Max and Min and Max must be integers + +seq_3(Min, Max) when integer(Min), integer(Max), Min =< Max -> + seq_3(Min, Max, 1, []). + +seq_3(Min, Max, Incr) -> + seq_3(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []). + +seq_3(Min, Min, I, L) -> [Min|L]; +seq_3(Min, Max, I, L) -> seq_3(Min, Max-I, I, [Max|L]). + +%% sum_3(L) suns the sum of the elements in L + +sum_3(L) -> sum_3(L, 0). +sum_3([H|T], Sum) -> sum_3(T, Sum + H); +sum_3([], Sum) -> Sum. + +%% duplicate_3(N, X) -> [X,X,X,.....,X] _3(N times) +%% return N copies of X + +duplicate_3(N, X) when integer(N), N >= 0 -> duplicate_3(N, X, []). + +duplicate_3(0, _, L) -> L; +duplicate_3(N, X, L) -> duplicate_3(N-1, X, [X|L]). + + +%% min_3(L) -> returns the minimum element of the list L + +min_3([H|T]) -> min_3(T, H). + +min_3([H|T], Min) when H < Min -> min_3(T, H); +min_3([_|T], Min) -> min_3(T, Min); +min_3([], Min) -> Min. + +%% max_3(L) -> returns the maximum element of the list L + +max_3([H|T]) -> max_3(T, H). + +max_3([H|T], Max) when H > Max -> max_3(T, H); +max_3([_|T], Max) -> max_3(T, Max); +max_3([], Max) -> Max. + +%% sublist_3(List, Start, Length) +%% Returns the sub-list starting at Start of length Length. + +sublist_3(List, S, L) when L >= 0 -> + sublist_3(nthtail_3(S-1, List), L). + +sublist_3([H|T], L) when L > 0 -> + [H|sublist_3(T, L-1)]; +sublist_3(List, L) -> []. + +%% delete_3(Item, List) -> List' +%% Delete the first occurance of Item from the list L. + +delete_3(Item, [Item|Rest]) -> Rest; +delete_3(Item, [H|Rest]) -> + [H|delete_3(Item, Rest)]; +delete_3(Item, []) -> []. + +%% sort_3(L) -> sorts the list L + +sort_3([X]) -> [X]; +sort_3([]) -> []; +sort_3(X) -> split_and_sort_3(X, [], []). + +split_and_sort_3([A,B|T], X, Y) -> + split_and_sort_3(T, [A|X], [B|Y]); +split_and_sort_3([H], X, Y) -> + split_and_sort_3([], [H|X], Y); +split_and_sort_3([], X, Y) -> + merge_3(sort_3(X), sort_3(Y), []). + +%% merge_3(X, Y) -> L +%% merges two sorted lists X and Y + +merge_3(X, Y) -> merge_3(X, Y, []). + +merge_3([H1|T1], [H2|T2], L) when H1 < H2 -> + merge_3(T1, [H2|T2], [H1|L]); +merge_3(T1, [H2|T2], L) -> + merge_3(T1, T2, [H2|L]); +merge_3([H|T], T2, L) -> + merge_3(T, T2, [H|L]); +merge_3([], [], L) -> + reverse_3(L). + +%% concat_3(L) concatinate the list representation of the elements +%% in L - the elements in L can be atoms, integers of strings. +%% Returns a list of characters. + +concat_3(List) -> + flatmap_3(fun thing_to_list/1, List). + +thing_to_list_3(X) when integer(X) -> integer_to_list(X); +thing_to_list_3(X) when float(X) -> float_to_list(X); +thing_to_list_3(X) when atom(X) -> atom_to_list(X); +thing_to_list_3(X) when list(X) -> X. %Assumed to be a string + +%% flatten_3(List) +%% flatten_3(List, Tail) +%% Flatten a list, adding optional tail. + +flatten_3(List) -> + flatten_3(List, [], []). + +flatten_3(List, Tail) -> + flatten_3(List, [], Tail). + +flatten_3([H|T], Cont, Tail) when list(H) -> + flatten_3(H, [T|Cont], Tail); +flatten_3([H|T], Cont, Tail) -> + [H|flatten_3(T, Cont, Tail)]; +flatten_3([], [H|Cont], Tail) -> + flatten_3(H, Cont, Tail); +flatten_3([], [], Tail) -> + Tail. + +%% flat_length_3(List) _3(undocumented can be rmove later) +%% Calculate the length of a list of lists. + +flat_length_3(List) -> flatlength_3(List). + +%% flatlength_3(List) +%% Calculate the length of a list of lists. + +flatlength_3(List) -> + flatlength_3(List, 0). + +flatlength_3([H|T], L) when list(H) -> + flatlength_3(H, flatlength_3(T, L)); +flatlength_3([H|T], L) -> + flatlength_3(T, L + 1); +flatlength_3([], L) -> L. + +%% keymember_3(Key, Index, [Tuple]) +%% keysearch_3(Key, Index, [Tuple]) +%% keydelete_3(Key, Index, [Tuple]) +%% keyreplace_3(Key, Index, [Tuple], NewTuple) +%% keysort_3(Index, [Tuple]) +%% keymerge_3(Index, [Tuple], [Tuple]) +%% keymap_3(Function, Index, [Tuple]) +%% keymap_3(Function, ExtraArgs, Index, [Tuple]) + +keymember_3(Key, N, [T|Ts]) when element(N, T) == Key -> true; +keymember_3(Key, N, [T|Ts]) -> + keymember_3(Key, N, Ts); +keymember_3(Key, N, []) -> false. + +keysearch_3(Key, N, [H|T]) when element(N, H) == Key -> + {value, H}; +keysearch_3(Key, N, [H|T]) -> + keysearch_3(Key, N, T); +keysearch_3(Key, N, []) -> false. + +keydelete_3(Key, N, [H|T]) when element(N, H) == Key -> T; +keydelete_3(Key, N, [H|T]) -> + [H|keydelete_3(Key, N, T)]; +keydelete_3(Key, N, []) -> []. + +keyreplace_3(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key -> + [New|Tail]; +keyreplace_3(Key, Pos, [H|T], New) -> + [H|keyreplace_3(Key, Pos, T, New)]; +keyreplace_3(Key, Pos, [], New) -> []. + +keysort_3(Index, [X]) -> [X]; +keysort_3(Index, []) -> []; +keysort_3(Index, X) -> split_and_keysort_3(X, [], [], Index). + +split_and_keysort_3([A,B|T], X, Y, Index) -> + split_and_keysort_3(T, [A|X], [B|Y], Index); +split_and_keysort_3([H], X, Y, Index) -> + split_and_keysort_3([], [H|X], Y, Index); +split_and_keysort_3([], X, Y, Index) -> + keymerge_3(Index, keysort_3(Index, X), keysort_3(Index, Y), []). + +keymerge_3(Index, X, Y) -> keymerge_3(Index, X, Y, []). + +keymerge_3(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) -> + keymerge_3(I, T1, [H2|T2], [H1|L]); +keymerge_3(Index, T1, [H2|T2], L) -> + keymerge_3(Index,T1, T2, [H2|L]); +keymerge_3(Index,[H|T], T2, L) -> + keymerge_3(Index,T, T2, [H|L]); +keymerge_3(Index, [], [], L) -> + reverse_3(L). + +keymap_3(Fun, Index, [Tup|Tail]) -> + [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap_3(Fun, Index, Tail)]; +keymap_3( _, _ , []) -> []. + +keymap_3(Fun, ExtraArgs, Index, [Tup|Tail]) -> + [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))| + keymap_3(Fun, ExtraArgs, Index, Tail)]; +keymap_3( _, _ , _, []) -> []. + +%% all_3(Predicate, List) +%% any_3(Predicate, List) +%% map_3(Function, List) +%% flatmap_3(Function, List) +%% foldl_3(Function, First, List) +%% foldr_3(Function, Last, List) +%% filter_3(Predicate, List) +%% zF(Function, List) +%% mapfoldl_3(Function, First, List) +%% mapfoldr_3(Function, Last, List) +%% foreach_3(Function, List) +%% takewhile_3(Predicate, List) +%% dropwhile_3(Predicate, List) +%% splitwith_3(Predicate, List) +%% for list programming. Function here is either a 'fun' or a tuple +%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke! +%% +%% N.B. Unless where the functions actually needs it only foreach/2/3, +%% which is meant to be used for its side effects, has a defined order +%% of evaluation. +%% +%% There are also versions with an extra argument, ExtraArgs, which is a +%% list of extra arguments to each call. + +all_3(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> all_3(Pred, Tail); + false -> false + end; +all_3(Pred, []) -> true. + +any_3(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> true; + false -> any_3(Pred, Tail) + end; +any_3(Pred, []) -> false. + +map_3(F, List) -> [ F(E) || E <- List ]. + +flatmap_3(F, [Hd|Tail]) -> + F(Hd) ++ flatmap_3(F, Tail); +flatmap_3(F, []) -> []. + +foldl_3(F, Accu, [Hd|Tail]) -> + foldl_3(F, F(Hd, Accu), Tail); +foldl_3(F, Accu, []) -> Accu. + +foldr_3(F, Accu, [Hd|Tail]) -> + F(Hd, foldr_3(F, Accu, Tail)); +foldr_3(F, Accu, []) -> Accu. + +filter_3(Pred, List) -> [ E || E <- List, Pred(E) ]. + +zF_3(F, [Hd|Tail]) -> + case F(Hd) of + true -> + [Hd|zF_3(F, Tail)]; + {true,Val} -> + [Val|zF_3(F, Tail)]; + false -> + zF_3(F, Tail) + end; +zF_3(F, []) -> []. + +foreach_3(F, [Hd|Tail]) -> + F(Hd), + foreach_3(F, Tail); +foreach_3(F, []) -> ok. + +mapfoldl_3(F, Accu0, [Hd|Tail]) -> + {R,Accu1} = F(Hd, Accu0), + {Rs,Accu2} = mapfoldl_3(F, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl_3(F, Accu, []) -> {[],Accu}. + +mapfoldr_3(F, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr_3(F, Accu0, Tail), + {R,Accu2} = F(Hd, Accu1), + {[R|Rs],Accu2}; +mapfoldr_3(F, Accu, []) -> {[],Accu}. + +takewhile_3(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> [Hd|takewhile_3(Pred, Tail)]; + false -> [] + end; +takewhile_3(Pred, []) -> []. + +dropwhile_3(Pred, [Hd|Tail]) -> + case Pred(Hd) of + true -> dropwhile_3(Pred, Tail); + false -> [Hd|Tail] + end; +dropwhile_3(Pred, []) -> []. + +splitwith_3(Pred, List) -> splitwith_3(Pred, List, []). + +splitwith_3(Pred, [Hd|Tail], Taken) -> + case Pred(Hd) of + true -> splitwith_3(Pred, Tail, [Hd|Taken]); + false -> {reverse_3(Taken), [Hd|Tail]} + end; +splitwith_3(Pred, [], Taken) -> {reverse_3(Taken),[]}. + +%% Versions of the above functions with extra arguments. + +all_3(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> all_3(Pred, Eas, Tail); + false -> false + end; +all_3(Pred, Eas, []) -> true. + +any_3(Pred, Eas, [Hd|Tail]) -> + case apply(Pred, [Hd|Eas]) of + true -> true; + false -> any_3(Pred, Eas, Tail) + end; +any_3(Pred, Eas, []) -> false. + +map_3(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ]. + +flatmap_3(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]) ++ flatmap_3(F, Eas, Tail); +flatmap_3(F, Eas, []) -> []. + +foldl_3(F, Eas, Accu, [Hd|Tail]) -> + foldl_3(F, Eas, apply(F, [Hd,Accu|Eas]), Tail); +foldl_3(F, Eas, Accu, []) -> Accu. + +foldr_3(F, Eas, Accu, [Hd|Tail]) -> + apply(F, [Hd,foldr_3(F, Eas, Accu, Tail)|Eas]); +foldr_3(F, Eas, Accu, []) -> + Accu. + +filter_3(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ]. + +zF_3(F, Eas, [Hd|Tail]) -> + case apply(F, [Hd|Eas]) of + true -> + [Hd|zF(F, Eas, Tail)]; + {true,Val} -> + [Val|zF(F, Eas, Tail)]; + false -> + zF(F, Eas, Tail) + end; +zF_3(F, Eas, []) -> []. + +foreach_3(F, Eas, [Hd|Tail]) -> + apply(F, [Hd|Eas]), + foreach_3(F, Eas, Tail); +foreach_3(F, Eas, []) -> ok. + +mapfoldl_3(F, Eas, Accu0, [Hd|Tail]) -> + {R,Accu1} = apply(F, [Hd,Accu0|Eas]), + {Rs,Accu2} = mapfoldl_3(F, Eas, Accu1, Tail), + {[R|Rs],Accu2}; +mapfoldl_3(F, Eas, Accu, []) -> {[],Accu}. + +mapfoldr_3(F, Eas, Accu0, [Hd|Tail]) -> + {Rs,Accu1} = mapfoldr_3(F, Eas, Accu0, Tail), + {R,Accu2} = apply(F, [Hd,Accu1|Eas]), + {[R|Rs],Accu2}; +mapfoldr_3(F, Eas, Accu, []) -> {[],Accu}. + +%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with +%% extra arguments as this going to be discontinued. + + + + +lots_of_atoms () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms1 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms2 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms3 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms4 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms5 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms6 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms7 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms8 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms9 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms10 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms11 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. + + +lots_of_atoms12 () -> + +Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + + +Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + + +Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg', + +Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'. diff --git a/lib/debugger/test/int_SUITE_data/ordsets1.erl b/lib/debugger/test/int_SUITE_data/ordsets1.erl new file mode 100644 index 0000000000..a01d35eb51 --- /dev/null +++ b/lib/debugger/test/int_SUITE_data/ordsets1.erl @@ -0,0 +1,191 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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% +%% + +%% +%% Copyright (C) 1991, Ellemtel Telecommunications Systems Laboratories +%% File : ordsets.erl +%% Author : Robert Virding +%% Purpose : Functions for manipulating sets as ordered lists. + +%% As yet some of these are not very efficiently written. + +-module(ordsets1). + +-export([new_set/0,is_set/1,set_to_list/1,list_to_set/1]). +-export([is_element/2,add_element/2,del_element/2]). +-export([union/2,union/1,intersection/2,intersection/1]). +-export([subtract/2,subset/2]). + +%% new_set() +%% Return a new empty ordered set. + +new_set() -> + []. + +%% is_set(Set) +%% Return 'true' if Set is an ordered set of elements, else 'false'. + +is_set([E|Es]) -> + is_set(Es, E); +is_set([]) -> + true. + +is_set([E2|Es], E1) when E1 < E2 -> + is_set(Es, E2); +is_set([E2|Es], E1) -> + false; +is_set([], E1) -> + true. + +%% set_to_list(OrdSet) +%% Return the elements in OrdSet as a list. + +set_to_list(S) -> + S. + +%% list_to_set(List) +%% Build an ordered set from the elements in List. + +list_to_set([E|Es]) -> + add_element(E, list_to_set(Es)); +list_to_set([]) -> + []. + +%% is_element(Element, OrdSet) +%% Return 'true' if Element is an element of OrdSet, else 'false'. + +is_element(E, [H|Es]) when E < H -> + false; +is_element(E, [H|Es]) when E == H -> + true; +is_element(E, [H|Es]) when E > H -> + is_element(E, Es); +is_element(E, []) -> + false. + +%% add_element(Element, OrdSet) +%% Return OrdSet with Element inserted in it. + +add_element(E, [H|Es]) when E < H -> + [E,H|Es]; +add_element(E, [H|Es]) when E == H -> + [H|Es]; +add_element(E, [H|Es]) when E > H -> + [H|add_element(E, Es)]; +add_element(E, []) -> + [E]. + +%% del_element(Element, OrdSet) +%% Return OrdSet but with Element removed. + +del_element(E, [H|Es]) when E < H -> + [H|Es]; +del_element(E, [H|Es]) when E == H -> + Es; +del_element(E, [H|Es]) when E > H -> + [H|del_element(E, Es)]; +del_element(E, []) -> + []. + +%% union(Set1, Set2) +%% Return the union of Set1 and Set2. + +union([H1|Es1], [H2|Es2]) when H1 < H2 -> + [H1|union(Es1, [H2|Es2])]; +union([H1|Es1], [H2|Es2]) when H1 == H2 -> + [H1|union(Es1, Es2)]; +union([H1|Es1], [H2|Es2]) when H1 > H2 -> + [H2|union([H1|Es1], Es2)]; +union([], Es2) -> + Es2; +union(Es1, []) -> + Es1. + +%% union(OrdSets) +%% Return the union of the list of sets. + +union([S1,S2|Ss]) -> + union1(union(S1,S2), Ss); +union([S]) -> + S; +union([]) -> + []. + +union1(S1, [S2|Ss]) -> + union1(union(S1, S2), Ss); +union1(S1, []) -> + S1. + +%% intersection(Set1, Set2) +%% Return the intersection of Set1 and Set2. + +intersection([H1|Es1], [H2|Es2]) when H1 < H2 -> + intersection(Es1, [H2|Es2]); +intersection([H1|Es1], [H2|Es2]) when H1 == H2 -> + [H1|intersection(Es1, Es2)]; +intersection([H1|Es1], [H2|Es2]) when H1 > H2 -> + intersection([H1|Es1], Es2); +intersection([], Es2) -> + []; +intersection(Es1, []) -> + []. + +%% intersection(OrdSets) +%% Return the intersection of the list of sets. + +intersection([S1,S2|Ss]) -> + intersection1(intersection(S1,S2), Ss); +intersection([S]) -> + S; +intersection([]) -> + []. + +intersection1(S1, [S2|Ss]) -> + intersection1(intersection(S1, S2), Ss); +intersection1(S1, []) -> + S1. + +%% subtract(Set1, Set2) +%% Return all and only the elements of Set1 which are not also in Set2. + +subtract([H1|Es1], [H2|Es2]) when H1 < H2 -> + [H1|subtract(Es1, [H2|Es2])]; +subtract([H1|Es1], [H2|Es2]) when H1 == H2 -> + subtract(Es1, Es2); +subtract([H1|Es1], [H2|Es2]) when H1 > H2 -> + subtract([H1|Es1], Es2); +subtract([], Es2) -> + []; +subtract(Es1, []) -> + Es1. + +%% subset(Set1, Set2) +%% Return 'true' when every element of Set1 is also a member of Set2, +%% else 'false'. + +subset([H1|Es1], [H2|Es2]) when H1 < H2 -> %H1 not in Set2 + false; +subset([H1|Es1], [H2|Es2]) when H1 == H2 -> + subset(Es1, Es2); +subset([H1|Es1], [H2|Es2]) when H1 > H2 -> + subset([H1|Es1], Es2); +subset([], Es2) -> + true; +subset(Es1, []) -> + false. diff --git a/lib/debugger/test/int_SUITE_data/test.erl b/lib/debugger/test/int_SUITE_data/test.erl new file mode 100644 index 0000000000..679b266380 --- /dev/null +++ b/lib/debugger/test/int_SUITE_data/test.erl @@ -0,0 +1,152 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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(test). + +%%-compile(export_all). +-export([test1/0, + test2/0, + test3/0, + test4/0, + test5/0, + test6/1, + test7/0, + test8/1, + test9/0, + test10/0, + test11/0 + ]). + + +-export([test9_server/1]). + + +test1() -> + R1 = lists1:reverse("retep"), + R2 = ordsets1:list_to_set([b,c,a,2,4,1]), + R3 = lists1:reverse("nilo"), + {R1,R2, R3}. + +test2() -> + R1 = spawn(lists1,reverse,["retep"]), + R2 = spawn(ordsets1,list_to_set,[[b,c,a,2,4,1]]), + R3 = spawn(lists1,reverse,["nilo"]), + {R1,R2, R3}. + + +test3() -> + A = a, + Pid = spawn(?MODULE, test1,[]), + B = b, + {A, B, Pid}. + +test4() -> + Pid = spawn(?MODULE, test1,[]), + A = a, + B = b, + {A, B, Pid}. +test5() -> + L1 = [a,b,c], + L = length(L1), + A = a, + B = b, + {A, B, L, L1}. + + + +test6(0) -> + ok; +test6(N) when N>0 -> + spawn(lists1,reverse,["adolfiparisrorsirapifloda"]), + test6(N-1). + + +test7() -> + CurDirReturn = file:get_cwd(), + {ok, CurDir} = CurDirReturn, + DirListReturn = file:list_dir(CurDir), + {ok, DirList} = DirListReturn, + io:format("~w~n",[DirList]). + + +test8(List) -> + %% foo + %%bar + %% foo + %%bar + %% foo + %%bar + %% foo + %%bar + + L2 = [gamma|List], + {L2, List}. + +test9() -> + S1 = spawn(?MODULE, test9_server,[self()]), + S2 = spawn(?MODULE, test9_server,[bongo]), + S3 = spawn(?MODULE, test9_server,[42]), + + test9_loop(S1,S2,S3). + +test9_loop(S1,S2,S3) -> + receive + {S1, hej} -> + io:format("S1 ~n"), + test9_loop(S1,S2,S3); + {S2, hej} -> + io:format("S2 ~n"), + test9_loop(S1,S2,S3); + {S3, hej} -> + io:format("S3 ~n"), + test9_loop(S1,S2,S3) + end. + + +test9_server(Pid) -> + io:format("started server: ~p~n",[Pid]), + test9_server1(Pid). + +test9_server1(Pid) -> + Pad = {pad, Pid}, + test9_server2(Pad). + +test9_server2(Pad) -> + {pad, Pid} = Pad, + Pid ! {self(), hej}. + + + + + +test10() -> + receive + X -> + done + after 20000 -> + timeout + end. + +test11() -> + receive + X -> + done + end. diff --git a/lib/debugger/test/int_SUITE_data/test1.erl b/lib/debugger/test/int_SUITE_data/test1.erl new file mode 100644 index 0000000000..a93416cbac --- /dev/null +++ b/lib/debugger/test/int_SUITE_data/test1.erl @@ -0,0 +1,34 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. 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(test1). + +-compile(export_all). + + +foo() -> + A = [1,2,3], + B = [a,b,c], + C = [d,e,f], + D = my_lists:append(A,B), + E = my_lists:append(D,C), + F = [1], + G = my_lists:append(E,F), + {A,B,C,D,E,F,G}. diff --git a/lib/debugger/test/int_break_SUITE.erl b/lib/debugger/test/int_break_SUITE.erl new file mode 100644 index 0000000000..b7b3c5598a --- /dev/null +++ b/lib/debugger/test/int_break_SUITE.erl @@ -0,0 +1,92 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2010. 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(int_break_SUITE). + +%% Test break points. + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + basic/1,cleanup/1]). + +-export([auto_attach/1]). + +all(suite) -> + [basic,cleanup]. + +init_per_testcase(_Case, Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line Mod = ordsets1, + ?line {module,Mod} = int:i(filename:join(DataDir, Mod)), + ?line ok = io:format("Interpreted modules: ~p", [int:interpreted()]), + ?line Dog = test_server:timetrap(?t:minutes(0.5)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + ?line ok = io:format("Interpreted modules: ~p", [int:interpreted()]), + ?line Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +basic(doc) -> "Tests setting a few break points."; +basic(suite) -> []; +basic(Config) when list(Config) -> + ?line int:auto_attach([init], {?MODULE,auto_attach}), + ?line S1 = [] = ordsets1:new_set(), + ?line ok = i:ib(ordsets1, 86), + ?line S2 = [xxx] = ordsets1:add_element(xxx, S1), + ?line S3 = [xxx,y] = ordsets1:add_element(y, S2), + ?line ok = i:ib(ordsets1, union, 2), + ?line [xxx,y,z] = ordsets1:union(S3, [z]), + ok. + +cleanup(doc) -> "Make sure that the auto-attach flag is turned off."; +cleanup(suite) -> []; +cleanup(Config) when list(Config) -> + ?line int:auto_attach(false), + ok. + +auto_attach(Pid) -> + {ok, Meta} = int:attached(Pid), + io:format("Pid = ~p; Meta = ~p", [Pid,Meta]), + link(Meta), + attach_loop(Pid, Meta). + +attach_loop(Pid, Meta) -> + receive + Msg -> + io:format("attached: ~p", [Msg]), + attach_cmd(Msg, Pid, Meta), + attach_loop(Pid, Meta) + end. + +attach_cmd({Meta,{break_at,ordsets1,36,2}}, _Pid, Meta) -> + int:meta(Meta, continue); +attach_cmd({Meta,{break_at,ordsets1,87,_}}, _Pid, Meta) -> + int:meta(Meta, continue); +attach_cmd({Meta,{break_at,ordsets1,89,_}}, _Pid, Meta) -> + int:meta(Meta, continue); +attach_cmd({Meta,{break_at,ordsets1,Line,_}}, _Pid, Meta) when 107 =< Line, Line =< 115 -> + int:meta(Meta, finish); +attach_cmd({Meta,{break_at,_Mod,_Line,_Other}}=Cmd, _Pid, Meta) -> + io:format("attached: no action for ~p", [Cmd]); +attach_cmd(_, _Pid, _Meta) -> + ok. diff --git a/lib/debugger/test/int_break_SUITE_data/Makefile.src b/lib/debugger/test/int_break_SUITE_data/Makefile.src new file mode 100644 index 0000000000..0d1ee35a67 --- /dev/null +++ b/lib/debugger/test/int_break_SUITE_data/Makefile.src @@ -0,0 +1,25 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2010. 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% +# + +EFLAGS=+debug_info + +all: ordsets1.@EMULATOR@ + +ordsets1.@EMULATOR@: ordsets1.erl + erlc $(EFLAGS) ordsets1.erl diff --git a/lib/debugger/test/int_break_SUITE_data/ordsets1.erl b/lib/debugger/test/int_break_SUITE_data/ordsets1.erl new file mode 100644 index 0000000000..6300c6097c --- /dev/null +++ b/lib/debugger/test/int_break_SUITE_data/ordsets1.erl @@ -0,0 +1,188 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2010. 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% +%% + +%% +%% Purpose : Functions for manipulating sets as ordered lists. + +%% As yet some of these are not very efficiently written. + +-module(ordsets1). + +-export([new_set/0,is_set/1,set_to_list/1,list_to_set/1]). +-export([is_element/2,add_element/2,del_element/2]). +-export([union/2,union/1,intersection/2,intersection/1]). +-export([subtract/2,subset/2]). + +%% new_set() +%% Return a new empty ordered set. + +new_set() -> + []. + +%% is_set(Set) +%% Return 'true' if Set is an ordered set of elements, else 'false'. + +is_set([E|Es]) -> + is_set(Es, E); +is_set([]) -> + true. + +is_set([E2|Es], E1) when E1 < E2 -> + is_set(Es, E2); +is_set([E2|Es], E1) -> + false; +is_set([], E1) -> + true. + +%% set_to_list(OrdSet) +%% Return the elements in OrdSet as a list. + +set_to_list(S) -> + S. + +%% list_to_set(List) +%% Build an ordered set from the elements in List. + +list_to_set([E|Es]) -> + add_element(E, list_to_set(Es)); +list_to_set([]) -> + []. + +%% is_element(Element, OrdSet) +%% Return 'true' if Element is an element of OrdSet, else 'false'. + +is_element(E, [H|Es]) when E < H -> + false; +is_element(E, [H|Es]) when E == H -> + true; +is_element(E, [H|Es]) when E > H -> + is_element(E, Es); +is_element(E, []) -> + false. + +%% add_element(Element, OrdSet) +%% Return OrdSet with Element inserted in it. + +add_element(E, [H|_]=Es) when E < H -> + [E|Es]; +add_element(E, [H|_]=Es) when E == H -> + Es; +add_element(E, [H|Es]) when E > H -> + [H|add_element(E, Es)]; +add_element(E, []) -> + [E]. + +%% del_element(Element, OrdSet) +%% Return OrdSet but with Element removed. + +del_element(E, [H|_]=Es) when E < H -> + Es; +del_element(E, [H|Es]) when E == H -> + Es; +del_element(E, [H|Es]) when E > H -> + [H|del_element(E, Es)]; +del_element(E, []) -> + []. + +%% union(Set1, Set2) +%% Return the union of Set1 and Set2. + +union([H1|Es1], [H2|_]=Es2) when H1 < H2 -> + [H1|union(Es1, Es2)]; +union([H1|Es1], [H2|Es2]) when H1 == H2 -> + [H1|union(Es1, Es2)]; +union([H1|_]=Es1, [H2|Es2]) when H1 > H2 -> + [H2|union(Es1, Es2)]; +union([], Es2) -> + Es2; +union(Es1, []) -> + Es1. + +%% union(OrdSets) +%% Return the union of the list of sets. + +union([S1,S2|Ss]) -> + union1(union(S1,S2), Ss); +union([S]) -> + S; +union([]) -> + []. + +union1(S1, [S2|Ss]) -> + union1(union(S1, S2), Ss); +union1(S1, []) -> + S1. + +%% intersection(Set1, Set2) +%% Return the intersection of Set1 and Set2. + +intersection([H1|Es1], [H2|_]=Es2) when H1 < H2 -> + intersection(Es1, Es2); +intersection([H1|Es1], [H2|Es2]) when H1 == H2 -> + [H1|intersection(Es1, Es2)]; +intersection([H1|_]=Es1, [H2|Es2]) when H1 > H2 -> + intersection(Es1, Es2); +intersection([], Es2) -> + []; +intersection(Es1, []) -> + []. + +%% intersection(OrdSets) +%% Return the intersection of the list of sets. + +intersection([S1,S2|Ss]) -> + intersection1(intersection(S1,S2), Ss); +intersection([S]) -> + S; +intersection([]) -> + []. + +intersection1(S1, [S2|Ss]) -> + intersection1(intersection(S1, S2), Ss); +intersection1(S1, []) -> + S1. + +%% subtract(Set1, Set2) +%% Return all and only the elements of Set1 which are not also in Set2. + +subtract([H1|Es1], [H2|_]=Es2) when H1 < H2 -> + [H1|subtract(Es1, Es2)]; +subtract([H1|Es1], [H2|Es2]) when H1 == H2 -> + subtract(Es1, Es2); +subtract([H1|_]=Es1, [H2|Es2]) when H1 > H2 -> + subtract(Es1, Es2); +subtract([], Es2) -> + []; +subtract(Es1, []) -> + Es1. + +%% subset(Set1, Set2) +%% Return 'true' when every element of Set1 is also a member of Set2, +%% else 'false'. + +subset([H1|Es1], [H2|Es2]) when H1 < H2 -> %H1 not in Set2 + false; +subset([H1|Es1], [H2|Es2]) when H1 == H2 -> + subset(Es1, Es2); +subset([H1|Es1], [H2|Es2]) when H1 > H2 -> + subset([H1|Es1], Es2); +subset([], Es2) -> + true; +subset(Es1, []) -> + false. diff --git a/lib/debugger/test/int_eval_SUITE.erl b/lib/debugger/test/int_eval_SUITE.erl new file mode 100644 index 0000000000..19b006e750 --- /dev/null +++ b/lib/debugger/test/int_eval_SUITE.erl @@ -0,0 +1,277 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2010. 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(int_eval_SUITE). + +%% Purpose: Deeper test of the evaluator. + +-export([all/1,init_per_testcase/2, fin_per_testcase/2, + bifs_outside_erlang/1, spawning/1, applying/1, + catch_and_throw/1, external_call/1, test_module_info/1, + apply_interpreted_fun/1, apply_uninterpreted_fun/1, + interpreted_exit/1, otp_8310/1]). + +%% Helpers. +-export([applier/3]). + +-define(IM, my_int_eval_module). + +-include("test_server.hrl"). + +all(suite) -> + [bifs_outside_erlang,spawning,applying,catch_and_throw, + external_call,test_module_info, + apply_interpreted_fun,apply_uninterpreted_fun, + interpreted_exit, otp_8310]. + +init_per_testcase(_Case, Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {module,?IM} = int:i(filename:join(DataDir, ?IM)), + ?line ok = io:format("Interpreted modules: ~p",[int:interpreted()]), + {ok, Dog} = timer:apply_after(timer:minutes(1), + erlang, exit, [self(), kill]), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + ok = io:format("Interpreted modules: ~p", [int:interpreted()]), + Dog = ?config(watchdog, Config), + timer:cancel(Dog), + ok. + +bifs_outside_erlang(doc) -> + "Test that BIFs outside the erlang module are correctly evaluated."; +bifs_outside_erlang(suite) -> + []; +bifs_outside_erlang(Config) when is_list(Config) -> + Fun = fun() -> + Id = ?IM:ets_new(), + Self = self(), + ok = io:format("Self: ~p", [Self]), + Info = ets:info(Id), + {owner,Self} = lists:nth(2, Info), + %% Was + %% {owner,Self} = element(2, Info), + %% in R10B. + ?IM:ets_delete(Id), + ok + end, + ?line ok = spawn_eval(Fun), + ok. + +spawning(doc) -> + "Try evalutate spawn_link/3."; +spawning(suite) -> + []; +spawning(Config) when is_list(Config) -> + ?line ok = spawn_eval(fun() -> ?IM:spawn_test() end). + +applying(doc) -> + "Try various sorts of applies."; +applying(suite) -> + []; +applying(Config) when is_list(Config) -> + Fun = fun({number,X}, {number,Y}) -> X+Y end, + ?line ok = spawn_eval(fun() -> ?IM:apply_test(Fun) end). + +catch_and_throw(doc) -> + "Test catch and throw/1."; +catch_and_throw(suite) -> + []; +catch_and_throw(Config) when is_list(Config) -> + {a,ball} = spawn_eval(fun() -> ok = ?IM:catch_a_ball(), + catch ?IM:throw_a_ball() end), + + %% Throw and catch without any extra outer catch. + + ?line process_flag(trap_exit, true), + ?line Pid1 = spawn_link(fun() -> exit(?IM:catch_a_ball()) end), + receive + {'EXIT',Pid1,ok} -> ok; + {'EXIT',Pid1,Bad1} -> ?line ?t:fail({bad_message,Bad1}) + after 5000 -> + ?line ?t:fail(timeout) + end, + + + %% Throw without catch. + + ?line Pid2 = spawn_link(fun() -> ?IM:throw_a_ball() end), + receive + {'EXIT',Pid2,{{nocatch,{a,ball}},[_|_]}} -> ok; + {'EXIT',Pid2,Bad2} -> ?line ?t:fail({bad_message,Bad2}) + after 5000 -> + ?line ?t:fail(timeout) + end, + + ?line ok = ?IM:more_catch(fun(_) -> ?IM:exit_me() end), + ?line ok = ?IM:more_catch(fun(_) -> exit({unint, exit}) end), + ?line {a, ball} = ?IM:more_catch(fun(_) -> ?IM:throw_a_ball() end), + ?line {b, ball} = ?IM:more_catch(fun(_) -> throw({b,ball}) end), + + ExitInt = {'EXIT',{int,exit}}, + ExitU = {'EXIT',{unint,exit}}, + + ?line ExitInt = (catch ?IM:more_nocatch(fun(_) -> ?IM:exit_me() end)), + ?line ExitU = (catch ?IM:more_nocatch(fun(_) -> exit({unint, exit}) end)), + ?line {a, ball} = (catch {error, ?IM:more_nocatch(fun(_) -> ?IM:throw_a_ball() end)}), + ?line {b, ball} = (catch {error, ?IM:more_nocatch(fun(_) -> throw({b,ball}) end)}), + ok. + +external_call(doc) -> + "Test external calls."; +external_call(suite) -> + []; +external_call(Config) when is_list(Config) -> + ?line ok = spawn_eval(fun() -> ?IM:external_call_test({some,stupid,data}) end). + +test_module_info(doc) -> + "Test the module_info/0,1 functions."; +test_module_info(suite) -> + []; +test_module_info(Config) when is_list(Config) -> + ?line ModInfo = ?IM:module_info(), + ?line {value,{exports,Exp}} = lists:keysearch(exports, 1, ModInfo), + ?line {value,{attributes,Attr}} = lists:keysearch(attributes, 1, ModInfo), + ?line Exp = ?IM:module_info(exports), + ?line Attr = ?IM:module_info(attributes), + ?line {value,{stupid_attribute,[{a,b}]}} = + lists:keysearch(stupid_attribute, 1, Attr), + + %% Check exports using a list comprehension in the module itself. + + ?line ok = ?IM:check_exports(Exp), + + %% Call module_info/0,1 from the module itself. + + ?line ok = ?IM:check_module_info(ModInfo, Exp), + + ok. + +apply_interpreted_fun(doc) -> + "Apply a fun defined in interpreted code."; +apply_interpreted_fun(suite) -> []; +apply_interpreted_fun(Config) when is_list(Config) -> + + %% Called from uninterpreted code + ?line F1 = spawn_eval(fun() -> ?IM:give_me_a_fun_0() end), + ?line perfectly_alright = spawn_eval(fun() -> F1() end), + ?line ATerm = {a,term}, + ?line F2 = spawn_eval(fun() -> ?IM:give_me_a_fun_0(ATerm) end), + ?line {ok,ATerm} = spawn_eval(fun() -> F2() end), + + %% Called from uninterpreted code, badarity + ?line {'EXIT',{{badarity,{F1,[snape]}},[{?MODULE,_,_}|_]}} = + spawn_eval(fun() -> F1(snape) end), + + %% Called from uninterpreted code, error in fun + ?line F3 = spawn_eval(fun() -> ?IM:give_me_a_bad_fun() end), + ?line {'EXIT',{snape,[{?IM,_FunName,_}|_]}} = + spawn_eval(fun() -> F3(snape) end), + + %% Called from within interpreted code + ?line perfectly_alright = spawn_eval(fun() -> ?IM:do_apply(F1) end), + + %% Called from within interpreted code, badarity + ?line {'EXIT',{{badarity,{F1,[snape]}},[{?IM,do_apply,_}|_]}} = + spawn_eval(fun() -> ?IM:do_apply(F1, snape) end), + + %% Called from within interpreted code, error in fun + ?line {'EXIT',{snape,[{?IM,_FunName,_}|_]}} = + spawn_eval(fun() -> ?IM:do_apply(F3, snape) end), + + %% Try some more complex funs. + ?line F4 = ?IM:give_me_a_fun_1(14, 42), + ?line {false,yes,yeah,false} = + F4({{1,nope},{14,yes},{42,yeah},{100,forget_it}}), + ?line [this_is_ok,me_too] = + F4([{-24,no_way},{15,this_is_ok},{1333,forget_me},{37,me_too}]), + + %% OTP-5837 + %% Try fun with guard containing variable bound in environment + ?line [yes,no,no,no] = ?IM:otp_5837(1), + + ok. + +apply_uninterpreted_fun(doc) -> + "Apply a fun defined outside interpreted code."; +apply_uninterpreted_fun(suite) -> []; +apply_uninterpreted_fun(Config) when is_list(Config) -> + + ?line F1 = fun(snape) -> + erlang:error(snape); + (_Arg) -> + perfectly_alright + end, + + %% Ok + ?line perfectly_alright = + spawn_eval(fun() -> ?IM:do_apply(F1, any_arg) end), + + %% Badarity (evaluated in dbg_debugged, which calls erlang:apply/2) + ?line {'EXIT',{{badarity,{F1,[]}},[{erlang,apply,_}|_]}} = + spawn_eval(fun() -> ?IM:do_apply(F1) end), + + %% Error in fun + ?line {'EXIT',{snape,[{?MODULE,_FunName,_}|_]}} = + spawn_eval(fun() -> ?IM:do_apply(F1, snape) end), + + ok. + +%% +%% Try executing an interpreted exit/1 call. +%% + +interpreted_exit(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line Reason = make_ref(), + ?line Pid = spawn_link(fun() -> ?IM:please_call_exit(Reason) end), + ?line receive + {'EXIT',Pid,Reason} -> + ok; + {'EXIT',Pid,BadReason} -> + ?line ?t:fail({bad_message,BadReason}) + after 10000 -> + ?line ?t:fail(timeout) + end, + ok. + +otp_8310(doc) -> + "OTP-8310. Bugfixes lc/bc and andalso/orelse."; +otp_8310(Config) when is_list(Config) -> + ?line ok = ?IM:otp_8310(), + ok. + +applier(M, F, A) -> + Res = apply(M, F, A), + io:format("~p:~p(~p) => ~p\n", [M,F,A,Res]), + Res. + +%% +%% Evaluate in another process, to prevent the test_case process to become +%% interpreted. +%% + +spawn_eval(Fun) -> + Self = self(), + spawn_link(fun() -> Self ! (catch Fun()) end), + receive + Result -> + Result + end. diff --git a/lib/debugger/test/int_eval_SUITE_data/Makefile.src b/lib/debugger/test/int_eval_SUITE_data/Makefile.src new file mode 100644 index 0000000000..28a1432157 --- /dev/null +++ b/lib/debugger/test/int_eval_SUITE_data/Makefile.src @@ -0,0 +1,26 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2010. 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% +# + + +EFLAGS=+debug_info + +all: my_int_eval_module.@EMULATOR@ + +my_int_eval_module.@EMULATOR@: my_int_eval_module.erl + erlc $(EFLAGS) my_int_eval_module.erl diff --git a/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl new file mode 100644 index 0000000000..997ee6e17d --- /dev/null +++ b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl @@ -0,0 +1,245 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2010. 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(my_int_eval_module). +-stupid_attribute({a,b}). + +-export([ets_new/0,ets_delete/1,spawn_test/0,apply_test/1,external_call_test/1]). +-export([check_exports/1,check_module_info/2]). +-export([give_me_a_fun_0/0,give_me_a_fun_0/1,give_me_a_fun_1/2, + give_me_a_bad_fun/0, do_apply/1, do_apply/2]). +-export([please_call_exit/1,i_will_do_the_exit/1]). +-export([more_catch/1,more_nocatch/1,exit_me/0]). +-export([f/1, f_try/1, f_catch/1]). +-export([otp_5837/1, otp_8310/0]). + +%% Internal exports. +-export([echo/2,my_subtract/2,catch_a_ball/0,throw_a_ball/0]). +-export([i_am_exported/1]). + +-import(lists, [member/2]). + +-define(line,put(test_server_loc,{?MODULE,?LINE}),). +-define(t,test_server). +-define(m,test_server:match). +-define(config,test_server:lookup_config). + +ets_new() -> + Id = ets:new(my_int_eval_table, [private]), + Id. + +ets_delete(Tab) -> + ets:delete(Tab). + +%% Spawning. + +spawn_test() -> + Term = {a,tuple}, + Pid = spawn_link(?MODULE, echo, [self(),Term]), + receive + {result,Pid,Term} -> ok; + Other -> {bad_response,Other} + after 5000 -> + timeout + end. + +echo(Parent, Term) -> + Parent ! {result,self(),Term}. + +%% Applying. + +apply_test(Fun) -> + 42 = Fun(number(2), number(40)), + 12 = apply(Fun, [number(7),number(5)]), + + Mod = module(), + Func = func(), + [a] = Mod:my_subtract(same([a,b,c]), same([b,c])), + [a,b] = Mod:Func(same([a,b,c]), same([c])), + [a,b,d] = ?MODULE:Func(same([a,b,c,d]), same([c])), + [d,e] = apply(Mod, Func, [same([d,e,f]), same([f])]), + [3] = apply(?MODULE, Func, [same([3,4]),same([4])]), + + %% This is obsolete, but it should work anyway. + HomeMadeFun = {?MODULE,my_subtract}, + [a] = HomeMadeFun(same([a,x,c]), same([x,c])), + [x] = apply(HomeMadeFun, [[x,y],[y,z]]), + + ok. + +number(X) -> {number,X}. +module() -> ?MODULE. +func() -> my_subtract. +same(X) -> X. + +my_subtract(X, Y) -> X -- Y. + +%% Catch and throw. + +catch_a_ball() -> + {a,ball} = (catch throw_a_ball()), + ok. + +throw_a_ball() -> + throw({a,ball}), + not_ok. + +exit_me() -> + exit({int,exit}). + +more_catch(Fun) -> + case catch lists:filter(Fun, [a]) of + {'EXIT', {_, exit}} -> + ok; + Else -> Else + end. + +more_nocatch(Fun) -> + lists:filter(Fun, [a]). + +%% External calls. + +external_call_test(Data) -> + {'EXIT',{undef,[{?MODULE,not_exported,[42,Data]}|_]}} = + (catch ?MODULE:not_exported(42, Data)), + {yes,Data} = i_am_exported(Data), + {yes,Data} = ?MODULE:i_am_exported(Data), + + %% Excercise the function cache in the interpreter. + + {ok,Data,[a,b]} = not_exported(Data, [a,b]), + {yes,Data} = i_am_exported(Data), + {ok,Data,[a,b]} = not_exported(Data, [a,b]), + {'EXIT',{undef,[{?MODULE,not_exported,[7,Data]}|_]}} = + (catch ?MODULE:not_exported(7, Data)), + {yes,Data} = ?MODULE:i_am_exported(Data), + ok. + +not_exported(N, D) -> + {ok,N,D}. + +i_am_exported(D) -> + {yes,D}. + +%% The module_info/0,1 functions and list comprehensions (funs). + +check_exports(Exp) -> + %% Check the structure of the export list and that there are more + %% than 4 elements. + + Exp = [{F,A} || {F,A} <- Exp, erlang:is_atom(F), erlang:is_integer(A)], + case length(Exp) of + Len when Len > 4 -> ok + end. + +check_module_info(ModInfo, Exports) -> + ModInfo = module_info(), + Exports = module_info(exports), + ok. + +%% Testcase apply_interpreted_fun/1. + +give_me_a_fun_0() -> + fun() -> perfectly_alright end. + +give_me_a_fun_0(Term) -> + fun() -> {ok,Term} end. + +give_me_a_fun_1(Min, Max) -> + Seq = lists:seq(Min, Max), + fun (L) when list(L) -> + [Info || {Key,Info} <- L, lists:member(Key, Seq)]; + (T) when tuple(T) -> + L = tuple_to_list(T), + F = fun({Key,Info}) -> + case lists:member(Key, Seq) of + true -> Info; + false -> false + end + end, + list_to_tuple(lists:map(F, L)) + end. + +give_me_a_bad_fun() -> + fun(Arg) -> erlang:error(Arg) end. + +do_apply(Fun) -> + Fun(). +do_apply(Fun, Arg) -> + Fun(Arg). + + +please_call_exit(Reason) -> + put(asked_to_call_exit, Reason), + put(will_call_my_good_friend, ''), + Res = int_eval_SUITE:applier(?MODULE, i_will_do_the_exit, [Reason]), + + %% We don't want a tail-recursive call above. + io:format("Returned from exit/1 -- how strange\n"). + +i_will_do_the_exit(Reason) -> + exit(Reason). + +f(Arg) -> + g(Arg). + +f_try(Arg) -> + try g(Arg) + catch + Class:Reason -> + {Class, Reason} + end. + +f_catch(Arg) -> + catch g(Arg). + +g({error, Reason}) -> + erlang:error(Reason); +g({exit, Reason}) -> + erlang:exit(Reason); +g({throw, Reason}) -> + erlang:throw(Reason); +g(Value) -> + Value. + +otp_5837(N) -> + n(N). + +n(N) -> + lists:map(fun(X) when N==X -> + yes; + (_) -> + no + end, + [1,2,3,4]). + +otp_8310() -> + a = if (false orelse a) =:= a -> a; true -> b end, + F1 = fun() -> a end, + {'EXIT',{{bad_filter,a},_}} = + (catch {a, [X || X <- [1,2,3], _ = F1()]}), + F2 = fun() -> << 3:8 >> end, + {'EXIT',{{bad_filter,<<3>>},_}} = + (catch {a, << << X >> || << X >> <= << 7:8 >>,_ = F2() >>}), + {'EXIT',{{bad_generator,a},_}} = + (catch {a, [X || X <- a]}), + {'EXIT',{{bad_generator,b},_}} = + (catch {a, << <<X>> || << X >> <= b >>}), + ok. diff --git a/lib/debugger/test/lc_SUITE.erl b/lib/debugger/test/lc_SUITE.erl new file mode 100644 index 0000000000..a22a689ec8 --- /dev/null +++ b/lib/debugger/test/lc_SUITE.erl @@ -0,0 +1,74 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2010. 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(lc_SUITE). + +-author('[email protected]'). +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + basic/1]). + +-include("test_server.hrl"). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [basic]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +basic(Config) when list(Config) -> + ?line L0 = lists:seq(1, 10), + ?line L1 = my_map(fun(X) -> {x,X} end, L0), + ?line L1 = [{x,X} || X <- L0], + ?line L0 = my_map(fun({x,X}) -> X end, L1), + ?line [1,2,3,4,5] = [X || X <- L0, X < 6], + ?line [4,5,6] = [X || X <- L0, X > 3, X < 7], + ?line [] = [X || X <- L0, X > 32, X < 7], + ?line [1,3,5,7,9] = [X || X <- L0, odd(X)], + + %% Error cases. + ?line [] = [X || X <- L1, X+1 < 2], + ?line [] = [{xx,X} || X <- L0, element(2, X) == no_no_no], + ?line {'EXIT',_} = (catch [X || X <- L1, odd(X)]), + + ok. + +my_map(F, L) -> + [F(X) || X <- L]. + +odd(X) -> + X rem 2 == 1. diff --git a/lib/debugger/test/record_SUITE.erl b/lib/debugger/test/record_SUITE.erl new file mode 100644 index 0000000000..06fd01555e --- /dev/null +++ b/lib/debugger/test/record_SUITE.erl @@ -0,0 +1,252 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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% +%% + +%% +%%% Purpose : Test records. + +-module(record_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + errors/1,record_test/1,eval_once/1]). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [errors,record_test,eval_once]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +-record(foo, {a,b,c,d}). +-record(bar, {a,b,c,d}). +-record(barf, {a,b,c,d,e}). + +errors(Config) when is_list(Config) -> + Foo = #foo{a=1,b=2,c=3,d=4}, + ?line #foo{a=19,b=42,c=3,d=4} = update_foo(Foo, 19, 42), + + ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19)), + ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35)), + ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17)), + ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)), + + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19)), + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35)), + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17)), + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)), + ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, + 35, 17, 42, -2)), + + ok. + +update_foo(#foo{}=R, A, B) -> + R#foo{a=A,b=B}. + +update_foo_bar(#foo{}=R, A) -> + R#bar{a=A}. + +update_foo_bar(#foo{}=R, A, _B) -> + R#bar{a=A,b=A}. + +update_foo_bar(#foo{}=R, A, _B, C) -> + R#bar{a=A,b=A,c=C}. + +update_foo_bar(#foo{}=R, A, _B, C, D) -> + R#bar{a=A,b=A,c=C,d=D}. + +update_foo_barf(#foo{}=R, A) -> + R#barf{a=A}. + +update_foo_barf(#foo{}=R, A, _B) -> + R#barf{a=A,b=A}. + +update_foo_barf(#foo{}=R, A, _B, C) -> + R#barf{a=A,b=A,c=C}. + +update_foo_barf(#foo{}=R, A, _B, C, D) -> + R#barf{a=A,b=A,c=C,d=D}. + +update_foo_barf(#foo{}=R, A, _B, C, D, E) -> + R#barf{a=A,b=A,c=C,d=D,e=E}. + + +-define(TrueGuard(Expr), if Expr -> ok; true -> ?t:fail() end). +-define(FalseGuard(Expr), if Expr -> ?t:fail(); true -> ok end). + +record_test(Config) when is_list(Config) -> + ?line true = is_record(#foo{}, foo), + ?line false = is_record(#foo{}, barf), + ?line false = is_record({foo}, foo), + + ?line true = erlang:is_record(#foo{}, foo), + ?line false = erlang:is_record(#foo{}, barf), + ?line false = erlang:is_record({foo}, foo), + + ?line false = is_record([], foo), + ?line false = is_record(Config, foo), + + ?line ?TrueGuard(is_record(#foo{}, foo)), + ?line ?FalseGuard(is_record(#foo{}, barf)), + ?line ?FalseGuard(is_record({foo}, foo)), + + ?line ?TrueGuard(erlang:is_record(#foo{}, foo)), + ?line ?FalseGuard(erlang:is_record(#foo{}, barf)), + ?line ?FalseGuard(erlang:is_record({foo}, foo)), + + ?line ?FalseGuard(is_record([], foo)), + ?line ?FalseGuard(is_record(Config, foo)), + + %% 'not is_record/2' to test guard optimization. + + ?line ?FalseGuard(not is_record(#foo{}, foo)), + ?line ?TrueGuard(not is_record(#foo{}, barf)), + ?line ?TrueGuard(not is_record({foo}, foo)), + + ?line ?FalseGuard(not erlang:is_record(#foo{}, foo)), + ?line ?TrueGuard(not erlang:is_record(#foo{}, barf)), + ?line ?TrueGuard(not erlang:is_record({foo}, foo)), + + Foo = id(#foo{}), + ?line ?FalseGuard(not erlang:is_record(Foo, foo)), + ?line ?TrueGuard(not erlang:is_record(Foo, barf)), + + ?line ?TrueGuard(not is_record(Config, foo)), + + ?line ?TrueGuard(not is_record(a, foo)), + ?line ?TrueGuard(not is_record([], foo)), + + %% Pass non-literal first argument. + + ?line true = is_record(id(#foo{}), foo), + ?line false = is_record(id(#foo{}), barf), + ?line false = is_record(id({foo}), foo), + + ?line true = erlang:is_record(id(#foo{}), foo), + ?line false = erlang:is_record(id(#foo{}), barf), + ?line false = erlang:is_record(id({foo}), foo), + + NoRec1 = id(blurf), + NoRec2 = id([]), + + ?line ?TrueGuard(not is_record(NoRec1, foo)), + ?line ?TrueGuard(not is_record(NoRec2, foo)), + + %% Force the use of guard bifs by using the 'xor' operation. + + False = id(false), + ?line ?TrueGuard(is_record(#foo{}, foo) xor False), + ?line ?FalseGuard(is_record(#foo{}, barf) xor False), + ?line ?FalseGuard(is_record({foo}, foo) xor False ), + + ?line ?TrueGuard(is_record(Foo, foo) xor False), + ?line ?FalseGuard(is_record(Foo, barf) xor False), + + + %% Implicit guards by using a list comprehension. + + List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]), + + ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo)], + ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar)], + ?line [1,#foo{a=2},3,5,#foo{a=6},7] = + [X || X <- List, not is_record(X, bar)], + ?line [1,3,5,7] = + [X || X <- List, ((not is_record(X, bar)) and (not is_record(X, foo)))], + ?line [#foo{a=2},#bar{d=4},#foo{a=6}] = + [X || X <- List, ((is_record(X, bar)) or (is_record(X, foo)))], + ?line [1,3,#bar{d=4}] = + [X || X <- List, ((is_record(X, bar)) or (X < 5))], + + ?line MyList = [#foo{a=3},x,[],{a,b}], + ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo)], + ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo)], + ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo) end], + ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo) end], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo) or + not is_binary(X)], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or + not is_binary(X)], + ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)], + ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or + is_reference(X)], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin is_record(X, foo) or + not is_binary(X) end], + ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo) or + not is_binary(X) end], + ?line [#foo{a=3}] = [X || X <- MyList, + begin is_record(X, foo) or is_reference(X) end], + ?line [x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo) or + is_reference(X) end], + ok. + +eval_once(Config) when is_list(Config) -> + ?line once(fun(GetRec) -> + true = erlang:is_record(GetRec(), foo) + end, #foo{}), + ?line once(fun(GetRec) -> + (GetRec())#foo{a=1} + end, #foo{}), + ?line once(fun(GetRec) -> + (GetRec())#foo{a=1,b=2} + end, #foo{}), + ?line once(fun(GetRec) -> + (GetRec())#foo{a=1,b=2,c=3} + end, #foo{}), + ?line once(fun(GetRec) -> + (GetRec())#foo{a=1,b=2,c=3,d=4} + end, #foo{}), + ok. + +once(Test, Record) -> + put(?MODULE, 0), + GetRec = fun() -> + put(?MODULE, 1+get(?MODULE)), + Record + end, + Result = Test(GetRec), + case get(?MODULE) of + 1 -> ok; + N -> + io:format("Evaluated ~w times\n", [N]), + ?t:fail() + end, + Result. + +id(I) -> I. diff --git a/lib/debugger/test/test_lib.erl b/lib/debugger/test/test_lib.erl new file mode 100644 index 0000000000..541375e64a --- /dev/null +++ b/lib/debugger/test/test_lib.erl @@ -0,0 +1,29 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2010. 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(test_lib). + +-export([interpret/1]). + +interpret(Mod) when atom(Mod) -> + case lists:member(Mod, int:interpreted()) of + true -> ok; + false -> {module,Mod} = i:ii(Mod) + end. diff --git a/lib/debugger/test/trycatch_SUITE.erl b/lib/debugger/test/trycatch_SUITE.erl new file mode 100644 index 0000000000..5901cdc9e5 --- /dev/null +++ b/lib/debugger/test/trycatch_SUITE.erl @@ -0,0 +1,796 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2010. 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(trycatch_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1, + basic/1,lean_throw/1,try_of/1,try_after/1,%after_bind/1, + catch_oops/1,after_oops/1,eclectic/1,rethrow/1, + nested_of/1,nested_catch/1,nested_after/1]). + +-include("test_server.hrl"). + +all(suite) -> + [{conf,init_all,cases(),finish_all}]. + +cases() -> + [basic,lean_throw,try_of,try_after,%after_bind, + catch_oops,after_oops,eclectic,rethrow, + nested_of,nested_catch,nested_after]. + +init_per_testcase(_Case, Config) -> + test_lib:interpret(?MODULE), + Dog = test_server:timetrap(?t:minutes(1)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +init_all(Config) when is_list(Config) -> + ?line test_lib:interpret(?MODULE), + ?line true = lists:member(?MODULE, int:interpreted()), + ok. + +finish_all(Config) when is_list(Config) -> + ok. + +basic(Conf) when is_list(Conf) -> + ?line 2 = + try my_div(4, 2) + catch + Class:Reason -> {Class,Reason} + end, + ?line error = + try my_div(1, 0) + catch + error:badarith -> error + end, + ?line error = + try 1/0 + catch + error:badarith -> error + end, + ?line ok = + try my_add(53, atom) + catch + error:badarith -> ok + end, + ?line exit_nisse = + try exit(nisse) + catch + exit:nisse -> exit_nisse + end, + ?line ok = + try throw(kalle) + catch + kalle -> ok + end, + + %% Try some stuff where the compiler will optimize away the try. + + V = id({a,variable}), + ?line V = try V catch nisse -> error end, + ?line 42 = try 42 catch nisse -> error end, + ?line [V] = try [V] catch nisse -> error end, + ?line {ok,V} = try {ok,V} catch nisse -> error end, + + %% Same idea, but use an after too. + + ?line V = try V catch nisse -> error after after_call() end, + ?line after_clean(), + ?line 42 = try 42 after after_call() end, + ?line after_clean(), + ?line [V] = try [V] catch nisse -> error after after_call() end, + ?line after_clean(), + ?line {ok,V} = try {ok,V} after after_call() end, + + %% Try/of + ?line ok = try V of + {a,variable} -> ok + catch nisse -> erro + end, + + ok. + +after_call() -> + put(basic, after_was_called). + +after_clean() -> + after_was_called = erase(basic). + +lean_throw(Conf) when is_list(Conf) -> + ?line {throw,kalle} = + try throw(kalle) + catch + Kalle -> {throw,Kalle} + end, + ?line {exit,kalle} = + try exit(kalle) + catch + Throw1 -> {throw,Throw1}; + exit:Reason1 -> {exit,Reason1} + end, + ?line {exit,kalle} = + try exit(kalle) + catch + exit:Reason2 -> {exit,Reason2}; + Throw2 -> {throw,Throw2} + end, + ?line {exit,kalle} = + try try exit(kalle) + catch + Throw3 -> {throw,Throw3} + end + catch + exit:Reason3 -> {exit,Reason3} + end, + ok. + +try_of(Conf) when is_list(Conf) -> + ?line {ok,{some,content}} = + try_of_1({value,{good,{some,content}}}), + ?line {error,[other,content]} = + try_of_1({value,{bad,[other,content]}}), + ?line {caught,{exit,{ex,it,[reason]}}} = + try_of_1({exit,{ex,it,[reason]}}), + ?line {caught,{throw,[term,{in,a,{tuple}}]}} = + try_of_1({throw,[term,{in,a,{tuple}}]}), + ?line {caught,{error,[bad,arg]}} = + try_of_1({error,[bad,arg]}), + ?line {caught,{error,badarith}} = + try_of_1({'div',{1,0}}), + ?line {caught,{error,badarith}} = + try_of_1({'add',{a,0}}), + ?line {caught,{error,badarg}} = + try_of_1({'abs',x}), + ?line {caught,{error,function_clause}} = + try_of_1(illegal), + ?line {error,{try_clause,{some,other_garbage}}} = + try try_of_1({value,{some,other_garbage}}) + catch error:Reason -> {error,Reason} + end, + ok. + +try_of_1(X) -> + try foo(X) of + {good,Y} -> {ok,Y}; + {bad,Y} -> {error,Y} + catch + Class:Reason -> + {caught,{Class,Reason}} + end. + +try_after(Conf) when is_list(Conf) -> + ?line {{ok,[some,value],undefined},finalized} = + try_after_1({value,{ok,[some,value]}},finalized), + ?line {{error,badarith,undefined},finalized} = + try_after_1({'div',{1,0}},finalized), + ?line {{error,badarith,undefined},finalized} = + try_after_1({'add',{1,a}},finalized), + ?line {{error,badarg,undefined},finalized} = + try_after_1({'abs',a},finalized), + ?line {{error,[the,{reason}],undefined},finalized} = + try_after_1({error,[the,{reason}]},finalized), + ?line {{throw,{thrown,[reason]},undefined},finalized} = + try_after_1({throw,{thrown,[reason]}},finalized), + ?line {{exit,{exited,{reason}},undefined},finalized} = + try_after_1({exit,{exited,{reason}}},finalized), + ?line {{error,function_clause,undefined},finalized} = + try_after_1(function_clause,finalized), + ?line ok = + try try_after_1({'add',{1,1}}, finalized) + catch + error:{try_clause,2} -> ok + end, + ?line finalized = erase(try_after), + ?line ok = + try try foo({exit,[reaso,{n}]}) + after put(try_after, finalized) + end + catch + exit:[reaso,{n}] -> ok + end, + ok. + +try_after_1(X, Y) -> + erase(try_after), + Try = + try foo(X) of + {ok,Value} -> {ok,Value,get(try_after)} + catch + Reason -> {throw,Reason,get(try_after)}; + error:Reason -> {error,Reason,get(try_after)}; + exit:Reason -> {exit,Reason,get(try_after)} + after + put(try_after, Y) + end, + {Try,erase(try_after)}. + +-ifdef(begone). + +after_bind(Conf) when is_list(Conf) -> + V = [make_ref(),self()|value], + ?line {value,{value,V}} = + after_bind_1({value,V}, V, {value,V}), + ok. + +after_bind_1(X, V, Y) -> + try + Try = + try foo(X) of + V -> value + catch + C1:V -> {caught,C1} + after + After = foo(Y) + end, + {Try,After} + of + V -> {value,V} + catch + C:D -> {caught,{C,D}} + end. + +-endif. + +catch_oops(Conf) when is_list(Conf) -> + V = {v,[a,l|u],{e},self()}, + ?line {value,V} = catch_oops_1({value,V}), + ?line {value,1} = catch_oops_1({'div',{1,1}}), + ?line {error,badarith} = catch_oops_1({'div',{1,0}}), + ?line {error,function_clause} = catch_oops_1(function_clause), + ?line {throw,V} = catch_oops_1({throw,V}), + ?line {exit,V} = catch_oops_1({exit,V}), + ok. + +catch_oops_1(X) -> + Ref = make_ref(), + try try foo({error,Ref}) + catch + error:Ref -> + foo(X) + end of + Value -> {value,Value} + catch + Class:Data -> {Class,Data} + end. + + + +after_oops(Conf) when is_list(Conf) -> + V = {self(),make_ref()}, + ?line {{value,V},V} = after_oops_1({value,V}, {value,V}), + ?line {{exit,V},V} = after_oops_1({exit,V}, {value,V}), + ?line {{error,V},undefined} = after_oops_1({value,V}, {error,V}), + ?line {{error,function_clause},undefined} = + after_oops_1({exit,V}, function_clause), + ok. + +after_oops_1(X, Y) -> + erase(after_oops), + Try = + try try foo(X) + after + put(after_oops, foo(Y)) + end of + V -> {value,V} + catch + C:D -> {C,D} + end, + {Try,erase(after_oops)}. + + + +eclectic(Conf) when is_list(Conf) -> + V = {make_ref(),3.1415926535,[[]|{}]}, + ?line {{value,{value,V},V},V} = + eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}), + ?line {{'EXIT',{V,[{?MODULE,foo,_}|_]}},V} = + eclectic_1({catch_foo,{error,V}}, undefined, {value,V}), + ?line {{error,{exit,V},{'EXIT',V}},V} = + eclectic_1({foo,{error,{exit,V}}}, error, {value,V}), + ?line {{value,{value,V},V},{'EXIT',{badarith,[{?MODULE,my_add,_}|_]}}} = + eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}), + ?line {{'EXIT',V},V} = + eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}), + ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,_}|_]}}}, {'EXIT',V}} = + eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}), + ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,_}|_]}}},{'EXIT',V}} = + eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}), + %% + ?line {{value,{value,{value,V},V}},V} = + eclectic_2({value,{value,V}}, undefined, {value,V}), + ?line {{value,{throw,{value,V},V}},V} = + eclectic_2({throw,{value,V}}, throw, {value,V}), + ?line {{caught,{'EXIT',V}},undefined} = + eclectic_2({value,{value,V}}, undefined, {exit,V}), + ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_}|_]}}},undefined} = + eclectic_2({error,{value,V}}, throw, {error,V}), + ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V]}|_]}}},V} = + eclectic_2({value,{'abs',V}}, undefined, {value,V}), + ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,_}|_]}}},V} = + eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}), + ?line {{caught,{'EXIT',V}},undefined} = + eclectic_2({value,{error,V}}, undefined, {exit,V}), + ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_}|_]}}},undefined} = + eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}), + ok. + +eclectic_1(X, C, Y) -> + erase(eclectic), + Done = make_ref(), + Try = + try case X of + {catch_foo,V} -> catch {Done,foo(V)}; + {foo,V} -> {Done,foo(V)} + end of + {Done,D} -> {value,D,catch foo(D)}; + {'EXIT',_}=Exit -> Exit; + D -> {D,catch foo(D)} + catch + C:D -> {C,D,catch foo(D)} + after + put(eclectic, catch foo(Y)) + end, + {Try,erase(eclectic)}. + +eclectic_2(X, C, Y) -> + Done = make_ref(), + erase(eclectic), + Catch = + case + catch + {Done, + try foo(X) of + V -> {value,V,foo(V)} + catch + C:D -> {C,D,foo(D)} + after + put(eclectic, foo(Y)) + end} of + {Done,Z} -> {value,Z}; + Z -> {caught,Z} + end, + {Catch,erase(eclectic)}. + +rethrow(Conf) when is_list(Conf) -> + V = {a,[b,{c,self()},make_ref]}, + ?line {value2,value1} = + rethrow_1({value,V}, V), + ?line {caught2,{error,V}} = + rethrow_2({error,V}, undefined), + ?line {caught2,{exit,V}} = + rethrow_1({exit,V}, error), + ?line {caught2,{throw,V}} = + rethrow_1({throw,V}, undefined), + ?line {caught2,{throw,V}} = + rethrow_2({throw,V}, undefined), + ?line {caught2,{error,badarith}} = + rethrow_1({'add',{0,a}}, throw), + ?line {caught2,{error,function_clause}} = + rethrow_2(function_clause, undefined), + ?line {caught2,{error,{try_clause,V}}} = + rethrow_1({value,V}, exit), + ?line {value2,{caught1,V}} = + rethrow_1({error,V}, error), + ?line {value2,{caught1,V}} = + rethrow_1({exit,V}, exit), + ?line {value2,caught1} = + rethrow_2({throw,V}, V), + ok. + +rethrow_1(X, C1) -> + try try foo(X) of + C1 -> value1 + catch + C1:D1 -> {caught1,D1} + end of + V2 -> {value2,V2} + catch + C2:D2 -> {caught2,{C2,D2}} + end. + +rethrow_2(X, C1) -> + try try foo(X) of + C1 -> value1 + catch + C1 -> caught1 % Implicit class throw: + end of + V2 -> {value2,V2} + catch + C2:D2 -> {caught2,{C2,D2}} + end. + + + +nested_of(Conf) when is_list(Conf) -> + V = {[self()|make_ref()],1.4142136}, + ?line {{value,{value1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{throw,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = + nested_of_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}), + %% + ?line {{caught,{error,{try_clause,{V,x1}}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,try_clause}, + void, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{exit,{V,x3}}}, + undefined, + {V,x4}, + finalized} = + nested_of_1({{value,{V,x1}},void,try_clause}, + void, {exit,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{throw,{V,x4}}}, + undefined, + undefined, + finalized} = + nested_of_1({{value,{V,x1}},void,try_clause}, + void, {exit,{V,x3}}, {throw,{V,x4}}), + %% + ?line {{value,{caught1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{error,{V,x1}},error,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = + nested_of_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}), + ?line {{caught,{error,badarg}}, + undefined, + undefined, + finalized} = + nested_of_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {'div',{17,0}}, {'abs',V}), + %% + ?line {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = + nested_of_1({{'add',{2,c}},rethrow,void}, + void, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarg}}, + undefined, + {V,x4}, + finalized} = + nested_of_1({{'add',{2,c}},rethrow,void}, + void, {'abs',V}, {value,{V,x4}}), + ?line {{caught,{error,function_clause}}, + undefined, + undefined, + finalized} = + nested_of_1({{'add',{2,c}},rethrow,void}, + void, {'abs',V}, function_clause), + ok. + +nested_of_1({X1,C1,V1}, + X2, X3, X4) -> + erase(nested3), + erase(nested4), + erase(nested), + Self = self(), + Try = + try + try self() + of + Self -> + try + foo(X1) + of + V1 -> {value1,foo(X2)} + catch + C1:V1 -> {caught1,foo(X2)} + after + put(nested3, foo(X3)) + end + after + put(nested4, foo(X4)) + end + of + V -> {value,V} + catch + C:D -> {caught,{C,D}} + after + put(nested, finalized) + end, + {Try,erase(nested3),erase(nested4),erase(nested)}. + + + +nested_catch(Conf) when is_list(Conf) -> + V = {[make_ref(),1.4142136,self()]}, + ?line {{value,{value1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{throw,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = + nested_catch_1({{value,{V,x1}},void,{V,x1}}, + {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}), + %% + ?line {{caught,{error,{try_clause,{V,x1}}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,try_clause}, + void, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{exit,{V,x3}}}, + undefined, + {V,x4}, + finalized} = + nested_catch_1({{value,{V,x1}},void,try_clause}, + void, {exit,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{throw,{V,x4}}}, + undefined, + undefined, + finalized} = + nested_catch_1({{value,{V,x1}},void,try_clause}, + void, {exit,{V,x3}}, {throw,{V,x4}}), + %% + ?line {{value,{caught1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{error,{V,x1}},error,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = + nested_catch_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}), + ?line {{caught,{error,badarg}}, + undefined, + undefined, + finalized} = + nested_catch_1({{error,{V,x1}},error,{V,x1}}, + {'add',{1,c}}, {'div',{17,0}}, {'abs',V}), + %% + ?line {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = + nested_catch_1({{'add',{2,c}},rethrow,void}, + void, {value,{V,x3}}, {value,{V,x4}}), + ?line {{caught,{error,badarg}}, + undefined, + {V,x4}, + finalized} = + nested_catch_1({{'add',{2,c}},rethrow,void}, + void, {'abs',V}, {value,{V,x4}}), + ?line {{caught,{error,function_clause}}, + undefined, + undefined, + finalized} = + nested_catch_1({{'add',{2,c}},rethrow,void}, + void, {'abs',V}, function_clause), + ok. + +nested_catch_1({X1,C1,V1}, + X2, X3, X4) -> + erase(nested3), + erase(nested4), + erase(nested), + Throw = make_ref(), + Try = + try + try throw(Throw) + catch + Throw -> + try + foo(X1) + of + V1 -> {value1,foo(X2)} + catch + C1:V1 -> {caught1,foo(X2)} + after + put(nested3, foo(X3)) + end + after + put(nested4, foo(X4)) + end + of + V -> {value,V} + catch + C:D -> {caught,{C,D}} + after + put(nested, finalized) + end, + {Try,erase(nested3),erase(nested4),erase(nested)}. + +nested_after(Conf) when is_list(Conf) -> + V = [{make_ref(),1.4142136,self()}], + ?line {value, + {V,x3}, + {value1,{V,x2}}, + finalized} = + nested_after_1({{value,{V,x1}},void,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}), + ?line {{caught,{error,{V,x2}}}, + {V,x3}, + undefined, + finalized} = + nested_after_1({{value,{V,x1}},void,{V,x1}}, + {error,{V,x2}}, {value,{V,x3}}), + ?line {{caught,{exit,{V,x3}}}, + undefined, + undefined, + finalized} = + nested_after_1({{value,{V,x1}},void,{V,x1}}, + {error,{V,x2}}, {exit,{V,x3}}), + %% + ?line {{caught,{error,{try_clause,{V,x1}}}}, + {V,x3}, + undefined, + finalized} = + nested_after_1({{value,{V,x1}},void,try_clause}, + void, {value,{V,x3}}), + ?line {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = + nested_after_1({{value,{V,x1}},void,try_clause}, + void, {'div',{17,0}}), + %% + ?line {value, + {V,x3}, + {caught1,{V,x2}}, + finalized} = + nested_after_1({{throw,{V,x1}},throw,{V,x1}}, + {value,{V,x2}}, {value,{V,x3}}), + ?line {{caught,{error,badarith}}, + {V,x3}, + undefined, + finalized} = + nested_after_1({{throw,{V,x1}},throw,{V,x1}}, + {'add',{a,b}}, {value,{V,x3}}), + ?line {{caught,{error,badarg}}, + undefined, + undefined, + finalized} = + nested_after_1({{throw,{V,x1}},throw,{V,x1}}, + {'add',{a,b}}, {'abs',V}), + %% + ?line {{caught,{throw,{V,x1}}}, + {V,x3}, + undefined, + finalized} = + nested_after_1({{throw,{V,x1}},rethrow,void}, + void, {value,{V,x3}}), + ?line {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = + nested_after_1({{throw,{V,x1}},rethrow,void}, + void, {'div',{1,0}}), + ok. + +nested_after_1({X1,C1,V1}, + X2, X3) -> + erase(nested3), + erase(nested4), + erase(nested), + Self = self(), + Try = + try + try self() + after + After = + try + foo(X1) + of + V1 -> {value1,foo(X2)} + catch + C1:V1 -> {caught1,foo(X2)} + after + put(nested3, foo(X3)) + end, + put(nested4, After) + end + of + Self -> value + catch + C:D -> {caught,{C,D}} + after + put(nested, finalized) + end, + {Try,erase(nested3),erase(nested4),erase(nested)}. + +foo({value,Value}) -> Value; +foo({'div',{A,B}}) -> + my_div(A, B); +foo({'add',{A,B}}) -> + my_add(A, B); +foo({'abs',X}) -> + my_abs(X); +foo({error,Error}) -> + erlang:error(Error); +foo({throw,Throw}) -> + erlang:throw(Throw); +foo({exit,Exit}) -> + erlang:exit(Exit); +foo({raise,{Class,Reason}}) -> + erlang:raise(Class, Reason). +%%foo(function_clause) -> % must not be defined! + +my_div(A, B) -> + A div B. + +my_add(A, B) -> + A + B. + +my_abs(X) -> abs(X). + +id(I) -> I. diff --git a/lib/docbuilder/src/docb_edoc_xml_cb.erl b/lib/docbuilder/src/docb_edoc_xml_cb.erl index f5cfc0fe18..90491bc007 100644 --- a/lib/docbuilder/src/docb_edoc_xml_cb.erl +++ b/lib/docbuilder/src/docb_edoc_xml_cb.erl @@ -340,9 +340,7 @@ otp_xmlify_e(#xmlElement{name=code} = E) -> % 4) [E#xmlElement{content=Content}] end; otp_xmlify_e(#xmlElement{name=Tag} = E) % 5a - when Tag==h1; Tag==h2; Tag==h3; Tag==h4; Tag==h5; - Tag==center; - Tag==font -> + when Tag==h1; Tag==h2; Tag==h3; Tag==h4; Tag==h5 -> Content = text_only(E#xmlElement.content), [E#xmlElement{name=b, content=Content}]; otp_xmlify_e(#xmlElement{name=Tag} = E) % 5b-c) @@ -354,21 +352,16 @@ otp_xmlify_e(#xmlElement{name=table} = E) -> % 6) module -> otp_xmlify_table(E#xmlElement.content); overview -> - case get_attrval(border, E) of - "" -> % implies border="0" - [{p, otp_xmlify_table(E#xmlElement.content)}]; - "0" -> - [{p, otp_xmlify_table(E#xmlElement.content)}]; - _Val -> - Content0 = otp_xmlify_e(E#xmlElement.content), - Summary = #xmlText{value=get_attrval(summary, E)}, - TCaption = E#xmlElement{name=tcaption, - attributes=[], - content=[Summary]}, - Content = Content0 ++ [TCaption], - [E#xmlElement{attributes=[], content=Content}] - end + Content0 = otp_xmlify_e(E#xmlElement.content), + Summary = #xmlText{value=get_attrval(summary, E)}, + TCaption = E#xmlElement{name=tcaption, + attributes=[], + content=[Summary]}, + Content = Content0 ++ [TCaption], + [E#xmlElement{attributes=[], content=Content}] end; +otp_xmlify_e(#xmlElement{name=tbody} = E) -> + otp_xmlify_e(E#xmlElement.content); otp_xmlify_e(#xmlElement{name=sup} = E) -> % 7) Text = get_text(E), [#xmlText{parents = E#xmlElement.parents, diff --git a/lib/docbuilder/vsn.mk b/lib/docbuilder/vsn.mk index 2852ebcc8b..5bb92fd209 100644 --- a/lib/docbuilder/vsn.mk +++ b/lib/docbuilder/vsn.mk @@ -1,14 +1 @@ DOCB_VSN = 0.9.8.7 - -TICKETS = OTP-8343 - -TICKETS_0.9.8.6 = OTP-8201 - -TICKETS_0.9.8.5 = OTP-7851 - -TICKETS_0.9.8.4 = OTP-7236 - -TICKETS_0.9.8.1 = OTP-7236 - - - diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl index 5614b02bb7..bba0f97645 100644 --- a/lib/erl_docgen/priv/xsl/db_html.xsl +++ b/lib/erl_docgen/priv/xsl/db_html.xsl @@ -1157,6 +1157,7 @@ </xsl:template> + <xsl:template match="name"> <xsl:variable name="tmpstring"> @@ -1208,6 +1209,9 @@ </xsl:variable> <a name="{$fname}-{$arity}"><span class="bold_code"><xsl:value-of select="."/></span></a><br/> </xsl:when> + <xsl:otherwise> + <span class="bold_code"><xsl:value-of select="."/></span> + </xsl:otherwise> </xsl:choose> </xsl:template> diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk index 5b14051034..33d8c1f708 100644 --- a/lib/erl_docgen/vsn.mk +++ b/lib/erl_docgen/vsn.mk @@ -1,22 +1 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2009-2010. 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% -# - ERL_DOCGEN_VSN = 0.2.1 - -TICKETS = diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml index 927395d1bf..36dfb149cc 100644 --- a/lib/erl_interface/doc/src/ei_connect.xml +++ b/lib/erl_interface/doc/src/ei_connect.xml @@ -116,7 +116,7 @@ int n = 0; struct in_addr addr; ei_cnode ec; -addr = inet_addr("150.236.14.75"); +addr.s_addr = inet_addr("150.236.14.75"); if (ei_connect_xinit(&ec, "chivas", "madonna", @@ -132,7 +132,7 @@ if (ei_connect_xinit(&ec, </p> <code type="none"><![CDATA[ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) { - fprintf("ERROR when initializing: %d",erl_errno); + fprintf(stderr,"ERROR when initializing: %d",erl_errno); exit(-1); } ]]></code> @@ -177,7 +177,7 @@ int fd = ei_connect(&ec, NODE); /*** Variant 2 ***/ struct in_addr addr; -addr = inet_addr(IP_ADDR); +addr.s_addr = inet_addr(IP_ADDR); fd = ei_xconnect(&ec, &addr, ALIVE); ]]></code> </desc> diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c index b1b79aa0e5..e191f3fbf0 100644 --- a/lib/erl_interface/src/connect/ei_connect.c +++ b/lib/erl_interface/src/connect/ei_connect.c @@ -502,10 +502,14 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name, return ERL_ERROR; } - if (this_node_name == NULL) + if (this_node_name == NULL) { sprintf(thisalivename, "c%d", (int) getpid()); - else + } else if (strlen(this_node_name) >= sizeof(thisalivename)) { + EI_TRACE_ERR0("ei_connect_init","ERROR: this_node_name too long"); + return ERL_ERROR; + } else { strcpy(thisalivename, this_node_name); + } if ((hp = ei_gethostbyname(thishostname)) == 0) { /* Looking up IP given hostname fails. We must be on a standalone diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c index 42aeab22b1..24a030c468 100644 --- a/lib/erl_interface/src/connect/ei_resolve.c +++ b/lib/erl_interface/src/connect/ei_resolve.c @@ -601,7 +601,7 @@ struct hostent *ei_gethostbyaddr_r(const char *addr, #ifndef HAVE_GETHOSTBYNAME_R return my_gethostbyaddr_r(addr,length,type,hostp,buffer,buflen,h_errnop); #else -#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000)) +#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__)) struct hostent *result; gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, &result, @@ -628,7 +628,7 @@ struct hostent *ei_gethostbyname_r(const char *name, #ifndef HAVE_GETHOSTBYNAME_R return my_gethostbyname_r(name,hostp,buffer,buflen,h_errnop); #else -#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000)) +#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__)) struct hostent *result; gethostbyname_r(name, hostp, buffer, buflen, &result, h_errnop); diff --git a/lib/erl_interface/src/epmd/epmd_port.c b/lib/erl_interface/src/epmd/epmd_port.c index 663b38d2d4..cf6122fafa 100644 --- a/lib/erl_interface/src/epmd/epmd_port.c +++ b/lib/erl_interface/src/epmd/epmd_port.c @@ -106,6 +106,12 @@ static int ei_epmd_r3_port (struct in_addr *addr, const char *alive, char ntoabuf[32]; #endif + if (len > sizeof(buf) - 3) + { + erl_errno = ERANGE; + return -1; + } + put16be(s,len); put8(s,EI_EPMD_PORT_REQ); strcpy(s,alive); @@ -164,6 +170,12 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive, #if defined(VXWORKS) char ntoabuf[32]; #endif + + if (len > sizeof(buf) - 3) + { + erl_errno = ERANGE; + return -1; + } put16be(s,len); put8(s,EI_EPMD_PORT2_REQ); diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c index 93b84cbb36..448de9aa23 100644 --- a/lib/erl_interface/src/prog/erl_call.c +++ b/lib/erl_interface/src/prog/erl_call.c @@ -123,6 +123,10 @@ static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags); static int read_stdin(char **buf); static void split_apply_string(char *str, char **mod, char **fun, char **args); +static void* ei_chk_malloc(size_t size); +static void* ei_chk_calloc(size_t nmemb, size_t size); +static void* ei_chk_realloc(void *old, size_t size); +static char* ei_chk_strdup(char *s); /*************************************************************************** @@ -132,7 +136,6 @@ static void split_apply_string(char *str, char **mod, ***************************************************************************/ /* FIXME isn't VxWorks to handle arguments differently? */ -/* FIXME check errors from malloc */ #if !defined(VXWORKS) int main(int argc, char *argv[]) @@ -165,8 +168,7 @@ int erl_call(int argc, char **argv) usage_arg(progname, "-sname "); } - flags.node = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.node, argv[i+1]); + flags.node = ei_chk_strdup(argv[i+1]); i++; flags.use_long_name = 0; } else if (strcmp(argv[i], "-name") == 0) { /* -name NAME */ @@ -174,8 +176,7 @@ int erl_call(int argc, char **argv) usage_arg(progname, "-name "); } - flags.node = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.node, argv[i+1]); + flags.node = ei_chk_strdup(argv[i+1]); i++; flags.use_long_name = 1; } else { @@ -210,16 +211,14 @@ int erl_call(int argc, char **argv) usage_arg(progname, "-c "); } flags.cookiep = 1; - flags.cookie = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.cookie, argv[i+1]); + flags.cookie = ei_chk_strdup(argv[i+1]); i++; break; case 'n': if (i+1 >= argc) { usage_arg(progname, "-n "); } - flags.node = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.node, argv[i+1]); + flags.node = ei_chk_strdup(argv[i+1]); flags.use_long_name = 1; i++; break; @@ -227,24 +226,21 @@ int erl_call(int argc, char **argv) if (i+1 >= argc) { usage_arg(progname, "-h "); } - flags.hidden = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.hidden, argv[i+1]); + flags.hidden = ei_chk_strdup(argv[i+1]); i++; break; case 'x': if (i+1 >= argc) { usage_arg(progname, "-x "); } - flags.script = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.script, argv[i+1]); + flags.script = ei_chk_strdup(argv[i+1]); i++; break; case 'a': if (i+1 >= argc) { usage_arg(progname, "-a "); } - flags.apply = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.apply, argv[i+1]); + flags.apply = ei_chk_strdup(argv[i+1]); i++; break; case '?': @@ -304,8 +300,7 @@ int erl_call(int argc, char **argv) if (flags.hidden == NULL) { /* As default we are c17@gethostname */ i = flags.randomp ? (time(NULL) % 997) : 17; - /* FIXME allocates to small !!! */ - flags.hidden = (char *) malloc(3 + 2 ); /* c17 or cXYZ */ + flags.hidden = (char *) ei_chk_malloc(10 + 2 ); /* c17 or cXYZ */ #if defined(VXWORKS) sprintf(flags.hidden, "c%d", i < 0 ? (int) taskIdSelf() : i); @@ -330,17 +325,25 @@ int erl_call(int argc, char **argv) initWinSock(); #endif - gethostname(h_hostname, EI_MAXHOSTNAMELEN); + if (gethostname(h_hostname, EI_MAXHOSTNAMELEN) < 0) { + fprintf(stderr,"erl_call: failed to get host name: %d\n", errno); + exit(1); + } if ((hp = ei_gethostbyname(h_hostname)) == 0) { fprintf(stderr,"erl_call: can't resolve hostname %s\n", h_hostname); exit(1); } - /* If shortnames cut of the name at first '.' */ + /* If shortnames, cut off the name at first '.' */ if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) { *ct = '\0'; } - strcpy(h_hostname, hp->h_name); + strncpy(h_hostname, hp->h_name, EI_MAXHOSTNAMELEN); + h_hostname[EI_MAXHOSTNAMELEN] = '\0'; memcpy(&h_ipadr.s_addr, *hp->h_addr_list, sizeof(struct in_addr)); + if (strlen(h_alivename) + strlen(h_hostname) + 2 > sizeof(h_nodename)) { + fprintf(stderr,"erl_call: hostname too long: %s\n", h_hostname); + exit(1); + } sprintf(h_nodename, "%s@%s", h_alivename, h_hostname); if (ei_connect_xinit(&ec, h_hostname, h_alivename, h_nodename, @@ -368,11 +371,16 @@ int erl_call(int argc, char **argv) fprintf(stderr,"erl_call: can't get_hostent(%s)\n", host); exit(1); } - /* If shortnames cut of the name at first '.' */ + /* If shortnames, cut off the name at first '.' */ if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) { *ct = '\0'; } - strcpy(host_name, hp->h_name); + strncpy(host_name, hp->h_name, EI_MAXHOSTNAMELEN); + host_name[EI_MAXHOSTNAMELEN] = '\0'; + if (strlen(flags.node) + strlen(host_name) + 2 > sizeof(nodename)) { + fprintf(stderr,"erl_call: nodename too long: %s\n", flags.node); + exit(1); + } sprintf(nodename, "%s@%s", flags.node, host_name); /* @@ -401,7 +409,7 @@ int erl_call(int argc, char **argv) ei_encode_empty_list(NULL, &i); - p = (char *)malloc(i); + p = (char *)ei_chk_malloc(i); i = 0; /* Reset */ ei_encode_empty_list(p, &i); @@ -426,6 +434,10 @@ int erl_call(int argc, char **argv) if (flags.modp && (modname != NULL)) { char fname[256]; + if (strlen(modname) + 4 + 1 > sizeof(fname)) { + fprintf(stderr,"erl_call: module name too long: %s\n", modname); + exit(1); + } strcpy(fname, modname); strcat(fname, ".erl"); @@ -443,7 +455,7 @@ int erl_call(int argc, char **argv) ei_encode_binary(NULL, &i, module, modsize); ei_encode_empty_list(NULL, &i); - p = (char *)malloc(i); + p = (char *)ei_chk_malloc(i); i = 0; /* Reset */ ei_encode_list_header(p, &i, 2); @@ -476,7 +488,7 @@ int erl_call(int argc, char **argv) ei_encode_empty_list(NULL, &i); ei_encode_empty_list(NULL, &i); - p = (char *)malloc(i); + p = (char *)ei_chk_malloc(i); i = 0; /* Reset */ ei_encode_list_header(p, &i, 2); @@ -521,7 +533,7 @@ int erl_call(int argc, char **argv) ei_encode_binary(NULL, &i, evalbuf, len); ei_encode_empty_list(NULL, &i); - p = (char *)malloc(i); + p = (char *)ei_chk_malloc(i); i = 0; /* Reset */ ei_encode_list_header(p, &i, 1); @@ -719,32 +731,28 @@ static void split_apply_string(char *str, EAT(str); len = str-begin; - *mod = (char *) calloc(len + 1, sizeof(char)); + *mod = (char *) ei_chk_calloc(len + 1, sizeof(char)); memcpy(*mod, begin, len); SKIP_SPACE(str); if (*str == '\0') { - *fun = (char *) calloc(strlen(start)+1, sizeof(char)); - strcpy(*fun, start); - *args = (char *) calloc(strlen(empty_list)+1, sizeof(char)); - strcpy(*args, empty_list); + *fun = ei_chk_strdup(start); + *args = ei_chk_strdup(empty_list); return; } begin = str; EAT(str); len = str-begin; - *fun = (char *) calloc(len + 1, sizeof(char)); + *fun = (char *) ei_chk_calloc(len + 1, sizeof(char)); memcpy(*fun, begin, len); SKIP_SPACE(str); if (*str == '\0') { - *args = (char *) calloc(strlen(empty_list)+1, sizeof(char)); - strcpy(*args, empty_list); + *args = ei_chk_strdup(empty_list); return; } - *args = (char *) calloc(strlen(str) + 1, sizeof(char)); - strcpy(*args, str); + *args = ei_chk_strdup(str); return; @@ -760,7 +768,7 @@ static int read_stdin(char **buf) int bsize = BUFSIZ; int len = 0; int i; - char *tmp = (char *) malloc(bsize); + char *tmp = (char *) ei_chk_malloc(bsize); while (1) { if ((i = read(0, &tmp[len], bsize-len)) < 0) { @@ -772,7 +780,7 @@ static int read_stdin(char **buf) len += i; if ((len+50) > bsize) { bsize = len * 2; - tmp = (char *) realloc(tmp, bsize); + tmp = (char *) ei_chk_realloc(tmp, bsize); } else { continue; } @@ -809,7 +817,7 @@ static int get_module(char **mbuf, char **mname) } } /* while */ i = tmp - start; - *mname = (char *) calloc(i+1, sizeof(char)); + *mname = (char *) ei_chk_calloc(i+1, sizeof(char)); memcpy(*mname, start, i); } if (*mbuf) @@ -905,3 +913,51 @@ static void initWinSock(void) } } #endif + + +/*************************************************************************** + * + * Utility functions + * + ***************************************************************************/ + +static void* ei_chk_malloc(size_t size) +{ + void *p = malloc(size); + if (p == NULL) { + fprintf(stderr,"erl_call: insufficient memory\n"); + exit(1); + } + return p; +} + +static void* ei_chk_calloc(size_t nmemb, size_t size) +{ + void *p = calloc(nmemb, size); + if (p == NULL) { + fprintf(stderr,"erl_call: insufficient memory\n"); + exit(1); + } + return p; +} + +static void* ei_chk_realloc(void *old, size_t size) +{ + void *p = realloc(old, size); + if (!p) { + fprintf(stderr, "erl_call: cannot reallocate %u bytes of memory from %p\n", + (unsigned) size, old); + exit (1); + } + return p; +} + +static char* ei_chk_strdup(char *s) +{ + char *p = strdup(s); + if (p == NULL) { + fprintf(stderr,"erl_call: insufficient memory\n"); + exit(1); + } + return p; +} diff --git a/lib/et/doc/src/et.xml b/lib/et/doc/src/et.xml index 9b170dd7d9..5e3453c348 100644 --- a/lib/et/doc/src/et.xml +++ b/lib/et/doc/src/et.xml @@ -29,6 +29,7 @@ <checked></checked> <date></date> <rev>%VSN%</rev> + <file>et</file> </header> <module>et</module> <modulesummary>Main API of the Event Trace (ET) application</modulesummary> diff --git a/lib/et/doc/src/et_collector.xml b/lib/et/doc/src/et_collector.xml index 88c478c89a..e9885dcbb3 100644 --- a/lib/et/doc/src/et_collector.xml +++ b/lib/et/doc/src/et_collector.xml @@ -29,6 +29,7 @@ <checked></checked> <date></date> <rev>%VSN%</rev> + <file>et_collector.xml</file> </header> <module>et_collector</module> <modulesummary>Collect trace events and provide a backing storage appropriate for iteration </modulesummary> diff --git a/lib/et/doc/src/et_selector.xml b/lib/et/doc/src/et_selector.xml index dd12166d85..34203306bb 100644 --- a/lib/et/doc/src/et_selector.xml +++ b/lib/et/doc/src/et_selector.xml @@ -29,6 +29,7 @@ <checked></checked> <date></date> <rev>%VSN%</rev> + <file>et_selector.xml</file> </header> <module>et_selector</module> <modulesummary>Define event transforms and trace patterns</modulesummary> diff --git a/lib/et/doc/src/et_tutorial.xmlsrc b/lib/et/doc/src/et_tutorial.xmlsrc index c72234a587..b0e2bf4af6 100644 --- a/lib/et/doc/src/et_tutorial.xmlsrc +++ b/lib/et/doc/src/et_tutorial.xmlsrc @@ -29,6 +29,7 @@ <checked></checked> <date></date> <rev>%VSN%</rev> + <file>et_tutorial.xml</file> </header> <section> diff --git a/lib/et/doc/src/et_viewer.xml b/lib/et/doc/src/et_viewer.xml index c16e5b8869..d4cfbdfa31 100644 --- a/lib/et/doc/src/et_viewer.xml +++ b/lib/et/doc/src/et_viewer.xml @@ -29,6 +29,7 @@ <checked></checked> <date></date> <rev>%VSN%</rev> + <file>et_viewer.xml</file> </header> <module>et_viewer</module> <modulesummary>Displays a sequence chart for trace events (messages/actions)</modulesummary> diff --git a/lib/et/src/et_wx_viewer.erl b/lib/et/src/et_wx_viewer.erl index 5cd3563aed..d42f8c0c86 100644 --- a/lib/et/src/et_wx_viewer.erl +++ b/lib/et/src/et_wx_viewer.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% Copyright Ericsson AB 2000-2010. 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 @@ -1233,7 +1233,7 @@ create_main_window(S) -> [{flag, ?wxEXPAND}]), CanvasSizer = wxBoxSizer:new(?wxHORIZONTAL), - Canvas = wxPanel:new(Panel, []), + Canvas = wxPanel:new(Panel, [{style, ?wxFULL_REPAINT_ON_RESIZE}]), {CanvasW,CanvasH} = wxPanel:getSize(Canvas), ScrollBar = wxScrollBar:new(Panel, ?wxID_ANY, [{style, ?wxSB_VERTICAL}]), @@ -1244,7 +1244,13 @@ create_main_window(S) -> wxPanel:connect(Canvas, left_up), wxPanel:connect(Canvas, right_up), wxPanel:connect(Canvas, size), - wxPanel:connect(Canvas, paint), + Self = self(), + wxPanel:connect(Canvas, paint, [{callback, %% Needed on windows + fun(Ev, _) -> + DC = wxPaintDC:new(Canvas), + wxPaintDC:destroy(DC), + Self ! Ev + end}]), wxPanel:connect(Canvas, key_down), wxPanel:connect(Canvas, kill_focus), wxPanel:connect(Canvas, enter_window, [{skip, true}]), @@ -1437,6 +1443,7 @@ create_help_menu(Bar) -> clear_canvas(S) -> DC = wxClientDC:new(S#state.canvas), + wxDC:setBackground(DC, ?wxWHITE_BRUSH), %% Needed on mac wxDC:clear(DC), {CanvasW, CanvasH} = wxPanel:getSize(S#state.canvas), wxSizer:recalcSizes(S#state.canvas_sizer), diff --git a/lib/et/test/Makefile b/lib/et/test/Makefile index 9aedf96ce9..7227ae8fd8 100644 --- a/lib/et/test/Makefile +++ b/lib/et/test/Makefile @@ -72,7 +72,8 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) et.spec $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR) - $(INSTALL_PROGRAM) ett $(INSTALL_PROGS) $(RELSYSDIR) + $(INSTALL_SCRIPT) ett $(RELSYSDIR) + $(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR) # chmod -f -R u+w $(RELSYSDIR) # @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk index b7d65b12a2..04ecb8c82e 100644 --- a/lib/et/vsn.mk +++ b/lib/et/vsn.mk @@ -1,24 +1 @@ -# This is an -*-makefile-*- file. -# %CopyrightBegin% -# -# Copyright Ericsson AB 2002-2010. 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% - ET_VSN = 1.4 -TICKETS = OTP-8058 - -TICKETS_1_3_3 = OTP-8201 -TICKETS_1_3_2 = OTP-8078 -TICKETS_1_3_1 = OTP-7830 diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 1f0247a040..6eeeab3610 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -1638,7 +1638,6 @@ type(erlang, system_info, 1, Xs) -> t_non_neg_integer()])])); ['allocator'] -> t_tuple([t_sup([t_atom('undefined'), - t_atom('elib_malloc'), t_atom('glibc')]), t_list(t_integer()), t_list(t_atom()), @@ -1659,9 +1658,8 @@ type(erlang, system_info, 1, Xs) -> t_binary(); ['dist_ctrl'] -> t_list(t_tuple([t_atom(), t_sup([t_pid(), t_port])])); - ['elib_malloc'] -> - t_sup([t_atom('false'), - t_list(t_tuple([t_atom(), t_any()]))]); + %% elib_malloc is intentionally not included, + %% because it scheduled for removal in R15. ['endian'] -> t_endian(); ['fullsweep_after'] -> diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl index 787fb05415..3c8f7b5712 100644 --- a/lib/hipe/icode/hipe_icode_exceptions.erl +++ b/lib/hipe/icode/hipe_icode_exceptions.erl @@ -344,6 +344,16 @@ pop_catch(Cs) -> pop_catch_1([[_|C] | Cs]) -> [C | pop_catch_1(Cs)]; +pop_catch_1([[] | Cs]) -> + %% The elements in the list represent different possible incoming + %% stacks of catch handlers to this BB. Before the fixpoint has + %% been found these elements are underapproximations of the true + %% stacks, therefore it's possible for these elements to be too + %% short for the number of pops implied by the code in the BB. + %% We must not fail in that case, so we set pop([]) = []. + %% This fixes find_catches_crash.erl and compiler_tests in the + %% HiPE test suite. + [[] | pop_catch_1(Cs)]; pop_catch_1([]) -> []. diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index ed722fecba..c80fb6a0a2 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -274,7 +274,7 @@ load(Mod, BeamFileName) when is_list(BeamFileName) -> Architecture = erlang:system_info(hipe_architecture), ChunkName = hipe_unified_loader:chunk_name(Architecture), case beam_lib:chunks(BeamFileName, [ChunkName]) of - {ok,{_,[{_,Bin}]}} when is_binary(Bin) -> do_load(Mod, Bin, Bin); + {ok,{_,[{_,Bin}]}} when is_binary(Bin) -> do_load(Mod, Bin, BeamFileName); Error -> {error, Error} end. @@ -913,7 +913,7 @@ do_load(Mod, Bin, WholeModule) -> %% In this case, the emulated code for the module must be loaded. {module, Mod} = code:ensure_loaded(Mod), code:load_native_partial(Mod, Bin); - BinCode when is_binary(BinCode) -> + BeamBinOrPath when is_binary(BeamBinOrPath) orelse is_list(BeamBinOrPath) -> case code:is_sticky(Mod) of true -> %% We unpack and repack the Beam binary as a workaround to diff --git a/lib/ic/test/Makefile b/lib/ic/test/Makefile new file mode 100644 index 0000000000..1142159d19 --- /dev/null +++ b/lib/ic/test/Makefile @@ -0,0 +1,277 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1998-2010. 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_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../vsn.mk +VSN=$(IC_VSN) +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/ic_test + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- +TEST_SPEC_FILE = ic.spec ic.spec.vxworks + + +IDL_FILES = + +COMPILER_TEST_FILES = \ + ic_SUITE_data/Corba.idl \ + ic_SUITE_data/Coss.idl \ + ic_SUITE_data/attr.idl \ + ic_SUITE_data/c_err1.idl \ + ic_SUITE_data/c_err2.idl \ + ic_SUITE_data/c_err3.idl \ + ic_SUITE_data/c_norm.idl \ + ic_SUITE_data/enum.idl \ + ic_SUITE_data/forward.idl \ + ic_SUITE_data/include.idl \ + ic_SUITE_data/include2.idl \ + ic_SUITE_data/include3.idl \ + ic_SUITE_data/inherit.idl \ + ic_SUITE_data/inherit_err.idl \ + ic_SUITE_data/inherit_warn.idl \ + ic_SUITE_data/mult_ids.idl \ + ic_SUITE_data/nasty.idl \ + ic_SUITE_data/one.idl \ + ic_SUITE_data/one_out.idl \ + ic_SUITE_data/one_raises.idl \ + ic_SUITE_data/one_followed.idl \ + ic_SUITE_data/one_void.idl \ + ic_SUITE_data/raises_reg.idl \ + ic_SUITE_data/struct.idl \ + ic_SUITE_data/syntax1.idl \ + ic_SUITE_data/syntax2.idl \ + ic_SUITE_data/syntax3.idl \ + ic_SUITE_data/syntax4.idl \ + ic_SUITE_data/syntax5.idl \ + ic_SUITE_data/syntax6.idl \ + ic_SUITE_data/type.idl \ + ic_SUITE_data/typeid.idl \ + ic_SUITE_data/u_case_mult.idl \ + ic_SUITE_data/u_mult.idl \ + ic_SUITE_data/u_norm.idl \ + ic_SUITE_data/u_type.idl \ + ic_SUITE_data/u_default.idl \ + ic_SUITE_data/undef_id.idl + + +COMPILER_TEST_FILES2 = \ + ic_register_SUITE_data/reg_m8.idl \ + ic_register_SUITE_data/reg_m9.idl \ + ic_register_SUITE_data/reg_m10.idl \ + ic_register_SUITE_data/reg_m11.idl \ + ic_register_SUITE_data/reg_m12.idl + + +COMPILER_TEST_FILES3 = \ + ic_pragma_SUITE_data/reg_m0.idl \ + ic_pragma_SUITE_data/reg_m1.idl \ + ic_pragma_SUITE_data/reg_m2.idl \ + ic_pragma_SUITE_data/reg_m3.idl \ + ic_pragma_SUITE_data/reg_m4.idl \ + ic_pragma_SUITE_data/reg_m5.idl \ + ic_pragma_SUITE_data/reg_m6.idl \ + ic_pragma_SUITE_data/reg_m7.idl \ + ic_pragma_SUITE_data/uggly.idl + + +COMPILER_TEST_FILES4 = \ + ic_be_SUITE_data/plain.idl + + +PREPROCESSOR_TEST_FILES = \ + ic_pp_SUITE_data/arg.idl \ + ic_pp_SUITE_data/cascade.idl \ + ic_pp_SUITE_data/comment.idl \ + ic_pp_SUITE_data/concat.idl \ + ic_pp_SUITE_data/define.idl \ + ic_pp_SUITE_data/if.idl \ + ic_pp_SUITE_data/if_zero.idl \ + ic_pp_SUITE_data/improp_nest_constr.idl \ + ic_pp_SUITE_data/inc.idl \ + ic_pp_SUITE_data/line.idl \ + ic_pp_SUITE_data/misc.idl \ + ic_pp_SUITE_data/nopara.idl \ + ic_pp_SUITE_data/predef.idl \ + ic_pp_SUITE_data/predef_time.idl \ + ic_pp_SUITE_data/self_ref.idl \ + ic_pp_SUITE_data/separate.idl \ + ic_pp_SUITE_data/swallow_sc.idl \ + ic_pp_SUITE_data/unintended_grp.idl + +C_CLIENT_ERL_SERVER_TEST_FILES = \ + c_client_erl_server_SUITE_data/Makefile.src \ + c_client_erl_server_SUITE_data/c_erl_test.idl \ + c_client_erl_server_SUITE_data/c_client.c \ + c_client_erl_server_SUITE_data/m_i_impl.erl + +C_CLIENT_ERL_SERVER_PROTO_TEST_FILES = \ + c_client_erl_server_proto_SUITE_data/Makefile.src \ + c_client_erl_server_proto_SUITE_data/c_erl_test.idl \ + c_client_erl_server_proto_SUITE_data/c_client.c \ + c_client_erl_server_proto_SUITE_data/my.c \ + c_client_erl_server_proto_SUITE_data/m_i_impl.erl + +C_CLIENT_ERL_SERVER_PROTO_TMO_TEST_FILES = \ + c_client_erl_server_proto_tmo_SUITE_data/Makefile.src \ + c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl \ + c_client_erl_server_proto_tmo_SUITE_data/c_client.c \ + c_client_erl_server_proto_tmo_SUITE_data/my.c \ + c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl + +ERL_CLIENT_C_SERVER_TEST_FILES = \ + erl_client_c_server_SUITE_data/Makefile.src \ + erl_client_c_server_SUITE_data/erl_c_test.idl \ + erl_client_c_server_SUITE_data/erl_client.erl \ + erl_client_c_server_SUITE_data/c_server.c \ + erl_client_c_server_SUITE_data/callbacks.c + +ERL_CLIENT_C_SERVER_PROTO_TEST_FILES = \ + erl_client_c_server_proto_SUITE_data/Makefile.src \ + erl_client_c_server_proto_SUITE_data/erl_c_test.idl \ + erl_client_c_server_proto_SUITE_data/erl_client.erl \ + erl_client_c_server_proto_SUITE_data/c_server.c \ + erl_client_c_server_proto_SUITE_data/callbacks.c + +JAVA_CLIENT_ERL_SERVER_TEST_FILES = \ + java_client_erl_server_SUITE_data/Makefile.src \ + java_client_erl_server_SUITE_data/java_erl_test.idl \ + java_client_erl_server_SUITE_data/JavaClient.java \ + java_client_erl_server_SUITE_data/m_i_impl.erl + +MODULES = \ + ic_SUITE \ + ic_register_SUITE \ + ic_pragma_SUITE \ + ic_pp_SUITE \ + ic_be_SUITE \ + c_client_erl_server_SUITE \ + c_client_erl_server_proto_SUITE \ + c_client_erl_server_proto_tmo_SUITE \ + erl_client_c_server_SUITE \ + erl_client_c_server_proto_SUITE \ + java_client_erl_server_SUITE + +GEN_MODULES = + +ERL_FILES = $(MODULES:%=%.erl) + +HRL_FILES = + +GEN_HRL_FILES = + + +GEN_FILES = \ + $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \ + $(GEN_MODULES=:%=$(IDLOUTDIR)/%.erl) + +GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR)) + +SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR)) + +TARGET_FILES = \ + $(GEN_TARGET_FILES) \ + $(SUITE_TARGET_FILES) + +# ---------------------------------------------------- +# PROGRAMS +# ---------------------------------------------------- + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +ERL_LOCAL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin + +ERL_COMPILE_FLAGS += \ + $(ERL_LOCAL_FLAGS) \ + -pa $(ERL_TOP)/lib/test_server/ebin \ + -pa $(ERL_TOP)/lib/orber/ebin \ + -I$(ERL_TOP)/lib/orber \ + -I$(ERL_TOP)/lib/test_server/include + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +tests debug opt: $(TARGET_FILES) + +clean: + rm -f $(TARGET_FILES) + rm -f errs core *~ + +docs: + +# ---------------------------------------------------- +# Special Targets +# ---------------------------------------------------- + + +# ---------------------------------------------------- +# Release Targets +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: + +release_docs_spec: + +release_tests_spec: tests + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DIR) $(RELSYSDIR)/ic_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/ic_register_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/ic_pragma_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/ic_pp_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/ic_be_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/c_client_erl_server_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/c_client_erl_server_proto_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/erl_client_c_server_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/erl_client_c_server_proto_SUITE_data + $(INSTALL_DIR) $(RELSYSDIR)/java_client_erl_server_SUITE_data + $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) $(ERL_FILES) \ + $(RELSYSDIR) + $(INSTALL_DATA) $(COMPILER_TEST_FILES) $(RELSYSDIR)/ic_SUITE_data + $(INSTALL_DATA) $(COMPILER_TEST_FILES2) \ + $(RELSYSDIR)/ic_register_SUITE_data + $(INSTALL_DATA) $(COMPILER_TEST_FILES3) \ + $(RELSYSDIR)/ic_pragma_SUITE_data + $(INSTALL_DATA) $(COMPILER_TEST_FILES4) \ + $(RELSYSDIR)/ic_be_SUITE_data + $(INSTALL_DATA) $(PREPROCESSOR_TEST_FILES) \ + $(RELSYSDIR)/ic_pp_SUITE_data + $(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_TEST_FILES) \ + $(RELSYSDIR)/c_client_erl_server_SUITE_data + $(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_PROTO_TEST_FILES) \ + $(RELSYSDIR)/c_client_erl_server_proto_SUITE_data + $(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_PROTO_TMO_TEST_FILES) \ + $(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data + $(INSTALL_DATA) $(ERL_CLIENT_C_SERVER_TEST_FILES) \ + $(RELSYSDIR)/erl_client_c_server_SUITE_data + $(INSTALL_DATA) $(ERL_CLIENT_C_SERVER_PROTO_TEST_FILES) \ + $(RELSYSDIR)/erl_client_c_server_proto_SUITE_data + $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR) + $(INSTALL_DATA) $(JAVA_CLIENT_ERL_SERVER_TEST_FILES) \ + $(RELSYSDIR)/java_client_erl_server_SUITE_data diff --git a/lib/ic/test/c_client_erl_server_SUITE.erl b/lib/ic/test/c_client_erl_server_SUITE.erl new file mode 100644 index 0000000000..40c1395d10 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_SUITE.erl @@ -0,0 +1,315 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-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% +%% +%% + +%%---------------------------------------------------------------------- +%% Purpose : Test suite for c-client/erl-server +%%---------------------------------------------------------------------- + + +-module(c_client_erl_server_SUITE). +-include("test_server.hrl"). + +-export([init_per_testcase/2, fin_per_testcase/2, + all/1, void_test/1, long_test/1, long_long_test/1, + unsigned_short_test/1, unsigned_long_test/1, + unsigned_long_long_test/1, double_test/1, char_test/1, + wchar_test/1, octet_test/1, bool_test/1, struct_test/1, + struct2_test/1, seq1_test/1, seq2_test/1, seq3_test/1, + seq4_test/1, seq5_test/1, array1_test/1, array2_test/1, + enum_test/1, string1_test/1, string2_test/1, string3_test/1, + string4_test/1, pid_test/1, port_test/1, ref_test/1, term_test/1, + typedef_test/1, inline_sequence_test/1, term_sequence_test/1, + term_struct_test/1, wstring1_test/1]). + +-define(DEFAULT_TIMEOUT, 20000). +-define(PORT_TIMEOUT, 15000). +-define(ERLANG_SERVER_NAME, idl_erlang_server). +-define(C_CLIENT_NODE_NAME, c_client_idl_test). + +%% Add/remove code path and watchdog before/after each test case. +%% +init_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:add_patha(DataDir), + + %% Since other test suites use the module m_i, we have + %% to make sure we are using the right m_i module. + code:purge(m_i), + code:load_file(m_i), + + WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT), + [{watchdog, WatchDog}| Config]. + +fin_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:del_path(DataDir), + WatchDog = ?config(watchdog, Config), + test_server:timetrap_cancel(WatchDog). + +all(doc) -> + "Test of IC with a C-client and an Erlang generic server. " + "The communication is via Erlang distribution."; +all(suite) -> + [void_test, long_test, long_long_test, unsigned_short_test, + unsigned_long_test, unsigned_long_long_test, double_test, + char_test, wchar_test, octet_test, bool_test, struct_test, + struct2_test, seq1_test, seq2_test, seq3_test, seq4_test, + seq5_test, array1_test, array2_test, enum_test, string1_test, + string2_test, string3_test, string4_test, pid_test, port_test, + ref_test, term_test, typedef_test, inline_sequence_test, + term_sequence_test, term_struct_test, wstring1_test]. + + +array1_test(doc) -> ""; +array1_test(suite) -> []; +array1_test(Config) -> + do_test(array1_test, Config). + +array2_test(doc) -> ""; +array2_test(suite) -> []; +array2_test(Config) -> + do_test(array2_test, Config). + +bool_test(doc) -> ""; +bool_test(suite) -> []; +bool_test(Config) -> + do_test(bool_test, Config). + +char_test(doc) -> ""; +char_test(suite) -> []; +char_test(Config) -> + do_test(char_test, Config). + +double_test(doc) -> ""; +double_test(suite) -> []; +double_test(Config) -> + do_test(double_test, Config). + +enum_test(doc) -> ""; +enum_test(suite) -> []; +enum_test(Config) -> + do_test(enum_test, Config). + +inline_sequence_test(doc) -> ""; +inline_sequence_test(suite) -> []; +inline_sequence_test(Config) -> + do_test(inline_sequence_test, Config). + +long_long_test(doc) -> ""; +long_long_test(suite) -> []; +long_long_test(Config) -> + do_test(long_long_test, Config). + +long_test(doc) -> ""; +long_test(suite) -> []; +long_test(Config) -> + do_test(long_test, Config). + +octet_test(doc) -> ""; +octet_test(suite) -> []; +octet_test(Config) -> + do_test(octet_test, Config). + +pid_test(doc) -> ""; +pid_test(suite) -> []; +pid_test(Config) -> + do_test(pid_test, Config). + +port_test(doc) -> ""; +port_test(suite) -> []; +port_test(Config) -> + do_test(port_test, Config). + +ref_test(doc) -> ""; +ref_test(suite) -> []; +ref_test(Config) -> + do_test(ref_test, Config). + +seq1_test(doc) -> ""; +seq1_test(suite) -> []; +seq1_test(Config) -> + do_test(seq1_test, Config). + +seq2_test(doc) -> ""; +seq2_test(suite) -> []; +seq2_test(Config) -> + do_test(seq2_test, Config). + +seq3_test(doc) -> ""; +seq3_test(suite) -> []; +seq3_test(Config) -> + do_test(seq3_test, Config). + +seq4_test(doc) -> ""; +seq4_test(suite) -> []; +seq4_test(Config) -> + do_test(seq4_test, Config). + +seq5_test(doc) -> ""; +seq5_test(suite) -> []; +seq5_test(Config) -> + do_test(seq5_test, Config). + +string1_test(doc) -> ""; +string1_test(suite) -> []; +string1_test(Config) -> + do_test(string1_test, Config). + +string2_test(doc) -> ""; +string2_test(suite) -> []; +string2_test(Config) -> + do_test(string2_test, Config). + +string3_test(doc) -> ""; +string3_test(suite) -> []; +string3_test(Config) -> + do_test(string3_test, Config). + +string4_test(doc) -> ""; +string4_test(suite) -> []; +string4_test(Config) -> + do_test(string4_test, Config). + +struct2_test(doc) -> ""; +struct2_test(suite) -> []; +struct2_test(Config) -> + do_test(struct2_test, Config). + +struct_test(doc) -> ""; +struct_test(suite) -> []; +struct_test(Config) -> + do_test(struct_test, Config). + +term_sequence_test(doc) -> ""; +term_sequence_test(suite) -> []; +term_sequence_test(Config) -> + do_test(term_sequence_test, Config). + +term_struct_test(doc) -> ""; +term_struct_test(suite) -> []; +term_struct_test(Config) -> + do_test(term_struct_test, Config). + +term_test(doc) -> ""; +term_test(suite) -> []; +term_test(Config) -> + do_test(term_test, Config). + +typedef_test(doc) -> ""; +typedef_test(suite) -> []; +typedef_test(Config) -> + do_test(typedef_test, Config). + +unsigned_long_long_test(doc) -> ""; +unsigned_long_long_test(suite) -> []; +unsigned_long_long_test(Config) -> + do_test(unsigned_long_long_test, Config). + +unsigned_long_test(doc) -> ""; +unsigned_long_test(suite) -> []; +unsigned_long_test(Config) -> + do_test(unsigned_long_test, Config). + +unsigned_short_test(doc) -> ""; +unsigned_short_test(suite) -> []; +unsigned_short_test(Config) -> + do_test(unsigned_short_test, Config). + +void_test(doc) -> ""; +void_test(suite) -> []; +void_test(Config) -> + do_test(void_test, Config). + +wchar_test(doc) -> ""; +wchar_test(suite) -> []; +wchar_test(Config) -> + do_test(wchar_test, Config). + +wstring1_test(doc) -> ""; +wstring1_test(suite) -> []; +wstring1_test(Config) -> + do_test(wstring1_test, Config). + + +%% It is here that all tests really are done. +%% + +do_test(Case, Config) -> + %% Trap exits + process_flag(trap_exit, true), + %% Start the server + {ok, _Pid} = m_i:oe_create_link([], {local, ?ERLANG_SERVER_NAME}), + Node = atom_to_list(node()), + DataDir = ?config(data_dir, Config), + %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]), + Cookie = atom_to_list(erlang:get_cookie()), + %% Start C-client node as a port program. + Cmd = filename:join([DataDir, "c_client"]) ++ + " -this-node-name " ++ atom_to_list(?C_CLIENT_NODE_NAME) ++ + " -peer-node " ++ Node ++ + " -peer-process-name " ++ atom_to_list(?ERLANG_SERVER_NAME) ++ + " -cookie " ++ Cookie ++ + " -test-case " ++ atom_to_list(Case), + Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]), + Res = wait_for_completion(Port), + %% Kill off node if there was timeout + case Res of + {error, timeout} -> + catch rpc:cast(?C_CLIENT_NODE_NAME, erlang, halt, [1]); + _ -> + ok + end, + process_flag(trap_exit, false), + catch m_i:stop(?ERLANG_SERVER_NAME), + ok = Res. + + +%% Wait for eof *and* exit status, but return if exit status indicates +%% an error, or we have been waiting more than PORT_TIMEOUT seconds. +%% +wait_for_completion(Port) -> + wait_for_completion(Port, 0). + +wait_for_completion(Port, N) when N < 2 -> + receive + {Port, {data, Bytes}} -> + %% Relay output + io:format("~s", [Bytes]), + wait_for_completion(Port, N); + {Port, {exit_status, 0}} -> + wait_for_completion(Port, N + 1); + {Port, {exit_status, Status}} -> + {error, Status}; + {Port, eof} -> + wait_for_completion(Port, N + 1); + {'EXIT', Port, Reason} -> + io:format("Port exited with reason: ~w~n", [Reason]), + wait_for_completion(Port, N); + {'EXIT', From, Reason} -> + io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]), + wait_for_completion(Port, N) + after ?PORT_TIMEOUT -> + {error, timeout} + end; +wait_for_completion(_, _) -> + ok. + + + diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src new file mode 100644 index 0000000000..6516e699bd --- /dev/null +++ b/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src @@ -0,0 +1,145 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-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% +# +# +# Makefile.src for c_client_erl_server test +# Note: This file *must* work for both Unix and Windows +# +# We use both `rm' (Unix) and `del' (Windows) for removing files, but +# with a `-' in front so that the error in not finding `rm' (`del') on +# Windows (Unix) is ignored. +# +# VxWorks? XXX +# + +.SUFFIXES: +.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@ + + +# Variables from ts: +# + +ERL_INCLUDE = @erl_include@ + +IC_INCLUDE_PATH = @ic_include_path@ +IC_LIB = @ic_libpath@@DS@@ic_lib@ + +ERL_INTERFACE_INCLUDE = @erl_interface_include@ +ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@ +ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@ +ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@ +ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@ + +CC = @CC@ +## XXX Should set warning flag with a DEBUG_FLAG +CFLAGS = @CFLAGS@ @DEFS@ -I@erl_include@ \ + -I@ic_include_path@ -I@erl_interface_include@ + +LD = @LD@ +LDFLAGS = @CROSSLDFLAGS@ +LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \ + $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS) +ERLC = erlc + +# Generated C header files +GEN_H_FILES = \ + m.h \ + m_i.h \ + oe_c_erl_test.h + +# Generated C files +GEN_C_FILES = \ + m.c \ + m_i.c \ + oe_c_erl_test.c \ + oe_code_m_a.c \ + oe_code_m_arr1.c \ + oe_code_m_arr2.c \ + oe_code_m_arr3.c \ + oe_code_m_aseq.c \ + oe_code_m_b.c \ + oe_code_m_bseq.c \ + oe_code_m_dd.c \ + oe_code_m_dyn.c \ + oe_code_m_dyn_sl.c \ + oe_code_m_es.c \ + oe_code_m_et.c \ + oe_code_m_etseq.c \ + oe_code_m_fruit.c \ + oe_code_m_lseq.c \ + oe_code_m_s.c \ + oe_code_m_s_sl.c \ + oe_code_m_sarr3.c \ + oe_code_m_simple.c \ + oe_code_m_ssarr3.c \ + oe_code_m_sseq.c \ + oe_code_m_ssstr3.c \ + oe_code_m_sstr3.c \ + oe_code_m_str1.c \ + oe_code_m_str3.c \ + oe_code_m_strRec.c \ + oe_code_m_strRec_str5.c \ + oe_code_m_strRec_str7.c + +GEN_HRL_FILES = \ + m.hrl \ + m_i.hrl \ + oe_c_erl_test.hrl + +GEN_ERL_FILES = \ + m.erl \ + m_arr2.erl \ + m_arr3.erl \ + m_i.erl \ + m_str3.erl \ + oe_c_erl_test.erl + +C_FILES = $(GEN_C_FILES) c_client.c + +OBJS = $(C_FILES:.c=@obj@) + +PGMS = c_client@exe@ + +ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl + +EBINS = $(ERL_FILES:.erl=.@EMULATOR@) + + +all: $(PGMS) $(EBINS) + +clean: + -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + +$(PGMS): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" c_erl_test.idl + +$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl + +.c@obj@: + $(CC) -c -o $*@obj@ $(CFLAGS) $< + +.erl.@EMULATOR@: + $(ERLC) -I $(IC_INCLUDE_PATH) $< + diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/c_client.c b/lib/ic/test/c_client_erl_server_SUITE_data/c_client.c new file mode 100644 index 0000000000..e4f9cfdece --- /dev/null +++ b/lib/ic/test/c_client_erl_server_SUITE_data/c_client.c @@ -0,0 +1,1760 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2010. 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% + * + */ +/* C-client for test of IC. + * + */ + +#include <stdio.h> +#include <stdlib.h> + +#ifndef __WIN32__ +# include <unistd.h> +#endif + +#include <string.h> + +#ifdef __WIN32__ +# include <time.h> +# include <sys/timeb.h> +#elif defined VXWORKS +#include <time.h> +#include <sys/times.h> +#else +#include <sys/time.h> +#endif + +#include <ctype.h> + +#ifdef __WIN32__ +# include <winsock2.h> +# include <windows.h> +#else +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netdb.h> +#endif + +#include "ei.h" +#include "erl_interface.h" +#include "m_i.h" + +#define HOSTNAMESZ 256 +#define NODENAMESZ 512 + +#define INBUFSZ 10 +#define OUTBUFSZ 0 + +#define MAXTRIES 5 + +#define CHECK_EXCEPTION(x) \ + if ((x)->_major != CORBA_NO_EXCEPTION) { \ + fprintf(stderr,"\n\nException: %s\n\n", \ + (char *)CORBA_exception_value((x))); \ + CORBA_exception_free((x)); \ + return -1; \ + } \ + +/* XXX Should free things here too! */ +#define RETURN_IF_OK(x) \ + if ((x)) {\ + fprintf(stdout, "ok\n");\ + return 0;\ + }\ + +#define cmp_str(x,y) (!strcmp((x),(y))) +#define cmp_wstr(x,y) (!ic_wstrcmp((x),(y))) + +typedef CORBA_Environment IC_Env; + +typedef int (*TestFunc)(IC_Env *); +typedef struct { + char *name; + TestFunc func; +} TestCase; + +static char longtext[] = +"Introduction The IC application is an IDL compiler implemented in Erlang." +" The IDL compiler generates client stubs and server skeletons." +" Several back-ends are supported, and they fall into three main groups." +" For more details on IC compiler options consult the ic(3) manual page." +" Argument passing cases 1 Caller allocates all necessary storage," +" except that which may be encapsulated and managed within the parameter itself." +" 2 The caller allocates a pointer and passes it by reference to the callee." +" The callee sets the pointer to point to a valid instance of the parameter's type." +" The caller is responsible for releasing the returned storage." +" Following completion of a request, the caller is not allowed to modify any values" +" in the returned storage. To do so the caller must first copy the returned instance" +" into a new instance, then modify the new instance. 3 The caller allocates a" +" pointer to an array slice which has all the same dimensions of the original" +" array except the first, and passes it by reference to the callee. The callee sets" +" the pointer to point to a valid instance of the array. The caller is responsible for" +" releasing the returned storage. Following completion of a request, the caller is not" +" allowed to modify any values in the returned storage. To do so the caller must first" +" copy the returned instance into a new instance, then modify the new instance." +" Generated Files Two files will be generated for each scope. One set of files will be" +" generated for each module and each interface scope. An extra set is generated for" +" those definitions at top level scope. One of the files is a header file(.h), and the" +" other file is a C source code file (.c). In addition to these files a number of C" +" source files will be generated for type encodings, they are named according to the " +"following template: oe_code_<type>.c."; +static char this_node[NODENAMESZ + 1]; +static char *progname; + +/* Test function prototypes */ + +static int void_test(IC_Env *env); +static int long_test(IC_Env *env); +static int long_long_test(IC_Env *env); +static int unsigned_short_test(IC_Env *env); +static int unsigned_long_test(IC_Env *env); +static int unsigned_long_long_test(IC_Env *env); +static int double_test(IC_Env *env); +static int char_test(IC_Env *env); +static int wchar_test(IC_Env *env); +static int octet_test(IC_Env *env); +static int bool_test(IC_Env *env); +static int struct_test(IC_Env *env); +static int struct2_test(IC_Env *env); +static int seq1_test(IC_Env *env); +static int seq2_test(IC_Env *env); +static int seq3_test(IC_Env *env); +static int seq4_test(IC_Env *env); +static int seq5_test(IC_Env *env); +static int array1_test(IC_Env *env); +static int array2_test(IC_Env *env); +static int enum_test(IC_Env *env); +static int string1_test(IC_Env *env); +static int string2_test(IC_Env *env); +static int string3_test(IC_Env *env); +static int string4_test(IC_Env *env); +static int pid_test(IC_Env *env); +static int port_test(IC_Env *env); +static int ref_test(IC_Env *env); +static int term_test(IC_Env *env); +static int typedef_test(IC_Env *env); +static int inline_sequence_test(IC_Env *env); +static int term_sequence_test(IC_Env *env); +static int term_struct_test(IC_Env *env); +static int wstring1_test(IC_Env *env); + +static TestCase test_cases[] = { + {"void_test", void_test}, + {"long_test", long_test}, + {"long_long_test", long_long_test}, + {"unsigned_short_test", unsigned_short_test}, + {"unsigned_long_test", unsigned_long_test}, + {"unsigned_long_long_test", unsigned_long_long_test}, + {"double_test", double_test}, + {"char_test", char_test}, + {"wchar_test", wchar_test}, + {"octet_test", octet_test}, + {"bool_test", bool_test}, + {"struct_test", struct_test}, + {"struct2_test", struct2_test}, + {"seq1_test", seq1_test}, + {"seq2_test", seq2_test}, + {"seq3_test", seq3_test}, + {"seq4_test", seq4_test}, + {"seq5_test", seq5_test}, + {"array1_test", array1_test}, + {"array2_test", array2_test}, + {"enum_test", enum_test}, + {"string1_test", string1_test}, + {"string2_test", string2_test}, + {"string3_test", string3_test}, + {"string4_test", string4_test}, + {"pid_test", pid_test}, + {"port_test", port_test}, + {"ref_test", ref_test}, + {"term_test", term_test}, + {"typedef_test", typedef_test}, + {"inline_sequence_test", inline_sequence_test}, + {"term_sequence_test", term_sequence_test}, + {"term_struct_test", term_struct_test}, + {"wstring1_test", wstring1_test}, + {"", NULL} +}; + +/* Other prototypes */ +static int cmp_aseq(m_aseq *a1, m_aseq *a2); +static int cmp_a(m_a *a1, m_a *a2); +static int cmp_bseq(m_bseq *b1, m_bseq *b2); +static int cmp_b(m_b *b1, m_b *b2); +static int cmp_lseq(m_lseq *b1, m_lseq *b2); +static int cmp_etseq(m_etseq *b1, m_etseq *b2); +static int cmp_et(m_et* b1, m_et *b2); +static int cmp_es(m_es *b1, m_es *b2); +static int cmp_arr1(m_arr1 b1, m_arr1 b2); +static int cmp_dd(m_dd b1, m_dd b2); +static int cmp_strRec(m_strRec *b1, m_strRec *b2); +static int cmp_sseq(m_sseq *b1, m_sseq *b2); +static int cmp_pid(erlang_pid *p1, erlang_pid *p2); +static int cmp_port(erlang_port *p1, erlang_port *p2); +static int cmp_ref(erlang_ref *p1, erlang_ref *p2); +static int cmp_s(m_s *b1, m_s *b2); +static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2); +static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2); +static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2); +static int cmp_arr3(m_arr3 b1, m_arr3 b2); + +static void print_aseq(m_aseq *a); +static void print_a(m_a *a); +static void print_bseq(m_bseq *b); +static void print_lseq(m_lseq *b); +static void print_b(m_b *b); +static void print_etseq(m_etseq *b); +static void print_et(m_et* b); +static void print_es(m_es *b); +static void print_arr1(long a[500]); +static void print_dd(long a[2][3]); +static void print_strRec(m_strRec* sr); +static void print_sseq(m_sseq *b); +static void print_pid(erlang_pid *p); +static void print_port(erlang_port *p); +static void print_ref(erlang_ref *p); +static void print_term(ETERM *t); +static void print_s(m_s *p); +static void print_ssstr3(m_ssstr3 *b1); +static void print_ssarr3(m_ssarr3 *b1); +static void print_sarr3(m_sarr3 *b1); +static void print_arr3(m_arr3 b1); +static void print_wstr(CORBA_wchar *ws); + +static void free_etseq_buf(m_etseq *b); +static void free_et(m_et* b); + +#ifdef __WIN32__ +typedef struct { + long tv_sec; + long tv_usec; +} MyTimeval; +#else +typedef struct timeval MyTimeval; +#endif +static void my_gettimeofday(MyTimeval *tv); +static void showtime(MyTimeval *start, MyTimeval *stop); +static void usage(void); +static void done(int r); + + + +/* main */ + +#ifdef VXWORKS +int client(int argc, char **argv) +#else +int main(int argc, char **argv) +#endif +{ + struct hostent *hp; + erlang_pid pid; + MyTimeval start, stop; + int i, fd, ires, tres; + IC_Env *env; + int tries = 0; + char *this_node_name = NULL; + char *peer_node = NULL; + char *peer_process_name = NULL; + char *cookie = NULL; + char host[HOSTNAMESZ + 1]; + TestFunc test_func = NULL; + TestCase *test_case; + char *test_case_name = NULL; + +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + + if (WSAStartup(wVersionRequested, &wsaData) != 0) { + fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL"); + exit(1); + } +#endif + + progname = argv[0]; + host[HOSTNAMESZ] = '\0'; + if (gethostname(host, HOSTNAMESZ) < 0) { + fprintf(stderr, "Can't find own hostname\n"); + done(1); + } + if ((hp = gethostbyname(host)) == 0) { + fprintf(stderr, "Can't get ip address for host %s\n", host); + done(1); + } + for (i = 1; i < argc; i++) { + if (cmp_str(argv[i], "-help")) { + usage(); + done(0); + } else if (cmp_str(argv[i], "-this-node-name")) { + i++; + this_node_name = argv[i]; + } else if (cmp_str(argv[i], "-peer-node")) { + i++; + peer_node = argv[i]; + } else if (cmp_str(argv[i], "-peer-process-name")) { + i++; + peer_process_name = argv[i]; + } else if (cmp_str(argv[i], "-cookie")) { + i++; + cookie = argv[i]; + } else if (cmp_str(argv[i], "-test-case")) { + i++; + test_case_name = argv[i]; + } else { + fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]); + usage(); + done(1); + } + } + + if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL + || peer_process_name == NULL || cookie == NULL) { + fprintf(stderr, "Error: missing option\n"); + usage(); + done(1); + } + + test_case = test_cases; + while (test_case->func) { + if (cmp_str(test_case->name, test_case_name)) { + test_func = test_case->func; + break; + } + test_case++; + } + if (test_func == NULL) { + fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name); + done(1); + } + + /* Behead hostname at first dot */ + for (i=0; host[i] != '\0'; i++) { + if (host[i] == '.') { host[i] = '\0'; break; } + } + sprintf(this_node, "%s@%s", this_node_name, host); + fprintf(stderr, "c_client: this node: \"%s\"\n", this_node); + fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node); + fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name); + + fprintf(stderr, "c_client: starting\n"); + + /* initialize erl_interface */ + erl_init(NULL, 0); + + for (tries = 0; tries < MAXTRIES; tries++) { + + /* connect to erlang node */ + + ires = erl_connect_xinit(host, this_node_name, this_node, + (struct in_addr *)*hp->h_addr_list, + cookie, 0); + + fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires); + + fd = erl_connect(peer_node); + fprintf(stderr, "c_client: erl_connect(): %d\n", fd); + + if (fd >= 0) + break; + fprintf(stderr, "c_client: cannot connect, retrying\n"); + } + if (fd < 0) { + fprintf(stderr, "c_client: cannot connect, exiting\n"); + done(1); + } + env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ); + env->_fd = fd; + strcpy(env->_regname, peer_process_name); + env->_to_pid = NULL; + env->_from_pid = &pid; + + strcpy(pid.node, this_node); + pid.num = fd; + pid.serial = 0; + pid.creation = 0; + + my_gettimeofday(&start); + tres = test_func(env); /* Call test case */ + my_gettimeofday(&stop); + showtime(&start, &stop); + erl_close_connection(fd); + + printf("c_client: env->_inbuf before : %d\n", INBUFSZ); + printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ); + printf("c_client: env->_inbuf after : %d\n", env->_inbufsz); + printf("c_client: env->_outbuf after : %d\n", env->_outbufsz); + + CORBA_free(env->_inbuf); + CORBA_free(env->_outbuf); + CORBA_free(env); + done(tres); +} + +static void usage() +{ + fprintf(stderr, "Usage: %s [-help] -this-node-name <name> " + "-peer-node <nodename> -peer-process-name <name> " + "-cookie <cookie> -test-case <test case name>\n", progname); + fprintf(stderr, "Example:\n %s -this-node-name kalle " + "-peer-node olle@home -peer-process-name idltest " + "-cookie oa678er -test-case octet_test\n", progname); +} + +static void done(int r) +{ +#ifdef __WIN32__ + WSACleanup(); +#endif + exit(r); +} + + +/* TESTS */ + +static int void_test(IC_Env *env) +{ + fprintf(stdout, "\n======== m_i_void test ======\n\n"); + m_i_void_test(NULL,env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(1); +} + +static int long_test(IC_Env *env) +{ + long l = 4711, lo, lr; + + fprintf(stdout, "\n======== m_i_long test ======\n\n"); + lr = m_i_long_test(NULL, l, &lo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(l == lo && l == lr); + if (l != lo) + fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", l, lo); + if (l != lr) + fprintf(stdout, " result error, sent: %ld, got: %ld\n", l, lr); + return -1; +} + +static int long_long_test(IC_Env *env) +{ + CORBA_long_long ll = 4711, llo, llr; + + fprintf(stdout, "\n======== m_i_longlong test ======\n\n"); + llr = m_i_longlong_test(NULL, ll, &llo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ll == llo && ll == llr); + if (ll != llo) + fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", + ll, llo); + if (ll != llr) + fprintf(stdout, " result error, sent: %ld, got: %ld\n", ll, llr); + return -1; +} + +static int unsigned_short_test(IC_Env *env) +{ + unsigned short x, y = 2, z; + + fprintf(stdout, "\n======== m_i_ushort test ======\n\n"); + x = m_i_ushort_test(NULL, y, &z, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(y == z && y == x); + if (y != z) + fprintf(stdout, " out parameter error, sent: %d, got: %d\n", y, z); + if (y != x) + fprintf(stdout, " result error, sent: %d, got: %d\n", y, x); + return -1; +} + + +static int unsigned_long_test(IC_Env *env) +{ + unsigned long ul = 5050, ulo, ulr; + + fprintf(stdout, "\n======== m_i_ulong test ======\n\n"); + ulr = m_i_ulong_test(NULL, ul, &ulo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ul == ulo && ul == ulr); + if (ul != ulo) + fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n", + ul, ulo); + if (ul != ulr) + fprintf(stdout, " result error, sent: %lu, got: %lu\n", ul, ulr); + return -1; +} + +/* + * Note: CORBA_unsigned_long_long is in fact a plain long. + */ +static int unsigned_long_long_test(IC_Env *env) +{ + CORBA_unsigned_long_long ull = 5050, ullo, ullr; + + fprintf(stdout, "\n======== m_i_ulonglong test ======\n\n"); + ullr = m_i_ulonglong_test(NULL, ull, &ullo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ull == ullo && ull == ullr); + if (ull != ullo) + fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n", + ull, ullo); + if (ull != ullr) + fprintf(stdout, " result error, sent: %lu, got: %lu\n", + ull, ullr); + return -1; +} + +static int double_test(IC_Env *env) +{ + double d = 12.1212, db, dr; + + fprintf(stdout, "\n======== m_i_double test ======\n\n"); + dr = m_i_double_test(NULL, d, &db, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(d == db && d == dr); + if (d != db) + fprintf(stdout, " out parameter error, sent: %f, got: %f\n", d, db); + if (d != dr) + fprintf(stdout, " result error, sent: %f, got: %f\n", d, dr); + return -1; +} + +static int char_test(IC_Env *env) +{ + char c = 'g', co, cr; + + /* char test */ + fprintf(stdout, "\n======== m_i_char test ======\n\n"); + cr = m_i_char_test(NULL, c, &co, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(c == co && c == cr); + if (c !=co) + fprintf(stdout, " out parameter error, sent: %c, got: %c\n", c, co); + if (c != cr) + fprintf(stdout, " result error, sent: %c, got: %c\n", c, cr); + return -1; +} + +static int wchar_test(IC_Env *env) +{ + CORBA_wchar wc = 103, wco, wcr; + + fprintf(stdout, "\n======== m_i_wchar test ======\n\n"); + wcr = m_i_wchar_test(NULL, wc, &wco, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(wc == wco && wc == wcr); + if (wc != wco) + fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n", + wc, wco); + if (wc != wcr) + fprintf(stdout, " result error, sent: %lu, got: %lu\n", + wc, wcr); + return -1; +} + +static int octet_test(IC_Env *env) +{ + char o ='r', oo, or; + + fprintf(stdout, "\n======== m_i_octet test ======\n\n"); + or = m_i_octet_test(NULL, o, &oo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(o == oo && o == or); + if (o != oo) + fprintf(stdout, " out parameter error, sent: %c, got: %c\n", o, oo); + if (o != or) + fprintf(stdout, " result error, sent: %c, got: %c\n", o, or); + return -1; +} + +static int bool_test(IC_Env *env) +{ + unsigned char i = 0, io, ir; + + fprintf(stdout, "\n======== m_i_bool test ======\n\n"); + ir = m_i_bool_test(NULL, i, &io, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(i == io && i == ir); + if (i != io) + fprintf(stdout, " out parameter error, sent: %d, got: %d\n", i, io); + if (i != ir) + fprintf(stdout, " result error, sent: %d, got: %d\n", i, ir); + return -1; +} + +static int struct_test(IC_Env *env) +{ + m_b b = {4711, 'a'}, bo, br; + + fprintf(stdout, "\n======== m_i_struct test ======\n\n"); + br = m_i_struct_test(NULL, &b, &bo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_b(&b, &bo) && cmp_b(&b, &br)); + if (!cmp_b(&b, &bo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_b(&b); + fprintf(stdout, " got:\n"); + print_b(&bo); + fprintf(stdout, "\n"); + } + if (!cmp_b(&b, &br)) { + fprintf(stdout, " result error, sent:\n"); + print_b(&b); + fprintf(stdout, " got:\n"); + print_b(&br); + fprintf(stdout, "\n"); + } + return -1; +} + +static int struct2_test(IC_Env *env) +{ + m_es esi = {m_peach, 5050}, eso, esr; + + fprintf(stdout, "\n======== m_i_struct2 test ======\n\n"); + esr = m_i_struct2_test(NULL, &esi, &eso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_es(&esi, &eso) && cmp_es(&esi, &esr)); + if (!cmp_es(&esi, &eso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_es(&esi); + fprintf(stdout, " got:\n"); + print_es(&eso); + fprintf(stdout, "\n"); + } + if (!cmp_es(&esi, &esr)) { + fprintf(stdout, " result error, sent:\n"); + print_es(&esi); + fprintf(stdout, " got:\n"); + print_es(&esr); + fprintf(stdout, "\n"); + } + return -1; +} + + +static int seq1_test(IC_Env *env) +{ + m_bseq bs, *bso, *bsr; + + m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}}; + bs._length = 3; + bs._buffer = ba; + + fprintf(stdout, "\n======== m_i_seq1 test ======\n\n"); + bsr = m_i_seq1_test(NULL, &bs, &bso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_bseq(&bs, bso) && cmp_bseq(&bs, bsr)); + if (!cmp_bseq(&bs, bso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_bseq(&bs); + fprintf(stdout, " got:\n"); + print_bseq(bso); + fprintf(stdout, "\n"); + } + if (!cmp_bseq(&bs, bsr)) { + fprintf(stdout, " result error, sent:\n"); + print_bseq(&bs); + fprintf(stdout, " got:\n"); + print_bseq(bsr); + fprintf(stdout, "\n"); + } + CORBA_free(bso); + CORBA_free(bsr); + return -1; +} + +static int seq2_test(IC_Env *env) +{ + m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}}; + m_a a; + m_a aa[2]; + m_aseq as, *aso, *asr; + + a.l = 9999; + a.y._length = 3; + a.y._buffer = ba; + a.d = 66.89898989; + + aa[0] = a; + aa[1] = a; + as._length = 2; + as._buffer = aa; + + fprintf(stdout, "\n======== m_i_seq2 test ======\n\n"); + asr = m_i_seq2_test(NULL, &as, &aso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_aseq(&as, aso) && cmp_aseq(&as, asr)); + if (!cmp_aseq(&as, aso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_aseq(&as); + fprintf(stdout, " got:\n"); + print_aseq(aso); + fprintf(stdout, "\n"); + } + if (!cmp_aseq(&as, asr)) { + fprintf(stdout, " result error, sent:\n"); + print_aseq(&as); + fprintf(stdout, " got:\n"); + print_aseq(asr); + fprintf(stdout, "\n"); + } + CORBA_free(aso); + CORBA_free(asr); + return -1; +} + +static int seq3_test(IC_Env *env) +{ + m_lseq lsi, *lso, *lsr; + long al[500]; + int i=0; + + for (i = 0; i < 500; i++) + al[i]=i; + lsi._length = 500; + lsi._buffer = al; + + fprintf(stdout, "\n======== m_i_seq3 test ======\n\n"); + lsr = m_i_seq3_test(NULL, &lsi, &lso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_lseq(&lsi, lso) && cmp_lseq(&lsi, lsr)); + if (!cmp_lseq(&lsi, lso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_lseq(&lsi); + fprintf(stdout, " got:\n"); + print_lseq(lso); + fprintf(stdout, "\n"); + } + if (!cmp_lseq(&lsi, lsr)) { + fprintf(stdout, " result error, sent:\n"); + print_lseq(&lsi); + fprintf(stdout, " got:\n"); + print_lseq(lsr); + fprintf(stdout, "\n"); + } + CORBA_free(lso); + CORBA_free(lsr); + return -1; +} + +static int seq4_test(IC_Env *env) +{ + char *stra0[3] = {"a", "long", "time"}; + char *stra1[3] = {"ago", "there", "was"}; + char *stra2[3] = {"a", "buggy", "compiler"}; + m_sstr3 str3s[3] = {{3, 3, stra0}, {3, 3, stra1}, {3, 3, stra2}}; + m_ssstr3 str3ssi = {3, 3, str3s}; + m_ssstr3 *str3sso, *str3ssr; + + fprintf(stdout, "\n======== m_i_seq4 test ======\n\n"); + str3ssr = m_i_seq4_test(NULL, &str3ssi, &str3sso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_ssstr3(&str3ssi, str3sso) && + cmp_ssstr3(&str3ssi, str3ssr)); + if (!cmp_ssstr3(&str3ssi, str3sso)){ + fprintf(stdout, " out parameter error, sent:\n"); + print_ssstr3(&str3ssi); + fprintf(stdout, " got:\n"); + print_ssstr3(str3sso); + fprintf(stdout, "\n"); + } + if (!cmp_ssstr3(&str3ssi, str3ssr)) { + fprintf(stdout, " result error, sent:\n"); + print_ssstr3(&str3ssi); + fprintf(stdout, " got:\n"); + print_ssstr3(str3ssr); + fprintf(stdout, "\n"); + } + CORBA_free(str3sso); + CORBA_free(str3ssr); + return -1; +} + +static int seq5_test(IC_Env *env) +{ + m_arr3 arr3a[3] = { + {4711, 18931947, 3}, + {4711, 18931947, 3}, + {4711, 18931947, 3}}; + m_sarr3 arr3sa[3] = {{3, 3, arr3a}, {3, 3, arr3a}, {3, 3, arr3a}}; + m_ssarr3 arr3ssi = {3, 3, arr3sa}; + m_ssarr3 *arr3sso; + m_ssarr3 *arr3ssr; + + fprintf(stdout, "\n======== m_i_seq5 test ======\n\n"); + arr3ssr = m_i_seq5_test(NULL, &arr3ssi, &arr3sso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_ssarr3(&arr3ssi, arr3sso) && + cmp_ssarr3(&arr3ssi, arr3ssr)); + if (!cmp_ssarr3(&arr3ssi, arr3sso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_ssarr3(&arr3ssi); + fprintf(stdout, " got:\n"); + print_ssarr3(arr3sso); + fprintf(stdout, "\n"); + } + if (!cmp_ssarr3(&arr3ssi, arr3ssr)) { + fprintf(stdout, " result error, sent:\n"); + print_ssarr3(&arr3ssi); + fprintf(stdout, " got:\n"); + print_ssarr3(arr3ssr); + fprintf(stdout, "\n"); + } + CORBA_free(arr3sso); + CORBA_free(arr3ssr); + return -1; +} + +static int array1_test(IC_Env *env) +{ + int i; + long al[500]; + m_arr1 alo; + m_arr1_slice* alr; + + for (i = 0; i < 500; i++) + al[i]=i; + + fprintf(stdout, "\n======== m_i_array1 test ======\n\n"); + alr = m_i_array1_test(NULL, al, alo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_arr1(al, alo) && cmp_arr1(al, alr)); + if (!cmp_arr1(al, alo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_arr1(al); + fprintf(stdout, " got:\n"); + print_arr1(alo); + fprintf(stdout, "\n"); + } + if (!cmp_arr1(al,alr)) { + fprintf(stdout, " result error, sent:\n"); + print_arr1(al); + fprintf(stdout, " got:\n"); + print_arr1(alr); + fprintf(stdout, "\n"); + } + free(alo); + free(alr); + return -1; +} + +static int array2_test(IC_Env *env) +{ + long dl[2][3] = {{11, 2, 7}, {22, 8 ,13}}; + m_dd dlo; + m_dd_slice* dlr; + + fprintf(stdout, "\n======== m_i_array2 test ======\n\n"); + dlr = m_i_array2_test(NULL, dl, dlo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_dd(dl,dlo) && cmp_dd(dl,dlr)); + if (!cmp_dd(dl,dlo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_dd(dl); + fprintf(stdout, " got:\n"); + print_dd(dlo); + fprintf(stdout, "\n"); + } + if (!cmp_dd(dl,dlr)) { + fprintf(stdout, " result error, sent:\n"); + print_dd(dl); + fprintf(stdout, " got:\n"); + print_dd(dlr); + fprintf(stdout, "\n"); + } + free(*dlr); + return -1; +} + +static int enum_test(IC_Env *env) +{ + m_fruit ei = m_banana, eo, er; + + fprintf(stdout, "\n======== m_i_enum test ======\n\n"); + er = m_i_enum_test(NULL, ei, &eo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ei == eo && ei == er); + if (ei != eo) + fprintf(stdout, " out parameter error, sent: %d, got: %d\n", ei, eo); + if (ei != er) + fprintf(stdout, " result error, sent: %d, got: %d\n", ei, er); + return -1; +} + +static int string1_test(IC_Env *env) +{ + char* si = longtext; + char* so; + char* sr; + + fprintf(stdout, "\n======== m_i_string1 test ======\n\n"); + sr = m_i_string1_test(NULL, si, &so, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, sr)); + if (!cmp_str(si, so)) + fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so); + if (!cmp_str(si, sr)) + fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr); + CORBA_free(so); + CORBA_free(sr); + return -1; +} + +static int string2_test(IC_Env *env) +{ + char* sa[3] = {"hello", "foo", "bar"}; + m_sseq ssi = {3, 3, sa}; + m_sseq *sso, *ssr; + + fprintf(stdout, "\n======== m_i_string2 test ======\n\n"); + ssr = m_i_string2_test(NULL, &ssi, &sso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_sseq(&ssi, sso) && cmp_sseq(&ssi, sso)); + if (!cmp_sseq(&ssi, sso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_sseq(&ssi); + fprintf(stdout, "got:\n"); + print_sseq(sso); + } + if (!cmp_sseq(&ssi, ssr)) { + fprintf(stdout, " result error, sent:\n"); + print_sseq(&ssi); + fprintf(stdout, "got:\n"); + print_sseq(ssr); + } + CORBA_free(sso); + CORBA_free(ssr); + return -1; +} + +static int string3_test(IC_Env *env) +{ + char* si = longtext; + char* so; + char* sr; + + fprintf(stdout, "\n======== m_i_string3 test ======\n\n"); + sr = m_i_string3_test(NULL, si, &so, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, so)); + if (!cmp_str(si, so)) + fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so); + if (!cmp_str(si, sr)) + fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr); + CORBA_free(so); + CORBA_free(sr); + return -1; +} + +static int string4_test(IC_Env *env) +{ + char as1[100] = "a string", as2[200] = "help", as3[200] = "hello there"; + m_strRec stri = { 1, /* dd */ + as1, /* str4 */ + {{'a', 'k'}, {'z', 'g'}, {'n', 'q'}}, /* str7 */ + {3, 3, "buf"}, /* str5 */ + as2, /* str6 */ + {'m', 'f', 'o'}, /* str8 */ + as3, /* str9 */ + {3, 3, "stu"} /* str10 */ + }; + m_strRec *stro, *strr; + + fprintf(stdout, "\n======== m_i_string4 test ======\n\n"); + strr = m_i_string4_test(NULL, &stri, &stro, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_strRec(&stri,stro) && cmp_strRec(&stri,strr)); + if (!cmp_strRec(&stri,stro)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_strRec(&stri); + fprintf(stdout, " got:\n"); + print_strRec(stro); + fprintf(stdout, "\n"); + } + if (!cmp_strRec(&stri,strr)) { + fprintf(stdout, " result error, sent:\n"); + print_strRec(&stri); + fprintf(stdout, " got:\n"); + print_strRec(strr); + fprintf(stdout, "\n"); + } + CORBA_free(stro); + CORBA_free(strr); + return -1; +} + + +static int pid_test(IC_Env *env) +{ + erlang_pid pid = {"", 7, 0, 0}, pido, pidr; + + strcpy(pid.node, this_node), /* this currently running node */ + fprintf(stdout, "\n======== m_i_pid test ======\n\n"); + pidr = m_i_pid_test(NULL, &pid, &pido, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_pid(&pid, &pido) && cmp_pid(&pid, &pidr)); + if (!cmp_pid(&pid, &pido)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_pid(&pid); + fprintf(stdout, "got:\n"); + print_pid(&pido); + } + if (!cmp_pid(&pid, &pidr)) { + fprintf(stdout, " result error, sent:\n"); + print_pid(&pid); + fprintf(stdout, "got:\n"); + print_pid(&pidr); + } + return -1; +} + +static int port_test(IC_Env *env) +{ + erlang_port porti = {"node", 5, 1}, porto, portr; + + fprintf(stdout, "\n======== m_i_port test ======\n\n"); + portr = m_i_port_test(NULL, &porti, &porto, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_port(&porti, &porto) && cmp_port(&porti, &portr)); + if (!cmp_port(&porti, &porto)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_port(&porti); + fprintf(stdout, "got:\n"); + print_port(&porto); + } + if (!cmp_port(&porti, &portr)) { + fprintf(stdout, " result error, sent:\n"); + print_port(&porti); + fprintf(stdout, "got:\n"); + print_port(&portr); + } + return -1; +} + +static int ref_test(IC_Env *env) +{ + erlang_ref refi = { "node1", 3, {1, 2, 3}, 1}, + refo, refr; + + fprintf(stdout, "\n======== m_i_ref test ======\n\n"); + refr = m_i_ref_test(NULL, &refi, &refo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_ref(&refi, &refo) && cmp_ref(&refi, &refr)); + if (!cmp_ref(&refi, &refo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_ref(&refi); + fprintf(stdout, "got:\n"); + print_ref(&refo); + } + if (!cmp_ref(&refi, &refr)) { + fprintf(stdout, " result error, sent:\n"); + print_ref(&refi); + fprintf(stdout, "got:\n"); + print_ref(&refr); + } + return -1; +} + +static int term_test(IC_Env *env) +{ + ETERM *ti, *to, *tr; + + ti = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"); + + fprintf(stdout, "\n======== m_i_term test ======\n\n"); + tr = m_i_term_test(NULL, ti, &to, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(erl_match(ti, to) && erl_match(ti, tr)); + if (!erl_match(ti, to)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_term(ti); + fprintf(stdout, "got:\n"); + print_term(to); + } + if (!erl_match(ti, tr)) { + fprintf(stdout, " result error, sent:\n"); + print_term(ti); + fprintf(stdout, "got:\n"); + print_term(tr); + } + erl_free_term(ti); + erl_free_term(to); + erl_free_term(tr); + return -1; +} + +static int typedef_test(IC_Env *env) +{ + m_banan mbi, mbo; /* erlang_port */ + m_apa mai; /* ETERM* */ + m_apa mao = NULL; + long tl; + + strcpy(mbi.node,"node"); + mbi.id = 15; + mbi.creation = 1; + + fprintf(stdout, "\n======== m_i_typedef test ======\n\n"); + mai = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"); + tl = m_i_typedef_test(NULL, mai, &mbi, &mao, &mbo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(erl_match(mai, mao) && cmp_port(&mbi, &mbo) && tl == 4711); + if (!erl_match(mai, mao)) { + fprintf(stdout, " out parameter error (term), sent:\n"); + print_term(mai); + fprintf(stdout, "got:\n"); + print_term(mao); + } + if (!cmp_port(&mbi, &mbo)) { + fprintf(stdout, " out parameter error (port), sent:\n"); + print_port(&mbi); + fprintf(stdout, "got:\n"); + print_port(&mbo); + } + if (tl != 4711) { + fprintf(stdout, " result error, sent: 4711, got %ld\n", tl); + } + erl_free_term(mai); + erl_free_term(mao); + return -1; +} + +static int inline_sequence_test(IC_Env *env) +{ + int i; + long al[500]; + m_s isi = {4711, {500, 10, al}}, + *iso, *isr; + + for (i = 0; i < 500; i++) + al[i]=i; + fprintf(stdout, "\n======== m_i_inline_sequence test ======\n\n"); + isr = m_i_inline_sequence_test(NULL, &isi, &iso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_s(&isi, iso) && cmp_s(&isi, isr)); + if (!cmp_s(&isi, iso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_s(&isi); + fprintf(stdout, "got:\n"); + print_s(iso); + } + if (!cmp_s(&isi, isr)) { + fprintf(stdout, " result error, sent:\n"); + print_s(&isi); + fprintf(stdout, "got:\n"); + print_s(isr); + } + CORBA_free(iso); + CORBA_free(isr); + return -1; +} + +static int term_sequence_test(IC_Env *env) +{ + ETERM* et_array[4] = { + erl_format("[{apa, 1, 23}, \"string\", {1.23, 45}]"), + erl_format("[{banan, 1, 23}, \"string\", {1.23, 45}]"), + erl_format("[{apelsin, 1, 23}, \"string\", {1.23, 45}]"), + erl_format("[{mango, 1, 23}, \"string\", {1.23, 45}]")}; + m_etseq etsi = {4, 4, et_array}, *etso, *etsr; + + fprintf(stdout, "\n======== m_i_term_sequence test ======\n\n"); + etsr = m_i_term_sequence_test(NULL, &etsi, &etso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_etseq(&etsi, etso) && cmp_etseq(&etsi, etsr)); + if (!cmp_etseq(&etsi, etso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_etseq(&etsi); + fprintf(stdout, "got:\n"); + print_etseq(etso); + } + if (!cmp_etseq(&etsi, etsr)) { + fprintf(stdout, " result error, sent:\n"); + print_etseq(&etsi); + fprintf(stdout, "got:\n"); + print_etseq(etsr); + } + free_etseq_buf(&etsi); + free_etseq_buf(etso); + free_etseq_buf(etsr); + CORBA_free(etso); + CORBA_free(etsr); + return -1; +} + +static int term_struct_test(IC_Env *env) +{ + m_et eti = { erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"), + 121212 }; + m_et eto, etr; + + fprintf(stdout, "\n======== m_i_term_struct test ======\n\n"); + etr = m_i_term_struct_test(NULL, &eti, &eto, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_et(&eti, &eto) && cmp_et(&eti, &etr)); + if (!cmp_et(&eti, &eto)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_et(&eti); + fprintf(stdout, "got:\n"); + print_et(&eto); + } + if (!cmp_et(&eti, &etr)) { + fprintf(stdout, " result error, sent:\n"); + print_et(&eti); + fprintf(stdout, "got:\n"); + print_et(&etr); + } + free_et(&eti); + free_et(&eto); + free_et(&etr); + return -1; +} + +static int wstring1_test(IC_Env *env) +{ + CORBA_wchar wsi[] = {100, 101, 102, 103, 104, 0}, *wso, *wsr; + + fprintf(stdout, "\n======== m_i_wstring1 test ======\n\n"); + wsr = m_i_wstring1_test(NULL, wsi, &wso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_wstr(wsi, wso) && cmp_wstr(wsi, wsr)); + if (!cmp_wstr(wsi, wso)) { + fprintf(stdout, " out parameter error, sent: \n"); + print_wstr(wsi); + fprintf(stdout, "got:\n"); + print_wstr(wso); + } + if (!cmp_wstr(wsi, wsr)) { + fprintf(stdout, " result error, sent: \n"); + print_wstr(wsi); + fprintf(stdout, "got:\n"); + print_wstr(wsr); + } + CORBA_free(wso); + CORBA_free(wsr); + return -1; +} + +/* Compare functions */ +static int cmp_aseq(m_aseq *a1, m_aseq *a2) +{ + int i; + + if (a1->_length != a2->_length) + return 0; + for (i = 0; i < a1->_length; i++) + if (cmp_a(&(a1->_buffer[i]), &(a2->_buffer[i])) == 0) + return 0; + return 1; +} + +static int cmp_a(m_a *a1, m_a *a2) +{ + return a1->l == a2->l && + a1->d == a2->d && + cmp_bseq(&a1->y, &a2->y); +} + +static int cmp_bseq(m_bseq *b1, m_bseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (cmp_b(&(b1->_buffer[i]), &(b2->_buffer[i])) == 0) + return 0; + return 1; +} + +static int cmp_b(m_b *b1, m_b *b2) +{ + return b1->l == b2->l && b1->c == b2->c; +} + +static int cmp_lseq(m_lseq *b1, m_lseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (b1->_buffer[i] != b2->_buffer[i]) + return 0; + return 1; +} + +static int cmp_etseq(m_etseq *b1, m_etseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (!erl_match(b1->_buffer[i], b2->_buffer[i])) + return 0; + return 1; +} + +static int cmp_et(m_et* b1, m_et *b2) +{ + return erl_match(b1->e, b2->e) && b1->l == b2->l; +} + +static int cmp_es(m_es *b1, m_es *b2) +{ + return b1->f == b2->f && b1->l == b2->l; +} + +static int cmp_arr1(m_arr1 b1, m_arr1 b2) +{ + int i; + + for (i = 0; i < 500; i++) + if (b1[i] != b2[i]) + return 0; + return 1; +} + +static int cmp_dd(m_dd b1, m_dd b2) +{ + + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + if (b1[i][j] != b2[i][j]) + return 0; + return 1; +} + + + +static int cmp_strRec(m_strRec *b1, m_strRec *b2) +{ + int i, j; + + if (b1->bb != b2->bb) + return 0; + if (!cmp_str(b1->str4,b2->str4)) + return 0; + if (b1->str5._length != b2->str5._length) + return 0; + for (j = 0; j < b1->str5._length; j++) + if (b1->str5._buffer[j] != b2->str5._buffer[j]) + return 0; + if (!cmp_str(b1->str6,b2->str6)) + return 0; + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + if (b1->str7[i][j] != b2->str7[i][j]) + return 0; + for (j = 0; j < 3; j++) + if (b1->str8[j] != b2->str8[j]) + return 0; + if (!cmp_str(b1->str9,b2->str9)) + return 0; + if (b1->str10._length != b2->str10._length) + return 0; + for (j = 0; j < b1->str10._length; j++) + if (b1->str10._buffer[j] != b2->str10._buffer[j]) + return 0; + return 1; +} + + +static int cmp_sseq(m_sseq *b1, m_sseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (!cmp_str(b1->_buffer[i], b2->_buffer[i])) + return 0; + return 1; +} + + +static int cmp_pid(erlang_pid *p1, erlang_pid *p2) +{ + return cmp_str(p1->node,p2-> node) && + p1->num == p2->num && + p1->serial == p2->serial && + p1->creation == p2->creation; +} + +static int cmp_port(erlang_port *p1, erlang_port *p2) +{ + return cmp_str(p1->node,p2-> node) && p1->id == p2->id; +} + +static int cmp_ref(erlang_ref *p1, erlang_ref *p2) +{ + return cmp_str(p1->node, p2->node) && + p1->len == p2->len && + (p1->len < 1 || p1->n[0] == p2->n[0]) && + (p1->len < 2 || p1->n[1] == p2->n[1]) && + (p1->len < 3 || p1->n[2] == p2->n[2]); +} + +static int cmp_s(m_s *b1, m_s *b2) +{ + int i; + + if (b1->l != b2->l) + return 0; + if (b1->sl._length != b2->sl._length) + return 0; + for (i = 0; i < b1->sl._length; i++) + if (b1->sl._buffer[i] != b2->sl._buffer[i]) + return 0; + return 1; +} + + +static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2) +{ + int i,j; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) { + if (b1->_buffer[i]._length != b2->_buffer[i]._length) + return 0; + for (j = 0; j < b1->_buffer[i]._length; j++) + if (!cmp_str(b1->_buffer[i]._buffer[j], + b2->_buffer[i]._buffer[j])) + return 0; + } + return 1; +} + + + +static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) { + if (!cmp_sarr3(&b1->_buffer[i], &b2->_buffer[i])) + return 0; + } + return 1; +} + +static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) { + if (!cmp_arr3(b1->_buffer[i], b2->_buffer[i])) + return 0; + } + return 1; +} + +static int cmp_arr3(m_arr3 b1, m_arr3 b2) +{ + int i; + + for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) { + if (b1[i] != b2[i]) + return 0; + } + return 1; +} + +/* Print functions */ +static void print_aseq(m_aseq *a) +{ + int i; + fprintf(stdout, "\nm_aseq size: %ld --------\n", a->_length); + for (i = 0; i < a->_length; i++) + print_a(&(a->_buffer[i])); +} + +static void print_a(m_a *a) +{ + fprintf(stdout, "\nm_a --------\n l: %ld\n d:%f\n", a->l, a->d); + print_bseq(&a->y); +} + +static void print_bseq(m_bseq *b) +{ + int i; + + fprintf(stdout, "\nm_bseq size: %ld --------\n",b->_length); + for (i = 0; i < b->_length; i++) + print_b(&(b->_buffer[i])); +} + +static void print_lseq(m_lseq *b) +{ + int i; + + fprintf(stdout, "\nm_lseq size: %ld --------\n",b->_length); + for (i = 0; i < b->_length; i++) + fprintf(stdout, "[%d]: %ld\n", i, b->_buffer[i]); +} + +static void print_b(m_b *b) +{ + fprintf(stdout, "\nm_b --------\n l: %ld\n c: %c\n", b->l, b->c); +} + + +static void print_etseq(m_etseq *b) +{ + int i; + + for (i = 0; i < b->_length; i++) { + fprintf(stdout, "[%d]:\n", i); + erl_print_term(stdout, b->_buffer[i]); + } +} + + +static void print_et(m_et* b) +{ + fprintf(stdout, "\net struct --------\n"); + erl_print_term(stdout, b->e); + fprintf(stdout, "long: %ld\n", b->l); + fprintf(stdout, "\n--------\n"); +} + +static void print_es(m_es *b) +{ + fprintf(stdout, "\nm_es --------\n f: %d\n l: %ld\n", b->f, b->l); +} + + +static void print_arr1(long a[10]) +{ + int i; + + for (i = 0; i < 10; i++) + fprintf(stdout, "\n[%d]: %ld\n", i, a[i]); +} + +static void print_dd(long a[2][3]) +{ + int i, j; + + fprintf(stdout, "\nlong dd[2][3] --------\n"); + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + fprintf(stdout, "\n[%d][%d]: %ld\n", i, j, a[i][j]); +} + + +static void print_strRec(m_strRec* sr) +{ + int i, j; + + fprintf(stdout, "\nboolean bb : %d\n",sr->bb); + fprintf(stdout, "string str4 : %s\n",sr->str4); + fprintf(stdout, "str7[2][3] :\n"); + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + fprintf(stdout, "str7[%d][%d]: %ld\n", i, j, sr->str7[i][j]); + fprintf(stdout, "str5._length : %ld\n",sr->str5._length); + for (j = 0; j < sr->str5._length; j++) + fprintf(stdout, "str5._buffer[%d]: %c\n", j, sr->str5._buffer[j]); + fprintf(stdout, "string str6 : %s\n",sr->str6); + fprintf(stdout, "str8 :\n"); + for (j = 0; j < 3; j++) + fprintf(stdout, "str8[%d]: %c\n", j, sr->str8[j]); + fprintf(stdout, "string str9 : %s\n",sr->str9); + fprintf(stdout, "str10._length : %ld\n",sr->str10._length); + for (j = 0; j < sr->str10._length; j++) + fprintf(stdout, "str10._buffer[%d]: %c\n", j, sr->str10._buffer[j]); +} + +static void print_sseq(m_sseq *b) +{ + int i; + + fprintf(stdout, "\nm_sseq size: %ld --------\n",b->_length); + for (i = 0; i < b->_length; i++) + fprintf(stdout, "%s\n", b->_buffer[i]); + +} + + +static void print_pid(erlang_pid *p) +{ + fprintf(stdout, "\nerlang_pid --------\n node: %s\n num: %d\n " + "serial: %d\n creation: %d\n", + p->node, p->num, p->serial, p->creation); +} + +static void print_port(erlang_port *p) +{ + fprintf(stdout, "\nerlang_port --------\n node: %s\n id: %d\n " + "creation: %d\n", p->node, p->id, p->creation); +} + +static void print_ref(erlang_ref *p) +{ + fprintf(stdout, "\nerlang_ref --------\n node: %s\n len: %d\n " + "n[0]: %d\n n[1]: %d\n n[2]: %d\n creation: %d\n", + p->node, p->len, p->n[0], p->n[1], p->n[2], p->creation); +} + +static void print_term(ETERM *t) +{ + fprintf(stdout, "\nETERM --------\n"); + erl_print_term(stdout, t); + fprintf(stdout, "\n--------\n"); +} + +static void print_s(m_s *p) +{ + int i; + + fprintf(stdout, "\n%ld\n", p->l); + for (i = 0; i < p->sl._length; i++) + fprintf(stdout, "\n[%d]: %ld\n", i, p->sl._buffer[i]); +} + + +static void print_ssstr3(m_ssstr3 *b1) +{ + int i,j; + + fprintf(stdout, "\nSSSTR3 --------\n"); + fprintf(stdout,"b1->_length = %ld\n",b1->_length); + for (i = 0; i < b1->_length; i++) { + fprintf(stdout,"\nb1->_buffer[%d]._length %ld\n", + i, b1->_buffer[i]._length); + for (j = 0; j < b1->_buffer[i]._length; j++) + fprintf(stdout,"b1->_buffer[%d]._buffer[%d] = %s\n", + i, j, b1->_buffer[i]._buffer[j]); + } + fprintf(stdout, "\n--------\n"); +} + +static void print_wstr(CORBA_wchar *ws) +{ + int i = 0; + + fprintf(stdout, "\nwstr --------\n"); + while (ws[i]) { + fprintf(stdout, "[%d]: %ld\n", i, ws[i]); + i++; + } + fprintf(stdout, "\n--------\n"); +} + + +static void print_ssarr3(m_ssarr3 *b1) +{ + int i; + + fprintf(stdout, "\nssarr3 --------\n"); + fprintf(stdout,"length: %ld\n",b1->_length); + fprintf(stdout, "buffer:\n"); + for (i = 0; i < b1->_length; i++) + print_sarr3(&b1->_buffer[i]); + fprintf(stdout, "\n--------\n"); +} + +static void print_sarr3(m_sarr3 *b1) +{ + int i; + + fprintf(stdout, "\nsarr3 --------\n"); + fprintf(stdout,"length: %ld\n",b1->_length); + fprintf(stdout, "buffer:\n"); + for (i = 0; i < b1->_length; i++) + print_arr3(b1->_buffer[i]); + fprintf(stdout, "\n--------\n"); +} + +static void print_arr3(m_arr3 b1) +{ + int i; + + fprintf(stdout, "\narr3 --------\n"); + for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) + fprintf(stdout, "%ld ", b1[i]); + fprintf(stdout, "\n--------\n"); +} + +static void free_etseq_buf(m_etseq *b) +{ + int i; + + for (i = 0; i < b->_length; i++) + erl_free_term(b->_buffer[i]); +} + +static void free_et(m_et* b) +{ + erl_free_term(b->e); +} + +static void showtime(MyTimeval *start, MyTimeval *stop) +{ + MyTimeval elapsed; + + elapsed.tv_sec = stop->tv_sec - start->tv_sec; + elapsed.tv_usec = stop->tv_usec - start->tv_usec; + while (elapsed.tv_usec < 0) { + elapsed.tv_sec -= 1; + elapsed.tv_usec += 1000000; + } + fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec); +} + +static void my_gettimeofday(MyTimeval *tv) +#ifdef __WIN32__ +#define EPOCH_JULIAN_DIFF 11644473600i64 +{ + SYSTEMTIME t; + FILETIME ft; + LONGLONG lft; + + GetSystemTime(&t); + SystemTimeToFileTime(&t, &ft); + memcpy(&lft, &ft, sizeof(lft)); + tv->tv_usec = (long) ((lft / 10i64) % 1000000i64); + tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF); +} +#elif defined VXWORKS +{ + int rate = sysClkRateGet(); /* Ticks per second */ + unsigned long ctick = tickGet(); + tv->tv_sec = ctick / rate; /* secs since reboot */ + tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate; +} +#else +{ + gettimeofday(tv, NULL); +} +#endif diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl b/lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl new file mode 100644 index 0000000000..ccb8f54508 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl @@ -0,0 +1,174 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 2001-2010. 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 "erlang.idl" + + +const short TestConst = 1; + +module m { + + const short TestConst = 2; + + struct b { + long l; + char c; + }; + + struct simple { + long l; + b b_t; + }; + + enum fruit {orange, banana, apple, peach, pear}; + + typedef sequence<long> lseq; + + typedef sequence<b> bseq; + + struct a { + long l; + bseq y; + double d; + }; + + typedef sequence<a> aseq; + + typedef sequence<string> sseq; + typedef string str; + typedef long myLong; + + typedef long arr1[500], dd[2][3]; + + typedef erlang::term apa; + typedef erlang::port banan; + + typedef sequence<erlang::term> etseq; + + struct s { + long l; + sequence<long> sl; + }; + + struct es { + fruit f; + myLong l; + }; + + struct et { + erlang::term e; + long l; + }; + + + typedef sequence<char> str1; + typedef string<12> str2; + typedef char str3[3]; + + typedef sequence<string> sstr3; // sequence of string + typedef sequence<sstr3> ssstr3; // sequence of sequences of strings + + typedef long arr3[3]; // array of long + typedef sequence<arr3> sarr3; // sequence of array + typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings + + struct strRec{ + boolean bb; + string str4; + long str7[3][2]; + sequence<char> str5; + string<12> str6; + str3 str8; + str2 str9; + str1 str10; + }; + + + struct dyn { + long l; + sequence<long> sl; + }; + typedef dyn arr2[1][2]; + + + interface i { + + const short TestConst = 3; + + //arr2 suck(in arr2 x, out arr2 y ); + + ///////////////////////////////// attribute long l; + + // simple types + void void_test(); + long long_test(in long a, out long a1); + long long longlong_test(in long long a, out long long a1); + unsigned short ushort_test(in unsigned short a, out unsigned short a1); + unsigned long ulong_test(in unsigned long a, out unsigned long a1); + unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1); + double double_test(in double a, out double a1); + char char_test(in char a, out char a1); + wchar wchar_test(in wchar a, out wchar a1); + octet octet_test(in octet a, out octet a1); + boolean bool_test(in boolean a, out boolean a1); + + // Seq. and struct tests + b struct_test(in b a, out b a1); + es struct2_test(in es a, out es a1); + //simple struct3_test(in simple x, out simple y); + bseq seq1_test(in bseq a, out bseq a1); + aseq seq2_test(in aseq a, out aseq a1); + lseq seq3_test(in lseq a, out lseq a1); + ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1); + ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1); + + // Array tests + arr1 array1_test(in arr1 a, out arr1 a1); + dd array2_test(in dd a, out dd a1); + + // enum test + fruit enum_test(in fruit a, out fruit a1); + + // string tests + string string1_test(in string a, out string a1); + wstring wstring1_test(in wstring a, out wstring a1); + sseq string2_test(in sseq a, out sseq a1); + str string3_test(in str a, out str a1); + strRec string4_test(in strRec a, out strRec a1); + + // Special erlang types + erlang::pid pid_test(in erlang::pid a, out erlang::pid a1); + erlang::port port_test(in erlang::port a, out erlang::port a1); + erlang::ref ref_test(in erlang::ref a, out erlang::ref a1); + erlang::term term_test(in erlang::term a, out erlang::term a1); + + // typedef test + long typedef_test(in apa a, in banan b, out apa a1, out banan b1); + + // inlined seq. test + s inline_sequence_test(in s a, out s a1); + + // term seq. test + etseq term_sequence_test(in etseq a, out etseq a1); + // term struct test + et term_struct_test(in et a, out et a1); + + }; + +}; diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl b/lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl new file mode 100644 index 0000000000..dffbbb059c --- /dev/null +++ b/lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl @@ -0,0 +1,28 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-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(erl_server). + +-export([run/0, stop/0]). + +run() -> + m_i:oe_create(). + +stop() -> + gen_server:cast(cidl_test, stop). diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl b/lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl new file mode 100644 index 0000000000..cfcaa793a5 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl @@ -0,0 +1,161 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-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(m_i_impl). +-include("m.hrl"). + +-export([init/1, terminate/2, void_test/1, long_test/2, ushort_test/2, + longlong_test/2, ulong_test/2, ulonglong_test/2, + double_test/2, char_test/2, wchar_test/2, octet_test/2, + bool_test/2, struct_test/2, struct2_test/2, seq1_test/2, + seq2_test/2, seq3_test/2, seq4_test/2, seq5_test/2, + array1_test/2, array2_test/2, enum_test/2, string1_test/2, + string2_test/2, string3_test/2, string4_test/2, pid_test/2, + port_test/2, ref_test/2, term_test/2, typedef_test/3, + inline_sequence_test/2, '_set_l'/2, '_get_l'/1, + term_struct_test/2, term_sequence_test/2, wstring1_test/2]). + +-define(PRINTDEBUG(Case), + io:format("erl_server: case: ~p~n" + "erl_server: location: ~p~n", [Case, [?FILE, ?LINE]])). +-define(PRINTDEBUG2(Case, Msg), + io:format("erl_server: case: ~p~n" + "erl_server: Msg: ~p~n" + "erl_server: location: ~p~n", [Case, Msg, [?FILE, ?LINE]])). + +init(Env) -> + {ok, []}. + +terminate(F, R) -> + ok. + +'_get_l'(State) -> + ?PRINTDEBUG("_get_l"), + {reply, State, State}. +void_test(State) -> + ?PRINTDEBUG("void_test"), + {reply, ok, State}. + +'_set_l'(State, V) -> + ?PRINTDEBUG2("_set_l", V), + {reply, ok, V}. +ushort_test(State, V) -> + ?PRINTDEBUG2("ushort_test", V), + {reply, {V, V}, State}. +long_test(State, V) -> + ?PRINTDEBUG2("long_test", V), + {reply, {V, V}, State}. +longlong_test(State, V) -> + ?PRINTDEBUG2("longlong_test", V), + {reply, {V, V}, State}. +ulong_test(State, V) -> + ?PRINTDEBUG2("ulong_test", V), + {reply, {V, V}, State}. +ulonglong_test(State, V) -> + ?PRINTDEBUG2("ulonglong_test", V), + {reply, {V, V}, State}. +double_test(State, V) -> + ?PRINTDEBUG2("double_test", V), + {reply, {V, V}, State}. +char_test(State, V) -> + ?PRINTDEBUG2("char_test", V), + {reply, {V, V}, State}. +wchar_test(State, V) -> + ?PRINTDEBUG2("wchar_test", V), + {reply, {V, V}, State}. +octet_test(State, V) -> + ?PRINTDEBUG2("octet_test", V), + {reply, {V, V}, State}. +bool_test(State, V) -> + ?PRINTDEBUG2("bool_test", V), + {reply, {V, V}, State}. + +struct_test(State, V) -> + ?PRINTDEBUG2("struct_test", V), + {reply, {V, V}, State}. +struct2_test(State, V) -> + ?PRINTDEBUG2("struct2_test", V), + {reply, {V, V}, State}. +seq1_test(State, V) -> + ?PRINTDEBUG2("seq1_test", V), + {reply, {V, V}, State}. +seq2_test(State, V) -> + ?PRINTDEBUG2("seq2_test", V), + {reply, {V, V}, State}. +seq3_test(State, V) -> + ?PRINTDEBUG2("seq3_test", V), + {reply, {V, V}, State}. +seq4_test(State, V) -> + ?PRINTDEBUG2("seq4_test", V), + {reply, {V, V}, State}. +seq5_test(State, V) -> + ?PRINTDEBUG2("seq5_test", V), + {reply, {V, V}, State}. +array1_test(State, V) -> + ?PRINTDEBUG2("array1_test", V), + {reply, {V, V}, State}. +array2_test(State, V) -> + ?PRINTDEBUG2("array2_test", V), + {reply, {V, V}, State}. +enum_test(State, V) -> + ?PRINTDEBUG2("enum_test", V), + {reply, {V, V}, State}. +string1_test(State, V) -> + ?PRINTDEBUG2("string1_test", V), + {reply, {V, V}, State}. +string2_test(State, V) -> + ?PRINTDEBUG2("string2_test", V), + {reply, {V, V}, State}. +string3_test(State, V) -> + ?PRINTDEBUG2("string3_test", V), + {reply, {V, V}, State}. +string4_test(State, V) -> + ?PRINTDEBUG2("string4_test", V), + {reply, {V, V}, State}. +pid_test(State, V) -> + ?PRINTDEBUG2("pid_test", V), + {reply, {V, V}, State}. +port_test(State, V) -> + ?PRINTDEBUG2("port_test", binary_to_list(term_to_binary(V))), + {reply, {V, V}, State}. +ref_test(State, V) -> + ?PRINTDEBUG2("ref_test", binary_to_list(term_to_binary(V))), + {reply, {V, V}, State}. +term_test(State, V) -> + ?PRINTDEBUG2("term_test", V), + {reply, {V, V}, State}. +typedef_test(State, A, B) -> + ?PRINTDEBUG2("typedef_test", [A,B]), + {reply, {4711, A, B}, State}. +inline_sequence_test(State, V) -> + ?PRINTDEBUG2("inline_sequence_test", V), + {reply, {V, V}, State}. +term_sequence_test(State, V) -> + ?PRINTDEBUG2("term_sequence_test", V), + {reply, {V, V}, State}. +term_struct_test(State, V) -> + ?PRINTDEBUG2("term_struct_test", V), + {reply, {V, V}, State}. +wstring1_test(State, V) -> + ?PRINTDEBUG2("wstring1_test", V), + {reply, {V, V}, State}. + + + + diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE.erl b/lib/ic/test/c_client_erl_server_proto_SUITE.erl new file mode 100644 index 0000000000..58309a2221 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_SUITE.erl @@ -0,0 +1,315 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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% +%% +%% + +%%---------------------------------------------------------------------- +%% Purpose : Test suite for c-client/erl-server +%%---------------------------------------------------------------------- + +-module(c_client_erl_server_proto_SUITE). +-include("test_server.hrl"). + +-export([init_per_testcase/2, fin_per_testcase/2, + all/1, void_test/1, long_test/1, long_long_test/1, + unsigned_short_test/1, unsigned_long_test/1, + unsigned_long_long_test/1, double_test/1, char_test/1, + wchar_test/1, octet_test/1, bool_test/1, struct_test/1, + struct2_test/1, seq1_test/1, seq2_test/1, seq3_test/1, + seq4_test/1, seq5_test/1, array1_test/1, array2_test/1, + enum_test/1, string1_test/1, string2_test/1, string3_test/1, + string4_test/1, pid_test/1, port_test/1, ref_test/1, term_test/1, + typedef_test/1, inline_sequence_test/1, term_sequence_test/1, + term_struct_test/1, wstring1_test/1]). + +-define(DEFAULT_TIMEOUT, 20000). +-define(PORT_TIMEOUT, 15000). +-define(ERLANG_SERVER_NAME, idl_erlang_server). +-define(C_CLIENT_NODE_NAME, c_client_idl_test). + +%% Add/remove code path and watchdog before/after each test case. +%% +init_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:add_patha(DataDir), + + %% Since other test suites use the module m_i, we have + %% to make sure we are using the right m_i module. + code:purge(m_i), + code:load_file(m_i), + + WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT), + [{watchdog, WatchDog}| Config]. + +fin_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:del_path(DataDir), + WatchDog = ?config(watchdog, Config), + test_server:timetrap_cancel(WatchDog). + +all(doc) -> + "Test of IC with a C-client and an Erlang generic server. " + "The communication is via Erlang distribution."; +all(suite) -> + [void_test, long_test, long_long_test, unsigned_short_test, + unsigned_long_test, unsigned_long_long_test, double_test, + char_test, wchar_test, octet_test, bool_test, struct_test, + struct2_test, seq1_test, seq2_test, seq3_test, seq4_test, + seq5_test, array1_test, array2_test, enum_test, string1_test, + string2_test, string3_test, string4_test, pid_test, port_test, + ref_test, term_test, typedef_test, inline_sequence_test, + term_sequence_test, term_struct_test, wstring1_test]. + + +array1_test(doc) -> ""; +array1_test(suite) -> []; +array1_test(Config) -> + do_test(array1_test, Config). + +array2_test(doc) -> ""; +array2_test(suite) -> []; +array2_test(Config) -> + do_test(array2_test, Config). + +bool_test(doc) -> ""; +bool_test(suite) -> []; +bool_test(Config) -> + do_test(bool_test, Config). + +char_test(doc) -> ""; +char_test(suite) -> []; +char_test(Config) -> + do_test(char_test, Config). + +double_test(doc) -> ""; +double_test(suite) -> []; +double_test(Config) -> + do_test(double_test, Config). + +enum_test(doc) -> ""; +enum_test(suite) -> []; +enum_test(Config) -> + do_test(enum_test, Config). + +inline_sequence_test(doc) -> ""; +inline_sequence_test(suite) -> []; +inline_sequence_test(Config) -> + do_test(inline_sequence_test, Config). + +long_long_test(doc) -> ""; +long_long_test(suite) -> []; +long_long_test(Config) -> + do_test(long_long_test, Config). + +long_test(doc) -> ""; +long_test(suite) -> []; +long_test(Config) -> + do_test(long_test, Config). + +octet_test(doc) -> ""; +octet_test(suite) -> []; +octet_test(Config) -> + do_test(octet_test, Config). + +pid_test(doc) -> ""; +pid_test(suite) -> []; +pid_test(Config) -> + do_test(pid_test, Config). + +port_test(doc) -> ""; +port_test(suite) -> []; +port_test(Config) -> + do_test(port_test, Config). + +ref_test(doc) -> ""; +ref_test(suite) -> []; +ref_test(Config) -> + do_test(ref_test, Config). + +seq1_test(doc) -> ""; +seq1_test(suite) -> []; +seq1_test(Config) -> + do_test(seq1_test, Config). + +seq2_test(doc) -> ""; +seq2_test(suite) -> []; +seq2_test(Config) -> + do_test(seq2_test, Config). + +seq3_test(doc) -> ""; +seq3_test(suite) -> []; +seq3_test(Config) -> + do_test(seq3_test, Config). + +seq4_test(doc) -> ""; +seq4_test(suite) -> []; +seq4_test(Config) -> + do_test(seq4_test, Config). + +seq5_test(doc) -> ""; +seq5_test(suite) -> []; +seq5_test(Config) -> + do_test(seq5_test, Config). + +string1_test(doc) -> ""; +string1_test(suite) -> []; +string1_test(Config) -> + do_test(string1_test, Config). + +string2_test(doc) -> ""; +string2_test(suite) -> []; +string2_test(Config) -> + do_test(string2_test, Config). + +string3_test(doc) -> ""; +string3_test(suite) -> []; +string3_test(Config) -> + do_test(string3_test, Config). + +string4_test(doc) -> ""; +string4_test(suite) -> []; +string4_test(Config) -> + do_test(string4_test, Config). + +struct2_test(doc) -> ""; +struct2_test(suite) -> []; +struct2_test(Config) -> + do_test(struct2_test, Config). + +struct_test(doc) -> ""; +struct_test(suite) -> []; +struct_test(Config) -> + do_test(struct_test, Config). + +term_sequence_test(doc) -> ""; +term_sequence_test(suite) -> []; +term_sequence_test(Config) -> + do_test(term_sequence_test, Config). + +term_struct_test(doc) -> ""; +term_struct_test(suite) -> []; +term_struct_test(Config) -> + do_test(term_struct_test, Config). + +term_test(doc) -> ""; +term_test(suite) -> []; +term_test(Config) -> + do_test(term_test, Config). + +typedef_test(doc) -> ""; +typedef_test(suite) -> []; +typedef_test(Config) -> + do_test(typedef_test, Config). + +unsigned_long_long_test(doc) -> ""; +unsigned_long_long_test(suite) -> []; +unsigned_long_long_test(Config) -> + do_test(unsigned_long_long_test, Config). + +unsigned_long_test(doc) -> ""; +unsigned_long_test(suite) -> []; +unsigned_long_test(Config) -> + do_test(unsigned_long_test, Config). + +unsigned_short_test(doc) -> ""; +unsigned_short_test(suite) -> []; +unsigned_short_test(Config) -> + do_test(unsigned_short_test, Config). + +void_test(doc) -> ""; +void_test(suite) -> []; +void_test(Config) -> + do_test(void_test, Config). + +wchar_test(doc) -> ""; +wchar_test(suite) -> []; +wchar_test(Config) -> + do_test(wchar_test, Config). + +wstring1_test(doc) -> ""; +wstring1_test(suite) -> []; +wstring1_test(Config) -> + do_test(wstring1_test, Config). + + +%% It is here that all tests really are done. +%% + +do_test(Case, Config) -> + %% Trap exits + process_flag(trap_exit, true), + %% Start the server + {ok, _Pid} = m_i:oe_create_link([], {local, ?ERLANG_SERVER_NAME}), + Node = atom_to_list(node()), + %% [NodeName, HostName] = string:tokens(Node, "@"), + DataDir = ?config(data_dir, Config), + %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]), + Cookie = atom_to_list(erlang:get_cookie()), + %% Start C-client node as a port program. + Cmd = filename:join([DataDir, "c_client"]) ++ + " -this-node-name " ++ atom_to_list(?C_CLIENT_NODE_NAME) ++ + " -peer-node " ++ Node ++ + " -peer-process-name " ++ atom_to_list(?ERLANG_SERVER_NAME) ++ + " -cookie " ++ Cookie ++ + " -test-case " ++ atom_to_list(Case), + Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]), + Res = wait_for_completion(Port), + %% Kill off node if there was timeout + case Res of + {error, timeout} -> + catch rpc:cast(?C_CLIENT_NODE_NAME, erlang, halt, [1]); + _ -> + ok + end, + process_flag(trap_exit, false), + catch m_i:stop(?ERLANG_SERVER_NAME), + ok = Res. + + +%% Wait for eof *and* exit status, but return if exit status indicates +%% an error, or we have been waiting more than PORT_TIMEOUT seconds. +%% +wait_for_completion(Port) -> + wait_for_completion(Port, 0). + +wait_for_completion(Port, N) when N < 2 -> + receive + {Port, {data, Bytes}} -> + %% Relay output + io:format("~s", [Bytes]), + wait_for_completion(Port, N); + {Port, {exit_status, 0}} -> + wait_for_completion(Port, N + 1); + {Port, {exit_status, Status}} -> + {error, Status}; + {Port, eof} -> + wait_for_completion(Port, N + 1); + {'EXIT', Port, Reason} -> + io:format("Port exited with reason: ~w~n", [Reason]), + wait_for_completion(Port, N); + {'EXIT', From, Reason} -> + io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]), + wait_for_completion(Port, N) + after ?PORT_TIMEOUT -> + {error, timeout} + end; +wait_for_completion(_, _) -> + ok. + + + diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src new file mode 100644 index 0000000000..3dcd1d9387 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src @@ -0,0 +1,146 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2003-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% +# +# +# Makefile.src for c_client_erl_server test +# Note: This file *must* work for both Unix and Windows +# +# We use both `rm' (Unix) and `del' (Windows) for removing files, but +# with a `-' in front so that the error in not finding `rm' (`del') on +# Windows (Unix) is ignored. +# +# VxWorks? XXX +# + +.SUFFIXES: +.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@ + + +# Variables from ts: +# + +ERL_INCLUDE = @erl_include@ + +IC_INCLUDE_PATH = @ic_include_path@ +IC_LIB = @ic_libpath@@DS@@ic_lib@ + +ERL_INTERFACE_INCLUDE = @erl_interface_include@ +ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@ +ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@ +ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@ +ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@ + +CC = @CC@ +## XXX Should set warning flag with a DEBUG_FLAG +CFLAGS = @CFLAGS@ @DEFS@ -I@erl_include@ \ + -I@ic_include_path@ -I@erl_interface_include@ + +LD = @LD@ +LDFLAGS = @CROSSLDFLAGS@ +LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \ + $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS) +ERLC = erlc + +# Generated C header files +GEN_H_FILES = \ + m.h \ + m_i.h \ + oe_c_erl_test.h + +# Generated C files +GEN_C_FILES = \ + m.c \ + m_i.c \ + oe_c_erl_test.c \ + oe_code_m_a.c \ + oe_code_m_arr1.c \ + oe_code_m_arr2.c \ + oe_code_m_arr3.c \ + oe_code_m_aseq.c \ + oe_code_m_b.c \ + oe_code_m_bseq.c \ + oe_code_m_dd.c \ + oe_code_m_dyn.c \ + oe_code_m_dyn_sl.c \ + oe_code_m_es.c \ + oe_code_m_et.c \ + oe_code_m_etseq.c \ + oe_code_m_fruit.c \ + oe_code_m_lseq.c \ + oe_code_m_s.c \ + oe_code_m_s_sl.c \ + oe_code_m_sarr3.c \ + oe_code_m_simple.c \ + oe_code_m_ssarr3.c \ + oe_code_m_sseq.c \ + oe_code_m_ssstr3.c \ + oe_code_m_sstr3.c \ + oe_code_m_str1.c \ + oe_code_m_str3.c \ + oe_code_m_strRec.c \ + oe_code_m_strRec_str5.c \ + oe_code_m_strRec_str7.c + +GEN_HRL_FILES = \ + m.hrl \ + m_i.hrl \ + oe_c_erl_test.hrl + +GEN_ERL_FILES = \ + m.erl \ + m_arr2.erl \ + m_arr3.erl \ + m_i.erl \ + m_str3.erl \ + oe_c_erl_test.erl + +C_FILES = $(GEN_C_FILES) c_client.c my.c + +OBJS = $(C_FILES:.c=@obj@) + +PGMS = c_client@exe@ + +ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl + +EBINS = $(ERL_FILES:.erl=.@EMULATOR@) + + +all: $(PGMS) $(EBINS) + +clean: + -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + +$(PGMS): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" \ + "+{user_protocol,my}" c_erl_test.idl + +$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl + +.c@obj@: + $(CC) -c -o $*@obj@ $(CFLAGS) $< + +.erl.@EMULATOR@: + $(ERLC) -I $(IC_INCLUDE_PATH) $< + diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c new file mode 100644 index 0000000000..f352b91fd5 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c @@ -0,0 +1,1763 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2003-2010. 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% + * + */ +/* C-client for test of IC. + * + * TODO: + * + * 1. XXX #includes for VxWorks, Windows + */ + +#include <stdio.h> +#include <stdlib.h> + +#ifndef __WIN32__ +# include <unistd.h> +#endif + +#include <string.h> + +#ifdef __WIN32__ +# include <time.h> +# include <sys/timeb.h> +#elif defined VXWORKS +#include <time.h> +#include <sys/times.h> +#else +#include <sys/time.h> +#endif + +#include <ctype.h> + +#ifdef __WIN32__ +# include <winsock2.h> +# include <windows.h> +#else +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netdb.h> +#endif + +#include "ei.h" +#include "erl_interface.h" +#include "m_i.h" + +#define HOSTNAMESZ 256 +#define NODENAMESZ 512 + +#define INBUFSZ 10 +#define OUTBUFSZ 0 + +#define MAXTRIES 5 + +#define CHECK_EXCEPTION(x) \ + if ((x)->_major != CORBA_NO_EXCEPTION) { \ + fprintf(stderr,"\n\nException: %s\n\n", \ + (char *)CORBA_exception_value((x))); \ + CORBA_exception_free((x)); \ + return -1; \ + } \ + +/* XXX Should free things here too! */ +#define RETURN_IF_OK(x) \ + if ((x)) {\ + fprintf(stdout, "ok\n");\ + return 0;\ + }\ + +#define cmp_str(x,y) (!strcmp((x),(y))) +#define cmp_wstr(x,y) (!ic_wstrcmp((x),(y))) + +typedef CORBA_Environment IC_Env; + +typedef int (*TestFunc)(IC_Env *); +typedef struct { + char *name; + TestFunc func; +} TestCase; + +static char longtext[] = +"Introduction The IC application is an IDL compiler implemented in Erlang." +" The IDL compiler generates client stubs and server skeletons." +" Several back-ends are supported, and they fall into three main groups." +" For more details on IC compiler options consult the ic(3) manual page." +" Argument passing cases 1 Caller allocates all necessary storage," +" except that which may be encapsulated and managed within the parameter itself." +" 2 The caller allocates a pointer and passes it by reference to the callee." +" The callee sets the pointer to point to a valid instance of the parameter's type." +" The caller is responsible for releasing the returned storage." +" Following completion of a request, the caller is not allowed to modify any values" +" in the returned storage. To do so the caller must first copy the returned instance" +" into a new instance, then modify the new instance. 3 The caller allocates a" +" pointer to an array slice which has all the same dimensions of the original" +" array except the first, and passes it by reference to the callee. The callee sets" +" the pointer to point to a valid instance of the array. The caller is responsible for" +" releasing the returned storage. Following completion of a request, the caller is not" +" allowed to modify any values in the returned storage. To do so the caller must first" +" copy the returned instance into a new instance, then modify the new instance." +" Generated Files Two files will be generated for each scope. One set of files will be" +" generated for each module and each interface scope. An extra set is generated for" +" those definitions at top level scope. One of the files is a header file(.h), and the" +" other file is a C source code file (.c). In addition to these files a number of C" +" source files will be generated for type encodings, they are named according to the " +"following template: oe_code_<type>.c."; +static char this_node[NODENAMESZ + 1]; +static char *progname; + +/* Test function prototypes */ + +static int void_test(IC_Env *env); +static int long_test(IC_Env *env); +static int long_long_test(IC_Env *env); +static int unsigned_short_test(IC_Env *env); +static int unsigned_long_test(IC_Env *env); +static int unsigned_long_long_test(IC_Env *env); +static int double_test(IC_Env *env); +static int char_test(IC_Env *env); +static int wchar_test(IC_Env *env); +static int octet_test(IC_Env *env); +static int bool_test(IC_Env *env); +static int struct_test(IC_Env *env); +static int struct2_test(IC_Env *env); +static int seq1_test(IC_Env *env); +static int seq2_test(IC_Env *env); +static int seq3_test(IC_Env *env); +static int seq4_test(IC_Env *env); +static int seq5_test(IC_Env *env); +static int array1_test(IC_Env *env); +static int array2_test(IC_Env *env); +static int enum_test(IC_Env *env); +static int string1_test(IC_Env *env); +static int string2_test(IC_Env *env); +static int string3_test(IC_Env *env); +static int string4_test(IC_Env *env); +static int pid_test(IC_Env *env); +static int port_test(IC_Env *env); +static int ref_test(IC_Env *env); +static int term_test(IC_Env *env); +static int typedef_test(IC_Env *env); +static int inline_sequence_test(IC_Env *env); +static int term_sequence_test(IC_Env *env); +static int term_struct_test(IC_Env *env); +static int wstring1_test(IC_Env *env); + +static TestCase test_cases[] = { + {"void_test", void_test}, + {"long_test", long_test}, + {"long_long_test", long_long_test}, + {"unsigned_short_test", unsigned_short_test}, + {"unsigned_long_test", unsigned_long_test}, + {"unsigned_long_long_test", unsigned_long_long_test}, + {"double_test", double_test}, + {"char_test", char_test}, + {"wchar_test", wchar_test}, + {"octet_test", octet_test}, + {"bool_test", bool_test}, + {"struct_test", struct_test}, + {"struct2_test", struct2_test}, + {"seq1_test", seq1_test}, + {"seq2_test", seq2_test}, + {"seq3_test", seq3_test}, + {"seq4_test", seq4_test}, + {"seq5_test", seq5_test}, + {"array1_test", array1_test}, + {"array2_test", array2_test}, + {"enum_test", enum_test}, + {"string1_test", string1_test}, + {"string2_test", string2_test}, + {"string3_test", string3_test}, + {"string4_test", string4_test}, + {"pid_test", pid_test}, + {"port_test", port_test}, + {"ref_test", ref_test}, + {"term_test", term_test}, + {"typedef_test", typedef_test}, + {"inline_sequence_test", inline_sequence_test}, + {"term_sequence_test", term_sequence_test}, + {"term_struct_test", term_struct_test}, + {"wstring1_test", wstring1_test}, + {"", NULL} +}; + +/* Other prototypes */ +static int cmp_aseq(m_aseq *a1, m_aseq *a2); +static int cmp_a(m_a *a1, m_a *a2); +static int cmp_bseq(m_bseq *b1, m_bseq *b2); +static int cmp_b(m_b *b1, m_b *b2); +static int cmp_lseq(m_lseq *b1, m_lseq *b2); +static int cmp_etseq(m_etseq *b1, m_etseq *b2); +static int cmp_et(m_et* b1, m_et *b2); +static int cmp_es(m_es *b1, m_es *b2); +static int cmp_arr1(m_arr1 b1, m_arr1 b2); +static int cmp_dd(m_dd b1, m_dd b2); +static int cmp_strRec(m_strRec *b1, m_strRec *b2); +static int cmp_sseq(m_sseq *b1, m_sseq *b2); +static int cmp_pid(erlang_pid *p1, erlang_pid *p2); +static int cmp_port(erlang_port *p1, erlang_port *p2); +static int cmp_ref(erlang_ref *p1, erlang_ref *p2); +static int cmp_s(m_s *b1, m_s *b2); +static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2); +static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2); +static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2); +static int cmp_arr3(m_arr3 b1, m_arr3 b2); + +static void print_aseq(m_aseq *a); +static void print_a(m_a *a); +static void print_bseq(m_bseq *b); +static void print_lseq(m_lseq *b); +static void print_b(m_b *b); +static void print_etseq(m_etseq *b); +static void print_et(m_et* b); +static void print_es(m_es *b); +static void print_arr1(long a[500]); +static void print_dd(long a[2][3]); +static void print_strRec(m_strRec* sr); +static void print_sseq(m_sseq *b); +static void print_pid(erlang_pid *p); +static void print_port(erlang_port *p); +static void print_ref(erlang_ref *p); +static void print_term(ETERM *t); +static void print_s(m_s *p); +static void print_ssstr3(m_ssstr3 *b1); +static void print_ssarr3(m_ssarr3 *b1); +static void print_sarr3(m_sarr3 *b1); +static void print_arr3(m_arr3 b1); +static void print_wstr(CORBA_wchar *ws); + +static void free_etseq_buf(m_etseq *b); +static void free_et(m_et* b); + +#ifdef __WIN32__ +typedef struct { + long tv_sec; + long tv_usec; +} MyTimeval; +#else +typedef struct timeval MyTimeval; +#endif +static void my_gettimeofday(MyTimeval *tv); +static void showtime(MyTimeval *start, MyTimeval *stop); +static void usage(void); +static void done(int r); + + + +/* main */ + +#ifdef VXWORKS +int client(int argc, char **argv) +#else +int main(int argc, char **argv) +#endif +{ + struct hostent *hp; + erlang_pid pid; + MyTimeval start, stop; + int i, fd, ires, tres; + IC_Env *env; + int tries = 0; + char *this_node_name = NULL; + char *peer_node = NULL; + char *peer_process_name = NULL; + char *cookie = NULL; + char host[HOSTNAMESZ + 1]; + TestFunc test_func = NULL; + TestCase *test_case; + char *test_case_name = NULL; + +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + + if (WSAStartup(wVersionRequested, &wsaData) != 0) { + fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL"); + exit(1); + } +#endif + + progname = argv[0]; + host[HOSTNAMESZ] = '\0'; + if (gethostname(host, HOSTNAMESZ) < 0) { + fprintf(stderr, "Can't find own hostname\n"); + done(1); + } + if ((hp = gethostbyname(host)) == 0) { + fprintf(stderr, "Can't get ip address for host %s\n", host); + done(1); + } + for (i = 1; i < argc; i++) { + if (cmp_str(argv[i], "-help")) { + usage(); + done(0); + } else if (cmp_str(argv[i], "-this-node-name")) { + i++; + this_node_name = argv[i]; + } else if (cmp_str(argv[i], "-peer-node")) { + i++; + peer_node = argv[i]; + } else if (cmp_str(argv[i], "-peer-process-name")) { + i++; + peer_process_name = argv[i]; + } else if (cmp_str(argv[i], "-cookie")) { + i++; + cookie = argv[i]; + } else if (cmp_str(argv[i], "-test-case")) { + i++; + test_case_name = argv[i]; + } else { + fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]); + usage(); + done(1); + } + } + + if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL + || peer_process_name == NULL || cookie == NULL) { + fprintf(stderr, "Error: missing option\n"); + usage(); + done(1); + } + + test_case = test_cases; + while (test_case->func) { + if (cmp_str(test_case->name, test_case_name)) { + test_func = test_case->func; + break; + } + test_case++; + } + if (test_func == NULL) { + fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name); + done(1); + } + + /* Behead hostname at first dot */ + for (i=0; host[i] != '\0'; i++) { + if (host[i] == '.') { host[i] = '\0'; break; } + } + sprintf(this_node, "%s@%s", this_node_name, host); + fprintf(stderr, "c_client: this node: \"%s\"\n", this_node); + fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node); + fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name); + + fprintf(stderr, "c_client: starting\n"); + + /* initialize erl_interface */ + erl_init(NULL, 0); + + for (tries = 0; tries < MAXTRIES; tries++) { + + /* connect to erlang node */ + + ires = erl_connect_xinit(host, this_node_name, this_node, + (struct in_addr *)*hp->h_addr_list, + cookie, 0); + + fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires); + + fd = erl_connect(peer_node); + fprintf(stderr, "c_client: erl_connect(): %d\n", fd); + + if (fd >= 0) + break; + fprintf(stderr, "c_client: cannot connect, retrying\n"); + } + if (fd < 0) { + fprintf(stderr, "c_client: cannot connect, exiting\n"); + done(1); + } + env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ); + env->_fd = fd; + strcpy(env->_regname, peer_process_name); + env->_to_pid = NULL; + env->_from_pid = &pid; + + strcpy(pid.node, this_node); + pid.num = fd; + pid.serial = 0; + pid.creation = 0; + + my_gettimeofday(&start); + tres = test_func(env); /* Call test case */ + my_gettimeofday(&stop); + showtime(&start, &stop); + erl_close_connection(fd); + + printf("c_client: env->_inbuf before : %d\n", INBUFSZ); + printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ); + printf("c_client: env->_inbuf after : %d\n", env->_inbufsz); + printf("c_client: env->_outbuf after : %d\n", env->_outbufsz); + + CORBA_free(env->_inbuf); + CORBA_free(env->_outbuf); + CORBA_free(env); + done(tres); +} + +static void usage() +{ + fprintf(stderr, "Usage: %s [-help] -this-node-name <name> " + "-peer-node <nodename> -peer-process-name <name> " + "-cookie <cookie> -test-case <test case name>\n", progname); + fprintf(stderr, "Example:\n %s -this-node-name kalle " + "-peer-node olle@home -peer-process-name idltest " + "-cookie oa678er -test-case octet_test\n", progname); +} + +static void done(int r) +{ +#ifdef __WIN32__ + WSACleanup(); +#endif + exit(r); +} + + +/* TESTS */ + +static int void_test(IC_Env *env) +{ + fprintf(stdout, "\n======== m_i_void test ======\n\n"); + m_i_void_test(NULL,env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(1); +} + +static int long_test(IC_Env *env) +{ + long l = 4711, lo, lr; + + fprintf(stdout, "\n======== m_i_long test ======\n\n"); + lr = m_i_long_test(NULL, l, &lo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(l == lo && l == lr); + if (l != lo) + fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", l, lo); + if (l != lr) + fprintf(stdout, " result error, sent: %ld, got: %ld\n", l, lr); + return -1; +} + +static int long_long_test(IC_Env *env) +{ + CORBA_long_long ll = 4711, llo, llr; + + fprintf(stdout, "\n======== m_i_longlong test ======\n\n"); + llr = m_i_longlong_test(NULL, ll, &llo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ll == llo && ll == llr); + if (ll != llo) + fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", + ll, llo); + if (ll != llr) + fprintf(stdout, " result error, sent: %ld, got: %ld\n", ll, llr); + return -1; +} + +static int unsigned_short_test(IC_Env *env) +{ + unsigned short x, y = 2, z; + + fprintf(stdout, "\n======== m_i_ushort test ======\n\n"); + x = m_i_ushort_test(NULL, y, &z, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(y == z && y == x); + if (y != z) + fprintf(stdout, " out parameter error, sent: %d, got: %d\n", y, z); + if (y != x) + fprintf(stdout, " result error, sent: %d, got: %d\n", y, x); + return -1; +} + + +static int unsigned_long_test(IC_Env *env) +{ + unsigned long ul = 5050, ulo, ulr; + + fprintf(stdout, "\n======== m_i_ulong test ======\n\n"); + ulr = m_i_ulong_test(NULL, ul, &ulo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ul == ulo && ul == ulr); + if (ul != ulo) + fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n", + ul, ulo); + if (ul != ulr) + fprintf(stdout, " result error, sent: %lu, got: %lu\n", ul, ulr); + return -1; +} + +/* + * Note: CORBA_unsigned_long_long is in fact a plain long. + */ +static int unsigned_long_long_test(IC_Env *env) +{ + CORBA_unsigned_long_long ull = 5050, ullo, ullr; + + fprintf(stdout, "\n======== m_i_ulonglong test ======\n\n"); + ullr = m_i_ulonglong_test(NULL, ull, &ullo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ull == ullo && ull == ullr); + if (ull != ullo) + fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n", + ull, ullo); + if (ull != ullr) + fprintf(stdout, " result error, sent: %lu, got: %lu\n", + ull, ullr); + return -1; +} + +static int double_test(IC_Env *env) +{ + double d = 12.1212, db, dr; + + fprintf(stdout, "\n======== m_i_double test ======\n\n"); + dr = m_i_double_test(NULL, d, &db, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(d == db && d == dr); + if (d != db) + fprintf(stdout, " out parameter error, sent: %f, got: %f\n", d, db); + if (d != dr) + fprintf(stdout, " result error, sent: %f, got: %f\n", d, dr); + return -1; +} + +static int char_test(IC_Env *env) +{ + char c = 'g', co, cr; + + /* char test */ + fprintf(stdout, "\n======== m_i_char test ======\n\n"); + cr = m_i_char_test(NULL, c, &co, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(c == co && c == cr); + if (c !=co) + fprintf(stdout, " out parameter error, sent: %c, got: %c\n", c, co); + if (c != cr) + fprintf(stdout, " result error, sent: %c, got: %c\n", c, cr); + return -1; +} + +static int wchar_test(IC_Env *env) +{ + CORBA_wchar wc = 103, wco, wcr; + + fprintf(stdout, "\n======== m_i_wchar test ======\n\n"); + wcr = m_i_wchar_test(NULL, wc, &wco, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(wc == wco && wc == wcr); + if (wc != wco) + fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n", + wc, wco); + if (wc != wcr) + fprintf(stdout, " result error, sent: %lu, got: %lu\n", + wc, wcr); + return -1; +} + +static int octet_test(IC_Env *env) +{ + char o ='r', oo, or; + + fprintf(stdout, "\n======== m_i_octet test ======\n\n"); + or = m_i_octet_test(NULL, o, &oo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(o == oo && o == or); + if (o != oo) + fprintf(stdout, " out parameter error, sent: %c, got: %c\n", o, oo); + if (o != or) + fprintf(stdout, " result error, sent: %c, got: %c\n", o, or); + return -1; +} + +static int bool_test(IC_Env *env) +{ + unsigned char i = 0, io, ir; + + fprintf(stdout, "\n======== m_i_bool test ======\n\n"); + ir = m_i_bool_test(NULL, i, &io, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(i == io && i == ir); + if (i != io) + fprintf(stdout, " out parameter error, sent: %d, got: %d\n", i, io); + if (i != ir) + fprintf(stdout, " result error, sent: %d, got: %d\n", i, ir); + return -1; +} + +static int struct_test(IC_Env *env) +{ + m_b b = {4711, 'a'}, bo, br; + + fprintf(stdout, "\n======== m_i_struct test ======\n\n"); + br = m_i_struct_test(NULL, &b, &bo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_b(&b, &bo) && cmp_b(&b, &br)); + if (!cmp_b(&b, &bo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_b(&b); + fprintf(stdout, " got:\n"); + print_b(&bo); + fprintf(stdout, "\n"); + } + if (!cmp_b(&b, &br)) { + fprintf(stdout, " result error, sent:\n"); + print_b(&b); + fprintf(stdout, " got:\n"); + print_b(&br); + fprintf(stdout, "\n"); + } + return -1; +} + +static int struct2_test(IC_Env *env) +{ + m_es esi = {m_peach, 5050}, eso, esr; + + fprintf(stdout, "\n======== m_i_struct2 test ======\n\n"); + esr = m_i_struct2_test(NULL, &esi, &eso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_es(&esi, &eso) && cmp_es(&esi, &esr)); + if (!cmp_es(&esi, &eso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_es(&esi); + fprintf(stdout, " got:\n"); + print_es(&eso); + fprintf(stdout, "\n"); + } + if (!cmp_es(&esi, &esr)) { + fprintf(stdout, " result error, sent:\n"); + print_es(&esi); + fprintf(stdout, " got:\n"); + print_es(&esr); + fprintf(stdout, "\n"); + } + return -1; +} + + +static int seq1_test(IC_Env *env) +{ + m_bseq bs, *bso, *bsr; + + m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}}; + bs._length = 3; + bs._buffer = ba; + + fprintf(stdout, "\n======== m_i_seq1 test ======\n\n"); + bsr = m_i_seq1_test(NULL, &bs, &bso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_bseq(&bs, bso) && cmp_bseq(&bs, bsr)); + if (!cmp_bseq(&bs, bso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_bseq(&bs); + fprintf(stdout, " got:\n"); + print_bseq(bso); + fprintf(stdout, "\n"); + } + if (!cmp_bseq(&bs, bsr)) { + fprintf(stdout, " result error, sent:\n"); + print_bseq(&bs); + fprintf(stdout, " got:\n"); + print_bseq(bsr); + fprintf(stdout, "\n"); + } + CORBA_free(bso); + CORBA_free(bsr); + return -1; +} + +static int seq2_test(IC_Env *env) +{ + m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}}; + m_a a; + m_a aa[2]; + m_aseq as, *aso, *asr; + + a.l = 9999; + a.y._length = 3; + a.y._buffer = ba; + a.d = 66.89898989; + + aa[0] = a; + aa[1] = a; + as._length = 2; + as._buffer = aa; + + fprintf(stdout, "\n======== m_i_seq2 test ======\n\n"); + asr = m_i_seq2_test(NULL, &as, &aso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_aseq(&as, aso) && cmp_aseq(&as, asr)); + if (!cmp_aseq(&as, aso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_aseq(&as); + fprintf(stdout, " got:\n"); + print_aseq(aso); + fprintf(stdout, "\n"); + } + if (!cmp_aseq(&as, asr)) { + fprintf(stdout, " result error, sent:\n"); + print_aseq(&as); + fprintf(stdout, " got:\n"); + print_aseq(asr); + fprintf(stdout, "\n"); + } + CORBA_free(aso); + CORBA_free(asr); + return -1; +} + +static int seq3_test(IC_Env *env) +{ + m_lseq lsi, *lso, *lsr; + long al[500]; + int i=0; + + for (i = 0; i < 500; i++) + al[i]=i; + lsi._length = 500; + lsi._buffer = al; + + fprintf(stdout, "\n======== m_i_seq3 test ======\n\n"); + lsr = m_i_seq3_test(NULL, &lsi, &lso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_lseq(&lsi, lso) && cmp_lseq(&lsi, lsr)); + if (!cmp_lseq(&lsi, lso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_lseq(&lsi); + fprintf(stdout, " got:\n"); + print_lseq(lso); + fprintf(stdout, "\n"); + } + if (!cmp_lseq(&lsi, lsr)) { + fprintf(stdout, " result error, sent:\n"); + print_lseq(&lsi); + fprintf(stdout, " got:\n"); + print_lseq(lsr); + fprintf(stdout, "\n"); + } + CORBA_free(lso); + CORBA_free(lsr); + return -1; +} + +static int seq4_test(IC_Env *env) +{ + char *stra0[3] = {"a", "long", "time"}; + char *stra1[3] = {"ago", "there", "was"}; + char *stra2[3] = {"a", "buggy", "compiler"}; + m_sstr3 str3s[3] = {{3, 3, stra0}, {3, 3, stra1}, {3, 3, stra2}}; + m_ssstr3 str3ssi = {3, 3, str3s}; + m_ssstr3 *str3sso, *str3ssr; + + fprintf(stdout, "\n======== m_i_seq4 test ======\n\n"); + str3ssr = m_i_seq4_test(NULL, &str3ssi, &str3sso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_ssstr3(&str3ssi, str3sso) && + cmp_ssstr3(&str3ssi, str3ssr)); + if (!cmp_ssstr3(&str3ssi, str3sso)){ + fprintf(stdout, " out parameter error, sent:\n"); + print_ssstr3(&str3ssi); + fprintf(stdout, " got:\n"); + print_ssstr3(str3sso); + fprintf(stdout, "\n"); + } + if (!cmp_ssstr3(&str3ssi, str3ssr)) { + fprintf(stdout, " result error, sent:\n"); + print_ssstr3(&str3ssi); + fprintf(stdout, " got:\n"); + print_ssstr3(str3ssr); + fprintf(stdout, "\n"); + } + CORBA_free(str3sso); + CORBA_free(str3ssr); + return -1; +} + +static int seq5_test(IC_Env *env) +{ + m_arr3 arr3a[3] = { + {4711, 18931947, 3}, + {4711, 18931947, 3}, + {4711, 18931947, 3}}; + m_sarr3 arr3sa[3] = {{3, 3, arr3a}, {3, 3, arr3a}, {3, 3, arr3a}}; + m_ssarr3 arr3ssi = {3, 3, arr3sa}; + m_ssarr3 *arr3sso; + m_ssarr3 *arr3ssr; + + fprintf(stdout, "\n======== m_i_seq5 test ======\n\n"); + arr3ssr = m_i_seq5_test(NULL, &arr3ssi, &arr3sso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_ssarr3(&arr3ssi, arr3sso) && + cmp_ssarr3(&arr3ssi, arr3ssr)); + if (!cmp_ssarr3(&arr3ssi, arr3sso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_ssarr3(&arr3ssi); + fprintf(stdout, " got:\n"); + print_ssarr3(arr3sso); + fprintf(stdout, "\n"); + } + if (!cmp_ssarr3(&arr3ssi, arr3ssr)) { + fprintf(stdout, " result error, sent:\n"); + print_ssarr3(&arr3ssi); + fprintf(stdout, " got:\n"); + print_ssarr3(arr3ssr); + fprintf(stdout, "\n"); + } + CORBA_free(arr3sso); + CORBA_free(arr3ssr); + return -1; +} + +static int array1_test(IC_Env *env) +{ + int i; + long al[500]; + m_arr1 alo; + m_arr1_slice* alr; + + for (i = 0; i < 500; i++) + al[i]=i; + + fprintf(stdout, "\n======== m_i_array1 test ======\n\n"); + alr = m_i_array1_test(NULL, al, alo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_arr1(al, alo) && cmp_arr1(al, alr)); + if (!cmp_arr1(al, alo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_arr1(al); + fprintf(stdout, " got:\n"); + print_arr1(alo); + fprintf(stdout, "\n"); + } + if (!cmp_arr1(al,alr)) { + fprintf(stdout, " result error, sent:\n"); + print_arr1(al); + fprintf(stdout, " got:\n"); + print_arr1(alr); + fprintf(stdout, "\n"); + } + free(alo); + free(alr); + return -1; +} + +static int array2_test(IC_Env *env) +{ + long dl[2][3] = {{11, 2, 7}, {22, 8 ,13}}; + m_dd dlo; + m_dd_slice* dlr; + + fprintf(stdout, "\n======== m_i_array2 test ======\n\n"); + dlr = m_i_array2_test(NULL, dl, dlo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_dd(dl,dlo) && cmp_dd(dl,dlr)); + if (!cmp_dd(dl,dlo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_dd(dl); + fprintf(stdout, " got:\n"); + print_dd(dlo); + fprintf(stdout, "\n"); + } + if (!cmp_dd(dl,dlr)) { + fprintf(stdout, " result error, sent:\n"); + print_dd(dl); + fprintf(stdout, " got:\n"); + print_dd(dlr); + fprintf(stdout, "\n"); + } + free(*dlr); + return -1; +} + +static int enum_test(IC_Env *env) +{ + m_fruit ei = m_banana, eo, er; + + fprintf(stdout, "\n======== m_i_enum test ======\n\n"); + er = m_i_enum_test(NULL, ei, &eo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ei == eo && ei == er); + if (ei != eo) + fprintf(stdout, " out parameter error, sent: %d, got: %d\n", ei, eo); + if (ei != er) + fprintf(stdout, " result error, sent: %d, got: %d\n", ei, er); + return -1; +} + +static int string1_test(IC_Env *env) +{ + char* si = longtext; + char* so; + char* sr; + + fprintf(stdout, "\n======== m_i_string1 test ======\n\n"); + sr = m_i_string1_test(NULL, si, &so, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, sr)); + if (!cmp_str(si, so)) + fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so); + if (!cmp_str(si, sr)) + fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr); + CORBA_free(so); + CORBA_free(sr); + return -1; +} + +static int string2_test(IC_Env *env) +{ + char* sa[3] = {"hello", "foo", "bar"}; + m_sseq ssi = {3, 3, sa}; + m_sseq *sso, *ssr; + + fprintf(stdout, "\n======== m_i_string2 test ======\n\n"); + ssr = m_i_string2_test(NULL, &ssi, &sso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_sseq(&ssi, sso) && cmp_sseq(&ssi, sso)); + if (!cmp_sseq(&ssi, sso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_sseq(&ssi); + fprintf(stdout, "got:\n"); + print_sseq(sso); + } + if (!cmp_sseq(&ssi, ssr)) { + fprintf(stdout, " result error, sent:\n"); + print_sseq(&ssi); + fprintf(stdout, "got:\n"); + print_sseq(ssr); + } + CORBA_free(sso); + CORBA_free(ssr); + return -1; +} + +static int string3_test(IC_Env *env) +{ + char* si = longtext; + char* so; + char* sr; + + fprintf(stdout, "\n======== m_i_string3 test ======\n\n"); + sr = m_i_string3_test(NULL, si, &so, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, so)); + if (!cmp_str(si, so)) + fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so); + if (!cmp_str(si, sr)) + fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr); + CORBA_free(so); + CORBA_free(sr); + return -1; +} + +static int string4_test(IC_Env *env) +{ + char as1[100] = "a string", as2[200] = "help", as3[200] = "hello there"; + m_strRec stri = { 1, /* dd */ + as1, /* str4 */ + {{'a', 'k'}, {'z', 'g'}, {'n', 'q'}}, /* str7 */ + {3, 3, "buf"}, /* str5 */ + as2, /* str6 */ + {'m', 'f', 'o'}, /* str8 */ + as3, /* str9 */ + {3, 3, "stu"} /* str10 */ + }; + m_strRec *stro, *strr; + + fprintf(stdout, "\n======== m_i_string4 test ======\n\n"); + strr = m_i_string4_test(NULL, &stri, &stro, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_strRec(&stri,stro) && cmp_strRec(&stri,strr)); + if (!cmp_strRec(&stri,stro)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_strRec(&stri); + fprintf(stdout, " got:\n"); + print_strRec(stro); + fprintf(stdout, "\n"); + } + if (!cmp_strRec(&stri,strr)) { + fprintf(stdout, " result error, sent:\n"); + print_strRec(&stri); + fprintf(stdout, " got:\n"); + print_strRec(strr); + fprintf(stdout, "\n"); + } + CORBA_free(stro); + CORBA_free(strr); + return -1; +} + + +static int pid_test(IC_Env *env) +{ + erlang_pid pid = {"", 7, 0, 0}, pido, pidr; + + strcpy(pid.node, this_node), /* this currently running node */ + fprintf(stdout, "\n======== m_i_pid test ======\n\n"); + pidr = m_i_pid_test(NULL, &pid, &pido, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_pid(&pid, &pido) && cmp_pid(&pid, &pidr)); + if (!cmp_pid(&pid, &pido)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_pid(&pid); + fprintf(stdout, "got:\n"); + print_pid(&pido); + } + if (!cmp_pid(&pid, &pidr)) { + fprintf(stdout, " result error, sent:\n"); + print_pid(&pid); + fprintf(stdout, "got:\n"); + print_pid(&pidr); + } + return -1; +} + +static int port_test(IC_Env *env) +{ + erlang_port porti = {"node", 5, 1}, porto, portr; + + fprintf(stdout, "\n======== m_i_port test ======\n\n"); + portr = m_i_port_test(NULL, &porti, &porto, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_port(&porti, &porto) && cmp_port(&porti, &portr)); + if (!cmp_port(&porti, &porto)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_port(&porti); + fprintf(stdout, "got:\n"); + print_port(&porto); + } + if (!cmp_port(&porti, &portr)) { + fprintf(stdout, " result error, sent:\n"); + print_port(&porti); + fprintf(stdout, "got:\n"); + print_port(&portr); + } + return -1; +} + +static int ref_test(IC_Env *env) +{ + erlang_ref refi = { "node1", 3, {1, 2, 3}, 1}, + refo, refr; + + fprintf(stdout, "\n======== m_i_ref test ======\n\n"); + refr = m_i_ref_test(NULL, &refi, &refo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_ref(&refi, &refo) && cmp_ref(&refi, &refr)); + if (!cmp_ref(&refi, &refo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_ref(&refi); + fprintf(stdout, "got:\n"); + print_ref(&refo); + } + if (!cmp_ref(&refi, &refr)) { + fprintf(stdout, " result error, sent:\n"); + print_ref(&refi); + fprintf(stdout, "got:\n"); + print_ref(&refr); + } + return -1; +} + +static int term_test(IC_Env *env) +{ + ETERM *ti, *to, *tr; + + ti = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"); + + fprintf(stdout, "\n======== m_i_term test ======\n\n"); + tr = m_i_term_test(NULL, ti, &to, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(erl_match(ti, to) && erl_match(ti, tr)); + if (!erl_match(ti, to)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_term(ti); + fprintf(stdout, "got:\n"); + print_term(to); + } + if (!erl_match(ti, tr)) { + fprintf(stdout, " result error, sent:\n"); + print_term(ti); + fprintf(stdout, "got:\n"); + print_term(tr); + } + erl_free_term(ti); + erl_free_term(to); + erl_free_term(tr); + return -1; +} + +static int typedef_test(IC_Env *env) +{ + m_banan mbi, mbo; /* erlang_port */ + m_apa mai; /* ETERM* */ + m_apa mao = NULL; + long tl; + + strcpy(mbi.node,"node"); + mbi.id = 15; + mbi.creation = 1; + + fprintf(stdout, "\n======== m_i_typedef test ======\n\n"); + mai = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"); + tl = m_i_typedef_test(NULL, mai, &mbi, &mao, &mbo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(erl_match(mai, mao) && cmp_port(&mbi, &mbo) && tl == 4711); + if (!erl_match(mai, mao)) { + fprintf(stdout, " out parameter error (term), sent:\n"); + print_term(mai); + fprintf(stdout, "got:\n"); + print_term(mao); + } + if (!cmp_port(&mbi, &mbo)) { + fprintf(stdout, " out parameter error (port), sent:\n"); + print_port(&mbi); + fprintf(stdout, "got:\n"); + print_port(&mbo); + } + if (tl != 4711) { + fprintf(stdout, " result error, sent: 4711, got %ld\n", tl); + } + erl_free_term(mai); + erl_free_term(mao); + return -1; +} + +static int inline_sequence_test(IC_Env *env) +{ + int i; + long al[500]; + m_s isi = {4711, {500, 10, al}}, + *iso, *isr; + + for (i = 0; i < 500; i++) + al[i]=i; + fprintf(stdout, "\n======== m_i_inline_sequence test ======\n\n"); + isr = m_i_inline_sequence_test(NULL, &isi, &iso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_s(&isi, iso) && cmp_s(&isi, isr)); + if (!cmp_s(&isi, iso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_s(&isi); + fprintf(stdout, "got:\n"); + print_s(iso); + } + if (!cmp_s(&isi, isr)) { + fprintf(stdout, " result error, sent:\n"); + print_s(&isi); + fprintf(stdout, "got:\n"); + print_s(isr); + } + CORBA_free(iso); + CORBA_free(isr); + return -1; +} + +static int term_sequence_test(IC_Env *env) +{ + ETERM* et_array[4] = { + erl_format("[{apa, 1, 23}, \"string\", {1.23, 45}]"), + erl_format("[{banan, 1, 23}, \"string\", {1.23, 45}]"), + erl_format("[{apelsin, 1, 23}, \"string\", {1.23, 45}]"), + erl_format("[{mango, 1, 23}, \"string\", {1.23, 45}]")}; + m_etseq etsi = {4, 4, et_array}, *etso, *etsr; + + fprintf(stdout, "\n======== m_i_term_sequence test ======\n\n"); + etsr = m_i_term_sequence_test(NULL, &etsi, &etso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_etseq(&etsi, etso) && cmp_etseq(&etsi, etsr)); + if (!cmp_etseq(&etsi, etso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_etseq(&etsi); + fprintf(stdout, "got:\n"); + print_etseq(etso); + } + if (!cmp_etseq(&etsi, etsr)) { + fprintf(stdout, " result error, sent:\n"); + print_etseq(&etsi); + fprintf(stdout, "got:\n"); + print_etseq(etsr); + } + free_etseq_buf(&etsi); + free_etseq_buf(etso); + free_etseq_buf(etsr); + CORBA_free(etso); + CORBA_free(etsr); + return -1; +} + +static int term_struct_test(IC_Env *env) +{ + m_et eti = { erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"), + 121212 }; + m_et eto, etr; + + fprintf(stdout, "\n======== m_i_term_struct test ======\n\n"); + etr = m_i_term_struct_test(NULL, &eti, &eto, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_et(&eti, &eto) && cmp_et(&eti, &etr)); + if (!cmp_et(&eti, &eto)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_et(&eti); + fprintf(stdout, "got:\n"); + print_et(&eto); + } + if (!cmp_et(&eti, &etr)) { + fprintf(stdout, " result error, sent:\n"); + print_et(&eti); + fprintf(stdout, "got:\n"); + print_et(&etr); + } + free_et(&eti); + free_et(&eto); + free_et(&etr); + return -1; +} + +static int wstring1_test(IC_Env *env) +{ + CORBA_wchar wsi[] = {100, 101, 102, 103, 104, 0}, *wso, *wsr; + + fprintf(stdout, "\n======== m_i_wstring1 test ======\n\n"); + wsr = m_i_wstring1_test(NULL, wsi, &wso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_wstr(wsi, wso) && cmp_wstr(wsi, wsr)); + if (!cmp_wstr(wsi, wso)) { + fprintf(stdout, " out parameter error, sent: \n"); + print_wstr(wsi); + fprintf(stdout, "got:\n"); + print_wstr(wso); + } + if (!cmp_wstr(wsi, wsr)) { + fprintf(stdout, " result error, sent: \n"); + print_wstr(wsi); + fprintf(stdout, "got:\n"); + print_wstr(wsr); + } + CORBA_free(wso); + CORBA_free(wsr); + return -1; +} + +/* Compare functions */ +static int cmp_aseq(m_aseq *a1, m_aseq *a2) +{ + int i; + + if (a1->_length != a2->_length) + return 0; + for (i = 0; i < a1->_length; i++) + if (cmp_a(&(a1->_buffer[i]), &(a2->_buffer[i])) == 0) + return 0; + return 1; +} + +static int cmp_a(m_a *a1, m_a *a2) +{ + return a1->l == a2->l && + a1->d == a2->d && + cmp_bseq(&a1->y, &a2->y); +} + +static int cmp_bseq(m_bseq *b1, m_bseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (cmp_b(&(b1->_buffer[i]), &(b2->_buffer[i])) == 0) + return 0; + return 1; +} + +static int cmp_b(m_b *b1, m_b *b2) +{ + return b1->l == b2->l && b1->c == b2->c; +} + +static int cmp_lseq(m_lseq *b1, m_lseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (b1->_buffer[i] != b2->_buffer[i]) + return 0; + return 1; +} + +static int cmp_etseq(m_etseq *b1, m_etseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (!erl_match(b1->_buffer[i], b2->_buffer[i])) + return 0; + return 1; +} + +static int cmp_et(m_et* b1, m_et *b2) +{ + return erl_match(b1->e, b2->e) && b1->l == b2->l; +} + +static int cmp_es(m_es *b1, m_es *b2) +{ + return b1->f == b2->f && b1->l == b2->l; +} + +static int cmp_arr1(m_arr1 b1, m_arr1 b2) +{ + int i; + + for (i = 0; i < 500; i++) + if (b1[i] != b2[i]) + return 0; + return 1; +} + +static int cmp_dd(m_dd b1, m_dd b2) +{ + + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + if (b1[i][j] != b2[i][j]) + return 0; + return 1; +} + + + +static int cmp_strRec(m_strRec *b1, m_strRec *b2) +{ + int i, j; + + if (b1->bb != b2->bb) + return 0; + if (!cmp_str(b1->str4,b2->str4)) + return 0; + if (b1->str5._length != b2->str5._length) + return 0; + for (j = 0; j < b1->str5._length; j++) + if (b1->str5._buffer[j] != b2->str5._buffer[j]) + return 0; + if (!cmp_str(b1->str6,b2->str6)) + return 0; + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + if (b1->str7[i][j] != b2->str7[i][j]) + return 0; + for (j = 0; j < 3; j++) + if (b1->str8[j] != b2->str8[j]) + return 0; + if (!cmp_str(b1->str9,b2->str9)) + return 0; + if (b1->str10._length != b2->str10._length) + return 0; + for (j = 0; j < b1->str10._length; j++) + if (b1->str10._buffer[j] != b2->str10._buffer[j]) + return 0; + return 1; +} + + +static int cmp_sseq(m_sseq *b1, m_sseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (!cmp_str(b1->_buffer[i], b2->_buffer[i])) + return 0; + return 1; +} + + +static int cmp_pid(erlang_pid *p1, erlang_pid *p2) +{ + return cmp_str(p1->node,p2-> node) && + p1->num == p2->num && + p1->serial == p2->serial && + p1->creation == p2->creation; +} + +static int cmp_port(erlang_port *p1, erlang_port *p2) +{ + return cmp_str(p1->node,p2-> node) && p1->id == p2->id; +} + +static int cmp_ref(erlang_ref *p1, erlang_ref *p2) +{ + return cmp_str(p1->node, p2->node) && + p1->len == p2->len && + (p1->len < 1 || p1->n[0] == p2->n[0]) && + (p1->len < 2 || p1->n[1] == p2->n[1]) && + (p1->len < 3 || p1->n[2] == p2->n[2]); +} + +static int cmp_s(m_s *b1, m_s *b2) +{ + int i; + + if (b1->l != b2->l) + return 0; + if (b1->sl._length != b2->sl._length) + return 0; + for (i = 0; i < b1->sl._length; i++) + if (b1->sl._buffer[i] != b2->sl._buffer[i]) + return 0; + return 1; +} + + +static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2) +{ + int i,j; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) { + if (b1->_buffer[i]._length != b2->_buffer[i]._length) + return 0; + for (j = 0; j < b1->_buffer[i]._length; j++) + if (!cmp_str(b1->_buffer[i]._buffer[j], + b2->_buffer[i]._buffer[j])) + return 0; + } + return 1; +} + + + +static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) { + if (!cmp_sarr3(&b1->_buffer[i], &b2->_buffer[i])) + return 0; + } + return 1; +} + +static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) { + if (!cmp_arr3(b1->_buffer[i], b2->_buffer[i])) + return 0; + } + return 1; +} + +static int cmp_arr3(m_arr3 b1, m_arr3 b2) +{ + int i; + + for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) { + if (b1[i] != b2[i]) + return 0; + } + return 1; +} + +/* Print functions */ +static void print_aseq(m_aseq *a) +{ + int i; + fprintf(stdout, "\nm_aseq size: %ld --------\n", a->_length); + for (i = 0; i < a->_length; i++) + print_a(&(a->_buffer[i])); +} + +static void print_a(m_a *a) +{ + fprintf(stdout, "\nm_a --------\n l: %ld\n d:%f\n", a->l, a->d); + print_bseq(&a->y); +} + +static void print_bseq(m_bseq *b) +{ + int i; + + fprintf(stdout, "\nm_bseq size: %ld --------\n",b->_length); + for (i = 0; i < b->_length; i++) + print_b(&(b->_buffer[i])); +} + +static void print_lseq(m_lseq *b) +{ + int i; + + fprintf(stdout, "\nm_lseq size: %ld --------\n",b->_length); + for (i = 0; i < b->_length; i++) + fprintf(stdout, "[%d]: %ld\n", i, b->_buffer[i]); +} + +static void print_b(m_b *b) +{ + fprintf(stdout, "\nm_b --------\n l: %ld\n c: %c\n", b->l, b->c); +} + + +static void print_etseq(m_etseq *b) +{ + int i; + + for (i = 0; i < b->_length; i++) { + fprintf(stdout, "[%d]:\n", i); + erl_print_term(stdout, b->_buffer[i]); + } +} + + +static void print_et(m_et* b) +{ + fprintf(stdout, "\net struct --------\n"); + erl_print_term(stdout, b->e); + fprintf(stdout, "long: %ld\n", b->l); + fprintf(stdout, "\n--------\n"); +} + +static void print_es(m_es *b) +{ + fprintf(stdout, "\nm_es --------\n f: %d\n l: %ld\n", b->f, b->l); +} + + +static void print_arr1(long a[10]) +{ + int i; + + for (i = 0; i < 10; i++) + fprintf(stdout, "\n[%d]: %ld\n", i, a[i]); +} + +static void print_dd(long a[2][3]) +{ + int i, j; + + fprintf(stdout, "\nlong dd[2][3] --------\n"); + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + fprintf(stdout, "\n[%d][%d]: %ld\n", i, j, a[i][j]); +} + + +static void print_strRec(m_strRec* sr) +{ + int i, j; + + fprintf(stdout, "\nboolean bb : %d\n",sr->bb); + fprintf(stdout, "string str4 : %s\n",sr->str4); + fprintf(stdout, "str7[2][3] :\n"); + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + fprintf(stdout, "str7[%d][%d]: %ld\n", i, j, sr->str7[i][j]); + fprintf(stdout, "str5._length : %ld\n",sr->str5._length); + for (j = 0; j < sr->str5._length; j++) + fprintf(stdout, "str5._buffer[%d]: %c\n", j, sr->str5._buffer[j]); + fprintf(stdout, "string str6 : %s\n",sr->str6); + fprintf(stdout, "str8 :\n"); + for (j = 0; j < 3; j++) + fprintf(stdout, "str8[%d]: %c\n", j, sr->str8[j]); + fprintf(stdout, "string str9 : %s\n",sr->str9); + fprintf(stdout, "str10._length : %ld\n",sr->str10._length); + for (j = 0; j < sr->str10._length; j++) + fprintf(stdout, "str10._buffer[%d]: %c\n", j, sr->str10._buffer[j]); +} + +static void print_sseq(m_sseq *b) +{ + int i; + + fprintf(stdout, "\nm_sseq size: %ld --------\n",b->_length); + for (i = 0; i < b->_length; i++) + fprintf(stdout, "%s\n", b->_buffer[i]); + +} + + +static void print_pid(erlang_pid *p) +{ + fprintf(stdout, "\nerlang_pid --------\n node: %s\n num: %d\n " + "serial: %d\n creation: %d\n", + p->node, p->num, p->serial, p->creation); +} + +static void print_port(erlang_port *p) +{ + fprintf(stdout, "\nerlang_port --------\n node: %s\n id: %d\n " + "creation: %d\n", p->node, p->id, p->creation); +} + +static void print_ref(erlang_ref *p) +{ + fprintf(stdout, "\nerlang_ref --------\n node: %s\n len: %d\n " + "n[0]: %d\n n[1]: %d\n n[2]: %d\n creation: %d\n", + p->node, p->len, p->n[0], p->n[1], p->n[2], p->creation); +} + +static void print_term(ETERM *t) +{ + fprintf(stdout, "\nETERM --------\n"); + erl_print_term(stdout, t); + fprintf(stdout, "\n--------\n"); +} + +static void print_s(m_s *p) +{ + int i; + + fprintf(stdout, "\n%ld\n", p->l); + for (i = 0; i < p->sl._length; i++) + fprintf(stdout, "\n[%d]: %ld\n", i, p->sl._buffer[i]); +} + + +static void print_ssstr3(m_ssstr3 *b1) +{ + int i,j; + + fprintf(stdout, "\nSSSTR3 --------\n"); + fprintf(stdout,"b1->_length = %ld\n",b1->_length); + for (i = 0; i < b1->_length; i++) { + fprintf(stdout,"\nb1->_buffer[%d]._length %ld\n", + i, b1->_buffer[i]._length); + for (j = 0; j < b1->_buffer[i]._length; j++) + fprintf(stdout,"b1->_buffer[%d]._buffer[%d] = %s\n", + i, j, b1->_buffer[i]._buffer[j]); + } + fprintf(stdout, "\n--------\n"); +} + +static void print_wstr(CORBA_wchar *ws) +{ + int i = 0; + + fprintf(stdout, "\nwstr --------\n"); + while (ws[i]) { + fprintf(stdout, "[%d]: %ld\n", i, ws[i]); + i++; + } + fprintf(stdout, "\n--------\n"); +} + + +static void print_ssarr3(m_ssarr3 *b1) +{ + int i; + + fprintf(stdout, "\nssarr3 --------\n"); + fprintf(stdout,"length: %ld\n",b1->_length); + fprintf(stdout, "buffer:\n"); + for (i = 0; i < b1->_length; i++) + print_sarr3(&b1->_buffer[i]); + fprintf(stdout, "\n--------\n"); +} + +static void print_sarr3(m_sarr3 *b1) +{ + int i; + + fprintf(stdout, "\nsarr3 --------\n"); + fprintf(stdout,"length: %ld\n",b1->_length); + fprintf(stdout, "buffer:\n"); + for (i = 0; i < b1->_length; i++) + print_arr3(b1->_buffer[i]); + fprintf(stdout, "\n--------\n"); +} + +static void print_arr3(m_arr3 b1) +{ + int i; + + fprintf(stdout, "\narr3 --------\n"); + for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) + fprintf(stdout, "%ld ", b1[i]); + fprintf(stdout, "\n--------\n"); +} + +static void free_etseq_buf(m_etseq *b) +{ + int i; + + for (i = 0; i < b->_length; i++) + erl_free_term(b->_buffer[i]); +} + +static void free_et(m_et* b) +{ + erl_free_term(b->e); +} + +static void showtime(MyTimeval *start, MyTimeval *stop) +{ + MyTimeval elapsed; + + elapsed.tv_sec = stop->tv_sec - start->tv_sec; + elapsed.tv_usec = stop->tv_usec - start->tv_usec; + while (elapsed.tv_usec < 0) { + elapsed.tv_sec -= 1; + elapsed.tv_usec += 1000000; + } + fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec); +} + +static void my_gettimeofday(MyTimeval *tv) +#ifdef __WIN32__ +#define EPOCH_JULIAN_DIFF 11644473600i64 +{ + SYSTEMTIME t; + FILETIME ft; + LONGLONG lft; + + GetSystemTime(&t); + SystemTimeToFileTime(&t, &ft); + memcpy(&lft, &ft, sizeof(lft)); + tv->tv_usec = (long) ((lft / 10i64) % 1000000i64); + tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF); +} +#elif defined VXWORKS +{ + int rate = sysClkRateGet(); /* Ticks per second */ + unsigned long ctick = tickGet(); + tv->tv_sec = ctick / rate; /* secs since reboot */ + tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate; +} +#else +{ + gettimeofday(tv, NULL); +} +#endif diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl new file mode 100644 index 0000000000..6d229c3ac1 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl @@ -0,0 +1,173 @@ + +// %CopyrightBegin% +// +// Copyright Ericsson AB 2003-2010. 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 "erlang.idl" + + +const short TestConst = 1; + +module m { + + const short TestConst = 2; + + struct b { + long l; + char c; + }; + + struct simple { + long l; + b b_t; + }; + + enum fruit {orange, banana, apple, peach, pear}; + + typedef sequence<long> lseq; + + typedef sequence<b> bseq; + + struct a { + long l; + bseq y; + double d; + }; + + typedef sequence<a> aseq; + + typedef sequence<string> sseq; + typedef string str; + typedef long myLong; + + typedef long arr1[500], dd[2][3]; + + typedef erlang::term apa; + typedef erlang::port banan; + + typedef sequence<erlang::term> etseq; + + struct s { + long l; + sequence<long> sl; + }; + + struct es { + fruit f; + myLong l; + }; + + struct et { + erlang::term e; + long l; + }; + + + typedef sequence<char> str1; + typedef string<12> str2; + typedef char str3[3]; + + typedef sequence<string> sstr3; // sequence of string + typedef sequence<sstr3> ssstr3; // sequence of sequences of strings + + typedef long arr3[3]; // array of long + typedef sequence<arr3> sarr3; // sequence of array + typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings + + struct strRec{ + boolean bb; + string str4; + long str7[3][2]; + sequence<char> str5; + string<12> str6; + str3 str8; + str2 str9; + str1 str10; + }; + + + struct dyn { + long l; + sequence<long> sl; + }; + typedef dyn arr2[1][2]; + + + interface i { + + const short TestConst = 3; + + //arr2 suck(in arr2 x, out arr2 y ); + + ///////////////////////////////// attribute long l; + + // simple types + void void_test(); + long long_test(in long a, out long a1); + long long longlong_test(in long long a, out long long a1); + unsigned short ushort_test(in unsigned short a, out unsigned short a1); + unsigned long ulong_test(in unsigned long a, out unsigned long a1); + unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1); + double double_test(in double a, out double a1); + char char_test(in char a, out char a1); + wchar wchar_test(in wchar a, out wchar a1); + octet octet_test(in octet a, out octet a1); + boolean bool_test(in boolean a, out boolean a1); + + // Seq. and struct tests + b struct_test(in b a, out b a1); + es struct2_test(in es a, out es a1); + //simple struct3_test(in simple x, out simple y); + bseq seq1_test(in bseq a, out bseq a1); + aseq seq2_test(in aseq a, out aseq a1); + lseq seq3_test(in lseq a, out lseq a1); + ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1); + ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1); + + // Array tests + arr1 array1_test(in arr1 a, out arr1 a1); + dd array2_test(in dd a, out dd a1); + + // enum test + fruit enum_test(in fruit a, out fruit a1); + + // string tests + string string1_test(in string a, out string a1); + wstring wstring1_test(in wstring a, out wstring a1); + sseq string2_test(in sseq a, out sseq a1); + str string3_test(in str a, out str a1); + strRec string4_test(in strRec a, out strRec a1); + + // Special erlang types + erlang::pid pid_test(in erlang::pid a, out erlang::pid a1); + erlang::port port_test(in erlang::port a, out erlang::port a1); + erlang::ref ref_test(in erlang::ref a, out erlang::ref a1); + erlang::term term_test(in erlang::term a, out erlang::term a1); + + // typedef test + long typedef_test(in apa a, in banan b, out apa a1, out banan b1); + + // inlined seq. test + s inline_sequence_test(in s a, out s a1); + + // term seq. test + etseq term_sequence_test(in etseq a, out etseq a1); + // term struct test + et term_struct_test(in et a, out et a1); + + }; + +}; diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl b/lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl new file mode 100644 index 0000000000..09358b7cf9 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl @@ -0,0 +1,28 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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(erl_server). + +-export([run/0, stop/0]). + +run() -> + m_i:oe_create(). + +stop() -> + gen_server:cast(cidl_test, stop). diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl b/lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl new file mode 100644 index 0000000000..9f231de856 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl @@ -0,0 +1,161 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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(m_i_impl). +-include("m.hrl"). + +-export([init/1, terminate/2, void_test/1, long_test/2, ushort_test/2, + longlong_test/2, ulong_test/2, ulonglong_test/2, + double_test/2, char_test/2, wchar_test/2, octet_test/2, + bool_test/2, struct_test/2, struct2_test/2, seq1_test/2, + seq2_test/2, seq3_test/2, seq4_test/2, seq5_test/2, + array1_test/2, array2_test/2, enum_test/2, string1_test/2, + string2_test/2, string3_test/2, string4_test/2, pid_test/2, + port_test/2, ref_test/2, term_test/2, typedef_test/3, + inline_sequence_test/2, '_set_l'/2, '_get_l'/1, + term_struct_test/2, term_sequence_test/2, wstring1_test/2]). + +-define(PRINTDEBUG(Case), + io:format("erl_server: case: ~p~n" + "erl_server: location: ~p~n", [Case, [?FILE, ?LINE]])). +-define(PRINTDEBUG2(Case, Msg), + io:format("erl_server: case: ~p~n" + "erl_server: Msg: ~p~n" + "erl_server: location: ~p~n", [Case, Msg, [?FILE, ?LINE]])). + +init(Env) -> + {ok, []}. + +terminate(F, R) -> + ok. + +'_get_l'(State) -> + ?PRINTDEBUG("_get_l"), + {reply, State, State}. +void_test(State) -> + ?PRINTDEBUG("void_test"), + {reply, ok, State}. + +'_set_l'(State, V) -> + ?PRINTDEBUG2("_set_l", V), + {reply, ok, V}. +ushort_test(State, V) -> + ?PRINTDEBUG2("ushort_test", V), + {reply, {V, V}, State}. +long_test(State, V) -> + ?PRINTDEBUG2("long_test", V), + {reply, {V, V}, State}. +longlong_test(State, V) -> + ?PRINTDEBUG2("longlong_test", V), + {reply, {V, V}, State}. +ulong_test(State, V) -> + ?PRINTDEBUG2("ulong_test", V), + {reply, {V, V}, State}. +ulonglong_test(State, V) -> + ?PRINTDEBUG2("ulonglong_test", V), + {reply, {V, V}, State}. +double_test(State, V) -> + ?PRINTDEBUG2("double_test", V), + {reply, {V, V}, State}. +char_test(State, V) -> + ?PRINTDEBUG2("char_test", V), + {reply, {V, V}, State}. +wchar_test(State, V) -> + ?PRINTDEBUG2("wchar_test", V), + {reply, {V, V}, State}. +octet_test(State, V) -> + ?PRINTDEBUG2("octet_test", V), + {reply, {V, V}, State}. +bool_test(State, V) -> + ?PRINTDEBUG2("bool_test", V), + {reply, {V, V}, State}. + +struct_test(State, V) -> + ?PRINTDEBUG2("struct_test", V), + {reply, {V, V}, State}. +struct2_test(State, V) -> + ?PRINTDEBUG2("struct2_test", V), + {reply, {V, V}, State}. +seq1_test(State, V) -> + ?PRINTDEBUG2("seq1_test", V), + {reply, {V, V}, State}. +seq2_test(State, V) -> + ?PRINTDEBUG2("seq2_test", V), + {reply, {V, V}, State}. +seq3_test(State, V) -> + ?PRINTDEBUG2("seq3_test", V), + {reply, {V, V}, State}. +seq4_test(State, V) -> + ?PRINTDEBUG2("seq4_test", V), + {reply, {V, V}, State}. +seq5_test(State, V) -> + ?PRINTDEBUG2("seq5_test", V), + {reply, {V, V}, State}. +array1_test(State, V) -> + ?PRINTDEBUG2("array1_test", V), + {reply, {V, V}, State}. +array2_test(State, V) -> + ?PRINTDEBUG2("array2_test", V), + {reply, {V, V}, State}. +enum_test(State, V) -> + ?PRINTDEBUG2("enum_test", V), + {reply, {V, V}, State}. +string1_test(State, V) -> + ?PRINTDEBUG2("string1_test", V), + {reply, {V, V}, State}. +string2_test(State, V) -> + ?PRINTDEBUG2("string2_test", V), + {reply, {V, V}, State}. +string3_test(State, V) -> + ?PRINTDEBUG2("string3_test", V), + {reply, {V, V}, State}. +string4_test(State, V) -> + ?PRINTDEBUG2("string4_test", V), + {reply, {V, V}, State}. +pid_test(State, V) -> + ?PRINTDEBUG2("pid_test", V), + {reply, {V, V}, State}. +port_test(State, V) -> + ?PRINTDEBUG2("port_test", binary_to_list(term_to_binary(V))), + {reply, {V, V}, State}. +ref_test(State, V) -> + ?PRINTDEBUG2("ref_test", binary_to_list(term_to_binary(V))), + {reply, {V, V}, State}. +term_test(State, V) -> + ?PRINTDEBUG2("term_test", V), + {reply, {V, V}, State}. +typedef_test(State, A, B) -> + ?PRINTDEBUG2("typedef_test", [A,B]), + {reply, {4711, A, B}, State}. +inline_sequence_test(State, V) -> + ?PRINTDEBUG2("inline_sequence_test", V), + {reply, {V, V}, State}. +term_sequence_test(State, V) -> + ?PRINTDEBUG2("term_sequence_test", V), + {reply, {V, V}, State}. +term_struct_test(State, V) -> + ?PRINTDEBUG2("term_struct_test", V), + {reply, {V, V}, State}. +wstring1_test(State, V) -> + ?PRINTDEBUG2("wstring1_test", V), + {reply, {V, V}, State}. + + + + diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c b/lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c new file mode 100644 index 0000000000..f8a3b28cc2 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c @@ -0,0 +1,50 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-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% + * + */ + +#include "ic.h" +#include "m_i.h" + +int my_prepare_notification_encoding(CORBA_Environment *env) +{ + return oe_prepare_notification_encoding(env); +} + +int my_send_notification(CORBA_Environment *env) +{ + return oe_send_notification(env); +} + +int my_prepare_request_encoding(CORBA_Environment *env) +{ + return oe_prepare_request_encoding(env); +} + +int my_send_request_and_receive_reply(CORBA_Environment *env) +{ + return oe_send_request_and_receive_reply(env); +} + +int my_prepare_reply_decoding(CORBA_Environment *env) +{ + return oe_prepare_reply_decoding(env); +} + + + diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl new file mode 100644 index 0000000000..595c5bf483 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl @@ -0,0 +1,315 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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% +%% +%% + +%%---------------------------------------------------------------------- +%% Purpose : Test suite for c-client/erl-server +%%---------------------------------------------------------------------- + +-module(c_client_erl_server_proto_tmo_SUITE). +-include("test_server.hrl"). + +-export([init_per_testcase/2, fin_per_testcase/2, + all/1, void_test/1, long_test/1, long_long_test/1, + unsigned_short_test/1, unsigned_long_test/1, + unsigned_long_long_test/1, double_test/1, char_test/1, + wchar_test/1, octet_test/1, bool_test/1, struct_test/1, + struct2_test/1, seq1_test/1, seq2_test/1, seq3_test/1, + seq4_test/1, seq5_test/1, array1_test/1, array2_test/1, + enum_test/1, string1_test/1, string2_test/1, string3_test/1, + string4_test/1, pid_test/1, port_test/1, ref_test/1, term_test/1, + typedef_test/1, inline_sequence_test/1, term_sequence_test/1, + term_struct_test/1, wstring1_test/1]). + +-define(DEFAULT_TIMEOUT, 20000). +-define(PORT_TIMEOUT, 15000). +-define(ERLANG_SERVER_NAME, idl_erlang_server). +-define(C_CLIENT_NODE_NAME, c_client_idl_test). + +%% Add/remove code path and watchdog before/after each test case. +%% +init_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:add_patha(DataDir), + + %% Since other test suites use the module m_i, we have + %% to make sure we are using the right m_i module. + code:purge(m_i), + code:load_file(m_i), + + WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT), + [{watchdog, WatchDog}| Config]. + +fin_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:del_path(DataDir), + WatchDog = ?config(watchdog, Config), + test_server:timetrap_cancel(WatchDog). + +all(doc) -> + "Test of IC with a C-client and an Erlang generic server. " + "The communication is via Erlang distribution."; +all(suite) -> + [void_test, long_test, long_long_test, unsigned_short_test, + unsigned_long_test, unsigned_long_long_test, double_test, + char_test, wchar_test, octet_test, bool_test, struct_test, + struct2_test, seq1_test, seq2_test, seq3_test, seq4_test, + seq5_test, array1_test, array2_test, enum_test, string1_test, + string2_test, string3_test, string4_test, pid_test, port_test, + ref_test, term_test, typedef_test, inline_sequence_test, + term_sequence_test, term_struct_test, wstring1_test]. + + +array1_test(doc) -> ""; +array1_test(suite) -> []; +array1_test(Config) -> + do_test(array1_test, Config). + +array2_test(doc) -> ""; +array2_test(suite) -> []; +array2_test(Config) -> + do_test(array2_test, Config). + +bool_test(doc) -> ""; +bool_test(suite) -> []; +bool_test(Config) -> + do_test(bool_test, Config). + +char_test(doc) -> ""; +char_test(suite) -> []; +char_test(Config) -> + do_test(char_test, Config). + +double_test(doc) -> ""; +double_test(suite) -> []; +double_test(Config) -> + do_test(double_test, Config). + +enum_test(doc) -> ""; +enum_test(suite) -> []; +enum_test(Config) -> + do_test(enum_test, Config). + +inline_sequence_test(doc) -> ""; +inline_sequence_test(suite) -> []; +inline_sequence_test(Config) -> + do_test(inline_sequence_test, Config). + +long_long_test(doc) -> ""; +long_long_test(suite) -> []; +long_long_test(Config) -> + do_test(long_long_test, Config). + +long_test(doc) -> ""; +long_test(suite) -> []; +long_test(Config) -> + do_test(long_test, Config). + +octet_test(doc) -> ""; +octet_test(suite) -> []; +octet_test(Config) -> + do_test(octet_test, Config). + +pid_test(doc) -> ""; +pid_test(suite) -> []; +pid_test(Config) -> + do_test(pid_test, Config). + +port_test(doc) -> ""; +port_test(suite) -> []; +port_test(Config) -> + do_test(port_test, Config). + +ref_test(doc) -> ""; +ref_test(suite) -> []; +ref_test(Config) -> + do_test(ref_test, Config). + +seq1_test(doc) -> ""; +seq1_test(suite) -> []; +seq1_test(Config) -> + do_test(seq1_test, Config). + +seq2_test(doc) -> ""; +seq2_test(suite) -> []; +seq2_test(Config) -> + do_test(seq2_test, Config). + +seq3_test(doc) -> ""; +seq3_test(suite) -> []; +seq3_test(Config) -> + do_test(seq3_test, Config). + +seq4_test(doc) -> ""; +seq4_test(suite) -> []; +seq4_test(Config) -> + do_test(seq4_test, Config). + +seq5_test(doc) -> ""; +seq5_test(suite) -> []; +seq5_test(Config) -> + do_test(seq5_test, Config). + +string1_test(doc) -> ""; +string1_test(suite) -> []; +string1_test(Config) -> + do_test(string1_test, Config). + +string2_test(doc) -> ""; +string2_test(suite) -> []; +string2_test(Config) -> + do_test(string2_test, Config). + +string3_test(doc) -> ""; +string3_test(suite) -> []; +string3_test(Config) -> + do_test(string3_test, Config). + +string4_test(doc) -> ""; +string4_test(suite) -> []; +string4_test(Config) -> + do_test(string4_test, Config). + +struct2_test(doc) -> ""; +struct2_test(suite) -> []; +struct2_test(Config) -> + do_test(struct2_test, Config). + +struct_test(doc) -> ""; +struct_test(suite) -> []; +struct_test(Config) -> + do_test(struct_test, Config). + +term_sequence_test(doc) -> ""; +term_sequence_test(suite) -> []; +term_sequence_test(Config) -> + do_test(term_sequence_test, Config). + +term_struct_test(doc) -> ""; +term_struct_test(suite) -> []; +term_struct_test(Config) -> + do_test(term_struct_test, Config). + +term_test(doc) -> ""; +term_test(suite) -> []; +term_test(Config) -> + do_test(term_test, Config). + +typedef_test(doc) -> ""; +typedef_test(suite) -> []; +typedef_test(Config) -> + do_test(typedef_test, Config). + +unsigned_long_long_test(doc) -> ""; +unsigned_long_long_test(suite) -> []; +unsigned_long_long_test(Config) -> + do_test(unsigned_long_long_test, Config). + +unsigned_long_test(doc) -> ""; +unsigned_long_test(suite) -> []; +unsigned_long_test(Config) -> + do_test(unsigned_long_test, Config). + +unsigned_short_test(doc) -> ""; +unsigned_short_test(suite) -> []; +unsigned_short_test(Config) -> + do_test(unsigned_short_test, Config). + +void_test(doc) -> ""; +void_test(suite) -> []; +void_test(Config) -> + do_test(void_test, Config). + +wchar_test(doc) -> ""; +wchar_test(suite) -> []; +wchar_test(Config) -> + do_test(wchar_test, Config). + +wstring1_test(doc) -> ""; +wstring1_test(suite) -> []; +wstring1_test(Config) -> + do_test(wstring1_test, Config). + + +%% It is here that all tests really are done. +%% + +do_test(Case, Config) -> + %% Trap exits + process_flag(trap_exit, true), + %% Start the server + {ok, _Pid} = m_i:oe_create_link([], {local, ?ERLANG_SERVER_NAME}), + Node = atom_to_list(node()), + %% [NodeName, HostName] = string:tokens(Node, "@"), + DataDir = ?config(data_dir, Config), + %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]), + Cookie = atom_to_list(erlang:get_cookie()), + %% Start C-client node as a port program. + Cmd = filename:join([DataDir, "c_client"]) ++ + " -this-node-name " ++ atom_to_list(?C_CLIENT_NODE_NAME) ++ + " -peer-node " ++ Node ++ + " -peer-process-name " ++ atom_to_list(?ERLANG_SERVER_NAME) ++ + " -cookie " ++ Cookie ++ + " -test-case " ++ atom_to_list(Case), + Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]), + Res = wait_for_completion(Port), + %% Kill off node if there was timeout + case Res of + {error, timeout} -> + catch rpc:cast(?C_CLIENT_NODE_NAME, erlang, halt, [1]); + _ -> + ok + end, + process_flag(trap_exit, false), + catch m_i:stop(?ERLANG_SERVER_NAME), + ok = Res. + + +%% Wait for eof *and* exit status, but return if exit status indicates +%% an error, or we have been waiting more than PORT_TIMEOUT seconds. +%% +wait_for_completion(Port) -> + wait_for_completion(Port, 0). + +wait_for_completion(Port, N) when N < 2 -> + receive + {Port, {data, Bytes}} -> + %% Relay output + io:format("~s", [Bytes]), + wait_for_completion(Port, N); + {Port, {exit_status, 0}} -> + wait_for_completion(Port, N + 1); + {Port, {exit_status, Status}} -> + {error, Status}; + {Port, eof} -> + wait_for_completion(Port, N + 1); + {'EXIT', Port, Reason} -> + io:format("Port exited with reason: ~w~n", [Reason]), + wait_for_completion(Port, N); + {'EXIT', From, Reason} -> + io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]), + wait_for_completion(Port, N) + after ?PORT_TIMEOUT -> + {error, timeout} + end; +wait_for_completion(_, _) -> + ok. + + + diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src new file mode 100644 index 0000000000..62672e0b95 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src @@ -0,0 +1,146 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-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% +# +# +# Makefile.src for c_client_erl_server test +# Note: This file *must* work for both Unix and Windows +# +# We use both `rm' (Unix) and `del' (Windows) for removing files, but +# with a `-' in front so that the error in not finding `rm' (`del') on +# Windows (Unix) is ignored. +# +# VxWorks? XXX +# + +.SUFFIXES: +.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@ + + +# Variables from ts: +# + +ERL_INCLUDE = @erl_include@ + +IC_INCLUDE_PATH = @ic_include_path@ +IC_LIB = @ic_libpath@@DS@@ic_lib@ + +ERL_INTERFACE_INCLUDE = @erl_interface_include@ +ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@ +ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@ +ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@ +ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@ + +CC = @CC@ +## XXX Should set warning flag with a DEBUG_FLAG +CFLAGS = @CFLAGS@ @DEFS@ -I@erl_include@ \ + -I@ic_include_path@ -I@erl_interface_include@ + +LD = @LD@ +LDFLAGS = @CROSSLDFLAGS@ +LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \ + $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS) +ERLC = erlc + +# Generated C header files +GEN_H_FILES = \ + m.h \ + m_i.h \ + oe_c_erl_test.h + +# Generated C files +GEN_C_FILES = \ + m.c \ + m_i.c \ + oe_c_erl_test.c \ + oe_code_m_a.c \ + oe_code_m_arr1.c \ + oe_code_m_arr2.c \ + oe_code_m_arr3.c \ + oe_code_m_aseq.c \ + oe_code_m_b.c \ + oe_code_m_bseq.c \ + oe_code_m_dd.c \ + oe_code_m_dyn.c \ + oe_code_m_dyn_sl.c \ + oe_code_m_es.c \ + oe_code_m_et.c \ + oe_code_m_etseq.c \ + oe_code_m_fruit.c \ + oe_code_m_lseq.c \ + oe_code_m_s.c \ + oe_code_m_s_sl.c \ + oe_code_m_sarr3.c \ + oe_code_m_simple.c \ + oe_code_m_ssarr3.c \ + oe_code_m_sseq.c \ + oe_code_m_ssstr3.c \ + oe_code_m_sstr3.c \ + oe_code_m_str1.c \ + oe_code_m_str3.c \ + oe_code_m_strRec.c \ + oe_code_m_strRec_str5.c \ + oe_code_m_strRec_str7.c + +GEN_HRL_FILES = \ + m.hrl \ + m_i.hrl \ + oe_c_erl_test.hrl + +GEN_ERL_FILES = \ + m.erl \ + m_arr2.erl \ + m_arr3.erl \ + m_i.erl \ + m_str3.erl \ + oe_c_erl_test.erl + +C_FILES = $(GEN_C_FILES) c_client.c my.c + +OBJS = $(C_FILES:.c=@obj@) + +PGMS = c_client@exe@ + +ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl + +EBINS = $(ERL_FILES:.erl=.@EMULATOR@) + + +all: $(PGMS) $(EBINS) + +clean: + -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + +$(PGMS): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" \ + "+{user_protocol,my}" "+{c_timeout,{5000,5000}}" c_erl_test.idl + +$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl + +.c@obj@: + $(CC) -c -o $*@obj@ $(CFLAGS) $< + +.erl.@EMULATOR@: + $(ERLC) -I $(IC_INCLUDE_PATH) $< + diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c new file mode 100644 index 0000000000..b2c5b0c836 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c @@ -0,0 +1,1763 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + * + */ +/* C-client for test of IC. + * + * TODO: + * + * 1. XXX #includes for VxWorks, Windows + */ + +#include <stdio.h> +#include <stdlib.h> + +#ifndef __WIN32__ +# include <unistd.h> +#endif + +#include <string.h> + +#ifdef __WIN32__ +# include <time.h> +# include <sys/timeb.h> +#elif defined VXWORKS +#include <time.h> +#include <sys/times.h> +#else +#include <sys/time.h> +#endif + +#include <ctype.h> + +#ifdef __WIN32__ +# include <winsock2.h> +# include <windows.h> +#else +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netdb.h> +#endif + +#include "ei.h" +#include "erl_interface.h" +#include "m_i.h" + +#define HOSTNAMESZ 256 +#define NODENAMESZ 512 + +#define INBUFSZ 10 +#define OUTBUFSZ 0 + +#define MAXTRIES 5 + +#define CHECK_EXCEPTION(x) \ + if ((x)->_major != CORBA_NO_EXCEPTION) { \ + fprintf(stderr,"\n\nException: %s\n\n", \ + (char *)CORBA_exception_value((x))); \ + CORBA_exception_free((x)); \ + return -1; \ + } \ + +/* XXX Should free things here too! */ +#define RETURN_IF_OK(x) \ + if ((x)) {\ + fprintf(stdout, "ok\n");\ + return 0;\ + }\ + +#define cmp_str(x,y) (!strcmp((x),(y))) +#define cmp_wstr(x,y) (!ic_wstrcmp((x),(y))) + +typedef CORBA_Environment IC_Env; + +typedef int (*TestFunc)(IC_Env *); +typedef struct { + char *name; + TestFunc func; +} TestCase; + +static char longtext[] = +"Introduction The IC application is an IDL compiler implemented in Erlang." +" The IDL compiler generates client stubs and server skeletons." +" Several back-ends are supported, and they fall into three main groups." +" For more details on IC compiler options consult the ic(3) manual page." +" Argument passing cases 1 Caller allocates all necessary storage," +" except that which may be encapsulated and managed within the parameter itself." +" 2 The caller allocates a pointer and passes it by reference to the callee." +" The callee sets the pointer to point to a valid instance of the parameter's type." +" The caller is responsible for releasing the returned storage." +" Following completion of a request, the caller is not allowed to modify any values" +" in the returned storage. To do so the caller must first copy the returned instance" +" into a new instance, then modify the new instance. 3 The caller allocates a" +" pointer to an array slice which has all the same dimensions of the original" +" array except the first, and passes it by reference to the callee. The callee sets" +" the pointer to point to a valid instance of the array. The caller is responsible for" +" releasing the returned storage. Following completion of a request, the caller is not" +" allowed to modify any values in the returned storage. To do so the caller must first" +" copy the returned instance into a new instance, then modify the new instance." +" Generated Files Two files will be generated for each scope. One set of files will be" +" generated for each module and each interface scope. An extra set is generated for" +" those definitions at top level scope. One of the files is a header file(.h), and the" +" other file is a C source code file (.c). In addition to these files a number of C" +" source files will be generated for type encodings, they are named according to the " +"following template: oe_code_<type>.c."; +static char this_node[NODENAMESZ + 1]; +static char *progname; + +/* Test function prototypes */ + +static int void_test(IC_Env *env); +static int long_test(IC_Env *env); +static int long_long_test(IC_Env *env); +static int unsigned_short_test(IC_Env *env); +static int unsigned_long_test(IC_Env *env); +static int unsigned_long_long_test(IC_Env *env); +static int double_test(IC_Env *env); +static int char_test(IC_Env *env); +static int wchar_test(IC_Env *env); +static int octet_test(IC_Env *env); +static int bool_test(IC_Env *env); +static int struct_test(IC_Env *env); +static int struct2_test(IC_Env *env); +static int seq1_test(IC_Env *env); +static int seq2_test(IC_Env *env); +static int seq3_test(IC_Env *env); +static int seq4_test(IC_Env *env); +static int seq5_test(IC_Env *env); +static int array1_test(IC_Env *env); +static int array2_test(IC_Env *env); +static int enum_test(IC_Env *env); +static int string1_test(IC_Env *env); +static int string2_test(IC_Env *env); +static int string3_test(IC_Env *env); +static int string4_test(IC_Env *env); +static int pid_test(IC_Env *env); +static int port_test(IC_Env *env); +static int ref_test(IC_Env *env); +static int term_test(IC_Env *env); +static int typedef_test(IC_Env *env); +static int inline_sequence_test(IC_Env *env); +static int term_sequence_test(IC_Env *env); +static int term_struct_test(IC_Env *env); +static int wstring1_test(IC_Env *env); + +static TestCase test_cases[] = { + {"void_test", void_test}, + {"long_test", long_test}, + {"long_long_test", long_long_test}, + {"unsigned_short_test", unsigned_short_test}, + {"unsigned_long_test", unsigned_long_test}, + {"unsigned_long_long_test", unsigned_long_long_test}, + {"double_test", double_test}, + {"char_test", char_test}, + {"wchar_test", wchar_test}, + {"octet_test", octet_test}, + {"bool_test", bool_test}, + {"struct_test", struct_test}, + {"struct2_test", struct2_test}, + {"seq1_test", seq1_test}, + {"seq2_test", seq2_test}, + {"seq3_test", seq3_test}, + {"seq4_test", seq4_test}, + {"seq5_test", seq5_test}, + {"array1_test", array1_test}, + {"array2_test", array2_test}, + {"enum_test", enum_test}, + {"string1_test", string1_test}, + {"string2_test", string2_test}, + {"string3_test", string3_test}, + {"string4_test", string4_test}, + {"pid_test", pid_test}, + {"port_test", port_test}, + {"ref_test", ref_test}, + {"term_test", term_test}, + {"typedef_test", typedef_test}, + {"inline_sequence_test", inline_sequence_test}, + {"term_sequence_test", term_sequence_test}, + {"term_struct_test", term_struct_test}, + {"wstring1_test", wstring1_test}, + {"", NULL} +}; + +/* Other prototypes */ +static int cmp_aseq(m_aseq *a1, m_aseq *a2); +static int cmp_a(m_a *a1, m_a *a2); +static int cmp_bseq(m_bseq *b1, m_bseq *b2); +static int cmp_b(m_b *b1, m_b *b2); +static int cmp_lseq(m_lseq *b1, m_lseq *b2); +static int cmp_etseq(m_etseq *b1, m_etseq *b2); +static int cmp_et(m_et* b1, m_et *b2); +static int cmp_es(m_es *b1, m_es *b2); +static int cmp_arr1(m_arr1 b1, m_arr1 b2); +static int cmp_dd(m_dd b1, m_dd b2); +static int cmp_strRec(m_strRec *b1, m_strRec *b2); +static int cmp_sseq(m_sseq *b1, m_sseq *b2); +static int cmp_pid(erlang_pid *p1, erlang_pid *p2); +static int cmp_port(erlang_port *p1, erlang_port *p2); +static int cmp_ref(erlang_ref *p1, erlang_ref *p2); +static int cmp_s(m_s *b1, m_s *b2); +static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2); +static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2); +static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2); +static int cmp_arr3(m_arr3 b1, m_arr3 b2); + +static void print_aseq(m_aseq *a); +static void print_a(m_a *a); +static void print_bseq(m_bseq *b); +static void print_lseq(m_lseq *b); +static void print_b(m_b *b); +static void print_etseq(m_etseq *b); +static void print_et(m_et* b); +static void print_es(m_es *b); +static void print_arr1(long a[500]); +static void print_dd(long a[2][3]); +static void print_strRec(m_strRec* sr); +static void print_sseq(m_sseq *b); +static void print_pid(erlang_pid *p); +static void print_port(erlang_port *p); +static void print_ref(erlang_ref *p); +static void print_term(ETERM *t); +static void print_s(m_s *p); +static void print_ssstr3(m_ssstr3 *b1); +static void print_ssarr3(m_ssarr3 *b1); +static void print_sarr3(m_sarr3 *b1); +static void print_arr3(m_arr3 b1); +static void print_wstr(CORBA_wchar *ws); + +static void free_etseq_buf(m_etseq *b); +static void free_et(m_et* b); + +#ifdef __WIN32__ +typedef struct { + long tv_sec; + long tv_usec; +} MyTimeval; +#else +typedef struct timeval MyTimeval; +#endif +static void my_gettimeofday(MyTimeval *tv); +static void showtime(MyTimeval *start, MyTimeval *stop); +static void usage(void); +static void done(int r); + + + +/* main */ + +#ifdef VXWORKS +int client(int argc, char **argv) +#else +int main(int argc, char **argv) +#endif +{ + struct hostent *hp; + erlang_pid pid; + MyTimeval start, stop; + int i, fd, ires, tres; + IC_Env *env; + int tries = 0; + char *this_node_name = NULL; + char *peer_node = NULL; + char *peer_process_name = NULL; + char *cookie = NULL; + char host[HOSTNAMESZ + 1]; + TestFunc test_func = NULL; + TestCase *test_case; + char *test_case_name = NULL; + +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + + if (WSAStartup(wVersionRequested, &wsaData) != 0) { + fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL"); + exit(1); + } +#endif + + progname = argv[0]; + host[HOSTNAMESZ] = '\0'; + if (gethostname(host, HOSTNAMESZ) < 0) { + fprintf(stderr, "Can't find own hostname\n"); + done(1); + } + if ((hp = gethostbyname(host)) == 0) { + fprintf(stderr, "Can't get ip address for host %s\n", host); + done(1); + } + for (i = 1; i < argc; i++) { + if (cmp_str(argv[i], "-help")) { + usage(); + done(0); + } else if (cmp_str(argv[i], "-this-node-name")) { + i++; + this_node_name = argv[i]; + } else if (cmp_str(argv[i], "-peer-node")) { + i++; + peer_node = argv[i]; + } else if (cmp_str(argv[i], "-peer-process-name")) { + i++; + peer_process_name = argv[i]; + } else if (cmp_str(argv[i], "-cookie")) { + i++; + cookie = argv[i]; + } else if (cmp_str(argv[i], "-test-case")) { + i++; + test_case_name = argv[i]; + } else { + fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]); + usage(); + done(1); + } + } + + if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL + || peer_process_name == NULL || cookie == NULL) { + fprintf(stderr, "Error: missing option\n"); + usage(); + done(1); + } + + test_case = test_cases; + while (test_case->func) { + if (cmp_str(test_case->name, test_case_name)) { + test_func = test_case->func; + break; + } + test_case++; + } + if (test_func == NULL) { + fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name); + done(1); + } + + /* Behead hostname at first dot */ + for (i=0; host[i] != '\0'; i++) { + if (host[i] == '.') { host[i] = '\0'; break; } + } + sprintf(this_node, "%s@%s", this_node_name, host); + fprintf(stderr, "c_client: this node: \"%s\"\n", this_node); + fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node); + fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name); + + fprintf(stderr, "c_client: starting\n"); + + /* initialize erl_interface */ + erl_init(NULL, 0); + + for (tries = 0; tries < MAXTRIES; tries++) { + + /* connect to erlang node */ + + ires = erl_connect_xinit(host, this_node_name, this_node, + (struct in_addr *)*hp->h_addr_list, + cookie, 0); + + fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires); + + fd = erl_connect(peer_node); + fprintf(stderr, "c_client: erl_connect(): %d\n", fd); + + if (fd >= 0) + break; + fprintf(stderr, "c_client: cannot connect, retrying\n"); + } + if (fd < 0) { + fprintf(stderr, "c_client: cannot connect, exiting\n"); + done(1); + } + env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ); + env->_fd = fd; + strcpy(env->_regname, peer_process_name); + env->_to_pid = NULL; + env->_from_pid = &pid; + + strcpy(pid.node, this_node); + pid.num = fd; + pid.serial = 0; + pid.creation = 0; + + my_gettimeofday(&start); + tres = test_func(env); /* Call test case */ + my_gettimeofday(&stop); + showtime(&start, &stop); + erl_close_connection(fd); + + printf("c_client: env->_inbuf before : %d\n", INBUFSZ); + printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ); + printf("c_client: env->_inbuf after : %d\n", env->_inbufsz); + printf("c_client: env->_outbuf after : %d\n", env->_outbufsz); + + CORBA_free(env->_inbuf); + CORBA_free(env->_outbuf); + CORBA_free(env); + done(tres); +} + +static void usage() +{ + fprintf(stderr, "Usage: %s [-help] -this-node-name <name> " + "-peer-node <nodename> -peer-process-name <name> " + "-cookie <cookie> -test-case <test case name>\n", progname); + fprintf(stderr, "Example:\n %s -this-node-name kalle " + "-peer-node olle@home -peer-process-name idltest " + "-cookie oa678er -test-case octet_test\n", progname); +} + +static void done(int r) +{ +#ifdef __WIN32__ + WSACleanup(); +#endif + exit(r); +} + + +/* TESTS */ + +static int void_test(IC_Env *env) +{ + fprintf(stdout, "\n======== m_i_void test ======\n\n"); + m_i_void_test(NULL,env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(1); +} + +static int long_test(IC_Env *env) +{ + long l = 4711, lo, lr; + + fprintf(stdout, "\n======== m_i_long test ======\n\n"); + lr = m_i_long_test(NULL, l, &lo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(l == lo && l == lr); + if (l != lo) + fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", l, lo); + if (l != lr) + fprintf(stdout, " result error, sent: %ld, got: %ld\n", l, lr); + return -1; +} + +static int long_long_test(IC_Env *env) +{ + CORBA_long_long ll = 4711, llo, llr; + + fprintf(stdout, "\n======== m_i_longlong test ======\n\n"); + llr = m_i_longlong_test(NULL, ll, &llo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ll == llo && ll == llr); + if (ll != llo) + fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", + ll, llo); + if (ll != llr) + fprintf(stdout, " result error, sent: %ld, got: %ld\n", ll, llr); + return -1; +} + +static int unsigned_short_test(IC_Env *env) +{ + unsigned short x, y = 2, z; + + fprintf(stdout, "\n======== m_i_ushort test ======\n\n"); + x = m_i_ushort_test(NULL, y, &z, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(y == z && y == x); + if (y != z) + fprintf(stdout, " out parameter error, sent: %d, got: %d\n", y, z); + if (y != x) + fprintf(stdout, " result error, sent: %d, got: %d\n", y, x); + return -1; +} + + +static int unsigned_long_test(IC_Env *env) +{ + unsigned long ul = 5050, ulo, ulr; + + fprintf(stdout, "\n======== m_i_ulong test ======\n\n"); + ulr = m_i_ulong_test(NULL, ul, &ulo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ul == ulo && ul == ulr); + if (ul != ulo) + fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n", + ul, ulo); + if (ul != ulr) + fprintf(stdout, " result error, sent: %lu, got: %lu\n", ul, ulr); + return -1; +} + +/* + * Note: CORBA_unsigned_long_long is in fact a plain long. + */ +static int unsigned_long_long_test(IC_Env *env) +{ + CORBA_unsigned_long_long ull = 5050, ullo, ullr; + + fprintf(stdout, "\n======== m_i_ulonglong test ======\n\n"); + ullr = m_i_ulonglong_test(NULL, ull, &ullo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ull == ullo && ull == ullr); + if (ull != ullo) + fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n", + ull, ullo); + if (ull != ullr) + fprintf(stdout, " result error, sent: %lu, got: %lu\n", + ull, ullr); + return -1; +} + +static int double_test(IC_Env *env) +{ + double d = 12.1212, db, dr; + + fprintf(stdout, "\n======== m_i_double test ======\n\n"); + dr = m_i_double_test(NULL, d, &db, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(d == db && d == dr); + if (d != db) + fprintf(stdout, " out parameter error, sent: %f, got: %f\n", d, db); + if (d != dr) + fprintf(stdout, " result error, sent: %f, got: %f\n", d, dr); + return -1; +} + +static int char_test(IC_Env *env) +{ + char c = 'g', co, cr; + + /* char test */ + fprintf(stdout, "\n======== m_i_char test ======\n\n"); + cr = m_i_char_test(NULL, c, &co, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(c == co && c == cr); + if (c !=co) + fprintf(stdout, " out parameter error, sent: %c, got: %c\n", c, co); + if (c != cr) + fprintf(stdout, " result error, sent: %c, got: %c\n", c, cr); + return -1; +} + +static int wchar_test(IC_Env *env) +{ + CORBA_wchar wc = 103, wco, wcr; + + fprintf(stdout, "\n======== m_i_wchar test ======\n\n"); + wcr = m_i_wchar_test(NULL, wc, &wco, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(wc == wco && wc == wcr); + if (wc != wco) + fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n", + wc, wco); + if (wc != wcr) + fprintf(stdout, " result error, sent: %lu, got: %lu\n", + wc, wcr); + return -1; +} + +static int octet_test(IC_Env *env) +{ + char o ='r', oo, or; + + fprintf(stdout, "\n======== m_i_octet test ======\n\n"); + or = m_i_octet_test(NULL, o, &oo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(o == oo && o == or); + if (o != oo) + fprintf(stdout, " out parameter error, sent: %c, got: %c\n", o, oo); + if (o != or) + fprintf(stdout, " result error, sent: %c, got: %c\n", o, or); + return -1; +} + +static int bool_test(IC_Env *env) +{ + unsigned char i = 0, io, ir; + + fprintf(stdout, "\n======== m_i_bool test ======\n\n"); + ir = m_i_bool_test(NULL, i, &io, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(i == io && i == ir); + if (i != io) + fprintf(stdout, " out parameter error, sent: %d, got: %d\n", i, io); + if (i != ir) + fprintf(stdout, " result error, sent: %d, got: %d\n", i, ir); + return -1; +} + +static int struct_test(IC_Env *env) +{ + m_b b = {4711, 'a'}, bo, br; + + fprintf(stdout, "\n======== m_i_struct test ======\n\n"); + br = m_i_struct_test(NULL, &b, &bo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_b(&b, &bo) && cmp_b(&b, &br)); + if (!cmp_b(&b, &bo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_b(&b); + fprintf(stdout, " got:\n"); + print_b(&bo); + fprintf(stdout, "\n"); + } + if (!cmp_b(&b, &br)) { + fprintf(stdout, " result error, sent:\n"); + print_b(&b); + fprintf(stdout, " got:\n"); + print_b(&br); + fprintf(stdout, "\n"); + } + return -1; +} + +static int struct2_test(IC_Env *env) +{ + m_es esi = {m_peach, 5050}, eso, esr; + + fprintf(stdout, "\n======== m_i_struct2 test ======\n\n"); + esr = m_i_struct2_test(NULL, &esi, &eso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_es(&esi, &eso) && cmp_es(&esi, &esr)); + if (!cmp_es(&esi, &eso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_es(&esi); + fprintf(stdout, " got:\n"); + print_es(&eso); + fprintf(stdout, "\n"); + } + if (!cmp_es(&esi, &esr)) { + fprintf(stdout, " result error, sent:\n"); + print_es(&esi); + fprintf(stdout, " got:\n"); + print_es(&esr); + fprintf(stdout, "\n"); + } + return -1; +} + + +static int seq1_test(IC_Env *env) +{ + m_bseq bs, *bso, *bsr; + + m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}}; + bs._length = 3; + bs._buffer = ba; + + fprintf(stdout, "\n======== m_i_seq1 test ======\n\n"); + bsr = m_i_seq1_test(NULL, &bs, &bso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_bseq(&bs, bso) && cmp_bseq(&bs, bsr)); + if (!cmp_bseq(&bs, bso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_bseq(&bs); + fprintf(stdout, " got:\n"); + print_bseq(bso); + fprintf(stdout, "\n"); + } + if (!cmp_bseq(&bs, bsr)) { + fprintf(stdout, " result error, sent:\n"); + print_bseq(&bs); + fprintf(stdout, " got:\n"); + print_bseq(bsr); + fprintf(stdout, "\n"); + } + CORBA_free(bso); + CORBA_free(bsr); + return -1; +} + +static int seq2_test(IC_Env *env) +{ + m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}}; + m_a a; + m_a aa[2]; + m_aseq as, *aso, *asr; + + a.l = 9999; + a.y._length = 3; + a.y._buffer = ba; + a.d = 66.89898989; + + aa[0] = a; + aa[1] = a; + as._length = 2; + as._buffer = aa; + + fprintf(stdout, "\n======== m_i_seq2 test ======\n\n"); + asr = m_i_seq2_test(NULL, &as, &aso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_aseq(&as, aso) && cmp_aseq(&as, asr)); + if (!cmp_aseq(&as, aso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_aseq(&as); + fprintf(stdout, " got:\n"); + print_aseq(aso); + fprintf(stdout, "\n"); + } + if (!cmp_aseq(&as, asr)) { + fprintf(stdout, " result error, sent:\n"); + print_aseq(&as); + fprintf(stdout, " got:\n"); + print_aseq(asr); + fprintf(stdout, "\n"); + } + CORBA_free(aso); + CORBA_free(asr); + return -1; +} + +static int seq3_test(IC_Env *env) +{ + m_lseq lsi, *lso, *lsr; + long al[500]; + int i=0; + + for (i = 0; i < 500; i++) + al[i]=i; + lsi._length = 500; + lsi._buffer = al; + + fprintf(stdout, "\n======== m_i_seq3 test ======\n\n"); + lsr = m_i_seq3_test(NULL, &lsi, &lso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_lseq(&lsi, lso) && cmp_lseq(&lsi, lsr)); + if (!cmp_lseq(&lsi, lso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_lseq(&lsi); + fprintf(stdout, " got:\n"); + print_lseq(lso); + fprintf(stdout, "\n"); + } + if (!cmp_lseq(&lsi, lsr)) { + fprintf(stdout, " result error, sent:\n"); + print_lseq(&lsi); + fprintf(stdout, " got:\n"); + print_lseq(lsr); + fprintf(stdout, "\n"); + } + CORBA_free(lso); + CORBA_free(lsr); + return -1; +} + +static int seq4_test(IC_Env *env) +{ + char *stra0[3] = {"a", "long", "time"}; + char *stra1[3] = {"ago", "there", "was"}; + char *stra2[3] = {"a", "buggy", "compiler"}; + m_sstr3 str3s[3] = {{3, 3, stra0}, {3, 3, stra1}, {3, 3, stra2}}; + m_ssstr3 str3ssi = {3, 3, str3s}; + m_ssstr3 *str3sso, *str3ssr; + + fprintf(stdout, "\n======== m_i_seq4 test ======\n\n"); + str3ssr = m_i_seq4_test(NULL, &str3ssi, &str3sso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_ssstr3(&str3ssi, str3sso) && + cmp_ssstr3(&str3ssi, str3ssr)); + if (!cmp_ssstr3(&str3ssi, str3sso)){ + fprintf(stdout, " out parameter error, sent:\n"); + print_ssstr3(&str3ssi); + fprintf(stdout, " got:\n"); + print_ssstr3(str3sso); + fprintf(stdout, "\n"); + } + if (!cmp_ssstr3(&str3ssi, str3ssr)) { + fprintf(stdout, " result error, sent:\n"); + print_ssstr3(&str3ssi); + fprintf(stdout, " got:\n"); + print_ssstr3(str3ssr); + fprintf(stdout, "\n"); + } + CORBA_free(str3sso); + CORBA_free(str3ssr); + return -1; +} + +static int seq5_test(IC_Env *env) +{ + m_arr3 arr3a[3] = { + {4711, 18931947, 3}, + {4711, 18931947, 3}, + {4711, 18931947, 3}}; + m_sarr3 arr3sa[3] = {{3, 3, arr3a}, {3, 3, arr3a}, {3, 3, arr3a}}; + m_ssarr3 arr3ssi = {3, 3, arr3sa}; + m_ssarr3 *arr3sso; + m_ssarr3 *arr3ssr; + + fprintf(stdout, "\n======== m_i_seq5 test ======\n\n"); + arr3ssr = m_i_seq5_test(NULL, &arr3ssi, &arr3sso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_ssarr3(&arr3ssi, arr3sso) && + cmp_ssarr3(&arr3ssi, arr3ssr)); + if (!cmp_ssarr3(&arr3ssi, arr3sso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_ssarr3(&arr3ssi); + fprintf(stdout, " got:\n"); + print_ssarr3(arr3sso); + fprintf(stdout, "\n"); + } + if (!cmp_ssarr3(&arr3ssi, arr3ssr)) { + fprintf(stdout, " result error, sent:\n"); + print_ssarr3(&arr3ssi); + fprintf(stdout, " got:\n"); + print_ssarr3(arr3ssr); + fprintf(stdout, "\n"); + } + CORBA_free(arr3sso); + CORBA_free(arr3ssr); + return -1; +} + +static int array1_test(IC_Env *env) +{ + int i; + long al[500]; + m_arr1 alo; + m_arr1_slice* alr; + + for (i = 0; i < 500; i++) + al[i]=i; + + fprintf(stdout, "\n======== m_i_array1 test ======\n\n"); + alr = m_i_array1_test(NULL, al, alo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_arr1(al, alo) && cmp_arr1(al, alr)); + if (!cmp_arr1(al, alo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_arr1(al); + fprintf(stdout, " got:\n"); + print_arr1(alo); + fprintf(stdout, "\n"); + } + if (!cmp_arr1(al,alr)) { + fprintf(stdout, " result error, sent:\n"); + print_arr1(al); + fprintf(stdout, " got:\n"); + print_arr1(alr); + fprintf(stdout, "\n"); + } + free(alo); + free(alr); + return -1; +} + +static int array2_test(IC_Env *env) +{ + long dl[2][3] = {{11, 2, 7}, {22, 8 ,13}}; + m_dd dlo; + m_dd_slice* dlr; + + fprintf(stdout, "\n======== m_i_array2 test ======\n\n"); + dlr = m_i_array2_test(NULL, dl, dlo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_dd(dl,dlo) && cmp_dd(dl,dlr)); + if (!cmp_dd(dl,dlo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_dd(dl); + fprintf(stdout, " got:\n"); + print_dd(dlo); + fprintf(stdout, "\n"); + } + if (!cmp_dd(dl,dlr)) { + fprintf(stdout, " result error, sent:\n"); + print_dd(dl); + fprintf(stdout, " got:\n"); + print_dd(dlr); + fprintf(stdout, "\n"); + } + free(*dlr); + return -1; +} + +static int enum_test(IC_Env *env) +{ + m_fruit ei = m_banana, eo, er; + + fprintf(stdout, "\n======== m_i_enum test ======\n\n"); + er = m_i_enum_test(NULL, ei, &eo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(ei == eo && ei == er); + if (ei != eo) + fprintf(stdout, " out parameter error, sent: %d, got: %d\n", ei, eo); + if (ei != er) + fprintf(stdout, " result error, sent: %d, got: %d\n", ei, er); + return -1; +} + +static int string1_test(IC_Env *env) +{ + char* si = longtext; + char* so; + char* sr; + + fprintf(stdout, "\n======== m_i_string1 test ======\n\n"); + sr = m_i_string1_test(NULL, si, &so, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, sr)); + if (!cmp_str(si, so)) + fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so); + if (!cmp_str(si, sr)) + fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr); + CORBA_free(so); + CORBA_free(sr); + return -1; +} + +static int string2_test(IC_Env *env) +{ + char* sa[3] = {"hello", "foo", "bar"}; + m_sseq ssi = {3, 3, sa}; + m_sseq *sso, *ssr; + + fprintf(stdout, "\n======== m_i_string2 test ======\n\n"); + ssr = m_i_string2_test(NULL, &ssi, &sso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_sseq(&ssi, sso) && cmp_sseq(&ssi, sso)); + if (!cmp_sseq(&ssi, sso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_sseq(&ssi); + fprintf(stdout, "got:\n"); + print_sseq(sso); + } + if (!cmp_sseq(&ssi, ssr)) { + fprintf(stdout, " result error, sent:\n"); + print_sseq(&ssi); + fprintf(stdout, "got:\n"); + print_sseq(ssr); + } + CORBA_free(sso); + CORBA_free(ssr); + return -1; +} + +static int string3_test(IC_Env *env) +{ + char* si = longtext; + char* so; + char* sr; + + fprintf(stdout, "\n======== m_i_string3 test ======\n\n"); + sr = m_i_string3_test(NULL, si, &so, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, so)); + if (!cmp_str(si, so)) + fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so); + if (!cmp_str(si, sr)) + fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr); + CORBA_free(so); + CORBA_free(sr); + return -1; +} + +static int string4_test(IC_Env *env) +{ + char as1[100] = "a string", as2[200] = "help", as3[200] = "hello there"; + m_strRec stri = { 1, /* dd */ + as1, /* str4 */ + {{'a', 'k'}, {'z', 'g'}, {'n', 'q'}}, /* str7 */ + {3, 3, "buf"}, /* str5 */ + as2, /* str6 */ + {'m', 'f', 'o'}, /* str8 */ + as3, /* str9 */ + {3, 3, "stu"} /* str10 */ + }; + m_strRec *stro, *strr; + + fprintf(stdout, "\n======== m_i_string4 test ======\n\n"); + strr = m_i_string4_test(NULL, &stri, &stro, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_strRec(&stri,stro) && cmp_strRec(&stri,strr)); + if (!cmp_strRec(&stri,stro)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_strRec(&stri); + fprintf(stdout, " got:\n"); + print_strRec(stro); + fprintf(stdout, "\n"); + } + if (!cmp_strRec(&stri,strr)) { + fprintf(stdout, " result error, sent:\n"); + print_strRec(&stri); + fprintf(stdout, " got:\n"); + print_strRec(strr); + fprintf(stdout, "\n"); + } + CORBA_free(stro); + CORBA_free(strr); + return -1; +} + + +static int pid_test(IC_Env *env) +{ + erlang_pid pid = {"", 7, 0, 0}, pido, pidr; + + strcpy(pid.node, this_node), /* this currently running node */ + fprintf(stdout, "\n======== m_i_pid test ======\n\n"); + pidr = m_i_pid_test(NULL, &pid, &pido, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_pid(&pid, &pido) && cmp_pid(&pid, &pidr)); + if (!cmp_pid(&pid, &pido)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_pid(&pid); + fprintf(stdout, "got:\n"); + print_pid(&pido); + } + if (!cmp_pid(&pid, &pidr)) { + fprintf(stdout, " result error, sent:\n"); + print_pid(&pid); + fprintf(stdout, "got:\n"); + print_pid(&pidr); + } + return -1; +} + +static int port_test(IC_Env *env) +{ + erlang_port porti = {"node", 5, 1}, porto, portr; + + fprintf(stdout, "\n======== m_i_port test ======\n\n"); + portr = m_i_port_test(NULL, &porti, &porto, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_port(&porti, &porto) && cmp_port(&porti, &portr)); + if (!cmp_port(&porti, &porto)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_port(&porti); + fprintf(stdout, "got:\n"); + print_port(&porto); + } + if (!cmp_port(&porti, &portr)) { + fprintf(stdout, " result error, sent:\n"); + print_port(&porti); + fprintf(stdout, "got:\n"); + print_port(&portr); + } + return -1; +} + +static int ref_test(IC_Env *env) +{ + erlang_ref refi = { "node1", 3, {1, 2, 3}, 1}, + refo, refr; + + fprintf(stdout, "\n======== m_i_ref test ======\n\n"); + refr = m_i_ref_test(NULL, &refi, &refo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_ref(&refi, &refo) && cmp_ref(&refi, &refr)); + if (!cmp_ref(&refi, &refo)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_ref(&refi); + fprintf(stdout, "got:\n"); + print_ref(&refo); + } + if (!cmp_ref(&refi, &refr)) { + fprintf(stdout, " result error, sent:\n"); + print_ref(&refi); + fprintf(stdout, "got:\n"); + print_ref(&refr); + } + return -1; +} + +static int term_test(IC_Env *env) +{ + ETERM *ti, *to, *tr; + + ti = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"); + + fprintf(stdout, "\n======== m_i_term test ======\n\n"); + tr = m_i_term_test(NULL, ti, &to, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(erl_match(ti, to) && erl_match(ti, tr)); + if (!erl_match(ti, to)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_term(ti); + fprintf(stdout, "got:\n"); + print_term(to); + } + if (!erl_match(ti, tr)) { + fprintf(stdout, " result error, sent:\n"); + print_term(ti); + fprintf(stdout, "got:\n"); + print_term(tr); + } + erl_free_term(ti); + erl_free_term(to); + erl_free_term(tr); + return -1; +} + +static int typedef_test(IC_Env *env) +{ + m_banan mbi, mbo; /* erlang_port */ + m_apa mai; /* ETERM* */ + m_apa mao = NULL; + long tl; + + strcpy(mbi.node,"node"); + mbi.id = 15; + mbi.creation = 1; + + fprintf(stdout, "\n======== m_i_typedef test ======\n\n"); + mai = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"); + tl = m_i_typedef_test(NULL, mai, &mbi, &mao, &mbo, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(erl_match(mai, mao) && cmp_port(&mbi, &mbo) && tl == 4711); + if (!erl_match(mai, mao)) { + fprintf(stdout, " out parameter error (term), sent:\n"); + print_term(mai); + fprintf(stdout, "got:\n"); + print_term(mao); + } + if (!cmp_port(&mbi, &mbo)) { + fprintf(stdout, " out parameter error (port), sent:\n"); + print_port(&mbi); + fprintf(stdout, "got:\n"); + print_port(&mbo); + } + if (tl != 4711) { + fprintf(stdout, " result error, sent: 4711, got %ld\n", tl); + } + erl_free_term(mai); + erl_free_term(mao); + return -1; +} + +static int inline_sequence_test(IC_Env *env) +{ + int i; + long al[500]; + m_s isi = {4711, {500, 10, al}}, + *iso, *isr; + + for (i = 0; i < 500; i++) + al[i]=i; + fprintf(stdout, "\n======== m_i_inline_sequence test ======\n\n"); + isr = m_i_inline_sequence_test(NULL, &isi, &iso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_s(&isi, iso) && cmp_s(&isi, isr)); + if (!cmp_s(&isi, iso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_s(&isi); + fprintf(stdout, "got:\n"); + print_s(iso); + } + if (!cmp_s(&isi, isr)) { + fprintf(stdout, " result error, sent:\n"); + print_s(&isi); + fprintf(stdout, "got:\n"); + print_s(isr); + } + CORBA_free(iso); + CORBA_free(isr); + return -1; +} + +static int term_sequence_test(IC_Env *env) +{ + ETERM* et_array[4] = { + erl_format("[{apa, 1, 23}, \"string\", {1.23, 45}]"), + erl_format("[{banan, 1, 23}, \"string\", {1.23, 45}]"), + erl_format("[{apelsin, 1, 23}, \"string\", {1.23, 45}]"), + erl_format("[{mango, 1, 23}, \"string\", {1.23, 45}]")}; + m_etseq etsi = {4, 4, et_array}, *etso, *etsr; + + fprintf(stdout, "\n======== m_i_term_sequence test ======\n\n"); + etsr = m_i_term_sequence_test(NULL, &etsi, &etso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_etseq(&etsi, etso) && cmp_etseq(&etsi, etsr)); + if (!cmp_etseq(&etsi, etso)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_etseq(&etsi); + fprintf(stdout, "got:\n"); + print_etseq(etso); + } + if (!cmp_etseq(&etsi, etsr)) { + fprintf(stdout, " result error, sent:\n"); + print_etseq(&etsi); + fprintf(stdout, "got:\n"); + print_etseq(etsr); + } + free_etseq_buf(&etsi); + free_etseq_buf(etso); + free_etseq_buf(etsr); + CORBA_free(etso); + CORBA_free(etsr); + return -1; +} + +static int term_struct_test(IC_Env *env) +{ + m_et eti = { erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"), + 121212 }; + m_et eto, etr; + + fprintf(stdout, "\n======== m_i_term_struct test ======\n\n"); + etr = m_i_term_struct_test(NULL, &eti, &eto, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_et(&eti, &eto) && cmp_et(&eti, &etr)); + if (!cmp_et(&eti, &eto)) { + fprintf(stdout, " out parameter error, sent:\n"); + print_et(&eti); + fprintf(stdout, "got:\n"); + print_et(&eto); + } + if (!cmp_et(&eti, &etr)) { + fprintf(stdout, " result error, sent:\n"); + print_et(&eti); + fprintf(stdout, "got:\n"); + print_et(&etr); + } + free_et(&eti); + free_et(&eto); + free_et(&etr); + return -1; +} + +static int wstring1_test(IC_Env *env) +{ + CORBA_wchar wsi[] = {100, 101, 102, 103, 104, 0}, *wso, *wsr; + + fprintf(stdout, "\n======== m_i_wstring1 test ======\n\n"); + wsr = m_i_wstring1_test(NULL, wsi, &wso, env); + CHECK_EXCEPTION(env); + RETURN_IF_OK(cmp_wstr(wsi, wso) && cmp_wstr(wsi, wsr)); + if (!cmp_wstr(wsi, wso)) { + fprintf(stdout, " out parameter error, sent: \n"); + print_wstr(wsi); + fprintf(stdout, "got:\n"); + print_wstr(wso); + } + if (!cmp_wstr(wsi, wsr)) { + fprintf(stdout, " result error, sent: \n"); + print_wstr(wsi); + fprintf(stdout, "got:\n"); + print_wstr(wsr); + } + CORBA_free(wso); + CORBA_free(wsr); + return -1; +} + +/* Compare functions */ +static int cmp_aseq(m_aseq *a1, m_aseq *a2) +{ + int i; + + if (a1->_length != a2->_length) + return 0; + for (i = 0; i < a1->_length; i++) + if (cmp_a(&(a1->_buffer[i]), &(a2->_buffer[i])) == 0) + return 0; + return 1; +} + +static int cmp_a(m_a *a1, m_a *a2) +{ + return a1->l == a2->l && + a1->d == a2->d && + cmp_bseq(&a1->y, &a2->y); +} + +static int cmp_bseq(m_bseq *b1, m_bseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (cmp_b(&(b1->_buffer[i]), &(b2->_buffer[i])) == 0) + return 0; + return 1; +} + +static int cmp_b(m_b *b1, m_b *b2) +{ + return b1->l == b2->l && b1->c == b2->c; +} + +static int cmp_lseq(m_lseq *b1, m_lseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (b1->_buffer[i] != b2->_buffer[i]) + return 0; + return 1; +} + +static int cmp_etseq(m_etseq *b1, m_etseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (!erl_match(b1->_buffer[i], b2->_buffer[i])) + return 0; + return 1; +} + +static int cmp_et(m_et* b1, m_et *b2) +{ + return erl_match(b1->e, b2->e) && b1->l == b2->l; +} + +static int cmp_es(m_es *b1, m_es *b2) +{ + return b1->f == b2->f && b1->l == b2->l; +} + +static int cmp_arr1(m_arr1 b1, m_arr1 b2) +{ + int i; + + for (i = 0; i < 500; i++) + if (b1[i] != b2[i]) + return 0; + return 1; +} + +static int cmp_dd(m_dd b1, m_dd b2) +{ + + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + if (b1[i][j] != b2[i][j]) + return 0; + return 1; +} + + + +static int cmp_strRec(m_strRec *b1, m_strRec *b2) +{ + int i, j; + + if (b1->bb != b2->bb) + return 0; + if (!cmp_str(b1->str4,b2->str4)) + return 0; + if (b1->str5._length != b2->str5._length) + return 0; + for (j = 0; j < b1->str5._length; j++) + if (b1->str5._buffer[j] != b2->str5._buffer[j]) + return 0; + if (!cmp_str(b1->str6,b2->str6)) + return 0; + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + if (b1->str7[i][j] != b2->str7[i][j]) + return 0; + for (j = 0; j < 3; j++) + if (b1->str8[j] != b2->str8[j]) + return 0; + if (!cmp_str(b1->str9,b2->str9)) + return 0; + if (b1->str10._length != b2->str10._length) + return 0; + for (j = 0; j < b1->str10._length; j++) + if (b1->str10._buffer[j] != b2->str10._buffer[j]) + return 0; + return 1; +} + + +static int cmp_sseq(m_sseq *b1, m_sseq *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) + if (!cmp_str(b1->_buffer[i], b2->_buffer[i])) + return 0; + return 1; +} + + +static int cmp_pid(erlang_pid *p1, erlang_pid *p2) +{ + return cmp_str(p1->node,p2-> node) && + p1->num == p2->num && + p1->serial == p2->serial && + p1->creation == p2->creation; +} + +static int cmp_port(erlang_port *p1, erlang_port *p2) +{ + return cmp_str(p1->node,p2-> node) && p1->id == p2->id; +} + +static int cmp_ref(erlang_ref *p1, erlang_ref *p2) +{ + return cmp_str(p1->node, p2->node) && + p1->len == p2->len && + (p1->len < 1 || p1->n[0] == p2->n[0]) && + (p1->len < 2 || p1->n[1] == p2->n[1]) && + (p1->len < 3 || p1->n[2] == p2->n[2]); +} + +static int cmp_s(m_s *b1, m_s *b2) +{ + int i; + + if (b1->l != b2->l) + return 0; + if (b1->sl._length != b2->sl._length) + return 0; + for (i = 0; i < b1->sl._length; i++) + if (b1->sl._buffer[i] != b2->sl._buffer[i]) + return 0; + return 1; +} + + +static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2) +{ + int i,j; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) { + if (b1->_buffer[i]._length != b2->_buffer[i]._length) + return 0; + for (j = 0; j < b1->_buffer[i]._length; j++) + if (!cmp_str(b1->_buffer[i]._buffer[j], + b2->_buffer[i]._buffer[j])) + return 0; + } + return 1; +} + + + +static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) { + if (!cmp_sarr3(&b1->_buffer[i], &b2->_buffer[i])) + return 0; + } + return 1; +} + +static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2) +{ + int i; + + if (b1->_length != b2->_length) + return 0; + for (i = 0; i < b1->_length; i++) { + if (!cmp_arr3(b1->_buffer[i], b2->_buffer[i])) + return 0; + } + return 1; +} + +static int cmp_arr3(m_arr3 b1, m_arr3 b2) +{ + int i; + + for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) { + if (b1[i] != b2[i]) + return 0; + } + return 1; +} + +/* Print functions */ +static void print_aseq(m_aseq *a) +{ + int i; + fprintf(stdout, "\nm_aseq size: %ld --------\n", a->_length); + for (i = 0; i < a->_length; i++) + print_a(&(a->_buffer[i])); +} + +static void print_a(m_a *a) +{ + fprintf(stdout, "\nm_a --------\n l: %ld\n d:%f\n", a->l, a->d); + print_bseq(&a->y); +} + +static void print_bseq(m_bseq *b) +{ + int i; + + fprintf(stdout, "\nm_bseq size: %ld --------\n",b->_length); + for (i = 0; i < b->_length; i++) + print_b(&(b->_buffer[i])); +} + +static void print_lseq(m_lseq *b) +{ + int i; + + fprintf(stdout, "\nm_lseq size: %ld --------\n",b->_length); + for (i = 0; i < b->_length; i++) + fprintf(stdout, "[%d]: %ld\n", i, b->_buffer[i]); +} + +static void print_b(m_b *b) +{ + fprintf(stdout, "\nm_b --------\n l: %ld\n c: %c\n", b->l, b->c); +} + + +static void print_etseq(m_etseq *b) +{ + int i; + + for (i = 0; i < b->_length; i++) { + fprintf(stdout, "[%d]:\n", i); + erl_print_term(stdout, b->_buffer[i]); + } +} + + +static void print_et(m_et* b) +{ + fprintf(stdout, "\net struct --------\n"); + erl_print_term(stdout, b->e); + fprintf(stdout, "long: %ld\n", b->l); + fprintf(stdout, "\n--------\n"); +} + +static void print_es(m_es *b) +{ + fprintf(stdout, "\nm_es --------\n f: %d\n l: %ld\n", b->f, b->l); +} + + +static void print_arr1(long a[10]) +{ + int i; + + for (i = 0; i < 10; i++) + fprintf(stdout, "\n[%d]: %ld\n", i, a[i]); +} + +static void print_dd(long a[2][3]) +{ + int i, j; + + fprintf(stdout, "\nlong dd[2][3] --------\n"); + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + fprintf(stdout, "\n[%d][%d]: %ld\n", i, j, a[i][j]); +} + + +static void print_strRec(m_strRec* sr) +{ + int i, j; + + fprintf(stdout, "\nboolean bb : %d\n",sr->bb); + fprintf(stdout, "string str4 : %s\n",sr->str4); + fprintf(stdout, "str7[2][3] :\n"); + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + fprintf(stdout, "str7[%d][%d]: %ld\n", i, j, sr->str7[i][j]); + fprintf(stdout, "str5._length : %ld\n",sr->str5._length); + for (j = 0; j < sr->str5._length; j++) + fprintf(stdout, "str5._buffer[%d]: %c\n", j, sr->str5._buffer[j]); + fprintf(stdout, "string str6 : %s\n",sr->str6); + fprintf(stdout, "str8 :\n"); + for (j = 0; j < 3; j++) + fprintf(stdout, "str8[%d]: %c\n", j, sr->str8[j]); + fprintf(stdout, "string str9 : %s\n",sr->str9); + fprintf(stdout, "str10._length : %ld\n",sr->str10._length); + for (j = 0; j < sr->str10._length; j++) + fprintf(stdout, "str10._buffer[%d]: %c\n", j, sr->str10._buffer[j]); +} + +static void print_sseq(m_sseq *b) +{ + int i; + + fprintf(stdout, "\nm_sseq size: %ld --------\n",b->_length); + for (i = 0; i < b->_length; i++) + fprintf(stdout, "%s\n", b->_buffer[i]); + +} + + +static void print_pid(erlang_pid *p) +{ + fprintf(stdout, "\nerlang_pid --------\n node: %s\n num: %d\n " + "serial: %d\n creation: %d\n", + p->node, p->num, p->serial, p->creation); +} + +static void print_port(erlang_port *p) +{ + fprintf(stdout, "\nerlang_port --------\n node: %s\n id: %d\n " + "creation: %d\n", p->node, p->id, p->creation); +} + +static void print_ref(erlang_ref *p) +{ + fprintf(stdout, "\nerlang_ref --------\n node: %s\n len: %d\n " + "n[0]: %d\n n[1]: %d\n n[2]: %d\n creation: %d\n", + p->node, p->len, p->n[0], p->n[1], p->n[2], p->creation); +} + +static void print_term(ETERM *t) +{ + fprintf(stdout, "\nETERM --------\n"); + erl_print_term(stdout, t); + fprintf(stdout, "\n--------\n"); +} + +static void print_s(m_s *p) +{ + int i; + + fprintf(stdout, "\n%ld\n", p->l); + for (i = 0; i < p->sl._length; i++) + fprintf(stdout, "\n[%d]: %ld\n", i, p->sl._buffer[i]); +} + + +static void print_ssstr3(m_ssstr3 *b1) +{ + int i,j; + + fprintf(stdout, "\nSSSTR3 --------\n"); + fprintf(stdout,"b1->_length = %ld\n",b1->_length); + for (i = 0; i < b1->_length; i++) { + fprintf(stdout,"\nb1->_buffer[%d]._length %ld\n", + i, b1->_buffer[i]._length); + for (j = 0; j < b1->_buffer[i]._length; j++) + fprintf(stdout,"b1->_buffer[%d]._buffer[%d] = %s\n", + i, j, b1->_buffer[i]._buffer[j]); + } + fprintf(stdout, "\n--------\n"); +} + +static void print_wstr(CORBA_wchar *ws) +{ + int i = 0; + + fprintf(stdout, "\nwstr --------\n"); + while (ws[i]) { + fprintf(stdout, "[%d]: %ld\n", i, ws[i]); + i++; + } + fprintf(stdout, "\n--------\n"); +} + + +static void print_ssarr3(m_ssarr3 *b1) +{ + int i; + + fprintf(stdout, "\nssarr3 --------\n"); + fprintf(stdout,"length: %ld\n",b1->_length); + fprintf(stdout, "buffer:\n"); + for (i = 0; i < b1->_length; i++) + print_sarr3(&b1->_buffer[i]); + fprintf(stdout, "\n--------\n"); +} + +static void print_sarr3(m_sarr3 *b1) +{ + int i; + + fprintf(stdout, "\nsarr3 --------\n"); + fprintf(stdout,"length: %ld\n",b1->_length); + fprintf(stdout, "buffer:\n"); + for (i = 0; i < b1->_length; i++) + print_arr3(b1->_buffer[i]); + fprintf(stdout, "\n--------\n"); +} + +static void print_arr3(m_arr3 b1) +{ + int i; + + fprintf(stdout, "\narr3 --------\n"); + for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) + fprintf(stdout, "%ld ", b1[i]); + fprintf(stdout, "\n--------\n"); +} + +static void free_etseq_buf(m_etseq *b) +{ + int i; + + for (i = 0; i < b->_length; i++) + erl_free_term(b->_buffer[i]); +} + +static void free_et(m_et* b) +{ + erl_free_term(b->e); +} + +static void showtime(MyTimeval *start, MyTimeval *stop) +{ + MyTimeval elapsed; + + elapsed.tv_sec = stop->tv_sec - start->tv_sec; + elapsed.tv_usec = stop->tv_usec - start->tv_usec; + while (elapsed.tv_usec < 0) { + elapsed.tv_sec -= 1; + elapsed.tv_usec += 1000000; + } + fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec); +} + +static void my_gettimeofday(MyTimeval *tv) +#ifdef __WIN32__ +#define EPOCH_JULIAN_DIFF 11644473600i64 +{ + SYSTEMTIME t; + FILETIME ft; + LONGLONG lft; + + GetSystemTime(&t); + SystemTimeToFileTime(&t, &ft); + memcpy(&lft, &ft, sizeof(lft)); + tv->tv_usec = (long) ((lft / 10i64) % 1000000i64); + tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF); +} +#elif defined VXWORKS +{ + int rate = sysClkRateGet(); /* Ticks per second */ + unsigned long ctick = tickGet(); + tv->tv_sec = ctick / rate; /* secs since reboot */ + tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate; +} +#else +{ + gettimeofday(tv, NULL); +} +#endif diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl new file mode 100644 index 0000000000..e687cec114 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl @@ -0,0 +1,173 @@ + +// %CopyrightBegin% +// +// Copyright Ericsson AB 2004-2010. 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 "erlang.idl" + + +const short TestConst = 1; + +module m { + + const short TestConst = 2; + + struct b { + long l; + char c; + }; + + struct simple { + long l; + b b_t; + }; + + enum fruit {orange, banana, apple, peach, pear}; + + typedef sequence<long> lseq; + + typedef sequence<b> bseq; + + struct a { + long l; + bseq y; + double d; + }; + + typedef sequence<a> aseq; + + typedef sequence<string> sseq; + typedef string str; + typedef long myLong; + + typedef long arr1[500], dd[2][3]; + + typedef erlang::term apa; + typedef erlang::port banan; + + typedef sequence<erlang::term> etseq; + + struct s { + long l; + sequence<long> sl; + }; + + struct es { + fruit f; + myLong l; + }; + + struct et { + erlang::term e; + long l; + }; + + + typedef sequence<char> str1; + typedef string<12> str2; + typedef char str3[3]; + + typedef sequence<string> sstr3; // sequence of string + typedef sequence<sstr3> ssstr3; // sequence of sequences of strings + + typedef long arr3[3]; // array of long + typedef sequence<arr3> sarr3; // sequence of array + typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings + + struct strRec{ + boolean bb; + string str4; + long str7[3][2]; + sequence<char> str5; + string<12> str6; + str3 str8; + str2 str9; + str1 str10; + }; + + + struct dyn { + long l; + sequence<long> sl; + }; + typedef dyn arr2[1][2]; + + + interface i { + + const short TestConst = 3; + + //arr2 suck(in arr2 x, out arr2 y ); + + ///////////////////////////////// attribute long l; + + // simple types + void void_test(); + long long_test(in long a, out long a1); + long long longlong_test(in long long a, out long long a1); + unsigned short ushort_test(in unsigned short a, out unsigned short a1); + unsigned long ulong_test(in unsigned long a, out unsigned long a1); + unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1); + double double_test(in double a, out double a1); + char char_test(in char a, out char a1); + wchar wchar_test(in wchar a, out wchar a1); + octet octet_test(in octet a, out octet a1); + boolean bool_test(in boolean a, out boolean a1); + + // Seq. and struct tests + b struct_test(in b a, out b a1); + es struct2_test(in es a, out es a1); + //simple struct3_test(in simple x, out simple y); + bseq seq1_test(in bseq a, out bseq a1); + aseq seq2_test(in aseq a, out aseq a1); + lseq seq3_test(in lseq a, out lseq a1); + ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1); + ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1); + + // Array tests + arr1 array1_test(in arr1 a, out arr1 a1); + dd array2_test(in dd a, out dd a1); + + // enum test + fruit enum_test(in fruit a, out fruit a1); + + // string tests + string string1_test(in string a, out string a1); + wstring wstring1_test(in wstring a, out wstring a1); + sseq string2_test(in sseq a, out sseq a1); + str string3_test(in str a, out str a1); + strRec string4_test(in strRec a, out strRec a1); + + // Special erlang types + erlang::pid pid_test(in erlang::pid a, out erlang::pid a1); + erlang::port port_test(in erlang::port a, out erlang::port a1); + erlang::ref ref_test(in erlang::ref a, out erlang::ref a1); + erlang::term term_test(in erlang::term a, out erlang::term a1); + + // typedef test + long typedef_test(in apa a, in banan b, out apa a1, out banan b1); + + // inlined seq. test + s inline_sequence_test(in s a, out s a1); + + // term seq. test + etseq term_sequence_test(in etseq a, out etseq a1); + // term struct test + et term_struct_test(in et a, out et a1); + + }; + +}; diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl new file mode 100644 index 0000000000..2e624ec5c0 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl @@ -0,0 +1,28 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(erl_server). + +-export([run/0, stop/0]). + +run() -> + m_i:oe_create(). + +stop() -> + gen_server:cast(cidl_test, stop). diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl new file mode 100644 index 0000000000..0c96fb9edf --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl @@ -0,0 +1,161 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(m_i_impl). +-include("m.hrl"). + +-export([init/1, terminate/2, void_test/1, long_test/2, ushort_test/2, + longlong_test/2, ulong_test/2, ulonglong_test/2, + double_test/2, char_test/2, wchar_test/2, octet_test/2, + bool_test/2, struct_test/2, struct2_test/2, seq1_test/2, + seq2_test/2, seq3_test/2, seq4_test/2, seq5_test/2, + array1_test/2, array2_test/2, enum_test/2, string1_test/2, + string2_test/2, string3_test/2, string4_test/2, pid_test/2, + port_test/2, ref_test/2, term_test/2, typedef_test/3, + inline_sequence_test/2, '_set_l'/2, '_get_l'/1, + term_struct_test/2, term_sequence_test/2, wstring1_test/2]). + +-define(PRINTDEBUG(Case), + io:format("erl_server: case: ~p~n" + "erl_server: location: ~p~n", [Case, [?FILE, ?LINE]])). +-define(PRINTDEBUG2(Case, Msg), + io:format("erl_server: case: ~p~n" + "erl_server: Msg: ~p~n" + "erl_server: location: ~p~n", [Case, Msg, [?FILE, ?LINE]])). + +init(Env) -> + {ok, []}. + +terminate(F, R) -> + ok. + +'_get_l'(State) -> + ?PRINTDEBUG("_get_l"), + {reply, State, State}. +void_test(State) -> + ?PRINTDEBUG("void_test"), + {reply, ok, State}. + +'_set_l'(State, V) -> + ?PRINTDEBUG2("_set_l", V), + {reply, ok, V}. +ushort_test(State, V) -> + ?PRINTDEBUG2("ushort_test", V), + {reply, {V, V}, State}. +long_test(State, V) -> + ?PRINTDEBUG2("long_test", V), + {reply, {V, V}, State}. +longlong_test(State, V) -> + ?PRINTDEBUG2("longlong_test", V), + {reply, {V, V}, State}. +ulong_test(State, V) -> + ?PRINTDEBUG2("ulong_test", V), + {reply, {V, V}, State}. +ulonglong_test(State, V) -> + ?PRINTDEBUG2("ulonglong_test", V), + {reply, {V, V}, State}. +double_test(State, V) -> + ?PRINTDEBUG2("double_test", V), + {reply, {V, V}, State}. +char_test(State, V) -> + ?PRINTDEBUG2("char_test", V), + {reply, {V, V}, State}. +wchar_test(State, V) -> + ?PRINTDEBUG2("wchar_test", V), + {reply, {V, V}, State}. +octet_test(State, V) -> + ?PRINTDEBUG2("octet_test", V), + {reply, {V, V}, State}. +bool_test(State, V) -> + ?PRINTDEBUG2("bool_test", V), + {reply, {V, V}, State}. + +struct_test(State, V) -> + ?PRINTDEBUG2("struct_test", V), + {reply, {V, V}, State}. +struct2_test(State, V) -> + ?PRINTDEBUG2("struct2_test", V), + {reply, {V, V}, State}. +seq1_test(State, V) -> + ?PRINTDEBUG2("seq1_test", V), + {reply, {V, V}, State}. +seq2_test(State, V) -> + ?PRINTDEBUG2("seq2_test", V), + {reply, {V, V}, State}. +seq3_test(State, V) -> + ?PRINTDEBUG2("seq3_test", V), + {reply, {V, V}, State}. +seq4_test(State, V) -> + ?PRINTDEBUG2("seq4_test", V), + {reply, {V, V}, State}. +seq5_test(State, V) -> + ?PRINTDEBUG2("seq5_test", V), + {reply, {V, V}, State}. +array1_test(State, V) -> + ?PRINTDEBUG2("array1_test", V), + {reply, {V, V}, State}. +array2_test(State, V) -> + ?PRINTDEBUG2("array2_test", V), + {reply, {V, V}, State}. +enum_test(State, V) -> + ?PRINTDEBUG2("enum_test", V), + {reply, {V, V}, State}. +string1_test(State, V) -> + ?PRINTDEBUG2("string1_test", V), + {reply, {V, V}, State}. +string2_test(State, V) -> + ?PRINTDEBUG2("string2_test", V), + {reply, {V, V}, State}. +string3_test(State, V) -> + ?PRINTDEBUG2("string3_test", V), + {reply, {V, V}, State}. +string4_test(State, V) -> + ?PRINTDEBUG2("string4_test", V), + {reply, {V, V}, State}. +pid_test(State, V) -> + ?PRINTDEBUG2("pid_test", V), + {reply, {V, V}, State}. +port_test(State, V) -> + ?PRINTDEBUG2("port_test", binary_to_list(term_to_binary(V))), + {reply, {V, V}, State}. +ref_test(State, V) -> + ?PRINTDEBUG2("ref_test", binary_to_list(term_to_binary(V))), + {reply, {V, V}, State}. +term_test(State, V) -> + ?PRINTDEBUG2("term_test", V), + {reply, {V, V}, State}. +typedef_test(State, A, B) -> + ?PRINTDEBUG2("typedef_test", [A,B]), + {reply, {4711, A, B}, State}. +inline_sequence_test(State, V) -> + ?PRINTDEBUG2("inline_sequence_test", V), + {reply, {V, V}, State}. +term_sequence_test(State, V) -> + ?PRINTDEBUG2("term_sequence_test", V), + {reply, {V, V}, State}. +term_struct_test(State, V) -> + ?PRINTDEBUG2("term_struct_test", V), + {reply, {V, V}, State}. +wstring1_test(State, V) -> + ?PRINTDEBUG2("wstring1_test", V), + {reply, {V, V}, State}. + + + + diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c new file mode 100644 index 0000000000..4e0be3fec1 --- /dev/null +++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c @@ -0,0 +1,51 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-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% + * + */ +#include "ic.h" +#include "m_i.h" + +int my_prepare_notification_encoding(CORBA_Environment *env) +{ + return oe_prepare_notification_encoding(env); +} + +int my_send_notification_tmo(CORBA_Environment *env, unsigned int send_ms) +{ + return oe_send_notification_tmo(env, send_ms); +} + +int my_prepare_request_encoding(CORBA_Environment *env) +{ + return oe_prepare_request_encoding(env); +} + +int my_send_request_and_receive_reply_tmo(CORBA_Environment *env, + unsigned int send_ms, + unsigned int recv_ms) +{ + return oe_send_request_and_receive_reply_tmo(env, send_ms, recv_ms); +} + +int my_prepare_reply_decoding(CORBA_Environment *env) +{ + return oe_prepare_reply_decoding(env); +} + + + diff --git a/lib/ic/test/erl_client_c_server_SUITE.erl b/lib/ic/test/erl_client_c_server_SUITE.erl new file mode 100644 index 0000000000..c5f5b6a218 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_SUITE.erl @@ -0,0 +1,350 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-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% +%% +%% + +%%---------------------------------------------------------------------- +%% Purpose : Test suite for erl-client/c-server +%%---------------------------------------------------------------------- + + +-module(erl_client_c_server_SUITE). +-include("test_server.hrl"). + +-export([init_per_testcase/2, fin_per_testcase/2, all/1, void_test/1, + long_test/1, longlong_test/1, ushort_test/1, ulong_test/1, + ulonglong_test/1, double_test/1, char_test/1, wchar_test/1, + octet_test/1, bool_test/1, struct_test/1, struct2_test/1, + seq1_test/1, seq2_test/1, seq3_test/1, seq4_test/1, + seq5_test/1, array1_test/1, array2_test/1, enum_test/1, + string1_test/1, string2_test/1, string3_test/1, + string4_test/1, pid_test/1, port_test/1, ref_test/1, + term_test/1, typedef_test/1, inline_sequence_test/1, + term_sequence_test/1, term_struct_test/1, wstring1_test/1]). + +-define(DEFAULT_TIMEOUT, 20000). +-define(PORT_TIMEOUT, 15000). +-define(CALL_TIMEOUT, 5000). + +-define(C_SERVER_NODE_NAME, idl_c_server_test). + +%% Add/remove code path and watchdog before/after each test case. +%% +init_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:add_patha(DataDir), + + %% Since other test suites use the module m_i, we have + %% to make sure we are using the right m_i module. + code:purge(m_i), + code:load_file(m_i), + + WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT), + [{watchdog, WatchDog}| Config]. + +fin_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:del_path(DataDir), + WatchDog = ?config(watchdog, Config), + test_server:timetrap_cancel(WatchDog). + +all(doc) -> + "Test of IC with an Erlang client and a C server. " + "The communication is via Erlang distribution."; +all(suite) -> + [void_test, long_test, longlong_test, ushort_test, + ulong_test, ulonglong_test, double_test, + char_test, wchar_test, octet_test, bool_test, struct_test, + struct2_test, seq1_test, seq2_test, seq3_test, seq4_test, + seq5_test, array1_test, array2_test, enum_test, string1_test, + string2_test, string3_test, string4_test, pid_test, port_test, + ref_test, term_test, typedef_test, inline_sequence_test, + term_sequence_test, term_struct_test, wstring1_test]. + + +array1_test(doc) -> ""; +array1_test(suite) -> []; +array1_test(Config) -> + do_test(array1_test, Config). + +array2_test(doc) -> ""; +array2_test(suite) -> []; +array2_test(Config) -> + do_test(array2_test, Config). + +bool_test(doc) -> ""; +bool_test(suite) -> []; +bool_test(Config) -> + do_test(bool_test, Config). + +char_test(doc) -> ""; +char_test(suite) -> []; +char_test(Config) -> + do_test(char_test, Config). + +double_test(doc) -> ""; +double_test(suite) -> []; +double_test(Config) -> + do_test(double_test, Config). + +enum_test(doc) -> ""; +enum_test(suite) -> []; +enum_test(Config) -> + do_test(enum_test, Config). + +inline_sequence_test(doc) -> ""; +inline_sequence_test(suite) -> []; +inline_sequence_test(Config) -> + do_test(inline_sequence_test, Config). + +longlong_test(doc) -> ""; +longlong_test(suite) -> []; +longlong_test(Config) -> + do_test(longlong_test, Config). + +long_test(doc) -> ""; +long_test(suite) -> []; +long_test(Config) -> + do_test(long_test, Config). + +octet_test(doc) -> ""; +octet_test(suite) -> []; +octet_test(Config) -> + do_test(octet_test, Config). + +pid_test(doc) -> ""; +pid_test(suite) -> []; +pid_test(Config) -> + do_test(pid_test, Config). + +port_test(doc) -> ""; +port_test(suite) -> []; +port_test(Config) -> + do_test(port_test, Config). + +ref_test(doc) -> ""; +ref_test(suite) -> []; +ref_test(Config) -> + do_test(ref_test, Config). + +seq1_test(doc) -> ""; +seq1_test(suite) -> []; +seq1_test(Config) -> + do_test(seq1_test, Config). + +seq2_test(doc) -> ""; +seq2_test(suite) -> []; +seq2_test(Config) -> + do_test(seq2_test, Config). + +seq3_test(doc) -> ""; +seq3_test(suite) -> []; +seq3_test(Config) -> + do_test(seq3_test, Config). + +seq4_test(doc) -> ""; +seq4_test(suite) -> []; +seq4_test(Config) -> + do_test(seq4_test, Config). + +seq5_test(doc) -> ""; +seq5_test(suite) -> []; +seq5_test(Config) -> + do_test(seq5_test, Config). + +string1_test(doc) -> ""; +string1_test(suite) -> []; +string1_test(Config) -> + do_test(string1_test, Config). + +string2_test(doc) -> ""; +string2_test(suite) -> []; +string2_test(Config) -> + do_test(string2_test, Config). + +string3_test(doc) -> ""; +string3_test(suite) -> []; +string3_test(Config) -> + do_test(string3_test, Config). + +string4_test(doc) -> ""; +string4_test(suite) -> []; +string4_test(Config) -> + do_test(string4_test, Config). + +struct2_test(doc) -> ""; +struct2_test(suite) -> []; +struct2_test(Config) -> + do_test(struct2_test, Config). + +struct_test(doc) -> ""; +struct_test(suite) -> []; +struct_test(Config) -> + do_test(struct_test, Config). + +term_sequence_test(doc) -> ""; +term_sequence_test(suite) -> []; +term_sequence_test(Config) -> + do_test(term_sequence_test, Config). + +term_struct_test(doc) -> ""; +term_struct_test(suite) -> []; +term_struct_test(Config) -> + do_test(term_struct_test, Config). + +term_test(doc) -> ""; +term_test(suite) -> []; +term_test(Config) -> + do_test(term_test, Config). + +typedef_test(doc) -> ""; +typedef_test(suite) -> []; +typedef_test(Config) -> + do_test(typedef_test, Config). + +ulonglong_test(doc) -> ""; +ulonglong_test(suite) -> []; +ulonglong_test(Config) -> + do_test(ulonglong_test, Config). + +ulong_test(doc) -> ""; +ulong_test(suite) -> []; +ulong_test(Config) -> + do_test(ulong_test, Config). + +ushort_test(doc) -> ""; +ushort_test(suite) -> []; +ushort_test(Config) -> + do_test(ushort_test, Config). + +void_test(doc) -> ""; +void_test(suite) -> []; +void_test(Config) -> + do_test(void_test, Config). + +wchar_test(doc) -> ""; +wchar_test(suite) -> []; +wchar_test(Config) -> + do_test(wchar_test, Config). + +wstring1_test(doc) -> ""; +wstring1_test(suite) -> []; +wstring1_test(Config) -> + do_test(wstring1_test, Config). + + +do_test(Case, Config) -> + %% Trap exits + process_flag(trap_exit, true), + Node = atom_to_list(node()), + [_NodeName, HostName] = string:tokens(Node, "@"), + DataDir = ?config(data_dir, Config), + %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]), + Cookie = atom_to_list(erlang:get_cookie()), + ServerNodeName = atom_to_list(?C_SERVER_NODE_NAME), + %% Start C-server node as a port program. We wait for the node + %% to connect to us. + Cmd = filename:join([DataDir, "c_server"]) ++ + " -this-node-name " ++ ServerNodeName ++ + " -peer-node " ++ Node ++ + " -cookie " ++ Cookie, + Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]), + ServerNode = list_to_atom(ServerNodeName ++ "@" ++ HostName), + Res = case wait_for_hidden_node(ServerNode) of + ok -> + %% Need a port for port_test and typedef_test + put(port_test_port, Port), + R = (catch erl_client:Case(ServerNode, ?CALL_TIMEOUT)), + case wait_for_completion(Port) of + {error, timeout} -> + kill_off_node(ServerNode); + _ -> + ok + end, + R; + {error, timeout} -> + case wait_for_completion(Port) of + {error, timeout} -> + kill_off_node(ServerNode); + _ -> + ok + end, + {error, timeout} + end, + process_flag(trap_exit, false), + true = Res. + + +%% Wait for eof *and* exit status, but return if exit status indicates +%% an error, or we have been waiting more than PORT_TIMEOUT seconds. +%% +wait_for_completion(Port) -> + wait_for_completion(Port, 0). + +wait_for_completion(Port, N) when N < 2 -> + receive + {Port, {data, Bytes}} -> + %% Relay output + io:format("~s", [Bytes]), + wait_for_completion(Port, N); + {Port, {exit_status, 0}} -> + wait_for_completion(Port, N + 1); + {Port, {exit_status, Status}} -> + {error, Status}; + {Port, eof} -> + wait_for_completion(Port, N + 1); + {'EXIT', Port, Reason} -> + io:format("Port exited with reason: ~w~n", [Reason]), + wait_for_completion(Port, N); + {'EXIT', From, Reason} -> + io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]), + wait_for_completion(Port, N) + after ?PORT_TIMEOUT -> + {error, timeout} + end; +wait_for_completion(_, _) -> + ok. + +wait_for_hidden_node(Node) -> + Times = ?DEFAULT_TIMEOUT div 100, + wait_for_hidden_node(Node, Times, 100). + +wait_for_hidden_node(Node, Times, WaitTime) when Times > 0 -> + io:format("Waiting for hidden node: ~p~n", [Node]), + case lists:member(Node, erlang:nodes(hidden)) of + true -> + ok; + false -> + delay(WaitTime), + wait_for_hidden_node(Node, Times - 1, WaitTime) + end; +wait_for_hidden_node(_Node, _, _WaitTime) -> + {error, timeout}. + +kill_off_node(Node) -> + catch rpc:cast(Node, erlang, halt, [1]). + +delay(Time) -> + receive + after Time -> + ok + end. + + + + diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src b/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src new file mode 100644 index 0000000000..cd34d2b247 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src @@ -0,0 +1,150 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2002-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% +# +# +# Makefile.src for erl_client_c_server test +# Note: This file *must* work for both Unix and Windows +# +# We use both `rm' (Unix) and `del' (Windows) for removing files, but +# with a `-' in front so that the error in not finding `rm' (`del') on +# Windows (Unix) is ignored. +# +# VxWorks? XXX +# + +.SUFFIXES: +.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@ + + +# Variables from ts: +# + +ERL_INCLUDE = @erl_include@ + +IC_INCLUDE_PATH = @ic_include_path@ +IC_LIB = @ic_libpath@@DS@@ic_lib@ + +ERL_INTERFACE_INCLUDE = @erl_interface_include@ +ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@ +ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@ +ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@ +ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@ + +CC = @CC@ +## XXX Should set warning flag with a DEBUG_FLAG +CFLAGS = @CFLAGS@ @DEFS@ -I$(ERL_INCLUDE) \ + -I$(IC_INCLUDE_PATH) -I$(ERL_INTERFACE_INCLUDE) + +LD = @LD@ +LDFLAGS = @CROSSLDFLAGS@ +LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \ + $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS) +ERLC = erlc + +# Generated C header files +GEN_H_FILES = \ + m__s.h \ + m_i__s.h \ + oe_erl_c_test__s.h + +# Generated C files +GEN_C_FILES = \ + m__s.c \ + m_i__s.c \ + oe_code_m_a.c \ + oe_code_m_arr1.c \ + oe_code_m_arr2.c \ + oe_code_m_arr3.c \ + oe_code_m_aseq.c \ + oe_code_m_b.c \ + oe_code_m_bseq.c \ + oe_code_m_dd.c \ + oe_code_m_dyn.c \ + oe_code_m_dyn_sl.c \ + oe_code_m_es.c \ + oe_code_m_et.c \ + oe_code_m_etseq.c \ + oe_code_m_fruit.c \ + oe_code_m_lseq.c \ + oe_code_m_s.c \ + oe_code_m_s_sl.c \ + oe_code_m_sarr3.c \ + oe_code_m_simple.c \ + oe_code_m_ssarr3.c \ + oe_code_m_sseq.c \ + oe_code_m_ssstr3.c \ + oe_code_m_sstr3.c \ + oe_code_m_str1.c \ + oe_code_m_str3.c \ + oe_code_m_strRec.c \ + oe_code_m_strRec_str5.c \ + oe_code_m_strRec_str7.c \ + oe_erl_c_test__s.c + +GEN_HRL_FILES = \ + m.hrl \ + m_i.hrl \ + oe_erl_c_test.hrl + +GEN_ERL_FILES = \ + m.erl \ + m_arr2.erl \ + m_arr3.erl \ + m_i.erl \ + m_str3.erl \ + oe_erl_c_test.erl + +C_FILES = $(GEN_C_FILES) c_server.c callbacks.c + +OBJS = $(C_FILES:.c=@obj@) + +PGMS = c_server@exe@ + +ERL_FILES = $(GEN_ERL_FILES) erl_client.erl + +EBINS = $(ERL_FILES:.erl=.@EMULATOR@) + + +all: $(PGMS) $(EBINS) + +clean: + -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + +$(PGMS): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +$(GEN_C_FILES) $(GEN_H_FILES): erl_c_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_server}" \ + "+{scoped_op_calls,true}" erl_c_test.idl + +# If we have scoped operation calls for C, we must have that for +# Erlang as well, if we use the m_i.erl file for calling the server. + +$(GEN_ERL_FILES) $(GEN_HRL_FILES): erl_c_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" \ + "+{scoped_op_calls,true}" "+{timeout,true}" erl_c_test.idl + +.c@obj@: + $(CC) -c -o $*@obj@ $(CFLAGS) $< + +.erl.@EMULATOR@: + $(ERLC) -W -I $(IC_INCLUDE_PATH) $< + diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/c_server.c b/lib/ic/test/erl_client_c_server_SUITE_data/c_server.c new file mode 100644 index 0000000000..acdeff80fe --- /dev/null +++ b/lib/ic/test/erl_client_c_server_SUITE_data/c_server.c @@ -0,0 +1,299 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2002-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% + * + */ +/* C-server for test of IC. + * + * The C-node implemented here connects to its peer node, waits for + * one message, evaluates the message, returns an result message, and + * terminates. + * + * TODO: + * + * 1. XXX #includes for VxWorks, Windows + */ + +#include <stdio.h> +#include <stdlib.h> + +#ifndef __WIN32__ +# include <unistd.h> +#endif + +#include <string.h> + +#ifdef __WIN32__ +# include <time.h> +# include <sys/timeb.h> +#elif defined VXWORKS +# include <time.h> +# include <sys/times.h> +#else +# include <sys/time.h> +#endif + +#include <ctype.h> + +#ifdef __WIN32__ +# include <winsock2.h> +# include <windows.h> +#else +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netdb.h> +#endif + +#include "ic.h" +#include "ei.h" +#include "erl_interface.h" +#include "eicode.h" +#include "m_i__s.h" +#include "m__s.h" + +#ifdef __WIN32__ +typedef struct { + long tv_sec; + long tv_usec; +} MyTimeval; +#else +typedef struct timeval MyTimeval; +#endif +static void my_gettimeofday(MyTimeval *tv); +static void showtime(MyTimeval *start, MyTimeval *stop); +static void usage(void); +static void done(int r); + +#define HOSTNAMESZ 256 +#define NODENAMESZ 512 +#define INBUFSZ 10 +#define OUTBUFSZ 0 +#define MAXTRIES 5 + +static char *progname; + +/* main */ +#ifdef VXWORKS +int c_server(int argc, char **argv) +#else +int main(int argc, char **argv) +#endif +{ + struct hostent *hp; + MyTimeval start, stop; + int i, fd, ires, tries; + CORBA_Environment *env; + char *this_node_name = NULL; + char *peer_node = NULL; + char *cookie = NULL; + char host[HOSTNAMESZ + 1]; + char this_node[NODENAMESZ + 1]; + erlang_msg msg; + int status, loop; + +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + + if (WSAStartup(wVersionRequested, &wsaData) != 0) { + fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL"); + exit(1); + } +#endif + + progname = argv[0]; + host[HOSTNAMESZ] = '\0'; + if (gethostname(host, HOSTNAMESZ) < 0) { + fprintf(stderr, "Can't find own hostname\n"); + done(1); + } + if ((hp = gethostbyname(host)) == 0) { + fprintf(stderr, "Can't get ip address for host %s\n", host); + done(1); + } + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-help") == 0) { + usage(); + done(0); + } else if (strcmp(argv[i], "-this-node-name") == 0) { + i++; + this_node_name = argv[i]; + } else if (strcmp(argv[i], "-peer-node") == 0) { + i++; + peer_node = argv[i]; + } else if (strcmp(argv[i], "-cookie") == 0) { + i++; + cookie = argv[i]; + } else { + fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]); + usage(); + done(1); + } + } + + if (this_node_name == NULL || peer_node == NULL || cookie == NULL) { + fprintf(stderr, "Error: missing option\n"); + usage(); + done(1); + } + + /* Behead hostname at first dot */ + for (i=0; host[i] != '\0'; i++) { + if (host[i] == '.') { host[i] = '\0'; break; } + } + sprintf(this_node, "%s@%s", this_node_name, host); + + fprintf(stderr, "c_server: this node: \"%s\"\n", this_node); + fprintf(stderr, "c_server: peer node: \"%s\"\n", peer_node); + + /* initialize erl_interface */ + erl_init(NULL, 0); + + for (tries = 0; tries < MAXTRIES; tries++) { + /* connect to peer node */ + ires = erl_connect_xinit(host, this_node_name, this_node, + (struct in_addr *)*hp->h_addr_list, + cookie, 0); + fprintf(stderr, "c_server: erl_connect_xinit(): %d\n", ires); + + fd = erl_connect(peer_node); + fprintf(stderr, "c_server: erl_connect(): %d\n", fd); + if (fd >= 0) + break; + fprintf(stderr, "c_server: cannot connect, retrying\n"); + } + if (fd < 0) { + fprintf(stderr, "c_server: cannot connect, exiting\n"); + done(1); + } + env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ); + env->_fd = fd; + + status = 1; + loop = 1; + my_gettimeofday(&start); + while (status >= 0 && loop > 0) { + status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz, + &msg, &env->_iin); + switch(status) { + case ERL_SEND: + case ERL_REG_SEND: + /* get result */ + m_i__switch(NULL, env); + switch(env->_major) { + case CORBA_NO_EXCEPTION: + break; + case CORBA_SYSTEM_EXCEPTION: + fprintf(stderr, "Request failure, reason : %s\n", + (char *) CORBA_exception_value(env)); + CORBA_exception_free(env); + break; + default: /* Should not happen */ + CORBA_exception_free(env); + break; + } + /* send back result data */ + if (env->_iout > 0) + ei_send_encoded(env->_fd, &env->_caller, env->_outbuf, + env->_iout); + loop = 0; + break; + case ERL_TICK: + break; + default: + if (status < 0) { + fprintf(stderr, "Status negative: %d\n", status); + loop = 0; + } + break; + } + } + my_gettimeofday(&stop); + showtime(&start, &stop); + + erl_close_connection(fd); + + CORBA_free(env->_inbuf); + CORBA_free(env->_outbuf); + CORBA_free(env); + if (status < 0) + done(-status); + else + done(0); +} + +static void usage() +{ + fprintf(stderr, "Usage: %s [-help] -this-node-name <name> " + "-peer-node <nodename> -cookie <cookie>\n", progname); + fprintf(stderr, "Example:\n %s -this-node-name kalle " + "-peer-node olle@home -cookie oa678er\n", progname); +} + +static void done(int r) +{ +#ifdef __WIN32__ + WSACleanup(); +#endif + exit(r); +} + +static void showtime(MyTimeval *start, MyTimeval *stop) +{ + MyTimeval elapsed; + + elapsed.tv_sec = stop->tv_sec - start->tv_sec; + elapsed.tv_usec = stop->tv_usec - start->tv_usec; + while (elapsed.tv_usec < 0) { + elapsed.tv_sec -= 1; + elapsed.tv_usec += 1000000; + } + fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec); +} + + + +static void my_gettimeofday(MyTimeval *tv) +#ifdef __WIN32__ +#define EPOCH_JULIAN_DIFF 11644473600i64 +{ + SYSTEMTIME t; + FILETIME ft; + LONGLONG lft; + + GetSystemTime(&t); + SystemTimeToFileTime(&t, &ft); + memcpy(&lft, &ft, sizeof(lft)); + tv->tv_usec = (long) ((lft / 10i64) % 1000000i64); + tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF); +} +#elif defined VXWORKS +{ + int rate = sysClkRateGet(); /* Ticks per second */ + unsigned long ctick = tickGet(); + tv->tv_sec = ctick / rate; /* secs since reboot */ + tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate; +} +#else +{ + gettimeofday(tv, NULL); +} +#endif diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c b/lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c new file mode 100644 index 0000000000..d6b28b619d --- /dev/null +++ b/lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c @@ -0,0 +1,610 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2002-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% + * + */ +#include <stdio.h> +#include <stdlib.h> +#ifndef __WIN32__ +# include <unistd.h> +#endif +#include <string.h> +#include <ctype.h> +#include <ic.h> +#include <erl_interface.h> +#include <ei.h> +#include "m_i__s.h" + + + +/* OK */ + +void my_void_test(CORBA_Object oe_obj, + CORBA_Environment *oe_env) +{ + /* printf("void test !\n"); */ +} + +m_i_void_test__rs* m_i_void_test__cb(CORBA_Object oe_obj, + CORBA_Environment *oe_env) +{ + return (m_i_void_test__rs*) (my_void_test); +} + + + +/* OK */ + +void my_long_test(CORBA_Object oe_obj, + long* a, + long* b, + long* c, + CORBA_Environment *oe_env) +{ + /* printf("long test !\n"); */ +} + + +m_i_long_test__rs* m_i_long_test__cb(CORBA_Object oe_obj, + long* a, + long* b, + long* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_long_test__rs*) (my_long_test); +} + +/* OK */ + +void my_longlong_test(CORBA_Object oe_obj, + CORBA_long_long* a, + CORBA_long_long* b, + CORBA_long_long* c, + CORBA_Environment *oe_env) +{ + /* printf("long test !\n"); */ +} + +m_i_longlong_test__rs* m_i_longlong_test__cb(CORBA_Object oe_obj, + CORBA_long_long* a, + CORBA_long_long* b, + CORBA_long_long* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_longlong_test__rs*) (my_longlong_test); +} + +/* OK */ +void my_ulong_test(CORBA_Object oe_obj, + unsigned long* a, + unsigned long* b, + unsigned long* c, + CORBA_Environment *oe_env) +{ + /* printf("ulong test !\n"); */ +} + +m_i_ulong_test__rs* m_i_ulong_test__cb(CORBA_Object oe_obj, + unsigned long* a, + unsigned long* b, + unsigned long* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_ulong_test__rs*) (my_ulong_test); +} + +/* OK */ +void my_ulonglong_test(CORBA_Object oe_obj, + CORBA_unsigned_long_long* a, + CORBA_unsigned_long_long* b, + CORBA_unsigned_long_long* c, + CORBA_Environment *oe_env) +{ + /* printf("ulong test !\n"); */ +} + +m_i_ulonglong_test__rs* m_i_ulonglong_test__cb(CORBA_Object oe_obj, + CORBA_unsigned_long_long* a, + CORBA_unsigned_long_long* b, + CORBA_unsigned_long_long* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_ulonglong_test__rs*) (my_ulonglong_test); +} + +m_i_ushort_test__rs* m_i_ushort_test__cb(CORBA_Object oe_obj, + unsigned short* a, + unsigned short* b, + unsigned short* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_ushort_test__rs*) NULL; +} + + +/* OK */ +void my_double_test(CORBA_Object oe_obj, + double* a, + double* b, + double* c, + CORBA_Environment *oe_env) +{ + /* printf("double test !\n"); */ +} + +m_i_double_test__rs* m_i_double_test__cb(CORBA_Object oe_obj, + double* a, + double* b, + double* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_double_test__rs*) (my_double_test); +} + +/* OK */ +m_i_char_test__rs* m_i_char_test__cb(CORBA_Object oe_obj, + char* a, + char* b, + char* c, + CORBA_Environment *oe_env) +{ + m_i_char_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + + +/* OK */ +m_i_wchar_test__rs* m_i_wchar_test__cb(CORBA_Object oe_obj, + CORBA_wchar* a, + CORBA_wchar* b, + CORBA_wchar* c, + CORBA_Environment *oe_env) +{ + m_i_wchar_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +m_i_octet_test__rs* m_i_octet_test__cb(CORBA_Object oe_obj, + char* a, + char* b, + char* c, + CORBA_Environment *oe_env) +{ + m_i_octet_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +m_i_bool_test__rs* m_i_bool_test__cb(CORBA_Object oe_obj, + CORBA_boolean* a, + CORBA_boolean* b, + CORBA_boolean* c, + CORBA_Environment *oe_env) +{ + m_i_bool_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +void my_struct_test(CORBA_Object oe_obj, + m_b* a, + m_b* b, + m_b* c, + CORBA_Environment *oe_env) +{ + /* printf("struct test !\n"); */ +} + +m_i_struct_test__rs* m_i_struct_test__cb(CORBA_Object oe_obj, + m_b* a, + m_b* b, + m_b* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_struct_test__rs*) (my_struct_test); +} + +/* OK */ +m_i_struct2_test__rs* m_i_struct2_test__cb(CORBA_Object oe_obj, + m_es* a, + m_es* b, + m_es* c, + CORBA_Environment *oe_env) +{ + m_i_struct2_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +/* XXX Commented out +m_i_struct3_test__rs* m_i_struct3_test__cb(CORBA_Object oe_obj, + m_simple* a, + m_simple* b, + m_simple* c, + CORBA_Environment *oe_env) +{ + m_i_struct3_test__rs* rs = NULL; + *a = *b; + *c = *b; + return rs; +} +*/ + +/* OK */ +m_i_seq1_test__rs* m_i_seq1_test__cb(CORBA_Object oe_obj, + m_bseq** a, + m_bseq* b, + m_bseq** c, + CORBA_Environment *oe_env) +{ + m_i_seq1_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + + +/* OK */ +m_i_seq2_test__rs* m_i_seq2_test__cb(CORBA_Object oe_obj, + m_aseq** a, + m_aseq* b, + m_aseq** c, + CORBA_Environment *oe_env) +{ + m_i_seq2_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_seq3_test__rs* m_i_seq3_test__cb(CORBA_Object oe_obj, + m_lseq** a, + m_lseq* b, + m_lseq** c, + CORBA_Environment *oe_env) +{ + m_i_seq3_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_seq4_test__rs* m_i_seq4_test__cb(CORBA_Object oe_obj, + m_ssstr3** a, + m_ssstr3* b, + m_ssstr3** c, + CORBA_Environment *oe_env) +{ + m_i_seq4_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_seq5_test__rs* m_i_seq5_test__cb(CORBA_Object oe_obj, + m_ssarr3** a, + m_ssarr3* b, + m_ssarr3** c, + CORBA_Environment *oe_env) +{ + m_i_seq5_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_array1_test__rs* m_i_array1_test__cb(CORBA_Object oe_obj, + m_arr1 a, + m_arr1 b, + m_arr1 c, + CORBA_Environment *oe_env) +{ + int i; + m_i_array1_test__rs* rs = NULL; + + for (i = 0; i < 500; i++) { + a[i] = b[i]; + c[i] = b[i]; + } + return rs; +} + +/* OK */ +m_i_array2_test__rs* m_i_array2_test__cb(CORBA_Object oe_obj, + m_dd a, + m_dd b, + m_dd c, + CORBA_Environment *oe_env) +{ + int i,j; + m_i_array2_test__rs* rs = NULL; + + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) { + a[i][j] = b[i][j]; + c[i][j] = b[i][j]; + } + return rs; +} + + +/* OK */ +m_i_enum_test__rs* m_i_enum_test__cb(CORBA_Object oe_obj, + m_fruit* a, + m_fruit* b, + m_fruit* c, + CORBA_Environment *oe_env) +{ + m_i_enum_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +m_i_string1_test__rs* m_i_string1_test__cb(CORBA_Object oe_obj, + char ** a, + char * b, + char ** c, + CORBA_Environment *oe_env) +{ + m_i_string1_test__rs* rs = NULL; + + /*printf("\nString in ------> %s\n\n",b);*/ + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_string2_test__rs* m_i_string2_test__cb(CORBA_Object oe_obj, + m_sseq** a, + m_sseq* b, + m_sseq** c, + CORBA_Environment *oe_env) +{ + m_i_string2_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_string3_test__rs* m_i_string3_test__cb(CORBA_Object oe_obj, + char ** a, + char * b, + char ** c, + CORBA_Environment *oe_env) +{ + m_i_string3_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +m_i_string4_test__rs* m_i_string4_test__cb(CORBA_Object oe_obj, + m_strRec** a, + m_strRec* b, + m_strRec** c, + CORBA_Environment *oe_env) +{ + *a = b; + *c = b; + + return (m_i_string4_test__rs*) NULL; +} + +/* OK */ +m_i_wstring1_test__rs* m_i_wstring1_test__cb(CORBA_Object oe_obj, + CORBA_wchar ** a, + CORBA_wchar * b, + CORBA_wchar ** c, + CORBA_Environment *oe_env) +{ + int tmp; + m_i_wstring1_test__rs* rs = NULL; + + /*printf("\nString in ------> %s\n\n",b);*/ + + for(tmp = 0; tmp < 5; tmp++) + fprintf(stderr,"\np[%d] = %ld\n", tmp, b[tmp]); + *a = b; + *c = b; + return rs; +} + + +/* OK */ +m_i_pid_test__rs* m_i_pid_test__cb(CORBA_Object oe_obj, + erlang_pid* a, + erlang_pid* b, + erlang_pid* c, + CORBA_Environment *oe_env) +{ + m_i_pid_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +m_i_port_test__rs* m_i_port_test__cb(CORBA_Object oe_obj, + erlang_port* a, + erlang_port* b, + erlang_port* c, + CORBA_Environment *oe_env) +{ + m_i_port_test__rs* rs = NULL; + + strcpy((*a).node,(*b).node); + (*a).id = (*b).id; + (*a).creation = 0; + + strcpy((*c).node,(*b).node); + (*c).id = (*b).id; + (*c).creation = 0; + return rs; +} + +/* OK */ +m_i_ref_test__rs* m_i_ref_test__cb(CORBA_Object oe_obj, + erlang_ref* a, + erlang_ref* b, + erlang_ref* c, + CORBA_Environment *oe_env) +{ + + m_i_ref_test__rs* rs = NULL; + + strcpy((*a).node,(*b).node); + /*(*a).id = (*b).id;*/ + (*a).len = (*b).len; + (*a).n[0] = (*b).n[0]; + (*a).n[1] = (*b).n[1]; + (*a).n[2] = (*b).n[2]; + (*a).creation = 0; + + strcpy((*c).node,(*b).node); + /*(*c).id = (*b).id;*/ + (*c).len = (*b).len; + (*c).n[0] = (*b).n[0]; + (*c).n[1] = (*b).n[1]; + (*c).n[2] = (*b).n[2]; + (*c).creation = 0; + return rs; +} + +/* OK */ +m_i_term_test__rs* m_i_term_test__cb(CORBA_Object oe_obj, + ETERM** a, + ETERM** b, + ETERM** c, + CORBA_Environment *oe_env) +{ + m_i_term_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +m_i_typedef_test__rs* m_i_typedef_test__cb(CORBA_Object oe_obj, + long* a, + ETERM** b, + erlang_port* c, + ETERM** d , + erlang_port* e, + CORBA_Environment *oe_env) +{ + m_i_typedef_test__rs* rs = NULL; + + *d = *b; + strcpy((*e).node,(*c).node); + (*e).id = (*c).id; + (*e).creation = 0; + *a = 4711; + return rs; +} + +/* OK */ +m_i_inline_sequence_test__rs* m_i_inline_sequence_test__cb( + CORBA_Object oe_obj, + m_s** a, + m_s* b, + m_s** c, + CORBA_Environment *oe_env) +{ + m_i_inline_sequence_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_term_sequence_test__rs* m_i_term_sequence_test__cb( + CORBA_Object oe_obj, + m_etseq** a, + m_etseq* b, + m_etseq** c, + CORBA_Environment *oe_env) +{ + m_i_term_sequence_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + + +/* OK */ +m_i_term_struct_test__rs* m_i_term_struct_test__cb(CORBA_Object oe_obj, + m_et* a, + m_et* b, + m_et* c, + CORBA_Environment *oe_env) +{ + m_i_term_struct_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl b/lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl new file mode 100644 index 0000000000..963bc69017 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl @@ -0,0 +1,174 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 2002-2010. 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 "erlang.idl" + + +const short TestConst = 1; + +module m { + + const short TestConst = 2; + + struct b { + long l; + char c; + }; + + struct simple { + long l; + b b_t; + }; + + enum fruit {orange, banana, apple, peach, pear}; + + typedef sequence<long> lseq; + + typedef sequence<b> bseq; + + struct a { + long l; + bseq y; + double d; + }; + + typedef sequence<a> aseq; + + typedef sequence<string> sseq; + typedef string str; + typedef long myLong; + + typedef long arr1[500], dd[2][3]; + + typedef erlang::term apa; + typedef erlang::port banan; + + typedef sequence<erlang::term> etseq; + + struct s { + long l; + sequence<long> sl; + }; + + struct es { + fruit f; + myLong l; + }; + + struct et { + erlang::term e; + long l; + }; + + + typedef sequence<char> str1; + typedef string<12> str2; + typedef char str3[3]; + + typedef sequence<string> sstr3; // sequence of string + typedef sequence<sstr3> ssstr3; // sequence of sequences of strings + + typedef long arr3[3]; // array of long + typedef sequence<arr3> sarr3; // sequence of array + typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings + + struct strRec{ + boolean bb; + string str4; + long str7[3][2]; + sequence<char> str5; + string<12> str6; + str3 str8; + str2 str9; + str1 str10; + }; + + + struct dyn { + long l; + sequence<long> sl; + }; + typedef dyn arr2[1][2]; + + + interface i { + + const short TestConst = 3; + + //arr2 suck(in arr2 x, out arr2 y ); + + ///////////////////////////////// attribute long l; + + // simple types + void void_test(); + long long_test(in long a, out long a1); + long long longlong_test(in long long a, out long long a1); + unsigned short ushort_test(in unsigned short a, out unsigned short a1); + unsigned long ulong_test(in unsigned long a, out unsigned long a1); + unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1); + double double_test(in double a, out double a1); + char char_test(in char a, out char a1); + wchar wchar_test(in wchar a, out wchar a1); + octet octet_test(in octet a, out octet a1); + boolean bool_test(in boolean a, out boolean a1); + + // Seq. and struct tests + b struct_test(in b a, out b a1); + es struct2_test(in es a, out es a1); + //simple struct3_test(in simple x, out simple y); + bseq seq1_test(in bseq a, out bseq a1); + aseq seq2_test(in aseq a, out aseq a1); + lseq seq3_test(in lseq a, out lseq a1); + ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1); + ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1); + + // Array tests + arr1 array1_test(in arr1 a, out arr1 a1); + dd array2_test(in dd a, out dd a1); + + // enum test + fruit enum_test(in fruit a, out fruit a1); + + // string tests + string string1_test(in string a, out string a1); + wstring wstring1_test(in wstring a, out wstring a1); + sseq string2_test(in sseq a, out sseq a1); + str string3_test(in str a, out str a1); + strRec string4_test(in strRec a, out strRec a1); + + // Special erlang types + erlang::pid pid_test(in erlang::pid a, out erlang::pid a1); + erlang::port port_test(in erlang::port a, out erlang::port a1); + erlang::ref ref_test(in erlang::ref a, out erlang::ref a1); + erlang::term term_test(in erlang::term a, out erlang::term a1); + + // typedef test + long typedef_test(in apa a, in banan b, out apa a1, out banan b1); + + // inlined seq. test + s inline_sequence_test(in s a, out s a1); + + // term seq. test + etseq term_sequence_test(in etseq a, out etseq a1); + // term struct test + et term_struct_test(in et a, out et a1); + + }; + +}; diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl b/lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl new file mode 100644 index 0000000000..79ec28a921 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl @@ -0,0 +1,331 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2010. 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(erl_client). + +-export([void_test/2, long_test/2, longlong_test/2, ushort_test/2, + ulong_test/2, ulonglong_test/2, double_test/2, char_test/2, + wchar_test/2, octet_test/2, bool_test/2, struct_test/2, + struct2_test/2, seq1_test/2, seq2_test/2, seq3_test/2, + seq4_test/2, seq5_test/2, array1_test/2, array2_test/2, + enum_test/2, string1_test/2, wstring1_test/2, string2_test/2, + string3_test/2, string4_test/2, pid_test/2, port_test/2, + ref_test/2, term_test/2, typedef_test/2, + inline_sequence_test/2, term_sequence_test/2, + term_struct_test/2 + +]). + +-include("m.hrl"). +-include("m_i.hrl"). +-include("oe_erl_c_test.hrl"). + +%%b +void_test(Node, Timeout) -> + Ret = m_i:void_test({olsson, Node}, Timeout), + Ret == void. % XXX Not documented +%%e + +%%b +long_test(Node, Timeout) -> + In = max_long(), + {Ret, Out} = m_i:long_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +longlong_test(Node, Timeout) -> + In = 65537, + {Ret, Out} = m_i:longlong_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +ushort_test(Node, Timeout) -> + In = max_ushort(), + {Ret, Out} = m_i:ushort_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +ulong_test(Node, Timeout) -> + In = max_ulong(), + {Ret, Out} = m_i:ulong_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +ulonglong_test(Node, Timeout) -> + In = 65537, + {Ret, Out} = m_i:ulonglong_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +double_test(Node, Timeout) -> + In = 37768.93, + {Ret, Out} = m_i:double_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +char_test(Node, Timeout) -> + In = 80, + {Ret, Out} = m_i:char_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +wchar_test(Node, Timeout) -> + In = 4097, + {Ret, Out} = m_i:wchar_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +octet_test(Node, Timeout) -> + In = 255, + {Ret, Out} = m_i:octet_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +bool_test(Node, Timeout) -> + In = false, + {Ret, Out} = m_i:bool_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +struct_test(Node, Timeout) -> + In = #m_b{l = max_long(), c = $a}, + {Ret, Out} = m_i:struct_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +struct2_test(Node, Timeout) -> + In = #m_es{ f = banana, l = max_long()}, + {Ret, Out} = m_i:struct2_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq1_test(Node, Timeout) -> + B1 = #m_b{l = max_long(), c = $a}, + B2 = #m_b{l = min_long(), c = $b}, + In = [B1, B2], + {Ret, Out} = m_i:seq1_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq2_test(Node, Timeout) -> + B = #m_b{l = max_long(), c = $a}, + A = #m_a{l = min_long(), y = [B, B], d = 4711.31}, + In = [A, A, A], + {Ret, Out} = m_i:seq2_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq3_test(Node, Timeout) -> + In = [max_long(), min_long(), max_long()], + {Ret, Out} = m_i:seq3_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq4_test(Node, Timeout) -> + In = [["hello", "all"], ["Erlang", "users", "!"]], + {Ret, Out} = m_i:seq4_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq5_test(Node, Timeout) -> + Arr3 = mk_array(3, max_long()), + In = [[Arr3, Arr3], [Arr3, Arr3, Arr3]], + {Ret, Out} = m_i:seq5_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +array1_test(Node, Timeout) -> + In = mk_array(500, min_long()), + {Ret, Out} = m_i:array1_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +array2_test(Node, Timeout) -> + In = mk_array(2, mk_array(3, min_long())), + {Ret, Out} = m_i:array2_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +enum_test(Node, Timeout) -> + In = banana, + {Ret, Out} = m_i:enum_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +string1_test(Node, Timeout) -> + In = "Developing Erlang applications is fun!", + {Ret, Out} = m_i:string1_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +wstring1_test(Node, Timeout) -> + In = [1047| "eveloping Erlang applications is fun!"], + {Ret, Out} = m_i:wstring1_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +string2_test(Node, Timeout) -> + In = ["Developing Erlang applications ", "is fun!"], + {Ret, Out} = m_i:string2_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +string3_test(Node, Timeout) -> + In = "Developing Erlang applications is fun!", + {Ret, Out} = m_i:string3_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +string4_test(Node, Timeout) -> + + In = #m_strRec{ + bb = true, + str4 = "Developing Erlang applications " + "is fun!", + str7 = mk_array(3, mk_array(2, max_long())), + str5 = [$a, $b, $c, $d, $e, $f], + str6 = "123456789012", + str8 = {$x, $y, $x}, + str9 = "123456789012", + str10 = [$a, $b, $c, $d, $e, $f] + }, + {Ret, Out} = m_i:string4_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +pid_test(Node, Timeout) -> + In = self(), + {Ret, Out} = m_i:pid_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +port_test(Node, Timeout) -> + In = get(port_test_port), + {Ret, Out} = m_i:port_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +ref_test(Node, Timeout) -> + In = make_ref(), + {Ret, Out} = m_i:ref_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +term_test(Node, Timeout) -> + In = {[a, b], 17, kalle}, + {Ret, Out} = m_i:term_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +typedef_test(Node, Timeout) -> + In1 = {nisse, [1, 2], olsson}, + In2 = get(port_test_port), + {Ret, Out1, Out2} = m_i:typedef_test({olsson, Node}, Timeout, In1, In2), + %% XXX Should check that Ret is an integer. + (Out1 == In1) and (Out2 == In2). +%%e + +%%b +inline_sequence_test(Node, Timeout) -> + In = #m_s{l = min_long(), sl = [max_long(), min_long()]}, + {Ret, Out} = m_i:inline_sequence_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +term_sequence_test(Node, Timeout) -> + In = lists:duplicate(17, {nisse, [1, 2], {kalle, olsson}}), + {Ret, Out} = m_i:term_sequence_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +term_struct_test(Node, Timeout) -> + In = #m_et{e = {nisse, ["abcde"], {kalle, olsson}}, l = 4711}, + {Ret, Out} = m_i:term_struct_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + + +%% Locals + +mk_array(Es) -> + list_to_tuple(Es). + +mk_array(N, E) -> + mk_array(lists:duplicate(N, E)). + +%% max_short() -> +%% power_of_two(15) - 1. +max_long() -> + power_of_two(31) - 1. +max_longlong() -> + power_of_two(63) - 1. +max_ushort() -> + power_of_two(16) - 1. +max_ulong() -> + power_of_two(32) - 1. +max_ulonglong() -> + power_of_two(64) - 1. + +%% min_short() -> +%% -power_of_two(15). +min_long() -> + -power_of_two(31). +%% min_longlong() -> +%% -power_of_two(63). +%% min_ushort() -> +%% 0. +%% min_ulong() -> +%% 0. +%% min_ulonglong() -> +%% 0. + +power_of_two(N) -> + round(math:pow(2, N)). + diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE.erl b/lib/ic/test/erl_client_c_server_proto_SUITE.erl new file mode 100644 index 0000000000..d75feb621a --- /dev/null +++ b/lib/ic/test/erl_client_c_server_proto_SUITE.erl @@ -0,0 +1,350 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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% +%% +%% + +%%---------------------------------------------------------------------- +%% Purpose : Test suite for erl-client/c-server +%%---------------------------------------------------------------------- + + +-module(erl_client_c_server_proto_SUITE). +-include("test_server.hrl"). + +-export([init_per_testcase/2, fin_per_testcase/2, all/1, void_test/1, + long_test/1, longlong_test/1, ushort_test/1, ulong_test/1, + ulonglong_test/1, double_test/1, char_test/1, wchar_test/1, + octet_test/1, bool_test/1, struct_test/1, struct2_test/1, + seq1_test/1, seq2_test/1, seq3_test/1, seq4_test/1, + seq5_test/1, array1_test/1, array2_test/1, enum_test/1, + string1_test/1, string2_test/1, string3_test/1, + string4_test/1, pid_test/1, port_test/1, ref_test/1, + term_test/1, typedef_test/1, inline_sequence_test/1, + term_sequence_test/1, term_struct_test/1, wstring1_test/1]). + +-define(DEFAULT_TIMEOUT, 20000). +-define(PORT_TIMEOUT, 15000). +-define(CALL_TIMEOUT, 5000). + +-define(C_SERVER_NODE_NAME, idl_c_server_test). + +%% Add/remove code path and watchdog before/after each test case. +%% +init_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:add_patha(DataDir), + + %% Since other test suites use the module m_i, we have + %% to make sure we are using the right m_i module. + code:purge(m_i), + code:load_file(m_i), + + WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT), + [{watchdog, WatchDog}| Config]. + +fin_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:del_path(DataDir), + WatchDog = ?config(watchdog, Config), + test_server:timetrap_cancel(WatchDog). + +all(doc) -> + "Test of IC with an Erlang client and a C server. " + "The communication is via Erlang distribution."; +all(suite) -> + [void_test, long_test, longlong_test, ushort_test, + ulong_test, ulonglong_test, double_test, + char_test, wchar_test, octet_test, bool_test, struct_test, + struct2_test, seq1_test, seq2_test, seq3_test, seq4_test, + seq5_test, array1_test, array2_test, enum_test, string1_test, + string2_test, string3_test, string4_test, pid_test, port_test, + ref_test, term_test, typedef_test, inline_sequence_test, + term_sequence_test, term_struct_test, wstring1_test]. + + +array1_test(doc) -> ""; +array1_test(suite) -> []; +array1_test(Config) -> + do_test(array1_test, Config). + +array2_test(doc) -> ""; +array2_test(suite) -> []; +array2_test(Config) -> + do_test(array2_test, Config). + +bool_test(doc) -> ""; +bool_test(suite) -> []; +bool_test(Config) -> + do_test(bool_test, Config). + +char_test(doc) -> ""; +char_test(suite) -> []; +char_test(Config) -> + do_test(char_test, Config). + +double_test(doc) -> ""; +double_test(suite) -> []; +double_test(Config) -> + do_test(double_test, Config). + +enum_test(doc) -> ""; +enum_test(suite) -> []; +enum_test(Config) -> + do_test(enum_test, Config). + +inline_sequence_test(doc) -> ""; +inline_sequence_test(suite) -> []; +inline_sequence_test(Config) -> + do_test(inline_sequence_test, Config). + +longlong_test(doc) -> ""; +longlong_test(suite) -> []; +longlong_test(Config) -> + do_test(longlong_test, Config). + +long_test(doc) -> ""; +long_test(suite) -> []; +long_test(Config) -> + do_test(long_test, Config). + +octet_test(doc) -> ""; +octet_test(suite) -> []; +octet_test(Config) -> + do_test(octet_test, Config). + +pid_test(doc) -> ""; +pid_test(suite) -> []; +pid_test(Config) -> + do_test(pid_test, Config). + +port_test(doc) -> ""; +port_test(suite) -> []; +port_test(Config) -> + do_test(port_test, Config). + +ref_test(doc) -> ""; +ref_test(suite) -> []; +ref_test(Config) -> + do_test(ref_test, Config). + +seq1_test(doc) -> ""; +seq1_test(suite) -> []; +seq1_test(Config) -> + do_test(seq1_test, Config). + +seq2_test(doc) -> ""; +seq2_test(suite) -> []; +seq2_test(Config) -> + do_test(seq2_test, Config). + +seq3_test(doc) -> ""; +seq3_test(suite) -> []; +seq3_test(Config) -> + do_test(seq3_test, Config). + +seq4_test(doc) -> ""; +seq4_test(suite) -> []; +seq4_test(Config) -> + do_test(seq4_test, Config). + +seq5_test(doc) -> ""; +seq5_test(suite) -> []; +seq5_test(Config) -> + do_test(seq5_test, Config). + +string1_test(doc) -> ""; +string1_test(suite) -> []; +string1_test(Config) -> + do_test(string1_test, Config). + +string2_test(doc) -> ""; +string2_test(suite) -> []; +string2_test(Config) -> + do_test(string2_test, Config). + +string3_test(doc) -> ""; +string3_test(suite) -> []; +string3_test(Config) -> + do_test(string3_test, Config). + +string4_test(doc) -> ""; +string4_test(suite) -> []; +string4_test(Config) -> + do_test(string4_test, Config). + +struct2_test(doc) -> ""; +struct2_test(suite) -> []; +struct2_test(Config) -> + do_test(struct2_test, Config). + +struct_test(doc) -> ""; +struct_test(suite) -> []; +struct_test(Config) -> + do_test(struct_test, Config). + +term_sequence_test(doc) -> ""; +term_sequence_test(suite) -> []; +term_sequence_test(Config) -> + do_test(term_sequence_test, Config). + +term_struct_test(doc) -> ""; +term_struct_test(suite) -> []; +term_struct_test(Config) -> + do_test(term_struct_test, Config). + +term_test(doc) -> ""; +term_test(suite) -> []; +term_test(Config) -> + do_test(term_test, Config). + +typedef_test(doc) -> ""; +typedef_test(suite) -> []; +typedef_test(Config) -> + do_test(typedef_test, Config). + +ulonglong_test(doc) -> ""; +ulonglong_test(suite) -> []; +ulonglong_test(Config) -> + do_test(ulonglong_test, Config). + +ulong_test(doc) -> ""; +ulong_test(suite) -> []; +ulong_test(Config) -> + do_test(ulong_test, Config). + +ushort_test(doc) -> ""; +ushort_test(suite) -> []; +ushort_test(Config) -> + do_test(ushort_test, Config). + +void_test(doc) -> ""; +void_test(suite) -> []; +void_test(Config) -> + do_test(void_test, Config). + +wchar_test(doc) -> ""; +wchar_test(suite) -> []; +wchar_test(Config) -> + do_test(wchar_test, Config). + +wstring1_test(doc) -> ""; +wstring1_test(suite) -> []; +wstring1_test(Config) -> + do_test(wstring1_test, Config). + + +do_test(Case, Config) -> + %% Trap exits + process_flag(trap_exit, true), + Node = atom_to_list(node()), + [_NodeName, HostName] = string:tokens(Node, "@"), + DataDir = ?config(data_dir, Config), + %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]), + Cookie = atom_to_list(erlang:get_cookie()), + ServerNodeName = atom_to_list(?C_SERVER_NODE_NAME), + %% Start C-server node as a port program. We wait for the node + %% to connect to us. + Cmd = filename:join([DataDir, "c_server"]) ++ + " -this-node-name " ++ ServerNodeName ++ + " -peer-node " ++ Node ++ + " -cookie " ++ Cookie, + Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]), + ServerNode = list_to_atom(ServerNodeName ++ "@" ++ HostName), + Res = case wait_for_hidden_node(ServerNode) of + ok -> + %% Need a port for port_test and typedef_test + put(port_test_port, Port), + R = (catch erl_client:Case(ServerNode, ?CALL_TIMEOUT)), + case wait_for_completion(Port) of + {error, timeout} -> + kill_off_node(ServerNode); + _ -> + ok + end, + R; + {error, timeout} -> + case wait_for_completion(Port) of + {error, timeout} -> + kill_off_node(ServerNode); + _ -> + ok + end, + {error, timeout} + end, + process_flag(trap_exit, false), + true = Res. + + +%% Wait for eof *and* exit status, but return if exit status indicates +%% an error, or we have been waiting more than PORT_TIMEOUT seconds. +%% +wait_for_completion(Port) -> + wait_for_completion(Port, 0). + +wait_for_completion(Port, N) when N < 2 -> + receive + {Port, {data, Bytes}} -> + %% Relay output + io:format("~s", [Bytes]), + wait_for_completion(Port, N); + {Port, {exit_status, 0}} -> + wait_for_completion(Port, N + 1); + {Port, {exit_status, Status}} -> + {error, Status}; + {Port, eof} -> + wait_for_completion(Port, N + 1); + {'EXIT', Port, Reason} -> + io:format("Port exited with reason: ~w~n", [Reason]), + wait_for_completion(Port, N); + {'EXIT', From, Reason} -> + io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]), + wait_for_completion(Port, N) + after ?PORT_TIMEOUT -> + {error, timeout} + end; +wait_for_completion(_, _) -> + ok. + +wait_for_hidden_node(Node) -> + Times = ?DEFAULT_TIMEOUT div 100, + wait_for_hidden_node(Node, Times, 100). + +wait_for_hidden_node(Node, Times, WaitTime) when Times > 0 -> + io:format("Waiting for hidden node: ~p~n", [Node]), + case lists:member(Node, erlang:nodes(hidden)) of + true -> + ok; + false -> + delay(WaitTime), + wait_for_hidden_node(Node, Times - 1, WaitTime) + end; +wait_for_hidden_node(_Node, _, _WaitTime) -> + {error, timeout}. + +kill_off_node(Node) -> + catch rpc:cast(Node, erlang, halt, [1]). + +delay(Time) -> + receive + after Time -> + ok + end. + + + + diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src b/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src new file mode 100644 index 0000000000..b7e7ee77d0 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src @@ -0,0 +1,150 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-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% +# +# +# Makefile.src for erl_client_c_server test +# Note: This file *must* work for both Unix and Windows +# +# We use both `rm' (Unix) and `del' (Windows) for removing files, but +# with a `-' in front so that the error in not finding `rm' (`del') on +# Windows (Unix) is ignored. +# +# VxWorks? XXX +# + +.SUFFIXES: +.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@ + + +# Variables from ts: +# + +ERL_INCLUDE = @erl_include@ + +IC_INCLUDE_PATH = @ic_include_path@ +IC_LIB = @ic_libpath@@DS@@ic_lib@ + +ERL_INTERFACE_INCLUDE = @erl_interface_include@ +ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@ +ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@ +ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@ +ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@ + +CC = @CC@ +## XXX Should set warning flag with a DEBUG_FLAG +CFLAGS = @CFLAGS@ @DEFS@ -I$(ERL_INCLUDE) \ + -I$(IC_INCLUDE_PATH) -I$(ERL_INTERFACE_INCLUDE) + +LD = @LD@ +LDFLAGS = @CROSSLDFLAGS@ +LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \ + $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS) +ERLC = erlc + +# Generated C header files +GEN_H_FILES = \ + m__s.h \ + m_i__s.h \ + oe_erl_c_test__s.h + +# Generated C files +GEN_C_FILES = \ + m__s.c \ + m_i__s.c \ + oe_code_m_a.c \ + oe_code_m_arr1.c \ + oe_code_m_arr2.c \ + oe_code_m_arr3.c \ + oe_code_m_aseq.c \ + oe_code_m_b.c \ + oe_code_m_bseq.c \ + oe_code_m_dd.c \ + oe_code_m_dyn.c \ + oe_code_m_dyn_sl.c \ + oe_code_m_es.c \ + oe_code_m_et.c \ + oe_code_m_etseq.c \ + oe_code_m_fruit.c \ + oe_code_m_lseq.c \ + oe_code_m_s.c \ + oe_code_m_s_sl.c \ + oe_code_m_sarr3.c \ + oe_code_m_simple.c \ + oe_code_m_ssarr3.c \ + oe_code_m_sseq.c \ + oe_code_m_ssstr3.c \ + oe_code_m_sstr3.c \ + oe_code_m_str1.c \ + oe_code_m_str3.c \ + oe_code_m_strRec.c \ + oe_code_m_strRec_str5.c \ + oe_code_m_strRec_str7.c \ + oe_erl_c_test__s.c + +GEN_HRL_FILES = \ + m.hrl \ + m_i.hrl \ + oe_erl_c_test.hrl + +GEN_ERL_FILES = \ + m.erl \ + m_arr2.erl \ + m_arr3.erl \ + m_i.erl \ + m_str3.erl \ + oe_erl_c_test.erl + +C_FILES = $(GEN_C_FILES) c_server.c callbacks.c + +OBJS = $(C_FILES:.c=@obj@) + +PGMS = c_server@exe@ + +ERL_FILES = $(GEN_ERL_FILES) erl_client.erl + +EBINS = $(ERL_FILES:.erl=.@EMULATOR@) + + +all: $(PGMS) $(EBINS) + +clean: + -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \ + $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) + +$(PGMS): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +$(GEN_C_FILES) $(GEN_H_FILES): erl_c_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_server}" \ + "+{scoped_op_calls,true}" erl_c_test.idl + +# If we have scoped operation calls for C, we must have that for +# Erlang as well, if we use the m_i.erl file for calling the server. + +$(GEN_ERL_FILES) $(GEN_HRL_FILES): erl_c_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" \ + "+{scoped_op_calls,true}" "+{timeout,true}" erl_c_test.idl + +.c@obj@: + $(CC) -c -o $*@obj@ $(CFLAGS) $< + +.erl.@EMULATOR@: + $(ERLC) -W -I $(IC_INCLUDE_PATH) $< + diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c b/lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c new file mode 100644 index 0000000000..329f444112 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c @@ -0,0 +1,299 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-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% + * + */ +/* C-server for test of IC. + * + * The C-node implemented here connects to its peer node, waits for + * one message, evaluates the message, returns an result message, and + * terminates. + * + * TODO: + * + * 1. XXX #includes for VxWorks, Windows + */ + +#include <stdio.h> +#include <stdlib.h> + +#ifndef __WIN32__ +# include <unistd.h> +#endif + +#include <string.h> + +#ifdef __WIN32__ +# include <time.h> +# include <sys/timeb.h> +#elif defined VXWORKS +# include <time.h> +# include <sys/times.h> +#else +# include <sys/time.h> +#endif + +#include <ctype.h> + +#ifdef __WIN32__ +# include <winsock2.h> +# include <windows.h> +#else +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netdb.h> +#endif + +#include "ic.h" +#include "ei.h" +#include "erl_interface.h" +#include "eicode.h" +#include "m_i__s.h" +#include "m__s.h" + +#ifdef __WIN32__ +typedef struct { + long tv_sec; + long tv_usec; +} MyTimeval; +#else +typedef struct timeval MyTimeval; +#endif +static void my_gettimeofday(MyTimeval *tv); +static void showtime(MyTimeval *start, MyTimeval *stop); +static void usage(void); +static void done(int r); + +#define HOSTNAMESZ 256 +#define NODENAMESZ 512 +#define INBUFSZ 10 +#define OUTBUFSZ 0 +#define MAXTRIES 5 + +static char *progname; + +/* main */ +#ifdef VXWORKS +int c_server(int argc, char **argv) +#else +int main(int argc, char **argv) +#endif +{ + struct hostent *hp; + MyTimeval start, stop; + int i, fd, ires, tries; + CORBA_Environment *env; + char *this_node_name = NULL; + char *peer_node = NULL; + char *cookie = NULL; + char host[HOSTNAMESZ + 1]; + char this_node[NODENAMESZ + 1]; + erlang_msg msg; + int status, loop; + +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + + if (WSAStartup(wVersionRequested, &wsaData) != 0) { + fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL"); + exit(1); + } +#endif + + progname = argv[0]; + host[HOSTNAMESZ] = '\0'; + if (gethostname(host, HOSTNAMESZ) < 0) { + fprintf(stderr, "Can't find own hostname\n"); + done(1); + } + if ((hp = gethostbyname(host)) == 0) { + fprintf(stderr, "Can't get ip address for host %s\n", host); + done(1); + } + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-help") == 0) { + usage(); + done(0); + } else if (strcmp(argv[i], "-this-node-name") == 0) { + i++; + this_node_name = argv[i]; + } else if (strcmp(argv[i], "-peer-node") == 0) { + i++; + peer_node = argv[i]; + } else if (strcmp(argv[i], "-cookie") == 0) { + i++; + cookie = argv[i]; + } else { + fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]); + usage(); + done(1); + } + } + + if (this_node_name == NULL || peer_node == NULL || cookie == NULL) { + fprintf(stderr, "Error: missing option\n"); + usage(); + done(1); + } + + /* Behead hostname at first dot */ + for (i=0; host[i] != '\0'; i++) { + if (host[i] == '.') { host[i] = '\0'; break; } + } + sprintf(this_node, "%s@%s", this_node_name, host); + + fprintf(stderr, "c_server: this node: \"%s\"\n", this_node); + fprintf(stderr, "c_server: peer node: \"%s\"\n", peer_node); + + /* initialize erl_interface */ + erl_init(NULL, 0); + + for (tries = 0; tries < MAXTRIES; tries++) { + /* connect to peer node */ + ires = erl_connect_xinit(host, this_node_name, this_node, + (struct in_addr *)*hp->h_addr_list, + cookie, 0); + fprintf(stderr, "c_server: erl_connect_xinit(): %d\n", ires); + + fd = erl_connect(peer_node); + fprintf(stderr, "c_server: erl_connect(): %d\n", fd); + if (fd >= 0) + break; + fprintf(stderr, "c_server: cannot connect, retrying\n"); + } + if (fd < 0) { + fprintf(stderr, "c_server: cannot connect, exiting\n"); + done(1); + } + env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ); + env->_fd = fd; + + status = 1; + loop = 1; + my_gettimeofday(&start); + while (status >= 0 && loop > 0) { + status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz, + &msg, &env->_iin); + switch(status) { + case ERL_SEND: + case ERL_REG_SEND: + /* get result */ + m_i__switch(NULL, env); + switch(env->_major) { + case CORBA_NO_EXCEPTION: + break; + case CORBA_SYSTEM_EXCEPTION: + fprintf(stderr, "Request failure, reason : %s\n", + (char *) CORBA_exception_value(env)); + CORBA_exception_free(env); + break; + default: /* Should not happen */ + CORBA_exception_free(env); + break; + } + /* send back result data */ + if (env->_iout > 0) + ei_send_encoded(env->_fd, &env->_caller, env->_outbuf, + env->_iout); + loop = 0; + break; + case ERL_TICK: + break; + default: + if (status < 0) { + fprintf(stderr, "Status negative: %d\n", status); + loop = 0; + } + break; + } + } + my_gettimeofday(&stop); + showtime(&start, &stop); + + erl_close_connection(fd); + + CORBA_free(env->_inbuf); + CORBA_free(env->_outbuf); + CORBA_free(env); + if (status < 0) + done(-status); + else + done(0); +} + +static void usage() +{ + fprintf(stderr, "Usage: %s [-help] -this-node-name <name> " + "-peer-node <nodename> -cookie <cookie>\n", progname); + fprintf(stderr, "Example:\n %s -this-node-name kalle " + "-peer-node olle@home -cookie oa678er\n", progname); +} + +static void done(int r) +{ +#ifdef __WIN32__ + WSACleanup(); +#endif + exit(r); +} + +static void showtime(MyTimeval *start, MyTimeval *stop) +{ + MyTimeval elapsed; + + elapsed.tv_sec = stop->tv_sec - start->tv_sec; + elapsed.tv_usec = stop->tv_usec - start->tv_usec; + while (elapsed.tv_usec < 0) { + elapsed.tv_sec -= 1; + elapsed.tv_usec += 1000000; + } + fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec); +} + + + +static void my_gettimeofday(MyTimeval *tv) +#ifdef __WIN32__ +#define EPOCH_JULIAN_DIFF 11644473600i64 +{ + SYSTEMTIME t; + FILETIME ft; + LONGLONG lft; + + GetSystemTime(&t); + SystemTimeToFileTime(&t, &ft); + memcpy(&lft, &ft, sizeof(lft)); + tv->tv_usec = (long) ((lft / 10i64) % 1000000i64); + tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF); +} +#elif defined VXWORKS +{ + int rate = sysClkRateGet(); /* Ticks per second */ + unsigned long ctick = tickGet(); + tv->tv_sec = ctick / rate; /* secs since reboot */ + tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate; +} +#else +{ + gettimeofday(tv, NULL); +} +#endif diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c b/lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c new file mode 100644 index 0000000000..b029bcc63c --- /dev/null +++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c @@ -0,0 +1,610 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-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% + * + */ +#include <stdio.h> +#include <stdlib.h> +#ifndef __WIN32__ +# include <unistd.h> +#endif +#include <string.h> +#include <ctype.h> +#include <ic.h> +#include <erl_interface.h> +#include <ei.h> +#include "m_i__s.h" + + + +/* OK */ + +void my_void_test(CORBA_Object oe_obj, + CORBA_Environment *oe_env) +{ + /* printf("void test !\n"); */ +} + +m_i_void_test__rs* m_i_void_test__cb(CORBA_Object oe_obj, + CORBA_Environment *oe_env) +{ + return (m_i_void_test__rs*) (my_void_test); +} + + + +/* OK */ + +void my_long_test(CORBA_Object oe_obj, + long* a, + long* b, + long* c, + CORBA_Environment *oe_env) +{ + /* printf("long test !\n"); */ +} + + +m_i_long_test__rs* m_i_long_test__cb(CORBA_Object oe_obj, + long* a, + long* b, + long* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_long_test__rs*) (my_long_test); +} + +/* OK */ + +void my_longlong_test(CORBA_Object oe_obj, + CORBA_long_long* a, + CORBA_long_long* b, + CORBA_long_long* c, + CORBA_Environment *oe_env) +{ + /* printf("long test !\n"); */ +} + +m_i_longlong_test__rs* m_i_longlong_test__cb(CORBA_Object oe_obj, + CORBA_long_long* a, + CORBA_long_long* b, + CORBA_long_long* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_longlong_test__rs*) (my_longlong_test); +} + +/* OK */ +void my_ulong_test(CORBA_Object oe_obj, + unsigned long* a, + unsigned long* b, + unsigned long* c, + CORBA_Environment *oe_env) +{ + /* printf("ulong test !\n"); */ +} + +m_i_ulong_test__rs* m_i_ulong_test__cb(CORBA_Object oe_obj, + unsigned long* a, + unsigned long* b, + unsigned long* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_ulong_test__rs*) (my_ulong_test); +} + +/* OK */ +void my_ulonglong_test(CORBA_Object oe_obj, + CORBA_unsigned_long_long* a, + CORBA_unsigned_long_long* b, + CORBA_unsigned_long_long* c, + CORBA_Environment *oe_env) +{ + /* printf("ulong test !\n"); */ +} + +m_i_ulonglong_test__rs* m_i_ulonglong_test__cb(CORBA_Object oe_obj, + CORBA_unsigned_long_long* a, + CORBA_unsigned_long_long* b, + CORBA_unsigned_long_long* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_ulonglong_test__rs*) (my_ulonglong_test); +} + +m_i_ushort_test__rs* m_i_ushort_test__cb(CORBA_Object oe_obj, + unsigned short* a, + unsigned short* b, + unsigned short* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_ushort_test__rs*) NULL; +} + + +/* OK */ +void my_double_test(CORBA_Object oe_obj, + double* a, + double* b, + double* c, + CORBA_Environment *oe_env) +{ + /* printf("double test !\n"); */ +} + +m_i_double_test__rs* m_i_double_test__cb(CORBA_Object oe_obj, + double* a, + double* b, + double* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_double_test__rs*) (my_double_test); +} + +/* OK */ +m_i_char_test__rs* m_i_char_test__cb(CORBA_Object oe_obj, + char* a, + char* b, + char* c, + CORBA_Environment *oe_env) +{ + m_i_char_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + + +/* OK */ +m_i_wchar_test__rs* m_i_wchar_test__cb(CORBA_Object oe_obj, + CORBA_wchar* a, + CORBA_wchar* b, + CORBA_wchar* c, + CORBA_Environment *oe_env) +{ + m_i_wchar_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +m_i_octet_test__rs* m_i_octet_test__cb(CORBA_Object oe_obj, + char* a, + char* b, + char* c, + CORBA_Environment *oe_env) +{ + m_i_octet_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +m_i_bool_test__rs* m_i_bool_test__cb(CORBA_Object oe_obj, + CORBA_boolean* a, + CORBA_boolean* b, + CORBA_boolean* c, + CORBA_Environment *oe_env) +{ + m_i_bool_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +void my_struct_test(CORBA_Object oe_obj, + m_b* a, + m_b* b, + m_b* c, + CORBA_Environment *oe_env) +{ + /* printf("struct test !\n"); */ +} + +m_i_struct_test__rs* m_i_struct_test__cb(CORBA_Object oe_obj, + m_b* a, + m_b* b, + m_b* c, + CORBA_Environment *oe_env) +{ + *a = *b; + *c = *b; + return (m_i_struct_test__rs*) (my_struct_test); +} + +/* OK */ +m_i_struct2_test__rs* m_i_struct2_test__cb(CORBA_Object oe_obj, + m_es* a, + m_es* b, + m_es* c, + CORBA_Environment *oe_env) +{ + m_i_struct2_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +/* XXX Commented out +m_i_struct3_test__rs* m_i_struct3_test__cb(CORBA_Object oe_obj, + m_simple* a, + m_simple* b, + m_simple* c, + CORBA_Environment *oe_env) +{ + m_i_struct3_test__rs* rs = NULL; + *a = *b; + *c = *b; + return rs; +} +*/ + +/* OK */ +m_i_seq1_test__rs* m_i_seq1_test__cb(CORBA_Object oe_obj, + m_bseq** a, + m_bseq* b, + m_bseq** c, + CORBA_Environment *oe_env) +{ + m_i_seq1_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + + +/* OK */ +m_i_seq2_test__rs* m_i_seq2_test__cb(CORBA_Object oe_obj, + m_aseq** a, + m_aseq* b, + m_aseq** c, + CORBA_Environment *oe_env) +{ + m_i_seq2_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_seq3_test__rs* m_i_seq3_test__cb(CORBA_Object oe_obj, + m_lseq** a, + m_lseq* b, + m_lseq** c, + CORBA_Environment *oe_env) +{ + m_i_seq3_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_seq4_test__rs* m_i_seq4_test__cb(CORBA_Object oe_obj, + m_ssstr3** a, + m_ssstr3* b, + m_ssstr3** c, + CORBA_Environment *oe_env) +{ + m_i_seq4_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_seq5_test__rs* m_i_seq5_test__cb(CORBA_Object oe_obj, + m_ssarr3** a, + m_ssarr3* b, + m_ssarr3** c, + CORBA_Environment *oe_env) +{ + m_i_seq5_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_array1_test__rs* m_i_array1_test__cb(CORBA_Object oe_obj, + m_arr1 a, + m_arr1 b, + m_arr1 c, + CORBA_Environment *oe_env) +{ + int i; + m_i_array1_test__rs* rs = NULL; + + for (i = 0; i < 500; i++) { + a[i] = b[i]; + c[i] = b[i]; + } + return rs; +} + +/* OK */ +m_i_array2_test__rs* m_i_array2_test__cb(CORBA_Object oe_obj, + m_dd a, + m_dd b, + m_dd c, + CORBA_Environment *oe_env) +{ + int i,j; + m_i_array2_test__rs* rs = NULL; + + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) { + a[i][j] = b[i][j]; + c[i][j] = b[i][j]; + } + return rs; +} + + +/* OK */ +m_i_enum_test__rs* m_i_enum_test__cb(CORBA_Object oe_obj, + m_fruit* a, + m_fruit* b, + m_fruit* c, + CORBA_Environment *oe_env) +{ + m_i_enum_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +m_i_string1_test__rs* m_i_string1_test__cb(CORBA_Object oe_obj, + char ** a, + char * b, + char ** c, + CORBA_Environment *oe_env) +{ + m_i_string1_test__rs* rs = NULL; + + /*printf("\nString in ------> %s\n\n",b);*/ + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_string2_test__rs* m_i_string2_test__cb(CORBA_Object oe_obj, + m_sseq** a, + m_sseq* b, + m_sseq** c, + CORBA_Environment *oe_env) +{ + m_i_string2_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_string3_test__rs* m_i_string3_test__cb(CORBA_Object oe_obj, + char ** a, + char * b, + char ** c, + CORBA_Environment *oe_env) +{ + m_i_string3_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +m_i_string4_test__rs* m_i_string4_test__cb(CORBA_Object oe_obj, + m_strRec** a, + m_strRec* b, + m_strRec** c, + CORBA_Environment *oe_env) +{ + *a = b; + *c = b; + + return (m_i_string4_test__rs*) NULL; +} + +/* OK */ +m_i_wstring1_test__rs* m_i_wstring1_test__cb(CORBA_Object oe_obj, + CORBA_wchar ** a, + CORBA_wchar * b, + CORBA_wchar ** c, + CORBA_Environment *oe_env) +{ + int tmp; + m_i_wstring1_test__rs* rs = NULL; + + /*printf("\nString in ------> %s\n\n",b);*/ + + for(tmp = 0; tmp < 5; tmp++) + fprintf(stderr,"\np[%d] = %ld\n", tmp, b[tmp]); + *a = b; + *c = b; + return rs; +} + + +/* OK */ +m_i_pid_test__rs* m_i_pid_test__cb(CORBA_Object oe_obj, + erlang_pid* a, + erlang_pid* b, + erlang_pid* c, + CORBA_Environment *oe_env) +{ + m_i_pid_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +/* OK */ +m_i_port_test__rs* m_i_port_test__cb(CORBA_Object oe_obj, + erlang_port* a, + erlang_port* b, + erlang_port* c, + CORBA_Environment *oe_env) +{ + m_i_port_test__rs* rs = NULL; + + strcpy((*a).node,(*b).node); + (*a).id = (*b).id; + (*a).creation = 0; + + strcpy((*c).node,(*b).node); + (*c).id = (*b).id; + (*c).creation = 0; + return rs; +} + +/* OK */ +m_i_ref_test__rs* m_i_ref_test__cb(CORBA_Object oe_obj, + erlang_ref* a, + erlang_ref* b, + erlang_ref* c, + CORBA_Environment *oe_env) +{ + + m_i_ref_test__rs* rs = NULL; + + strcpy((*a).node,(*b).node); + /*(*a).id = (*b).id;*/ + (*a).len = (*b).len; + (*a).n[0] = (*b).n[0]; + (*a).n[1] = (*b).n[1]; + (*a).n[2] = (*b).n[2]; + (*a).creation = 0; + + strcpy((*c).node,(*b).node); + /*(*c).id = (*b).id;*/ + (*c).len = (*b).len; + (*c).n[0] = (*b).n[0]; + (*c).n[1] = (*b).n[1]; + (*c).n[2] = (*b).n[2]; + (*c).creation = 0; + return rs; +} + +/* OK */ +m_i_term_test__rs* m_i_term_test__cb(CORBA_Object oe_obj, + ETERM** a, + ETERM** b, + ETERM** c, + CORBA_Environment *oe_env) +{ + m_i_term_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + +m_i_typedef_test__rs* m_i_typedef_test__cb(CORBA_Object oe_obj, + long* a, + ETERM** b, + erlang_port* c, + ETERM** d , + erlang_port* e, + CORBA_Environment *oe_env) +{ + m_i_typedef_test__rs* rs = NULL; + + *d = *b; + strcpy((*e).node,(*c).node); + (*e).id = (*c).id; + (*e).creation = 0; + *a = 4711; + return rs; +} + +/* OK */ +m_i_inline_sequence_test__rs* m_i_inline_sequence_test__cb( + CORBA_Object oe_obj, + m_s** a, + m_s* b, + m_s** c, + CORBA_Environment *oe_env) +{ + m_i_inline_sequence_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + +/* OK */ +m_i_term_sequence_test__rs* m_i_term_sequence_test__cb( + CORBA_Object oe_obj, + m_etseq** a, + m_etseq* b, + m_etseq** c, + CORBA_Environment *oe_env) +{ + m_i_term_sequence_test__rs* rs = NULL; + + *a = b; + *c = b; + return rs; +} + + +/* OK */ +m_i_term_struct_test__rs* m_i_term_struct_test__cb(CORBA_Object oe_obj, + m_et* a, + m_et* b, + m_et* c, + CORBA_Environment *oe_env) +{ + m_i_term_struct_test__rs* rs = NULL; + + *a = *b; + *c = *b; + return rs; +} + diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl new file mode 100644 index 0000000000..e90d0dd5f0 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl @@ -0,0 +1,174 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 2004-2010. 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 "erlang.idl" + + +const short TestConst = 1; + +module m { + + const short TestConst = 2; + + struct b { + long l; + char c; + }; + + struct simple { + long l; + b b_t; + }; + + enum fruit {orange, banana, apple, peach, pear}; + + typedef sequence<long> lseq; + + typedef sequence<b> bseq; + + struct a { + long l; + bseq y; + double d; + }; + + typedef sequence<a> aseq; + + typedef sequence<string> sseq; + typedef string str; + typedef long myLong; + + typedef long arr1[500], dd[2][3]; + + typedef erlang::term apa; + typedef erlang::port banan; + + typedef sequence<erlang::term> etseq; + + struct s { + long l; + sequence<long> sl; + }; + + struct es { + fruit f; + myLong l; + }; + + struct et { + erlang::term e; + long l; + }; + + + typedef sequence<char> str1; + typedef string<12> str2; + typedef char str3[3]; + + typedef sequence<string> sstr3; // sequence of string + typedef sequence<sstr3> ssstr3; // sequence of sequences of strings + + typedef long arr3[3]; // array of long + typedef sequence<arr3> sarr3; // sequence of array + typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings + + struct strRec{ + boolean bb; + string str4; + long str7[3][2]; + sequence<char> str5; + string<12> str6; + str3 str8; + str2 str9; + str1 str10; + }; + + + struct dyn { + long l; + sequence<long> sl; + }; + typedef dyn arr2[1][2]; + + + interface i { + + const short TestConst = 3; + + //arr2 suck(in arr2 x, out arr2 y ); + + ///////////////////////////////// attribute long l; + + // simple types + void void_test(); + long long_test(in long a, out long a1); + long long longlong_test(in long long a, out long long a1); + unsigned short ushort_test(in unsigned short a, out unsigned short a1); + unsigned long ulong_test(in unsigned long a, out unsigned long a1); + unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1); + double double_test(in double a, out double a1); + char char_test(in char a, out char a1); + wchar wchar_test(in wchar a, out wchar a1); + octet octet_test(in octet a, out octet a1); + boolean bool_test(in boolean a, out boolean a1); + + // Seq. and struct tests + b struct_test(in b a, out b a1); + es struct2_test(in es a, out es a1); + //simple struct3_test(in simple x, out simple y); + bseq seq1_test(in bseq a, out bseq a1); + aseq seq2_test(in aseq a, out aseq a1); + lseq seq3_test(in lseq a, out lseq a1); + ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1); + ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1); + + // Array tests + arr1 array1_test(in arr1 a, out arr1 a1); + dd array2_test(in dd a, out dd a1); + + // enum test + fruit enum_test(in fruit a, out fruit a1); + + // string tests + string string1_test(in string a, out string a1); + wstring wstring1_test(in wstring a, out wstring a1); + sseq string2_test(in sseq a, out sseq a1); + str string3_test(in str a, out str a1); + strRec string4_test(in strRec a, out strRec a1); + + // Special erlang types + erlang::pid pid_test(in erlang::pid a, out erlang::pid a1); + erlang::port port_test(in erlang::port a, out erlang::port a1); + erlang::ref ref_test(in erlang::ref a, out erlang::ref a1); + erlang::term term_test(in erlang::term a, out erlang::term a1); + + // typedef test + long typedef_test(in apa a, in banan b, out apa a1, out banan b1); + + // inlined seq. test + s inline_sequence_test(in s a, out s a1); + + // term seq. test + etseq term_sequence_test(in etseq a, out etseq a1); + // term struct test + et term_struct_test(in et a, out et a1); + + }; + +}; diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl new file mode 100644 index 0000000000..b5ee7af199 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl @@ -0,0 +1,331 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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(erl_client). + +-export([void_test/2, long_test/2, longlong_test/2, ushort_test/2, + ulong_test/2, ulonglong_test/2, double_test/2, char_test/2, + wchar_test/2, octet_test/2, bool_test/2, struct_test/2, + struct2_test/2, seq1_test/2, seq2_test/2, seq3_test/2, + seq4_test/2, seq5_test/2, array1_test/2, array2_test/2, + enum_test/2, string1_test/2, wstring1_test/2, string2_test/2, + string3_test/2, string4_test/2, pid_test/2, port_test/2, + ref_test/2, term_test/2, typedef_test/2, + inline_sequence_test/2, term_sequence_test/2, + term_struct_test/2 + +]). + +-include("m.hrl"). +-include("m_i.hrl"). +-include("oe_erl_c_test.hrl"). + +%%b +void_test(Node, Timeout) -> + Ret = m_i:void_test({olsson, Node}, Timeout), + Ret == void. % XXX Not documented +%%e + +%%b +long_test(Node, Timeout) -> + In = max_long(), + {Ret, Out} = m_i:long_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +longlong_test(Node, Timeout) -> + In = 65537, + {Ret, Out} = m_i:longlong_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +ushort_test(Node, Timeout) -> + In = max_ushort(), + {Ret, Out} = m_i:ushort_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +ulong_test(Node, Timeout) -> + In = max_ulong(), + {Ret, Out} = m_i:ulong_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +ulonglong_test(Node, Timeout) -> + In = 65537, + {Ret, Out} = m_i:ulonglong_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +double_test(Node, Timeout) -> + In = 37768.93, + {Ret, Out} = m_i:double_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +char_test(Node, Timeout) -> + In = 80, + {Ret, Out} = m_i:char_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +wchar_test(Node, Timeout) -> + In = 4097, + {Ret, Out} = m_i:wchar_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +octet_test(Node, Timeout) -> + In = 255, + {Ret, Out} = m_i:octet_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +bool_test(Node, Timeout) -> + In = false, + {Ret, Out} = m_i:bool_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +struct_test(Node, Timeout) -> + In = #m_b{l = max_long(), c = $a}, + {Ret, Out} = m_i:struct_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +struct2_test(Node, Timeout) -> + In = #m_es{ f = banana, l = max_long()}, + {Ret, Out} = m_i:struct2_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq1_test(Node, Timeout) -> + B1 = #m_b{l = max_long(), c = $a}, + B2 = #m_b{l = min_long(), c = $b}, + In = [B1, B2], + {Ret, Out} = m_i:seq1_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq2_test(Node, Timeout) -> + B = #m_b{l = max_long(), c = $a}, + A = #m_a{l = min_long(), y = [B, B], d = 4711.31}, + In = [A, A, A], + {Ret, Out} = m_i:seq2_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq3_test(Node, Timeout) -> + In = [max_long(), min_long(), max_long()], + {Ret, Out} = m_i:seq3_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq4_test(Node, Timeout) -> + In = [["hej", "hopp"], ["ditt", "feta", "nylle"]], + {Ret, Out} = m_i:seq4_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +seq5_test(Node, Timeout) -> + Arr3 = mk_array(3, max_long()), + In = [[Arr3, Arr3], [Arr3, Arr3, Arr3]], + {Ret, Out} = m_i:seq5_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +array1_test(Node, Timeout) -> + In = mk_array(500, min_long()), + {Ret, Out} = m_i:array1_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +array2_test(Node, Timeout) -> + In = mk_array(2, mk_array(3, min_long())), + {Ret, Out} = m_i:array2_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +enum_test(Node, Timeout) -> + In = banana, + {Ret, Out} = m_i:enum_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +string1_test(Node, Timeout) -> + In = "Die Paula muss beim Tango immer weinen", + {Ret, Out} = m_i:string1_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +wstring1_test(Node, Timeout) -> + In = [1047| "ie Paula muss beim Tango immer weinen"], + {Ret, Out} = m_i:wstring1_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +string2_test(Node, Timeout) -> + In = ["Lass doch die Blumen,", "Konrad!"], + {Ret, Out} = m_i:string2_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +string3_test(Node, Timeout) -> + In = "Seeman, lass uns freuden!", + {Ret, Out} = m_i:string3_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +string4_test(Node, Timeout) -> + + In = #m_strRec{ + bb = true, + str4 = "Paula war zu Hause in ihrem Stadtchen als die beste Tanzerin" + "bekannt", + str7 = mk_array(3, mk_array(2, max_long())), + str5 = [$a, $b, $c, $d, $e, $f], + str6 = "123456789012", + str8 = {$x, $y, $x}, + str9 = "123456789012", + str10 = [$a, $b, $c, $d, $e, $f] + }, + {Ret, Out} = m_i:string4_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +pid_test(Node, Timeout) -> + In = self(), + {Ret, Out} = m_i:pid_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +port_test(Node, Timeout) -> + In = get(port_test_port), + {Ret, Out} = m_i:port_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +ref_test(Node, Timeout) -> + In = make_ref(), + {Ret, Out} = m_i:ref_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +term_test(Node, Timeout) -> + In = {[a, b], 17, kalle}, + {Ret, Out} = m_i:term_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +typedef_test(Node, Timeout) -> + In1 = {nisse, [1, 2], olsson}, + In2 = get(port_test_port), + {Ret, Out1, Out2} = m_i:typedef_test({olsson, Node}, Timeout, In1, In2), + %% XXX Should check that Ret is an integer. + (Out1 == In1) and (Out2 == In2). +%%e + +%%b +inline_sequence_test(Node, Timeout) -> + In = #m_s{l = min_long(), sl = [max_long(), min_long()]}, + {Ret, Out} = m_i:inline_sequence_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +term_sequence_test(Node, Timeout) -> + In = lists:duplicate(17, {nisse, [1, 2], {kalle, olsson}}), + {Ret, Out} = m_i:term_sequence_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + +%%b +term_struct_test(Node, Timeout) -> + In = #m_et{e = {nisse, ["abcde"], {kalle, olsson}}, l = 4711}, + {Ret, Out} = m_i:term_struct_test({olsson, Node}, Timeout, In), + (Ret == In) and (Out == In). +%%e + + +%% Locals + +mk_array(Es) -> + list_to_tuple(Es). + +mk_array(N, E) -> + mk_array(lists:duplicate(N, E)). + +%% max_short() -> +%% power_of_two(15) - 1. +max_long() -> + power_of_two(31) - 1. +max_longlong() -> + power_of_two(63) - 1. +max_ushort() -> + power_of_two(16) - 1. +max_ulong() -> + power_of_two(32) - 1. +max_ulonglong() -> + power_of_two(64) - 1. + +%% min_short() -> +%% -power_of_two(15). +min_long() -> + -power_of_two(31). +%% min_longlong() -> +%% -power_of_two(63). +%% min_ushort() -> +%% 0. +%% min_ulong() -> +%% 0. +%% min_ulonglong() -> +%% 0. + +power_of_two(N) -> + round(math:pow(2, N)). + diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c b/lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c new file mode 100644 index 0000000000..c0401b2621 --- /dev/null +++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c @@ -0,0 +1,34 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-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% + * + */ +#include "ic.h" +#include "m_i.h" + +int my_prepare_request_decoding(CORBA_Environment *env) +{ + return oe_prepare_request_decoding(env); +} + +int my_prepare_reply_encoding(CORBA_Environment *env) +{ + return oe_prepare_reply_encoding(env); +} + + + diff --git a/lib/ic/test/ic.spec b/lib/ic/test/ic.spec new file mode 100644 index 0000000000..280c2aba47 --- /dev/null +++ b/lib/ic/test/ic.spec @@ -0,0 +1 @@ +{topcase, {dir, "../ic_test"}}. diff --git a/lib/ic/test/ic.spec.vxworks b/lib/ic/test/ic.spec.vxworks new file mode 100644 index 0000000000..b15260ab70 --- /dev/null +++ b/lib/ic/test/ic.spec.vxworks @@ -0,0 +1,2 @@ +{topcase, {dir, "../ic_test"}}. +{skip,{ic_pp_SUITE,"Uses gcc"}}. diff --git a/lib/ic/test/ic_SUITE.erl b/lib/ic/test/ic_SUITE.erl new file mode 100644 index 0000000000..6682c82f01 --- /dev/null +++ b/lib/ic/test/ic_SUITE.erl @@ -0,0 +1,973 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2010. 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% +%% +%% +%%%---------------------------------------------------------------------- +%%% Purpose : Test suite for the IDL compiler +%%%---------------------------------------------------------------------- + +-module(ic_SUITE). +-include("test_server.hrl"). + +-export([all/1]). + + +-include_lib("orber/src/orber_ifr.hrl"). +-include_lib("orber/src/ifr_objects.hrl"). +-include_lib("orber/include/ifr_types.hrl"). + + +%% The type cases +-export([type/1, type_norm/1]). + +%% The syntax case +-export([syntax/1]). +-export([syntax1/1, syntax2/1, syntax3/1, syntax4/1, syntax5/1, syntax6/1]). + +%% The constant cases +-export([const/1]). +-export([const_norm/1, const_bad_tk/1, const_bad_type/1]). +-export([const_bad_comb/1]). + +%% The union cases +-export([union/1]). +-export([union_norm/1, union_type/1, union_mult_err/1, union_case_mult/1]). +-export([union_default/1]). + +%% The enum cases +-export([enum/1]). +-export([enum_norm/1]). + +%% The struct cases +-export([struct/1]). +-export([struct_norm/1]). + +%% The oneway cases +-export([oneway/1]). +-export([oneway_norm/1, oneway_raises/1, oneway_out/1, oneway_void/1, oneway_followed/1]). + +%% The attributes cases +-export([attr/1]). +-export([attr_norm/1]). + +%% The raises registration case +-export([raises_reg/1]). + + +%% The typeID case + +%% general stuff +-export([general/1]). +-export([typeid/1, undef_id/1, dir/1, nasty_names/1, coss/1, mult_ids/1]). +-export([forward/1, include/1, app_test/1]). + +%% inheritance stuff +-export([inherit/1, inherit_norm/1, inherit_warn/1, inherit_err/1]). + +%% Standard options to the ic compiler, NOTE unholy use of OutDir + +-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])). + + +%% Top of cases + +all(doc) -> + []; +all(suite) -> [app_test, const, union, enum, attr, type, struct, general, inherit, + oneway, syntax, raises_reg]. + + +app_test(doc) -> []; +app_test(suite) -> []; +app_test(_Config) -> + ok=test_server:app_test(ic), + ok. + +%%--------------------------------------------------------------------- +%% +%% Test of constant expressions. +%% + +const(suite) -> [const_norm, const_bad_tk, const_bad_type, const_bad_comb]. + + +const_norm(doc) -> + ["Checks normal constant types and values"]; +const_norm(suite) -> []; +const_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(const_norm), + File = filename:join(DataDir, c_norm), + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, const_norm_files()), + ok. + +const_bad_tk(doc) -> + ["Checks when the constant value doesn't match the declared type"]; +const_bad_tk(suite) -> []; +const_bad_tk(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, c_err1), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(18, bad_tk_match, R), + ok. + +const_bad_type(doc) -> + ["Checks operands of ops are of correct type"]; +const_bad_type(suite) -> []; +const_bad_type(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, c_err2), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(4, bad_type, R), + ok. + +const_bad_comb(doc) -> + ["Checks operands of ops are of conflicting types"]; +const_bad_comb(suite) -> []; +const_bad_comb(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, c_err3), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(3, bad_type_combination, R), + ok. + + + +union(suite) -> [union_norm, union_type, union_mult_err, union_case_mult, + union_default]; +union(doc) -> + ["Checks allowed usage of the union as well as the illegal cases"]. + + +union_norm(doc) -> + ["Checks that normal union declarations works."]; +union_norm(suite) -> []; +union_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(union_norm), + File = filename:join(DataDir, u_norm), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, union_norm_files()), + ok. + + +%% Checks OTP-2007 +union_default(doc) -> + ["Checks that default cases are correct in type code."]; +union_default(suite) -> []; +union_default(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(union_default), + File = filename:join(DataDir, u_default), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, union_default_files(), [load]), + TkList = i1:oe_get_interface(), + check_label("op0", 0, TkList), + check_label("op1", 1, TkList), + check_label("op2", 2, TkList), + check_label("op3", -1, TkList), + ok. + +check_label(Id, N, List) -> + case lists:keysearch(Id, 1, List) of + {value, {_, {{_, _, _, _, D, L}, _, _}}} -> + if D /= N -> + test_server:fail({bad_default_num, D, N}); + D /= -1 -> + case lists:nth(D+1, L) of + T when element(1, T) == default -> + ok; + _Que -> + test_server:fail({bad_default_list, D, L}) + end; + true -> + %% D = N = -1, just check that there is no default label + case lists:keysearch(default, 1, L) of + false -> + ok; + _ -> + test_server:fail({bad_default_label, D, L}) + end + end; + _ -> + test_server:fail({'no_such_op!', Id, List}) + end. + +union_type(doc) -> + ["Checks that errors are detected. Check that mismatch between case ", + "value and declared discriminator type is detected."]; +union_type(suite) -> []; +union_type(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, u_type), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(28, bad_case_type, R), + ok. + + +union_mult_err(doc) -> + ["Check that multiple declared declarators are caught.", + "Also check that if the discriminator is an enum, then the enum name", + "must not be used as a declarator in the union switch (declarator", + "as opposed to label)."]; +union_mult_err(suite) -> []; +union_mult_err(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, u_mult), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(8, multiply_defined, R), + ok. + +%% Checking mult cases. Now check that other errors are found in the +%% correct order XXXX + + +union_case_mult(doc) -> + ["Check that multiply defined case labels are found and reported."]; +union_case_mult(suite) -> []; +union_case_mult(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, u_case_mult), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(7, multiple_cases, R), + ok. + + +%%-------------------------------------------------------------------- +%% +%% Enum cases +%% + +enum(suite) -> [enum_norm]; +enum(doc) -> + ["Checks allowed usage of the enum as well as the illegal cases"]. + +enum_norm(doc) -> + ["Checks that normal enum declarations works."]; +enum_norm(suite) -> []; +enum_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(enum_norm), + File = filename:join(DataDir, enum), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, enum_norm_files()), + ok. + + +%%-------------------------------------------------------------------- +%% +%% Struct cases +%% + +struct(suite) -> [struct_norm]; +struct(doc) -> + ["Checks allowed usage of the struct as well as the illegal cases"]. + +struct_norm(doc) -> + ["Checks that normal struct declarations works."]; +struct_norm(suite) -> []; +struct_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(struct_norm), + File = filename:join(DataDir, struct), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, struct_norm_files()), + Mod = ridiculous_name_to_avoid_clash_svenne, + TestFile = filename:join(OutDir, Mod), + ?line ok = gen_struct_file(TestFile, Mod), + ?line ok = compile(OutDir, [Mod], [load]), +%% ?line {ok, Mod, []} = compile:file(TestFile, +%% [{i, OutDir}, {outdir, OutDir}, +%% return, load]), + ?line ok = Mod:test(), + ok. + + +%%-------------------------------------------------------------------- +%% +%% General cases +%% + +general(doc) -> + ["Check general things like directories and type identifier", + "detection."]; +general(suite) -> [typeid, undef_id, mult_ids, forward, include, nasty_names]. +%% coss (add sometimes, takes 440 seconds!) + +typeid(doc) -> + ["Check that type id's are generated correctly"]; +typeid(suite) -> []; +typeid(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(typeid), + File = filename:join(DataDir, typeid), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, typeid_files(), [load]), + ?line "IDL:I1:1.0" = 'I1':'typeID'(), + ?line "IDL:M1/I1:1.0" = 'M1_I1':'typeID'(), + ?line "IDL:M2/M1/I1:1.0" = 'M2_M1_I1':'typeID'(), + ?line "IDL:M3/M2/M1/I1:1.0" = 'M3_M2_M1_I1':'typeID'(), + ok. + + +%%% This test case is removed because there's no way to test this from +%%% an automated test suite. +dir(doc) -> + ["Check that relative directories work, absolute is used in", + "all other cases in the suite."]; +%%% xxxxxx +dir(suite) -> []; +dir(Config) when is_list(Config) -> +ok; +dir(Config) -> + DataDir = ?config(data_dir, Config), + + %% Needs a unique directory (any better way?) + OutDir = mk_unique("oe_the_dir"), + + %% More unique names + File = filename:join(DataDir, mk_unique("oe_the_file")), + Const = mk_unique("oe_the_constant"), + Mod = list_to_atom(File), + Func = list_to_atom(Const), + + %% Generate a unique IDL file with a single constant + gen_file(File, Const), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line ok = compile(OutDir, [load]), + ?line 19955 = Mod:Func(), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, [load]), + ?line 19955 = Mod:Func(), + + ?line ok = ic:gen(File), +%%% ?line ok = compile(".", [load]), + ok. + +undef_id(doc) -> + ["Check that various undefied id's are detected correctly"]; +undef_id(suite) -> []; +undef_id(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, undef_id), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(16, tk_not_found, R), + ok. + +mult_ids(doc) -> + ["Check that multiply defined ids are caught."]; +mult_ids(suite) -> []; +mult_ids(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, mult_ids), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(22, multiply_defined, R), + ok. + + +nasty_names(doc) -> + ["Check that various nasty names can be generated.", + "Try to provoke name clashes and name conflicts with", + "Erlang and IDL"]; +nasty_names(suite) -> []; +nasty_names(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(nasty_names), + File = filename:join(DataDir, nasty), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, nasty_names_files(), [load]), + ok. + +coss(doc) -> + ["Check that the Coss standard specification works."]; +coss(suite) -> []; +coss(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(coss), + File = filename:join(DataDir, 'Coss'), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, [_W1]} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, []), + ok. + +forward(doc) -> + ["Check that forward declaratios work."]; +forward(suite) -> []; +forward(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(forward), + File = filename:join(DataDir, forward), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, forward_files(), [load]), + ok. + +include(doc) -> + ["Check that various undefied id's are detected correctly"]; +include(suite) -> []; +include(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, include), + ?line error = ic:gen(File, stdopts(OutDir)++[{preproc_flags,"-I" ++ DataDir}]), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[{preproc_flags,"-I" ++ DataDir},silent2]), + case lists:map(fun(D) -> + filename:rootname(filename:basename(element(3, D))) + end, + lists:sort(R)) of + ["include", + "include2", + "include2", + "include3"] -> + ok; + RRR -> + test_server:fail({bad_include_file, RRR}) + end, + ok. + + + + +%%-------------------------------------------------------------------- +%% +%% Inhertit cases +%% + +inherit(doc) -> + ["Check the inheritance mechanism."]; +inherit(suite) -> [inherit_norm, inherit_warn, inherit_err]. + +inherit_norm(doc) -> + ["Checks that normal inheritance works."]; +inherit_norm(suite) -> []; +inherit_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(inherit_norm), + File = filename:join(DataDir, inherit), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, _Ws} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, inherit_norm_files(), [load]), + + %% Now check constant values: + ?line 9 = m1_I1:c1(), + + ?line 9 = m1_I2:c1(), + ?line 14 = m1_I2:c2(), + ?line 27 = m1_I2:c3(), + + ?line 50 = m1_I3:c1(), + ?line 14 = m1_I3:c2(), + ?line 27 = m1_I3:c3(), + ?line 91 = m1_I3:c4(), + ?line 100 = m1_I3:c5(), + ok. + +inherit_warn(doc) -> + ["Check that various inheritance shadowing is detected"]; +inherit_warn(suite) -> []; +inherit_warn(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, inherit_warn), + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(7, inherit_name_shadow, R), + ok. + +inherit_err(doc) -> + ["Check that various inheritance errors is detected"]; +inherit_err(suite) -> []; +inherit_err(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, inherit_err), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, _Ws, R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(21, inherit_name_collision, R), + ok. + + +oneway(doc) -> + ["Check the oneway operation mechanism."]; +oneway(suite) -> [oneway_norm, oneway_out, oneway_raises, oneway_void, oneway_followed ]. + +oneway_norm(doc) -> + ["Checks that normal oneway operations works."]; +oneway_norm(suite) -> []; +oneway_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(oneway_norm), + File = filename:join(DataDir, one), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line ok = compile(OutDir, oneway_norm_files(), [load]), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, oneway_norm_files(), [load]), + ok. + +oneway_void(doc) -> + ["Check that non-void oneways are detected."]; +oneway_void(suite) -> []; +oneway_void(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, one_void), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(2, bad_oneway_type, R), + ok. + +oneway_raises(doc) -> + ["Check that oneways cannot raise exceptions."]; +oneway_raises(suite) -> []; +oneway_raises(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, one_raises), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(3, oneway_raises, R), + ok. + +oneway_out(doc) -> + ["Check that illegal out parameters are detected"]; +oneway_out(suite) -> []; +oneway_out(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, one_out), + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(2, oneway_outparams, R), + ok. + +oneway_followed(doc) -> + ["Checks that normal oneways, followed by other operations."]; +oneway_followed(suite) -> []; +oneway_followed(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(oneway_followed), + File = filename:join(DataDir, one_followed), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line ok = compile(OutDir, oneway_followed_files(), [load]), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, oneway_followed_files(), [load]), + ok. + +attr(doc) -> + ["Check that attributes work."]; +attr(suite) -> [attr_norm]. + +attr_norm(doc) -> + ["Checks that normal attr operations works."]; +attr_norm(suite) -> []; +attr_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(attr_norm), + File = filename:join(DataDir, attr), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line ok = compile(OutDir, attr_norm_files(), [load]), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, attr_norm_files(), [load]), + ok. + +type(doc) -> + ["Check that typeibutes work."]; +type(suite) -> [type_norm]. + +type_norm(doc) -> + ["Checks all types are handled."]; +type_norm(suite) -> []; +type_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(type_norm), + File = filename:join(DataDir, type), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line ok = compile(OutDir, type_norm_files(), [load]), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, type_norm_files(), [load]), + ok. + + +syntax(doc) -> + ["Check that syntax errors are discovered."]; +syntax(suite) -> [syntax1, syntax2, syntax3, syntax4, syntax5, syntax6]. + +syntax1(suite) -> []; +syntax1(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, syntax1), + + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(1, parse_error, R), + ok. + +syntax2(suite) -> []; +syntax2(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, syntax2), + + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(1, parse_error, R), + ok. + +syntax3(suite) -> []; +syntax3(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, syntax3), + + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(1, parse_error, R), + ok. + +syntax4(suite) -> []; +syntax4(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, syntax4), + + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(1, parse_error, R), + ok. + +syntax5(suite) -> []; +syntax5(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, syntax5), + + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(1, parse_error, R), + ok. + +syntax6(suite) -> []; +syntax6(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, syntax6), + + ?line error = ic:gen(File, stdopts(OutDir)), + ?line {error, [], R} = + ic:gen(File, stdopts(OutDir)++[silent2]), + check_errors(1, parse_error, R), + ok. + + + +%%-------------------------------------------------------------------- +%% +%% Checks RAISES to be registered under IFR operation registration +%% ( OTP-2102 ) +%% + +raises_reg(doc) -> + ["Check that exceptions are really registered to operations."]; +raises_reg(suite) -> []; +raises_reg(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(raises_reg_check), + File = filename:join(DataDir, raises_reg), + + ?line ok = ic:gen(File, stdopts(OutDir)), + ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]), + ?line ok = compile(OutDir, raises_reg_files(), [load]), + + set_up('oe_raises_reg'), + + io:format("~n##### Starting the test case #####~n"), + io:format("Checking for existance of exception : ~s~n",["IDL:Raises_RegModule/Exception_1:1.0"]), + raises_register_check("IDL:Raises_RegModule/R_R/op:1.0","IDL:Raises_RegModule/Exception_1:1.0"), + + io:format("Checking for existance of exception : ~s~n",["IDL:Raises_RegModule/Exception_2:1.0"]), + raises_register_check("IDL:Raises_RegModule/R_R/op:1.0","IDL:Raises_RegModule/Exception_2:1.0"), + + io:format("Checking for existance of exception : ~s~n",["IDL:Raises_RegModule/XXXXXXXX:1.0"]), + raises_register_check("IDL:Raises_RegModule/R_R/op:1.0","IDL:RaisesModule/XXXXXXXX:1.0"), + + set_down('oe_raises_reg'), + + ok. + +set_up(Register) -> + io:format("Setting up.....~n"), + mnesia:stop(), + mnesia:delete_schema([node()]), + mnesia:create_schema([node()]), + mnesia:start(), + orber:install([node()]), + orber:start(), + io:format("Running OE_register()~n"), + Register:'oe_register'(). + +set_down(Register) -> + io:format("Running OE_unregister()~n"), + Register:'oe_unregister'(), + io:format("Setting down.....~n"), + orber:stop(), + orber:uninstall(), + mnesia:stop(), + mnesia:delete_schema([node()]). + + +raises_register_check(OpId,ExcId) -> + case is_valid_exc(OpId,ExcId) of + true -> + ok; % Because right exception where found, + % the test succeeds for normal cases. + false -> + ok; % Because the exception tested, is not + % registered for that operation. + FailReason -> + test_server:fail({FailReason, OpId, ExcId}) + % Because the test descovered errors in a previous + % stage, or no exceptions where registered att all. + % ( This testcase assumes that operations to be + % checked allways raise excption(s) ) + end. + +is_valid_exc(OpId,ExcId) -> + OE_IFR = orber_ifr:find_repository(), + OpDef = orber_ifr:'Repository_lookup_id'(OE_IFR,OpId), + ExcDefList = orber_ifr:get_exceptions(OpDef), + case ExcDefList of + [] -> + no_exceptions_registered; + _ -> + ExcDef=orber_ifr:lookup_id(OE_IFR,ExcId), + lists:member(ExcDef,ExcDefList) + end. + +%%-------------------------------------------------------------------- +%% +%% Utilities + + +stdopts(OutDir) -> + [{outdir, OutDir},{maxerrs, infinity}]. + +mk_unique(Prefix) -> + {A,B,C} = now(), + Prefix++"_"++integer_to_list(A)++"_"++integer_to_list(B)++"_"++ + integer_to_list(C). + +gen_file(File, Const) -> + {ok, Fd} = file:open(File++".idl", [write]), + io:format(Fd, "interface ~s {~n", [File]), + io:format(Fd, " const long ~s = 19955;~n", [Const]), + io:format(Fd, "};~n", []), + file:close(Fd). + + +%% Compile all files in Dir. Used for checking that valid Erlang has +%% been generated. +%%compile(Dir) -> +%% compile(Dir, []). +%%compile(Dir, Opts) -> +%% {ok, Cwd} = file:get_cwd(), +%% catch do_compile(Dir, Opts), +%% file:set_cwd(Cwd). + +%%do_compile(Dir, Opts) -> +%% ok = file:set_cwd(Dir), +%% up_to_date = ts_make_erl:all(Opts), +%% ok. + +compile(Dir, Files) -> + compile(Dir, Files, []). + +compile(Dir, Files, Opts) -> + {ok, Cwd} = file:get_cwd(), + file:set_cwd(Dir), + io:format("Changing to ~p~n", [Dir]), + case catch do_compile(Files, Opts) of + ok -> + file:set_cwd(Cwd); + Err -> + file:set_cwd(Cwd), + test_server:fail(Err) + end. + +do_compile([], _Opts) -> ok; +do_compile([F | Fs], Opts) -> + io:format("Compiling ~p", [F]), + case compile:file(F, Opts) of + ok -> + io:format(" ok~n", []), + do_load(F, Opts), + do_compile(Fs, Opts); + {ok, _} -> + io:format(" ok~n", []), + do_load(F, Opts), + do_compile(Fs, Opts); + {ok, _, _} -> + io:format(" ok~n", []), + do_load(F, Opts), + do_compile(Fs, Opts); + Err -> + io:format(" error: ~p~n", [Err]), + Err + end. + +do_load(File, Opts) -> + case lists:member(load, Opts) of + true -> + io:format("Loading file ~p", [File]), + code:purge(File), + R = code:load_abs(File), + io:format("Loaded: ~p", [R]); + false -> + ok + end. + + +%% Check that ErrList consists of exactly Num errors of type ErrType +check_errors(Num, ErrType, ErrList) -> + Num = length(ErrList), + lists:foreach(fun(T) -> + case catch element(1, element(4, T)) of + ErrType -> ok; + Else -> + test_server:fail({bad, ErrType, Else}) + end end, ErrList). + +to_list(X) when is_atom(X) -> atom_to_list(X); +to_list(X) -> X. + + +%% File must be an atom +gen_struct_file(File, Mod) -> + + ?line {ok, Fd} = file:open(to_list(File)++".erl", [write]), + io:format(Fd, "~n", []), + io:format(Fd, "-module(~p).~n", [Mod]), + io:format(Fd, "-export([test/0]).~n", []), + io:format(Fd, "-include(\"oe_struct.hrl\").~n", []), + io:format(Fd, "test() ->~n", []), + io:format(Fd, " A = #'S1'{a=99, b=$a, s=\"123456789\"},~n", []), + io:format(Fd, " B = #'S2'{a=9, b=#'S2_S3'{a=1, b=9, b1=5, c=$2},~n", []), + io:format(Fd, " c=[#'S1'{a=1}, #'S1'{a=2}],~n", []), + io:format(Fd, +" c2=[#'S1'{a=2}, #'S1'{a=3}, #'S1'{a=2}, #'S1'{a=3}]},~n", []), + io:format(Fd, " C = #'S2_S3'{a=11, b=999, b1=19},~n", []), + io:format(Fd, " D = #s4{a=7},~n", []), + io:format(Fd, " E = {1, #'U1_S5'{a=3}},~n", []), + io:format(Fd, " F = {2, {$b, #'U1_U2_s6'{a=6, b=false}}},~n", []), + io:format(Fd, " ok.~n", []), + file:close(Fd). + + +union_norm_files() -> ['oe_u_norm']. +union_default_files() -> ['oe_u_default', i1]. + +typeid_files() -> ['oe_typeid', 'M3_M2_M1_I1', 'M2_M1_I1', 'M1_I1', 'I1']. + +struct_norm_files() -> ['oe_struct']. +oneway_norm_files() -> ['oe_one', 'I1']. +oneway_followed_files() -> ['oe_one_followed', 'I1']. +nasty_names_files() -> ['oe_nasty', 'I2', 'I1']. + +inherit_norm_files() -> [m1_I3, m1_I2, m1_I1, 'oe_inherit', 'I4', 'I3', + 'I2', 'I1']. + +forward_files() -> [i1, 'oe_forward']. +enum_norm_files() -> ['oe_enum']. +const_norm_files() -> ['oe_c_norm']. +attr_norm_files() -> ['oe_attr', 'I1', 'I2']. +type_norm_files() -> ['oe_type']. + +raises_reg_files() -> ['oe_raises_reg']. + + + + + + + + + + + + + + + + diff --git a/lib/ic/test/ic_SUITE_data/Corba.idl b/lib/ic/test/ic_SUITE_data/Corba.idl new file mode 100644 index 0000000000..6b81132500 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/Corba.idl @@ -0,0 +1,1013 @@ +// This file contains OMG IDL from CORBA V2.0, July 1995. +// Includes IDL for CORBA Core +// (Interface Repository, ORB Interface, Basic Object Adapter Interface) +// and CORBA Interoperability (IOP, GIOP, IIOP, and DCE CIOP modules) + +// Complete OMG IDL for Interface Repository starts on pg 6-42, CORBA V2.0 July 1995 +// IRObject interface described on pg 6-9 CORBA V2.0, July 1995 +// Contained interface: pg 6-11 CORBA V2, 7-95 +// Container interface: pg 6-12 thru 6-15 CORBA V2, 7-95 +// IDLType interface: pg 6-15 CORBA V2, 7-95 +// Repository interface: pg 6-16 CORBA V2, 7-95 +// ModuleDef interface: pg 6-17 CORBA V2, 7-95 +// ConstantDef interface: pg 6-18 CORBA V2, 7-95 +// TypeDef interface: pg 6-19 CORBA V2, 7-95 +// StructDef interface: pg 6-19 CORBA V2, 7-95 +// UnionDef interface: pg 6-19 CORBA V2, 7-95 +// EnumDef interface: pg 6-20 CORBA V2, 7-95 +// AliasDef interface: pg 6-21 CORBA V2, 7-95 +// PrimitiveDef interface: pg 6-21 CORBA V2, 7-95 +// StringDef interface: pg 6-22 CORBA V2, 7-95 +// SequenceDef interface: pg 6-22 CORBA V2, 7-95 +// ArrayDef interface: pg 6-23 CORBA V2, 7-95 +// ExceptionDef interface: pg 6-24 CORBA V2, 7-95 +// AttributeDef interface: pg 6-25 CORBA V2, 7-95 +// OperationDef interface: pg 6-26 CORBA V2, 7-95 +// InterfaceDef interface: pg 6-28 CORBA V2, 7-95 +// TypeCode interface (PIDL): pg 6-34 CORBA V2, 7-95 +// ORB interface: pg 6-40 CORBA V2, 7-95 + +#ifndef __CORBA_IDL +#define __CORBA_IDL + +// #pragma prefix "omg.org" +module CORBA { + + interface TypeCode; + typedef string Identifier; + typedef string ScopedName; + typedef string RepositoryId; + + /* + * start of section added by Christian Blum + */ + + typedef enum new_type {NO,USER,SYSTEM_EXCEPTION} exception_type; + + /** + * no definition for this type + */ + interface ImplementationDef + { + }; + + /** + * no definition for this type + */ + //interface Principal + struct Principal + { + string str; + }; + + /** + * no definition for this type + */ + interface Environment + { + + }; + + typedef unsigned long Flags; + typedef unsigned long Status; + + struct NamedValue // PIDL + { + Identifier name; // argument name + any argument; // argument + long len; // length/count of argument value + Flags arg_modes; // argument mode flags + + }; + + typedef sequence<NamedValue> NVList; /* C */ + + interface Request // PIDL + { + + Status add_arg ( + in Identifier name, // argument name + in TypeCode arg_type, // argument datatype + // in void * value, // argument value to be added + in any value_LOOK_AT_SOURCE, // changed by blum + in long len, // length/count of argument value + in Flags arg_flags // argument flags + ); + + Status invoke ( + in Flags invoke_flags // invocation flags + ); + + Status delete (); + Status send ( + in Flags invoke_flags // invocation flags + ); + + Status get_response ( + in Flags response_flags // response flags + ); + + }; + + + interface Context // PIDL + { + + Status set_one_value ( + in Identifier prop_name, // property name to add + in string value // property value to add + ); + + Status set_values ( + in NVList values // property values to be changed + ); + + Status get_values ( + in Identifier start_scope, // search scope + in Flags op_flags, // operation flags + in Identifier prop_name, // name of property(s) to retrieve + out NVList values // requested property(s) + ); + + Status delete_values ( + in Identifier prop_name // name of property(s) to delete + ); + + Status create_child ( + in Identifier ctx_name, // name of context object + out Context child_ctx // newly created context object + ); + + Status delete ( + in Flags del_flags // flags controlling deletion + ); + + }; + + /* + * end of section added by Christian Blum + */ + + + enum DefinitionKind { + dk_none, dk_all, + dk_Attribute, dk_Constant, dk_Exception, dk_Interface, + dk_Module, dk_Operation, dk_Typedef, + dk_Alias, dk_Struct, dk_Union, dk_Enum, + dk_Primitive, dk_String, dk_Sequence, dk_Array, + dk_Repository + }; + + + interface IRObject { + // read interface + readonly attribute DefinitionKind def_kind; + + // write interface + void destroy (); + }; + + + + typedef string VersionSpec; + + interface Contained; + interface Repository; + interface Container; + + interface Contained : IRObject { + // read/write interface + + attribute RepositoryId id; + attribute Identifier name; + attribute VersionSpec version; + + // read interface + + readonly attribute Container defined_in; + readonly attribute ScopedName absolute_name; + readonly attribute Repository containing_repository; + + struct Description { + DefinitionKind kind; + any value; + }; + + Description describe (); + + // write interface + + void move ( + in Container new_container, + in Identifier new_name, + in VersionSpec new_version + ); + }; + + + interface ModuleDef; + interface ConstantDef; + interface IDLType; + interface StructDef; + interface UnionDef; + interface EnumDef; + interface AliasDef; + interface InterfaceDef; + typedef sequence <InterfaceDef> InterfaceDefSeq; + + typedef sequence <Contained> ContainedSeq; + + struct StructMember { + Identifier name; + TypeCode type; + IDLType type_def; + }; + typedef sequence <StructMember> StructMemberSeq; + + struct UnionMember { + Identifier name; + any label; + TypeCode type; + IDLType type_def; + }; + typedef sequence <UnionMember> UnionMemberSeq; + + typedef sequence <Identifier> EnumMemberSeq; + + interface Container : IRObject { + // read interface + + Contained lookup ( in ScopedName search_name); + + ContainedSeq contents ( + in DefinitionKind limit_type, + in boolean exclude_inherited + ); + + ContainedSeq lookup_name ( + in Identifier search_name, + in long levels_to_search, + in DefinitionKind limit_type, + in boolean exclude_inherited + ); + + struct Description { + Contained contained_object; + DefinitionKind kind; + any value; + }; + + typedef sequence<Description> DescriptionSeq; + + DescriptionSeq describe_contents ( + in DefinitionKind limit_type, + in boolean exclude_inherited, + in long max_returned_objs + ); + + // write interface + + ModuleDef create_module ( + in RepositoryId id, + in Identifier name, + in VersionSpec version + ); + + ConstantDef create_constant ( + in RepositoryId id, + in Identifier name, + in VersionSpec version, + in IDLType type, + in any value + ); + + StructDef create_struct ( + in RepositoryId id, + in Identifier name, + in VersionSpec version, + in StructMemberSeq members + ); + + UnionDef create_union ( + in RepositoryId id, + in Identifier name, + in VersionSpec version, + in IDLType discriminator_type, + in UnionMemberSeq members + ); + + EnumDef create_enum ( + in RepositoryId id, + in Identifier name, + in VersionSpec version, + in EnumMemberSeq members + ); + + AliasDef create_alias ( + in RepositoryId id, + in Identifier name, + in VersionSpec version, + in IDLType original_type + ); + + InterfaceDef create_interface ( + in RepositoryId id, + in Identifier name, + in VersionSpec version, + in InterfaceDefSeq base_interfaces + ); + }; + + + + interface IDLType : IRObject { + readonly attribute TypeCode type; + }; + + + + interface PrimitiveDef; + interface StringDef; + interface SequenceDef; + interface ArrayDef; + + enum PrimitiveKind { + pk_null, pk_void, pk_short, pk_long, pk_ushort, pk_ulong, + pk_float, pk_double, pk_boolean, pk_char, pk_octet, + pk_any, pk_TypeCode, pk_Principal, pk_string, pk_objref + }; + + interface Repository : Container { + // read interface + + Contained lookup_id (in RepositoryId search_id); + + PrimitiveDef get_primitive (in PrimitiveKind kind); + + // write interface + + StringDef create_string (in unsigned long bound); + + SequenceDef create_sequence ( + in unsigned long bound, + in IDLType element_type + ); + + ArrayDef create_array ( + in unsigned long length, + in IDLType element_type + ); + }; + + + interface ModuleDef : Container, Contained { + }; + + struct ModuleDescription { + Identifier name; + RepositoryId id; + RepositoryId defined_in; + VersionSpec version; + }; + + + interface ConstantDef : Contained { + readonly attribute TypeCode type; + attribute IDLType type_def; + attribute any value; + }; + + struct ConstantDescription { + Identifier name; + RepositoryId id; + RepositoryId defined_in; + VersionSpec version; + TypeCode type; + any value; + }; + + + interface TypedefDef : Contained, IDLType { + }; + + struct TypeDescription { + Identifier name; + RepositoryId id; + RepositoryId defined_in; + VersionSpec version; + TypeCode type; + }; + + + interface StructDef : TypedefDef { + attribute StructMemberSeq members; + }; + + + interface UnionDef : TypedefDef { + readonly attribute TypeCode discriminator_type; + attribute IDLType discriminator_type_def; + attribute UnionMemberSeq members; + }; + + + interface EnumDef : TypedefDef { + attribute EnumMemberSeq members; + }; + + + interface AliasDef : TypedefDef { + attribute IDLType original_type_def; + }; + + + interface PrimitiveDef: IDLType { + readonly attribute PrimitiveKind kind; + }; + + + interface StringDef : IDLType { + attribute unsigned long bound; + }; + + + interface SequenceDef : IDLType { + attribute unsigned long bound; + readonly attribute TypeCode element_type; + attribute IDLType element_type_def; + }; + + interface ArrayDef : IDLType { + attribute unsigned long length; + readonly attribute TypeCode element_type; + attribute IDLType element_type_def; + }; + + + interface ExceptionDef : Contained { + readonly attribute TypeCode type; + attribute StructMemberSeq members; + }; + struct ExceptionDescription { + Identifier name; + RepositoryId id; + RepositoryId defined_in; + VersionSpec version; + TypeCode type; + }; + + + + enum AttributeMode {ATTR_NORMAL, ATTR_READONLY}; + + interface AttributeDef : Contained { + readonly attribute TypeCode type; + attribute IDLType type_def; + attribute AttributeMode mode; + }; + + struct AttributeDescription { + Identifier name; + RepositoryId id; + RepositoryId defined_in; + VersionSpec version; + TypeCode type; + AttributeMode mode; + }; + + + + enum OperationMode {OP_NORMAL, OP_ONEWAY}; + + enum ParameterMode {PARAM_IN, PARAM_OUT, PARAM_INOUT}; + struct ParameterDescription { + Identifier name; + TypeCode type; + IDLType type_def; + ParameterMode mode; + }; + typedef sequence <ParameterDescription> ParDescriptionSeq; + + typedef Identifier ContextIdentifier; + typedef sequence <ContextIdentifier> ContextIdSeq; + + typedef sequence <ExceptionDef> ExceptionDefSeq; + typedef sequence <ExceptionDescription> ExcDescriptionSeq; + + interface OperationDef : Contained { + readonly attribute TypeCode result; + attribute IDLType result_def; + attribute ParDescriptionSeq params; + attribute OperationMode mode; + attribute ContextIdSeq contexts; + attribute ExceptionDefSeq exceptions; + }; + + struct OperationDescription { + Identifier name; + RepositoryId id; + RepositoryId defined_in; + VersionSpec version; + TypeCode result; + OperationMode mode; + ContextIdSeq contexts; + ParDescriptionSeq parameters; + ExcDescriptionSeq exceptions; + }; + + + + typedef sequence <RepositoryId> RepositoryIdSeq; + typedef sequence <OperationDescription> OpDescriptionSeq; + typedef sequence <AttributeDescription> AttrDescriptionSeq; + + interface InterfaceDef : Container, Contained, IDLType { + // read/write interface + + attribute InterfaceDefSeq base_interfaces; + + // read interface + + boolean is_a (in RepositoryId interface_id); + + struct FullInterfaceDescription { + Identifier name; + RepositoryId id; + RepositoryId defined_in; + VersionSpec version; + OpDescriptionSeq operations; + AttrDescriptionSeq attributes; + RepositoryIdSeq base_interfaces; + TypeCode type; + }; + + FullInterfaceDescription describe_interface(); + + // write interface + + AttributeDef create_attribute ( + in RepositoryId id, + in Identifier name, + in VersionSpec version, + in IDLType type, + in AttributeMode mode + ); + + OperationDef create_operation ( + in RepositoryId id, + in Identifier name, + in VersionSpec version, + in IDLType result, + in OperationMode mode, + in ParDescriptionSeq params, + in ExceptionDefSeq exceptions, + in ContextIdSeq contexts + ); + }; + + struct InterfaceDescription { + Identifier name; + RepositoryId id; + RepositoryId defined_in; + VersionSpec version; + RepositoryIdSeq base_interfaces; + }; + + + + enum TCKind { + tk_null, tk_void, + tk_short, tk_long, tk_ushort, tk_ulong, + tk_float, tk_double, tk_boolean, tk_char, + tk_octet, tk_any, tk_TypeCode, tk_Principal, tk_objref, + tk_struct, tk_union, tk_enum, tk_string, + tk_sequence, tk_array, tk_alias, tk_except + }; + + interface TypeCode { // PIDL + exception Bounds {}; + exception BadKind {}; + + // for all TypeCode kinds + boolean equal (in TypeCode tc); + TCKind kind (); + + // for tk_objref, tk_struct, tk_union, tk_enum, tk_alias, and tk_except + RepositoryId id () raises (BadKind); + + // for tk_objref, tk_struct, tk_union, tk_enum, tk_alias, and tk_except + Identifier name () raises (BadKind); + + // for tk_struct, tk_union, tk_enum, and tk_except + unsigned long member_count () raises (BadKind); + Identifier member_name (in unsigned long index) raises (BadKind, Bounds); + + // for tk_struct, tk_union, and tk_except + TypeCode member_type (in unsigned long index) raises (BadKind, Bounds); + + // for tk_union + any member_label (in unsigned long index) raises (BadKind, Bounds); + TypeCode discriminator_type () raises (BadKind); + long default_index () raises (BadKind); + + // for tk_string, tk_sequence, and tk_array + unsigned long length () raises (BadKind); + + // for tk_sequence, tk_array, and tk_alias + TypeCode content_type () raises (BadKind); + + // deprecated interface + long param_count (); + any parameter (in long index) raises (Bounds); + }; + + + /* + * following line added by Christian Blum + */ + interface BOA; + + interface ORB { + // other operations ... + + TypeCode create_struct_tc ( + in RepositoryId id, + in Identifier name, + in StructMemberSeq members + ); + + TypeCode create_union_tc ( + in RepositoryId id, + in Identifier name, + in TypeCode discriminator_type, + in UnionMemberSeq members + ); + + TypeCode create_enum_tc ( + in RepositoryId id, + in Identifier name, + in EnumMemberSeq members + ); + + TypeCode create_alias_tc ( + in RepositoryId id, + in Identifier name, + in TypeCode original_type + ); + + TypeCode create_exception_tc ( + in RepositoryId id, + in Identifier name, + in StructMemberSeq members + ); + + TypeCode create_interface_tc ( + in RepositoryId id, + in Identifier name + ); + + TypeCode create_string_tc ( + in unsigned long bound + ); + + TypeCode create_sequence_tc ( + in unsigned long bound, + in TypeCode element_type + ); + + TypeCode create_recursive_sequence_tc ( + in unsigned long bound, + in unsigned long offset + ); + + TypeCode create_array_tc ( + in unsigned long length, + in TypeCode element_type + ); + + /* + * following line commented out by Christian Blum + */ + // }; + + // The ORB interface (PIDL) is described in Chapter 7, CORBA V2.0 July 1995 + // Object interface (object reference operations): pg 7-3 CORBA V2, 7-95 + // ORB initialization: pg 7-7 CORBA V2, 7-95 + // Object Adapter and Basic Object Adapter initialization: pg 7-8 CORBA V2 7-95 + // Getting initial references: pg 7-10 CORBA V2 7-95 + //PIDL + + /* + * following line commented out by Christian Blum + */ + //interface ORB { + + + string object_to_string (in Object obj); + Object string_to_object (in string str); + + Status create_list ( + in long count, + out NVList new_list + ); + Status create_operation_list ( + in OperationDef oper, + out NVList new_list + ); + Status get_default_context (out Context ctx); + + // Initializing the ORB + typedef string ORBid; + typedef sequence <string> arg_list; + ORB ORB_init (inout arg_list argv, in ORBid orb_identifier); + + // Initializing an object adapter and the Basic Object Adapter + typedef string OAid; + + // Template for OA initialization operations + // <OA> <OA>_init (inout arg_list argv, + // in OAid oa_identifier); + + + + BOA BOA_init (inout arg_list argv, + in OAid boa_identifier); + + + + // Getting initial object references + typedef string ObjectId; + typedef sequence <ObjectId> ObjectIdList; + + exception InvalidName {}; + + ObjectIdList list_initial_services (); + + Object resolve_initial_references (in ObjectId identifier) + raises (InvalidName); + }; + + // had to be changed..., Gerald Brose 1996 + interface ORBject { + + ImplementationDef get_implementation (); + InterfaceDef get_interface (); + boolean is_nil(); + Object duplicate (); + void release (); + boolean is_a (in string logical_type_id); + boolean non_existent(); + boolean is_equivalent (in Object other_object); + unsigned long hash(in unsigned long maximum); + + + Status create_request ( + in Context ctx, + in Identifier operation, + in NVList arg_list, + inout NamedValue result, + out Request request, + in Flags req_flags + ); + }; + + + // Basic Object Adapter interface described in Chapter 8, CORBA V2.0, July 1995 + // interface InterfaceDef; // from Interface Repository // PIDL + // interface ImplementationDef; // from Implementation Repository + // interface Object; // an object reference + // interface Principal; // for the authentication service + typedef sequence <octet, 1024> ReferenceData; + + interface BOA { + Object create ( + in ReferenceData id, + in InterfaceDef intf, + in ImplementationDef impl + ); + void dispose (in Object obj); + ReferenceData get_id (in Object obj); + + void change_implementation (in Object obj, + in ImplementationDef impl + ); + + Principal get_principal (in Object obj, + in Environment ev + ); + + void set_exception (in exception_type major, // NO, USER, + //or SYSTEM_EXCEPTION + in string userid, // exception type id + in any param_LOOK_AT_SOURCE + // in void *param // pointer to associated data + ); + + void impl_is_ready (in ImplementationDef impl); + void deactivate_impl (in ImplementationDef impl); + void obj_is_ready (in Object obj, in ImplementationDef impl); + void deactivate_obj (in Object obj); + }; +}; + +// IOP module described in chap 10 CORBA V2, 7-95 +module IOP{ // IDL + // + // Standard Protocol Profile tag values + // + typedef unsigned long ProfileId; + const ProfileId TAG_INTERNET_IOP = 0; + const ProfileId TAG_MULTIPLE_COMPONENTS = 1; + + struct TaggedProfile { + ProfileId tag; + sequence <octet> profile_data; + }; + + // + // an Interoperable Object Reference is a sequence of + // object-specific protocol profiles, plus a type ID. + // + struct IOR { + string type_id; + sequence <TaggedProfile> profiles; + }; + + // + // Standard way of representing multicomponent profiles. + // This would be encapsulated in a TaggedProfile. + // + typedef unsigned long ComponentId; + struct TaggedComponent { + ComponentId tag; + sequence <octet> component_data; + }; + typedef sequence <TaggedComponent> MultipleComponentProfile; + + + typedef unsigned long ServiceID; + + struct ServiceContext { + ServiceID context_id; + sequence <octet> context_data; + }; + typedef sequence <ServiceContext> ServiceContextList; + + const ServiceID TransactionService = 0; + + + +}; +// GIOP module described in CORBA V2, 7-95 chap 12 +// Complete IDL for GIOP module in CORBA +// V2.0, 7-95 p 10-29 +// GIOP message header: CORBA V2, 7-95 p 12-16 +// GIOP request header: CORBA V2, 7-95 p 12-17 +// GIOP reply header: CORBA V2, 7-95 p 12-19 +// GIOP cancel request and locate request: CORBA V2, 7-95 pp 12-20 -- 12-21 +// GIOP locate reply: CORBA V2, 7-95 p 12-22 +module GIOP { // IDL + enum MsgType { + Request, Reply, CancelRequest, + LocateRequest, LocateReply, + CloseConnection, MessageError + }; + + struct Version { + char major; + char minor; + }; + + struct MessageHeader { + char magic [4]; + Version GIOP_version; + boolean byte_order; + octet message_type; + unsigned long message_size; + }; + + struct RequestHeader { + ::IOP::ServiceContextList service_context; + unsigned long request_id; + boolean response_expected; + sequence <octet> object_key; + string operation; + + /* + * ::CORBA:: added for correct scope + */ + ::CORBA::Principal requesting_principal; + }; + + enum ReplyStatusType { + NO_EXCEPTION, + USER_EXCEPTION, + SYSTEM_EXCEPTION, + LOCATION_FORWARD + }; + + struct ReplyHeader { + ::IOP::ServiceContextList service_context; + unsigned long request_id; + ReplyStatusType reply_status; + }; + + struct CancelRequestHeader { + unsigned long request_id; + }; + + struct LocateRequestHeader { + unsigned long request_id; + sequence <octet> object_key; + }; + + enum LocateStatusType { + UNKNOWN_OBJECT, + OBJECT_HERE, + OBJECT_FORWARD + }; + + struct LocateReplyHeader { + unsigned long request_id; + LocateStatusType locate_status; + }; +}; +// IIOP module described in CORBA V2, 7-95 chap 12 +// Complete IDL for IIOP module: CORBA V2, 7-95 p 12-31 +module IIOP { // IDL + struct Version { + char major; + char minor; + }; + + struct ProfileBody { + Version iiop_version; + string host; + unsigned short port; + sequence <octet> object_key; + }; +}; +// DCE CIOP module described in CORBA V2, 7-95 chap 13 +// IDL for DCE CIOP module: CORBA V2, 7-95 p 13-2 +module DCE_CIOP { + struct InvokeRequestHeader { + boolean byte_order; + ::IOP::ServiceContextList service_context; + sequence <octet> object_key; + string endpoint_id; + string operation; + ::CORBA::Principal principal; + sequence <string> client_context; + + // in and inout parameters follow + }; + enum InvokeResponseStatus { + INVOKE_NO_EXCEPTION, + INVOKE_USER_EXCEPTION, + INVOKE_SYSTEM_EXCEPTION, + INVOKE_LOCATION_FORWARD, + INVOKE_TRY_AGAIN + }; + + struct InvokeResponseHeader { + boolean byte_order; + ::IOP::ServiceContextList service_context; + InvokeResponseStatus status; + + // if status = INVOKE_NO_EXCEPTION, + // result then inouts and outs follow + + // if status = INVOKE_USER_EXCEPTION or + // INVOKE_SYSTEM_EXCEPTION, an exception follows + + // if status = INVOKE_LOCATION_FORWARD, an + // ::IOP::MultipleComponentsProfile follows + }; + + struct LocateRequestHeader { + boolean byte_order; + sequence <octet> object_key; + string endpoint_id; + string operation; + + // no body follows + }; + + module IOP { + + /* + * ::IOP:: added to get the right scope + */ + const ::IOP::ComponentId TAG_OBJECT_KEY = 10; + const ::IOP::ComponentId TAG_ENDPOINT_ID = 11; + const ::IOP::ComponentId TAG_LOCATION_POLICY = 12; + // illegal IDL + /* const octet LOCATE_NEVER = 0; + const octet LOCATE_OBJECT = 1; + const octet LOCATE_OPERATION = 2; + const octet LOCATE_ALWAYS = 3; + */ + }; +}; + +#endif diff --git a/lib/ic/test/ic_SUITE_data/Coss.idl b/lib/ic/test/ic_SUITE_data/Coss.idl new file mode 100644 index 0000000000..c84d4a8247 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/Coss.idl @@ -0,0 +1,1537 @@ +// This file contains OMG IDL and PIDL for the Common Object Services. +// CosNaming Module, p 3-6 CORBAservices, Naming Service V1.0, 3/94 + +// A few minor changes for the JacORB distribution: +// +// added am enclosing COSS module and changed scoped names accordingly +// +// corrected a few syntax errors +// +// commented out: +// #includes +// forward declaration of Object + +#include "Corba.idl" + +module COSS { + +module CosNaming { + + typedef string Istring; + struct NameComponent { + Istring id; + Istring kind; + }; + + typedef sequence <NameComponent> Name; + + enum BindingType {nobject, ncontext}; + + struct Binding { + Name binding_name; + BindingType binding_type; + }; + + typedef sequence <Binding> BindingList; + interface BindingIterator; + + interface NamingContext { + + enum NotFoundReason { missing_node, not_context, not_object}; + + exception NotFound { + NotFoundReason why; + Name rest_of_name; + }; + + exception CannotProceed { + NamingContext cxt; + Name rest_of_name; + }; + + exception InvalidName{}; + exception AlreadyBound {}; + exception NotEmpty{}; + + void bind(in Name n, in Object obj) + raises(NotFound, CannotProceed, InvalidName, AlreadyBound); + void rebind(in Name n, in Object obj) + raises(NotFound, CannotProceed, InvalidName); + void bind_context(in Name n, in NamingContext nc) + raises(NotFound, CannotProceed, InvalidName, AlreadyBound); + void rebind_context(in Name n, in NamingContext nc) + raises(NotFound, CannotProceed, InvalidName); + Object resolve (in Name n) + raises(NotFound, CannotProceed, InvalidName); + void unbind(in Name n) + raises(NotFound, CannotProceed, InvalidName); + NamingContext new_context(); + NamingContext bind_new_context(in Name n) + raises(NotFound, AlreadyBound, CannotProceed, InvalidName); + void destroy( ) + raises(NotEmpty); + void list (in unsigned long how_many, + out BindingList bl, out BindingIterator bi); + }; + + interface BindingIterator { + boolean next_one(out Binding b); + boolean next_n(in unsigned long how_many, + out BindingList bl); + void destroy(); + }; +}; + +// Names Library interface in PIDL, CORBAservices p 3- 14, Naming Service V1.0 3/94 +/* +interface LNameComponent { // PIDL + exception NotSet{}; + string get_id() + raises(NotSet); + void set_id(in string i); + string get_kind() + raises(NotSet); + void set_kind(in string k); + void destroy(); +}; + +interface LName { // PIDL + exception NoComponent{}; + exception OverFlow{}; + exception InvalidName{}; + LName insert_component(in unsigned long i, + in LNameComponent n) + raises(NoComponent, OverFlow); + LNameComponent get_component(in unsigned long i) + raises(NoComponent); + LNameComponent delete_component(in unsigned long i) + raises(NoComponent); + unsigned long num_components(); + boolean equal(in LName ln); + boolean less_than(in LName ln); + Name to_idl_form() + raises(InvalidName); + void from_idl_form(in Name n); + void destroy(); +}; + +LName create_lname(); // C/C++ +LNameComponent create_lname_component(); // C/C++ +*/ + +// CosEventComm Module, CORBAservices p 4-8, Event Service V1.0 3/94 + +module CosEventComm { + + exception Disconnected{}; + + interface PushConsumer { + void push (in any data) raises(Disconnected); + void disconnect_push_consumer(); + }; + + interface PushSupplier { + void disconnect_push_supplier(); + }; + + interface PullSupplier { + any pull () raises(Disconnected); + any try_pull (out boolean has_event) + raises(Disconnected); + void disconnect_pull_supplier(); + }; + + interface PullConsumer { + void disconnect_pull_consumer(); + }; + +}; + +// CosEventChannelAdmin Module, p 4-15 CORBAservices, Event +// Service V1.0, 3/94 + +// #include "CosEventComm.idl" + +module CosEventChannelAdmin { + + exception AlreadyConnected {}; + exception TypeError {}; + + interface ProxyPushConsumer: ::COSS::CosEventComm::PushConsumer { + void connect_push_supplier( + in ::COSS::CosEventComm::PushSupplier push_supplier) + raises(AlreadyConnected); + }; + + interface ProxyPullSupplier: ::COSS::CosEventComm::PullSupplier { + void connect_pull_consumer( + in ::COSS::CosEventComm::PullConsumer pull_consumer) + raises(AlreadyConnected); + }; + + interface ProxyPullConsumer: ::COSS::CosEventComm::PullConsumer { + void connect_pull_supplier( + in ::COSS::CosEventComm::PullSupplier pull_supplier) + raises(AlreadyConnected,TypeError); + }; + + interface ProxyPushSupplier: ::COSS::CosEventComm::PushSupplier { + void connect_push_consumer( + in ::COSS::CosEventComm::PushConsumer + push_consumer) + raises(AlreadyConnected, TypeError); + }; + + + interface ConsumerAdmin { + ProxyPushSupplier obtain_push_supplier(); + ProxyPullSupplier obtain_pull_supplier(); + }; + + interface SupplierAdmin { + ProxyPushConsumer obtain_push_consumer(); + ProxyPullConsumer obtain_pull_consumer(); + }; + + interface EventChannel { + ConsumerAdmin for_consumers(); + SupplierAdmin for_suppliers(); + void destroy(); + }; + +}; + + +// CosTyped Event Module, p 4-22 CORBAservices, Event Service +// V1.0, 3/94 + +// // #include "CosEventComm.idl" + +module CosTypedEventComm { + + interface TypedPushConsumer : ::COSS::CosEventComm::PushConsumer { + Object get_typed_consumer(); + }; + + interface TypedPullSupplier : ::COSS::CosEventComm::PullSupplier { + Object get_typed_supplier(); + }; + +}; + +// CosTypedEventChannelAdmin Module, p 4- 25 CORBAservices, +// Event Service V1.0, 3/94 + +// // #include "CosEventChannel.idl" +// // #include "CosTypedEventComm.idl" +module CosTypedEventChannelAdmin { + exception InterfaceNotSupported {}; + exception NoSuchImplementation {}; + typedef string Key; + + interface TypedProxyPushConsumer : + ::COSS::CosEventChannelAdmin::ProxyPushConsumer, + ::COSS::CosTypedEventComm::TypedPushConsumer { }; + + interface TypedProxyPullSupplier : + ::COSS::CosEventChannelAdmin::ProxyPullSupplier, + ::COSS::CosTypedEventComm::TypedPullSupplier { }; + + interface TypedSupplierAdmin : + ::COSS::CosEventChannelAdmin::SupplierAdmin { + TypedProxyPushConsumer obtain_typed_push_consumer( + in Key supported_interface) + raises(InterfaceNotSupported); + ::COSS::CosEventChannelAdmin::ProxyPullConsumer obtain_typed_pull_consumer ( + in Key uses_interface) + raises(NoSuchImplementation); + }; + + interface TypedConsumerAdmin : + ::COSS::CosEventChannelAdmin::ConsumerAdmin { + TypedProxyPullSupplier obtain_typed_pull_supplier( + in Key supported_interface) + raises (InterfaceNotSupported); + ::COSS::CosEventChannelAdmin::ProxyPushSupplier obtain_typed_push_supplier( + in Key uses_interface) + raises(NoSuchImplementation); + }; + + interface TypedEventChannel { + TypedConsumerAdmin for_consumers(); + TypedSupplierAdmin for_suppliers(); + void destroy (); + }; +}; + + +// CosPersistencePID Module, p 5-20 CORBAservices, +// Persistent Object Service V1.0, 3/94 + +//#ifndef __COSPERSISTENCE +//#define __COSPERSISTENCE + +module CosPersistencePID { + + interface PID { + attribute string datastore_type; + string get_PIDString(); + }; +}; + + +// CosPersistencePDS Module, p 5-20 CORBAservices, +// Persistent Object Service V1.0, 3/94 + +// #include "CosPersistencePID.idl" + +module CosPersistencePDS { + +// interface Object; + interface PDS { + PDS connect (in Object obj, + in ::COSS::CosPersistencePID::PID p); + void disconnect (in Object obj, + in ::COSS::CosPersistencePID::PID p); + void store (in Object obj, + in ::COSS::CosPersistencePID::PID p); + void restore (in Object obj, + in ::COSS::CosPersistencePID::PID p); + void delete (in Object obj, + in ::COSS::CosPersistencePID::PID p); + }; +}; + + +// CosPersistencePO Module, p 5-12 CORBAservices, +// Persistent Object Service V1.0, 3/94 + +// // #include "CosPersistencePDS.idl" +// CosPersistencePDS.idl +// // #includes CosPersistencePID.idl + +module CosPersistencePO { + + interface PO { + attribute ::COSS::CosPersistencePID::PID p; + ::COSS::CosPersistencePDS::PDS connect ( + in ::COSS::CosPersistencePID::PID p); + void disconnect (in ::COSS::CosPersistencePID::PID p); + void store (in ::COSS::CosPersistencePID::PID p); + void restore (in ::COSS::CosPersistencePID::PID p); + void delete (in ::COSS::CosPersistencePID::PID p); + }; + + interface SD { + void pre_store(); + void post_restore(); + }; +}; + + +// CosPersistencePOM Module, p 5-15 CORBAservices, +// Persistent Object Service V1.0, 3/94 + +// #include "CosPersistencePDS.idl" + +// CosPersistencePDS.idl // #includes CosPersistencePID.idl + +module CosPersistencePOM { + +// interface Object; + + interface POM { + ::COSS::CosPersistencePDS::PDS connect ( + in Object obj, + in ::COSS::CosPersistencePID::PID p); + void disconnect ( + in Object obj, + in ::COSS::CosPersistencePID::PID p); + void store ( + in Object obj, + in ::COSS::CosPersistencePID::PID p); + void restore ( + in Object obj, + in ::COSS::CosPersistencePID::PID p); + void delete ( + in Object obj, + in ::COSS::CosPersistencePID::PID p); + }; + }; + +// CosPersistencePDS_DA Module, p 5-22 CORBAservices, +// Persistent Object Service, V1.0, 3/94 + +// #include "CosPersistencePDS.idl" +// CosPersistencePDS.idl // #includes CosPersistencePID.idl + +module CosPersistencePDS_DA { + + typedef string DAObjectID; + + interface PID_DA : ::COSS::CosPersistencePID::PID { + attribute DAObjectID oid; + }; + + interface DAObject { + boolean dado_same(in DAObject d); + DAObjectID dado_oid(); + PID_DA dado_pid(); + void dado_remove(); + void dado_free(); + }; + + interface DAObjectFactory { + DAObject create(); + }; + + interface DAObjectFactoryFinder { + DAObjectFactory find_factory(in string key); + }; + + interface PDS_DA : ::COSS::CosPersistencePDS::PDS { + DAObject get_data(); + void set_data(in DAObject new_data); + DAObject lookup(in DAObjectID id); + PID_DA get_pid(); + PID_DA get_object_pid(in DAObject dao); + DAObjectFactoryFinder data_factories(); + }; + + typedef sequence<string> AttributeNames; + interface DynamicAttributeAccess { + AttributeNames attribute_names(); + any attribute_get(in string name); + void attribute_set(in string name, in any value); + }; + + typedef string ClusterID; + typedef sequence<ClusterID> ClusterIDs; + interface PDS_ClusteredDA : PDS_DA{ + ClusterID cluster_id(); + string cluster_kind(); + ClusterIDs clusters_of(); + PDS_ClusteredDA create_cluster(in string kind); + PDS_ClusteredDA open_cluster(in ClusterID cluster); + PDS_ClusteredDA copy_cluster( + in PDS_DA source); + }; +}; + +// CosPersistenceDDO Module, p 5-32 CORBAservices, Persistent Object Service V1.0, 3/94 + +// #include "CosPersistencePID.idl" +module CosPersistenceDDO { + + interface DDO { + attribute string object_type; + attribute ::COSS::CosPersistencePID::PID p; + short add_data(); + short add_data_property (in short data_id); + short get_data_count(); + short get_data_property_count (in short data_id); + void get_data_property (in short data_id, + in short property_id, + out string property_name, + out any property_value); + void set_data_property (in short data_id, + in short property_id, + in string property_name, + in any property_value); + void get_data (in short data_id, + out string data_name, + out any data_value); + void set_data (in short data_id, + in string data_name, + in any data_value); + }; +}; + +// CosPersistenceDS_CLI module, p 5-34 CORBAservices, +// Persistent Object Service V1.0, 3/94 + +// #include "CosPersistenceDDO.idl" +// CosPersistenceDDO.idl // #includes CosPersistencePID.idl + +module CosPersistenceDS_CLI { + interface UserEnvironment { + void set_option (in long option,in any value); + void get_option (in long option,out any value); + void release(); + }; + + interface Connection { + void set_option (in long option,in any value); + void get_option (in long option,out any value); + }; + + interface ConnectionFactory { + Connection create_object ( + in UserEnvironment user_envir); + }; + + interface Cursor { + void set_position (in long position,in any value); + ::COSS::CosPersistenceDDO::DDO fetch_object(); + }; + + interface CursorFactory { + Cursor create_object ( + in Connection connection); + }; + + interface PID_CLI : ::COSS::CosPersistencePID::PID { + attribute string datastore_id; + attribute string id; + }; + + + + interface Datastore_CLI { + void connect (in Connection connection, + in string datastore_id, + in string user_name, + in string authentication); + void disconnect (in Connection connection); + Connection get_connection ( + in string datastore_id, + in string user_name); + void add_object (in Connection connection, + in ::COSS::CosPersistenceDDO::DDO data_obj); + void delete_object ( + in Connection connection, + in ::COSS::CosPersistenceDDO::DDO data_obj); + void update_object ( + in Connection connection, + in ::COSS::CosPersistenceDDO::DDO data_obj); + void retrieve_object( + in Connection connection, + in ::COSS::CosPersistenceDDO::DDO data_obj); + Cursor select_object( + in Connection connection, + in string key); + void transact (in UserEnvironment user_envir, + in short completion_type); + void assign_PID (in PID_CLI p); + void assign_PID_relative ( + in PID_CLI source_pid, + in PID_CLI target_pid); + boolean is_identical_PID ( + in PID_CLI pid_1, + in PID_CLI pid_2); + string get_object_type (in PID_CLI p); + void register_mapping_schema (in string schema_file); + Cursor execute (in Connection connection, + in string command); + }; + +}; + + +// CosLifeCycle Module, p 6-10 CORBAservices, LifeCycle Service V1.0, 3/94 + +// #include "Naming.idl" + +module CosLifeCycle +{ + typedef ::COSS::CosNaming::Name Key; + typedef Object Factory; + typedef sequence <Factory> Factories; + typedef struct NVP { + ::COSS::CosNaming::Istring name; + any value; + } NameValuePair; + typedef sequence <NameValuePair> Criteria; + + exception NoFactory { + Key search_key; + }; + exception NotCopyable { string reason; }; + exception NotMovable { string reason; }; + exception NotRemovable { string reason; }; + exception InvalidCriteria{ + Criteria invalid_criteria; + }; + exception CannotMeetCriteria { + Criteria unmet_criteria; + }; + + + interface FactoryFinder { + Factories find_factories(in Key factory_key) + raises(NoFactory); + }; + + interface LifeCycleObject { + LifeCycleObject copy(in FactoryFinder there, + in Criteria the_criteria) + raises(NoFactory, NotCopyable, InvalidCriteria, + CannotMeetCriteria); + void move(in FactoryFinder there, + in Criteria the_criteria) + raises(NoFactory, NotMovable, InvalidCriteria, + CannotMeetCriteria); + void remove() + raises(NotRemovable); + }; + + interface GenericFactory { + boolean supports(in Key k); + Object create_object( + in Key k, + in Criteria the_criteria) + raises (NoFactory, InvalidCriteria, + CannotMeetCriteria); + }; +}; + + + +// LifeCycleService Module, p 6- 55 CORBAservices, Life Cycle +// Service V1.0, 3/94 + +// #include "LifeCycle.idl" + +module LifeCycleService { + + typedef sequence <::COSS::CosLifeCycle::NameValuePair> PolicyList; + typedef sequence <::COSS::CosLifeCycle::Key> Keys; + typedef sequence <::COSS::CosLifeCycle::NameValuePair> PropertyList; + typedef sequence <::COSS::CosNaming::NameComponent> NameComponents; + + interface LifeCycleServiceAdmin { + + attribute PolicyList policies; + + void bind_generic_factory( + in ::COSS::CosLifeCycle::GenericFactory gf, + in ::COSS::CosNaming::NameComponent name, + in Keys key_set, + in PropertyList other_properties) + raises (::COSS::CosNaming::NamingContext::AlreadyBound, ::COSS::CosNaming::NamingContext::InvalidName); + + void unbind_generic_factory( + in ::COSS::CosNaming::NameComponent name) + raises (::COSS::CosNaming::NamingContext::NotFound, ::COSS::CosNaming::NamingContext::InvalidName); + + ::COSS::CosLifeCycle::GenericFactory resolve_generic_factory( + in ::COSS::CosNaming::NameComponent name) + raises (::COSS::CosNaming::NamingContext::NotFound, ::COSS::CosNaming::NamingContext::InvalidName); + + NameComponents list_generic_factories(); + + boolean match_service (in ::COSS::CosLifeCycle::GenericFactory f); + + string get_hint(); + + void get_link_properties( + in ::COSS::CosNaming::NameComponent name, + out Keys key_set, + out PropertyList other_properties) + raises (::COSS::CosNaming::NamingContext::NotFound, ::COSS::CosNaming::NamingContext::InvalidName); + }; +}; + +// CosTransactions Module, p 10-66 +// CORBAservices, Transaction Service V1.0, 3/94 + +module CosTransactions { +// DATATYPES +enum Status { + StatusActive, + StatusMarkedRollback, + StatusPrepared, + StatusCommitted, + StatusRolledBack, + StatusUnknown, + StatusNoTransaction +}; + +enum Vote { + VoteCommit, + VoteRollback, + VoteReadOnly +}; + +// Standard exceptions +exception TransactionRequired {}; +exception TransactionRolledBack {}; +exception InvalidTransaction {}; + +// Heuristic exceptions +exception HeuristicRollback {}; +exception HeuristicCommit {}; +exception HeuristicMixed {}; +exception HeuristicHazard {}; + +// Exception from Orb operations +exception WrongTransaction {}; + +// Other transaction-specific exceptions +exception SubtransactionsUnavailable {}; +exception NotSubtransaction {}; +exception Inactive {}; +exception NotPrepared {}; +exception NoTransaction {}; +exception InvalidControl {}; +exception Unavailable {}; + +// Forward references for interfaces defined later in module +interface Control; +interface Terminator; +interface Coordinator; +interface Resource; +interface RecoveryCoordinator; +interface SubtransactionAwareResource; +interface TransactionFactory; +interface TransactionalObject; +interface Current; + +// Current transaction pseudo object (PIDL) + interface Current { + void begin() + raises(SubtransactionsUnavailable); + void commit(in boolean report_heuristics) + raises( + NoTransaction, + HeuristicMixed, + HeuristicHazard + ); + void rollback() + raises(NoTransaction); + void rollback_only() + raises(NoTransaction); + + Status get_status(); + string get_transaction_name(); + void set_timeout(in unsigned long seconds); + + Control get_control(); + Control suspend(); + void resume(in Control which) + raises(InvalidControl); + }; + + interface TransactionFactory { + Control create(in unsigned long time_out); + }; + + interface Control { + Terminator get_terminator() + raises(Unavailable); + Coordinator get_coordinator() + raises(Unavailable); + }; + + interface Terminator { + void commit(in boolean report_heuristics) + raises( + HeuristicMixed, + HeuristicHazard + ); + void rollback(); + }; + + + interface Coordinator { + + Status get_status(); + Status get_parent_status(); + Status get_top_level_status(); + + boolean is_same_transaction(in Coordinator tc); + boolean is_related_transaction(in Coordinator tc); + boolean is_ancestor_transaction(in Coordinator tc); + boolean is_descendant_transaction(in Coordinator tc); + boolean is_top_level_transaction(); + + unsigned long hash_transaction(); + unsigned long hash_top_level_tran(); + + RecoveryCoordinator register_resource(in Resource r) + raises(Inactive); + + void register_subtran_aware(in SubtransactionAwareResource r) + raises(Inactive, NotSubtransaction); + + void rollback_only() + raises(Inactive); + + string get_transaction_name(); + + Control create_subtransaction() + raises(SubtransactionsUnavailable, Inactive); + }; + + interface RecoveryCoordinator { + Status replay_completion(in Resource r) + raises(NotPrepared); + }; + +}; // end module CosTransactions + + +// CosConcurrency Control Module, p 7-8 CORBAservices, +// Concurrency Control Service V1.0, 3/94 + +// #include <CosTransactions.idl> +module CosConcurrencyControl { + + enum lock_mode { + read, + write, + upgrade, + intention_read, + intention_write + }; + + exception LockNotHeld{}; + + interface LockCoordinator + { + void drop_locks(); + }; + + interface LockSet + { + void lock(in lock_mode mode); + boolean try_lock(in lock_mode mode); + + void unlock(in lock_mode mode) + raises(LockNotHeld); + void change_mode(in lock_mode held_mode, + in lock_mode new_mode) + raises(LockNotHeld); + LockCoordinator get_coordinator( + in ::COSS::CosTransactions::Coordinator which); + }; + + interface TransactionalLockSet + { + void lock(in ::COSS::CosTransactions::Coordinator current, + in lock_mode mode); + boolean try_lock(in ::COSS::CosTransactions::Coordinator current, + in lock_mode mode); + void unlock(in ::COSS::CosTransactions::Coordinator current, + in lock_mode mode) + raises(LockNotHeld); + void change_mode(in ::COSS::CosTransactions::Coordinator current, + in lock_mode held_mode, + in lock_mode new_mode) + raises(LockNotHeld); + LockCoordinator get_coordinator( + in ::COSS::CosTransactions::Coordinator which); + }; + + interface LockSetFactory + { + LockSet create(); + LockSet create_related(in LockSet which); + TransactionalLockSet create_transactional(); + TransactionalLockSet create_transactional_related(in + TransactionalLockSet which); + }; +}; + +// CosObjectIdentity Module, p 9-19 CORBAservices, Relationship +// Service V1.0, 3/94 + + +module CosObjectIdentity { + + typedef unsigned long ObjectIdentifier; + + interface IdentifiableObject { + readonly attribute ObjectIdentifier constant_random_id; + boolean is_identical ( + in IdentifiableObject other_object); + }; + +}; + + +// CosRelationships Module, p 9-21 CORBAservices, Relationship +// Service V1.0, 3/94 + +// #include <ObjectIdentity.idl> + +module CosRelationships { + + interface RoleFactory; + interface RelationshipFactory; + interface Relationship; + interface Role; + interface RelationshipIterator; + + typedef Object RelatedObject; + typedef sequence<Role> Roles; + typedef string RoleName; + typedef sequence<RoleName> RoleNames; + + struct NamedRole {RoleName name; Role aRole;}; + typedef sequence<NamedRole> NamedRoles; + + struct RelationshipHandle { + Relationship the_relationship; + ::COSS::CosObjectIdentity::ObjectIdentifier constant_random_id; + }; + typedef sequence<RelationshipHandle> RelationshipHandles; + + interface RelationshipFactory { + struct NamedRoleType { + RoleName name; + ::CORBA::InterfaceDef named_role_type; + }; + typedef sequence<NamedRoleType> NamedRoleTypes; + readonly attribute ::CORBA::InterfaceDef relationship_type; + readonly attribute unsigned short degree; + readonly attribute NamedRoleTypes named_role_types; + exception RoleTypeError {NamedRoles culprits;}; + exception MaxCardinalityExceeded { + NamedRoles culprits;}; + exception DegreeError {unsigned short required_degree;}; + exception DuplicateRoleName {NamedRoles culprits;}; + exception UnknownRoleName {NamedRoles culprits;}; + + Relationship create (in NamedRoles named_roles) + raises (RoleTypeError, + MaxCardinalityExceeded, + DegreeError, + DuplicateRoleName, + UnknownRoleName); + }; + + interface Relationship : + ::COSS::CosObjectIdentity::IdentifiableObject { + exception CannotUnlink { + Roles offending_roles; + }; + readonly attribute NamedRoles named_roles; + void destroy () raises(CannotUnlink); + }; + + interface Role { + exception UnknownRoleName {}; + exception UnknownRelationship {}; + exception RelationshipTypeError {}; + exception CannotDestroyRelationship { + RelationshipHandles offenders; + }; + exception ParticipatingInRelationship { + RelationshipHandles the_relationships; + }; + readonly attribute RelatedObject related_object; + RelatedObject get_other_related_object ( + in RelationshipHandle rel, + in RoleName target_name) + raises (UnknownRoleName, + UnknownRelationship); + Role get_other_role (in RelationshipHandle rel, + in RoleName target_name) + raises (UnknownRoleName, UnknownRelationship); + void get_relationships ( + in unsigned long how_many, + out RelationshipHandles rels, + out RelationshipIterator iterator); + void destroy_relationships() + raises(CannotDestroyRelationship); + void destroy() raises(ParticipatingInRelationship); + boolean check_minimum_cardinality (); + void link (in RelationshipHandle rel, + in NamedRoles named_roles) + raises(RelationshipFactory::MaxCardinalityExceeded, + RelationshipTypeError); + void unlink (in RelationshipHandle rel) + raises (UnknownRelationship); + }; + + interface RoleFactory { + exception NilRelatedObject {}; + exception RelatedObjectTypeError {}; + readonly attribute ::CORBA::InterfaceDef role_type; + readonly attribute unsigned long max_cardinality; + readonly attribute unsigned long min_cardinality; +// the following isn't allowed in IDL, +// readonly attribute sequence <::CORBA::InterfaceDef> related_object_types; + typedef sequence <::CORBA::InterfaceDef> InterfaceDefSeq; + readonly attribute InterfaceDefSeq related_object_types; + Role create_role (in RelatedObject related_object) + raises (NilRelatedObject, RelatedObjectTypeError); + }; + + interface RelationshipIterator { + boolean next_one (out RelationshipHandle rel); + boolean next_n (in unsigned long how_many, + out RelationshipHandles rels); + void destroy (); + }; + +}; + +// CosCompoundExternalization Module, p 8-20 CORBAservices, +// Externalization Service V1.0, 3/94 + +// #include <Graphs.idl> +// #include <Stream.idl> + +// CosGraphs Module, p 9-39 CORBAservices, Relationship Service +// V1.0, 3/94 + +// #include <Relationships.idl> +// #include <ObjectIdentity.idl> + +module CosGraphs { + + interface TraversalFactory; + interface Traversal; + interface TraversalCriteria; + interface Node; + interface NodeFactory; + interface Role; + interface EdgeIterator; + + struct NodeHandle { + Node the_node; + ::COSS::CosObjectIdentity::ObjectIdentifier constant_random_id; + }; + typedef sequence<NodeHandle> NodeHandles; + + struct NamedRole { + Role the_role; + ::COSS::CosRelationships::RoleName the_name; + }; + typedef sequence<NamedRole> NamedRoles; + + struct EndPoint { + NodeHandle the_node; + NamedRole the_role; + }; + typedef sequence<EndPoint> EndPoints; + + struct Edge { + EndPoint from; + ::COSS::CosRelationships::RelationshipHandle the_relationship; + EndPoints relatives; + }; + typedef sequence<Edge> Edges; + + enum PropagationValue {deep, shallow, none, inhibit}; + enum Mode {depthFirst, breadthFirst, bestFirst}; + + interface TraversalFactory { + Traversal create_traversal_on ( + in NodeHandle root_node, + in TraversalCriteria the_criteria, + in Mode how); + }; + + interface Traversal { + typedef unsigned long TraversalScopedId; + struct ScopedEndPoint { + EndPoint point; + TraversalScopedId id; + }; + typedef sequence<ScopedEndPoint> ScopedEndPoints; + struct ScopedRelationship { + ::COSS::CosRelationships::RelationshipHandle + scoped_relationship; + TraversalScopedId id; + }; + struct ScopedEdge { + ScopedEndPoint from; + ScopedRelationship the_relationship; + ScopedEndPoints relatives; + }; + typedef sequence<ScopedEdge> ScopedEdges; + boolean next_one (out ScopedEdge the_edge); + boolean next_n (in short how_many, + out ScopedEdges the_edges); + void destroy (); + }; + + interface TraversalCriteria { + struct WeightedEdge { + Edge the_edge; + unsigned long weight; + sequence<NodeHandle> next_nodes; + }; + typedef sequence<WeightedEdge> WeightedEdges; + void visit_node(in NodeHandle a_node, + in Mode search_mode); + boolean next_one (out WeightedEdge the_edge); + boolean next_n (in short how_many, + out WeightedEdges the_edges); + void destroy(); + }; + + interface Node: ::COSS::CosObjectIdentity::IdentifiableObject { + typedef sequence<Role> Roles; + exception NoSuchRole {}; + exception DuplicateRoleType {}; + + readonly attribute ::COSS::CosRelationships::RelatedObject + related_object; + readonly attribute Roles roles_of_node; + Roles roles_of_type ( + in ::CORBA::InterfaceDef role_type); + void add_role (in Role a_role) + raises (DuplicateRoleType); + void remove_role (in ::CORBA::InterfaceDef of_type) + raises (NoSuchRole); + }; + + interface NodeFactory { + Node create_node (in Object related_object); + }; + + interface Role : ::COSS::CosRelationships::Role { + void get_edges ( in long how_many, + out Edges the_edges, + out EdgeIterator the_rest); + }; + + interface EdgeIterator { + boolean next_one (out Edge the_edge); + boolean next_n ( in unsigned long how_many, + out Edges the_edges); + void destroy (); + }; + +}; + + + +// CosStream Module, 8-15 CORBAservices, +// Externalization Service V1.0, 3/94 + +// #include <LifeCycle.idl> +// #include <ObjectIdentity.idl> +// #include <CompoundExternalization.idl> +module CosStream { + exception ObjectCreationError{}; + exception StreamDataFormatError{}; + interface StreamIO; + + interface Streamable: ::COSS::CosObjectIdentity::IdentifiableObject + { + readonly attribute ::COSS::CosLifeCycle::Key external_form_id; + void externalize_to_stream( + in StreamIO targetStreamIO); + void internalize_from_stream( + in StreamIO sourceStreamIO, + in ::COSS::CosLifeCycle::FactoryFinder there) + raises( ::COSS::CosLifeCycle::NoFactory, + ObjectCreationError, + StreamDataFormatError ); + }; + + interface StreamableFactory { + Streamable create_uninitialized(); + }; + + + interface StreamIO { + void write_string(in string aString); + void write_char(in char aChar); + void write_octet(in octet anOctet); + void write_unsigned_long( + in unsigned long anUnsignedLong); + void write_unsigned_short( + in unsigned short anUnsignedShort); + void write_long(in long aLong); + void write_short(in short aShort); + void write_float(in float aFloat); + void write_double(in double aDouble); + void write_boolean(in boolean aBoolean); + void write_object(in Streamable aStreamable); + // void write_graph(in ::COSS::CosCompoundExternalization::Node aNode); + string read_string() + raises(StreamDataFormatError); + char read_char() + raises(StreamDataFormatError ); + octet read_octet() + raises(StreamDataFormatError ); + unsigned long read_unsigned_long() + raises(StreamDataFormatError ); + unsigned short read_unsigned_short() + raises( StreamDataFormatError ); + long read_long() + raises(StreamDataFormatError ); + short read_short() + raises(StreamDataFormatError ); + float read_float() + raises(StreamDataFormatError ); + double read_double() + raises(StreamDataFormatError ); + boolean read_boolean() + raises(StreamDataFormatError ); + Streamable read_object( + in ::COSS::CosLifeCycle::FactoryFinder there, + in Streamable aStreamable) + raises(StreamDataFormatError ); +// void read_graph( +// in ::COSS::CosCompoundExternalization::Node starting_node, +// in ::COSS::CosLifeCycle::FactoryFinder there) +// raises(StreamDataFormatError ); + }; +}; + +module CosCompoundExternalization { + interface Node; + interface Role; + interface Relationship; + interface PropagationCriteriaFactory; + + struct RelationshipHandle { + Relationship theRelationship; + ::COSS::CosObjectIdentity::ObjectIdentifier constantRandomId; + }; + + interface Node : ::COSS::CosGraphs::Node, ::COSS::CosStream::Streamable{ + void externalize_node (in ::COSS::CosStream::StreamIO sio); + void internalize_node (in ::COSS::CosStream::StreamIO sio, + in ::COSS::CosLifeCycle::FactoryFinder there, + out ::COSS::CosGraphs::Node::Roles rolesOfNode) + raises (::COSS::CosLifeCycle::NoFactory); + }; + + interface Role : ::COSS::CosGraphs::Role { + void externalize_role (in ::COSS::CosStream::StreamIO sio); + void internalize_role (in ::COSS::CosStream::StreamIO sio); + ::COSS::CosGraphs::PropagationValue externalize_propagation ( + in RelationshipHandle rel, + in ::COSS::CosRelationships::RoleName toRoleName, + out boolean sameForAll); + }; + + interface Relationship : + ::COSS::CosRelationships::Relationship { + void externalize_relationship ( + in ::COSS::CosStream::StreamIO sio); + void internalize_relationship( + in ::COSS::CosStream::StreamIO sio, + in ::COSS::CosGraphs::NamedRoles newRoles); + ::COSS::CosGraphs::PropagationValue externalize_propagation ( + in ::COSS::CosRelationships::RoleName fromRoleName, + in ::COSS::CosRelationships::RoleName toRoleName, + out boolean sameForAll); + }; + + interface PropagationCriteriaFactory { + ::COSS::CosGraphs::TraversalCriteria create_for_externalize( ); + }; + +}; + +// CosExternalization Module, 8-12 CORBAservices, +// Externalization Service V1.0, 3/94 + + +// #include <LifeCycle.idl> +// #include <Stream.idl> +module CosExternalization { + exception InvalidFileNameError{}; + exception ContextAlreadyRegistered{}; + interface Stream: ::COSS::CosLifeCycle::LifeCycleObject{ + void externalize( + in ::COSS::CosStream::Streamable theObject); + ::COSS::CosStream::Streamable internalize( + in ::COSS::CosLifeCycle::FactoryFinder there) + raises( ::COSS::CosLifeCycle::NoFactory, + ::COSS::CosStream::StreamDataFormatError ); + void begin_context() + raises( ContextAlreadyRegistered); + void end_context(); + void flush(); + }; + interface StreamFactory { + Stream create(); + }; + interface FileStreamFactory { + Stream create( + in string theFileName) + raises( InvalidFileNameError ); + }; +}; + +// CosContainment Module, p 9- 48 CORBAservices, Relationship +// Service V1.0, 3/94 + +// #include <Graphs.idl> + +module CosContainment { + + interface Relationship : + ::COSS::CosRelationships::Relationship {}; + + interface ContainsRole : ::COSS::CosGraphs::Role {}; + + interface ContainedInRole : ::COSS::CosGraphs::Role {}; + +}; + +// CosExternalizationContainment Module, p 8-26 CORBAservices, +// Externalization Service V1.0, 3/94 + +// #include <Containment.idl> +// #include <CompoundExternalization.idl> + +module CosExternalizationContainment { + + interface Relationship : + ::COSS::CosCompoundExternalization::Relationship, + ::COSS::CosContainment::Relationship {}; + + interface ContainsRole : + ::COSS::CosCompoundExternalization::Role, + ::COSS::CosContainment::ContainsRole {}; + + interface ContainedInRole : + ::COSS::CosCompoundExternalization::Role, + ::COSS::CosContainment::ContainedInRole {}; +}; + +// CosReference Module, p 9-50 CORBAservices, +// Relationship Service V1.0, 3/94 + +// #include <Graphs.idl> + +module CosReference { + + interface Relationship : + ::COSS::CosRelationships::Relationship {}; + + interface ReferencesRole : ::COSS::CosGraphs::Role {}; + + interface ReferencedByRole : ::COSS::CosGraphs::Role {}; + +}; + +// CosExternalizationReference Module, p 8-28 CORBAservices, +// Externalization Service V1.0, 3/94 + +// #include <Reference.idl> +// #include <CompoundExternalization.idl> + +module CosExternalizationReference { + + interface Relationship : + ::COSS::CosCompoundExternalization::Relationship, + ::COSS::CosReference::Relationship {}; + + interface ReferencesRole : + ::COSS::CosCompoundExternalization::Role, + ::COSS::CosReference::ReferencesRole {}; + + interface ReferencedByRole : + ::COSS::CosCompoundExternalization::Role, + ::COSS::CosReference::ReferencedByRole {}; +}; + +// PIDL for CosTSInteroperation Module, p 10-59 +// CORBAservices, Transaction Service V1.0, 3/94 +module CosTSInteroperation { // PIDL + struct otid_t { + long formatID; /*format identifier. 0 is OSI TP */ + long bequal_length; + sequence <octet> tid; + }; + struct TransIdentity { + ::COSS::CosTransactions::Coordinator coordinator; + ::COSS::CosTransactions::Terminator terminator; + otid_t otid; + }; + struct PropagationContext { + unsigned long timeout; + TransIdentity current; + sequence <TransIdentity> parents; + any implementation_specific_data; + }; +}; + +// PIDL for CosTSPortability Module, p 10-63 +// CORBAservices, Transaction Service V1.0, 3/94 + +module CosTSPortability { // PIDL + typedef long ReqId; + + interface Sender { + void sending_request(in ReqId id, + out ::COSS::CosTSInteroperation::PropagationContext ctx); + void received_reply(in ReqId id, + in ::COSS::CosTSInteroperation::PropagationContext ctx, + in ::CORBA::Environment env); + }; + + interface Receiver { + void received_request(in ReqId id, + in ::COSS::CosTSInteroperation::PropagationContext ctx); + void sending_reply(in ReqId id, + out::COSS::CosTSInteroperation::PropagationContext ctx); + }; +}; + +// CosCompoundLifeCycle Module, p 6-30 CORBAservices, +// Life Cycle Service V1.0, 3/94 + +// #include <LifeCycle.idl> +// #include <Relationships.idl> +// #include <Graphs.idl> + +module CosCompoundLifeCycle { + interface OperationsFactory; + interface Operations; + interface Node; + interface Role; + interface Relationship; + interface PropagationCriteriaFactory; + + enum Operation {copy, move, remove}; + + struct RelationshipHandle { + Relationship the_relationship; + ::COSS::CosObjectIdentity::ObjectIdentifier constant_random_id; + }; + + interface OperationsFactory { + Operations create_compound_operations(); + }; + + interface Operations { + Node copy ( + in Node starting_node, + in ::COSS::CosLifeCycle::FactoryFinder there, + in ::COSS::CosLifeCycle::Criteria the_criteria) + raises (::COSS::CosLifeCycle::NoFactory, + ::COSS::CosLifeCycle::NotCopyable, + ::COSS::CosLifeCycle::InvalidCriteria, + ::COSS::CosLifeCycle::CannotMeetCriteria); + void move ( + in Node starting_node, + in ::COSS::CosLifeCycle::FactoryFinder there, + in ::COSS::CosLifeCycle::Criteria the_criteria) + raises (::COSS::CosLifeCycle::NoFactory, + ::COSS::CosLifeCycle::NotMovable, + ::COSS::CosLifeCycle::InvalidCriteria, + ::COSS::CosLifeCycle::CannotMeetCriteria); + void remove (in Node starting_node) + raises (::COSS::CosLifeCycle::NotRemovable); + void destroy(); + }; + + interface Node : ::COSS::CosGraphs::Node { + exception NotLifeCycleObject {}; + void copy_node ( in ::COSS::CosLifeCycle::FactoryFinder there, + in ::COSS::CosLifeCycle::Criteria the_criteria, + out Node new_node, + out ::COSS::CosGraphs::Node::Roles roles_of_new_node) + raises (::COSS::CosLifeCycle::NoFactory, + ::COSS::CosLifeCycle::NotCopyable, + ::COSS::CosLifeCycle::InvalidCriteria, + ::COSS::CosLifeCycle::CannotMeetCriteria); + void move_node (in ::COSS::CosLifeCycle::FactoryFinder there, + in ::COSS::CosLifeCycle::Criteria the_criteria) + raises (::COSS::CosLifeCycle::NoFactory, + ::COSS::CosLifeCycle::NotMovable, + ::COSS::CosLifeCycle::InvalidCriteria, + ::COSS::CosLifeCycle::CannotMeetCriteria); + void remove_node () + raises (::COSS::CosLifeCycle::NotRemovable); + ::COSS::CosLifeCycle::LifeCycleObject get_life_cycle_object() + raises (NotLifeCycleObject); + }; + + interface Role : ::COSS::CosGraphs::Role { + Role copy_role (in ::COSS::CosLifeCycle::FactoryFinder there, + in ::COSS::CosLifeCycle::Criteria the_criteria) + raises (::COSS::CosLifeCycle::NoFactory, + ::COSS::CosLifeCycle::NotCopyable, + ::COSS::CosLifeCycle::InvalidCriteria, + ::COSS::CosLifeCycle::CannotMeetCriteria); + void move_role (in ::COSS::CosLifeCycle::FactoryFinder there, + in ::COSS::CosLifeCycle::Criteria the_criteria) + raises (::COSS::CosLifeCycle::NoFactory, + ::COSS::CosLifeCycle::NotMovable, + ::COSS::CosLifeCycle::InvalidCriteria, + ::COSS::CosLifeCycle::CannotMeetCriteria); + ::COSS::CosGraphs::PropagationValue life_cycle_propagation ( + in Operation op, + in RelationshipHandle rel, + in ::COSS::CosRelationships::RoleName to_role_name, + out boolean same_for_all); + }; + + interface Relationship : + ::COSS::CosRelationships::Relationship { + Relationship copy_relationship ( + in ::COSS::CosLifeCycle::FactoryFinder there, + in ::COSS::CosLifeCycle::Criteria the_criteria, + in ::COSS::CosGraphs::NamedRoles new_roles) + raises (::COSS::CosLifeCycle::NoFactory, + ::COSS::CosLifeCycle::NotCopyable, + ::COSS::CosLifeCycle::InvalidCriteria, + ::COSS::CosLifeCycle::CannotMeetCriteria); + void move_relationship ( + in ::COSS::CosLifeCycle::FactoryFinder there, + in ::COSS::CosLifeCycle::Criteria the_criteria) + raises (::COSS::CosLifeCycle::NoFactory, + ::COSS::CosLifeCycle::NotMovable, + ::COSS::CosLifeCycle::InvalidCriteria, + ::COSS::CosLifeCycle::CannotMeetCriteria); + ::COSS::CosGraphs::PropagationValue life_cycle_propagation ( + in Operation op, + in ::COSS::CosRelationships::RoleName from_role_name, + in ::COSS::CosRelationships::RoleName to_role_name, + out boolean same_for_all); + }; + + interface PropagationCriteriaFactory { + ::COSS::CosGraphs::TraversalCriteria create(in Operation op); + }; + +}; + +// CosLifeCycleContainment Module, p 6-42 CORBAservices, +// Life Cycle Service V1.0, 3/94 + +// #include <Containment.idl> +// #include <CompoundLifeCycle.idl> + +module CosLifeCycleContainment { + + interface Relationship : + ::COSS::CosCompoundLifeCycle::Relationship, + ::COSS::CosContainment::Relationship {}; + + interface ContainsRole : + ::COSS::CosCompoundLifeCycle::Role, + ::COSS::CosContainment::ContainsRole {}; + + interface ContainedInRole : + ::COSS::CosCompoundLifeCycle::Role, + ::COSS::CosContainment::ContainedInRole {}; +}; + +// CosLifeCycleReference Module, p 6-44 CORBAservices, +// Life Cycle Service V1.0, 3/94 + +// #include <Reference.idl> +// #include <CompoundLifeCycle.idl> + +module CosLifeCycleReference { + + interface Relationship : + ::COSS::CosCompoundLifeCycle::Relationship, + ::COSS::CosReference::Relationship {}; + + interface ReferencesRole : + ::COSS::CosCompoundLifeCycle::Role, + ::COSS::CosReference::ReferencesRole {}; + + interface ReferencedByRole : + ::COSS::CosCompoundLifeCycle::Role, + ::COSS::CosReference::ReferencedByRole {}; +}; + + +}; // end module COSS diff --git a/lib/ic/test/ic_SUITE_data/attr.idl b/lib/ic/test/ic_SUITE_data/attr.idl new file mode 100644 index 0000000000..c74223eca6 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/attr.idl @@ -0,0 +1,29 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +interface I1 { + attribute long a1, a2; + attribute char a3; +}; + +interface I2 : I1 { + attribute short a4; + readonly attribute char a5; +}; + diff --git a/lib/ic/test/ic_SUITE_data/c_err1.idl b/lib/ic/test/ic_SUITE_data/c_err1.idl new file mode 100644 index 0000000000..e1bc93dae8 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/c_err1.idl @@ -0,0 +1,63 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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 forces the bad_tk_match. This triggers when the type of +// the expression does not match the declared type of the constant +// + +const long c1 = TRUE; +const unsigned short c1b= TRUE; +const boolean c2 = +5; +const long c3 = 'c'; +const float c5 = 3; +const unsigned long c6 = -2; // Maybe not checked in compiler or suite + +const boolean c4 = 1 | 2; + + +// Now define some correct constants for use in reference checking + +const long longC = -9; +const short shortC = -9; +const unsigned long ulongC = 1; +const unsigned short ushortC = 0; + +const float floatC = 5.1; +const double doubleC = -2.111; + +const boolean boolC = TRUE; + +const char charC = 'f'; +const string stringC = "hej"; +const string<9> stringCb = "hejdu"; + +// Check the reference errors + +const long c19 = floatC; +const short c20 = doubleC; +const unsigned long c21 = charC; +const unsigned short c22 = stringC; +const float c23 = stringCb; +const double c24 = boolC; +const boolean c25 = longC; +const char c26 = shortC; +const string c27 = ushortC; +const string<9> c28 = ulongC; +const long c29 = 3+floatC; diff --git a/lib/ic/test/ic_SUITE_data/c_err2.idl b/lib/ic/test/ic_SUITE_data/c_err2.idl new file mode 100644 index 0000000000..8dac241c7f --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/c_err2.idl @@ -0,0 +1,30 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Checks bad type of operands +// + + +const long c1 = 1 + TRUE; +const boolean c3 = TRUE | FALSE | 19.8; +const long c4 = 1 << TRUE; +const long c5 = TRUE >> TRUE; + + diff --git a/lib/ic/test/ic_SUITE_data/c_err3.idl b/lib/ic/test/ic_SUITE_data/c_err3.idl new file mode 100644 index 0000000000..dde9539f6f --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/c_err3.idl @@ -0,0 +1,28 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Checks ill-formed expressions (type conflict in operands) +// + + +const long c1 = 5|TRUE; +const long c2 = 5&TRUE; +const long c3 = 5^TRUE; + diff --git a/lib/ic/test/ic_SUITE_data/c_norm.idl b/lib/ic/test/ic_SUITE_data/c_norm.idl new file mode 100644 index 0000000000..6f6ef8ff79 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/c_norm.idl @@ -0,0 +1,163 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Check normal values and expressions for constants +// + +// Integer types +const long co1 = 077; +const long ch1 = 0xf1; +const long ch2 = 0XAB; +const long c1 = 1; +const short c2 = 3; +const unsigned long c3 = 1; +const unsigned short c4 = 3; + +// Unary ops +const long c1hb = -0x1; +const long c1b = -1; +const short c2b = -3; +const long c1c = +1; +const short c2c = +3; +// ~ not supported + +// Check binary ops +const long c1d = 9+1-3; +const long c1hd = 9+1-0xf3; +const short c2d = 7+3; +const short c2e = 7*3; +const long c1e = 1 | 7; +const long c1f = 7 & 9; +const long c1g = (1 | 7) & 9; +const long c1h = 1^7; + +//floats +const float c5 = 1.9; +const double c6 = 1.9; +const float c5b = -1.9; +const double c6b = -1.9; + +// Check type operand casting +const float c5c = 1/(9+2) * 2; +const double c6c = 1.9-1; +//const double c6d = 1; // Does not work yet + +// Booleans and expressions +const boolean c7 = TRUE; +const boolean c7b = FALSE; +const boolean c7c = TRUE | FALSE; +const boolean c7d = TRUE & FALSE; +const boolean c7e = TRUE&TRUE | FALSE&TRUE; +const boolean c7f = TRUE&TRUE ^ FALSE&TRUE; + +// Character and string +const char c8 = 'c'; +const char c8b = '\n'; +const string c9 = "hej"; +const string<9> c9b = "hejdu"; + + +// +// Check that value references work +// + +const long rc1 = c1g; +const long rc1h = c1h + 9; +const short rc2 = c2; +const unsigned long rc3 = c3; +const unsigned short rc4 = c4; + + +const float rc5c = c5c; +const double rc6c = c6c; +const double rc6d = c6c+1.3; + +const boolean rc7 = c7; +const boolean rc7c = c7c | TRUE; + +const char rc8 = c8; +const char rc8b = c8b; +const string rc9 = c9; +const string<9> rc9b = c9b; + + + + +// +// Now check that all typerefs work +// + +typedef long longT; +typedef short shortT; +typedef unsigned long ulongT; +typedef unsigned short ushortT; + +typedef float floatT; +typedef double doubleT; + +typedef char charT; +typedef string stringT; + +typedef boolean booleanT; + +const longT cc1 = 1; +const shortT cc2 = 3; +const ::longT cc1b = -1; +const ::shortT cc2b = -3; + +const floatT cc5 = 1.9; +const doubleT cc6 = 1.9; +const floatT cc5b = -1.9; +const doubleT cc6b = -1.9; +const floatT cc5c = 1/(9+2) * 2; +const doubleT cc6c = 1.9-1; + +const booleanT cc7 = TRUE; +const booleanT cc7b = TRUE; +const booleanT cc7c = TRUE | FALSE; +const booleanT cc7d = TRUE & FALSE; +const booleanT cc7e = TRUE&TRUE | FALSE&TRUE; + + +const charT cc8 = 'c'; +const charT cc8b = '\n'; +const stringT cc9 = "hej"; +const stringT cc9b = "hejdu"; + + +// +// Check value casting +// +const long longC = -9; +const short shortC = -9; +const unsigned long ulongC = 1; +const unsigned short ushortC = 0; + +const float floatC = 5.1; +const double doubleC = -2.111; + +const long c20 = shortC; +const long c21 = ulongC; +const long c22 = ushortC; +const short c23 = ushortC; +const double c34 = floatC; + + + diff --git a/lib/ic/test/ic_SUITE_data/enum.idl b/lib/ic/test/ic_SUITE_data/enum.idl new file mode 100644 index 0000000000..c164e4bf74 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/enum.idl @@ -0,0 +1,32 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + + +enum E1 {kalle, sune}; + +enum E2 { el0, el1, el2, el3, el4, el5, el6, el7, el8, el9, el10, el11, el12, el13, +el14, el15, el16, el17, el18, el19, el20, el21, el22, el23, el24, el25, el26, el27, +el28, el29, el30, el31, el32, el33, el34, el35, el36, el37, el38, el39, el40, el41, +el42, el43, el44, el45, el46, el47, el48, el49, el50, el51, el52, el53, el54, el55, +el56, el57, el58, el59}; + + + + + diff --git a/lib/ic/test/ic_SUITE_data/forward.idl b/lib/ic/test/ic_SUITE_data/forward.idl new file mode 100644 index 0000000000..1e16265af5 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/forward.idl @@ -0,0 +1,34 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Check that forward declarations are handled correctly +// + + +interface i1; + + +interface i1 { + typedef long T; +}; + + +interface i1; + diff --git a/lib/ic/test/ic_SUITE_data/include.idl b/lib/ic/test/ic_SUITE_data/include.idl new file mode 100644 index 0000000000..24022bfa1e --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/include.idl @@ -0,0 +1,30 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// Check that errors are given with the correct file name reference + +#include "include2.idl" + + +typedef T1 T7; +typedef long T7; +typedef long T111; + + + diff --git a/lib/ic/test/ic_SUITE_data/include2.idl b/lib/ic/test/ic_SUITE_data/include2.idl new file mode 100644 index 0000000000..2f8f7fd62c --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/include2.idl @@ -0,0 +1,26 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// Check that errors are given with the correct file name reference + +#include "include3.idl" + + +typedef T7 T1; + diff --git a/lib/ic/test/ic_SUITE_data/include3.idl b/lib/ic/test/ic_SUITE_data/include3.idl new file mode 100644 index 0000000000..c5f89c6c63 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/include3.idl @@ -0,0 +1,25 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// Check that errors are given with the correct file name reference + +typedef T7 T1; + + + diff --git a/lib/ic/test/ic_SUITE_data/inherit.idl b/lib/ic/test/ic_SUITE_data/inherit.idl new file mode 100644 index 0000000000..71b79c8748 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/inherit.idl @@ -0,0 +1,68 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + + +interface I1 { + typedef long T1; + typedef struct S1 {long a; boolean b;} T2; + typedef string StringT, StringT_arr[10]; + + T1 op1( in StringT a, inout char b, out StringT_arr c ); + T2 op2( in char a, inout char b, out StringT_arr c ); + + const T1 LongC = 10; + const StringT StringC = "Hola bambino"; + +}; + + +interface I2 : I1 { + T1 op3( in long a); + + const long c1 = LongC; + const string c2 = StringC; +}; + +interface I3 : I1 {}; + +interface I4 : I3, I2 {}; // Check that branced inherit works + + + +// Now use cnstants to check that inheritance works as expected + +module m1 { + interface I1 { + typedef long T1; + + const T1 c1 = 9; + }; + + interface I2 : I1 { + const T1 c2 = c1+5; // c2 = 14 + const long c3 = c2+c1+4; // c3 = 27 + }; + + interface I3 : I2, I1 { + const long c1 = 50; // Overrides I1::c1 + const T1 c4 = c1+c2+c3; // c4=91 + const T1 c5 = I1::c1+c1+c2+c3; // 100 + }; +}; + diff --git a/lib/ic/test/ic_SUITE_data/inherit_err.idl b/lib/ic/test/ic_SUITE_data/inherit_err.idl new file mode 100644 index 0000000000..4cfc3ffbff --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/inherit_err.idl @@ -0,0 +1,71 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Ops and attributes must not be redefined (shadowed) + +interface I1 { + long op1( in long a, inout char b, out boolean c ); + long op2( in char a, inout char b, out boolean c ); + attribute long a1, a2; + readonly attribute char a3; +}; + +interface I2 : I1 { + long op1( in float a, inout char b, out boolean c ); + long op2( in char a, inout char b, out boolean c ); + attribute long a1, a2; + readonly attribute char a3; +}; + +interface I3 : I1 { + long op3 (in string<19> b); +}; + + +interface I4 : I3 { + long op1( in float a, inout char b, out boolean c ); + long op2( in char a, inout char b, out boolean c ); + attribute long a1, a2; + readonly attribute char a3; + + long op3 (in string<19> b); +}; + + +interface I11 { + long op1( in float a, inout char b, out boolean c ); + long op2( in char a, inout char b, out boolean c ); + attribute long a1, a2; + readonly attribute char a3; +}; + + + +interface I5 : I1, I11 {}; + +interface I6 : I1 { + const long op1=0; + const long op2=0; + const long a1=0; + const long a2=0; + const long a3=0; +}; + + diff --git a/lib/ic/test/ic_SUITE_data/inherit_warn.idl b/lib/ic/test/ic_SUITE_data/inherit_warn.idl new file mode 100644 index 0000000000..502bfac8d4 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/inherit_warn.idl @@ -0,0 +1,64 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Checks that shadow warnings comes out as expected +// + + +interface I1 { + typedef long T1; + typedef struct S1 {long a; boolean b;} T2; + typedef string StringT, StringT_arr[10]; + + T1 op1( in StringT a, inout char b, out StringT_arr c ); + T2 op2( in char a, inout char b, out StringT_arr c ); + + const T1 LongC = 10; + const StringT StringC = "Hola bambino"; + +}; + + +interface I2 : I1 { + typedef char T1; // Shadows I1::T1 + const boolean StringC = FALSE; // shadows I1::StringC + + T1 op3( in long a); + + const long c1 = LongC; + const boolean c2 = StringC; +}; + +interface I3 : I2 {}; // More shadows + +interface I4 : I1 { + T1 op4(); + const T1 c2 = 66; +}; + +interface I5 : I4 { + typedef string T1; // Shadows I1::T1 + const char LongC = 'a'; // Shadows I1::LongC +}; + + +interface I6 : I4, I3 { +}; + diff --git a/lib/ic/test/ic_SUITE_data/mult_ids.idl b/lib/ic/test/ic_SUITE_data/mult_ids.idl new file mode 100644 index 0000000000..46deaa9f55 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/mult_ids.idl @@ -0,0 +1,92 @@ + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% +// +// Check that multiply defined identifiers are detected +// + +typedef long T1; +typedef long T1; +typedef long T2; +exception T2 {}; + + +//Exceptions +exception Exc1 {}; +exception Exc1 {}; + + +// Enums +enum E1 {kalle}; +enum E1 {kalle}; +enum E2 {kalle, sune, kalle}; + + +// Structs +struct S1 {long a;}; +struct S1 {long a;}; +struct S2 {long a; short a;}; +struct S3 {long a,b; short a;}; +struct S4 {long a,a; short a;}; + + +// Constants +const long c1 = 0; +const long c1 = 0; + + +// Interfaces + +interface i1 {}; +interface i1 {}; + +interface i2 { + attribute long a1; + attribute long a1; +}; + +interface i3 { + attribute long a1, a2; + attribute long a2; +}; + +interface i4 { + attribute long a1, a1; +}; + +interface i5 { + long op1(); + long op1(); + + long op2(in long a, inout char a); +}; + + +// Unions + +union U1 switch (long) {case 1: long a;}; +union U1 switch (long) {case 1: long a;}; + +union U2 switch (long) { +case 1: long a; +default: char a; +}; + + + + + diff --git a/lib/ic/test/ic_SUITE_data/nasty.idl b/lib/ic/test/ic_SUITE_data/nasty.idl new file mode 100644 index 0000000000..15fd523c0f --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/nasty.idl @@ -0,0 +1,60 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Checks nasty name collisions +// + +typedef string T; + + +#define nasty01 version +#define nasty02 preproc +#define nasty03 pragma +#define nasty04 compile +#define nasty05 if +#define nasty06 receive +#define nasty07 foldr +#define nasty08 length +#define nasty09 ID + +interface I1 { + attribute T nasty01; + attribute T nasty02; + attribute T nasty03; + attribute T nasty04; + attribute T nasty05; + attribute T nasty06; + attribute T nasty07; + attribute T nasty08; + attribute T nasty09; +}; + +interface I2 { + T nasty01(); + T nasty02(); + T nasty03(); + T nasty04(); + T nasty05(); + T nasty06(); + T nasty07(); + T nasty08(); + T nasty09(); +}; + diff --git a/lib/ic/test/ic_SUITE_data/one.idl b/lib/ic/test/ic_SUITE_data/one.idl new file mode 100644 index 0000000000..99281d6079 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/one.idl @@ -0,0 +1,29 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// Test oneway operations + +interface I1 { + long op1(in char a, inout boolean b, out string c); + oneway void op2(in char a, in boolean b, in string c); + oneway void op3(); +}; + + + diff --git a/lib/ic/test/ic_SUITE_data/one_followed.idl b/lib/ic/test/ic_SUITE_data/one_followed.idl new file mode 100644 index 0000000000..da8ee74e25 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/one_followed.idl @@ -0,0 +1,54 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% + +// Test oneway operations followed by other operations + +interface I1 { + oneway void op1(); + oneway void op2(in char a, in boolean b, in string c); + long op3(in char a, inout boolean b, out string c); +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/ic/test/ic_SUITE_data/one_out.idl b/lib/ic/test/ic_SUITE_data/one_out.idl new file mode 100644 index 0000000000..65f177ff22 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/one_out.idl @@ -0,0 +1,28 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// Test oneway operations not using in out params + +interface I1 { + oneway void op1(in char a, inout boolean b, in string c); + oneway void op2(in char a, out boolean b, in string c); +}; + + + diff --git a/lib/ic/test/ic_SUITE_data/one_raises.idl b/lib/ic/test/ic_SUITE_data/one_raises.idl new file mode 100644 index 0000000000..8290877363 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/one_raises.idl @@ -0,0 +1,32 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// Test oneway operations not using in out params + +exception hell {boolean burn; unsigned long for_how_long;}; +exception high_water {long mark;}; + +interface I1 { + oneway void op1(in char a) raises (hell); + oneway void op2(in char a) raises (hell); + oneway void op3() raises (hell, high_water); +}; + + + diff --git a/lib/ic/test/ic_SUITE_data/one_void.idl b/lib/ic/test/ic_SUITE_data/one_void.idl new file mode 100644 index 0000000000..e1d51c7abb --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/one_void.idl @@ -0,0 +1,30 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// Test oneway operations not using in out params + +typedef long T; + +interface I1 { + oneway char op1(in char a); + oneway T op2(in char a); +}; + + + diff --git a/lib/ic/test/ic_SUITE_data/raises_reg.idl b/lib/ic/test/ic_SUITE_data/raises_reg.idl new file mode 100644 index 0000000000..d4458811dc --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/raises_reg.idl @@ -0,0 +1,52 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#ifndef _RAISES_REG_IDL +#define _RAISES_REG_IDL + +module Raises_RegModule { + + exception Exception_1 {}; + + exception Exception_2 {}; + + interface R_R { + + void op() + raises(Raises_RegModule::Exception_1,Raises_RegModule::Exception_2); + + }; + +}; + +#endif + + + + + + + + + + + + + + + diff --git a/lib/ic/test/ic_SUITE_data/struct.idl b/lib/ic/test/ic_SUITE_data/struct.idl new file mode 100644 index 0000000000..337ee170e3 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/struct.idl @@ -0,0 +1,53 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + + +struct S1 { + long a; + char b; + string<9> s; +}; + +struct S2 { + long a; + struct S3 { + long a; + short b, b1; + char c; + } b; + sequence <S1> c, c2, c3, c4, c5, c6, c7; +}; + + +// Check that structs are detected down in other types + + +typedef struct s4 {long a;} T1; +union U1 switch (long) { +case 1: + struct S5 {unsigned short a;} a; +case 2: + union U2 switch (char) { + case 'a': + boolean a; + case 'b': + struct s6 {long a; boolean b;} c; + } b; +}; + diff --git a/lib/ic/test/ic_SUITE_data/syntax1.idl b/lib/ic/test/ic_SUITE_data/syntax1.idl new file mode 100644 index 0000000000..83c7de7943 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/syntax1.idl @@ -0,0 +1,28 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Check syntax errors +// + + +typedef long T1 _; + + + diff --git a/lib/ic/test/ic_SUITE_data/syntax2.idl b/lib/ic/test/ic_SUITE_data/syntax2.idl new file mode 100644 index 0000000000..10498206c1 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/syntax2.idl @@ -0,0 +1,27 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% +struct S2 { + long a_arr[99]; + struct S3 { + long a;_arr[99] + boolean b_arr[99]; + } b; +}; + + diff --git a/lib/ic/test/ic_SUITE_data/syntax3.idl b/lib/ic/test/ic_SUITE_data/syntax3.idl new file mode 100644 index 0000000000..69ab6b9783 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/syntax3.idl @@ -0,0 +1,20 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% +typdef long T1; + diff --git a/lib/ic/test/ic_SUITE_data/syntax4.idl b/lib/ic/test/ic_SUITE_data/syntax4.idl new file mode 100644 index 0000000000..077a251729 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/syntax4.idl @@ -0,0 +1,23 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% +union U1 switch (long) { +case 1: long a; +2: short b; +}; + diff --git a/lib/ic/test/ic_SUITE_data/syntax5.idl b/lib/ic/test/ic_SUITE_data/syntax5.idl new file mode 100644 index 0000000000..10af9fc18c --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/syntax5.idl @@ -0,0 +1,22 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% +union U1 switch (enum E1 {kalle, sune}) { +case kalle: long a; +sune: short b; +}; diff --git a/lib/ic/test/ic_SUITE_data/syntax6.idl b/lib/ic/test/ic_SUITE_data/syntax6.idl new file mode 100644 index 0000000000..dc15704d94 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/syntax6.idl @@ -0,0 +1,20 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +constant long c1 = 0; diff --git a/lib/ic/test/ic_SUITE_data/type.idl b/lib/ic/test/ic_SUITE_data/type.idl new file mode 100644 index 0000000000..67e1d502bd --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/type.idl @@ -0,0 +1,190 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Check all types in IDL +// + +typedef long T01; +typedef unsigned long T02; +typedef short T03; +typedef unsigned short T04; +typedef float T05; +typedef double T06; +typedef char T07; +typedef boolean T08; +typedef octet T09; +typedef any T10; +typedef Object T11; +typedef T01 T12; + +// Template types +typedef sequence <long> T21; +typedef sequence <unsigned long> T22; +typedef sequence <short, 2> T23; +typedef sequence <unsigned short, 6> T24; +typedef sequence <float, 12> T25; +typedef sequence <double> T26; +typedef sequence <char, 1> T27; +typedef sequence <boolean> T28; +typedef sequence <octet, 9> T29; +typedef sequence <any> T30; +typedef sequence <Object,2 > T31; +typedef sequence <T01> T32; +typedef sequence <sequence <sequence <T32> > > T33; + +struct S1 { + long a; + boolean b; +}; + +struct S2 { + long a; + struct S3 { + long a; + boolean b; + } b; +}; + +union U1 switch (enum E1 {kalle1, sune1}) { +case kalle1: long a; +default: boolean b; +case sune1: octet c; +}; + +union U2 switch (enum E2 {kalle2, sune2}) { +case kalle2: long a; +default: struct S4 { long a; short b;} b; +case sune2: octet c; +}; + +// Typedefs of above types + +typedef struct S11 { + long a; + boolean b; +} T41; + +typedef struct S21 { + long a; + struct S3 { + long a; + boolean b; + } b; +} T42; + +typedef union U11 switch (enum E3 {kalle3, sune3}) { +case kalle3: long a; +default: boolean b; +case sune3: octet c; +} T43; + +typedef union U21 switch (enum E4 {kalle4, sune4}) { +case kalle4: long a; +default: struct S4 { long a; short b;} b; +case sune4: octet c; +} T44; + + + + +// Array versions + +typedef long T01_arr[99]; +typedef unsigned long T02_arr[99]; +typedef short T03_arr[99]; +typedef unsigned short T04_arr[99]; +typedef float T05_arr[99]; +typedef double T06_arr[99]; +typedef char T07_arr[99]; +typedef boolean T08_arr[99]; +typedef octet T09_arr[99]; +typedef any T10_arr[99]; +typedef Object T11_arr[99]; +typedef T01 T12_arr[99]; + +typedef sequence <long> T21_arr[99]; +typedef sequence <unsigned long> T22_arr[99]; +typedef sequence <short, 2> T23_arr[99]; +typedef sequence <unsigned short, 6> T24_arr[99]; +typedef sequence <float, 12> T25_arr[99]; +typedef sequence <double> T26_arr[99]; +typedef sequence <char, 1> T27_arr[99]; +typedef sequence <boolean> T28_arr[99]; +typedef sequence <octet, 9> T29_arr[99]; +typedef sequence <any> T30_arr[99]; +typedef sequence <Object,2 > T31_arr[99]; +typedef sequence <T01> T32_arr[99]; +typedef sequence <sequence <sequence <T32> > > T33_arr[99]; + +struct S12 { + long a; + boolean b_arr[99]; +}; + +struct S22 { + long a_arr[99]; + struct S3 { + long a_arr[99]; + boolean b_arr[99]; + } b; +}; + +union U12 switch (enum E12 {kalle12, sune12}) { +case kalle12: long a_arr[99]; +default: boolean b; +case sune12: octet c; +}; + +union U22 switch (enum E22 {kalle22, sune22}) { +case kalle22: long a; +default: struct S4 { long a; short b;} b_arr[99]; +case sune22: octet c; +}; + +// Typedefs of above types + +typedef struct S13 { + long a_arr[99]; + boolean b; +} T41_arr[99]; + +typedef struct S23 { + long a; + struct S3 { + long a; + boolean b_arr[99]; + char c; + } b; +} T42_arr[99]; + +typedef union U13 switch (enum E13 {kalle13, sune13}) { +case kalle13: long a; +default: boolean b_arr[99]; +case sune13: octet c; +} T43_arr[99]; + +typedef union U23 switch (enum E23 {kalle23, sune23}) { +case kalle23: long a_arr[99]; +default: struct S4 { long a; short b;} b_arr[99]; +case sune23: octet c_arr[99]; +} T44_arr[99]; + + + diff --git a/lib/ic/test/ic_SUITE_data/typeid.idl b/lib/ic/test/ic_SUITE_data/typeid.idl new file mode 100644 index 0000000000..6e99f4a50d --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/typeid.idl @@ -0,0 +1,28 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +interface I1 {}; + +module M1 { interface I1 {};}; + +module M2 { module M1 { interface I1 {};};}; + +module M3 { module M2 { module M1 { interface I1 {};};};}; + + diff --git a/lib/ic/test/ic_SUITE_data/u_case_mult.idl b/lib/ic/test/ic_SUITE_data/u_case_mult.idl new file mode 100644 index 0000000000..3c30e144d8 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/u_case_mult.idl @@ -0,0 +1,54 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// Check that case labels are not duplicated + +union U1 switch (long) { +case 1 : long a; +case 1 : short b; +}; + +union U2 switch (char) { +case 'c' : long a; +case 'c' : short b; +}; + +union U2b switch (char) { +case 'c' : +case 'c' : long a; +case 'e': long b; +case 'c': long c; +}; + +union U3 switch (enum E1 {kalle, kula}) { +case kula : long a; +case kula : short b; +}; + +union U4 switch (boolean) { +case TRUE : long a; +case TRUE : short b; +}; + +union U5 switch (boolean) { +case TRUE : long a; +default: short p; +default: short pp; +}; + diff --git a/lib/ic/test/ic_SUITE_data/u_default.idl b/lib/ic/test/ic_SUITE_data/u_default.idl new file mode 100644 index 0000000000..e5d94a5e54 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/u_default.idl @@ -0,0 +1,51 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Checking that default labels are correct in TK +// + +interface i1 { + union U1 switch (long) { + default: long a; + case 1: case 2: long b; + }; + + union U2 switch (long) { + case 0: default: long a; + case 1: case 2: long b; + }; + + union U3 switch (long) { + case -1: long aa; + case 0: default: long a; + case 1: case 2: long b; + }; + + union U4 switch (long) { + case -1: long aa; + case 0: long a; + case 1: case 2: long b; + }; + + U1 op0(); + U2 op1(); + U3 op2(); + U4 op3(); +}; diff --git a/lib/ic/test/ic_SUITE_data/u_mult.idl b/lib/ic/test/ic_SUITE_data/u_mult.idl new file mode 100644 index 0000000000..b916861eec --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/u_mult.idl @@ -0,0 +1,61 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + + +// Check multiply defined declarators + +enum E2 {kal, kula, E1}; // legal, but used below + +// Now check that declarator a is multiply defined in all unions below +union U0 switch (long) { +case 0: long a; +case 1: short a; +}; +union U00 switch (char) { +case 'c' : long a; +case 'f' : char c; +case 'b' : short a; +}; +union U000 switch (boolean) { +case TRUE: long a; +case FALSE: short a; +}; +union U0000 switch (E2) { +case kal: long a; +case kula: short a; +}; + + + + +// Check that enum name duplication is found. + +union U1 switch (enum E1 {kalle, kula, E1}) { +case E1 : long a; // legal +case kalle : short E1; // illegal +}; + + +// This is legal, but ended up here anyway + +union U2 switch(::E2) { +case kal : long a; +case kula : short b; +default : boolean E1; +}; diff --git a/lib/ic/test/ic_SUITE_data/u_norm.idl b/lib/ic/test/ic_SUITE_data/u_norm.idl new file mode 100644 index 0000000000..e23796b8ca --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/u_norm.idl @@ -0,0 +1,63 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + + +union U1 switch (long) { +case 1: long a; +case 2: case 3: short b; +}; + + +union U2 switch (unsigned short) { +case 10: boolean a; +case 188: char b; +default: string c; +}; + + +union U3 switch (enum E1 {kalle, kula, boll}) { +case kalle: long a; +case kula: U2 b; +}; + +enum E2 {Cissi, Anders}; + +union U4 switch (::E2) { +case Cissi: U1 a; +default: case Anders: unsigned long b; +}; + +union U5 switch(char) { +case 'e': long a; +case 'b': case 'f': char b; +default: struct S {long a; boolean b;} c; +}; + + +// Now check that references can be used as case values + +const long c1 = 9; +const long c2 = 10; + +union U6 switch (long) { +case c1: boolean a; +case ::c2: boolean b; +}; + + diff --git a/lib/ic/test/ic_SUITE_data/u_type.idl b/lib/ic/test/ic_SUITE_data/u_type.idl new file mode 100644 index 0000000000..44e3326305 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/u_type.idl @@ -0,0 +1,82 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + + +// +// Check that case values match declared discriminator type +// + + +const long longC = 0; +const short shortC = 0; +const char charC = 'c'; +const string stringC = "Yacht"; + +enum E1 {kalle, kula}; + +union U1 switch (long) { +case 'c' : long a; +case TRUE : long b; +case stringC : long d; +case kalle : long f; +}; + +union U2 switch (unsigned long) { +case 'c' : long a; +case TRUE : long b; +case stringC : long d; +case kalle : long f; +}; + +union U3 switch (short) { +case 'c' : long a; +case TRUE : long b; +case stringC : long d; +case kalle : long f; +}; + +union U4 switch (unsigned short) { +case 'c' : long a; +case TRUE : long b; +case stringC : long d; +case kalle : long f; +}; + +union U5 switch (char) { +case TRUE : long b; +case stringC : long d; +case shortC : long e; +case kalle : long f; +}; + + +union U6 switch (E1) { +case 'c' : long a; +case TRUE : long b; +case stringC : long d; +case shortC : long e; +}; + +union U7 switch (enum E2 {ja, nej, kanske}) { +case 'c' : long a; +case TRUE : long b; +case stringC : long d; +case shortC : long e; +}; + diff --git a/lib/ic/test/ic_SUITE_data/undef_id.idl b/lib/ic/test/ic_SUITE_data/undef_id.idl new file mode 100644 index 0000000000..01a35c4ef8 --- /dev/null +++ b/lib/ic/test/ic_SUITE_data/undef_id.idl @@ -0,0 +1,63 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1997-2010. 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% + +// +// Check that undefined ids are detected +// + +typedef T7 T1; + +const char c1 = ::c0; +const T01 c2 = 'h'; +const T7 c3 = 9; + +interface i1 { + T17 op(); + long op2( in T7 a); + attribute T7 a1, a2; + readonly attribute T17 a3; +}; + +union U1 switch (long) { +case 1: long a; +case ::g : short b; +}; + +union U2 switch (enum E1 {kalle, kula}) { +case kula1: long a; +case kalle : short b; +}; + +union U3 switch (long) { +case kula2: long a; +case ::E3::kalle : short b; +case ::E4::kalle : short c; +}; + +enum E2 {kalle2, kula2}; + +union U4 switch (E2) { +case kula1: long a; +case kula1: long b; +case c3: short c; +}; + + + + diff --git a/lib/ic/test/ic_be_SUITE.erl b/lib/ic/test/ic_be_SUITE.erl new file mode 100644 index 0000000000..e3caf7bdff --- /dev/null +++ b/lib/ic/test/ic_be_SUITE.erl @@ -0,0 +1,69 @@ +%% +%% %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% +%% +%% +%%%---------------------------------------------------------------------- +%%% Purpose : Test suite for the backends of the IDL compiler +%%%---------------------------------------------------------------------- + +-module(ic_be_SUITE). +-include("test_server.hrl"). + + +-export([all/1,plain/1]). + + +-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])). + + +%% Top of cases + +all(suite) -> [plain]. + + + +plain(doc) -> + ["Checking code for the plain backend."]; +plain(suite) -> []; +plain(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(slask), + File = filename:join(DataDir, plain), + + ?line ok = ic:gen(File,stdopts(OutDir)++[{be,erl_plain}]), + + ok. + + + + +%%-------------------------------------------------------------------- +%% +%% Utilities + + +stdopts(OutDir) -> + [{outdir, OutDir}, {maxerrs, infinity}]. + + + + + +to_list(X) when is_atom(X) -> atom_to_list(X); +to_list(X) -> X. + diff --git a/lib/ic/test/ic_be_SUITE_data/plain.idl b/lib/ic/test/ic_be_SUITE_data/plain.idl new file mode 100644 index 0000000000..ee0a995807 --- /dev/null +++ b/lib/ic/test/ic_be_SUITE_data/plain.idl @@ -0,0 +1,33 @@ + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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 m { + + struct s { + long x; + long y; + }; + + interface i { + + void foo( in s a, out short b ); + + }; + +}; + diff --git a/lib/ic/test/ic_pp_SUITE.erl b/lib/ic/test/ic_pp_SUITE.erl new file mode 100644 index 0000000000..d68242bf3a --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE.erl @@ -0,0 +1,647 @@ +%% +%% %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% +%% +%% +%%---------------------------------------------------------------------- +%% Purpose : Test suite for the IDL preprocessor +%%---------------------------------------------------------------------- + +-module(ic_pp_SUITE). +-include("test_server.hrl"). + + + +%% Standard options to the ic compiler, NOTE unholy use of OutDir + +-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])). +-define(GCC, "g++"). +-define(GCC_VER, "2.95.3"). + +-export([all/1]). +-export([arg/1]). +-export([arg_norm/1]). +-export([cascade/1]). +-export([cascade_norm/1]). +-export([comment/1]). +-export([comment_norm/1]). +-export([concat/1]). +-export([concat_norm/1]). +-export([define/1]). +-export([define_norm/1]). +-export(['if'/1]). +-export([if_norm/1]). +-export([if_zero/1]). +-export([misc/1]). +-export([misc_norm/1]). +-export([improp_nest_constr/1]). +-export([improp_nest_constr_norm/1]). +-export([inc/1]). +-export([inc_norm/1]). +-export([line/1]). +-export([line_norm/1]). +-export([nopara/1]). +-export([nopara_norm/1]). +-export([predef/1]). +-export([predef_norm/1]). +-export([predef_time/1]). +-export([predef_time_norm/1]). +-export([self_ref/1]). +-export([self_ref_norm/1]). +-export([separate/1]). +-export([separate_norm/1]). +-export([swallow_sc/1]). +-export([swallow_sc_norm/1]). +-export([unintended_grp/1]). +-export([unintended_grp_norm/1]). +-export([cases/0, init_all/1, finish_all/1]). + + +all(doc) -> ["Preprocessing tests for IC"]; +all(suite) -> + {req, [], {conf, init_all, cases(), finish_all}}. + +init_all(Config) -> + if + is_list(Config) -> + case os:type() of + {win32, _} -> + {skipped, "Very unplesent to run on windows"}; + _ -> + check_gcc(Config) + end; + true -> + exit("Config not a list") + end. + +check_gcc(Config) -> + case os:find_executable(?GCC) of + false -> + {skipped, + lists:flatten(io_lib:format("Can not run without ~s in path", + [?GCC]))}; + _ -> + case trim(os:cmd(?GCC++" --version")) of + ?GCC_VER++[] -> + Config; + ?GCC_VER++[D|_] when is_integer(D), D>=$0, D=<$9 -> + fail_gcc(?GCC_VER++[D]); + ?GCC_VER++_ -> + Config; + Ver -> + fail_gcc(Ver) + end + end. + +fail_gcc(Ver) -> + {skipped, lists:flatten(io_lib:format("Need ~s v~s, not ~s", + [?GCC, ?GCC_VER, Ver]))}. + +trim(S) -> lists:reverse(skip_white(lists:reverse(skip_white(S)))). + +skip_white([$\s|T]) -> skip_white(T); +skip_white([$\n|T]) -> skip_white(T); +skip_white([$\r|T]) -> skip_white(T); +skip_white([$\t|T]) -> skip_white(T); +skip_white(L) -> L. + + +finish_all(Config) -> + Config. + + +cases() -> + [arg, cascade, comment, concat, define, misc, 'if', improp_nest_constr, inc, + line, nopara, predef, predef_time, self_ref, separate, swallow_sc, + unintended_grp]. + + + +%%-------------------------------------------------------------------- +%% arg +%%-------------------------------------------------------------------- + +arg(suite) -> [arg_norm]; +arg(doc) -> ["Check #define with some arguments"]. + +arg_norm(doc) -> ["Checks arguments for #define."]; +arg_norm(suite) -> []; +arg_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(arg_norm), + File = filename:join(DataDir, arg), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% cascade +%%-------------------------------------------------------------------- + +cascade(suite) -> [cascade_norm]; +cascade(doc) -> ["Check cascade #define"]. + +cascade_norm(doc) -> ["Check cascade #define."]; +cascade_norm(suite) -> []; +cascade_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(cascade_norm), + File = filename:join(DataDir, cascade), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% comment +%%-------------------------------------------------------------------- + +comment(suite) -> [comment_norm]; +comment(doc) -> ["Check comments"]. + +comment_norm(doc) -> ["Check comments."]; +comment_norm(suite) -> []; +comment_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(comment_norm), + File = filename:join(DataDir, comment), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% concat +%%-------------------------------------------------------------------- + +concat(suite) -> [concat_norm]; +concat(doc) -> ["Check concatinations, i.e ## "]. + +concat_norm(doc) -> ["Check concatinations, i.e ## ."]; +concat_norm(suite) -> []; +concat_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(concat_norm), + File = filename:join(DataDir, concat), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% define +%%-------------------------------------------------------------------- + +define(suite) -> [define_norm]; +define(doc) -> ["Check misceleaneous #define"]. + +define_norm(doc) -> ["Check misceleaneous #define."]; +define_norm(suite) -> []; +define_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(define_norm), + File = filename:join(DataDir, define), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% if +%%-------------------------------------------------------------------- + +'if'(suite) -> [if_norm, if_zero]; +'if'(doc) -> ["Check #if, #elif, and #endif. Note these are not implementen and will ~n + result in an error message from internal_pp"]. + +if_norm(doc) -> ["Check #if, #elif, and #endif. ."]; +if_norm(suite) -> []; +if_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(if_norm), + File = filename:join(DataDir, 'if'), + + ?line ok = test_file(File, DataDir), + ok. + +if_zero(doc) -> ["Check #if 0"]; +if_zero(suite) -> []; +if_zero(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(if_zero), + File = filename:join(DataDir, if_zero), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% inc +%%-------------------------------------------------------------------- + +inc(suite) -> [inc_norm]; +inc(doc) -> ["Check #include"]. + +inc_norm(doc) -> ["Check #include."]; +inc_norm(suite) -> []; +inc_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(inc_norm), + File = filename:join(DataDir, inc), + + ?line ok = test_file(File, DataDir), + ok. + + + +%%-------------------------------------------------------------------- +%% improp_nest_constr +%%-------------------------------------------------------------------- + +improp_nest_constr(suite) -> [improp_nest_constr_norm]; +improp_nest_constr(doc) -> ["Check improperly nested constructs"]. + +improp_nest_constr_norm(doc) -> ["Check improperly nested constructs."]; +improp_nest_constr_norm(suite) -> []; +improp_nest_constr_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(improp_nest_constr_norm), + File = filename:join(DataDir, improp_nest_constr), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% misc +%%-------------------------------------------------------------------- + +misc(suite) -> [misc_norm]; +misc(doc) -> ["Misceleaneous checks"]. + +misc_norm(doc) -> ["Misceleaneous checks."]; +misc_norm(suite) -> []; +misc_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(misc_norm), + File = filename:join(DataDir, misc), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% line +%%-------------------------------------------------------------------- + +line(suite) -> [line_norm]; +line(doc) -> ["Checks #line"]. + +line_norm(doc) -> ["Checks #line."]; +line_norm(suite) -> []; +line_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(line_norm), + File = filename:join(DataDir, line), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% nopara +%%-------------------------------------------------------------------- + +nopara(suite) -> [nopara_norm]; +nopara(doc) -> ["Checks #define with no parameters"]. + +nopara_norm(doc) -> ["Checks #define with no parameters."]; +nopara_norm(suite) -> []; +nopara_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(nopara_norm), + File = filename:join(DataDir, nopara), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% predef +%%-------------------------------------------------------------------- + +predef(suite) -> [predef_norm]; +predef(doc) -> ["Checks predefined macros. Note: not __TIME__ and __DATE__"]. + +predef_norm(doc) -> ["Checks predefined macros. Note: not __TIME__ and __DATE__."]; +predef_norm(suite) -> []; +predef_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(predef_norm), + File = filename:join(DataDir, predef), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% predef_time +%%-------------------------------------------------------------------- + +predef_time(suite) -> [predef_time_norm]; +predef_time(doc) -> ["Checks the predefined macros __TIME__ and __DATE__"]. + +predef_time_norm(doc) -> ["Checks the predefined macros __TIME__ and __DATE__."]; +predef_time_norm(suite) -> []; +predef_time_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(predef_time_norm), + File = filename:join(DataDir, predef_time), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% self_ref +%%-------------------------------------------------------------------- + +self_ref(suite) -> [self_ref_norm]; +self_ref(doc) -> ["Checks self referring macros"]. + +self_ref_norm(doc) -> ["Checks self referring macros."]; +self_ref_norm(suite) -> []; +self_ref_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(self_ref_norm), + File = filename:join(DataDir, self_ref), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% separate +%%-------------------------------------------------------------------- + +separate(suite) -> [separate_norm]; +separate(doc) -> ["Checks separete expansion of macro arguments"]. + +separate_norm(doc) -> ["Checks separete expansion of macro arguments."]; +separate_norm(suite) -> []; +separate_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(separate_norm), + File = filename:join(DataDir, separate), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% swallow_sc +%%-------------------------------------------------------------------- + +swallow_sc(suite) -> [swallow_sc_norm]; +swallow_sc(doc) -> ["Checks swallowing an undesirable semicolon"]. + +swallow_sc_norm(doc) -> ["Checks swallowing an undesirable semicolon."]; +swallow_sc_norm(suite) -> []; +swallow_sc_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(swallow_sc_norm), + File = filename:join(DataDir, swallow_sc), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% unintended_grp +%%-------------------------------------------------------------------- + +unintended_grp(suite) -> [unintended_grp_norm]; +unintended_grp(doc) -> ["Checks unintended grouping of arithmetic"]. + +unintended_grp_norm(doc) -> ["Checks unintended grouping of arithmetic."]; +unintended_grp_norm(suite) -> []; +unintended_grp_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(unintended_grp_norm), + File = filename:join(DataDir, unintended_grp), + + ?line ok = test_file(File, DataDir), + ok. + + + + + +test_file(FileT, DataDir) -> + case test_file_1(FileT, DataDir) of + ok -> ok; + Chars -> + io:put_chars(Chars), + {error,{FileT,DataDir}} + end. + +test_file_1(FileT, DataDir) -> + Tok = string:tokens(FileT, "/"), + FileName = lists:last(Tok), + File = FileT++".idl", + + ?line test_server:format("File ~p~n",[File]), + ?line test_server:format("FileName ~p~n",[FileName]), + + Flags = "-I"++DataDir, + + ?line test_server:format("Flags ~p~n",[Flags]), + + ?line Erl = pp_erl(File, Flags), + ?line Gcc = pp_gcc(File, Flags), + + ?line case Erl of + {error,_ErlError} -> + ?line test_server:format("Internal_pp Result ~n==================~n~p~n~n",[Erl]); + {warning, _ErlWar} -> + ?line test_server:format("Internal_pp Result ~n==================~n~p~n~n",[Erl]); + _ -> + ?line test_server:format("Internal_pp Result ~n==================~n~s~n~n",[Erl]) + end, + + ?line case Gcc of + {error,GccError} -> + Error = string:tokens(GccError, "\n"), + ?line test_server:format(?GCC" Result ~n==========~n~p~n~n", + [Error]); + _ -> + ?line test_server:format(?GCC" Result ~n==========~n~s~n~n",[Gcc]) + end, + + + + ?line case {Erl,Gcc} of + {{warning,W}, {error,X}} -> + ?line case is_ok(W,X) of + yes -> + ok; + no -> + io_lib:format("Internal_pp found Warning = ~p ~n" + ?GCC" found Error = ~p~n",[W,X]) + end; + + + {{warning,W}, _} -> + io_lib:format(?GCC" did not find warnings while ~n" + "Internal_pp found the following Warning = ~p~n",[W]); + + {{error,E}, {error,X}} -> + ?line case is_ok(E,X) of + yes -> + ok; + no -> + io_lib:format("Internal_pp found Error = ~p ~n" + ?GCC" found Error = ~p~n",[E,X]) + end; + + {{error,E}, _} -> + ?line case FileName of + "if" -> + ?line case if_res(E) of + ok -> + ok; + _ -> + io_lib:format(?GCC" did not find errors while ~n" + "Internal_pp found the following Error = ~p~n",[E]) + end; + _ -> + io_lib:format(?GCC" did not find errors while ~n" + "Internal_pp found the following Error = ~p~n",[lists:flatten(E)]) + end; + + {_, {error,X}} -> + io_lib:format("Internal_pp did not find errors while ~n" + ?GCC" found the following Error = ~p~n",[X]); + + _ -> + + ?line file:write_file("/tmp/Erl.pp",list_to_binary(Erl)), + ?line file:write_file("/tmp/Gcc.pp",list_to_binary(Gcc)), + + ?line Res = os:cmd("diff -b -w /tmp/Erl.pp /tmp/Gcc.pp"), + ?line test_server:format("///////////{error,E} E ~p FileName~p~n",[Res,FileName]), + ?line case {Res, FileName} of + {[], _} -> + ?line test_server:format("Diff = [] OK!!!!!!~n"), + ok; + {_, "predef_time"} -> + Tokens = string:tokens(Res,"\n"), + ?line test_server:format("///////////{error,E} Tokens~p~n",[Tokens]), + case Tokens of + ["3c3",_,"---",_,"5c5",_,"---",_,"9c9",_,"---",_] -> + ok; + _ -> + io_lib:format("Diff Result = ~p~n",[Res]) + end; + _ -> + io_lib:format("Diff Result = ~p~n",[Res]) + end + end. + + + + + +pp_erl(File, Flags) -> + case ic_pp:run(File,Flags) of + {ok, [$#, $ , $1 | Rest], []} -> + [$#, $ , $1 | Rest]; + {ok, [$#, $ , $1 | _Rest], Warning} -> + {warning,Warning}; + {error,Error} -> + {error,Error} + end. + +pp_gcc(File, Flags) -> + Cmd = ?GCC" -x c++ -E", + Line = Cmd++" "++Flags++" "++File, + + case os:cmd(Line) of + [$#, $ , $1 | Rest] -> + [$#, $ , $1 | Rest]; + Res -> + + case string:str(Res,"# 1 \"") of + 0 -> + {error,Res}; + X -> + {error, string:sub_string(Res, 1, X-1)} + end + end. + + +is_ok([],_Gcc) -> + yes; +is_ok([{FileName,Line,Text}|T],Gcc) -> + Str = FileName++":"++integer_to_list(Line)++": "++Text, + case string:str(Gcc,Str) of + 0 -> + io:format("~n is_ok Internal_pp missed Error = ~s~n",[Str]), + no; + _X -> + is_ok(T,Gcc) + end; +is_ok([Str|T],Gcc) -> + case string:str(Gcc,Str) of + 0 -> + io:format("~n is_ok Internal_pp missed Error = ~s~n",[Str]), + no; + _X -> + is_ok(T,Gcc) + end. + + +to_list(X) when is_atom(X) -> atom_to_list(X); +to_list(X) -> X. + + + +if_res(E) -> + if_res(E,1). + +if_res([H|T],Nr) -> + %% Dir = "/clearcase/otp/libraries/ic/test/ic_pp_SUITE_data/if.idl", + case {Nr, H} of + {1, {_Dir, 2, "only '#if 0' is implemented at present"}} -> + if_res(T,Nr+1); + {2, {_Dir, 3, "only '#if 0' is implemented at present"}} -> + if_res(T,Nr+1); + {3, {_Dir, 5, "`else' command is not implemented at present"}} -> + if_res(T,Nr+1); + {4, {_Dir, 9, "`elif' command is not implemented at present"}} -> + if_res(T,Nr+1); + {5, {_Dir, 11, "`else' command is not implemented at present"}} -> + ok; + _ -> + error + end; +if_res(_, _) -> + error. + + + diff --git a/lib/ic/test/ic_pp_SUITE_data/arg.idl b/lib/ic/test/ic_pp_SUITE_data/arg.idl new file mode 100644 index 0000000000..b4d266121d --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/arg.idl @@ -0,0 +1,38 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define xstr (s) str(s) +#define str(s) #s +#define foo 4 + +xstr(foo); + +#define x(kalle)stina +x(kurt) +x + +#define y(kalle) stina +y(kurt) +y + +#define a(kalle) stina +a(kurt) +a + +#define b (kalle) stina +b(kurt) diff --git a/lib/ic/test/ic_pp_SUITE_data/cascade.idl b/lib/ic/test/ic_pp_SUITE_data/cascade.idl new file mode 100644 index 0000000000..8dff1ee99f --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/cascade.idl @@ -0,0 +1,29 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define BUFS 1020 +#define TABS BUFS +#undef BUFS +#define BUFS 37 + + +main() +{ + TABS; + +} diff --git a/lib/ic/test/ic_pp_SUITE_data/comment.idl b/lib/ic/test/ic_pp_SUITE_data/comment.idl new file mode 100644 index 0000000000..d2ca3e7872 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/comment.idl @@ -0,0 +1,72 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define T 12 +#define F T + +//comment +/*exception except {};*/ + +// comment + // comment +/* another */ + /* another */ +/* still +another */ + /* still + another */ +__LINE__ +/* yet \ + another */ +// yet \ + another +__LINE__ + +#include "all.c" +#include <all.c> +#include /* comment */ "all.c" +#include /* comment */ <all.c> +#include "all.c" /* comment */ +#include <all.c> /* comment */ +#include // "all.c" +#include // <all.c> +#include "all.c" // comment +#include <all.c> // comment +#include "all/*cc*/.c" +#include <all/*cc*/.c> + +main() +{ + printf(" %d \n",F); + a(); + +} +//comment +/*exception hell {};*/ +#undef T +#define T "3/*com\ +ment*/4" +a() +{ + printf(" %d \n",F); + printf(" %d \n",T); +} + +b() +{} + diff --git a/lib/ic/test/ic_pp_SUITE_data/concat.idl b/lib/ic/test/ic_pp_SUITE_data/concat.idl new file mode 100644 index 0000000000..b8527fadfc --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/concat.idl @@ -0,0 +1,60 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define sune kurt +#define a(name) a #name name##_command +#define b(name) b #name name## _command +#define c(name) c #name name ##_command +#define d(name) d #name name ## _command +#define e(name) e #name command ## _command +#define f(name) f #name command ## %_command +#define g(name) g #name name ## %_command +#define h(name) h #name %_command ## name +#define i(name) i #name name ## _ ## name +#define j(name) j #name name ## name +#define k(name) k #name name ## name +#define l(name) l #name !name ## name +#define m(name) m #name name ## !name +#define n(name) n #name !name ## !name +#define o(name) stina +#define p(name) name +#define q1(name) q1 #name j(name) ## j(name) +#define q2(name) q2 #name j(name) +#define q3(name) q3 #name !! ## j(name) +#define q4(name) q4 #name ## j(name) + +a(quit) +b(quit) +c(quit) +d(quit) +e(quit) +f(quit) +g(sune) +h(sune) +i(sune) +j(sune) +l(sune) +m(sune) +n(sune) +k(j(sune)) +k(o(sune)) +k(p(sune)) +q1(sune) +q2(sune) +q3(sune) +q4(sune) diff --git a/lib/ic/test/ic_pp_SUITE_data/define.idl b/lib/ic/test/ic_pp_SUITE_data/define.idl new file mode 100644 index 0000000000..6aac63dd1e --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/define.idl @@ -0,0 +1,41 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define 8 +#define +#define a +#define _a +#define b dfs +#define 9 fdas +#define a8 +#define A +#define (c) fadfas +#define )c) fadfas +#define % c) fadfas +#define d(p) kfdsa +#define e(p) sinus(p) +#warning warning line +#define w%er percent +#define q() no_para +#warning warning line +#undef +#undef 8 +#undef a +#undef b +#undef _a d(kk) + diff --git a/lib/ic/test/ic_pp_SUITE_data/if.idl b/lib/ic/test/ic_pp_SUITE_data/if.idl new file mode 100644 index 0000000000..c381fa73ee --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/if.idl @@ -0,0 +1,32 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define kurt 12 +#if !true +#if X == 1 +ett +#else +else +#endif +true +#elif kurt +trueelif +#else +trueelse +#endif +end diff --git a/lib/ic/test/ic_pp_SUITE_data/if_zero.idl b/lib/ic/test/ic_pp_SUITE_data/if_zero.idl new file mode 100644 index 0000000000..d715f9d61e --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/if_zero.idl @@ -0,0 +1,31 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#if 0 +pelle = mallan +#endif +pelle = stina +#if 0 +kalle = stina +#endif +kalle = mallan +#if 0 +kurt = fia +#endif +fia = kurt + diff --git a/lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl b/lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl new file mode 100644 index 0000000000..463ee3c695 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl @@ -0,0 +1,30 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define double(x) (2*(x)) +#define call_with_1(x) x(1) + +#define strange(file) fprintf (file, "%s %d", + +main() +{ + call_with_1(double); + strange(stderr) p, 35) + +} + diff --git a/lib/ic/test/ic_pp_SUITE_data/inc.idl b/lib/ic/test/ic_pp_SUITE_data/inc.idl new file mode 100644 index 0000000000..0dcd637082 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/inc.idl @@ -0,0 +1,68 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% + +int x; + +#include "head.h" +#warning line nr +main() +{ + printf(test()); +} + + + + + + + + +#define C false +#define Z on +#include "inc2.h" +#undef Z +"Ca" C +"Za" Z +#include "inc2.h" +"Cb" C +"Zb" Z + +main() +{ +#define Q(a,b) sinus(a,b kurt ## b) + if (Q(34,56)=='NULL') printf(" T AAA%sEEEE \n",Q); + printf(" %d \n",F); + a(); +} +//comment +/*exception +hell {};*/ +#undef T +#define T "3/*com\ment*/4" +#define T 33 +#define F again +a () +{ + printf(" %d \n",F); + printf(" %d \n",T); +} + +b() +{} + diff --git a/lib/ic/test/ic_pp_SUITE_data/included1.idl b/lib/ic/test/ic_pp_SUITE_data/included1.idl new file mode 100644 index 0000000000..4cd26c4543 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/included1.idl @@ -0,0 +1,35 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 2000-2010. 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% +#ifndef INCLUDED1_IDL +#define INCLUDED1_IDL + + +#ifndef SOMETHING +#endif + + +struct s { + + long l; + +}; + + + +#endif diff --git a/lib/ic/test/ic_pp_SUITE_data/included2.idl b/lib/ic/test/ic_pp_SUITE_data/included2.idl new file mode 100644 index 0000000000..7cc44eef3e --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/included2.idl @@ -0,0 +1,41 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 2000-2010. 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% +#ifndef INCLUDED2_IDL +#define INCLUDED2_IDL + +#include "included1.idl" + + +#ifdef SOMETHING +#endif + + +module m { + + struct t { + + s st; + + }; + + +}; + + +#endif diff --git a/lib/ic/test/ic_pp_SUITE_data/includer.idl b/lib/ic/test/ic_pp_SUITE_data/includer.idl new file mode 100644 index 0000000000..c6ebc234e8 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/includer.idl @@ -0,0 +1,45 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 2000-2010. 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% +#ifndef INCLUDER_IDL +#define INCLUDER_IDL + +#include "included1.idl" +#include "included2.idl" + +#ifdef SOMETHING +#endif + + + +module n { + + interface j { + + s op(in m::t inpar); + + }; + +}; + + + + +#endif + + diff --git a/lib/ic/test/ic_pp_SUITE_data/line.idl b/lib/ic/test/ic_pp_SUITE_data/line.idl new file mode 100644 index 0000000000..5bd9c9446d --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/line.idl @@ -0,0 +1,45 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#line +#line 8 +#line 8a +#line 12 abc.c +#line 12 "kurt.c" +#warning fdafdsaf + + +#define T 12 +#define F T +#define Q(a) sinus(a) +#undef Q +# +#line 12 +#warning test of warning +#warning second of warning +#warning third of warning +#pragma kurt +#ident kurt +#kurt fdsafd +#line 20 +main() +{ + if (Q(34,56)=='NULL') printf(" T AAA%sEEEE \n",Q); + printf(" %d \n",F); +} +sune diff --git a/lib/ic/test/ic_pp_SUITE_data/misc.idl b/lib/ic/test/ic_pp_SUITE_data/misc.idl new file mode 100644 index 0000000000..9c18610fcf --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/misc.idl @@ -0,0 +1,44 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define str(s) #s +str(fool); +str(foo); +str(kurt); +#define xstr(s) str(s) +#define foo 4 +#define kurt sune +#define sune 17 + +xstr(fool); +xstr(foo); +xstr(kurt); + +#define a(b) b #8b +#define r(b) b # +#define t(b) b ## a +a(sinus) + +#define ww #www +ww + +#define x 14 + y +#define y 12 + #x +x + +#define e(a) cosinus(a) diff --git a/lib/ic/test/ic_pp_SUITE_data/nopara.idl b/lib/ic/test/ic_pp_SUITE_data/nopara.idl new file mode 100644 index 0000000000..1bb137da11 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/nopara.idl @@ -0,0 +1,35 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#11a +#define xstr str(s) + kurt*2; +#define asdf pragma +#asdf +#define asd #pragma asd + +#10 +#12 8kurt + +#define sss "stringing in the rain" +#define ddd "string +ing in the rain" asd +#line 20 +#include "head.h" qqqq +#include %!# +#include <sys.h> + diff --git a/lib/ic/test/ic_pp_SUITE_data/predef.idl b/lib/ic/test/ic_pp_SUITE_data/predef.idl new file mode 100644 index 0000000000..d8abcb25d5 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/predef.idl @@ -0,0 +1,33 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define b(q,w) kurt q w + + +b(__LINE__, __FILE__) +__LINE__ +__FILE__ + + + +b(__INCLUDE_LEVEL__, __BASE_FILE__) +__INCLUDE_LEVEL__ +__BASE_FILE__ + +Line __LINE__ +#include "predef.h" diff --git a/lib/ic/test/ic_pp_SUITE_data/predef_time.idl b/lib/ic/test/ic_pp_SUITE_data/predef_time.idl new file mode 100644 index 0000000000..05e3ba9175 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/predef_time.idl @@ -0,0 +1,24 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define b(q,w) kurt q w +b(__DATE__, __TIME__) +__DATE__ +__TIME__ + +#include "predef_time.h" diff --git a/lib/ic/test/ic_pp_SUITE_data/self_ref.idl b/lib/ic/test/ic_pp_SUITE_data/self_ref.idl new file mode 100644 index 0000000000..a44666272e --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/self_ref.idl @@ -0,0 +1,26 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define foo (4 + foo) + + +main() +{ + foo; + +} diff --git a/lib/ic/test/ic_pp_SUITE_data/separate.idl b/lib/ic/test/ic_pp_SUITE_data/separate.idl new file mode 100644 index 0000000000..a3faf9b986 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/separate.idl @@ -0,0 +1,37 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define xstr(s) str(s) +#define str(s) #s +#define foo 4 +#define str1(s) #s lose(s) +#define foo1 4 + +main() +{ + str(foo); + str1(foo1); + xstr(foo); + +#define qxstr(s) qstr(s) + qxstr(qfoo); +#define qstr(s) #s + qstr( 4 ) ; +#define qfoo 4 + qstr(qfoo); +} diff --git a/lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl b/lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl new file mode 100644 index 0000000000..71ed329ca6 --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl @@ -0,0 +1,37 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +/* comment \ + ends */ +// comment\ +ends +Line __LINE__ +#define SKIP_SPACES(p, limit) \ +{register char *lim = (limit); \ + while (p != lim) { \ + if (*p++ != ' ') { \ + p--; break; }}} + + +main() +{ + if (*p != 0) + SKIP_SPACES (ppp, lim); + else + a = 17; +} diff --git a/lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl b/lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl new file mode 100644 index 0000000000..3618bab1bc --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl @@ -0,0 +1,29 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +#define ceil_div( xz, yz) (xz + yz - 1) / yz +#define ceil_div2(xz, yz) ((xz) + (yz) - 1) / (yz) + +#define b kurt + +main() +{ + ceil_div(b & c, sizeof(int)); + ceil_div2(b & c, sizeof(int)); + +} diff --git a/lib/ic/test/ic_pragma_SUITE.erl b/lib/ic/test/ic_pragma_SUITE.erl new file mode 100644 index 0000000000..0edb5d4717 --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE.erl @@ -0,0 +1,295 @@ +%% +%% %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: ic_pragma_SUITE.erl +%% +%% Description: +%% Test suite for the IFR object registration when +%% pragmas are engaged +%% +%%----------------------------------------------------------------- +-module(ic_pragma_SUITE). + +-include("test_server.hrl"). +-include_lib("orber/include/corba.hrl"). +%%----------------------------------------------------------------- +%% External exports +%%----------------------------------------------------------------- +-export([all/1, init_all/1, finish_all/1]). +-export([ifr_pragma_reg/1, pragma_error/1, uggly_pragmas/1]). + + +%%----------------------------------------------------------------- +%% Macros +%%----------------------------------------------------------------- +-define(REMAP_EXCEPT(F), case catch F of + {'EXCEPTION', E} -> exit(E); + R -> R + end). +%% Standard options to the ic compiler, NOTE unholy use of OutDir + +-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])). + + +%%----------------------------------------------------------------- +%% Func: all/1 +%% Args: +%% Returns: +%%----------------------------------------------------------------- +all(doc) -> ["Description", "more description"]; +all(suite) -> {req, + [mnesia], + {conf, init_all, cases(), finish_all}}. + +cases() -> + [ifr_pragma_reg,pragma_error,uggly_pragmas]. + +%%----------------------------------------------------------------- +%% Init and cleanup functions. +%%----------------------------------------------------------------- +init_all(Config) -> + io:format("Setting up.....~n"), + mnesia:stop(), + mnesia:delete_schema([node()]), + mnesia:create_schema([node()]), + mnesia:start(), + orber:install([node()]), + orber:start(), + if + is_list(Config) -> + Config; + true -> + exit("Config not a list") + end. + +finish_all(Config) -> + io:format("Setting down.....~n"), + orber:stop(), + orber:uninstall(), + mnesia:stop(), + mnesia:delete_schema([node()]), + Config. + + + + +%%----------------------------------------------------------------- +%% Test Case: IFR registration with pragmas +%%----------------------------------------------------------------- +ifr_pragma_reg(doc) -> + ["Checks that IFR object is correctly registered under pragma engagement."]; +ifr_pragma_reg(suite) -> []; +ifr_pragma_reg(Config) when is_list(Config) -> + ?REMAP_EXCEPT(ifr_pragma_reg_run(Config)). + +ifr_pragma_reg_run(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(ifr_pragma_reg), + File0 = filename:join(DataDir, reg_m0), + ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}]), + ?line ok = compile(OutDir, ifr_pragma_files()), + code:add_pathz(OutDir), + + %% OE_register for all files + ?line ok = 'oe_reg_m0':'oe_register'(), + + %% Pragma registration test + OE_IFR = orber_ifr:find_repository(), + io:format("~n##### Starting the test case #####~n"), + check_pragma_effect(OE_IFR,"IDL:M1/T1:1.0"), + check_pragma_effect(OE_IFR,"DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3"), + check_pragma_effect(OE_IFR,"IDL:P2/T3:1.0"), + check_pragma_effect(OE_IFR,"IDL:P1/M2/T4:2.4"), + + %% OE_unregister for all files + ?line ok = 'oe_reg_m0':'oe_unregister'(), + code:del_path(OutDir), + ok. + + +ifr_pragma_files() -> ['oe_reg_m0']. + + +check_pragma_effect(OE_IFR,ID) -> + io:format("Checking for existance of : ~s~n",[ID]), + case orber_ifr:lookup_id(OE_IFR,ID) of + [] -> + test_server:fail(ID ++ " does not exist"), + false; + {Def,_} -> + io:format("Id refers to = {~p,#Bin}~n",[Def]), + true + end. + + + + +%%----------------------------------------------------------------- +%% Test Case: Syntactical / Semantical error pragma definitions +%%----------------------------------------------------------------- +pragma_error(doc) -> + ["Finds errornous pragma definitions under compilation."]; +pragma_error(suite) -> []; +pragma_error(Config) when is_list(Config) -> + ?REMAP_EXCEPT(pragma_error_run(Config)). + +pragma_error_run(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(pragma_error), + File1 = filename:join(DataDir, reg_m1), + File2 = filename:join(DataDir, reg_m2), + File3 = filename:join(DataDir, reg_m3), + File4 = filename:join(DataDir, reg_m4), + File5 = filename:join(DataDir, reg_m5), + File6 = filename:join(DataDir, reg_m6), + + ?line error = ic:gen(File1, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + + ?line error = ic:gen(File2, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + + ?line error = ic:gen(File3, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + + ?line ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + + ?line error = ic:gen(File5, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + + ?line error = ic:gen(File6, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ok. + + + + +%%----------------------------------------------------------------- +%% Test Case: IFR registration with realy uggly placed pragmas +%%----------------------------------------------------------------- +uggly_pragmas(doc) -> + ["Checks that IFR object is correctly registered under really uggly pragma engagement."]; +uggly_pragmas(suite) -> []; +uggly_pragmas(Config) when is_list(Config) -> + ?REMAP_EXCEPT(uggly_pragmas_run(Config)). + +uggly_pragmas_run(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(ifr_pragma_reg), + File0 = filename:join(DataDir, uggly), + + ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}]), + + ?line ok = compile(OutDir, uggly_pragma_files()), + code:add_pathz(OutDir), + + %% OE_register for all files + ?line ok = 'oe_uggly':'oe_register'(), + + %% Pragma registration test + OE_IFR = orber_ifr:find_repository(), + io:format("~n##### Starting the test case #####~n"), + + check_pragma_effect(OE_IFR, "IDL:M:1.0"), + check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:10"), + check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:11"), + check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:17"), + check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:34"), + check_pragma_effect(OE_IFR, "IDL:Exc1:2.2"), + check_pragma_effect(OE_IFR, "IDL:Exc2:2.2"), + check_pragma_effect(OE_IFR, "IDL:S:1.0"), + check_pragma_effect(OE_IFR, "IDL:U:1.0"), + check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:23"), + + %% OE_unregister for all files + ?line ok = 'oe_uggly':'oe_unregister'(), + + code:del_path(OutDir), + ok. + + +uggly_pragma_files() -> ['oe_uggly']. + + + + +%%---------------------------- + + +stdopts(OutDir) -> + [{outdir, OutDir}, {maxerrs, infinity}]. + + +compile(Dir, Files) -> + compile(Dir, Files, []). + +compile(Dir, Files, Opts) -> + {ok, Cwd} = file:get_cwd(), + file:set_cwd(Dir), + io:format("Changing to ~p~n", [Dir]), + case catch do_compile(Files, Opts) of + ok -> + file:set_cwd(Cwd); + Err -> + file:set_cwd(Cwd), + test_server:fail(Err) + end. + +do_compile([], _Opts) -> ok; +do_compile([F | Fs], Opts) -> + io:format("Compiling ~p", [F]), + case compile:file(F, Opts) of + ok -> + io:format(" ok~n", []), + do_load(F, Opts), + do_compile(Fs, Opts); + {ok, _} -> + io:format(" ok~n", []), + do_load(F, Opts), + do_compile(Fs, Opts); + {ok, _, _} -> + io:format(" ok~n", []), + do_load(F, Opts), + do_compile(Fs, Opts); + Err -> + io:format(" error: ~p~n", [Err]), + Err + end. + +do_load(File, Opts) -> + case lists:member(load, Opts) of + true -> + io:format("Loading file ~p", [File]), + code:purge(File), + R = code:load_abs(File), + io:format("Loaded: ~p", [R]); + false -> + ok + end. + + +to_list(X) when is_atom(X) -> atom_to_list(X); +to_list(X) -> X. + + + diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl new file mode 100644 index 0000000000..80f0f2cdd1 --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl @@ -0,0 +1,77 @@ + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% + +// Normal pragmas + +module M1 { + + typedef long T1; + + typedef long T2; + +#pragma ID T2 "DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3" + +}; + + +#pragma prefix "P1" + +module M2 { + + module M3 { + +#pragma prefix "P2" + + interface I1 { + void Op( in short b, + out short c); + }; + typedef long T3; + }; + + + typedef long T4; + +#pragma version T4 2.4 + +}; + + + +/* + + Specified types with the following scoped names + and RepositoryIds + + ::M1::T1 IDL:M1/T1:1.0 + + ::M1::T2 DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3 + + ::M2::M3::T3 IDL:P2/T3:1.0 + + ::M2::T4 IDL:P1/M2/T4:2.4 + +*/ + + + + + + + + diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl new file mode 100644 index 0000000000..6c22788290 --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl @@ -0,0 +1,75 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// Bad pragma IDs + +// Completelly bad id +module M1 { + + typedef long T1; + + typedef long T2; + +#pragma ID T2 "CompletelyBadId" + +}; + + +// Bad id, should start with DCE +module M2 { + + typedef long T1; + + typedef long T2; + +#pragma ID T2 "BAD:d62207a2-011e-11ce-88b4-0800090b5d3e:3" + +}; + + +// Bad version in ID : not a short number +module M3 { + + typedef long T1; + + typedef long T2; + +#pragma ID T2 "DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:ABCD" + +}; + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl new file mode 100644 index 0000000000..1751751295 --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl @@ -0,0 +1,40 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// Bad pragma versions + + +// Bad major version : not a short number +module M1 { + + typedef long T4; + +#pragma version T4 2000000000.4 + +}; + +// Bad minor version : not a short number +module M2 { + + typedef long T4; + +#pragma version T4 2.4000000000000 + +}; + + diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl new file mode 100644 index 0000000000..b7c9da249f --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl @@ -0,0 +1,38 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// Bad pragma prefixs + +module M2 { + + module M3 { + +#pragma prefix P2 // Should be "P2" + + interface I1 { + void foo( in short b, + out short c); + }; + typedef long T3; + }; + + + typedef long T4; +}; + + diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl new file mode 100644 index 0000000000..0c7079e3dd --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl @@ -0,0 +1,64 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// Unrecognmizable pragmas + +module M1 { + + typedef long T1; + + typedef long T2; + + + // Should be ID directive + +#pragma ShouldBeId T2 "DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3" + +}; + + // Should be prefix directive + +#pragma ShouldBePrefix "P1" + +module M2 { + + module M3 { + + // Should be prefix directive + +#pragma ShouldBePrefix "P2" + + interface I1 { + void foo( in short b, + out short c); + }; + typedef long T3; + }; + + + typedef long T4; + + + // Should be version + +#pragma ShouldBeVersion T4 2.4 + +}; + + + diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl new file mode 100644 index 0000000000..cbf053fac4 --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl @@ -0,0 +1,28 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% + +// Version not in valid form : major.ninor + +module M1 { + + typedef long T4; + + #pragma version T4 2 + +}; diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl new file mode 100644 index 0000000000..b7c9da249f --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl @@ -0,0 +1,38 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// Bad pragma prefixs + +module M2 { + + module M3 { + +#pragma prefix P2 // Should be "P2" + + interface I1 { + void foo( in short b, + out short c); + }; + typedef long T3; + }; + + + typedef long T4; +}; + + diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl new file mode 100644 index 0000000000..349c13b244 --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl @@ -0,0 +1,62 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% + +// Very uggly pragmas + + +#pragma prefix "P1" // Normal pragma + +module M4 { + + module M5 { + +#pragma prefix "P2" // Inside a parameter list + + interface I1 { + void Op( + #pragma prefix "P2" // Inside a parameter list + in short b, + #pragma prefix "P2" // Inside a parameter list + out short c + #pragma prefix "P2" // Inside a parameter list + ); + }; + typedef long T3; + }; + +}; + + + +/* + + Specified types with the following scoped names + and RepositoryIds + + ::M4::M5::T3 IDL:P2/T3:1.0 + +*/ + + + + + + + + diff --git a/lib/ic/test/ic_pragma_SUITE_data/uggly.idl b/lib/ic/test/ic_pragma_SUITE_data/uggly.idl new file mode 100644 index 0000000000..8ed3ac57ec --- /dev/null +++ b/lib/ic/test/ic_pragma_SUITE_data/uggly.idl @@ -0,0 +1,204 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// Really uggly pragmas + + +struct S { + +#pragma ID TDL1 "LOCAL:SomeLocalId:1" +#pragma ID TDL1 "LOCAL:SomeLocalId:2" + +long a + +#pragma ID TDL1 "LOCAL:SomeLocalId:3" +#pragma ID TDL1 "LOCAL:SomeLocalId:4" + +; + +#pragma ID TDL1 "LOCAL:SomeLocalId:5" +#pragma ID TDL1 "LOCAL:SomeLocalId:6" + +long b + +#pragma ID TDL1 "LOCAL:SomeLocalId:7" +#pragma ID TDL1 "LOCAL:SomeLocalId:8" + +; + + +#pragma ID TDL1 "LOCAL:SomeLocalId:9" +#pragma ID TDL1 "LOCAL:SomeLocalId:10" + +}; + + +typedef long TDL1; + + +exception Exc1{ + +#pragma version Exc1 2.2 +#pragma ID TDL2 "LOCAL:SomeLocalId:11" + +}; + + +typedef long TDL2; + + +exception Exc2 { + +#pragma version Exc2 2.2 +#pragma ID TDL3 "LOCAL:SomeLocalId:11" + + long a + +#pragma ID TDL3 "LOCAL:SomeLocalId:12" +#pragma ID TDL3 "LOCAL:SomeLocalId:13" + + ; + +#pragma ID TDL3 "LOCAL:SomeLocalId:14" +#pragma ID TDL3 "LOCAL:SomeLocalId:15" + + long b + +#pragma ID TDL3 "LOCAL:SomeLocalId:16" + + ; + +#pragma ID TDL3 "LOCAL:SomeLocalId:17" + + +}; + +typedef long TDL3; + +enum E { +#pragma ID E "LOCAL:SomeLocalId:18" + a +#pragma ID E "LOCAL:SomeLocalId:19" + , +#pragma ID E "LOCAL:SomeLocalId:20" + b +#pragma ID E "LOCAL:SomeLocalId:21" +, +#pragma ID E "LOCAL:SomeLocalId:22" + c +#pragma ID E "LOCAL:SomeLocalId:23" +}; + + + +union U switch (long) { + +#pragma ID TDL4 "LOCAL:SomeLocalId:24" + + case 1: + +#pragma ID TDL4 "LOCAL:SomeLocalId:25" + + long a + +#pragma ID TDL4 "LOCAL:SomeLocalId:26" + +; + +#pragma ID TDL4 "LOCAL:SomeLocalId:27" + + case 2: + +#pragma ID TDL4 "LOCAL:SomeLocalId:28" + + case 3: + +#pragma ID TDL4 "LOCAL:SomeLocalId:29" + +long b + +#pragma ID TDL4 "LOCAL:SomeLocalId:30" + +; + +#pragma ID TDL4 "LOCAL:SomeLocalId:31" + + default : + +#pragma ID TDL4 "LOCAL:SomeLocalId:32" + +long c + +#pragma ID TDL4 "LOCAL:SomeLocalId:33" + +; + +#pragma ID TDL4 "LOCAL:SomeLocalId:34" + +}; + + +typedef long TDL4; + + + +module M { + + interface I { + + void fun1( + +#pragma version fun1 3.0 +#pragma ID TDL5 "LOCAL:SomeLocalId:35" + + in short b + +#pragma ID TDL5 "LOCAL:SomeLocalId:36" +#pragma ID TDL5 "LOCAL:SomeLocalId:37" + + , + +#pragma ID TDL5 "LOCAL:SomeLocalId:38" +#pragma ID TDL5 "LOCAL:SomeLocalId:39" + + out short c + +#pragma ID TDL5 "LOCAL:SomeLocalId:40" +#pragma ID TDL5 "LOCAL:SomeLocalId:41" + + ); + + + typedef long TDL5; + + + void fun2( + +#pragma ID TDL6 "LOCAL:SomeLocalId:42" +#pragma ID TDL6 "LOCAL:SomeLocalId:43" + + ); + + typedef long TDL6; + + }; + + + +}; + diff --git a/lib/ic/test/ic_register_SUITE.erl b/lib/ic/test/ic_register_SUITE.erl new file mode 100644 index 0000000000..ae7578199a --- /dev/null +++ b/lib/ic/test/ic_register_SUITE.erl @@ -0,0 +1,425 @@ +%% +%% %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: ic_register_SUITE.erl +%% +%% Description: +%% Test suite for the IFR object registration +%% +%%----------------------------------------------------------------- +-module(ic_register_SUITE). + +-include("test_server.hrl"). +-include_lib("orber/include/corba.hrl"). +%%----------------------------------------------------------------- +%% External exports +%%----------------------------------------------------------------- +-export([all/1, init_all/1, finish_all/1, ifr_reg_unreg/1]). +-export([ifr_inheritence_reg/1,ifr_reg_unreg_with_inheritence/1]). +-export([ifr_reg_unreg_with_inheritence_bad_order/1]). + +%%----------------------------------------------------------------- +%% Internal exports +%%----------------------------------------------------------------- +-export([]). + +%%----------------------------------------------------------------- +%% Macros +%%----------------------------------------------------------------- +-define(REMAP_EXCEPT(F), case catch F of + {'EXCEPTION', E} -> exit(E); + R -> R + end). +%% Standard options to the ic compiler, NOTE unholy use of OutDir + +-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])). + + +%%----------------------------------------------------------------- +%% Func: all/1 +%% Args: +%% Returns: +%%----------------------------------------------------------------- +all(doc) -> ["Description", "more description"]; +all(suite) -> {req, + [mnesia], + {conf, init_all, cases(), finish_all}}. + +cases() -> + [ifr_reg_unreg,ifr_reg_unreg_with_inheritence, + ifr_reg_unreg_with_inheritence_bad_order,ifr_inheritence_reg]. + +%%----------------------------------------------------------------- +%% Init and cleanup functions. +%%----------------------------------------------------------------- + +init_all(Config) -> + io:format("Setting up.....~n"), + mnesia:stop(), + mnesia:delete_schema([node()]), + mnesia:create_schema([node()]), + mnesia:start(), + orber:install([node()]), + orber:start(), + if + is_list(Config) -> + Config; + true -> + exit("Config not a list") + end. + +finish_all(Config) -> + io:format("Setting down.....~n"), + orber:stop(), + orber:uninstall(), + mnesia:stop(), + mnesia:delete_schema([node()]), + Config. + + + +%%----------------------------------------------------------------- +%% Test Case: IFR type registration +%%----------------------------------------------------------------- +ifr_reg_unreg(doc) -> + ["Checks that the generated register/unregister " + "code for the IFR is correct."]; +ifr_reg_unreg(suite) -> []; +ifr_reg_unreg(Config) when is_list(Config) -> + ?REMAP_EXCEPT(ifr_reg_unregt_run(Config)). + +ifr_reg_unregt_run(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(ifr_reg_unreg), + File0 = filename:join(DataDir, reg_m8), + File1 = filename:join(DataDir, reg_m9), + File2 = filename:join(DataDir, reg_m10), + ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File0, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = compile(OutDir, ifr_reg_unreg_files()), + code:add_pathz(OutDir), + ?line ok = 'oe_reg_m8':'oe_register'(), + ?line ok = 'oe_reg_m9':'oe_register'(), + ?line ok = 'oe_reg_m10':'oe_register'(), + ?line ok = 'oe_reg_m10':'oe_unregister'(), + ?line ok = 'oe_reg_m9':'oe_unregister'(), + ?line ok = 'oe_reg_m8':'oe_unregister'(), + code:del_path(OutDir), + ok. + +ifr_reg_unreg_files() -> ['oe_reg_m8', 'oe_reg_m9', 'oe_reg_m10']. + + + +%%----------------------------------------------------------------- +%% Test Case: IFR registration when object inheritence +%% is applied and registered. +%%----------------------------------------------------------------- +ifr_reg_unreg_with_inheritence(doc) -> + ["Checks that the generated register/unregister " + "code for the IFR is correct, and works even when" + "the object inheritence is registered. This fixes" + "two bugs in ifr that caused crash when trying to" + "use OE_register/OE_unregister in a sequence of" + "compiled files that contained interfaces who" + "inherited others in sequence."]; +ifr_reg_unreg_with_inheritence(suite) -> []; +ifr_reg_unreg_with_inheritence(Config) when is_list(Config) -> + ?REMAP_EXCEPT(ifr_reg_unreg_with_inheritence_run(Config)). + +ifr_reg_unreg_with_inheritence_run(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(ifr_reg_unreg), + File0 = filename:join(DataDir, reg_m8), + File1 = filename:join(DataDir, reg_m9), + File2 = filename:join(DataDir, reg_m10), + File3 = filename:join(DataDir, reg_m11), + File4 = filename:join(DataDir, reg_m12), + ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File0, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File3, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File3, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File4, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = compile(OutDir, ifr_reg_unreg_with_inheritence_files()), + code:add_pathz(OutDir), + ?line ok = 'oe_reg_m8':'oe_register'(), + ?line ok = 'oe_reg_m9':'oe_register'(), + ?line ok = 'oe_reg_m10':'oe_register'(), + ?line ok = 'oe_reg_m11':'oe_register'(), + ?line ok = 'oe_reg_m12':'oe_register'(), + ?line ok = 'oe_reg_m8':'oe_unregister'(), + ?line ok = 'oe_reg_m9':'oe_unregister'(), + ?line ok = 'oe_reg_m10':'oe_unregister'(), + ?line ok = 'oe_reg_m11':'oe_unregister'(), + ?line ok = 'oe_reg_m12':'oe_unregister'(), + code:del_path(OutDir), + ok. + +ifr_reg_unreg_with_inheritence_files() -> + ['oe_reg_m8', 'oe_reg_m9', 'oe_reg_m10', 'oe_reg_m11', 'oe_reg_m12']. + + + + + +%%----------------------------------------------------------------- +%% Test Case: IFR registration when object inheritence +%% is applied and registered in a bad order. +%% Modules included and used from an ifr object +%% are not allready registered when the current +%% object is getting registered. +%%----------------------------------------------------------------- +ifr_reg_unreg_with_inheritence_bad_order(doc) -> + ["This tests that ifr registration is done with + the right write order." + "Modules included and used from an ifr object" + "are tested if allready registered when the " + "current object is getting registered."]; +ifr_reg_unreg_with_inheritence_bad_order(suite) -> []; +ifr_reg_unreg_with_inheritence_bad_order(Config) when is_list(Config) -> + ?REMAP_EXCEPT(ifr_reg_unreg_with_inheritence_bad_order_run(Config)). + +ifr_reg_unreg_with_inheritence_bad_order_run(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(ifr_reg_unreg), + File1 = filename:join(DataDir, reg_m9), + File2 = filename:join(DataDir, reg_m10), + File4 = filename:join(DataDir, reg_m12), + ?line ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File4, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = compile(OutDir, ifr_reg_unreg_with_inheritence_files()), + code:add_pathz(OutDir), + case catch 'oe_reg_m12':'oe_register'() of + {'EXIT',Reason1} -> + io:format("IFR object missing detected : ~p~n",[Reason1]), + true; + _ -> + test_server:fail("Failed to detect object missing : IDL:M1:1.0~n") + end, + ?line ok = 'oe_reg_m9':'oe_register'(), + case catch 'oe_reg_m10':'oe_register'() of + {'EXIT',Reason2} -> + io:format("IFR object missing detected : ~p~n",[Reason2]), + true; + _ -> + test_server:fail("Failed to detect object missing : IDL:M0:1.0~n") + end, + ?line ok = 'oe_reg_m9':'oe_unregister'(), + code:del_path(OutDir), + ok. + + + +%%----------------------------------------------------------------- +%% Test Case: IFR registration with inheritence +%%----------------------------------------------------------------- +ifr_inheritence_reg(doc) -> + ["Checks that IFR object inheritence is correctly registered."]; +ifr_inheritence_reg(suite) -> []; +ifr_inheritence_reg(Config) when is_list(Config) -> + ?REMAP_EXCEPT(ifr_inh_reg_run(Config)). + +ifr_inh_reg_run(Config) -> + DataDir = ?config(data_dir, Config), + OutDir = ?OUT(ifr_reg_unreg), + File0 = filename:join(DataDir, reg_m8), + File1 = filename:join(DataDir, reg_m9), + File2 = filename:join(DataDir, reg_m10), + File3 = filename:join(DataDir, reg_m11), + File4 = filename:join(DataDir, reg_m12), + ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File0, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File3, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File3, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags, + "-I" ++ DataDir}] ), + ?line {ok, []} = ic:gen(File4, stdopts(OutDir)++[silent2, {preproc_flags, + "-I" ++ DataDir}]), + ?line ok = compile(OutDir, ifr_reg_unreg_with_inheritence_files()), + code:add_pathz(OutDir), + %% OE_register for all files + ?line ok = 'oe_reg_m8':'oe_register'(), + ?line ok = 'oe_reg_m9':'oe_register'(), + ?line ok = 'oe_reg_m10':'oe_register'(), + ?line ok = 'oe_reg_m11':'oe_register'(), + ?line ok = 'oe_reg_m12':'oe_register'(), + + %% Inheritence registration test + OE_IFR = orber_ifr:find_repository(), + %% Interfaces that not inherit from other interfaces + ?line [] = get_inh(OE_IFR, "IDL:m0/i0:1.0"), + ?line [] = get_inh(OE_IFR, "IDL:m1/i1:1.0"), + ?line [] = get_inh(OE_IFR, "IDL:m3/i3:1.0"), + %% Interfaces that inherit from other interfaces + ?line ["IDL:m1/i1:1.0"] = get_inh(OE_IFR, "IDL:m2/i2:1.0"), + ?line ["IDL:m1/i1:1.0","IDL:m2/i2:1.0"] = get_inh(OE_IFR, "IDL:m4/i4:1.0"), + ?line ["IDL:m3/i3:1.0"] = get_inh(OE_IFR, "IDL:m4/i5:1.0"), + + %% OE_unregister for all files + ?line ok = 'oe_reg_m8':'oe_unregister'(), + ?line ok = 'oe_reg_m9':'oe_unregister'(), + ?line ok = 'oe_reg_m10':'oe_unregister'(), + ?line ok = 'oe_reg_m11':'oe_unregister'(), + ?line ok = 'oe_reg_m12':'oe_unregister'(), + code:del_path(OutDir), + ok. + + +get_inh(OE_IFR,ID) -> + OE_CURRENT = orber_ifr:lookup_id(OE_IFR,ID), + INH_LIST = orber_ifr:get_base_interfaces(OE_CURRENT), + case INH_LIST of + [] -> + io:format("~nInterface ~p inherits from nobody.~n",[ID]), + []; + _ -> + print_inh_list_ids(ID, INH_LIST, []) + end. + +print_inh_list_ids(_ID, [], Acc) -> + lists:reverse(Acc); +print_inh_list_ids(ID, [H|T], Acc) -> + io:format("~n"), + Parent = orber_ifr:get_id(H), + io:format("Interface ~p inherits from ~p.~n", [ID, Parent]), + print_inh_list_ids(ID, T, [Parent|Acc]). + + + + +stdopts(OutDir) -> + [{outdir, OutDir}, {maxerrs, infinity}]. + + +compile(Dir, Files) -> + compile(Dir, Files, []). + +compile(Dir, Files, Opts) -> + {ok, Cwd} = file:get_cwd(), + file:set_cwd(Dir), + io:format("Changing to ~p~n", [Dir]), + case catch do_compile(Files, Opts) of + ok -> + file:set_cwd(Cwd); + Err -> + file:set_cwd(Cwd), + test_server:fail(Err) + end. + +do_compile([], _Opts) -> ok; +do_compile([F | Fs], Opts) -> + io:format("Compiling ~p", [F]), + case compile:file(F, Opts) of + ok -> + io:format(" ok~n", []), + do_load(F, Opts), + do_compile(Fs, Opts); + {ok, _} -> + io:format(" ok~n", []), + do_load(F, Opts), + do_compile(Fs, Opts); + {ok, _, _} -> + io:format(" ok~n", []), + do_load(F, Opts), + do_compile(Fs, Opts); + Err -> + io:format(" error: ~p~n", [Err]), + Err + end. + +do_load(File, Opts) -> + case lists:member(load, Opts) of + true -> + io:format("Loading file ~p", [File]), + code:purge(File), + R = code:load_abs(File), + io:format("Loaded: ~p", [R]); + false -> + ok + end. + + +to_list(X) when is_atom(X) -> atom_to_list(X); +to_list(X) -> X. + + + + + + + + + + + + + + + + + + diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m10.idl b/lib/ic/test/ic_register_SUITE_data/reg_m10.idl new file mode 100644 index 0000000000..9c1f126b64 --- /dev/null +++ b/lib/ic/test/ic_register_SUITE_data/reg_m10.idl @@ -0,0 +1,37 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// +// IDL for testing register/unregister in the IFR when using included specs +// +#include "reg_m9.idl" + +typedef sequence<long> Sequence1; + +#include "reg_m8.idl" + +module m2 { + + interface i2 : m1::i1 + { + short op3( in long a, inout char b, out long c ); + }; + + +}; + diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m11.idl b/lib/ic/test/ic_register_SUITE_data/reg_m11.idl new file mode 100644 index 0000000000..607d695357 --- /dev/null +++ b/lib/ic/test/ic_register_SUITE_data/reg_m11.idl @@ -0,0 +1,32 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// +// IDL for testing register/unregister in the IFR when using included specs +// + +module m3 { + + interface i3 + { + short op4( in long a, inout char b, out long c ); + }; + + +}; + diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m12.idl b/lib/ic/test/ic_register_SUITE_data/reg_m12.idl new file mode 100644 index 0000000000..3dd9267655 --- /dev/null +++ b/lib/ic/test/ic_register_SUITE_data/reg_m12.idl @@ -0,0 +1,40 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// +// IDL for testing register/unregister in the IFR when using included specs +// Special case with multiple inheritence. +// +#include "reg_m10.idl" +#include "reg_m11.idl" + +module m4 { + + interface i4 : m2::i2 + { + short op5( in long a, inout char b, out long c ); + }; + + interface i5 : m3::i3 + { + short op6( in long a, inout char b, out long c ); + }; + + +}; + diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m8.idl b/lib/ic/test/ic_register_SUITE_data/reg_m8.idl new file mode 100644 index 0000000000..dc7432c05d --- /dev/null +++ b/lib/ic/test/ic_register_SUITE_data/reg_m8.idl @@ -0,0 +1,32 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// +// IDL for testing register/unregister in the IFR when using included specs +// +module m0 { + + interface i0 { + void op1( in short c ); + float op2( in char a); + + }; + + +}; + diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m9.idl b/lib/ic/test/ic_register_SUITE_data/reg_m9.idl new file mode 100644 index 0000000000..e937c41608 --- /dev/null +++ b/lib/ic/test/ic_register_SUITE_data/reg_m9.idl @@ -0,0 +1,32 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 1998-2010. 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% +// +// IDL for testing register/unregister in the IFR when using included specs +// +module m1 { + + interface i1 { + void op1( in short c ); + float op2( in char a); + + }; + + +}; + diff --git a/lib/ic/test/java_client_erl_server_SUITE.erl b/lib/ic/test/java_client_erl_server_SUITE.erl new file mode 100644 index 0000000000..ee77ef0c4e --- /dev/null +++ b/lib/ic/test/java_client_erl_server_SUITE.erl @@ -0,0 +1,330 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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% +%% +%% +%%%---------------------------------------------------------------------- +%%% Purpose : Test suite for the backends of the IDL compiler +%%%---------------------------------------------------------------------- + +-module(java_client_erl_server_SUITE). +-include("test_server.hrl"). + + +-export([all/1,init_all/1,finish_all/1,init_per_testcase/2,fin_per_testcase/2]). +-export([marshal_ll/1,marshal_ull/1, + marshal_l/1,marshal_ul/1, + marshal_s/1,marshal_us/1, + marshal_c/1,marshal_wc/1, + marshal_str/1, + marshal_any_3/1,marshal_any_2/1]). + + +%% Top of cases + +all(doc) -> + "Test of IC with a Java-client and an Erlang generic server. " + "The communication is via Erlang distribution."; +all(suite) -> {conf,init_all,cases(),finish_all}. + +cases() -> [marshal_ll,marshal_ull, + marshal_l,marshal_ul, + marshal_s,marshal_us, + marshal_c,marshal_wc, + marshal_str, + marshal_any_3,marshal_any_2]. + +init_all(Config) when is_list(Config) -> + case case code:priv_dir(jinterface) of + {error,bad_name} -> + false; + P -> + filelib:is_dir(P) + end + of + true -> + case find_executable(["java"]) of + false -> + {skip,"Found no Java VM"}; + Path -> + [{java,Path}|Config] + end; + false -> + {skip,"No jinterface application"} + end. + + +find_executable([]) -> + false; +find_executable([E|T]) -> + case os:find_executable(E) of + false -> find_executable(T); + Path -> Path + end. + +finish_all(Config) -> Config. + + + +%% Add/remove code path and watchdog before/after each test case. +%% +init_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:add_patha(DataDir), + + %% Since other test suites use the module m_i et,al, we have + %% to make sure we are using the right modules. + code:purge(m_i), + code:purge(m_i_impl), + code:purge(oe_java_erl_test), + code:load_file(m_i), + code:load_file(m_i_impl), + code:load_file(oe_java_erl_test), + + WatchDog = test_server:timetrap(test_server:seconds(20)), + [{watchdog, WatchDog}| Config]. + +fin_per_testcase(_Case, Config) -> + DataDir = ?config(data_dir, Config), + code:del_path(DataDir), + WatchDog = ?config(watchdog, Config), + test_server:timetrap_cancel(WatchDog). + + + +%%-------------------------------------------------------------------- +%% +%% Test cases + +marshal_ll(doc) -> + ["Testing marshalling of IDL long long"]; +marshal_ll(suite) -> []; +marshal_ll(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_ll}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_ll]), + ?line ok = m_i:stop(Server), + ok. + +marshal_ull(doc) -> + ["Testing marshalling of IDL unsigned long long"]; +marshal_ull(suite) -> []; +marshal_ull(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_ull}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_ull]), + ?line ok = m_i:stop(Server), + ok. + +marshal_l(doc) -> + ["Testing marshalling of IDL long"]; +marshal_l(suite) -> []; +marshal_l(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_l}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_l]), + ?line ok = m_i:stop(Server), + ok. + +marshal_ul(doc) -> + ["Testing marshalling of IDL unsigned long"]; +marshal_ul(suite) -> []; +marshal_ul(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_ul}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_ul]), + ?line ok = m_i:stop(Server), + ok. + +marshal_s(doc) -> + ["Testing marshalling of IDL short"]; +marshal_s(suite) -> []; +marshal_s(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_s}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_s]), + ?line ok = m_i:stop(Server), + ok. + +marshal_us(doc) -> + ["Testing marshalling of IDL unsigned short"]; +marshal_us(suite) -> []; +marshal_us(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_us}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_us]), + ?line ok = m_i:stop(Server), + ok. + +marshal_c(doc) -> + ["Testing marshalling of IDL char"]; +marshal_c(suite) -> []; +marshal_c(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_c}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_c]), + ?line ok = m_i:stop(Server), + ok. + +marshal_wc(doc) -> + ["Testing marshalling of IDL char"]; +marshal_wc(suite) -> []; +marshal_wc(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_wc}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_wc]), + ?line ok = m_i:stop(Server), + ok. + +marshal_str(doc) -> + ["Testing marshalling of IDL string"]; +marshal_str(suite) -> []; +marshal_str(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_str}), + ?line ok = java(?config(java, Config), DataDir, +%%% "-DOtpConnection.trace=4 " + "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_str]), + ?line ok = m_i:stop(Server), + ok. + +marshal_any_3(doc) -> + ["Testing marshalling of IDL any"]; +marshal_any_3(suite) -> []; +marshal_any_3(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_any_3}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_any_3]), + ?line ok = m_i:stop(Server), + ok. + +marshal_any_2(doc) -> + ["Testing marshalling of IDL any"]; +marshal_any_2(suite) -> []; +marshal_any_2(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_any_2}), + ?line ok = java(?config(java, Config), DataDir, "JavaClient", + ["JavaClient",node(),erlang:get_cookie(),marshal_any_2]), + ?line ok = m_i:stop(Server), + ok. + +%%-------------------------------------------------------------------- +%% +%% Utilities + + +java(Java, Dir, ClassAndArgs) -> + cmd(Java++" -classpath "++classpath(Dir)++" "++ClassAndArgs). + +java(Java, Dir, Class, Args) -> + java(Java, Dir, Class++" "++to_string(Args)). + +to_string([H|T]) when is_integer(H) -> + integer_to_list(H)++" "++to_string(T); +to_string([H|T]) when is_atom(H) -> + atom_to_list(H)++" "++to_string(T); +to_string([H|T]) when is_list(H) -> + lists:flatten(H)++" "++to_string(T); +to_string([]) -> []. + +% javac(Dir, File) -> +% cmd("javac -d "++Dir++" -classpath "++classpath(Dir)++" "++ +% filename:join(Dir, File)). + +classpath(Dir) -> + PS = + case os:type() of + {win32, _} -> ";"; + _ -> ":" + end, + Dir++PS++ + filename:join([code:lib_dir(ic),"priv","ic.jar"])++PS++ + filename:join([code:lib_dir(jinterface),"priv","OtpErlang.jar"])++PS++ + case os:getenv("CLASSPATH") of + false -> ""; + Classpath -> Classpath + end. + + +cmd(Cmd) -> + PortOpts = [{line,80},eof,exit_status,stderr_to_stdout], + io:format("<cmd> ~s~n", [Cmd]), + case catch open_port({spawn,Cmd}, PortOpts) of + Port when is_port(Port) -> + Result = cmd_loop(Port, []), + io:format("<cmd=~w>~n", [Result]), + case Result of + 0 -> ok; + ExitCode when is_integer(ExitCode) -> {error,ExitCode}; + Error -> Error + end; + {'EXIT',Reason} -> + {error,Reason} + end. + +cmd_loop(Port, Line) -> + receive + {Port,eof} -> + receive + {Port,{exit_status,ExitStatus}} -> + ExitStatus + after 1 -> + undefined + end; + {Port,{exit_status,ExitStatus}} -> + receive + {Port,eof} -> + ok after 1 -> ok end, + ExitStatus; + {Port,{data,{Tag,Data}}} -> + case Tag of + eol -> + io:put_chars([Line|cr_to_nl(Data)]), + io:nl(), + cmd_loop(Port, []); + noeol -> + cmd_loop(Port, [Line|cr_to_nl(Data)]) + end; + {'EXIT',Port,Reason} -> + {error,Reason}; + Other -> + io:format("WARNING: Unexpected at ~s:~p: ~p~n", + [?MODULE_STRING,?LINE,Other]), + cmd_loop(Port, Line) + end. + +%% Convert lonely CR to NL, and CRLF to NL +%% +cr_to_nl([$\r,$\n|T]) -> + [$\n|cr_to_nl(T)]; +cr_to_nl([$\r|T]) -> + [$\n|cr_to_nl(T)]; +cr_to_nl([C|T]) -> + [C|cr_to_nl(T)]; +cr_to_nl([]) -> + []. diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java b/lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java new file mode 100644 index 0000000000..1881279ac8 --- /dev/null +++ b/lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java @@ -0,0 +1,759 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2003-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% + * + */ +public class JavaClient { + + public static void main(String[] argv) + { + System.out.println("Hello World!"); + if (argv.length < 4) { + System.out.println("Too few arguments!"); + System.exit(1); + } + // for (int j = 0; j < argv.length; j++) + // System.out.println(argv[j]); + try { + if (argv[3].equals("marshal_ll")) { + System.out.println("marshal_ll"); + marshal_ll(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_ull")) { + marshal_ull(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_l")) { + marshal_l(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_ul")) { + marshal_ul(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_s")) { + marshal_s(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_us")) { + marshal_us(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_c")) { + marshal_c(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_wc")) { + marshal_wc(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_str")) { + marshal_str(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_any_3")) { + marshal_any_3(argv[0], argv[1], argv[2], argv[3]); + } + else if (argv[3].equals("marshal_any_2")) { + marshal_any_2(argv[0], argv[1], argv[2], argv[3]); + } + else { + System.out.println("Unknown test: "+argv[3]); + System.exit(2); + } + } catch (java.lang.Exception e) { + System.out.println("Exception!: "+e); + System.exit(3); + } + System.exit(0); + } + + + + static void marshal_ll(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + // Just warming up.. + System.out.println("Just warming up.."+i); + verify_ll(i, 3, 2, 1); + verify_ll(i, 5, 4, 3); + verify_ll(i, -128, 0, 1); + // The small integer border + verify_ll(i, 255, 0, 1); + verify_ll(i, 256, 0, 1); + // The integer border + verify_ll(i, (1L<<26)-1L, 0L, 1); + verify_ll(i, 1L<<26, 0L, 1); + verify_ll(i, -(1L<<26), 0L, 1); + verify_ll(i, (1L<<27)-1L, 0L, 1); + verify_ll(i, 1L<<27, 0L, 1); + verify_ll(i, -(1L<<27), 0L, 1); + // Bignum byte borders + verify_ll(i, (1L<<32)-1L, 0L, 1); + verify_ll(i, 1L<<32, 0L, 1); + verify_ll(i, -(1L<<32)+1L, 0L, 1); + verify_ll(i, -(1L<<32), 0L, 1); + verify_ll(i, (1L<<40)-1L, 0L, 1); + verify_ll(i, 1L<<40, 0L, 1); + verify_ll(i, -(1L<<40)+1L, 0L, 1); + verify_ll(i, -(1L<<40), 0L, 1); + verify_ll(i, (1L<<48)-1L, 0L, 1); + verify_ll(i, 1L<<48, 0L, 1); + verify_ll(i, -(1L<<48)+1L, 0L, 1); + verify_ll(i, -(1L<<48), 0L, 1); + // Java long border + verify_ll(i, java.lang.Long.MAX_VALUE, 0L, 1); + verify_ll(i, java.lang.Long.MIN_VALUE, 0L, 1); + verify_ll(i, -1L, 0L, 1); + // Impossible decodes + verify_ll_bad(i, java.lang.Long.MAX_VALUE, -1L, 1); + verify_ll_bad(i, java.lang.Long.MIN_VALUE, 1L, 1); + verify_ll_bad(i, java.lang.Long.MIN_VALUE, 0L, -1); + verify_ll_bad(i, java.lang.Long.MAX_VALUE, -1L, 2); + verify_ll_bad(i, java.lang.Long.MIN_VALUE, 0L, 2); + } + + static void marshal_ull(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + // Just warming up.. + verify_ull(i, 3, 2, 1); + verify_ull(i, 5, 4, 3); + // The small integer border + verify_ull(i, 255, 0, 1); + verify_ull(i, 256, 0, 1); + // The integer border + verify_ull(i, (1L<<26)-1L, 0L, 1); + verify_ull(i, 1L<<26, 0L, 1); + verify_ull(i, (1L<<27)-1L, 0L, 1); + verify_ull(i, 1L<<27, 0L, 1); + // Bignum byte borders + verify_ull(i, (1L<<32)-1L, 0L, 1); + verify_ull(i, 1L<<32, 0L, 1); + verify_ull(i, (1L<<40)-1L, 0L, 1); + verify_ull(i, 1L<<40, 0L, 1); + verify_ull(i, (1L<<48)-1L, 0L, 1); + verify_ull(i, 1L<<48, 0L, 1); + // Java long border + verify_ull(i, java.lang.Long.MAX_VALUE, 0L, 1); + verify_ull(i, java.lang.Long.MIN_VALUE, 0L, 1); + verify_ull(i, -1L, 0L, 1); + verify_ull(i, java.lang.Long.MAX_VALUE, + java.lang.Long.MIN_VALUE, 1); + // Impossible decodes + verify_ull_bad(i, -1L, -1L, 1); + verify_ull_bad(i, java.lang.Long.MAX_VALUE, -1L, 2); + } + + static void marshal_l(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + // Just warming up.. + verify_l(i, 3, 2, 1); + verify_l(i, 5, 4, 3); + verify_l(i, -128, 0, 1); + // The small integer border + verify_l(i, 255, 0, 1); + verify_l(i, 256, 0, 1); + // The integer border + verify_l(i, (1<<26)-1, 0, 1); + verify_l(i, 1<<26, 0, 1); + verify_l(i, -(1<<26), 0, 1); + verify_l(i, (1<<27)-1, 0, 1); + verify_l(i, 1<<27, 0, 1); + verify_l(i, -(1<<27), 0, 1); + // Java int border + verify_l(i, java.lang.Integer.MAX_VALUE, 0, 1); + verify_l(i, java.lang.Integer.MIN_VALUE, 0, 1); + // Impossible decodes + verify_l_bad(i, java.lang.Integer.MAX_VALUE, -1, 1); + verify_l_bad(i, java.lang.Integer.MIN_VALUE, 1, 1); + verify_l_bad(i, java.lang.Integer.MIN_VALUE, 0, -1); + } + + static void marshal_ul(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + // Just warming up.. + verify_ul(i, 3, 2, 1); + verify_ul(i, 5, 4, 3); + // The small integer border + verify_ul(i, 255, 0, 1); + verify_ul(i, 256, 0, 1); + // The integer border + verify_ul(i, (1<<26)-1, 0, 1); + verify_ul(i, 1<<26, 0, 1); + verify_ul(i, (1<<27)-1, 0, 1); + verify_ul(i, 1<<27, 0, 1); + // Java int border + verify_ul(i, java.lang.Integer.MAX_VALUE, 0, 1); + verify_ul(i, java.lang.Integer.MIN_VALUE, 0, 1); + verify_ul(i, -1, 0, 1); + verify_ul(i, java.lang.Integer.MAX_VALUE, + java.lang.Integer.MIN_VALUE, 1); + // Impossible decodes + verify_ul_bad(i, -1, -1, 1); + } + + static void marshal_s(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + // Just warming up.. + verify_s(i, 3, 2, 1); + verify_s(i, 5, 4, 3); + verify_s(i, -128, 0, 1); + // The small integer border + verify_s(i, 255, 0, 1); + verify_s(i, 256, 0, 1); + // Java short border + verify_s(i, java.lang.Short.MAX_VALUE, 0, 1); + verify_s(i, java.lang.Short.MIN_VALUE, 0, 1); + // Impossible decodes + verify_s_bad(i, java.lang.Short.MAX_VALUE, -1, 1); + verify_s_bad(i, java.lang.Short.MIN_VALUE, 1, 1); + verify_s_bad(i, java.lang.Short.MIN_VALUE, 0, -1); + } + + static void marshal_us(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + // Just warming up.. + verify_us(i, 3, 2, 1); + verify_us(i, 5, 4, 3); + // The small integer border + verify_us(i, 255, 0, 1); + verify_us(i, 256, 0, 1); + // Java short border + verify_us(i, java.lang.Short.MAX_VALUE, 0, 1); + verify_us(i, java.lang.Short.MIN_VALUE, 0, 1); + verify_us(i, -1, 0, 1); + verify_us(i, java.lang.Short.MAX_VALUE, + java.lang.Short.MIN_VALUE, 1); + // Impossible decodes + verify_us_bad(i, -1, -1, 1); + } + + static void marshal_c(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + // Just warming up.. + verify_c(i, '\3', '\2', 1); + verify_c(i, '\5', '\4', 3); + // The small integer border + verify_c(i, '\u00FF', '\0', 1); + verify_c(i, '\u0100', '\0', 1); + // Java char border + verify_c(i, java.lang.Character.MAX_VALUE, '\0', 1); + verify_c(i, java.lang.Character.MIN_VALUE, '\0', 1); + verify_c(i, java.lang.Character.MAX_VALUE, + java.lang.Character.MIN_VALUE, 1); + // Impossible decodes + verify_c_bad(i, '\u8000', '\0', 2); + } + + static void marshal_wc(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + // Just warming up.. + verify_wc(i, '\3', '\2', 1); + verify_wc(i, '\5', '\4', 3); + // The small integer border + verify_wc(i, '\u00FF', '\0', 1); + verify_wc(i, '\u0100', '\0', 1); + // Java char border + verify_wc(i, java.lang.Character.MAX_VALUE, '\0', 1); + verify_wc(i, java.lang.Character.MIN_VALUE, '\0', 1); + verify_wc(i, java.lang.Character.MAX_VALUE, + java.lang.Character.MIN_VALUE, 1); + // Impossible decodes + verify_c_bad(i, '\u8000', '\0', 2); + } + + static void marshal_str(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + // Just warming up.. + verify_str(i, 100, 100); + verify_str(i, 100, 1); + // Erlang string border + verify_str(i, 65535, 1); + verify_str(i, 2, 65535); + // Erlang string border out + verify_str(i, 65536, 1); + verify_str(i, 65536, 65536); + } + + static void marshal_any_3(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + com.ericsson.otp.ic.Any x = new com.ericsson.otp.ic.Any(); + com.ericsson.otp.ic.Any y = new com.ericsson.otp.ic.Any(); + com.ericsson.otp.ic.Any z = new com.ericsson.otp.ic.Any(); + + x.insert_longlong(java.lang.Long.MAX_VALUE); + y.insert_longlong(1L); + z.insert_longlong(java.lang.Long.MAX_VALUE-1L); + System.out.println("verify_any_3 longlong max"); + verify_any_3(i, x, y, 1, z); + + x.insert_longlong(java.lang.Long.MIN_VALUE); + y.insert_longlong(-1L); + z.insert_longlong(java.lang.Long.MIN_VALUE+1L); + System.out.println("verify_any_3 longlong min"); + verify_any_3(i, x, y, 1, z); + + x.insert_ulonglong(-1L); + y.insert_longlong(1L); + z.insert_ulonglong(-2L); + System.out.println("verify_any_3 ulonglong max"); + verify_any_3(i, x, y, 1, z); + + x.insert_ulonglong(0L); + y.insert_longlong(-1L); + z.insert_ulonglong(1L); + System.out.println("verify_any_3 ulonglong min"); + verify_any_3(i, x, y, 1, z); + + x.insert_long(java.lang.Integer.MAX_VALUE); + y.insert_long(1); + z.insert_long(java.lang.Integer.MAX_VALUE-1); + System.out.println("verify_any_3 long max"); + verify_any_3(i, x, y, 1, z); + + x.insert_long(java.lang.Integer.MIN_VALUE); + y.insert_long(-1); + z.insert_long(java.lang.Integer.MIN_VALUE+1); + System.out.println("verify_any_3 long min"); + verify_any_3(i, x, y, 1, z); + + x.insert_ulong(-1); + y.insert_long(1); + z.insert_ulong(-2); + System.out.println("verify_any_3 ulong max"); + verify_any_3(i, x, y, 1, z); + + x.insert_ulong(0); + y.insert_long(-1); + z.insert_ulong(1); + System.out.println("verify_any_3 ulong min"); + verify_any_3(i, x, y, 1, z); + + x.insert_short(java.lang.Short.MAX_VALUE); + y.insert_short((short)1); + z.insert_short((short)(java.lang.Short.MAX_VALUE-1)); + System.out.println("verify_any_3 short max"); + verify_any_3(i, x, y, 1, z); + + x.insert_short(java.lang.Short.MIN_VALUE); + y.insert_short((short)-1); + z.insert_short((short)(java.lang.Short.MIN_VALUE+1)); + System.out.println("verify_any_3 short min"); + verify_any_3(i, x, y, 1, z); + + x.insert_ushort((short)-1); + y.insert_short((short)1); + z.insert_ushort((short)-2); + System.out.println("verify_any_3 ushort max"); + verify_any_3(i, x, y, 1, z); + + x.insert_ushort((short)0); + y.insert_short((short)-1); + z.insert_ushort((short)1); + System.out.println("verify_any_3 ushort min"); + verify_any_3(i, x, y, 1, z); + + x.insert_char('\377'); + y.insert_char('\1'); + z.insert_char('\376'); + System.out.println("verify_any_3 char max"); + verify_any_3(i, x, y, 1, z); + + x.insert_wchar('\uFFFF'); + y.insert_wchar('\u0001'); + z.insert_wchar('\uFFFE'); + System.out.println("verify_any_3 char max"); + verify_any_3(i, x, y, 1, z); + } + + static void marshal_any_2(String selfNode, String peerNode, + String cookie, String serverName) + throws java.lang.Exception + { + m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName); + m.s s = new m.s(); + com.ericsson.otp.ic.Any a = new com.ericsson.otp.ic.Any(); + // + s.ull_x = -1L; + s.ll_x = java.lang.Long.MAX_VALUE; + s.ll_y = 1L; + s.ull_z = -2L; + s.ll_z = java.lang.Long.MAX_VALUE-1L; + // + s.ul_x = -1; + s.l_x = java.lang.Integer.MAX_VALUE; + s.l_y = 1; + s.ul_z = -2; + s.l_z = java.lang.Integer.MAX_VALUE-1; + // + s.us_x = (short)-1; + s.s_x = java.lang.Short.MAX_VALUE; + s.s_y = (short)1; + s.us_z = (short)-2; + s.s_z = (short)(java.lang.Short.MAX_VALUE-1); + // + s.c_x = '\377'; + s.c_y = '\1'; + s.c_z = '\376'; + s.wc_x = '\uFFFF'; + s.wc_y = '\u0001'; + s.wc_z = '\uFFFE'; + m.sHelper.insert(a, s); + verify_any_2(i, a, 1); + + s.ull_x = 0L; + s.ll_x = java.lang.Long.MIN_VALUE; + s.ll_y = -1L; + s.ull_z = 1L; + s.ll_z = java.lang.Long.MIN_VALUE+1L; + // + s.ul_x = 0; + s.l_x = java.lang.Integer.MIN_VALUE; + s.l_y = -1; + s.ul_z = 1; + s.l_z = java.lang.Integer.MIN_VALUE+1; + // + s.us_x = (short)0; + s.s_x = java.lang.Short.MIN_VALUE; + s.s_y = (short)-1; + s.us_z = (short)1; + s.s_z = (short)(java.lang.Short.MIN_VALUE+1); + // + s.c_x = '\0'; + s.c_y = '\0'; + s.c_z = '\0'; + s.wc_x = '\u0000'; + s.wc_y = '\u0000'; + s.wc_z = '\u0000'; + m.sHelper.insert(a, s); + verify_any_2(i, a, 1); + } + + + static void verify_ll(m._iStub i, long x, long y, int b) + throws java.lang.Exception + { + m.s a = new m.s(); + System.out.println("verify_ll "+a); + a.ll_x = x; + a.ll_y = y; + long expected = (x - y)*(short)b; + long result = i.marshal_ll(a, (short)b); + if (result == expected) { + System.out.println("verify_ll("+x+", "+y+", "+b+") => " + +result); + } else { + System.out.println("verify_ll("+x+", "+y+", "+b+") => " + +result+" != "+expected); + System.exit(4); + } + } + + static void verify_ull(m._iStub i, long x, long y, int b) + throws java.lang.Exception + { + m.s a = new m.s(); + a.ull_x = x; + a.ll_y = y; + long expected = (x - y)*(short)b; + long result = i.marshal_ull(a, (short)b); + if (result == expected) { + System.out.println("verify_ull("+x+", "+y+", "+b+") => " + +result); + } else { + System.out.println("verify_ull("+x+", "+y+", "+b+") => " + +result+" != "+expected); + System.exit(4); + } + } + + static void verify_l(m._iStub i, int x, int y, int b) + throws java.lang.Exception + { + m.s a = new m.s(); + a.l_x = x; + a.l_y = y; + int expected = (x - y)*(short)b; + int result = i.marshal_l(a, (short)b); + if (result == expected) { + System.out.println("verify_l("+x+", "+y+", "+b+") => " + +result); + } else { + System.out.println("verify_l("+x+", "+y+", "+b+") => " + +result+" != "+expected); + System.exit(4); + } + } + + static void verify_ul(m._iStub i, int x, int y, int b) + throws java.lang.Exception + { + m.s a = new m.s(); + a.ul_x = x; + a.l_y = y; + int expected = (x - y)*(short)b; + int result = i.marshal_ul(a, (short)b); + if (result == expected) { + System.out.println("verify_ul("+x+", "+y+", "+b+") => " + +result); + } else { + System.out.println("verify_ul("+x+", "+y+", "+b+") => " + +result+" != "+expected); + System.exit(4); + } + } + + static void verify_s(m._iStub i, int x, int y, int b) + throws java.lang.Exception + { + m.s a = new m.s(); + a.s_x = (short)x; + a.s_y = (short)y; + short expected = (short)((x - y)*(short)b); + short result = i.marshal_s(a, (short)b); + if (result == expected) { + System.out.println("verify_s("+x+", "+y+", "+b+") => " + +result); + } else { + System.out.println("verify_s("+x+", "+y+", "+b+") => " + +result+" != "+expected); + System.exit(4); + } + } + + static void verify_us(m._iStub i, int x, int y, int b) + throws java.lang.Exception + { + m.s a = new m.s(); + a.us_x = (short)x; + a.s_y = (short)y; + short expected = (short)((x - y)*(short)b); + short result = i.marshal_us(a, (short)b); + if (result == expected) { + System.out.println("verify_us("+x+", "+y+", "+b+") => " + +result); + } else { + System.out.println("verify_us("+x+", "+y+", "+b+") => " + +result+" != "+expected); + System.exit(4); + } + } + + static void verify_c(m._iStub i, char x, char y, int b) + throws java.lang.Exception + { + m.s a = new m.s(); + a.c_x = x; + a.c_y = y; + char expected = (char)(((int)x - (int)y)*(short)b); + char result = i.marshal_c(a, (short)b); + if (result == expected) { + System.out.println("verify_c("+x+", "+y+", "+b+") => " + +result); + } else { + System.out.println("verify_c("+x+", "+y+", "+b+") => " + +result+" != "+expected); + System.exit(4); + } + } + + static void verify_wc(m._iStub i, char x, char y, int b) + throws java.lang.Exception + { + m.s a = new m.s(); + a.wc_x = x; + a.wc_y = y; + char expected = (char)(((int)x - (int)y)*(short)b); + char result = i.marshal_wc(a, (short)b); + if (result == expected) { + System.out.println("verify_wc("+x+", "+y+", "+b+") => " + +result); + } else { + System.out.println("verify_wc("+x+", "+y+", "+b+") => " + +result+" != "+expected); + System.exit(4); + } + } + + static void verify_str(m._iStub i, int a_len, int b_len) + throws java.lang.Exception + { + String a = mk_str(a_len); + String b = mk_str(b_len); + String expected = a + b; + String result = i.strcat(a, b); + if (result.equals(expected)) { + System.out.println("verify_str(\""+a+"\", \""+b+"\") => \"" + +result+"\""); + } else { + System.out.println("verify_str(\""+a+"\", \""+b+"\") => \"" + +result+"\" != \""+expected.length()+"\""); + System.exit(4); + } + } + + static String mk_str(int len) + throws StringIndexOutOfBoundsException + { + StringBuffer s = new StringBuffer(); + // 17 characters is prime relative all bases of two - on purpose + do s.append("qwertyuiopasdfghj"); while (s.length() < len); + return s.substring(0, len); + } + + static void verify_any_3(m._iStub i, + com.ericsson.otp.ic.Any x, + com.ericsson.otp.ic.Any y, + int b, + com.ericsson.otp.ic.Any expected) + throws java.lang.Exception + { + com.ericsson.otp.ic.Any result = i.marshal_any_3(x, y, (short)b); + if (! expected.equal(result)) { + System.exit(4); + } + } + + static void verify_any_2(m._iStub i, com.ericsson.otp.ic.Any a, int b) + throws java.lang.Exception + { + com.ericsson.otp.ic.Any result = i.marshal_any_2(a, (short)b); + if (! a.equal(result)) { + System.exit(4); + } + } + + + + static void verify_ll_bad(m._iStub i, long x, long y, int b) + throws java.lang.Exception + { + try { + verify_ll(i, x, y, b); + System.out.println("Expected exception missing!"); + System.exit(5); + } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) { + System.out.println("Expected exception: "+e); + } + } + + static void verify_ull_bad(m._iStub i, long x, long y, int b) + throws java.lang.Exception + { + try { + verify_ull(i, x, y, b); + System.out.println("Expected exception missing!"); + System.exit(5); + } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) { + System.out.println("Expected exception: "+e); + } + } + + static void verify_l_bad(m._iStub i, int x, int y, int b) + throws java.lang.Exception + { + try { + verify_l(i, x, y, b); + System.out.println("Expected exception missing!"); + System.exit(5); + } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) { + System.out.println("Expected exception: "+e); + } + } + + static void verify_ul_bad(m._iStub i, int x, int y, int b) + throws java.lang.Exception + { + try { + verify_ul(i, x, y, b); + System.out.println("Expected exception missing!"); + System.exit(5); + } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) { + System.out.println("Expected exception: "+e); + } + } + + static void verify_s_bad(m._iStub i, int x, int y, int b) + throws java.lang.Exception + { + try { + verify_s(i, x, y, b); + System.out.println("Expected exception missing!"); + System.exit(5); + } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) { + System.out.println("Expected exception: "+e); + } + } + + static void verify_us_bad(m._iStub i, int x, int y, int b) + throws java.lang.Exception + { + try { + verify_us(i, x, y, b); + System.out.println("Expected exception missing!"); + System.exit(5); + } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) { + System.out.println("Expected exception: "+e); + } + } + + static void verify_c_bad(m._iStub i, char x, char y, int b) + throws java.lang.Exception + { + try { + verify_c(i, x, y, b); + System.out.println("Expected exception missing!"); + System.exit(5); + } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) { + System.out.println("Expected exception: "+e); + } + } + + static void verify_wc_bad(m._iStub i, char x, char y, int b) + throws java.lang.Exception + { + try { + verify_wc(i, x, y, b); + System.out.println("Expected exception missing!"); + System.exit(5); + } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) { + System.out.println("Expected exception: "+e); + } + } + +} diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src b/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src new file mode 100644 index 0000000000..de1503401c --- /dev/null +++ b/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src @@ -0,0 +1,88 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2003-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% +# +# +# Makefile.src for java_client_erl_server test +# Note: This file *must* work for both Unix and Windows +# +# We use both `rm' (Unix) and `del' (Windows) for removing files, but +# with a `-' in front so that the error in not finding `rm' (`del') on +# Windows (Unix) is ignored. +# +# VxWorks? XXX +# + +.SUFFIXES: +.SUFFIXES: .erl .idl .@EMULATOR@ .java + + +JAVAC = @JAVAC@ +ERLC = erlc + +# ic variables available from ts: +# +# ic_libpath: @ic_libpath@ +# ic_include_path: @ic_include_path@ + +IC_INCLUDE_PATH = @ic_include_path@ +IC_CLASSPATH = @ic_classpath@ + +JINTERFACE_CLASSPATH = @jinterface_classpath@ + +CLASSPATH = .@PS@$(IC_CLASSPATH)@PS@$(JINTERFACE_CLASSPATH)@PS@ + +GEN_JAVA_FILES = \ + m@DS@_iImplBase.java \ + m@DS@_iStub.java \ + +GEN_HRL_FILES = \ + m.hrl \ + m_i.hrl \ + oe_java_erl_test.hrl + +GEN_ERL_FILES = \ + m_i.erl \ + oe_java_erl_test.erl + +JAVA_FILES = $(GEN_JAVA_FILES) JavaClient.java +CLASS_FILES = $(JAVA_FILES:.java=.class) +ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl +EBINS = $(ERL_FILES:.erl=.@EMULATOR@) + + +all: $(CLASS_FILES) $(EBINS) + +clean: + -rm -f $(GEN_JAVA_FILES) $(CLASS_FILES) \ + $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS) + -del /F /Q $(GEN_JAVA_FILES) $(CLASS_FILES) \ + $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS) + +$(GEN_JAVA_FILES) : java_erl_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,java}" java_erl_test.idl + +$(CLASS_FILES) : $(JAVA_FILES) + $(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES) + +$(GEN_ERL_FILES) $(GEN_HRL_FILES): java_erl_test.idl + $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" java_erl_test.idl + +.erl.@EMULATOR@: + $(ERLC) -I $(IC_INCLUDE_PATH) $< diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl b/lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl new file mode 100644 index 0000000000..b72c972d3b --- /dev/null +++ b/lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl @@ -0,0 +1,68 @@ + + +// %CopyrightBegin% +// +// Copyright Ericsson AB 2003-2010. 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 m { + + struct s { + long long ll_x; + unsigned long long ull_x; + long long ll_y; + long long ll_z; + unsigned long long ull_z; + + long l_x; + unsigned long ul_x; + long l_y; + long l_z; + unsigned long ul_z; + + short s_x; + unsigned short us_x; + short s_y; + short s_z; + unsigned short us_z; + + char c_x; + char c_y; + char c_z; + + wchar wc_x; + wchar wc_y; + wchar wc_z; + }; + + interface i { + long long marshal_ll( in s a, in short b ); + unsigned long long marshal_ull( in s a, in short b ); + + long marshal_l( in s a, in short b ); + unsigned long marshal_ul( in s a, in short b ); + + short marshal_s( in s a, in short b ); + unsigned short marshal_us( in s a, in short b ); + + char marshal_c( in s a, in short b ); + wchar marshal_wc( in s a, in short b ); + + string strcat( in string a, in string b ); + + any marshal_any_3( in any x, in any y, in short b ); + any marshal_any_2( in any a, in short b ); + }; + +}; diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl b/lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl new file mode 100644 index 0000000000..77e532288f --- /dev/null +++ b/lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl @@ -0,0 +1,169 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-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(m_i_impl). + +-export([marshal_ll/3,marshal_ull/3, + marshal_l/3,marshal_ul/3, + marshal_s/3,marshal_us/3, + marshal_c/3,marshal_wc/3, + strcat/3, + marshal_any_3/4,marshal_any_2/3]). +-export([init/1,terminate/2,code_change/3]). + +-include("m.hrl"). + +-define(TK_M_S, {tk_struct, + "IDL:m/s:1.0", + "s", + [{"ll_x",tk_longlong}, + {"ull_x",tk_ulonglong}, + {"ll_y",tk_longlong}, + {"ll_z",tk_longlong}, + {"ull_z",tk_ulonglong}, + {"l_x",tk_long}, + {"ul_x",tk_ulong}, + {"l_y",tk_long}, + {"l_z",tk_long}, + {"ul_z",tk_ulong}, + {"s_x",tk_short}, + {"us_x",tk_ushort}, + {"s_y",tk_short}, + {"s_z",tk_short}, + {"us_z",tk_ushort}, + {"c_x",tk_char}, + {"c_y",tk_char}, + {"c_z",tk_char}, + {"wc_x",tk_wchar}, + {"wc_y",tk_wchar}, + {"wc_z",tk_wchar}|_]}). + + + +marshal_ll(State, #m_s{ll_x = X, ll_y = Y}=_A, B) when integer(B) -> + R = (X - Y)*B, + io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]), + {reply, R, State}. + +marshal_ull(State, #m_s{ull_x = X, ll_y = Y}=_A, B) when integer(B) -> + R = (X - Y)*B, + io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]), + {reply, R, State}. + + +marshal_l(State, #m_s{l_x = X, l_y = Y}=_A, B) when integer(B) -> + R = (X - Y)*B, + io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]), + {reply, R, State}. + +marshal_ul(State, #m_s{ul_x = X, l_y = Y}=_A, B) when integer(B) -> + R = (X - Y)*B, + io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]), + {reply, R, State}. + + +marshal_s(State, #m_s{s_x = X, s_y = Y}=_A, B) when integer(B) -> + R = (X - Y)*B, + io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]), + {reply, R, State}. + +marshal_us(State, #m_s{us_x = X, s_y = Y}=_A, B) when integer(B) -> + R = (X - Y)*B, + io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]), + {reply, R, State}. + + +marshal_c(State, #m_s{c_x = X, c_y = Y}=_A, B) when integer(B) -> + R = (X - Y)*B, + io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]), + {reply, R, State}. + +marshal_wc(State, #m_s{wc_x = X, wc_y = Y}=_A, B) when integer(B) -> + R = (X - Y)*B, + io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]), + {reply, R, State}. + +strcat(State, A, B) when list(A), list(B) -> + R = A++B, + io:format("~p", [{?MODULE,?LINE,[length(A),length(B),A,B,R]}]), + {reply, R, State}; +strcat(State, A, B) -> + io:format("~p", [{?MODULE,?LINE,[A,B]}]), + {reply, [], State}. + +marshal_any_3(State, {any,TkX,_}=X, {any,_,_}=Y, B) when integer(B) -> + R = any(mul(sub(any(X), any(Y)), B), TkX), + io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]), + {reply, R, State}. + +marshal_any_2(State, + {any,TkA,#m_s{ll_x=LL_X, ull_x=ULL_X, ll_y=LL_Y, + l_x=L_X, ul_x=UL_X, l_y=L_Y, + s_x=S_X, us_x=US_X, s_y=S_Y, + c_x=C_X, c_y=C_Y, + wc_x=WC_X, wc_y=WC_Y} = A}, + B) when integer(B) -> + {check_type_code,?TK_M_S} = {check_type_code,TkA}, + ULL_Z = (ULL_X - LL_Y) * B, + LL_Z = (LL_X - LL_Y) * B, + UL_Z = (UL_X - L_Y) * B, + L_Z = (L_X - L_Y) * B, + US_Z = (US_X - S_Y) * B, + S_Z = (S_X - S_Y) * B, + C_Z = (C_X - C_Y) * B, + WC_Z = (WC_X - WC_Y) * B, + R = A#m_s{ll_z=LL_Z, ull_z=ULL_Z, + l_z=L_Z, ul_z=UL_Z, + s_z=S_Z, us_z=US_Z, + c_z=C_Z, wc_z=WC_Z}, + io:format("~p", [{?MODULE,?LINE,[A,B,R]}]), + {reply, {any,TkA,R}, State}. + + + +init(_Env) -> + {ok, []}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +any({any,tk_longlong,X}) -> X; +any({any,tk_long,X}) -> X; +any({any,tk_short,X}) -> X; +any({any,tk_ulonglong,X}) -> X; +any({any,tk_ulong,X}) -> X; +any({any,tk_ushort,X}) -> X; +any({any,tk_char,X}) -> X; +any({any,tk_wchar,X}) -> X. + +any(X, Tk) when integer(X) -> {any,Tk,X}. + +sub(X, Y) when integer(X), integer(Y) -> + X - Y. + +mul(X, Y) when integer(X), integer(Y) -> + X * Y. + +napp(0, L) -> L; +napp(N, L) when integer(N), N >= 1 -> napp(N-1, L)++L. diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk index 4aa2a04b60..074d0b3d39 100644 --- a/lib/ic/vsn.mk +++ b/lib/ic/vsn.mk @@ -1,20 +1 @@ IC_VSN = 4.2.25 - -TICKETS = OTP-8639 - -TICKETS_4.2.24 = OTP-8307 \ - OTP-8353 \ - OTP-8354 \ - OTP-8355 - -TICKETS_4.2.23 = OTP-8201 - -TICKETS_4.2.22 = OTP-8088 - -TICKETS_4.2.21 = OTP-7982 - -TICKETS_4.2.20 = OTP-7837 - -TICKETS_4.2.19 = OTP-7595 - -TICKETS_4.2.18 = OTP-7313 diff --git a/lib/inets/doc/src/http_client.xml b/lib/inets/doc/src/http_client.xml index 510c30eb35..ea8053cafa 100644 --- a/lib/inets/doc/src/http_client.xml +++ b/lib/inets/doc/src/http_client.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2009</year> + <year>2004</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -56,8 +56,8 @@ <pre> [{inets, [{services, [{httpc, PropertyList}]}]}] </pre> - <p>For valid properties see <seealso - marker="http">http(3)</seealso></p> + <p>For valid properties see + <seealso marker="http">httpc(3)</seealso>. </p> </section> <section> @@ -71,67 +71,66 @@ but not for requests to localhost. This will apply to all subsequent requests</p> <code type="erl"> - 2 > http:set_options([{proxy, {{"www-proxy.mycompany.com", 8000}, + 2 > httpc:set_options([{proxy, {{"www-proxy.mycompany.com", 8000}, ["localhost"]}}]). ok </code> <p>An ordinary synchronous request. </p> <code type="erl"> 3 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = - http:request(get, {"http://www.erlang.org", []}, [], []). + httpc:request(get, {"http://www.erlang.org", []}, [], []). </code> <p>With all default values, as above, a get request can also be written like this.</p> <code type="erl"> 4 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = - http:request("http://www.erlang.org"). + httpc:request("http://www.erlang.org"). </code> <p>An ordinary asynchronous request. The result will be sent to the calling process on the form {http, {ReqestId, Result}}</p> <code type="erl"> 5 > {ok, RequestId} = - http:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]). + httpc:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]). </code> <p>In this case the calling process is the shell, so we receive the result.</p> <code type="erl"> - 6 > receive {http, {RequestId, Result}} -> ok after 500 -> error end. + 6 > receive {http, {RequestId, Result}} -> ok after 500 -> error end. ok </code> <p>Send a request with a specified connection header. </p> <code type="erl"> 7 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} = - http:request(get, {"http://www.erlang.org", [{"connection", "close"}]}, + httpc:request(get, {"http://www.erlang.org", [{"connection", "close"}]}, [], []). </code> <p>Start a HTTP client profile. </p> <code><![CDATA[ - 8 > {ok, Pid} = inets:start(httpc, [{profile, foo}]). + 8 > {ok, Pid} = inets:start(httpc, [{profile, foo}]). {ok, <0.45.0>} ]]></code> <p>The new profile has no proxy settings so the connection will be refused</p> <code type="erl"> - 9 > http:request("http://www.erlang.org", foo). - {error,econnrefused} + 9 > httpc:request("http://www.erlang.org", foo). + {error, econnrefused} </code> <p>Stop a HTTP client profile. </p> <code type="erl"> - 10 > inets:stop(httpc, foo). + 10 > inets:stop(httpc, foo). ok </code> <p>Alternatively:</p> <code type="erl"> - 10 > inets:stop(httpc, Pid). + 10 > inets:stop(httpc, Pid). ok </code> - </section> </chapter> diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml index 81dfe7e944..c367d7fa77 100644 --- a/lib/inets/doc/src/inets.xml +++ b/lib/inets/doc/src/inets.xml @@ -13,12 +13,12 @@ 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. - + </legalnotice> <title>inets</title> @@ -40,13 +40,13 @@ <title>COMMON DATA TYPES </title> <p>Type definitions that are used more than once in this module: </p> - <p><c> service() = ftpc | tfptd | httpc | httpd</c></p> + <p><c> service() = ftpc | tftp | httpc | httpd</c></p> <p><c> property() = atom() </c></p> </section> <funcs> <func> <name>services() -> [{Service, Pid}]</name> - <fsummary>Returns a list of currently running services. </fsummary> + <fsummary>Returns a list of currently running services. </fsummary> <type> <v>Service = service()</v> <v>Pid = pid()</v> @@ -97,7 +97,7 @@ <name>start(Type) -> ok | {error, Reason}</name> <fsummary>Starts the Inets application. </fsummary> <type> - <v>Type = permanent | transient | temporary</v> + <v>Type = permanent | transient | temporary</v> </type> <desc> <p>Starts the Inets application. Default type @@ -115,11 +115,9 @@ </func> <func> <name>start(Service, ServiceConfig) -> {ok, Pid} | {error, Reason}</name> - <name>start(Service, ServiceConfig, How) -> {ok, Pid} | - {error, Reason}</name> + <name>start(Service, ServiceConfig, How) -> {ok, Pid} | {error, Reason}</name> <fsummary>Dynamically starts an inets - service after the inets application has been - started. </fsummary> + service after the inets application has been started. </fsummary> <type> <v>Service = service()</v> <v>ServiceConfig = [{Option, Value}]</v> @@ -153,9 +151,9 @@ <fsummary>Stops a started service of the inets application or takes down a "stand_alone-service" gracefully.</fsummary> <type> - <v>Service = service() | stand_alone</v> + <v>Service = service() | stand_alone</v> <v>Reference = pid() | term() - service specified reference</v> - <v>Reason = term()</v> + <v>Reason = term()</v> </type> <desc> <p>Stops a started service of the inets application or takes @@ -169,7 +167,7 @@ <section> <title>SEE ALSO</title> <p><seealso marker="ftp">ftp(3)</seealso>, - <seealso marker="http">http(3)</seealso>, + <seealso marker="httpc">httpc(3)</seealso>, <seealso marker="httpd">httpd(3)</seealso>, <seealso marker="tftp">tftp(3)</seealso></p> </section> diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index c34b641b7b..8af6613fa2 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2002-2010. 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% %% %% @@ -605,24 +605,29 @@ handle_info({ssl_error, _, _} = Reason, State) -> %% Internally, to a request handling process, a request timeout is %% seen as a canceled request. handle_info({timeout, RequestId}, - #state{request = #request{id = RequestId} = Request, - canceled = Canceled} = State) -> + #state{request = #request{id = RequestId} = Request, + canceled = Canceled, + profile_name = ProfileName} = State) -> ?hcri("timeout of current request", [{id, RequestId}]), httpc_response:send(Request#request.from, httpc_response:error(Request, timeout)), + httpc_manager:request_done(RequestId, ProfileName), ?hcrv("response (timeout) sent - now terminate", []), {stop, normal, State#state{request = Request#request{from = answer_sent}, canceled = [RequestId | Canceled]}}; -handle_info({timeout, RequestId}, #state{canceled = Canceled} = State) -> +handle_info({timeout, RequestId}, + #state{canceled = Canceled, + profile_name = ProfileName} = State) -> ?hcri("timeout", [{id, RequestId}]), Filter = fun(#request{id = Id, from = From} = Request) when Id =:= RequestId -> ?hcrv("found request", [{id, Id}, {from, From}]), %% Notify the owner - Response = httpc_response:error(Request, timeout), - httpc_response:send(From, Response), + httpc_response:send(From, + httpc_response:error(Request, timeout)), + httpc_manager:request_done(RequestId, ProfileName), ?hcrv("response (timeout) sent", []), [Request#request{from = answer_sent}]; (_) -> diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index d5d6376369..1e1bde220b 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2002-2010. 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% %% %% @@ -66,15 +66,6 @@ state % State of the handler: initiating | started | operational | canceled }). -%% Entries in the handler / request cross-ref table -%% -record(request_info, -%% { -%% id, % Id of the request -%% handler, % Pid of the handler process -%% from, % The From value for the caller -%% mref % Monitor ref for the caller -%% }). - %%==================================================================== %% Internal Application API @@ -577,7 +568,9 @@ handle_info({'EXIT', Pid, Reason}, #state{handler_db = HandlerDb} = State) -> handle_info({'DOWN', _, _, Pid, _}, State) -> %% - %% Check what happens to waiting requests! Chall we not send a reply? + %% Normally this should have been cleaned up already + %% (when receiving {request_done, PequestId}), but + %% just in case there is a glitch, cleanup anyway. %% Pattern = #handler_info{handler = Pid, _ = '_'}, @@ -649,7 +642,16 @@ get_handler_info(Tab) -> Acc end, Handlers2 = lists:foldl(F, [], Handlers1), - Handlers3 = [{Pid, State, httpc_handler:info(Pid)} || + Handlers3 = [{Pid, State, + case (catch httpc_handler:info(Pid)) of + {'EXIT', _} -> + %% Why would this crash? + %% Only if the process has died, but we don't + %% know about it? + []; + Else -> + Else + end} || {Pid, State} <- Handlers2], Handlers3. @@ -666,6 +668,10 @@ handle_started(StarterPid, ReqId, HandlerPid, case ets:lookup(HandlerDb, ReqId) of [#handler_info{state = initiating} = HandlerInfo] -> ?hcri("received started ack for initiating handler", []), + %% As a last resort, make sure we know when it exits, + %% in case it forgets to notify us. + %% We dont need to know the ref id? + erlang:monitor(process, HandlerPid), HandlerInfo2 = HandlerInfo#handler_info{handler = HandlerPid, state = started}, ets:insert(HandlerDb, HandlerInfo2), diff --git a/lib/inets/src/inets_app/inets.erl b/lib/inets/src/inets_app/inets.erl index f1fa5fd997..054468e445 100644 --- a/lib/inets/src/inets_app/inets.erl +++ b/lib/inets/src/inets_app/inets.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2006-2010. 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% %% %% @@ -57,7 +57,7 @@ start(Type) -> %% Function: start(Service, ServiceConfig [, How]) -> {ok, Pid} | %% {error, Reason} %% -%% Service = - ftpc | tftpd | httpc | httpd +%% Service = - ftpc | tftpd | tftpc | tftp | httpc | httpd %% ServiceConfig = ConfPropList | ConfFile %% ConfPropList = [{Property, Value}] according to service %% ConfFile = Path - when service is httpd @@ -100,7 +100,7 @@ stop() -> %%-------------------------------------------------------------------- %% Function: stop(Service, Pid) -> ok %% -%% Service - ftp | tftpd | http | httpd | stand_alone +%% Service - ftpc | ftp | tftpd | tftpc | tftp | httpc | httpd | stand_alone %% %% Description: Stops a started service of the inets application or takes %% down a stand alone "service" gracefully. @@ -382,7 +382,7 @@ key1search(Key, Vals, Def) -> %% Description: Returns a list of supported services %%------------------------------------------------------------------- service_names() -> - [ftpc, tftpd, httpc, httpd]. + [ftpc, tftp, httpc, httpd]. %%----------------------------------------------------------------- @@ -725,8 +725,8 @@ call_service(Service, Call, Args) -> service_module(tftpd) -> tftp; -service_module(httpc) -> - httpc; +service_module(tftpc) -> + tftp; service_module(ftpc) -> ftp; service_module(Service) -> diff --git a/lib/inets/test/ftp_macosx_x86_test.erl b/lib/inets/test/ftp_macosx_x86_test.erl index c59a992421..5566d4feaa 100644 --- a/lib/inets/test/ftp_macosx_x86_test.erl +++ b/lib/inets/test/ftp_macosx_x86_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2010. 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,7 +108,7 @@ passive_pwd(X) -> ?LIB_MOD:passive_pwd(X). passive_cd(X) -> ?LIB_MOD:passive_cd(X). passive_lcd(X) -> ?LIB_MOD:passive_lcd(X). passive_ls(X) -> ?LIB_MOD:passive_ls(X). -passive_nlist(X) -> ?LIB_MOD:passive_nlist(X). +passive_nlist(X) -> ?LIB_MOD:passive_nlist([{wildcard_support, false} | X]). passive_rename(X) -> ?LIB_MOD:passive_rename(X). passive_delete(X) -> ?LIB_MOD:passive_delete(X). passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X). @@ -129,7 +129,7 @@ active_pwd(X) -> ?LIB_MOD:active_pwd(X). active_cd(X) -> ?LIB_MOD:active_cd(X). active_lcd(X) -> ?LIB_MOD:active_lcd(X). active_ls(X) -> ?LIB_MOD:active_ls(X). -active_nlist(X) -> ?LIB_MOD:active_nlist(X). +active_nlist(X) -> ?LIB_MOD:active_nlist([{wildcard_support, false} | X]). active_rename(X) -> ?LIB_MOD:active_rename(X). active_delete(X) -> ?LIB_MOD:active_delete(X). active_mkdir(X) -> ?LIB_MOD:active_mkdir(X). diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl index 5e27bc3a86..c539b7c17c 100644 --- a/lib/inets/test/ftp_suite_lib.erl +++ b/lib/inets/test/ftp_suite_lib.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2005-2010. 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% %% %% @@ -508,7 +508,8 @@ passive_nlist(suite) -> []; passive_nlist(Config) when is_list(Config) -> Pid = ?config(ftp, Config), - do_nlist(Pid). + WildcardSupport = ?config(wildcard_support, Config), + do_nlist(Pid, WildcardSupport). %%------------------------------------------------------------------------- @@ -768,7 +769,8 @@ active_nlist(suite) -> []; active_nlist(Config) when is_list(Config) -> Pid = ?config(ftp, Config), - do_nlist(Pid). + WildcardSupport = ?config(wildcard_support, Config), + do_nlist(Pid, WildcardSupport). %%------------------------------------------------------------------------- @@ -1242,16 +1244,20 @@ do_ls(Pid) -> {ok, _} = ftp:ls(Pid, "incom*"), ok. -do_nlist(Pid) -> +do_nlist(Pid, WildcardSupport) -> {ok, _} = ftp:nlist(Pid), {ok, _} = ftp:nlist(Pid, "incoming"), %% neither nlist nor ls operates on a directory %% they operate on a pathname, which *can* be a %% directory, but can also be a filename or a group %% of files (including wildcards). - {ok, _} = ftp:nlist(Pid, "incom*"), -%% {error, epath} = ftp:nlist(Pid, ?BAD_DIR), - ok. + case WildcardSupport of + true -> + {ok, _} = ftp:nlist(Pid, "incom*"), + ok; + _ -> + ok + end. do_rename(Pid, Config) -> PrivDir = ?config(priv_dir, Config), diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index b5fd896001..902e440c80 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2004-2010. 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% %% %% @@ -306,7 +306,8 @@ tickets(suite) -> otp_8106, otp_8056, otp_8352, - otp_8371 + otp_8371, + otp_8739 ]. @@ -2561,7 +2562,78 @@ otp_8371(Config) when is_list(Config) -> ok. +%%------------------------------------------------------------------------- +otp_8739(doc) -> + ["OTP-8739"]; +otp_8739(suite) -> + []; +otp_8739(Config) when is_list(Config) -> + {_DummyServerPid, Port} = otp_8739_dummy_server(), + URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html", + Method = get, + Request = {URL, []}, + HttpOptions = [{connect_timeout, 500}, {timeout, 1}], + Options = [{sync, true}], + case http:request(Method, Request, HttpOptions, Options) of + {error, timeout} -> + %% And now we check the size of the handler db + Info = httpc:info(), + tsp("Info: ~p", [Info]), + {value, {handlers, Handlers}} = + lists:keysearch(handlers, 1, Info), + case Handlers of + [] -> + ok; + _ -> + tsf({unexpected_handlers, Handlers}) + end; + Unexpected -> + tsf({unexpected, Unexpected}) + end. + + +otp_8739_dummy_server() -> + Parent = self(), + Pid = spawn_link(fun() -> otp_8739_dummy_server_init(Parent) end), + receive + {port, Port} -> + {Pid, Port} + end. + +otp_8739_dummy_server_init(Parent) -> + {ok, ListenSocket} = + gen_tcp:listen(0, [binary, inet, {packet, 0}, + {reuseaddr,true}, + {active, false}]), + {ok, Port} = inet:port(ListenSocket), + Parent ! {port, Port}, + otp_8739_dummy_server_main(Parent, ListenSocket). + +otp_8739_dummy_server_main(Parent, ListenSocket) -> + case gen_tcp:accept(ListenSocket) of + {ok, Sock} -> + %% Ignore the request, and simply wait for the socket to close + receive + {tcp_closed, Sock} -> + (catch gen_tcp:close(ListenSocket)), + exit(normal); + {tcp_error, Sock, Reason} -> + tsp("socket error: ~p", [Reason]), + (catch gen_tcp:close(ListenSocket)), + exit(normal) + after 10000 -> + %% Just in case + (catch gen_tcp:close(Sock)), + (catch gen_tcp:close(ListenSocket)), + exit(timeout) + end; + Error -> + exit(Error) + end. + + + %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 57c87e7036..b53d47d99c 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -1,118 +1,4 @@ -#-*-makefile-*- ; force emacs to enter makefile-mode - -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2010. 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% - APPLICATION = inets INETS_VSN = 5.4 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" - -TICKETS = OTP-7907 OTP-8564 OTP-8573 - -TICKETS_5_3_3 = \ - OTP-8609 \ - OTP-8610 \ - OTP-8624 - -TICKETS_5_3_2 = \ - OTP-8542 \ - OTP-8607 - -TICKETS_5_3_1 = \ - OTP-8508 \ - OTP-8509 - -TICKETS_5_3 = \ - OTP-8016 \ - OTP-8056 \ - OTP-8103 \ - OTP-8106 \ - OTP-8312 \ - OTP-8315 \ - OTP-8327 \ - OTP-8349 \ - OTP-8351 \ - OTP-8352 \ - OTP-8359 \ - OTP-8371 - -TICKETS_5_2 = \ - OTP-8204 \ - OTP-8206 \ - OTP-8247 \ - OTP-8248 \ - OTP-8249 \ - OTP-8258 \ - OTP-8280 - -TICKETS_5_1_3 = OTP-8154 - -TICKETS_5_1_2 = OTP-7298 OTP-8101 OTP-8118 - -TICKETS_5_1_1 = OTP-8052 OTP-8069 - -TICKETS_5_1 = OTP-7994 OTP-7998 OTP-8001 OTP-8004 OTP-8005 - -TICKETS_5_0_14 = OTP-7882 OTP-7883 OTP-7888 OTP-7950 OTP-7976 - -TICKETS_5.0.13 = \ - OTP-7723 \ - OTP-7724 \ - OTP-7726 \ - OTP-7463 \ - OTP-7815 \ - OTP-7857 - -# TICKETS_5.0.12 = \ -# OTP-7636 -# -# TICKETS_5.0.11 = \ -# OTP-7574 \ -# OTP-7597 \ -# OTP-7598 \ -# OTP-7605 -# -# TICKETS_5.0.10 = \ -# OTP-7450 \ -# OTP-7454 \ -# OTP-7490 \ -# OTP-7512 -# -# TICKETS_5.0.9 = \ -# OTP-7257 \ -# OTP-7323 \ -# OTP-7341 -# -# TICKETS_5.0.8 = \ -# OTP-7315 \ -# OTP-7321 -# -# TICKETS_5.0.7 = \ -# OTP-7304 -# -# TICKETS_5.0.6 = \ -# OTP-7266 -# -# TICKETS_5.0.5 = \ -# OTP-7220 \ -# OTP-7221 -# -# TICKETS_5.0.4 = \ -# OTP-7173 -# - diff --git a/lib/jinterface/test/Makefile b/lib/jinterface/test/Makefile new file mode 100644 index 0000000000..36955d1e91 --- /dev/null +++ b/lib/jinterface/test/Makefile @@ -0,0 +1,84 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2010. 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_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../vsn.mk + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/jinterface_test + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- +TEST_SPEC_FILE = jinterface.dynspec + +MODULES = nc_SUITE \ + jinterface_SUITE + +GEN_MODULES = jitu + +ERL_FILES = $(MODULES:%=%.erl) $(GEN_MODULES:%=%.erl) + +GEN_TARGET_FILES = $(GEN_MODULES:%=%.$(EMULATOR)) + +SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR)) + +TARGET_FILES = \ + $(GEN_TARGET_FILES) \ + $(SUITE_TARGET_FILES) + +# ---------------------------------------------------- +# PROGRAMS +# ---------------------------------------------------- + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +tests debug opt: + +clean: + rm -f $(TARGET_FILES) + rm -f errs core *~ + +docs: + +# ---------------------------------------------------- +# Special Targets +# ---------------------------------------------------- + + +# ---------------------------------------------------- +# Release Targets +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: + +release_docs_spec: + +release_tests_spec: tests + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) $(TEST_SPEC_FILE) $(ERL_FILES) $(RELSYSDIR) + @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) diff --git a/lib/jinterface/test/jinterface.dynspec b/lib/jinterface/test/jinterface.dynspec new file mode 100644 index 0000000000..44712521df --- /dev/null +++ b/lib/jinterface/test/jinterface.dynspec @@ -0,0 +1,32 @@ +%% -*- erlang -*- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2010. 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% +%% +%% You can test this file using this command. +%% file:script("jinterface.dynspec", [{'Os',"Unix"}]). + +case case code:priv_dir(jinterface) of + {error,bad_name} -> false; + P -> filelib:is_dir(P) end of + true -> + []; + false -> + NoApp = "No jinterface application", + [{skip,{nc_SUITE,NoApp}}, + {skip,{jinterface_SUITE,NoApp}}] +end. diff --git a/lib/jinterface/test/jinterface_SUITE.erl b/lib/jinterface/test/jinterface_SUITE.erl new file mode 100644 index 0000000000..ea097680dd --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE.erl @@ -0,0 +1,761 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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(jinterface_SUITE). + +-export([all/1, init_per_suite/1, end_per_suite/1, + init_per_testcase/2, end_per_testcase/2]). + +-export([nodename/1, register_and_whereis/1, get_names/1, boolean_atom/1, + node_ping/1, mbox_ping/1, + java_erlang_send_receive/1, + java_internal_send_receive_same_node/1, + java_internal_send_receive_different_nodes/1, + java_internal_send_receive_self/1, + java_link_and_exit/1, erl_link_and_exit/1, + erl_link_java_exit/1, java_link_erl_exit/1, + internal_link_linking_exits/1, internal_link_linked_exits/1, + internal_unlink_linking_exits/1, internal_unlink_linked_exits/1, + normal_exit/1, kill_mbox/1, kill_erl_proc_from_java/1, + kill_mbox_from_erlang/1, erl_exit_with_reason_any_term/1, + java_exit_with_reason_any_term/1, + status_handler_localStatus/1, status_handler_remoteStatus/1, + status_handler_connAttempt/1]). + +-include("test_server.hrl"). +-include("test_server_line.hrl"). + +-define(debug,true). +-ifdef(debug). +-define(dbg(Str,Args), io:format(Str,Args)). +-else. +-define(dbg(Str,Args), ok). +-endif. + +-define(link_test_reason,link_test_reason). + +%% Test cases in MboxSendReceive.java +-define(java_erlang_send_receive,1). +-define(java_internal_send_receive_same_node,2). +-define(java_internal_send_receive_different_nodes,3). +-define(java_internal_send_receive_self,4). + +%% Test cases in MboxLinkUnlink.java +-define(java_link_and_exit, 1). +-define(erl_link_and_exit, 2). +-define(erl_link_java_exit, 3). +-define(java_link_erl_exit, 4). +-define(internal_link_linking_exits, 5). +-define(internal_link_linked_exits, 6). +-define(internal_unlink_linking_exits,7). +-define(internal_unlink_linked_exits,8). +-define(normal_exit,9). +-define(kill_mbox,10). +-define(kill_erl_proc_from_java,11). +-define(kill_mbox_from_erlang,12). +-define(erl_exit_with_reason_any_term,13). +-define(java_exit_with_reason_any_term,14). + + +%% Test cases in NodeStatusHandler.java +-define(status_handler_localStatus,1). +-define(status_handler_remoteStatus,2). +-define(status_handler_connAttempt,3). + +%%%----------------------------------------------------------------- +%%% INIT/END +%%%----------------------------------------------------------------- +all(suite) -> + lists:append([ + fundamental(), + ping(), + send_receive(), + link_unlink(), + status_handler() + ]). + +fundamental() -> + [ + nodename, % Nodename.java + register_and_whereis, % RegisterAndWhereis.java + get_names, % GetNames.java + boolean_atom % BooleanAtom.java + ]. + +ping() -> + [ + %% Implemented in NodePing.java + node_ping, + + %% Implemented in MboxPing.java + mbox_ping + ]. + + +send_receive() -> + [ + %% Implemented in MboxSendReceive.java + java_erlang_send_receive, + java_internal_send_receive_same_node, + java_internal_send_receive_different_nodes, + java_internal_send_receive_self + ]. + +%% Note: +%% +%% The test cases in MboxLinkUnlink.java and in +%% NodePing.java, all uses default cookie, and if there +%% is a problem with having the same default cookie in +%% erlang vs jinterface, e.g because the home directory +%% does not get the same in some cases on Windows +%% - they will all fail. + +link_unlink() -> + [ + %% Implemented in MboxLinkUnlink.java + java_link_and_exit, + erl_link_and_exit, + erl_link_java_exit, + java_link_erl_exit, + internal_link_linking_exits, + internal_link_linked_exits, + internal_unlink_linking_exits, + internal_unlink_linked_exits, + normal_exit, + kill_mbox, + kill_erl_proc_from_java, + kill_mbox_from_erlang, + erl_exit_with_reason_any_term, + java_exit_with_reason_any_term + ]. + +status_handler() -> + [ + %% Implemented in NodeStatusHandler.java + status_handler_localStatus, + status_handler_remoteStatus, + status_handler_connAttempt + ]. + + +init_per_suite(Config) when is_list(Config) -> + jitu:init_all(Config). + +end_per_suite(Config) when is_list(Config) -> + jitu:finish_all(Config). + +init_per_testcase(_Case,Config) -> + Dog = ?t:timetrap({seconds,10}), + [{watch_dog,Dog}|Config]. + +end_per_testcase(_Case,Config) -> + ?t:timetrap_cancel(?config(watch_dog,Config)), + ok. + + +%%%----------------------------------------------------------------- +%%% TEST CASES +%%%----------------------------------------------------------------- +nodename(doc) -> + ["Nodename.java: " + "Test OtpNode.node(), OtpNode.alive() and OtpNode.host()"]; +nodename(suite) -> + []; +nodename(Config) when is_list(Config) -> + [_,Host] = string:tokens(atom_to_list(node()),"@"), + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "Nodename", + [list_to_atom(Host)]). + +%%%----------------------------------------------------------------- +register_and_whereis(doc) -> + ["RegisterAndWhereis.java: " + "Test OtpNode.registerName(...), OtpMbox.registerName(...) and " + "OtpNode.whereis(...)"]; +register_and_whereis(suite) -> + []; +register_and_whereis(Config) when is_list(Config) -> + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "RegisterAndWhereis", + []). + +%%%----------------------------------------------------------------- +get_names(doc) -> + ["GetNames.java: " + "Test OtpNode.getNames()"]; +get_names(suite) -> + []; +get_names(Config) when is_list(Config) -> + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "GetNames", + []). + +%%%----------------------------------------------------------------- +boolean_atom(doc) -> + ["BooleanAtom.java: " + "Test OtpErlangAtom.booleanValue()"]; +boolean_atom(suite) -> + []; +boolean_atom(Config) when is_list(Config) -> + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "BooleanAtom", + []). + +%%%----------------------------------------------------------------- +node_ping(doc) -> + ["NodePing.java: " + "Test OtpNode.ping(java.lang.String node, long timeout)"]; +node_ping(suite) -> + []; +node_ping(Config) when is_list(Config) -> + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "NodePing", + [erlang:get_cookie(),node()]). + +%%%----------------------------------------------------------------- +mbox_ping(doc) -> + ["MboxPing.java: " + "Test OtpNode.createMbox(...) and OtpMbox.ping(...)"]; +mbox_ping(suite) -> + []; +mbox_ping(Config) when is_list(Config) -> + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "MboxPing", + [erlang:get_cookie(),node()]). + +%%%----------------------------------------------------------------- +java_erlang_send_receive(doc) -> + ["Test sending/receiving of erlang messages between erlang and java"]; +java_erlang_send_receive(suite) -> + []; +java_erlang_send_receive(Config) when is_list(Config) -> + send_receive(?java_erlang_send_receive, fun echo_loop/0, Config). + +echo_loop() -> + receive + {From,Msg} -> + ?dbg("erl_send_receive_server received ~p",[{From,Msg}]), + ?dbg("erl_send_receive_server sending ~p",[Msg]), + From ! Msg, + echo_loop(); + done -> + ok + end. + + +%%%----------------------------------------------------------------- +java_internal_send_receive_same_node(doc) -> + ["MboxSendReceive.java: " + "Test sending/receiving of erlang messages between mboxes " + "on the same java node."]; +java_internal_send_receive_same_node(suite) -> + []; +java_internal_send_receive_same_node(Config) when is_list(Config) -> + send_receive(?java_internal_send_receive_same_node, + fun() -> receive done -> ok end end, + Config). + +%%%----------------------------------------------------------------- +java_internal_send_receive_different_nodes(doc) -> + ["MboxSendReceive.java: " + "Test sending/receiving of erlang messages between mboxes " + "on different java nodes."]; +java_internal_send_receive_different_nodes(suite) -> + []; +java_internal_send_receive_different_nodes(Config) when is_list(Config) -> + send_receive(?java_internal_send_receive_different_nodes, + fun() -> receive done -> ok end end, + Config). + +%%%----------------------------------------------------------------- +java_internal_send_receive_self(doc) -> + ["MboxSendReceive.java: " + "Test sending/receiving of erlang messages from an mbox to itself"]; +java_internal_send_receive_self(suite) -> + []; +java_internal_send_receive_self(Config) when is_list(Config) -> + send_receive(?java_internal_send_receive_self, + fun() -> receive done -> ok end end, + Config). + +%%%----------------------------------------------------------------- +java_link_and_exit(doc) -> + ["MboxLinkUnlink.java: " + "Test link between erlang process and java mailbox." + "Java mailbox links and exits"]; +java_link_and_exit(suite) -> + []; +java_link_and_exit(Config) when is_list(Config) -> + LinkFun = + fun(Mbox) -> + Mbox ! {?java_link_and_exit,self(),?link_test_reason}, + receive after infinity -> ok end + end, + erl_java_link(LinkFun,java_link_and_exit,Config). + + +%%%----------------------------------------------------------------- +erl_link_and_exit(doc) -> + ["MboxLinkUnlink.java: " + "Test link between erlang process and java mailbox." + "Erlang process links and exits"]; +erl_link_and_exit(suite) -> + []; +erl_link_and_exit(Config) when is_list(Config) -> + LinkFun = fun(Mbox) -> + link(Mbox), + Mbox ! {?erl_link_and_exit,self(),?link_test_reason}, + receive ok -> ok end, + exit(?link_test_reason) + end, + erl_java_link(LinkFun,erl_link_and_exit,Config). + +%%%----------------------------------------------------------------- +erl_link_java_exit(doc) -> + ["MboxLinkUnlink.java: " + "Test link between erlang process and java mailbox." + "Erlang process links and java mailbox exits"]; +erl_link_java_exit(suite) -> + []; +erl_link_java_exit(Config) when is_list(Config) -> + LinkFun = fun(Mbox) -> + link(Mbox), + Mbox ! {?erl_link_java_exit,self(),?link_test_reason}, + receive after infinity -> ok end + end, + erl_java_link(LinkFun,erl_link_java_exit,Config). + + +%%%----------------------------------------------------------------- +java_link_erl_exit(doc) -> + ["MboxLinkUnlink.java: " + "Test link between erlang process and java mailbox." + "Java mailbox links and erlang process exits"]; +java_link_erl_exit(suite) -> + []; +java_link_erl_exit(Config) when is_list(Config) -> + LinkFun = + fun(Mbox) -> + Mbox ! {?java_link_erl_exit,self(),?link_test_reason}, + receive ok -> ok end, + exit(?link_test_reason) + end, + erl_java_link(LinkFun,java_link_erl_exit,Config). + +%%%----------------------------------------------------------------- +internal_link_linking_exits(doc) -> + ["MboxLinkUnlink.java: " + "Test link between two java mailboxes." + "The mailbox which creates the link is the one exiting"]; +internal_link_linking_exits(suite) -> + []; +internal_link_linking_exits(Config) when is_list(Config) -> + internal_link_unlink(?internal_link_linking_exits, + internal_link_linking_exits, + Config). + +%%%----------------------------------------------------------------- +internal_link_linked_exits(doc) -> + ["MboxLinkUnlink.java: " + "Test link between two java mailboxes." + "The mailbox which dies not create the link is the one exiting"]; +internal_link_linked_exits(suite) -> + []; +internal_link_linked_exits(Config) when is_list(Config) -> + internal_link_unlink(?internal_link_linked_exits, + internal_link_linked_exits, + Config). + +%%%----------------------------------------------------------------- +internal_unlink_linking_exits(doc) -> + ["MboxLinkUnlink.java: " + "Test link and unlink between two java mailboxes. " + "Mailbox1 creates a link to mailbox2 and removes it. " + "Then it creates another link and mailbox2 removes is. " + "Finally mailbox1 exits - mailbox2 must survive"]; +internal_unlink_linking_exits(suite) -> + []; +internal_unlink_linking_exits(Config) when is_list(Config) -> + internal_link_unlink(?internal_unlink_linking_exits, + internal_unlink_linking_exits, + Config). + +%%%----------------------------------------------------------------- +internal_unlink_linked_exits(doc) -> + ["MboxLinkUnlink.java: " + "Test link and unlink between two java mailboxes. " + "Mailbox1 creates a link to mailbox2 and removes it. " + "Then it creates another link and mailbox2 removes is. " + "Finally mailbox2 exits - mailbox1 must survive"]; +internal_unlink_linked_exits(suite) -> + []; +internal_unlink_linked_exits(Config) when is_list(Config) -> + internal_link_unlink(?internal_unlink_linked_exits, + internal_unlink_linked_exits, + Config). + +%%%----------------------------------------------------------------- +normal_exit(doc) -> + ["MboxLinkUnlink.java: " + "Test that mbox.close() uses exit reason 'normal', i.e. " + "that linked processes are not terminated."]; +normal_exit(suite) -> + []; +normal_exit(Config) when is_list(Config) -> + Fun = + fun() -> + register(erl_link_server,self()), + process_flag(trap_exit,true), + receive + {Main,Mbox} when is_pid(Main), is_pid(Mbox) -> + ?dbg("Erlang sending \"~p\"",[normal_exit]), + link(Mbox), + Pid = spawn_link(fun() -> + link(Mbox), + Mbox ! {?normal_exit}, + receive after infinity -> ok end + end), + receive + {'EXIT',Mbox,normal} -> + %% Make sure that we don't get the + %% exit signal from Pid, and Pid + %% should still be alive. + receive + {'EXIT',Pid,Reason} -> + ?dbg("Got unexpected exit signal: ~p", + [{'EXIT',Pid,Reason}]), + exit({unexpected,{'EXIT',Pid,Reason}}) + after 500 -> + true = erlang:is_process_alive(Pid), + exit(Pid,kill) + end, + receive done -> Main ! done end + after 1000 -> + receive + Other -> + ?dbg("Got garbage when waiting for exit:" + " ~p", [Other]), + Main ! done, + exit({got_unexpected,Other}) + after 0 -> + ok + end + end; + Other -> + ?dbg("Got garbage: ~p",[Other]), + exit(Other) + end + end, + + spawn_link(Fun), + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "MboxLinkUnlink", + [erlang:get_cookie(),node()]). + + +%%%----------------------------------------------------------------- +kill_mbox(doc) -> + ["MboxLinkUnlink.java: " + "Test that mbox.exit(new OtpErlangAtom(\"kill\") causes linked " + "processes to exit with reason 'killed', which can be trapped."]; +kill_mbox(suite) -> + {skip, "Not yet implemented"}; +kill_mbox(Config) when is_list(Config) -> + Fun = + fun() -> + register(erl_link_server,self()), + process_flag(trap_exit,true), + receive + {Main,Mbox} when is_pid(Main), is_pid(Mbox) -> + ?dbg("Erlang sending \"~p\"",[kill_mbox]), + Pid = spawn_link(fun() -> + process_flag(trap_exit,true), + link(Mbox), + Mbox ! {?kill_mbox}, + receive + {'EXIT',Mbox,killed} -> + exit(correct_reason); + {'EXIT',Mbox,R} -> + exit({faulty_reason,R}) + end + end), + receive + {'EXIT',Pid,{faulty_reason,Reason}} -> + receive done -> Main ! done end, + exit({faulty_reason,Reason}); + {'EXIT',Pid,im_killed} -> + receive done -> Main ! done end + after 1000 -> + receive + Other -> + ?dbg("Got garbage when waiting for exit:" + " ~p", [Other]), + Main ! done, + exit({got_unexpected,Other}) + after 0 -> + ok + end + end; + Other -> + ?dbg("Got garbage: ~p",[Other]), + exit(Other) + end + end, + + spawn_link(Fun), + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "MboxLinkUnlink", + [erlang:get_cookie(),node()]). + +%%%----------------------------------------------------------------- +kill_erl_proc_from_java(doc) -> + ["MboxLinkUnlink.java: " + "Test that mbox.exit(pid, new OtpErlangAtom(\"kill\") causes erlang " + "processes <pid> to be killed, even if trapping exits"]; +kill_erl_proc_from_java(suite) -> + []; +kill_erl_proc_from_java(Config) when is_list(Config) -> + LinkFun = fun(Mbox) -> + process_flag(trap_exit,true), + link(Mbox), + Mbox ! {?kill_erl_proc_from_java, self()}, + receive after infinity -> ok end + end, + erl_java_link(LinkFun,kill_erl_proc_from_java,killed,Config). + +%%%----------------------------------------------------------------- +kill_mbox_from_erlang(doc) -> + ["MboxLinkUnlink.java: " + "Test that exit(Mbox,kill) causes linked the Mbox to be killed, and" + "linked processes to exit with reason 'killed', even if trapping exits"]; +kill_mbox_from_erlang(suite) -> + {skip, "Not yet implemented"}; +kill_mbox_from_erlang(Config) when is_list(Config) -> + LinkFun = fun(Mbox) -> + link(Mbox), + Mbox ! {?kill_mbox_from_erlang}, + exit(Mbox,kill), + receive after infinity -> ok end + end, + erl_java_link(LinkFun,kill_mbox_from_erlang,killed,Config). + +%%%----------------------------------------------------------------- +erl_exit_with_reason_any_term(doc) -> + ["MboxLinkUnlink.java: " + "Test that any erlang term can be used as exit reason when erlang " + "process exits and is linked to an mbox."]; +erl_exit_with_reason_any_term(suite) -> + []; +erl_exit_with_reason_any_term(Config) when is_list(Config) -> + Reason = [hei,self(),{this,is,"a",[different,"reason"]}], + LinkFun = fun(Mbox) -> + link(Mbox), + Mbox ! {?erl_exit_with_reason_any_term,self(),Reason}, + receive ok -> ok end, + exit(Reason) + end, + erl_java_link(LinkFun,erl_exit_with_reason_any_term,Reason,Config). + +%%%----------------------------------------------------------------- +java_exit_with_reason_any_term(doc) -> + ["MboxLinkUnlink.java: " + "Test that any erlang term can be used as exit reason when mbox " + "exits and is linked to an erlang process."]; +java_exit_with_reason_any_term(suite) -> + []; +java_exit_with_reason_any_term(Config) when is_list(Config) -> + Reason = [hei,self(),{this,is,"a",[different,"reason"]}], + LinkFun = + fun(Mbox) -> + Mbox ! {?java_exit_with_reason_any_term,self(),Reason}, + receive after infinity -> ok end + end, + erl_java_link(LinkFun,java_exit_with_reason_any_term,Reason,Config). + + +%%%----------------------------------------------------------------- +status_handler_localStatus(doc) -> + ["NodeStatusHandler.java: " + "Test OtpNode.registerStatusHandler(...) and the callback " + "OtpNodeStatus.localStatus(...)"]; +status_handler_localStatus(suite) -> + []; +status_handler_localStatus(Config) when is_list(Config) -> + spawn_link(fun() -> + erl_status_server([{opt,{localStatus,"javanode1",true}}, + {localStatus,"javanode1",false}]) + end), + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "NodeStatusHandler", + [erlang:get_cookie(),node(),?status_handler_localStatus]). + +%%%----------------------------------------------------------------- +status_handler_remoteStatus(doc) -> + ["NodeStatusHandler.java: " + "Test OtpNode.registerStatusHandler(...) and the callback " + "OtpNodeStatus.remoteStatus(...)"]; +status_handler_remoteStatus(suite) -> + []; +status_handler_remoteStatus(Config) when is_list(Config) -> + spawn_link(fun() -> + erl_status_server([{opt,{localStatus,"javanode1",true}}, + {remoteStatus,"javanode2",true}, + {remoteStatus,"javanode2",false}]) + end), + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "NodeStatusHandler", + [erlang:get_cookie(),node(),?status_handler_remoteStatus]). + + +%%%----------------------------------------------------------------- +status_handler_connAttempt(doc) -> + ["NodeStatusHandler.java: " + "Test OtpNode.registerStatusHandler(...) and the callback " + "OtpNodeStatus.connAttempt(...)"]; +status_handler_connAttempt(suite) -> + []; +status_handler_connAttempt(Config) when is_list(Config) -> + spawn_link(fun() -> + erl_status_server([{opt,{localStatus,"javanode1",true}}, + {connAttempt,"unknown",true}, + {connAttempt,"javanode3",false}]) + end), + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "NodeStatusHandler", + [erlang:get_cookie(),node(),?status_handler_connAttempt]). + + +%%%----------------------------------------------------------------- +%%% INTERNAL FUNCTIONS +%%%----------------------------------------------------------------- +send_receive(TestCaseTag,Fun,Config) -> + spawn(fun() -> + register(erl_send_receive_server,self()), + receive + From when is_pid(From) -> + JavaNode = node(From), + [JavaNode] = nodes(hidden), + From ! {TestCaseTag,self()}, + Fun(), + unregister(erl_send_receive_server) + end + end), + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "MboxSendReceive", + [erlang:get_cookie(),node()]). + + +internal_link_unlink(Tag,Msg,Config) -> + Fun = + fun() -> + register(erl_link_server,self()), + process_flag(trap_exit,true), + receive + {Main,Mbox} when is_pid(Main), is_pid(Mbox) -> + ?dbg("Erlang sending \"~p\"",[Msg]), + Mbox ! {Tag,self(),?link_test_reason}, + receive done -> Main ! done end; + Other -> + ?dbg("Got garbage: ~p",[Other]), + exit(Other) + end + end, + + spawn_link(Fun), + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "MboxLinkUnlink", + [erlang:get_cookie(),node()]). + + +erl_java_link(LinkFun,Msg,Config) -> + erl_java_link(LinkFun,Msg,?link_test_reason,Config). + +erl_java_link(LinkFun,Msg,Reason,Config) -> + Fun = + fun() -> + register(erl_link_server,self()), + process_flag(trap_exit,true), + receive + {Main,Mbox} when is_pid(Mbox), is_pid(Mbox) -> + ?dbg("Erlang sending \"~p\"",[Msg]), + Pid = spawn_link(fun() -> LinkFun(Mbox) end), + receive + {'EXIT',Pid,Reason} -> + receive done -> Main ! done end + after 1000 -> + receive + Other -> + ?dbg("Got garbage when waiting for exit:" + " ~p", [Other]), + Main ! done, + exit({got_unexpected,Other}) + after 0 -> + ok + end + end; + Other -> + ?dbg("Got garbage: ~p",[Other]), + exit(Other) + end + end, + + spawn_link(Fun), + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + "MboxLinkUnlink", + [erlang:get_cookie(),node()]). + +erl_status_server(List) -> + register(erl_status_server,self()), + erl_status_server(List,undefined). +erl_status_server([{opt,{Tag,NodeName,Up}},{Tag2,NodeName2,Up2}|Rest],_) -> + receive + {Tag,Node,Up,From} = M -> + ?dbg("erl_status_server got: ~p",[M]), + true = lists:prefix(NodeName,Node), + erl_status_server([{Tag2,NodeName2,Up2}|Rest],From); + {Tag2,Node2,Up2,From2} = M2 -> + ?dbg("erl_status_server got: ~p",[M2]), + true = lists:prefix(NodeName2,Node2), + erl_status_server(Rest,From2) + end; +erl_status_server([{Tag,NodeName,Up}|Rest],_) -> + receive + {Tag,Node,Up,From} = M -> + ?dbg("erl_status_server got: ~p",[M]), + true = lists:prefix(NodeName,Node), + erl_status_server(Rest,From); + Other -> + ?dbg("erl_status_server got garbage: ~p",[Other]), + exit(Other) + end; +erl_status_server([],From) -> + From ! done. diff --git a/lib/jinterface/test/jinterface_SUITE_data/BooleanAtom.java b/lib/jinterface/test/jinterface_SUITE_data/BooleanAtom.java new file mode 100644 index 0000000000..9554d50c9f --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/BooleanAtom.java @@ -0,0 +1,46 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import com.ericsson.otp.erlang.*; + +class BooleanAtom { + + /* + Implements test case jinterface_SUITE:boolean_atom/1 + + Test the function OtpErlangAtom.booleanValue() + */ + + public static void main(String argv[]) { + + OtpErlangAtom atom = new OtpErlangAtom("true"); + if (!atom.booleanValue()) fail(1); + + atom = new OtpErlangAtom("false"); + if (atom.booleanValue()) fail(2); + + atom = new OtpErlangAtom("somethingelse"); + if (atom.booleanValue()) fail(3); + + } + + private static void fail(int reason) { + System.exit(reason); + } +} diff --git a/lib/jinterface/test/jinterface_SUITE_data/GetNames.java b/lib/jinterface/test/jinterface_SUITE_data/GetNames.java new file mode 100644 index 0000000000..3d2bc4ac84 --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/GetNames.java @@ -0,0 +1,68 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import java.util.ArrayList; +import com.ericsson.otp.erlang.*; + +class GetNames { + + /* + Implements test case jinterface_SUITE:get_names/1 + + */ + + public static void main(String argv[]) { + + try { + OtpNode node = new OtpNode("javanode"); + OtpMbox mbox1 = node.createMbox(); + mbox1.registerName("mbox1"); + node.createMbox("mbox2"); + OtpMbox mbox3 = node.createMbox(); + node.registerName("mbox3",mbox3); + + ArrayList existing_names = new ArrayList(); + existing_names.add("mbox3"); + existing_names.add("mbox2"); + existing_names.add("mbox1"); + + String[] names = node.getNames(); + if (names.length != existing_names.size()) fail(1); + + for(int i=0; i<names.length; i++) { + System.out.println("" + names[i]); + existing_names.remove(names[i]); + } + + if (!existing_names.isEmpty()) fail(2); + } + catch (Exception e) { + fail("" + e, 3); + } + } + + private static void fail(int reason) { + System.exit(reason); + } + + private static void fail(String str, int reason) { + System.out.println(str); + System.exit(reason); + } +} diff --git a/lib/jinterface/test/jinterface_SUITE_data/Makefile.src b/lib/jinterface/test/jinterface_SUITE_data/Makefile.src new file mode 100644 index 0000000000..2a3dca463b --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/Makefile.src @@ -0,0 +1,62 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2010. 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% +# + +# Note: This file *must* work for both Unix and Windows +# +# We use both `rm' (Unix) and `del' (Windows) for removing files, but +# with a `-' in front so that the error in not finding `rm' (`del') on +# Windows (Unix) is ignored. +# +# VxWorks? XXX +# + +.SUFFIXES: +.SUFFIXES: .java + + +JAVAC = @JAVAC@ +ERLC = erlc + +JINTERFACE_CLASSPATH = @jinterface_classpath@ + +CLASSPATH = .@PS@$(JINTERFACE_CLASSPATH)@PS@ + +JAVA_FILES = \ + Nodename.java \ + RegisterAndWhereis.java \ + GetNames.java \ + BooleanAtom.java \ + NodePing.java \ + MboxPing.java \ + MboxSendReceive.java \ + MboxLinkUnlink.java \ + NodeStatusHandler.java + +CLASS_FILES = $(JAVA_FILES:.java=.class) + +all: $(CLASS_FILES) + +clean: + -rm -f $(CLASS_FILES) + -del /F /Q $(CLASS_FILES) + +$(CLASS_FILES) : $(JAVA_FILES) + $(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES) + +# diff --git a/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java b/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java new file mode 100644 index 0000000000..5d1d097cc8 --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java @@ -0,0 +1,201 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import com.ericsson.otp.erlang.*; + +class MboxLinkUnlink { + + /* + Implements test case jinterface_SUITE:mbox_link_unlink/1 + + + + */ + + private static final int java_link_and_exit = 1; + private static final int erl_link_and_exit = 2; + private static final int erl_link_java_exit = 3; + private static final int java_link_erl_exit = 4; + private static final int internal_link_linking_exits = 5; + private static final int internal_link_linked_exits = 6; + private static final int internal_unlink_linking_exits = 7; + private static final int internal_unlink_linked_exits = 8; + private static final int normal_exit = 9; + private static final int kill_mbox = 10; + private static final int kill_erl_proc_from_java = 11; + private static final int kill_mbox_from_erlang = 12; + private static final int erl_exit_with_reason_any_term = 13; + private static final int java_exit_with_reason_any_term = 14; + + private static boolean dbg = true; + + + public static void main(String argv[]) { + + + //String cookie = argv[0]; + String erlNode = argv[1]; + OtpErlangObject expected = null; + boolean waiting = false; + + try { // + OtpNode node = new OtpNode("javanode"); + OtpMbox mainMbox = node.createMbox(); + + try { + // Initiate and set up connection to erlang process + OtpMbox mbox = node.createMbox(); + OtpMbox mbox2; + + OtpErlangObject[] msg = {mainMbox.self(),mbox.self()}; + mbox.send("erl_link_server", erlNode, new OtpErlangTuple(msg)); + OtpErlangObject o = mbox.receive(1000); + if (o == null) System.exit(1); + OtpErlangTuple tuple = (OtpErlangTuple)o; + int tag = (int)((OtpErlangLong)tuple.elementAt(0)).longValue(); + + switch (tag) { + + case java_exit_with_reason_any_term: + case java_link_and_exit: + dbg("Java got \"java_link_and_exit\" or " + + "\"java_exit_with_reason_any_term\""); + mbox.link((OtpErlangPid)tuple.elementAt(1)); + mbox.send((OtpErlangPid)tuple.elementAt(1), + new OtpErlangAtom("ok")); + mbox.exit(tuple.elementAt(2)); + break; + case erl_exit_with_reason_any_term: + case erl_link_and_exit: + dbg("Java got \"erl_link_and_exit\" or " + + "\"erl_exit_with_reason_any_term\""); + mbox.send((OtpErlangPid)tuple.elementAt(1), + new OtpErlangAtom("ok")); + waiting = true; + expected = tuple.elementAt(2); + mbox.receive(1000); + System.exit(2); + case erl_link_java_exit: + dbg("Java got \"erl_link_java_exit\""); + mbox.exit(tuple.elementAt(2)); + break; + case java_link_erl_exit: + dbg("Java got \"java_link_erl_exit\""); + mbox.link((OtpErlangPid)tuple.elementAt(1)); + mbox.send((OtpErlangPid)tuple.elementAt(1), + new OtpErlangAtom("ok")); + waiting = true; + expected = tuple.elementAt(2); + mbox.receive(1000); + System.exit(3); + case internal_link_linking_exits: + dbg("Java got \"internal_link_linking_exits\""); + mbox2 = node.createMbox(); + mbox.link(mbox2.self()); + mbox.exit(tuple.elementAt(2)); + waiting = true; + expected = tuple.elementAt(2); + mbox2.receive(1000); // hanging waiting for exit + System.exit(4); // got someting other than exit + case internal_link_linked_exits: + dbg("Java got \"internal_link_linked_exits\""); + mbox2 = node.createMbox(); + mbox.link(mbox2.self()); + mbox2.exit(tuple.elementAt(2)); + waiting = true; + expected = tuple.elementAt(2); + mbox.receive(1000); // hanging waiting for exit + System.exit(5); // got someting other than exit + case internal_unlink_linking_exits: + dbg("Java got \"internal_unlink_linking_exits\""); + mbox2 = node.createMbox(); + mbox.link(mbox2.self()); + mbox.unlink(mbox2.self()); + mbox.link(mbox2.self()); + mbox2.unlink(mbox.self()); + mbox2.exit(tuple.elementAt(2)); + if (mbox.receive(500)!=null) System.exit(6); + break; + case internal_unlink_linked_exits: + dbg("Java got \"internal_unlink_linked_exits\""); + mbox2 = node.createMbox(); + mbox.link(mbox2.self()); + mbox.unlink(mbox2.self()); + mbox.link(mbox2.self()); + mbox2.unlink(mbox.self()); + mbox.exit(tuple.elementAt(2)); + if (mbox2.receive(500)!=null) System.exit(7); + break; + case normal_exit: + dbg("Java got \"normal_exit\""); + mbox.close(); + break; + case kill_mbox: + dbg("Java got \"kill_mbox\""); + mbox.exit("kill"); + break; + case kill_erl_proc_from_java: + dbg("Java got \"kill_erl_proc_from_java\""); + mbox.exit((OtpErlangPid)tuple.elementAt(1),"kill"); + break; + case kill_mbox_from_erlang: + dbg("Java got \"kill_mbox_from_erlang\""); + /* This will make the testcase successful, but it is + not the correct way to do it... + Mbox should probably just die when the kill signal is + received from erlang (or other mbox). + + try { + mbox.receive(1000); + System.exit(8); + } + catch (OtpErlangExit exit) { + if(!(exit.reason().equals(new OtpErlangAtom("kill")))) + System.exit(9); + mbox.exit("killed"); + } + */ + break; + } + } + catch (OtpErlangExit exit) { + dbg("Java got exit: " + exit.reason()); + if(!(waiting && exit.reason().equals(expected))) + System.exit(10); + } + + OtpErlangAtom done = new OtpErlangAtom("done"); + mainMbox.send("erl_link_server", erlNode, done); + OtpErlangObject o = mainMbox.receive(1000); + if (o == null) System.exit(11); + else if (!((OtpErlangAtom)o).equals(done)) + System.exit(12); + + } + catch (Exception e) { + System.out.println("EXCEPTION: " + e); + System.exit(13); + } + } + + private static void dbg(String str) { + if (dbg) System.out.println(str); + } + +} diff --git a/lib/jinterface/test/jinterface_SUITE_data/MboxPing.java b/lib/jinterface/test/jinterface_SUITE_data/MboxPing.java new file mode 100644 index 0000000000..3a8497028e --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/MboxPing.java @@ -0,0 +1,50 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import com.ericsson.otp.erlang.*; + +class MboxPing { + + /* + Implements test case jinterface_SUITE:mbox_ping/1 + + Creates an OtpNode object with an OtpMbox object. The test_server + node is pinged from the OtpMbox. + */ + + public static void main(String argv[]) { + + try { + OtpNode node = new OtpNode("javanode",argv[0]); + OtpMbox mbox = node.createMbox(); + if (mbox.ping(argv[1],2000)) { + System.out.println("OtpMbox.ping(" + argv[1] + ") -> true"); + } + else { + System.out.println("ERROR: OtpMbox.ping(" + argv[1] + + ") -> false"); + System.exit(1); + } + } + catch (Exception e) { + System.out.println("" + e); + System.exit(2); + } + } +} diff --git a/lib/jinterface/test/jinterface_SUITE_data/MboxSendReceive.java b/lib/jinterface/test/jinterface_SUITE_data/MboxSendReceive.java new file mode 100644 index 0000000000..2db71bb5cd --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/MboxSendReceive.java @@ -0,0 +1,229 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import com.ericsson.otp.erlang.*; + +class MboxSendReceive { + + /* + Implements test case jinterface_SUITE:mbox_send_receive/1 + + Test OtpMbox.send(...) and OtpMbox.receive(...) + */ + + private static final boolean dbg = true; + private static final int recTime = 2000; + + private static final int java_erlang_send_receive = 1; + private static final int java_internal_send_receive_same_node = 2; + private static final int java_internal_send_receive_different_nodes = 3; + private static final int java_internal_send_receive_self = 4; + + public static void main(String argv[]) { + + String cookie = argv[0]; + String erlNode = argv[1]; + + OtpErlangObject[] msgArray = new OtpErlangObject[2]; + msgArray[1] = new OtpErlangAtom("hello world"); + OtpErlangTuple msg = null; + + try { + // Initiate: create javanode and mboxes + OtpNode node = new OtpNode("javanode",cookie); + OtpMbox mbox = node.createMbox(); + OtpMbox mbox2 = node.createMbox("java_echo_server2"); + + // Send the pid of mbox to erlang and wait for test case + // instruction: {TestCaseTag, Pid} + mbox.send("erl_send_receive_server", erlNode, mbox.self()); + OtpErlangObject o = mbox.receive(recTime); + if (o == null) System.exit(1); + OtpErlangTuple testCase = (OtpErlangTuple)o; + dbg("mbox received " + testCase); + int tag = (int)((OtpErlangLong)testCase.elementAt(0)).longValue(); + OtpErlangPid erlangPid = (OtpErlangPid)testCase.elementAt(1); + + switch (tag) { + + case java_erlang_send_receive: + + // Test1 (happened during initiation): + // Send mbox pid to erlang process with registered name. + // Erlang process sent back its pid to the mbox pid. + + // Test2: Register name and sent it to the erlang pid. Erlang + // process shall send message back to my registered name. + + mbox.registerName("java_echo_server"); + msgArray[0] = getNameNode("java_echo_server",node); + msg = new OtpErlangTuple(msgArray); + + dbg("java_echo_server sending " + msg); + mbox.send(erlangPid,msg); + + o = mbox.receive(recTime); + dbg("java_echo_server received " + o); + if (o == null) System.exit(2); + if (!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(3); + + // Test3: Same as Test2, but using a new mbox2 which + // got its name already when it is created - i.e. not + // using mbox.registerName + msgArray[0] = getNameNode("java_echo_server2",node); + msg = new OtpErlangTuple(msgArray); + + dbg("java_echo_server2 sending " + msg); + mbox2.send(erlangPid,msg); + + o = mbox2.receive(recTime); + dbg("java_echo_server received " + o); + if (o == null) System.exit(4); + if (!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(5); + + break; + + case java_internal_send_receive_same_node: + + // Test1: Sending message between mboxes on same node + // given registered name and node without host. + mbox.send("java_echo_server2","javanode",msgArray[1]); + o = mbox2.receive(recTime); + dbg("Mbox at same node: " + o); + if (o == null) System.exit(6); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(7); + + // Test2: Sending message between mboxes on same node + // given registered name and node with host. + mbox.send("java_echo_server2",mbox2.self().node(),msgArray[1]); + o = mbox2.receive(recTime); + dbg("Mbox at same node: " + o); + if (o == null) System.exit(8); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(9); + + // Test3: Sending message between mboxes on same node + // given registered name but not node. + mbox.send("java_echo_server2",msgArray[1]); + o = mbox2.receive(recTime); + dbg("Mbox at same node: " + o); + if (o == null) System.exit(10); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(11); + + // Test4: Sending message between mboxes on same node + // given pid. + mbox.send(mbox2.self(),msgArray[1]); + o = mbox2.receive(recTime); + dbg("Mbox at same node: " + o); + if (o == null) System.exit(12); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(13); + + break; + + case java_internal_send_receive_different_nodes: + + OtpNode node2 = new OtpNode("javanode2", cookie); + OtpMbox mboxOtherNode = node2.createMbox("mboxOtherNode"); + + // Test1: Sending message between mboxes on different + // nodes given registered name and node without host. + mbox.send("mboxOtherNode","javanode2",msgArray[1]); + o = mboxOtherNode.receive(recTime); + dbg("Mbox at same node: " + o); + if (o == null) System.exit(14); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(15); + + // Test2: Sending message between mboxes on different + // nodes given registered name and node with host. + mbox.send("mboxOtherNode",mboxOtherNode.self().node(), + msgArray[1]); + o = mboxOtherNode.receive(recTime); + dbg("Mbox at same node: " + o); + if (o == null) System.exit(16); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(17); + + // Test3: Sending message between mboxes on different + // nodes given pid. + mbox.send(mboxOtherNode.self(),msgArray[1]); + o = mboxOtherNode.receive(recTime); + dbg("Mbox at same node: " + o); + if (o == null) System.exit(18); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(19); + + break; + + + case java_internal_send_receive_self: + + // Test1: Sending message to myself given registered + // name and node without host. + mbox2.send("java_echo_server2","javanode",msgArray[1]); + o = mbox2.receive(recTime); + dbg("Self: " + o); + if (o == null) System.exit(18); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(19); + + // Test2: Sending message to myself given registered + // name and node with host. + mbox2.send("java_echo_server2",mbox2.self().node(),msgArray[1]); + o = mbox2.receive(recTime); + dbg("Self: " + o); + if (o == null) System.exit(20); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(21); + + // Test3: Sending message to myself given registered + // name but not host. + mbox2.send("java_echo_server2",msgArray[1]); + o = mbox2.receive(recTime); + dbg("Self: " + o); + if (o == null) System.exit(22); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(23); + + // Test4: Sending message to myself given pid. + mbox2.send(mbox2.self(),msgArray[1]); + o = mbox2.receive(recTime); + dbg("Self: " + o); + if (o == null) System.exit(24); + if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(25); + + break; + + } + + // Closing erl_send_receive_server by sending the atom 'done' to it. + mbox.send(erlangPid,new OtpErlangAtom("done")); + } + catch (Exception e) { + System.out.println("" + e); + System.exit(26); + } + } + + private static OtpErlangTuple getNameNode(String mboxName,OtpNode node) { + OtpErlangObject[] array = {new OtpErlangAtom(mboxName), + new OtpErlangAtom(node.node())}; + return new OtpErlangTuple(array); + + } + + private static void dbg(String str) { + if (dbg) System.out.println(str); + } + + +} diff --git a/lib/jinterface/test/jinterface_SUITE_data/NodePing.java b/lib/jinterface/test/jinterface_SUITE_data/NodePing.java new file mode 100644 index 0000000000..d0df5c46b5 --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/NodePing.java @@ -0,0 +1,83 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import com.ericsson.otp.erlang.*; + +class NodePing { + + /* + Implements test case jinterface_SUITE:node_ping/1 + + Creates three OtpNode objects. One with default cookie, one with + specified same cookie as the node running the test case and one + with a faulty cookie. From each OtpNode object the test_server + node is pinged. + + Also the default cookie node pings itself, and the node with the + specified cookie pings the node with default cookie. + */ + + public static void main(String argv[]) { + + String cookie = argv[0]; + String erlNode = argv[1]; + + try { + OtpNode node1 = new OtpNode("javanode1"); + ping(node1,erlNode,"Default cookie:",true,1); + ping(node1,node1.node(),"Self:",true,2); + ping(node1,"javanode1","Self:",true,3); + + OtpNode node2 = new OtpNode("javanode2",cookie); + ping(node2,erlNode,"Specified cookie:",true,4); + ping(node2,"javanode1","Javanode (no host):",true,5); + ping(node2,node1.node(),"Javanode:",true,6); + + OtpNode node3 = new OtpNode("javanode3","faultycookie"); + ping(node3,erlNode,"Faulty cookie:",false,7); + + // Test OtpNode.cookie() and OtpNode.setCookie(cookie) as well + if (!node3.cookie().equals("faultycookie")) + fail("Testing OtpNode.cookie()",8); + String old = node3.setCookie(cookie); + if (!old.equals("faultycookie")) + fail("Checking return of OtpNode.setCookie(cookie)",9); + ping(node3,erlNode,"setCookie:",true,10); + } + catch (Exception e) { + fail("" + e, 11); + } + } + + private static void ping(OtpNode node, String remote, String descr, + boolean expected, int reason) { + if ( node.ping(remote,2000) == expected ) { + System.out.println(descr + " ping(" + remote + ") -> " + expected); + } + else { + fail("ERROR: " + descr + " ping(" + remote +") -> " + !expected, + reason); + } + } + + private static void fail(String str, int reason) { + System.out.println(str); + System.exit(reason); + } +} diff --git a/lib/jinterface/test/jinterface_SUITE_data/NodeStatusHandler.java b/lib/jinterface/test/jinterface_SUITE_data/NodeStatusHandler.java new file mode 100644 index 0000000000..51ea15b5ef --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/NodeStatusHandler.java @@ -0,0 +1,168 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import com.ericsson.otp.erlang.*; + +public class NodeStatusHandler extends OtpNodeStatus { + /* + Implements java side of test cases in jinterface_SUITE.erl + + Test OtpNode.registerStatusHandler(...) and class OtpNodeStatus. + */ + + private static final boolean dbg = true; + private static final int recTime = 2000; + + private static String erlNode = null; + private static String cookie = null; + private static OtpMbox mbox = null; + + private static final int status_handler_localStatus = 1; + private static final int status_handler_remoteStatus = 2; + private static final int status_handler_connAttempt = 3; + + public static void main(String argv[]) { + + cookie = argv[0]; + erlNode = argv[1]; + + try { + OtpNode javaNode = new OtpNode("javanode", cookie); + mbox = javaNode.createMbox(); + } + catch (Exception e) { + dbg("EXCEPTION when creating javanode: " + e); + System.exit(1); + } + + try { + OtpNode node1 = new OtpNode("javanode1", cookie); + node1.registerStatusHandler(new NodeStatusHandler()); + + switch (Integer.parseInt(argv[2])) { + + case status_handler_localStatus: + dbg("java running test case \"status_handler_localStatus\""); + + Thread.sleep(200); // Give 'nodeup' message a chance + // before closing + node1.close(); + Thread.sleep(500); + break; + + case status_handler_remoteStatus: + dbg("java running test case \"status_handler_remoteStatus\""); + + OtpNode node2 = new OtpNode("javanode2", cookie); + node2.ping(node1.node(),2000); + node2.close(); + Thread.sleep(500); + break; + + case status_handler_connAttempt: + dbg("java running test case \"status_handler_connAttempt\""); + + OtpNode node3 = new OtpNode("javanode3","othercookie"); + node3.ping(node1.node(),2000); + node1.ping(node3.node(),2000); + break; + + } + + OtpErlangObject o = mbox.receive(recTime); + if (o == null) System.exit(2); + if (! ((OtpErlangAtom)o).atomValue().equals("done")) + System.exit(3); + + } + catch (Exception e) { + dbg("EXCEPTION: " + e); + System.exit(4); + } + + } + + + + public void remoteStatus(String node, boolean up, Object info) { + try { + dbg("Got remoteStatus: " + node + " " + up + " " + info); + OtpErlangObject[] msgArray = new OtpErlangObject[4]; + msgArray[0] = new OtpErlangAtom("remoteStatus"); + msgArray[1] = new OtpErlangString(node); + msgArray[2] = new OtpErlangBoolean(up); + msgArray[3] = mbox.self(); + OtpErlangTuple msg = new OtpErlangTuple(msgArray); + mbox.send("erl_status_server", erlNode, msg); + + } + catch (Exception e) { + dbg("EXCEPTION in remoteStatus: " + e + "\nArgs: " + + node + " " + up + " " + info); + System.exit(5); + } + } + + + public void localStatus(String node, boolean up, Object info) { + try { + dbg("Got localStatus: " + node + " " + up + " " + info); + OtpErlangObject[] msgArray = new OtpErlangObject[4]; + msgArray[0] = new OtpErlangAtom("localStatus"); + msgArray[1] = new OtpErlangString(node); + msgArray[2] = new OtpErlangBoolean(up); + msgArray[3] = mbox.self(); + OtpErlangTuple msg = new OtpErlangTuple(msgArray); + mbox.send("erl_status_server", erlNode, msg); + + } + catch (Exception e) { + dbg("EXCEPTION in localStatus: " + e + "\nArgs: " + + node + " " + up + " " + info); + System.exit(6); + } + } + + + + public void connAttempt(String node, boolean incoming, Object info) { + try { + dbg("Got connAttempt: " + node + " " + incoming + " " + info); + OtpErlangObject[] msgArray = new OtpErlangObject[4]; + msgArray[0] = new OtpErlangAtom("connAttempt"); + msgArray[1] = new OtpErlangString(node); + msgArray[2] = new OtpErlangBoolean(incoming); + msgArray[3] = mbox.self(); + OtpErlangTuple msg = new OtpErlangTuple(msgArray); + mbox.send("erl_status_server", erlNode, msg); + + } + catch (Exception e) { + dbg("EXCEPTION in connAttempt: " + e + "\nArgs: " + + node + " " + incoming + " " + info); + System.exit(7); + } + } + + + private static void dbg(String str) { + if (dbg) System.out.println(str); + } + +} diff --git a/lib/jinterface/test/jinterface_SUITE_data/Nodename.java b/lib/jinterface/test/jinterface_SUITE_data/Nodename.java new file mode 100644 index 0000000000..dc8cb9c49f --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/Nodename.java @@ -0,0 +1,54 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import com.ericsson.otp.erlang.*; + +class Nodename { + + /* + Implements test case jinterface_SUITE:nodename/1 + + */ + + public static void main(String argv[]) { + + String host = argv[0]; + + try { + OtpNode node = new OtpNode("javanode"); + System.out.println("Given host: " + host + + " Host: " + node.host() + + " Alive: " + node.alive() + + " Node: " + node.node()); + + if (!node.host().equals(host)) fail(1); + if (!node.alive().equals("javanode")) fail(2); + if (!node.node().equals("javanode@" + host)) fail(3); + } + catch (Exception e) { + System.out.println("" + e); + fail(4); + } + } + + private static void fail(int reason) { + System.exit(reason); + } + +} diff --git a/lib/jinterface/test/jinterface_SUITE_data/RegisterAndWhereis.java b/lib/jinterface/test/jinterface_SUITE_data/RegisterAndWhereis.java new file mode 100644 index 0000000000..9df01981b2 --- /dev/null +++ b/lib/jinterface/test/jinterface_SUITE_data/RegisterAndWhereis.java @@ -0,0 +1,79 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import com.ericsson.otp.erlang.*; + +class RegisterAndWhereis { + + /* + Implements test case jinterface_SUITE:register_and_whereis/1 + + */ + + public static void main(String argv[]) { + + try { + OtpNode node = new OtpNode("javanode"); + OtpMbox mbox1 = node.createMbox(); + mbox1.registerName("mbox1"); + OtpMbox mbox2 = node.createMbox("mbox2"); + OtpMbox mbox3 = node.createMbox(); + node.registerName("mbox3",mbox3); + + OtpErlangPid pid1 = mbox1.self(); + OtpErlangPid pid2 = mbox2.self(); + OtpErlangPid pid3 = mbox3.self(); + + if (!pid1.equals(node.whereis("mbox1"))) fail(1); + if (!pid1.equals(mbox1.whereis("mbox1"))) fail(2); + if (!pid1.equals(mbox2.whereis("mbox1"))) fail(3); + if (!pid1.equals(mbox3.whereis("mbox1"))) fail(4); + if (!pid2.equals(node.whereis("mbox2"))) fail(5); + if (!pid2.equals(mbox2.whereis("mbox2"))) fail(6); + if (!pid3.equals(node.whereis("mbox3"))) fail(7); + if (!pid3.equals(mbox3.whereis("mbox3"))) fail(8); + + node.closeMbox(mbox1); + mbox2.close(); + + if (node.whereis("mbox1") != null) fail(9); + if (node.whereis("mbox2") != null) fail(10); + if (mbox3.whereis("mbox1") != null) fail(11); + if (mbox3.whereis("mbox2") != null) fail(12); + + mbox3.close(); + if (mbox2.whereis("mbox3") != null) fail(13); + + + + } + catch (Exception e) { + fail("" + e, 14); + } + } + + private static void fail(int reason) { + System.exit(reason); + } + + private static void fail(String str, int reason) { + System.out.println(str); + System.exit(reason); + } +} diff --git a/lib/jinterface/test/jitu.erl b/lib/jinterface/test/jitu.erl new file mode 100644 index 0000000000..c57fb9bfad --- /dev/null +++ b/lib/jinterface/test/jitu.erl @@ -0,0 +1,156 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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% +%% + +%%---------------------------------------------------------------------- +%% JInterface Test Utils +%%---------------------------------------------------------------------- +-module(jitu). + + +-export([java/3, + java/4, + java/5, + init_all/1, + finish_all/1]). + +%% +%% Lots of stuff here are originating from java_client_erl_server_SUITE.erl +%% (ic) ... +%% + + + +java(Java, Dir, ClassAndArgs) -> + cmd(Java++" -classpath "++classpath(Dir)++" "++ClassAndArgs). + +java(Java, Dir, Class, Args) -> + java(Java, Dir, Class++" "++to_string(Args)). + +java(Java, Dir, Class, Args, Props) -> + java(Java, Dir, Props++" "++Class, Args). + + + + +init_all(Config) when list(Config) -> + case find_executable(["java"]) of + false -> {skip,"Found no Java VM"}; + Path -> [{java,Path}|Config] + end. + +finish_all(Config) -> Config. + +%% +%% Internal stuff... +%% + + +find_executable([]) -> + false; +find_executable([E|T]) -> + case os:find_executable(E) of + false -> find_executable(T); + Path -> Path + end. + +to_string([H|T]) when integer(H) -> + integer_to_list(H)++" "++to_string(T); +to_string([H|T]) when atom(H) -> + atom_to_list(H)++" "++to_string(T); +to_string([H|T]) when pid(H) -> + pid_to_list(H)++" "++to_string(T); +to_string([H|T]) when list(H) -> + lists:flatten(H)++" "++to_string(T); +to_string([]) -> []. + +% javac(Dir, File) -> +% cmd("javac -d "++Dir++" -classpath "++classpath(Dir)++" "++ +% filename:join(Dir, File)). + +classpath(Dir) -> + PS = + case os:type() of + {win32, _} -> ";"; + _ -> ":" + end, + Dir++PS++ + filename:join([code:lib_dir(jinterface),"priv","OtpErlang.jar"])++PS++ + case os:getenv("CLASSPATH") of + false -> ""; + Classpath -> Classpath + end. + + +cmd(Cmd) -> + PortOpts = [{line,80},eof,exit_status,stderr_to_stdout], + io:format("cmd: ~s~n", [Cmd]), + case catch open_port({spawn,Cmd}, PortOpts) of + Port when port(Port) -> + Result = cmd_loop(Port, []), + io:format("cmd res: ~w~n", [Result]), + case Result of + 0 -> ok; + ExitCode when integer(ExitCode) -> {error,ExitCode}; + Error -> Error + end; + {'EXIT',Reason} -> + {error,Reason} + end. + +cmd_loop(Port, Line) -> + receive + {Port,eof} -> + receive + {Port,{exit_status,ExitStatus}} -> + ExitStatus + after 1 -> + undefined + end; + {Port,{exit_status,ExitStatus}} -> + receive + {Port,eof} -> + ok after 1 -> ok end, + ExitStatus; + {Port,{data,{Tag,Data}}} -> + case Tag of + eol -> + io:put_chars([Line|cr_to_nl(Data)]), + io:nl(), + cmd_loop(Port, []); + noeol -> + cmd_loop(Port, [Line|cr_to_nl(Data)]) + end; + {'EXIT',Port,Reason} -> + {error,Reason}; + Other -> + io:format("WARNING: Unexpected at ~s:~p: ~p~n", + [?MODULE_STRING,?LINE,Other]), + cmd_loop(Port, Line) + end. + +%% Convert lonely CR to NL, and CRLF to NL +%% +cr_to_nl([$\r,$\n|T]) -> + [$\n|cr_to_nl(T)]; +cr_to_nl([$\r|T]) -> + [$\n|cr_to_nl(T)]; +cr_to_nl([C|T]) -> + [C|cr_to_nl(T)]; +cr_to_nl([]) -> + []. diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl new file mode 100644 index 0000000000..82dd3c2535 --- /dev/null +++ b/lib/jinterface/test/nc_SUITE.erl @@ -0,0 +1,736 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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(nc_SUITE). + + +-include("test_server.hrl"). +-include("test_server_line.hrl"). + + +-export([all/1, + init_per_suite/1, + end_per_suite/1, + init_per_testcase/2, + end_per_testcase/2]). + +-export([pid_roundtrip/1, + port_roundtrip/1, + ref_roundtrip/1, + new_float/1, + old_stuff/1, + binary_roundtrip/1, + decompress_roundtrip/1, + compress_roundtrip/1, + integer_roundtrip/1, + fun_roundtrip/1, + lists_roundtrip/1, + lists_roundtrip_2/1, + lists_iterator/1, + unicode/1, + unicode_list_to_string/1, + unicode_string_to_list/1, + connect/1]). + + +%% Top of cases + +all(doc) -> []; +all(suite) -> [pid_roundtrip, + port_roundtrip, + ref_roundtrip, + new_float, + old_stuff, + binary_roundtrip, + decompress_roundtrip, + compress_roundtrip, + integer_roundtrip, + fun_roundtrip, + lists_roundtrip, + lists_roundtrip_2, + lists_iterator, + unicode, + unicode_list_to_string, + unicode_string_to_list, + connect]. + + + + +init_per_suite(Config) when is_list(Config) -> + jitu:init_all(Config). + +end_per_suite(Config) -> + jitu:finish_all(Config). + + + +%% Add/remove watchdog before/after each test case. +%% +init_per_testcase(Case, Config) -> + T = case atom_to_list(Case) of + "unicode"++_ -> 240; + _ -> 20 + end, + WatchDog = test_server:timetrap(test_server:seconds(T)), + [{watchdog, WatchDog}| Config]. + +end_per_testcase(_Case, Config) -> + WatchDog = ?config(watchdog, Config), + test_server:timetrap_cancel(WatchDog). + + +%% +%% Test cases +%% + +pid_roundtrip(doc) -> []; +pid_roundtrip(suite) -> []; +pid_roundtrip(Config) when is_list(Config)-> + ThisNode = {node(), erlang:system_info(creation)}, + RemNode = {gurka@sallad, 2}, + do_echo([self(), + mk_pid(ThisNode, 4711, 4711), + mk_pid(ThisNode, 32767, 8191), + mk_pid(RemNode, 4711, 4711), + mk_pid(RemNode, 32767, 8191)], + Config). + +fun_roundtrip(doc) -> []; +fun_roundtrip(suite) -> []; +fun_roundtrip(Config) when is_list(Config)-> + do_echo([fun(A, B) -> A + B end, + fun(A) -> lists:reverse(A) end, + fun() -> ok end, + fun fun_roundtrip/1], + Config). + +port_roundtrip(doc) -> []; +port_roundtrip(suite) -> []; +port_roundtrip(Config) when is_list(Config)-> + ThisNode = {node(), erlang:system_info(creation)}, + RemNode = {gurka@sallad, 2}, + do_echo([hd(erlang:ports()), + mk_port(ThisNode, 4711), + mk_port(ThisNode, 268435455), + mk_port(RemNode, 4711), + mk_port(RemNode, 268435455)], + Config). + +ref_roundtrip(doc) -> []; +ref_roundtrip(suite) -> []; +ref_roundtrip(Config) when is_list(Config)-> + ThisNode = {node(), erlang:system_info(creation)}, + RemNode = {gurka@sallad, 2}, + do_echo([make_ref(), + mk_ref(ThisNode, [4711]), + mk_ref(ThisNode, [4711, 4711, 4711]), + mk_ref(ThisNode, [262143, 4294967295, 4294967295]), + mk_ref(RemNode, [4711]), + mk_ref(RemNode, [4711, 4711, 4711]), + mk_ref(RemNode, [262143, 4294967295, 4294967295])], + Config). + +new_float(doc) -> []; +new_float(suite) -> []; +new_float(Config) when is_list(Config)-> + Two16 = float(1 bsl 16), + X = math:sqrt(2), + Floats = lists:reverse(seq(1/X, 63, fun(Y) -> Y / Two16 end), + [0.0|seq(X, 63, fun(Y) -> Y * Two16 end)]), + io:format("~w", [Floats]), + do_echo(Floats, Config). + +old_stuff(doc) -> []; +old_stuff(suite) -> []; +old_stuff(Config) when is_list(Config)-> + Terms = [0.0,math:sqrt(2)], + OutTrans = + fun (D) -> + {self(),term_to_binary(D, [{minor_version,0}]),binary} + end, + InTrans = + fun (Echoer, D, {Echoer,D,binary}) -> + ok + end, + do_echo(Terms, Config, OutTrans, InTrans). + +binary_roundtrip(doc) -> []; +binary_roundtrip(suite) -> []; +binary_roundtrip(Config) when is_list(Config) -> + do_echo([<<17>>, + <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17>>, + <<3:2>>, + <<3,7:3>>, + <<>>], + Config). + +decompress_roundtrip(doc) -> []; +decompress_roundtrip(suite) -> []; +decompress_roundtrip(Config) when is_list(Config) -> + Terms = + [0.0, + math:sqrt(2), + <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,31:5>>, + make_ref()], + OutTrans = + fun (D) -> + {self(),term_to_binary(D, [compressed]),binary} + end, + InTrans = + fun (Echoer, D, {Echoer,D,binary}) -> + ok + end, + do_echo(Terms, Config, OutTrans, InTrans). + +compress_roundtrip(doc) -> []; +compress_roundtrip(suite) -> []; +compress_roundtrip(Config) when is_list(Config) -> + Terms = + [0.0, + math:sqrt(2), + <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,31:5>>, + make_ref()], + OutTrans = + fun (D) -> + {self(),D,compress} + end, + InTrans = + fun (Echoer, D, {Echoer,B,compress}) -> + D = binary_to_term(B) + end, + do_echo(Terms, Config, OutTrans, InTrans). + + + +integer_roundtrip(doc) -> []; +integer_roundtrip(suite) -> []; +integer_roundtrip(Config) when is_list(Config) -> + Xs = [1 bsl X || X <- [26,27,28,29,30,31,32,33, + 62,63,64,65, + 126,127,128,129]], + Terms = [0,1,-1,-2] + ++lists:flatmap(fun (X) -> [X-2,X-1,X,-X+1,-X,-X-1] end, + Xs), + io:format("~w", [Terms]), + OutTrans = + fun (V) -> + {self(),V,bigint} + end, + InTrans = + fun (Echoer, V, {Echoer,{V,W,X,L,U},bigint}) -> + Bitlength = bitlength(V), + {w,W} = {w,signum(V) * Bitlength}, + Y = V band 16#FFFFffffFFFFffff, + {y,Y} = {y,X band 16#FFFFffffFFFFffff}, + {l,L} = {l,if V =:= X, Bitlength < 64 -> 1; + true -> 0 end}, + {u,U} = {u,if V =:= Y, V >= 0, Bitlength =< 64 -> 1; + true -> 0 end} + end, + do_echo(Terms, Config, OutTrans, InTrans). + +signum(V) when is_integer(V), V > 0 -> 1; +signum(V) when is_integer(V), V < 0 -> -1; +signum(0) -> 0. + +bitlength(0) -> + 0; +bitlength(-1) -> + 0; +bitlength(V) when is_integer(V) -> + 1 + bitlength(V bsr 1). + + + +lists_roundtrip(doc) -> []; +lists_roundtrip(suite) -> []; +lists_roundtrip(Config) when is_list(Config) -> + Ls = [lists:seq(1,10), + lists:seq(11,17)++last_tail, + [{default}], + [car|cdr], + [[]], + []], + do_echo(Ls, Config). + + + +lists_roundtrip_2(doc) -> []; +lists_roundtrip_2(suite) -> []; +lists_roundtrip_2(Config) when is_list(Config) -> + Ls = [{[a,b],tail}, + {[c,d,e],tail}, + {[],tail}, + {[f],tail}, + {[g,h|i],tail}, + {[j,k,l|m],tail}, + {[n|o],tail}, + {[z,1,2,3,4],tail3}, + {[z,5,6,7],tail3}, + {[z,8,9],tail3}, + {[z,10],tail3}, + {[],tail3}, + {[z,11,12,13,14|15],tail3}, + {[z,16,17,18|19],tail3}, + {[z,20,21|22],tail3}, + {[z,23|24],tail3}, + {[z|25],tail3}, + {"abc123",sub3atom}, + {"abc",sub3atom} + ], + Trans = + fun ([_|T], tail) -> + T; + (L, tail) when is_list(L) -> + null; + ([_,_,_|T], tail3) -> + T; + (L, tail3) when is_list(L) -> + null; + ([_,_,_|L], sub3atom) -> + list_to_atom(L) + end, + OutTrans = + fun ({L,Twist}) -> + {self(),L,Twist} + end, + InTrans = + fun (Echoer, {L,Twist}, {Echoer,X,Twist}) -> + Y = Trans(L, Twist), + io:format("## ~w ~w ~w ~w~n", [L,Twist,X,Y]), + X = Y + end, + do_echo(Ls, Config, OutTrans, InTrans). + + + + +lists_iterator(doc) -> []; +lists_iterator(suite) -> []; +lists_iterator(Config) when is_list(Config) -> + Ls = [["able ","was ","I ","ere ","I ","saw ","elba"]], + do_echo(Ls, Config, + fun (L) -> {self(),L,strcat} end, + fun (Echoer, L, {Echoer,X,strcat}) -> + io:format("## ~p ~p~n", [L,X]), + X = lists:flatten(L) + end). + + + +unicode(doc) -> []; +unicode(suite) -> []; +unicode(Config) when is_list(Config) -> + S1 = "plain ascii", + S2 = "iso-latin ��� �", + S3 = "Codepoints... ��� \x{1000}", + S4 = [0,1,31,32,63,64,127,128,255], + S5 = [0,1,127,128,255,256,16#d7ff, + 16#e000,16#fffd,16#10000,16#10ffff], + Ss = [S1,S2,S3,S4,S5], + do_echo(unicode_cp_gen([{S,valid} || S <- Ss] ++ cp_gen(71)), Config, + fun ({L,invalid}) -> {self(),L,utf8}; + ({L,Tag}) -> {self(),L,Tag}; + ({L}) -> {self(),L} + end, + fun (Echoer, {L,invalid}=Out, {Echoer,X,utf8}=In) -> + case L of + X -> ok; + _ -> + ?t:fail({mismatch,Out,In}) + end; + (Echoer, {L,Tag}=Out, {Echoer,X,Tag}=In) -> + case unicode:characters_to_binary(L, utf8) of + X -> ok; + _ -> + ?t:fail({mismatch,Out,In}) + end; + (Echoer, {L}=Out, {Echoer,X}=In) -> + case L of + X -> ok; + _ -> + ?t:fail({mismatch,Out,In}) + end + end, ["unicode"]). + +%% Lazy wrapper to lazy list +unicode_cp_gen([{S,valid}|Ss]) -> + [{S,utf8},{S}|unicode_cp_gen(Ss)]; +unicode_cp_gen([{S,invalid}=St|Ss]) -> + [St,{S}|unicode_cp_gen(Ss)]; +unicode_cp_gen([]) -> + []; +unicode_cp_gen(Cont) when is_function(Cont, 0) -> + fun () -> + unicode_cp_gen(Cont()) + end. + + + +unicode_list_to_string(doc) -> []; +unicode_list_to_string(suite) -> []; +unicode_list_to_string(Config) when is_list(Config) -> + do_echo(cp_gen(73), Config, + fun ({L,_}) -> {self(),L,to_string_neg_int_list} end, + fun (Echoer, {L,invalid}=Out, {Echoer,X,_}=In) -> + case L of + X -> ok; + _ -> + ?t:fail({mismatch,Out,In}) + end; + (Echoer, {L,valid}=Out, {Echoer,X,_}=In) -> + B = unicode:characters_to_binary(L, unicode, {utf16,big}), + case [-D || <<D:16/big>> <= B] of + X -> ok; + _ -> + ?t:fail({mismatch,Out,In}) + end + end). + + + +unicode_string_to_list(doc) -> []; +unicode_string_to_list(suite) -> []; +unicode_string_to_list(Config) when is_list(Config) -> + do_echo(cp_gen(79), Config, + fun ({L,_}) -> {self(),L,to_neg_int_list} end, + fun (Echoer, {L,invalid}=Out, {Echoer,X,_}=In) -> + case L of + X -> ok; + _ -> + ?t:fail({mismatch,Out,In}) + end; + (Echoer, {L,valid}=Out, {Echoer,X,_}=In) -> + case [-C || C <- L] of + X -> ok; + _ -> + ?t:fail({mismatch,Out,In}) + end + end, ["unicode"]). + + +%% Lazy list +cp_gen(N) -> + cp_gen(N, -1, 16#110000). + +cp_gen(N, Start, End) -> + cp_gen(N, Start, End, cp_validity(Start), [], 0, [], 0). + +cp_gen(N, U, End, PrevValidity, Acc, Len, Ss, Ls) when Len >= N -> + cp_gen(N, U, End, PrevValidity, [], 0, [{Acc,PrevValidity}|Ss], Ls+1); +cp_gen(N, U, End, PrevValidity, Acc, Len, Ss, Ls) when Ls >= N -> + Ss ++ fun () -> + cp_gen(N, U, End, PrevValidity, Acc, Len, [], 0) + end; +cp_gen(_, U, End, _, Acc, _, Ss, _) when U > End -> + [{Acc,valid}|Ss]; +cp_gen(N, U, End, PrevValidity, Acc, Len, Ss, Ls) -> + Validity = cp_validity(U), + NextU = U+1, + {NextAcc,NextLen} = case Validity of + valid -> {[U|Acc],Len+1}; + invalid -> {Acc,Len} + end, + {NextSs,NextLs} = case Validity of + PrevValidity -> {Ss,Ls}; + valid -> {[{[U-1],PrevValidity}|Ss],Ls+1}; + invalid -> {[{[U],Validity}|Ss],Ls+1} + end, + cp_gen(N, NextU, End, Validity, NextAcc, NextLen, NextSs, NextLs). + +cp_validity(UnicodeCP) -> + try <<UnicodeCP/big-utf32>> of + _ -> valid + catch + error:_ -> invalid + end. + + + +connect(doc) -> []; +connect(suite) -> []; +connect(Config) when is_list(Config) -> + WD = filename:dirname(code:which(?MODULE)), + {ok,Other} = ?t:start_node(make_name(), slave, [{args,"-pa "++WD}]), + Action = + fun (Pid) -> + JName = node(Pid), + Hidden = [JName], + Pid ! {self(),Other}, + receive + {Pid,Other,true} -> + ok; + Unexpected1 -> + ?t:fail({result,Unexpected1}) + end, + Hidden = erlang:nodes(hidden), + Hidden = rpc:call(Other, erlang, nodes, [hidden]), + true = + rpc:call(Other, erlang, disconnect_node, [JName]), + [] = + rpc:call(Other, erlang, nodes, [hidden]), + Hidden = erlang:nodes(hidden), + %% Again + receive after 2000 -> ok end, + %% We have no way of knowing when the Java node + %% detects the nodedown. + Pid ! {self(),Other}, + receive + {Pid,Other,true} -> + ok; + Unexpected2-> + ?t:fail({result,Unexpected2}) + end, + Hidden = rpc:call(Other, erlang, nodes, [hidden]) + end, + run_server(connection_server, Config, Action, []). + + + +seq(_, 0, _) -> + []; +seq(X, N, Fun) -> + [X|seq(Fun(X), N-1, Fun)]. + +do_echo(DataList, Config) -> + do_echo(DataList, Config, + fun (D) -> % OutTrans + {self(),D} + end, + fun (Echoer, D, {Echoer,D}) -> % InTrans + ok + end, []). + +do_echo(DataList, Config, OutTrans, InTrans) -> + do_echo(DataList, Config, OutTrans, InTrans, []). + +do_echo(DataList, Config, OutTrans, InTrans, ExtraArgs) + when is_list(DataList), is_list(Config) -> + run_server(echo_server, Config, + fun (Echoer) -> + echo_loop(DataList, Echoer, OutTrans, InTrans, []) + end, + ExtraArgs). + +echo_loop([D|Ds], Echoer, OutTrans, InTrans, TermAcc) -> + OutMsg = OutTrans(D), + Echoer ! OutMsg, + io:format("echo_server ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]), + receive + Reply -> + io:format("echo_server ~p: receive ~P~n", + [self(),Reply,10]), + InTrans(Echoer, D, Reply) + end, + Term = case OutMsg of + {_, T, _} -> T; + {_, T} -> T + end, + echo_loop(Ds, Echoer, OutTrans, InTrans, [Term | TermAcc]); +echo_loop([], Echoer, _, _, TermAcc) -> + check_terms(Echoer, TermAcc); +%% Lazy list +echo_loop(Cont, Echoer, OutTrans, InTrans, TermAcc) + when is_function(Cont, 0) -> + check_terms(Echoer, TermAcc), + OutMsg = Echoer ! {self(),undefined,hash_clear}, + io:format("echo_server ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]), + receive + {Echoer,hash_cleared,hash_clear}=Reply -> + io:format("echo_server ~p: receive ~P~n", + [self(),Reply,10]), + ok; + Other -> + io:format("echo_server_terms unexpected ~p: receive ~P~n", + [self(),Other,10]), + ?t:fail({unexpected, Other}) + end, + echo_loop(Cont(), Echoer, OutTrans, InTrans, []). + +check_terms(Echoer, [Term | Rest]) -> + OutMsg = {self(),Term,hash_lookup}, + Echoer ! OutMsg, + io:format("check_terms ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]), + receive + {Echoer,true,hash_lookup} = ReplyMsg -> + io:format("check_terms ~p: receive ~P~n", + [self(),ReplyMsg,10]), + check_terms(Echoer, Rest); + Other -> + io:format("check_terms unexpected ~p: receive ~P~n", + [self(),Other,10]), + ?t:fail({unexpected, Other}) + end; +check_terms(_, []) -> + ok. + +run_server(Server, Config, Action, ExtraArgs) -> + Name = make_name(), + true = register(Name, self()), + JName = make_name(), + spawn_link(fun () -> + ok = jitu:java(?config(java, Config), + ?config(data_dir, Config), + atom_to_list(Server), + [JName, + erlang:get_cookie(), + node(), + Name]++ExtraArgs + ), + %,"-DOtpConnection.trace=3"), + Name ! {done, JName} + end), + receive + {Server, JName, Pid} -> + ?t:format("~w: ~p (~p)~n", + [Server, Pid, node(Pid)]), + ?t:format("nodes(hidden): ~p~n", + [nodes(hidden)]), + Action(Pid), + Pid ! bye, + receive + {done, JName} -> + ok + end; + Other -> + ?t:fail({unexpected,Other}) + end. + +%% +%% Utils... +%% + +make_name() -> + {A, B, C} = now(), + list_to_atom(atom_to_list(?MODULE) + ++ "-" ++ integer_to_list(A) + ++ "-" ++ integer_to_list(B) + ++ "-" ++ integer_to_list(C)). + + + +-define(VERSION_MAGIC, 131). + +-define(ATOM_EXT, 100). +-define(REFERENCE_EXT, 101). +-define(PORT_EXT, 102). +-define(PID_EXT, 103). +-define(NEW_REFERENCE_EXT, 114). + +uint32_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 32 -> + [(Uint bsr 24) band 16#ff, + (Uint bsr 16) band 16#ff, + (Uint bsr 8) band 16#ff, + Uint band 16#ff]; +uint32_be(Uint) -> + exit({badarg, uint32_be, [Uint]}). + + +uint16_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 16 -> + [(Uint bsr 8) band 16#ff, + Uint band 16#ff]; +uint16_be(Uint) -> + exit({badarg, uint16_be, [Uint]}). + +uint8(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 8 -> + Uint band 16#ff; +uint8(Uint) -> + exit({badarg, uint8, [Uint]}). + + + +mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) -> + mk_pid({atom_to_list(NodeName), Creation}, Number, Serial); +mk_pid({NodeName, Creation}, Number, Serial) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?PID_EXT, + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint32_be(Number), + uint32_be(Serial), + uint8(Creation)])) of + Pid when is_pid(Pid) -> + Pid; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_pid, [{NodeName, Creation}, Number, Serial]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end. + +mk_port({NodeName, Creation}, Number) when is_atom(NodeName) -> + mk_port({atom_to_list(NodeName), Creation}, Number); +mk_port({NodeName, Creation}, Number) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?PORT_EXT, + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint32_be(Number), + uint8(Creation)])) of + Port when is_port(Port) -> + Port; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_port, [{NodeName, Creation}, Number]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end. + +mk_ref({NodeName, Creation}, Numbers) when is_atom(NodeName), + is_integer(Creation), + is_list(Numbers) -> + mk_ref({atom_to_list(NodeName), Creation}, Numbers); +mk_ref({NodeName, Creation}, [Number]) when is_list(NodeName), + is_integer(Creation), + is_integer(Number) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?REFERENCE_EXT, + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint32_be(Number), + uint8(Creation)])) of + Ref when is_reference(Ref) -> + Ref; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_ref, [{NodeName, Creation}, [Number]]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end; +mk_ref({NodeName, Creation}, Numbers) when is_list(NodeName), + is_integer(Creation), + is_list(Numbers) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?NEW_REFERENCE_EXT, + uint16_be(length(Numbers)), + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint8(Creation), + lists:map(fun (N) -> + uint32_be(N) + end, + Numbers)])) of + Ref when is_reference(Ref) -> + Ref; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_ref, [{NodeName, Creation}, Numbers]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end. diff --git a/lib/jinterface/test/nc_SUITE_data/Makefile.src b/lib/jinterface/test/nc_SUITE_data/Makefile.src new file mode 100644 index 0000000000..3d131250be --- /dev/null +++ b/lib/jinterface/test/nc_SUITE_data/Makefile.src @@ -0,0 +1,53 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2010. 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% +# + +# Makefile.src for java_client_erl_server test +# Note: This file *must* work for both Unix and Windows +# +# We use both `rm' (Unix) and `del' (Windows) for removing files, but +# with a `-' in front so that the error in not finding `rm' (`del') on +# Windows (Unix) is ignored. +# +# VxWorks? XXX +# + +.SUFFIXES: +.SUFFIXES: .java + + +JAVAC = @JAVAC@ +ERLC = erlc + +JINTERFACE_CLASSPATH = @jinterface_classpath@ + +CLASSPATH = .@PS@$(JINTERFACE_CLASSPATH)@PS@ + +JAVA_FILES = echo_server.java connection_server.java +CLASS_FILES = $(JAVA_FILES:.java=.class) + +all: $(CLASS_FILES) + +clean: + -rm -f $(CLASS_FILES) + -del /F /Q $(CLASS_FILES) + +$(CLASS_FILES) : $(JAVA_FILES) + $(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES) + +# diff --git a/lib/jinterface/test/nc_SUITE_data/connection_server.java b/lib/jinterface/test/nc_SUITE_data/connection_server.java new file mode 100644 index 0000000000..19ed1c7d5c --- /dev/null +++ b/lib/jinterface/test/nc_SUITE_data/connection_server.java @@ -0,0 +1,96 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import com.ericsson.otp.erlang.*; + +public class connection_server { + static java.lang.String Name = "connection_server"; + + public static void main(String[] argv) { + try { + System.out.println("connection_server booting..."); + + for (int j = 0; j < argv.length; j++) + System.out.println("argv[" + j + "] = \"" + argv[j] + "\""); + + if (argv.length != 4) { + System.out.println("Wrong number of arguments!"); + System.exit(1); + } + + // Start node and mbox + OtpNode node = new OtpNode(argv[0], argv[1]); + OtpMbox mbox = node.createMbox(); + if (! mbox.registerName(Name)) { + System.out.println("Could not register name " + Name); + System.exit(3); + } + + // Announce our presence + OtpErlangObject[] amsg = new OtpErlangObject[3]; + amsg[0] = new OtpErlangAtom(Name); + amsg[1] = new OtpErlangAtom(argv[0]); + amsg[2] = mbox.self(); + OtpErlangTuple atuple = new OtpErlangTuple(amsg); + mbox.send(argv[3], argv[2], atuple); + + // Do connects ... + while (true) { + OtpErlangObject o = mbox.receive(); + if (o == null) + continue; + if (o instanceof OtpErlangTuple) { + OtpErlangTuple msg = (OtpErlangTuple) o; + OtpErlangPid from = (OtpErlangPid)(msg.elementAt(0)); + OtpErlangAtom conn_node = (OtpErlangAtom) msg.elementAt(1); + + System.out.println("Got request to connect to: " + + conn_node); + OtpErlangObject[] rmsg = new OtpErlangObject[3]; + rmsg[0] = mbox.self(); + rmsg[1] = conn_node; + if (node.ping(conn_node.atomValue(), 1000)) { + System.out.println("Successfully connected to " + + conn_node.toString()); + rmsg[2] = new OtpErlangAtom("true"); + } + else { + System.out.println("Failed to connect to " + + conn_node.toString()); + rmsg[2] = new OtpErlangAtom("false"); + } + + OtpErlangTuple rtuple = new OtpErlangTuple(rmsg); + + mbox.send(from, rtuple); + } + else { // probably 'bye' + System.out.println("connection_server halting..."); + System.exit(0); + } + } + } + catch (Exception e) { + System.out.println("" + e); + System.exit(2); + } + + } + +} diff --git a/lib/jinterface/test/nc_SUITE_data/echo_server.java b/lib/jinterface/test/nc_SUITE_data/echo_server.java new file mode 100644 index 0000000000..0550e4beb1 --- /dev/null +++ b/lib/jinterface/test/nc_SUITE_data/echo_server.java @@ -0,0 +1,261 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2010. 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% + */ + +import java.io.UnsupportedEncodingException; +import java.util.HashSet; + +import com.ericsson.otp.erlang.OtpErlangAtom; +import com.ericsson.otp.erlang.OtpErlangBinary; +import com.ericsson.otp.erlang.OtpErlangBoolean; +import com.ericsson.otp.erlang.OtpErlangException; +import com.ericsson.otp.erlang.OtpErlangInt; +import com.ericsson.otp.erlang.OtpErlangList; +import com.ericsson.otp.erlang.OtpErlangLong; +import com.ericsson.otp.erlang.OtpErlangObject; +import com.ericsson.otp.erlang.OtpErlangPid; +import com.ericsson.otp.erlang.OtpErlangString; +import com.ericsson.otp.erlang.OtpErlangTuple; +import com.ericsson.otp.erlang.OtpExternal; +import com.ericsson.otp.erlang.OtpInputStream; +import com.ericsson.otp.erlang.OtpMbox; +import com.ericsson.otp.erlang.OtpNode; +import com.ericsson.otp.erlang.OtpOutputStream; + +public class echo_server { + private static boolean debug = false; + + public static void main(final String[] argv) { + try { + System.out.println("echo_server booting..."); + + for (int j = 0; j < argv.length; j++) { + System.out.println("argv[" + j + "] = \"" + argv[j] + "\""); + } + + if (argv.length != 4 && argv.length != 5) { + System.out.println("Wrong number of arguments!"); + System.exit(1); + } + + // Start node and mbox + final OtpNode node = new OtpNode(argv[0], argv[1]); + if (argv.length == 5 && argv[4].equals("unicode")) { + System.out.println("Setting unicode string mode."); + node.setFlags(OtpInputStream.DECODE_INT_LISTS_AS_STRINGS); + } + final OtpMbox mbox = node.createMbox(); + + // Announce our presence + final OtpErlangObject[] amsg = new OtpErlangObject[3]; + amsg[0] = new OtpErlangAtom("echo_server"); + amsg[1] = new OtpErlangAtom(argv[0]); + amsg[2] = mbox.self(); + final OtpErlangTuple atuple = new OtpErlangTuple(amsg); + mbox.send(argv[3], argv[2], atuple); + + // Do echoing... + while (true) { + final OtpErlangObject o = mbox.receive(); + if (o == null) { + continue; + } + if (o instanceof OtpErlangTuple) { + final OtpErlangTuple msg = (OtpErlangTuple) o; + final int arity = msg.arity(); + if (arity < 2) { + System.out + .println("Arity < 2; echo_server aborting..."); + System.exit(2); + } else if (arity == 2) { + final OtpErlangPid from = (OtpErlangPid) msg + .elementAt(0); + if (debug) System.out.println("Echoing: " + + msg.elementAt(1)); + + final OtpErlangObject[] rmsg = new OtpErlangObject[2]; + rmsg[0] = mbox.self(); + rmsg[1] = msg.elementAt(1); + final OtpErlangTuple rtuple = new OtpErlangTuple(rmsg); + + mbox.send(from, rtuple); + continue; + } else if (arity == 3) { + echoTwisted(mbox, msg); + continue; + } else { + System.out + .println("Arity > 3; echo_server aborting..."); + System.exit(2); + } + } else if (o instanceof OtpErlangAtom) { + OtpErlangAtom a = (OtpErlangAtom) o; + if (a.atomValue().equals("debug")) { + debug = true; + } else if (a.atomValue().equals("bye")) { + System.out.println("echo_server halting..."); + System.exit(0); + } + } else { // probably 'bye' + } + System.out.println("Unexpected: " + o + + " echo_server aborting..."); + System.exit(2); + } + } catch (final Exception e) { + System.out.println("" + e); + System.exit(2); + } + } + + private static void echoTwisted(final OtpMbox mbox, + final OtpErlangTuple msg) + throws OtpErlangException { + final OtpErlangPid from = (OtpErlangPid) msg.elementAt(0); + + final OtpErlangObject[] rmsg = new OtpErlangObject[3]; + if (debug) System.out.println("Echo in: " + msg); + rmsg[0] = mbox.self(); + rmsg[1] = twist(msg.elementAt(1), rmsg[2] = msg.elementAt(2)); + final OtpErlangTuple rtuple = new OtpErlangTuple(rmsg); + if (debug) System.out.println("Echo out: " + rtuple); + + mbox.send(from, rtuple); + } + + private static HashSet<OtpErlangObject> hash_set = + new HashSet<OtpErlangObject>(); + + private static OtpErlangObject twist(final OtpErlangObject i, + final OtpErlangObject t) throws OtpErlangException { + hash_set.add(i); + if (t instanceof OtpErlangAtom) { + final String atomValue = ((OtpErlangAtom) t).atomValue(); + if (atomValue.equals("binary") && i instanceof OtpErlangBinary) { + final OtpErlangBinary b = (OtpErlangBinary) i; + final OtpInputStream bis = new OtpInputStream(b.binaryValue(), + 0); + final OtpErlangObject o = bis.read_any(); + return o; + } else if (atomValue.equals("compress")) { + final OtpOutputStream oos = new OtpOutputStream(); + oos.write1(OtpExternal.versionTag); + oos.write_compressed(i); + final OtpErlangBinary o = + new OtpErlangBinary(oos.toByteArray()); + return o; + } else if (atomValue.equals("bigint") + && i instanceof OtpErlangLong) { + final OtpErlangLong l = (OtpErlangLong) i; + final int w = l.signum() * l.bitLength(); + final OtpErlangLong x = new OtpErlangLong(l.longValue()); + final java.math.BigInteger b = l.bigIntegerValue(); + System.out.println("long: " + l + ": " + w + ": " + b.signum() + * b.bitLength() + ": " + x + ": " + l.isLong() + ": " + + l.isULong()); + return new OtpErlangTuple(new OtpErlangObject[] { l, + new OtpErlangInt(w), x, + new OtpErlangInt(l.isLong() ? 1 : 0), + new OtpErlangInt(l.isULong() ? 1 : 0) }); + } else if (atomValue.equals("tail") + && i instanceof OtpErlangList) { + final OtpErlangObject o = ((OtpErlangList) i).getTail(); + if (o == null) { + return new OtpErlangAtom("null"); + } + return o; + } else if (atomValue.equals("tail3") + && i instanceof OtpErlangList) { + final OtpErlangObject o = ((OtpErlangList) i).getNthTail(3); + if (o == null) { + return new OtpErlangAtom("null"); + } + return o; + } else if (atomValue.equals("strcat") + && i instanceof OtpErlangList) { + final java.lang.StringBuffer b = new java.lang.StringBuffer(); + final OtpErlangList l = (OtpErlangList) i; + for (final OtpErlangObject j : l) { + final OtpErlangString k = (OtpErlangString) j; + b.append(k.stringValue()); + } + final OtpErlangObject o = new OtpErlangString(b.toString()); + return o; + } else if (atomValue.equals("sub3atom") + && i instanceof OtpErlangString) { + final OtpErlangString s = (OtpErlangString) i; + final OtpErlangAtom o = new OtpErlangAtom(s.stringValue() + .substring(3)); + return o; + } else if (atomValue.equals("utf8")) { + if (i instanceof OtpErlangString) { + final OtpErlangString s = (OtpErlangString) i; + byte[] bytes; + try { + bytes = s.stringValue().getBytes("UTF-8"); + } catch (final UnsupportedEncodingException e) { + bytes = new byte[] { 'e', 'r', 'r', 'o', 'r' }; + } + final OtpErlangBinary b = new OtpErlangBinary(bytes); + return b; + } + } else if(atomValue.equals("to_string_neg_int_list")) { + OtpErlangString oes = null; + if (i instanceof OtpErlangString) { + oes = (OtpErlangString) i; + } else if (i instanceof OtpErlangList) { + OtpErlangList oel = (OtpErlangList) i; + try { + oes = new OtpErlangString(oel); + } catch (final Exception e) { + } + } + if (oes != null) { + String s = oes.stringValue(); + int n = s.length(); + OtpErlangObject l[] = new OtpErlangObject[n]; + for (int j = 0; j < n; j++) { + int c = s.charAt(j); + l[j] = new OtpErlangInt(-c); + } + return new OtpErlangList(l); + } + } else if(atomValue.equals("to_neg_int_list")) { + if (i instanceof OtpErlangString) { + OtpErlangString oes = (OtpErlangString) i; + OtpErlangList oel = new OtpErlangList(oes.stringValue()); + int n = oel.arity(); + OtpErlangObject l[] = new OtpErlangObject[n]; + for (int j = 0; j < n; j++) { + OtpErlangLong c = (OtpErlangLong) oel.elementAt(j); + l[j] = new OtpErlangInt(-c.intValue()); + } + return new OtpErlangList(l); + } + } else if (atomValue.equals("hash_lookup")) { + final boolean exists = hash_set.contains(i); + final OtpErlangBoolean b = new OtpErlangBoolean(exists); + return b; + } else if (atomValue.equals("hash_clear")) { + hash_set.clear(); + return new OtpErlangAtom("hash_cleared"); + } + } + return i; + } +} diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk index 6b5719d7c5..26613febbf 100644 --- a/lib/jinterface/vsn.mk +++ b/lib/jinterface/vsn.mk @@ -1,19 +1 @@ -## -## %CopyrightBegin% -## -## Copyright Ericsson AB 2000-2010. 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% - JINTERFACE_VSN = 1.5.3 diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml index 4e65bf46f8..9a62b45d63 100644 --- a/lib/kernel/doc/src/erl_ddll.xml +++ b/lib/kernel/doc/src/erl_ddll.xml @@ -177,7 +177,7 @@ <name>demonitor(MonitorRef) -> ok</name> <fsummary>Remove a monitor for a driver</fsummary> <type> - <v>MonitorRef = ref()</v> + <v>MonitorRef = reference()</v> </type> <desc> <p>Removes a driver monitor in much the same way as @@ -185,7 +185,7 @@ monitors. See <seealso marker="#monitor/2">monitor/2</seealso>, <seealso marker="#try_load/3">try_load/3</seealso> and <seealso marker="#try_unload/2">try_unload/2</seealso> for details about how to create driver monitors.</p> <p>The function throws a <c>badarg</c> exception if the - parameter is not a ref(). </p> + parameter is not a reference(). </p> </desc> </func> <func> @@ -400,7 +400,7 @@ <v>Item = {Name, When}</v> <v>Name = atom() | string()</v> <v>When = loaded | unloaded | unloaded_only</v> - <v>MonitorRef = ref()</v> + <v>MonitorRef = reference()</v> </type> <desc> <p>This function creates a driver monitor and works in many @@ -449,7 +449,7 @@ eventually lead to one of the following messages being sent:</p> <taglist> - <tag><em>{'UP', ref(), driver, Name, loaded}</em></tag> + <tag><em>{'UP', reference(), driver, Name, loaded}</em></tag> <item> <p>This message is sent, either immediately if the driver is already loaded and no reloading is @@ -459,7 +459,7 @@ expected to know if reloading is demanded prior to creating a monitor for loading.</p> </item> - <tag><em>{'UP', ref(), driver, Name, permanent}</em></tag> + <tag><em>{'UP', reference(), driver, Name, permanent}</em></tag> <item> <p>This message will be sent if reloading was expected, but the (old) driver made itself @@ -467,7 +467,7 @@ sent if the driver was permanent or statically linked in when trying to create the monitor.</p> </item> - <tag><em>{'DOWN', ref(), driver, Name, load_cancelled}</em></tag> + <tag><em>{'DOWN', reference(), driver, Name, load_cancelled}</em></tag> <item> <p>This message will arrive if reloading was underway, but the <seealso marker="#users">user</seealso> having requested @@ -476,7 +476,7 @@ (or <c>unload/1</c>/<c>unload_driver/1</c>) again before it was reloaded.</p> </item> - <tag><em>{'DOWN', ref(), driver, Name, {load_failure, Failure}}</em></tag> + <tag><em>{'DOWN', reference(), driver, Name, {load_failure, Failure}}</em></tag> <item> <p>This message will arrive if reloading was underway but the loading for some reason @@ -500,7 +500,7 @@ <p>A driver monitor for unload will eventually result in one of the following messages being sent:</p> <taglist> - <tag><em>{'DOWN', ref(), driver, Name, unloaded}</em></tag> + <tag><em>{'DOWN', reference(), driver, Name, unloaded}</em></tag> <item> <p>The driver instance monitored is now unloaded. As the unload might have been due to a @@ -508,7 +508,7 @@ again have been loaded when this message arrives.</p> </item> - <tag><em>{'UP', ref(), driver, Name, unload_cancelled}</em></tag> + <tag><em>{'UP', reference(), driver, Name, unload_cancelled}</em></tag> <item> <p>This message will be sent if unloading was expected, but while the driver was waiting for @@ -525,7 +525,7 @@ similar to an <c>unloaded</c> monitor, but does never result in this message.</p> </item> - <tag><em>{'UP', ref(), driver, Name, permanent}</em></tag> + <tag><em>{'UP', reference(), driver, Name, permanent}</em></tag> <item> <p>This message will be sent if unloading was expected, but the driver made itself @@ -539,7 +539,7 @@ <item> <p>A monitor created as <c>unloaded_only</c> behaves exactly as one created as <c>unloaded</c> with the - exception that the <c>{'UP', ref(), driver, Name, unload_cancelled}</c> message will never be + exception that the <c>{'UP', reference(), driver, Name, unload_cancelled}</c> message will never be sent, but the monitor instead persists until the driver <em>really</em> gets unloaded.</p> </item> @@ -626,7 +626,7 @@ <v>ReloadOption = pending_driver | pending</v> <v>Status = loaded | already_loaded | PendingStatus </v> <v>PendingStatus = pending_driver | pending_process</v> - <v>Ref = ref()</v> + <v>Ref = reference()</v> <v>ErrorDesc = ErrorAtom | OpaqueError</v> <v>ErrorAtom = linked_in_driver | inconsistent | permanent | not_loaded_by_this_process | not_loaded | pending_reload | pending_process</v> </type> @@ -650,7 +650,7 @@ registered and a corresponding <c>try_unload</c> is expected sometime in the future.</p> </item> - <tag><em>{ok, pending_driver}</em>or <em>{ok, pending_driver, ref()}</em></tag> + <tag><em>{ok, pending_driver}</em>or <em>{ok, pending_driver, reference()}</em></tag> <item> <p>The load request is registered, but the loading is delayed due to the fact that an earlier instance of the @@ -665,7 +665,7 @@ set. In other words, this return value will always need to be handled!</p> </item> - <tag><em>{ok, pending_process}</em>or <em>{ok, pending_process, ref()}</em></tag> + <tag><em>{ok, pending_process}</em>or <em>{ok, pending_process, reference()}</em></tag> <item> <p>The load request is registered, but the loading is delayed due to the fact that an earlier instance of the @@ -683,7 +683,7 @@ about when the driver is <em>actually</em> loaded. This can be achieved by using the <c>{monitor, PendingOption}</c> option.</p> <p>When monitoring is requested, and a corresponding <c>{ok, pending_driver}</c> or <c>{ok, pending_process}</c> would be - returned, the function will instead return a tuple <c>{ok, PendingStatus, ref()}</c> and the process will, at a later + returned, the function will instead return a tuple <c>{ok, PendingStatus, reference()}</c> and the process will, at a later time when the driver actually gets loaded, get a monitor message. The monitor message one can expect is described in the <seealso marker="#monitor/2">monitor/2</seealso> @@ -760,7 +760,7 @@ <p>A <c>MonitorOption</c> tells <c>try_load/3</c> to trigger a driver monitor under certain conditions. When the monitor is triggered, the - function will return a three-tuple <c>{ok, PendingStatus, ref()}</c>, where the <c>ref()</c> is + function will return a three-tuple <c>{ok, PendingStatus, reference()}</c>, where the <c>reference()</c> is the monitor ref for the driver monitor.</p> <p>Only one <c>MonitorOption</c> can be specified and it is either the atom <c>pending</c>, which means @@ -891,7 +891,7 @@ <v>MonitorOption = pending_driver | pending</v> <v>Status = unloaded | PendingStatus </v> <v>PendingStatus = pending_driver | pending_process</v> - <v>Ref = ref()</v> + <v>Ref = reference()</v> <v>ErrorAtom = linked_in_driver | not_loaded | not_loaded_by_this_process | permanent</v> </type> <desc> @@ -943,7 +943,7 @@ ports using it and there are no more <seealso marker="#users">users</seealso> requiring it to be loaded.</p> </item> - <tag><em>{ok, pending_driver}</em>or <em>{ok, pending_driver, ref()}</em></tag> + <tag><em>{ok, pending_driver}</em>or <em>{ok, pending_driver, reference()}</em></tag> <item> <p>This return value indicates that this call removed the last <seealso marker="#users">user</seealso> from the @@ -957,7 +957,7 @@ in that case, however transient. Monitors are as always useful to detect when the driver is really unloaded.</p> </item> - <tag><em>{ok, pending_process}</em>or <em>{ok, pending_process, ref()}</em></tag> + <tag><em>{ok, pending_process}</em>or <em>{ok, pending_process, reference()}</em></tag> <item> <p>The unload request is registered, but there are still other <seealso marker="#users">users</seealso> holding diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index 032dcc5251..8e7192a496 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2009</year> + <year>1997</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -284,9 +284,10 @@ socket() <type> <v>Socket = socket()</v> <v>Length = int()</v> - <v>Packet = [char()] | binary()</v> + <v>Packet = [char()] | binary() | HttpPacket</v> <v>Timeout = int() | infinity</v> <v>Reason = closed | posix()</v> + <v>HttpPacket = see the description of <c>HttpPacket</c> in <seealso marker="erts:erlang#decode_packet/3">erlang:decode_packet/3</seealso></v> </type> <desc> <p>This function receives a packet from a socket in passive diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl index 5a31e3976f..cccfa75005 100644 --- a/lib/kernel/src/gen_sctp.erl +++ b/lib/kernel/src/gen_sctp.erl @@ -39,7 +39,7 @@ open() -> open([]). open(Opts) when is_list(Opts) -> - Mod = mod(Opts), + Mod = mod(Opts, undefined), case Mod:open(Opts) of {error,badarg} -> erlang:error(badarg, [Opts]); @@ -166,18 +166,14 @@ send(S, #sctp_assoc_change{assoc_id=AssocId}, Stream, Data) when is_port(S), is_integer(Stream) -> case inet_db:lookup_socket(S) of {ok,Mod} -> - Mod:sendmsg(S, #sctp_sndrcvinfo{ - stream = Stream, - assoc_id = AssocId}, Data); + Mod:send(S, AssocId, Stream, Data); Error -> Error end; send(S, AssocId, Stream, Data) when is_port(S), is_integer(AssocId), is_integer(Stream) -> case inet_db:lookup_socket(S) of {ok,Mod} -> - Mod:sendmsg(S, #sctp_sndrcvinfo{ - stream = Stream, - assoc_id = AssocId}, Data); + Mod:send(S, AssocId, Stream, Data); Error -> Error end; send(S, AssocChange, Stream, Data) -> @@ -238,17 +234,27 @@ controlling_process(S, Pid) -> %% Utilites %% -%% Get the SCTP moudule -mod() -> inet_db:sctp_module(). +%% Get the SCTP module, but IPv6 address overrides default IPv4 +mod(Address) -> + case inet_db:sctp_module() of + inet_sctp when tuple_size(Address) =:= 8 -> + inet6_sctp; + Mod -> + Mod + end. %% Get the SCTP module, but option sctp_module|inet|inet6 overrides -mod([{sctp_module,Mod}|_]) -> +mod([{sctp_module,Mod}|_], _Address) -> Mod; -mod([inet|_]) -> +mod([inet|_], _Address) -> inet_sctp; -mod([inet6|_]) -> +mod([inet6|_], _Address) -> inet6_sctp; -mod([_|Opts]) -> - mod(Opts); -mod([]) -> - mod(). +mod([{ip, Address}|Opts], _) -> + mod(Opts, Address); +mod([{ifaddr, Address}|Opts], _) -> + mod(Opts, Address); +mod([_|Opts], Address) -> + mod(Opts, Address); +mod([], Address) -> + mod(Address). diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl index 7401b06a64..16a87d71b6 100644 --- a/lib/kernel/src/gen_tcp.erl +++ b/lib/kernel/src/gen_tcp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2010. 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 @@ -46,7 +46,7 @@ connect(Address, Port, Opts, Time) -> end. connect1(Address,Port,Opts,Timer) -> - Mod = mod(Opts), + Mod = mod(Opts, Address), case Mod:getaddrs(Address,Timer) of {ok,IPs} -> case Mod:getserv(Port) of @@ -73,7 +73,7 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) -> %% Listen on a tcp port %% listen(Port, Opts) -> - Mod = mod(Opts), + Mod = mod(Opts, undefined), case Mod:getserv(Port) of {ok,TP} -> Mod:listen(TP, Opts); @@ -173,20 +173,30 @@ controlling_process(S, NewOwner) -> %% Create a port/socket from a file descriptor %% fdopen(Fd, Opts) -> - Mod = mod(Opts), + Mod = mod(Opts, undefined), Mod:fdopen(Fd, Opts). -%% Get the tcp_module -mod() -> inet_db:tcp_module(). +%% Get the tcp_module, but IPv6 address overrides default IPv4 +mod(Address) -> + case inet_db:tcp_module() of + inet_tcp when tuple_size(Address) =:= 8 -> + inet6_tcp; + Mod -> + Mod + end. %% Get the tcp_module, but option tcp_module|inet|inet6 overrides -mod([{tcp_module,Mod}|_]) -> +mod([{tcp_module,Mod}|_], _Address) -> Mod; -mod([inet|_]) -> +mod([inet|_], _Address) -> inet_tcp; -mod([inet6|_]) -> +mod([inet6|_], _Address) -> inet6_tcp; -mod([_|Opts]) -> - mod(Opts); -mod([]) -> - mod(). +mod([{ip, Address}|Opts], _) -> + mod(Opts, Address); +mod([{ifaddr, Address}|Opts], _) -> + mod(Opts, Address); +mod([_|Opts], Address) -> + mod(Opts, Address); +mod([], Address) -> + mod(Address). diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl index 6bded4bda6..99020c7b6c 100644 --- a/lib/kernel/src/gen_udp.erl +++ b/lib/kernel/src/gen_udp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2010. 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,7 +29,7 @@ open(Port) -> open(Port, []). open(Port, Opts) -> - Mod = mod(Opts), + Mod = mod(Opts, undefined), {ok,UP} = Mod:getserv(Port), Mod:open(UP, Opts). @@ -97,21 +97,31 @@ controlling_process(S, NewOwner) -> %% Create a port/socket from a file descriptor %% fdopen(Fd, Opts) -> - Mod = mod(), + Mod = mod(Opts, undefined), Mod:fdopen(Fd, Opts). -%% Get the udp_module -mod() -> inet_db:udp_module(). +%% Get the udp_module, but IPv6 address overrides default IPv4 +mod(Address) -> + case inet_db:udp_module() of + inet_udp when tuple_size(Address) =:= 8 -> + inet6_udp; + Mod -> + Mod + end. %% Get the udp_module, but option udp_module|inet|inet6 overrides -mod([{udp_module,Mod}|_]) -> +mod([{udp_module,Mod}|_], _Address) -> Mod; -mod([inet|_]) -> +mod([inet|_], _Address) -> inet_udp; -mod([inet6|_]) -> +mod([inet6|_], _Address) -> inet6_udp; -mod([_|Opts]) -> - mod(Opts); -mod([]) -> - mod(). +mod([{ip, Address}|Opts], _) -> + mod(Opts, Address); +mod([{ifaddr, Address}|Opts], _) -> + mod(Opts, Address); +mod([_|Opts], Address) -> + mod(Opts, Address); +mod([], Address) -> + mod(Address). diff --git a/lib/kernel/src/inet6_sctp.erl b/lib/kernel/src/inet6_sctp.erl index 5c49c4fec3..5bf3fca647 100644 --- a/lib/kernel/src/inet6_sctp.erl +++ b/lib/kernel/src/inet6_sctp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2010. 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 @@ -32,7 +32,7 @@ -define(FAMILY, inet6). -export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]). --export([open/1,close/1,listen/2,connect/5,sendmsg/3,recv/2]). +-export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]). @@ -71,5 +71,24 @@ connect(S, Addr, Port, Opts, Timer) -> sendmsg(S, SRI, Data) -> prim_inet:sendmsg(S, SRI, Data). +send(S, AssocId, Stream, Data) -> + case prim_inet:getopts( + S, + [{sctp_default_send_param,#sctp_sndrcvinfo{assoc_id=AssocId}}]) of + {ok, + [{sctp_default_send_param, + #sctp_sndrcvinfo{ + flags=Flags, context=Context, ppid=PPID, timetolive=TTL}}]} -> + prim_inet:sendmsg( + S, + #sctp_sndrcvinfo{ + flags=Flags, context=Context, ppid=PPID, timetolive=TTL, + assoc_id=AssocId, stream=Stream}, + Data); + _ -> + prim_inet:sendmsg( + S, #sctp_sndrcvinfo{assoc_id=AssocId, stream=Stream}, Data) + end. + recv(S, Timeout) -> prim_inet:recvfrom(S, 0, Timeout). diff --git a/lib/kernel/src/inet_sctp.erl b/lib/kernel/src/inet_sctp.erl index 795bf83807..de74b573bd 100644 --- a/lib/kernel/src/inet_sctp.erl +++ b/lib/kernel/src/inet_sctp.erl @@ -31,7 +31,7 @@ -define(FAMILY, inet). -export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]). --export([open/1,close/1,listen/2,connect/5,sendmsg/3,recv/2]). +-export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]). @@ -141,5 +141,24 @@ connect_get_assoc(S, Addr, Port, Active, Timer) -> sendmsg(S, SRI, Data) -> prim_inet:sendmsg(S, SRI, Data). +send(S, AssocId, Stream, Data) -> + case prim_inet:getopts( + S, + [{sctp_default_send_param,#sctp_sndrcvinfo{assoc_id=AssocId}}]) of + {ok, + [{sctp_default_send_param, + #sctp_sndrcvinfo{ + flags=Flags, context=Context, ppid=PPID, timetolive=TTL}}]} -> + prim_inet:sendmsg( + S, + #sctp_sndrcvinfo{ + flags=Flags, context=Context, ppid=PPID, timetolive=TTL, + assoc_id=AssocId, stream=Stream}, + Data); + _ -> + prim_inet:sendmsg( + S, #sctp_sndrcvinfo{assoc_id=AssocId, stream=Stream}, Data) + end. + recv(S, Timeout) -> prim_inet:recvfrom(S, 0, Timeout). diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl index 0e5cc8c2c6..f5e2820bbe 100644 --- a/lib/kernel/src/net_kernel.erl +++ b/lib/kernel/src/net_kernel.erl @@ -500,8 +500,8 @@ handle_call({new_ticktime,T,TP}, From, #state{tick = #tick{ticker = Tckr, time = T, how = How}}}, From); -handle_call({new_ticktime,From,_}, - _, +handle_call({new_ticktime,_T,_TP}, + From, #state{tick = #tick_change{time = T}} = State) -> async_reply({reply, {ongoing_change_to, T}, State}, From); diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index d15f6aa0d5..21a96f804a 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -273,6 +273,7 @@ tick_change(Config) when is_list(Config) -> ?line PaDir = filename:dirname(code:which(?MODULE)), ?line [BN, CN] = get_nodenames(2, tick_change), ?line DefaultTT = net_kernel:get_net_ticktime(), + ?line unchanged = net_kernel:set_net_ticktime(DefaultTT, 60), ?line case DefaultTT of I when is_integer(I) -> ?line ok; _ -> ?line ?t:fail(DefaultTT) @@ -377,6 +378,7 @@ run_tick_change_test(B, C, PrevTT, TT, PaDir) -> end, ?line change_initiated = net_kernel:set_net_ticktime(TT,20), + ?line {ongoing_change_to,_} = net_kernel:set_net_ticktime(TT,20), ?line sleep(3), ?line change_initiated = rpc:call(B,net_kernel,set_net_ticktime,[TT,15]), ?line sleep(7), diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl index fad8c7398b..9aa94a0868 100644 --- a/lib/kernel/test/gen_sctp_SUITE.erl +++ b/lib/kernel/test/gen_sctp_SUITE.erl @@ -23,12 +23,16 @@ %%-compile(export_all). --export([all/1,init_per_testcase/2,fin_per_testcase/2, - basic/1,api_open_close/1,api_listen/1,api_connect_init/1, - xfer_min/1,xfer_active/1]). +-export([all/1,init_per_testcase/2,fin_per_testcase/2]). +-export( + [basic/1, + api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1, + xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1]). all(suite) -> - [basic,api_open_close,api_listen,api_connect_init,xfer_min,xfer_active]. + [basic, + api_open_close,api_listen,api_connect_init,api_opts, + xfer_min,xfer_active,def_sndrcvinfo,implicit_inet6]. init_per_testcase(_Func, Config) -> Dog = test_server:timetrap(test_server:seconds(15)), @@ -39,6 +43,10 @@ fin_per_testcase(_Func, Config) -> +-define(LOGVAR(Var), begin io:format(??Var" = ~p~n", [Var]) end). + + + basic(doc) -> "Hello world"; basic(suite) -> @@ -214,12 +222,17 @@ xfer_active(Config) when is_list(Config) -> end, ?line ok = gen_sctp:close(Sb), ?line receive - {sctp,Sa,Loopback,Pb, - {[], - #sctp_assoc_change{state=comm_lost, - assoc_id=SaAssocId}}} -> ok - after 17 -> ok %% On Solaris this does not arrive - end, + {sctp,Sa,Loopback,Pb, + {[], + #sctp_assoc_change{state=comm_lost, + assoc_id=SaAssocId}}} -> ok + after Timeout -> + ?line test_server:fail({unexpected,flush()}) + end, + ?line receive + {sctp_error,Sa,enotconn} -> ok % Solaris + after 17 -> ok %% Only happens on Solaris + end, ?line ok = gen_sctp:close(Sa), %% ?line receive @@ -228,6 +241,148 @@ xfer_active(Config) when is_list(Config) -> end, ok. +def_sndrcvinfo(doc) -> + "Test that #sctp_sndrcvinfo{} parameters set on a socket " + "are used by gen_sctp:send/4"; +def_sndrcvinfo(suite) -> + []; +def_sndrcvinfo(Config) when is_list(Config) -> + ?line Loopback = {127,0,0,1}, + ?line Data = <<"What goes up, must come down.">>, + %% + ?line S1 = + ok(gen_sctp:open( + 0, [{sctp_default_send_param,#sctp_sndrcvinfo{ppid=17}}])), + ?LOGVAR(S1), + ?line P1 = + ok(inet:port(S1)), + ?LOGVAR(P1), + ?line #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} = + getopt(S1, sctp_default_send_param), + ?line ok = + gen_sctp:listen(S1, true), + %% + ?line S2 = + ok(gen_sctp:open()), + ?LOGVAR(S2), + ?line P2 = + ok(inet:port(S2)), + ?LOGVAR(P2), + ?line #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} = + getopt(S2, sctp_default_send_param), + %% + ?line #sctp_assoc_change{ + state=comm_up, + error=0, + assoc_id=S2AssocId} = S2AssocChange = + ok(gen_sctp:connect(S2, Loopback, P1, [])), + ?LOGVAR(S2AssocChange), + ?line case ok(gen_sctp:recv(S1)) of + {Loopback, P2,[], + #sctp_assoc_change{ + state=comm_up, + error=0, + assoc_id=S1AssocId}} -> + ?LOGVAR(S1AssocId) + end, + ?line #sctp_sndrcvinfo{ + ppid=17, context=0, timetolive=0, assoc_id=S1AssocId} = + getopt( + S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}), + ?line #sctp_sndrcvinfo{ + ppid=0, context=0, timetolive=0, assoc_id=S2AssocId} = + getopt( + S2, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S2AssocId}), + %% + ?line ok = + gen_sctp:send(S1, S1AssocId, 1, <<"1: ",Data/binary>>), + ?line case ok(gen_sctp:recv(S2)) of + {Loopback,P1, + [#sctp_sndrcvinfo{ + stream=1, ppid=17, context=0, assoc_id=S2AssocId}], + <<"1: ",Data/binary>>} -> ok + end, + %% + ?line ok = + setopt( + S1, sctp_default_send_param, #sctp_sndrcvinfo{ppid=18}), + ?line ok = + setopt( + S1, sctp_default_send_param, + #sctp_sndrcvinfo{ppid=19, assoc_id=S1AssocId}), + ?line #sctp_sndrcvinfo{ + ppid=18, context=0, timetolive=0, assoc_id=0} = + getopt(S1, sctp_default_send_param), + ?line #sctp_sndrcvinfo{ + ppid=19, context=0, timetolive=0, assoc_id=S1AssocId} = + getopt( + S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}), + %% + ?line ok = + gen_sctp:send(S1, S1AssocId, 0, <<"2: ",Data/binary>>), + ?line case ok(gen_sctp:recv(S2)) of + {Loopback,P1, + [#sctp_sndrcvinfo{ + stream=0, ppid=19, context=0, assoc_id=S2AssocId}], + <<"2: ",Data/binary>>} -> ok + end, + ?line ok = + gen_sctp:send(S2, S2AssocChange, 1, <<"3: ",Data/binary>>), + ?line case ok(gen_sctp:recv(S1)) of + {Loopback,P2, + [#sctp_sndrcvinfo{ + stream=1, ppid=0, context=0, assoc_id=S1AssocId}], + <<"3: ",Data/binary>>} -> ok; + {Loopback,P2,[], + #sctp_paddr_change{ + addr={Loopback,_}, state=addr_available, + error=0, assoc_id=S1AssocId}} -> + ?line case ok(gen_sctp:recv(S1)) of + {Loopback,P2, + [#sctp_sndrcvinfo{ + stream=1, ppid=0, context=0, + assoc_id=S1AssocId}], + <<"3: ",Data/binary>>} -> ok + end + end, + ?line ok = + gen_sctp:send( + S2, + #sctp_sndrcvinfo{stream=0, ppid=20, assoc_id=S2AssocId}, + <<"4: ",Data/binary>>), + ?line case ok(gen_sctp:recv(S1)) of + {Loopback,P2, + [#sctp_sndrcvinfo{ + stream=0, ppid=20, context=0, assoc_id=S1AssocId}], + <<"4: ",Data/binary>>} -> ok + end, + %% + ?line ok = + gen_sctp:close(S1), + ?line ok = + gen_sctp:close(S2), + ?line receive + Msg -> + test_server:fail({received,Msg}) + after 17 -> ok + end, + ok. + +getopt(S, Opt) -> + {ok,[{Opt,Val}]} = inet:getopts(S, [Opt]), + Val. + +getopt(S, Opt, Param) -> + {ok,[{Opt,Val}]} = inet:getopts(S, [{Opt,Param}]), + Val. + +setopt(S, Opt, Val) -> + inet:setopts(S, [{Opt,Val}]). + +ok({ok,X}) -> + io:format("OK: ~p~n", [X]), + X. + flush() -> receive Msg -> @@ -382,3 +537,72 @@ api_connect_init(Config) when is_list(Config) -> ?line ok = gen_sctp:close(Sa), ?line ok = gen_sctp:close(Sb), ok. + +api_opts(doc) -> + "Test socket options"; +api_opts(suite) -> + []; +api_opts(Config) when is_list(Config) -> + ?line {ok,S} = gen_sctp:open(0), + ?line OSType = os:type(), + ?line case {inet:setopts(S, [{linger,{true,2}}]),OSType} of + {ok,_} -> + ok; + {{error,einval},{unix,sunos}} -> + ok + end. + +implicit_inet6(Config) when is_list(Config) -> + ?line Hostname = ok(inet:gethostname()), + ?line + case gen_sctp:open(0, [inet6]) of + {ok,S1} -> + ?line + case inet:getaddr(Hostname, inet6) of + {ok,Host} -> + ?line Loopback = {0,0,0,0,0,0,0,1}, + ?line io:format("~s ~p~n", ["Loopback",Loopback]), + ?line implicit_inet6(S1, Loopback), + ?line ok = gen_sctp:close(S1), + %% + ?line Localhost = + ok(inet:getaddr("localhost", inet6)), + ?line io:format("~s ~p~n", ["localhost",Localhost]), + ?line S2 = + ok(gen_sctp:open(0, [{ip,Localhost}])), + ?line implicit_inet6(S2, Localhost), + ?line ok = gen_sctp:close(S2), + %% + ?line io:format("~s ~p~n", [Hostname,Host]), + ?line S3 = + ok(gen_sctp:open(0, [{ifaddr,Host}])), + ?line implicit_inet6(S3, Host), + ?line ok = gen_sctp:close(S1); + {error,eafnosupport} -> + ?line ok = gen_sctp:close(S1), + {skip,"Can not look up IPv6 address"} + end; + _ -> + {skip,"IPv6 not supported"} + end. + +implicit_inet6(S1, Addr) -> + ?line ok = gen_sctp:listen(S1, true), + ?line P1 = ok(inet:port(S1)), + ?line S2 = ok(gen_sctp:open(0, [inet6])), + ?line P2 = ok(inet:port(S2)), + ?line #sctp_assoc_change{state=comm_up} = + ok(gen_sctp:connect(S2, Addr, P1, [])), + ?line case ok(gen_sctp:recv(S1)) of + {Addr,P2,[],#sctp_assoc_change{state=comm_up}} -> + ok + end, + ?line case ok(inet:sockname(S1)) of + {Addr,P1} -> ok; + {{0,0,0,0,0,0,0,0},P1} -> ok + end, + ?line case ok(inet:sockname(S2)) of + {Addr,P2} -> ok; + {{0,0,0,0,0,0,0,0},P2} -> ok + end, + ?line ok = gen_sctp:close(S2). diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index 11d19aaa82..94637290a1 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2010. 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,10 +30,11 @@ t_connect/1, t_connect_bad/1, t_recv/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_fdopen/1, t_implicit_inet6/1]). all(suite) -> [t_accept, t_connect, t_recv, t_shutdown_write, - t_shutdown_both, t_shutdown_error, t_fdopen]. + t_shutdown_both, t_shutdown_error, t_fdopen, + t_implicit_inet6]. init_per_testcase(_Func, Config) -> Dog = test_server:timetrap(test_server:seconds(60)), @@ -156,6 +157,54 @@ t_fdopen(Config) when is_list(Config) -> ok. +%%% implicit inet6 option to api functions + +t_implicit_inet6(Config) when is_list(Config) -> + ?line Hostname = ok(inet:gethostname()), + ?line + case gen_tcp:listen(0, [inet6]) of + {ok,S1} -> + ?line + case inet:getaddr(Hostname, inet6) of + {ok,Host} -> + ?line Loopback = {0,0,0,0,0,0,0,1}, + ?line io:format("~s ~p~n", ["Loopback",Loopback]), + ?line implicit_inet6(S1, Loopback), + ?line ok = gen_tcp:close(S1), + %% + ?line Localhost = + ok(inet:getaddr("localhost", inet6)), + ?line io:format("~s ~p~n", ["localhost",Localhost]), + ?line S2 = ok(gen_tcp:listen(0, [{ip,Localhost}])), + ?line implicit_inet6(S2, Localhost), + ?line ok = gen_tcp:close(S2), + %% + ?line io:format("~s ~p~n", [Hostname,Host]), + ?line S3 = ok(gen_tcp:listen(0, [{ifaddr,Host}])), + ?line implicit_inet6(S3, Host), + ?line ok = gen_tcp:close(S1); + {error,eafnosupport} -> + ?line ok = gen_tcp:close(S1), + {skip,"Can not look up IPv6 address"} + end; + _ -> + {skip,"IPv6 not supported"} + end. + +implicit_inet6(S, Addr) -> + ?line P = ok(inet:port(S)), + ?line S2 = ok(gen_tcp:connect(Addr, P, [])), + ?line P2 = ok(inet:port(S2)), + ?line S1 = ok(gen_tcp:accept(S)), + ?line P1 = P = ok(inet:port(S1)), + ?line {Addr,P2} = ok(inet:peername(S1)), + ?line {Addr,P1} = ok(inet:peername(S2)), + ?line {Addr,P1} = ok(inet:sockname(S1)), + ?line {Addr,P2} = ok(inet:sockname(S2)), + ?line ok = gen_tcp:close(S2), + ?line ok = gen_tcp:close(S1). + + %%% Utilities @@ -217,3 +266,5 @@ unused_ip(A, B, C, D) -> {ok, _} -> unused_ip(A, B, C, D+1); {error, _} -> {ok, {A, B, C, D}} end. + +ok({ok,V}) -> V. diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 5d726a3b1b..d73c5fab56 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1998-2010. 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(gen_tcp_misc_SUITE). @@ -957,12 +957,11 @@ http_bad_packet(Config) when is_list(Config) -> http_worker(S) -> case gen_tcp:recv(S, 0, 30000) of + {ok,{http_error,Error}} -> + io:format("Http error: ~s\n", [Error]); {ok,Data} -> io:format("Data: ~p\n", [Data]), - http_worker(S); - {error,Rsn} -> - io:format("Error: ~p\n", [Rsn]), - ok + http_worker(S) end. http_bad_client(Port) -> diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl index fa1991872b..44dd8607b9 100644 --- a/lib/kernel/test/gen_udp_SUITE.erl +++ b/lib/kernel/test/gen_udp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2010. 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 @@ -34,12 +34,12 @@ -export([send_to_closed/1, buffer_size/1, binary_passive_recv/1, bad_address/1, - read_packets/1, open_fd/1, connect/1]). + read_packets/1, open_fd/1, connect/1, implicit_inet6/1]). all(suite) -> [send_to_closed, buffer_size, binary_passive_recv, bad_address, read_packets, - open_fd, connect]. + open_fd, connect, implicit_inet6]. init_per_testcase(_Case, Config) -> ?line Dog=test_server:timetrap(?default_timeout), @@ -425,3 +425,57 @@ connect(Config) when is_list(Config) -> ok = gen_udp:send(S2, <<16#deadbeef:32>>), {error,econnrefused} = gen_udp:recv(S2, 0, 5), ok. + +implicit_inet6(Config) when is_list(Config) -> + ?line Hostname = ok(inet:gethostname()), + ?line Active = {active,false}, + ?line + case gen_udp:open(0, [inet6,Active]) of + {ok,S1} -> + ?line + case inet:getaddr(Hostname, inet6) of + {ok,Host} -> + ?line Loopback = {0,0,0,0,0,0,0,1}, + ?line io:format("~s ~p~n", ["Loopback",Loopback]), + ?line implicit_inet6(S1, Active, Loopback), + ?line ok = gen_udp:close(S1), + %% + ?line Localhost = + ok(inet:getaddr("localhost", inet6)), + ?line io:format("~s ~p~n", ["localhost",Localhost]), + ?line S2 = + ok(gen_udp:open(0, [{ip,Localhost},Active])), + ?line implicit_inet6(S2, Active, Localhost), + ?line ok = gen_udp:close(S2), + %% + ?line io:format("~s ~p~n", [Hostname,Host]), + ?line S3 = + ok(gen_udp:open(0, [{ifaddr,Host},Active])), + ?line implicit_inet6(S3, Active, Host), + ?line ok = gen_udp:close(S1); + {error,eafnosupport} -> + ?line ok = gen_udp:close(S1), + {skip,"Can not look up IPv6 address"} + end; + _ -> + {skip,"IPv6 not supported"} + end. + +implicit_inet6(S1, Active, Addr) -> + ?line P1 = ok(inet:port(S1)), + ?line S2 = ok(gen_udp:open(0, [inet6,Active])), + ?line P2 = ok(inet:port(S2)), + ?line ok = gen_udp:connect(S2, Addr, P1), + ?line ok = gen_udp:connect(S1, Addr, P2), + ?line {Addr,P2} = ok(inet:peername(S1)), + ?line {Addr,P1} = ok(inet:peername(S2)), + ?line {Addr,P1} = ok(inet:sockname(S1)), + ?line {Addr,P2} = ok(inet:sockname(S2)), + ?line ok = gen_udp:send(S1, Addr, P2, "ping"), + ?line {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)), + ?line ok = gen_udp:send(S2, Addr, P1, "pong"), + ?line {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)), + ?line ok = gen_udp:close(S2). + + +ok({ok,V}) -> V. diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index eb8f918491..f4f27933a5 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -26,7 +26,8 @@ t_gethostbyaddr_v6/1, t_getaddr_v6/1, t_gethostbyname_v6/1, ipv4_to_ipv6/1, host_and_addr/1, parse/1, t_gethostnative/1, gethostnative_parallell/1, cname_loop/1, - gethostnative_soft_restart/1,gethostnative_debug_level/1,getif/1]). + gethostnative_soft_restart/1,gethostnative_debug_level/1,getif/1, + getif_ifr_name_overflow/1,getservbyname_overflow/1]). -export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1, kill_gethost/0, parallell_gethost/0]). @@ -39,7 +40,7 @@ all(suite) -> ipv4_to_ipv6, host_and_addr, parse,t_gethostnative, gethostnative_parallell, cname_loop, gethostnative_debug_level,gethostnative_soft_restart, - getif]. + getif,getif_ifr_name_overflow,getservbyname_overflow]. init_per_testcase(_Func, Config) -> Dog = test_server:timetrap(test_server:seconds(60)), @@ -876,6 +877,17 @@ getif(Config) when is_list(Config) -> ?line {ok,Address} = inet:getaddr(Hostname, inet), ?line {ok,Loopback} = inet:getaddr("localhost", inet), ?line {ok,Interfaces} = inet:getiflist(), + ?line HWAs = + lists:sort( + lists:foldl( + fun (I, Acc) -> + case inet:ifget(I, [hwaddr]) of + {ok,[{hwaddr,A}]} -> [A|Acc]; + {ok,[]} -> Acc + end + end, [], Interfaces)), + ?line io:format("HWAs = ~p~n", [HWAs]), + ?line length(HWAs) > 0 orelse ?t:fail(no_HWAs), ?line Addresses = lists:sort( lists:foldl( @@ -891,6 +903,20 @@ getif(Config) when is_list(Config) -> ?line true = ip_member(Loopback, Addresses), ?line ok. +getif_ifr_name_overflow(doc) -> + "Test long interface names do not overrun buffer"; +getif_ifr_name_overflow(Config) when is_list(Config) -> + %% emulator should not crash + ?line {ok,[]} = inet:ifget(lists:duplicate(128, "x"), [addr]), + ok. + +getservbyname_overflow(doc) -> + "Test long service names do not overrun buffer"; +getservbyname_overflow(Config) when is_list(Config) -> + %% emulator should not crash + ?line {error,einval} = inet:getservbyname(list_to_atom(lists:flatten(lists:duplicate(128, "x"))), tcp), + ok. + %% Works just like lists:member/2, except that any {127,_,_,_} tuple %% matches any other {127,_,_,_}. We do this to handle Linux systems %% that use (for instance) 127.0.1.1 as the IP address for the hostname. diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 9a191f9aeb..651d082379 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1,20 +1 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2010. 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% -# - KERNEL_VSN = 2.14.1 diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk index efb46253aa..73ac5bbc63 100644 --- a/lib/megaco/vsn.mk +++ b/lib/megaco/vsn.mk @@ -1,151 +1,4 @@ -#-*-makefile-*- ; force emacs to enter makefile-mode - -# %CopyrightBegin% -# -# Copyright Ericsson AB 2001-2010. 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% - APPLICATION = megaco MEGACO_VSN = 3.14.1.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)" - -TICKETS = OTP-8696 - -TICKETS_3_14_1 = OTP-8529 OTP-8561 OTP-8627 OTP-8634 - -TICKETS_3_14 = OTP-8317 OTP-8323 OTP-8328 OTP-8362 OTP-8403 - -TICKETS_3_13 = OTP-8205 OTP-8239 OTP-8249 - -TICKETS_3_12 = OTP-8183 OTP-8212 - -TICKETS_3_11_3 = OTP-8164 OTP-8167 OTP-8191 - -TICKETS_3_11_2 = OTP-8123 - -TICKETS_3_11_1 = OTP-8081 OTP-8114 - -TICKETS_3_11 = OTP-7302 OTP-7995 - -TICKETS_3_10_1 = OTP-7926 OTP-7936 - -TICKETS_3_10_0_1 = OTP-7851 - -TICKETS_3_10 = OTP-7713 OTP-7743 - -TICKETS_3_9_4 = OTP-7728 OTP-7733 - -TICKETS_3_9_3 = OTP-7700 - -TICKETS_3_9_2 = OTP-7671 OTP-7672 - -TICKETS_3_9_1_1 = OTP-7614 - -TICKETS_3_9_1 = OTP-7572 OTP-7573 OTP-7576 - -TICKETS_3_9 = OTP-7431 - -TICKETS_3_8_2 = OTP-7534 - -TICKETS_3_8_1 = OTP-7398 OTP-7417 OTP-7444 OTP-7449 OTP-7455 OTP-7457 OTP-7459 - -TICKETS_3_8 = OTP-7192 OTP-7228 OTP-7259 - -TICKETS_3_7_5 = OTP-7286 OTP-7303 - -TICKETS_3_7_4 = OTP-7249 OTP-7251 - -TICKETS_3_7_3 = OTP-7168 OTP-7180 OTP-7189 OTP-7216 - -TICKETS_3_7_2 = OTP-6972 OTP-7138 - -TICKETS_3_7_1 = OTP-6919 OTP-6971 OTP-6992 OTP-6999 OTP-7000 OTP-7005 OTP-7124 - -TICKETS_3_7 = OTP-5979 OTP-6753 OTP-6804 OTP-6865 OTP-6919 OTP-6976 - -TICKETS_3_6_2 = OTP-6921 - -TICKETS_3_6_1 = OTP-6803 - -TICKETS_3_6_0_1 = OTP-6704 - -TICKETS_3_6 = OTP-6185 OTP-6578 OTP-6441 OTP-6442 OTP-6544 OTP-6605 OTP-6609 - -TICKETS_3_5_3 = OTP-6520 OTP-6549 - -TICKETS_3_5_2 = OTP-6404 OTP-6422 OTP-6490 OTP-6503 - -TICKETS_3_5_1 = OTP-6275 OTP-6276 - -TICKETS_3_5 = OTP-6223 OTP-6253 OTP-6256 - -TICKETS_3_4_4 = OTP-6181 OTP-6182 OTP-6217 OTP-6219 - -TICKETS_3_4_3 = OTP-6170 OTP-6171 OTP-6172 - -TICKETS_3_4_2 = OTP-6148 - -TICKETS_3_4_1 = OTP-6113 - -TICKETS_3_4 = \ - OTP-5769 \ - OTP-5980 \ - OTP-6009 \ - OTP-6025 \ - OTP-6028 \ - OTP-6030 \ - OTP-6048 \ - OTP-6051 \ - OTP-6052 \ - OTP-6055 \ - OTP-6089 \ - OTP-6090 - -TICKETS_3_3_5 = OTP-6108 - -TICKETS_3_3_4 = OTP-6076 - -TICKETS_3_3_3 = OTP-6046 - -TICKETS_3_3_2 = OTP-6017 OTP-6022 - -TICKETS_3_3_1 = OTP-5993 - -TICKETS_3_3 = OTP-5965 OTP-5973 - -TICKETS_3_2_7 = OTP-5948 OTP-5952 OTP-5953 - -TICKETS_3_2_6 = OTP-5918 OTP-5919 OTP-5920 - -TICKETS_3_2_5 = OTP-5887 - -TICKETS_3_2_4 = OTP-5867 OTP-5879 OTP-5880 OTP-5881 OTP-5882 OTP-5885 OTP-5886 - -TICKETS_3_2_3 = OTP-5826 OTP-5830 OTP-5833 OTP-5836 OTP-5839 - -TICKETS_3_2_2 = OTP-5799 OTP-5803 OTP-5804 OTP-5805 OTP-5816 - -TICKETS_3_2_1 = OTP-5725 OTP-5793 - -TICKETS_3_2 = OTP-5717 OTP-5750 - -TICKETS_3_1 = OTP-5542 OTP-5597 OTP-5600 OTP-5601 OTP-5619 OTP-5664 - -TICKETS_3_0_1 = \ - OTP-5401 \ - OTP-5446 \ - OTP-5447 - diff --git a/lib/mnesia/test/Makefile b/lib/mnesia/test/Makefile index a4f32e3f78..4f98efaed1 100644 --- a/lib/mnesia/test/Makefile +++ b/lib/mnesia/test/Makefile @@ -109,7 +109,7 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) mnesia.spec mnesia.spec.vxworks $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR) - $(INSTALL_PROGRAM) mt $(INSTALL_PROGS) $(RELSYSDIR) + $(INSTALL_SCRIPT) mt $(INSTALL_PROGS) $(RELSYSDIR) # chmod -f -R u+w $(RELSYSDIR) # @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index 2780b737b6..ab2bb73c33 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1,17 +1 @@ - MNESIA_VSN = 4.4.14 - -TICKETS = OTP-8519 -#TICKETS_4.4.13 = OTP-8402 OTP-8406 -#TICKETS_4.4.12 = OTP-8250 -#TICKETS_4.4.11 = OTP-8074 -#TICKETS_4.4.10 = OTP-7928 OTP-7968 OTP-8002 -#TICKETS_4.4.9 = OTP-7911 -#TICKETS_4.4.8 = OTP-7753 OTP-7835 -#TICKETS_4.4.7 = OTP-7524 OTP-7625 -#TICKETS_4.4.6 = OTP-7585 -#TICKETS_4.4.5 = OTP-7466 -#TICKETS_4.4.4 = OTP-7419 -#TICKETS_4.4.3 = OTP-7340 OTP-7378 OTP-7383 -#TICKETS_4.4.2 = OTP-7205 OTP-7208 -#TICKETS_4.4.1 = OTP-7170 diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk index d813466437..fac3f06d4b 100644 --- a/lib/odbc/vsn.mk +++ b/lib/odbc/vsn.mk @@ -1,23 +1 @@ ODBC_VSN = 2.10.8 - -TICKETS = OTP-7452 OTP-8511 - -TICKETS_2.10.6 = \ - OTP-8250 \ - OTP-8291 - -TICKETS_2.10.5 = \ - OTP-7978 - -TICKETS_2.10.4 = \ - OTP-7720 \ - OTP-7721 - -TICKETS_2.10.3 = \ - OTP-7418 -TICKETS_2.10.2 = \ - OTP-7297 -TICKETS_2.10.1 = \ - OTP-7019 \ - OTP-7294 \ - OTP-7307 diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk index ec349ee189..cf80e27a61 100644 --- a/lib/orber/vsn.mk +++ b/lib/orber/vsn.mk @@ -1,21 +1 @@ - ORBER_VSN = 3.6.16 - -TICKETS = OTP-8489 \ - OTP-8543 - -TICKETS_3.6.15 = OTP-8353 \ - OTP-8354 \ - OTP-8374 \ - OTP-8409 \ - OTP-8448 - -TICKETS_3.6.14 = OTP-8201 - -TICKETS_3.6.13 = OTP-7987 - -TICKETS_3.6.12 = OTP-7906 - -TICKETS_3.6.11 = OTP-7837 - -TICKETS_3.6.10 = OTP-7595 diff --git a/lib/os_mon/test/Makefile b/lib/os_mon/test/Makefile new file mode 100644 index 0000000000..c87285e38b --- /dev/null +++ b/lib/os_mon/test/Makefile @@ -0,0 +1,92 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2010. 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_TOP)/make/target.mk + +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES= \ + os_mon_SUITE \ + disksup_SUITE \ + memsup_SUITE \ + cpu_sup_SUITE \ + os_mon_mib_SUITE \ + os_sup_SUITE \ + os_mon_conf + +EBIN = . + +HRL_FILES= + +ERL_FILES= $(MODULES:%=%.erl) + +TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + +SOURCE = $(ERL_FILES) $(HRL_FILES) + +EMAKEFILE=Emakefile + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/os_mon_test + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +ERL_MAKE_FLAGS += +ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \ + -I$(ERL_TOP)/lib/snmp/include + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +make_emakefile: + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\ + > $(EMAKEFILE) + +tests debug opt: make_emakefile + erl $(ERL_MAKE_FLAGS) -make + +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) + rm -f core *~ + +docs: + + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: + +release_tests_spec: make_emakefile + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) os_mon.spec $(EMAKEFILE) $(SOURCE) $(RELSYSDIR) + +## tar chf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + +release_docs_spec: diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl new file mode 100644 index 0000000000..45f9d981d1 --- /dev/null +++ b/lib/os_mon/test/cpu_sup_SUITE.erl @@ -0,0 +1,282 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2010. 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(cpu_sup_SUITE). +-include("test_server.hrl"). + +%% Test server specific exports +-export([all/1]). +-export([init_per_suite/1, end_per_suite/1]). +-export([init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([load_api/1]). +-export([util_api/1, util_values/1]). +-export([port/1]). +-export([terminate/1, unavailable/1, restart/1]). + +%% Default timetrap timeout (set in init_per_testcase) +-define(default_timeout, ?t:minutes(1)). + +init_per_suite(Config) when is_list(Config) -> + ?line ok = application:start(os_mon), + Config. + +end_per_suite(Config) when is_list(Config) -> + ?line ok = application:stop(os_mon), + Config. + +init_per_testcase(_Case, Config) -> + Dog = ?t:timetrap(?default_timeout), + [{watchdog, Dog} | Config]. + +end_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +all(suite) -> + case ?t:os_type() of + {unix, sunos} -> + [load_api, util_api, util_values, port, + {conf, terminate, [unavailable], restart}]; + {unix, linux} -> + [load_api, util_api, util_values, port, + {conf, terminate, [unavailable], restart}]; + {unix, _OSname} -> + [load_api]; + _OS -> + [unavailable] + end. + +load_api(suite) -> + []; +load_api(doc) -> + ["Test of load API functions"]; +load_api(Config) when is_list(Config) -> + + %% nprocs() + ?line N = cpu_sup:nprocs(), + ?line true = is_integer(N), + ?line true = N>0, + + %% avg1() + ?line Load1 = cpu_sup:avg1(), + ?line true = is_integer(Load1), + ?line true = Load1>0, + + %% avg5() + ?line Load5 = cpu_sup:avg5(), + ?line true = is_integer(Load5), + ?line true = Load5>0, + + %% avg15() + ?line Load15 = cpu_sup:avg15(), + ?line true = is_integer(Load15), + ?line true = Load15>0, + + ok. + +util_api(suite) -> + []; +util_api(doc) -> + ["Test of utilization API functions"]; +util_api(Config) when is_list(Config) -> + %% Some useful funs when testing util/1 + BusyP = fun({user, _Share}) -> true; + ({nice_user, _Share}) -> true; + ({kernel, _Share}) -> true; + ({hard_irq, _Share}) -> true; + ({soft_irq, _Share}) -> true; + (_) -> false + end, + NonBusyP = fun({wait, _Share}) -> true; + ({idle, _Share}) -> true; + ({steal, _Share}) -> true; + (_) -> false + end, + Sum = fun({_Tag, X}, Acc) -> Acc+X end, + + %% util() + ?line Util1 = cpu_sup:util(), + ?line true = is_number(Util1), + ?line true = Util1>0, + ?line Util2 = cpu_sup:util(), + ?line true = is_number(Util2), + ?line true = Util2>0, + + %% util([]) + ?line {all, Busy1, NonBusy1, []} = cpu_sup:util([]), + ?line 100.00 = Busy1 + NonBusy1, + + %% util([detailed]) + ?line {Cpus2, Busy2, NonBusy2, []} = cpu_sup:util([detailed]), + ?line true = lists:all(fun(X) -> is_integer(X) end, Cpus2), + ?line true = lists:all(BusyP, Busy2), + ?line true = lists:all(NonBusyP, NonBusy2), + ?line 100.00 = lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2), + + %% util([per_cpu]) + ?line [{Cpu3, Busy3, NonBusy3, []}|_] = cpu_sup:util([per_cpu]), + ?line true = is_integer(Cpu3), + ?line 100.00 = Busy3 + NonBusy3, + + %% util([detailed, per_cpu]) + ?line [{Cpu4, Busy4, NonBusy4, []}|_] = + cpu_sup:util([detailed, per_cpu]), + ?line true = is_integer(Cpu4), + ?line true = lists:all(BusyP, Busy2), + ?line true = lists:all(NonBusyP, NonBusy2), + ?line 100.00 = lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4), + + %% bad util/1 calls + ?line {'EXIT',{badarg,_}} = (catch cpu_sup:util(detailed)), + ?line {'EXIT',{badarg,_}} = (catch cpu_sup:util([detialed])), + + ok. + +-define(SPIN_TIME, 1000). + +util_values(suite) -> + []; +util_values(doc) -> + ["Test utilization values"]; +util_values(Config) when is_list(Config) -> + + Tester = self(), + Ref = make_ref(), + Loop = fun (L) -> L(L) end, + Spinner = fun () -> + Looper = spawn_link(fun () -> Loop(Loop) end), + receive after ?SPIN_TIME -> ok end, + unlink(Looper), + exit(Looper, kill), + Tester ! Ref + end, + + ?line cpu_sup:util(), + + ?line spawn_link(Spinner), + ?line receive Ref -> ok end, + ?line HighUtil1 = cpu_sup:util(), + + ?line receive after ?SPIN_TIME -> ok end, + ?line LowUtil1 = cpu_sup:util(), + + ?line spawn_link(Spinner), + ?line receive Ref -> ok end, + ?line HighUtil2 = cpu_sup:util(), + + ?line receive after ?SPIN_TIME -> ok end, + ?line LowUtil2 = cpu_sup:util(), + + Utils = [{high1,HighUtil1}, {low1,LowUtil1}, + {high2,HighUtil2}, {low2,LowUtil2}], + ?t:format("Utils: ~p~n", [Utils]), + + ?line false = LowUtil1 > HighUtil1, + ?line false = LowUtil1 > HighUtil2, + ?line false = LowUtil2 > HighUtil1, + ?line false = LowUtil2 > HighUtil2, + + ok. + + +% Outdated +% The portprogram is now restarted if killed, and not by os_mon... + +port(suite) -> + []; +port(doc) -> + ["Test that cpu_sup handles a terminating port program"]; +port(Config) when is_list(Config) -> + case cpu_sup_os_pid() of + {ok, PidStr} -> + %% Monitor cpu_sup + ?line MonRef = erlang:monitor(process, cpu_sup), + ?line N1 = cpu_sup:nprocs(), + ?line true = N1>0, + + %% Kill the port program + case os:cmd("kill -9 " ++ PidStr) of + [] -> + %% cpu_sup should not terminate + receive + {'DOWN', MonRef, _, _, Reason} -> + ?line ?t:fail({unexpected_exit_reason, Reason}) + after 3000 -> + ok + end, + + %% Give cpu_sup time to restart cpu_sup port + ?t:sleep(?t:seconds(3)), + ?line N2 = cpu_sup:nprocs(), + ?line true = N2>0, + + erlang:demonitor(MonRef), + ok; + + Line -> + erlang:demonitor(MonRef), + {skip, {not_killed, Line}} + end; + _ -> + {skip, os_pid_not_found } + end. + +terminate(suite) -> + []; +terminate(Config) when is_list(Config) -> + ?line ok = application:set_env(os_mon, start_cpu_sup, false), + ?line ok = supervisor:terminate_child(os_mon_sup, cpu_sup), + ok. + +unavailable(suite) -> + []; +unavailable(doc) -> + ["Test correct behaviour when service is unavailable"]; +unavailable(Config) when is_list(Config) -> + + %% Make sure all API functions return their dummy values + ?line 0 = cpu_sup:nprocs(), + ?line 0 = cpu_sup:avg1(), + ?line 0 = cpu_sup:avg5(), + ?line 0 = cpu_sup:avg15(), + ?line 0 = cpu_sup:util(), + ?line {all,0,0,[]} = cpu_sup:util([]), + ?line {all,0,0,[]} = cpu_sup:util([detailed]), + ?line {all,0,0,[]} = cpu_sup:util([per_cpu]), + ?line {all,0,0,[]} = cpu_sup:util([detailed,per_cpu]), + + ok. + +restart(suite) -> + []; +restart(Config) when is_list(Config) -> + ?line ok = application:set_env(os_mon, start_cpu_sup, true), + ?line {ok, _Pid} = supervisor:restart_child(os_mon_sup, cpu_sup), + ok. + +%% Aux + +cpu_sup_os_pid() -> + Str = os:cmd("ps -e | grep '[c]pu_sup'"), + case io_lib:fread("~s", Str) of + {ok, [Pid], _Rest} -> {ok, Pid}; + _ -> {error, pid_not_found} + end. diff --git a/lib/os_mon/test/disksup_SUITE.erl b/lib/os_mon/test/disksup_SUITE.erl new file mode 100644 index 0000000000..987d631c36 --- /dev/null +++ b/lib/os_mon/test/disksup_SUITE.erl @@ -0,0 +1,426 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2010. 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(disksup_SUITE). +-include("test_server.hrl"). + +%% Test server specific exports +-export([all/1]). +-export([init_per_suite/1, end_per_suite/1]). +-export([init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([api/1, config/1, alarm/1]). +-export([port/1]). +-export([terminate/1, unavailable/1, restart/1]). +-export([otp_5910/1]). + +%% Default timetrap timeout (set in init_per_testcase) +-define(default_timeout, ?t:minutes(1)). + +init_per_suite(Config) when is_list(Config) -> + ?line ok = application:start(os_mon), + Config. + +end_per_suite(Config) when is_list(Config) -> + ?line ok = application:stop(os_mon), + Config. + +init_per_testcase(_Case, Config) -> + Dog = ?t:timetrap(?default_timeout), + [{watchdog,Dog} | Config]. + +end_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +all(suite) -> + Bugs = [otp_5910], + case ?t:os_type() of + {unix, sunos} -> + [api, config, alarm, port, + {conf, terminate, [unavailable], restart}] ++ Bugs; + {unix, _OSname} -> + [api, alarm] ++ Bugs; + {win32, _OSname} -> + [api, alarm] ++ Bugs; + _OS -> + [unavailable] + end. + +api(suite) -> + []; +api(doc) -> + ["Test of API functions"]; +api(Config) when is_list(Config) -> + + %% get_disk_data() + ?line [{Id, KByte, Capacity}|_] = disksup:get_disk_data(), + ?line true = io_lib:printable_list(Id), + ?line true = is_integer(KByte), + ?line true = is_integer(Capacity), + ?line true = KByte>0, + ?line true = Capacity>0, + + %% get_check_interval() + ?line 1800000 = disksup:get_check_interval(), + + %% set_check_interval(Minutes) + ?line ok = disksup:set_check_interval(20), + ?line 1200000 = disksup:get_check_interval(), + ?line {'EXIT',{badarg,_}} = (catch disksup:set_check_interval(0.5)), + ?line 1200000 = disksup:get_check_interval(), + ?line ok = disksup:set_check_interval(30), + + %% get_almost_full_threshold() + ?line 80 = disksup:get_almost_full_threshold(), + + %% set_almost_full_threshold(Float) + ?line ok = disksup:set_almost_full_threshold(0.90), + ?line 90 = disksup:get_almost_full_threshold(), + ?line {'EXIT',{badarg,_}} = + (catch disksup:set_almost_full_threshold(-0.5)), + ?line 90 = disksup:get_almost_full_threshold(), + ?line ok = disksup:set_almost_full_threshold(0.80), + + ok. + +config(suite) -> + []; +config(doc) -> + ["Test configuration"]; +config(Config) when is_list(Config) -> + + %% Change configuration parameters and make sure change is reflected + %% when disksup is restarted + ?line ok = + application:set_env(os_mon, disk_space_check_interval, 29), + ?line ok = + application:set_env(os_mon, disk_almost_full_threshold, 0.81), + + ?line ok = supervisor:terminate_child(os_mon_sup, disksup), + ?line {ok, _Child1} = supervisor:restart_child(os_mon_sup, disksup), + + ?line 1740000 = disksup:get_check_interval(), + ?line 81 = disksup:get_almost_full_threshold(), + + %% Also try this with bad parameter values, should be ignored + ?line ok = + application:set_env(os_mon, disk_space_check_interval, 0.5), + ?line ok = + application:set_env(os_mon, disk_almost_full_threshold, -0.81), + + ?line ok = supervisor:terminate_child(os_mon_sup, disksup), + ?line {ok, _Child2} = supervisor:restart_child(os_mon_sup, disksup), + + ?line 1800000 = disksup:get_check_interval(), + ?line 80 = disksup:get_almost_full_threshold(), + + %% Reset configuration parameters + ?line ok = + application:set_env(os_mon, disk_space_check_interval, 30), + ?line ok = + application:set_env(os_mon, disk_almost_full_threshold, 0.80), + + ok. + +%%---------------------------------------------------------------------- +%% NOTE: The test case is a bit weak as it will fail if the disk usage +%% changes too much during its course, or if there are timing problems +%% with the alarm_handler receiving the alarms too late +%%---------------------------------------------------------------------- +alarm(suite) -> + []; +alarm(doc) -> + ["Test that alarms are set and cleared"]; +alarm(Config) when is_list(Config) -> + + %% Find out how many disks exceed the threshold + %% and make sure the corresponding number of alarms is set + ?line Threshold1 = disksup:get_almost_full_threshold(), % 80 + ?line Data1 = disksup:get_disk_data(), + ?line Over1 = over_threshold(Data1, Threshold1), + ?line Alarms1 = get_alarms(), + if + Over1==length(Alarms1) -> + ?line true; + true -> + dump_info(), + ?line ?t:fail({bad_alarms, Threshold1, Data1, Alarms1}) + end, + + %% Try to find a disk with space usage below Threshold1, + %% lower the threshold accordingly and make sure new alarms are set + Fun1 = fun({_Id, _Kbyte, Capacity}) -> + if + Capacity>0, Capacity<Threshold1 -> true; + true -> false + end + end, + ?line case until(Fun1, Data1) of + {_, _, Cap1} -> + Threshold2 = Cap1-1, + ?line ok = + disksup:set_almost_full_threshold(Threshold2/100), + ?line disksup ! timeout, % force a disk check + ?line Data2 = disksup:get_disk_data(), + ?line Over2 = over_threshold(Data2, Threshold2), + ?line Alarms2 = get_alarms(), + if + Over2==length(Alarms2), Over2>Over1 -> + ?line true; + true -> + dump_info(), + ?line ?t:fail({bad_alarms, Threshold2, Data2, Alarms2}) + end; + false -> + ?line ignore + end, + + %% Find out the highest space usage among all disks + %% and try to raise the threshold above this value, + %% make sure all alarms are cleared + Fun2 = fun({_Id, _Kbyte, Capacity}, MaxAcc) -> + if + Capacity>MaxAcc -> Capacity; + true -> MaxAcc + end + end, + ?line case lists:foldl(Fun2, 0, Data1) of + Max when Max<100 -> + Threshold3 = Max+1, + ?line ok = + disksup:set_almost_full_threshold(Threshold3/100), + ?line disksup ! timeout, % force a disk check + ?line Data3 = disksup:get_disk_data(), + ?line Over3 = over_threshold(Data3, Threshold3), + ?line Alarms3 = get_alarms(), + if + Over3==0, length(Alarms3)==0 -> + ?line ok; + true -> + dump_info(), + ?line ?t:fail({bad_alarms, Threshold3, Data3, Alarms3}) + end; + 100 -> + ?line ignore + end, + + %% Reset threshold + ?line ok = disksup:set_almost_full_threshold(Threshold1/100), + + ok. + +over_threshold(Data, Threshold) -> + Data2 = remove_duplicated_disks(lists:keysort(1, Data)), + lists:foldl(fun({_Id, _Kbyte, Cap}, N) when Cap>=Threshold -> + N+1; + (_DiskData, N) -> + N + end, + 0, + Data2). + +%% On some platforms (for example MontaVista) data for one disk can be +%% "duplicated": +%% Linux ppb 2.4.20_mvl31-pcore680 #1 Sun Feb 1 23:12:56 PST 2004 ppc unknown +%% +%% MontaVista(R) Linux(R) Professional Edition 3.1 +%% +%% [ppb:~]> /bin/df -lk +%% Filesystem 1k-blocks Used Available Use% Mounted on +%% rootfs 8066141 3023763 4961717 38% / +%% /dev/root 8066141 3023763 4961717 38% / +%% tmpfs 192892 0 192892 0% /dev/shm +%% +%% disksup: +%% [{"/",8066141,38}, {"/",8066141,38}, {"/dev/shm",192892,0}] +%% +%% disksup will only set ONE alarm for "/". +%% Therefore the list of disk data must be sorted and duplicated disk +%% tuples removed before calculating how many alarms should be set, or +%% the testcase will fail erroneously. +remove_duplicated_disks([{Id, _, _}, {Id, Kbyte, Cap}|T]) -> + remove_duplicated_disks([{Id, Kbyte, Cap}|T]); +remove_duplicated_disks([H|T]) -> + [H|remove_duplicated_disks(T)]; +remove_duplicated_disks([]) -> + []. + +get_alarms() -> + lists:filter(fun({{disk_almost_full, _Disk},_}) -> true; + (_) -> false + end, + alarm_handler:get_alarms()). + +until(Fun, [H|T]) -> + case Fun(H) of + true -> H; + false -> + until(Fun, T) + end; +until(_Fun, []) -> + false. + +port(suite) -> + []; +port(doc) -> + ["Test that disksup handles a terminating port program"]; +port(Config) when is_list(Config) -> + ?line Str = os:cmd("ps -ef | grep '[d]isksup'"), + case io_lib:fread("~s ~s", Str) of + {ok, [_Uid,Pid], _Rest} -> + + %% Monitor disksup + ?line MonRef = erlang:monitor(process, disksup), + ?line [{_Disk1,Kbyte1,_Cap1}|_] = disksup:get_disk_data(), + ?line true = Kbyte1>0, + + %% Kill the port program + case os:cmd("kill -9 " ++ Pid) of + [] -> + + %% disksup should now terminate + receive + {'DOWN', MonRef, _, _, {port_died, _Reason}} -> + ok; + {'DOWN', MonRef, _, _, Reason} -> + ?line ?t:fail({unexpected_exit_reason, Reason}) + after + 3000 -> + ?line ?t:fail({still_alive, Str}) + end, + + %% Give os_mon_sup time to restart disksup + ?t:sleep(?t:seconds(3)), + ?line [{_Disk2,Kbyte2,_Cap2}|_] = + disksup:get_disk_data(), + ?line true = Kbyte2>0, + + ok; + + Line -> + erlang:demonitor(MonRef), + {skip, {not_killed, Line}} + end; + _ -> + {skip, {os_pid_not_found, Str}} + end. + +terminate(suite) -> + []; +terminate(Config) when is_list(Config) -> + ?line ok = application:set_env(os_mon, start_disksup, false), + ?line ok = supervisor:terminate_child(os_mon_sup, disksup), + ok. + +unavailable(suite) -> + []; +unavailable(doc) -> + ["Test correct behaviour when service is unavailable"]; +unavailable(Config) when is_list(Config) -> + + %% Make sure all API functions return their dummy values + ?line [{"none",0,0}] = disksup:get_disk_data(), + ?line 1800000 = disksup:get_check_interval(), + ?line ok = disksup:set_check_interval(5), + ?line 80 = disksup:get_almost_full_threshold(), + ?line ok = disksup:set_almost_full_threshold(0.9), + + ok. + +restart(suite) -> + []; +restart(Config) when is_list(Config) -> + ?line ok = application:set_env(os_mon, start_disksup, true), + ?line {ok, _Pid} = supervisor:restart_child(os_mon_sup, disksup), + ok. + +otp_5910(suite) -> + []; +otp_5910(doc) -> + ["Test that alarms are cleared if disksup crashes or " + "if OS_Mon is stopped"]; +otp_5910(Config) when is_list(Config) -> + + %% Make sure disksup sets at least one alarm + ?line Data = disksup:get_disk_data(), + ?line Threshold0 = disksup:get_almost_full_threshold(), + ?line Threshold = case over_threshold(Data, Threshold0) of + 0 -> + [{_Id,_Kbyte,Cap}|_] = Data, + ?line ok = disksup:set_almost_full_threshold((Cap-1)/100), + Cap-1; + _N -> + Threshold0 + end, + ?line ok = application:set_env(os_mon, + disk_almost_full_threshold, + Threshold/100), + ?line disksup ! timeout, % force a disk check + ?line Data2 = disksup:get_disk_data(), + ?line Over = over_threshold(Data2, Threshold), + ?line Alarms = get_alarms(), + if + Over==0 -> + ?line ?t:fail({threshold_too_low, Data2, Threshold}); + Over==length(Alarms) -> + ok; + true -> + dump_info(), + ?line ?t:fail({bad_alarms, Threshold, Data2, Alarms}) + end, + + %% Kill disksup + exit(whereis(disksup), faked_disksup_crash), + + %% Wait a little to make sure disksup has been restarted, + %% then make sure the alarms are set once, but not twice + ?t:sleep(?t:seconds(1)), + ?line Data3 = disksup:get_disk_data(), + ?line Alarms2 = get_alarms(), + if + length(Alarms2)==length(Alarms) -> + ok; + true -> + dump_info(), + ?line ?t:fail({bad_alarms, Threshold, Data3, Alarms,Alarms2}) + end, + + %% Stop OS_Mon and make sure all disksup alarms are cleared + ?line ok = application:stop(os_mon), + ?t:sleep(?t:seconds(1)), + ?line Alarms3 = get_alarms(), + if + length(Alarms3)==0 -> + ok; + true -> + ?line ?t:fail({alarms_not_cleared, Alarms3}) + end, + + %% Reset threshold and restart OS_Mon + ?line ok = application:set_env(os_mon, + disksup_almost_full_threshold, 0.8), + ?line ok = disksup:set_almost_full_threshold(0.8), + ?line ok = application:start(os_mon), + + ok. + +dump_info() -> + io:format("Status: ~p~n", [sys:get_status(disksup)]). diff --git a/lib/os_mon/test/memsup_SUITE.erl b/lib/os_mon/test/memsup_SUITE.erl new file mode 100644 index 0000000000..01a7f6c7f2 --- /dev/null +++ b/lib/os_mon/test/memsup_SUITE.erl @@ -0,0 +1,782 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2010. 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(memsup_SUITE). +-include("test_server.hrl"). + +%% Test server specific exports +-export([all/1]). +-export([init_per_suite/1, end_per_suite/1]). +-export([init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([api/1, alarm1/1, alarm2/1, process/1]). +-export([config/1, timeout/1, unavailable/1, port/1]). +-export([otp_5910/1]). + +%% Default timetrap timeout (set in init_per_testcase) +-define(default_timeout, ?t:minutes(1)). + +init_per_suite(Config) when is_list(Config) -> + ?line ok = application:start(os_mon), + Config. + +end_per_suite(Config) when is_list(Config) -> + ?line ok = application:stop(os_mon), + Config. + +init_per_testcase(_Case, Config) -> + Dog = ?t:timetrap(?default_timeout), + [{watchdog,Dog} | Config]. + +end_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + Config. + +all(suite) -> + All = case ?t:os_type() of + {unix, sunos} -> + [api, alarm1, alarm2, process, + config, timeout, unavailable, port]; + {unix, linux} -> + [api, alarm1, alarm2, process, timeout]; + _OS -> + [api, alarm1, alarm2, process] + end, + Bugs = [otp_5910], + All ++ Bugs. + +api(suite) -> + []; +api(doc) -> + ["Test of API functions"]; +api(Config) when is_list(Config) -> + + %% get_memory_data() + ?line RegMemData = memsup:get_memory_data(), + case RegMemData of + {TotMem, AllBytes, {Pid, PidBytes}} when is_integer(TotMem), + is_integer(AllBytes), + is_pid(Pid), + is_integer(PidBytes) -> + ok; + {0, 0, _WorstPid} -> + ?line ?t:fail(first_data_collection_failed); + _ -> + ?line ?t:fail({bad_return, RegMemData}) + end, + + %% get_system_memory_data() + ?line ExtMemData = memsup:get_system_memory_data(), + Tags = [ total_memory, + free_memory, + system_total_memory, + largest_free, + number_of_free, + free_swap, + total_swap, + cached_memory, + buffered_memory, + shared_memory], + + ?line true = lists:all(fun({Tag,Value}) when is_atom(Tag), + is_integer(Value) -> + lists:member(Tag, Tags); + (_) -> + false + end, + ExtMemData), + + %% get_os_wordsize() + ?line ok = case memsup:get_os_wordsize() of + 32 -> ok; + 64 -> ok; + unsupported_os -> ok; + _ -> error + end, + + %% get_check_interval() + ?line 60000 = memsup:get_check_interval(), + + %% set_check_interval(Minutes) + ?line ok = memsup:set_check_interval(2), + ?line 120000 = memsup:get_check_interval(), + ?line {'EXIT',{badarg,_}} = + (catch memsup:set_check_interval(0.2)), + ?line 120000 = memsup:get_check_interval(), + ?line ok = memsup:set_check_interval(1), + + %% get_procmem_high_watermark() + ?line 5 = memsup:get_procmem_high_watermark(), + + %% set_procmem_high_watermark() + ?line ok = memsup:set_procmem_high_watermark(0.1), + ?line 10 = memsup:get_procmem_high_watermark(), + ?line {'EXIT',{badarg,_}} = + (catch memsup:set_procmem_high_watermark(-0.1)), + ?line 10 = memsup:get_procmem_high_watermark(), + ?line ok = memsup:set_procmem_high_watermark(0.05), + + %% get_sysmem_high_watermark() + ?line 80 = memsup:get_sysmem_high_watermark(), + + %% set_sysmem_high_watermark() + ?line ok = memsup:set_sysmem_high_watermark(0.9), + ?line 90 = memsup:get_sysmem_high_watermark(), + ?line {'EXIT',{badarg,_}} = + (catch memsup:set_sysmem_high_watermark(-0.9)), + ?line 90 = memsup:get_sysmem_high_watermark(), + ?line ok = memsup:set_sysmem_high_watermark(0.8), + + %% get|set_helper_timeout + ?line 30 = memsup:get_helper_timeout(), + ?line ok = memsup:set_helper_timeout(29), + ?line 29 = memsup:get_helper_timeout(), + ?line {'EXIT',{badarg,_}} = (catch memsup:set_helper_timeout(31.0)), + ?line 29 = memsup:get_helper_timeout(), + ok. + +%%---------------------------------------------------------------------- +%% NOTE: The test case is a bit weak as it will fail if the memory +%% usage changes too much during its course. +%%---------------------------------------------------------------------- +alarm1(suite) -> + []; +alarm1(doc) -> + ["Test alarms when memsup_system_only==false"]; +alarm1(Config) when is_list(Config) -> + + %% If system memory usage is too high, the testcase cannot + %% be run correctly + ?line {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(), + io:format("alarm1: Total: ~p, Alloc: ~p~n", [Total, Alloc]), + ?line SysUsage = Alloc/Total, + if + SysUsage>0.99 -> + {skip, sys_mem_too_high}; + true -> + alarm1(Config, SysUsage) + end. + +alarm1(_Config, SysUsage) -> + %% Set a long memory check interval, we will force memory checks + %% instead + ?line ok = memsup:set_check_interval(60), + + %% Check thresholds + ?line SysThreshold = (memsup:get_sysmem_high_watermark()/100), + ?line ProcThreshold = (memsup:get_procmem_high_watermark()/100), + + %% Check if a system alarm already should be set or not + SysP = if + SysUsage>SysThreshold -> true; + SysUsage=<SysThreshold -> false + end, + + %% If system memory is higher than threshold, make sure the system + %% alarm is set. Otherwise, make sure it is not set + case alarm_set(system_memory_high_watermark) of + {true, []} when SysP -> + ok; + false when not SysP -> + ok; + _ -> + ?line ?t:fail({sys_alarm, SysUsage, SysThreshold}) + end, + + %% Lower/raise the threshold to clear/set the alarm + NewSysThreshold = if + SysP -> + Value = 1.1*SysUsage, + if + Value > 0.99 -> 0.99; + true -> Value + end; + not SysP -> 0.9*SysUsage + end, + + ?line ok = memsup:set_sysmem_high_watermark(NewSysThreshold), + + %% Initiate and wait for a new data collection + ?line ok = force_collection(), + + %% Make sure the alarm is cleared/set + ?t:sleep(?t:seconds(5)), + case alarm_set(system_memory_high_watermark) of + {true, []} when not SysP -> + ok; + false when SysP -> + ok; + _ -> + ?line ?t:fail({sys_alarm, SysUsage, NewSysThreshold}) + end, + + %% Reset the threshold to set/clear the alarm again + ?line ok = memsup:set_sysmem_high_watermark(SysThreshold), + ?line ok = force_collection(), + ?t:sleep(?t:seconds(1)), + case alarm_set(system_memory_high_watermark) of + {true, []} when SysP -> + ok; + false when not SysP -> + ok; + _ -> + ?line ?t:fail({sys_alarm, SysUsage, SysThreshold}) + end, + + %% Check memory usage + ?line {Total2, _, {WorstPid, PidAlloc}} = memsup:get_memory_data(), + + %% Check if a process alarm already should be set or not + PidUsage = PidAlloc/Total2, + ProcP = if + PidUsage>ProcThreshold -> true; + PidUsage=<ProcThreshold -> false + end, + + %% Make sure the process alarm is set/not set accordingly + case alarm_set(process_memory_high_watermark) of + {true, WorstPid} when ProcP -> + ok; + false when not ProcP -> + ok; + {true, BadPid1} when ProcP -> + ?line ?t:fail({proc_alarm, WorstPid, BadPid1}); + _ -> + ?line ?t:fail({proc_alarm, PidUsage, ProcThreshold}) + end, + + %% Lower/raise the threshold to clear/set the alarm + NewProcThreshold = if + ProcP -> 1.1*PidUsage; + not ProcP -> 0.9*PidUsage + end, + ?line ok = memsup:set_procmem_high_watermark(NewProcThreshold), + ?line ok = force_collection(), + ?t:sleep(?t:seconds(1)), + case alarm_set(process_memory_high_watermark) of + {true, WorstPid} when not ProcP -> + ok; + false when ProcP -> + ok; + {true, BadPid2} when not ProcP -> + ?line test_server:fail({proc_alarm, WorstPid, BadPid2}); + _ -> + ?line ?t:fail({proc_alarm, PidUsage, ProcThreshold}) + end, + + %% Reset the threshold to clear/set the alarm + ?line ok = memsup:set_procmem_high_watermark(ProcThreshold), + ?line ok = force_collection(), + ?t:sleep(?t:seconds(1)), + case alarm_set(process_memory_high_watermark) of + {true, WorstPid} when ProcP -> + ok; + false when not ProcP -> + ok; + {true, BadPid3} when ProcP -> + ?line test_server:fail({proc_alarm, WorstPid, BadPid3}); + _ -> + ?line ?t:fail({proc_alarm, PidUsage, ProcThreshold}) + end, + + %% Reset memory check interval + ?line ok = memsup:set_check_interval(1), + ok. + +alarm2(suite) -> + []; +alarm2(doc) -> + ["Test alarms when memsup_system_only==true"]; +alarm2(Config) when is_list(Config) -> + + %% If system memory usage is too high, the testcase cannot + %% be run correctly + ?line {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(), + ?line SysUsage = Alloc/Total, + if + SysUsage>0.99 -> + {skip, sys_mem_too_high}; + true -> + alarm2(Config, SysUsage) + end. + +alarm2(_Config, _SysUsage) -> + + %% Change memsup_system_only and restart memsup + ?line ok = application:set_env(os_mon, memsup_system_only, true), + ?line ok = supervisor:terminate_child(os_mon_sup, memsup), + ?line {ok, _Memsup1} = supervisor:restart_child(os_mon_sup, memsup), + + %% Set a long memory check interval, we will force memory checks + %% instead + ?line ok = memsup:set_check_interval(60), + + %% Check data and thresholds + ?line {Total, Alloc, undefined} = memsup:get_memory_data(), + ?line SysThreshold = (memsup:get_sysmem_high_watermark()/100), + ?line true = is_integer(memsup:get_procmem_high_watermark()), + + %% Check if a system alarm already should be set or not + ?line SysUsage = Alloc/Total, + SysP = if + SysUsage>SysThreshold -> true; + SysUsage=<SysThreshold -> false + end, + + %% If system memory is higher than threshold, make sure the system + %% alarm is set. Otherwise, make sure it is not set + case alarm_set(system_memory_high_watermark) of + {true, []} when SysP -> + ok; + false when not SysP -> + ok; + _ -> + ?line ?t:fail({sys_alarm, SysUsage, SysThreshold}) + end, + + %% Lower/raise the threshold to clear/set the alarm + NewSysThreshold = if + SysP -> + Value = 1.1*SysUsage, + if + Value > 0.99 -> 0.99; + true -> Value + end; + not SysP -> 0.9*SysUsage + end, + + ?line ok = memsup:set_sysmem_high_watermark(NewSysThreshold), + + %% Initiate and wait for a new data collection + ?line ok = force_collection(), + + %% Make sure the alarm is cleared/set + ?t:sleep(?t:seconds(1)), + case alarm_set(system_memory_high_watermark) of + {true, []} when not SysP -> + ok; + false when SysP -> + ok; + _ -> + ?line ?t:fail({sys_alarm, SysUsage, NewSysThreshold}) + end, + + %% Reset the threshold to set/clear the alarm again + ?line ok = memsup:set_sysmem_high_watermark(SysThreshold), + ?line ok = force_collection(), + ?t:sleep(?t:seconds(1)), + case alarm_set(system_memory_high_watermark) of + {true, []} when SysP -> + ok; + false when not SysP -> + ok; + _ -> + ?line ?t:fail({sys_alarm, SysUsage, SysThreshold}) + end, + + %% Reset memsup_system_only and restart memsup + %% (memory check interval is then automatically reset) + ?line ok = application:set_env(os_mon, memsup_system_only, false), + ?line ok = supervisor:terminate_child(os_mon_sup, memsup), + ?line {ok, _Memsup2} = supervisor:restart_child(os_mon_sup, memsup), + + ok. + +alarm_set(Alarm) -> + alarm_set(Alarm, alarm_handler:get_alarms()). +alarm_set(Alarm, [{Alarm,Data}|_]) -> + {true,Data}; +alarm_set(Alarm, [_|T]) -> + alarm_set(Alarm, T); +alarm_set(_Alarm, []) -> + false. + +process(suite) -> + []; +process(doc) -> + ["Make sure memsup discovers a process grown very large"]; +process(Config) when is_list(Config) -> + + %% Set a long memory check interval, we will force memory checks + %% instead + ?line ok = memsup:set_check_interval(60), + + %% Collect data + MemData = memsup:get_memory_data(), + io:format("process: memsup:get_memory_data() = ~p~n", [MemData]), + ?line {_Total,_Free,{_,Bytes}} = MemData, + + %% Start a new process larger than Worst + ?line WorsePid = spawn(fun() -> new_hog(Bytes) end), + ?t:sleep(?t:seconds(1)), + + %% Initiate and wait for a new data collection + ?line ok = force_collection(), + + %% Check that get_memory_data() returns updated result + ?line case memsup:get_memory_data() of + {_, _, {WorsePid, _MoreBytes}} -> + ok; + {_, _, BadWorst} -> + ?line ?t:fail({worst_pid, BadWorst}) + end, + + %% Reset memory check interval + ?line exit(WorsePid, done), + ?line ok = memsup:set_check_interval(1), + ok. + +new_hog(Bytes) -> + WordSize = erlang:system_info(wordsize), + N = (Bytes+200) div WordSize div 2, + List = lists:duplicate(N, a), + new_hog_1(List). + +new_hog_1(List) -> + receive + _Any -> exit(List) + end. + +config(suite) -> + []; +config(doc) -> + ["Test configuration"]; +config(Config) when is_list(Config) -> + + %% Change configuration parameters and make sure change is reflected + %% when memsup is restarted + ?line ok = application:set_env(os_mon, memory_check_interval, 2), + ?line ok = + application:set_env(os_mon, system_memory_high_watermark, 0.9), + ?line ok = + application:set_env(os_mon, process_memory_high_watermark, 0.1), + ?line ok = application:set_env(os_mon, memsup_helper_timeout, 35), + ?line ok = application:set_env(os_mon, memsup_system_only, true), + + ?line ok = supervisor:terminate_child(os_mon_sup, memsup), + ?line {ok, _Child1} = supervisor:restart_child(os_mon_sup, memsup), + + ?line 120000 = memsup:get_check_interval(), + ?line 90 = memsup:get_sysmem_high_watermark(), + ?line 10 = memsup:get_procmem_high_watermark(), + ?line 35 = memsup:get_helper_timeout(), + + %% Also try this with bad parameter values, should be ignored + ?line ok = application:set_env(os_mon, memory_check_interval, 0.2), + ?line ok = + application:set_env(os_mon, system_memory_high_watermark, -0.9), + ?line ok = + application:set_env(os_mon, process_memory_high_watermark,-0.1), + ?line ok = application:set_env(os_mon, memsup_helper_timeout, 0.35), + ?line ok = application:set_env(os_mon, memsup_system_only, arne), + + ?line ok = supervisor:terminate_child(os_mon_sup, memsup), + ?line {ok, _Child2} = supervisor:restart_child(os_mon_sup, memsup), + + ?line 60000 = memsup:get_check_interval(), + ?line 80 = memsup:get_sysmem_high_watermark(), + ?line 5 = memsup:get_procmem_high_watermark(), + ?line 30 = memsup:get_helper_timeout(), + + %% Reset configuration parameters + ?line ok = application:set_env(os_mon, memory_check_interval, 1), + ?line ok = + application:set_env(os_mon, system_memory_high_watermark, 0.8), + ?line ok = + application:set_env(os_mon, process_memory_high_watermark,0.05), + ?line ok = application:set_env(os_mon, memsup_helper_timeout, 30), + ?line ok = application:set_env(os_mon, memsup_system_only, false), + + ok. + +unavailable(suite) -> + []; +unavailable(doc) -> + ["Test correct behaviour when service is unavailable"]; +unavailable(Config) when is_list(Config) -> + + %% Close memsup + ?line ok = application:set_env(os_mon, start_memsup, false), + ?line ok = supervisor:terminate_child(os_mon_sup, memsup), + + %% Make sure all API functions return their dummy values + ?line {0,0,{_Pid,0}} = memsup:get_memory_data(), + ?line ok = application:set_env(os_mon, memsup_system_only, true), + ?line {0,0,undefined} = memsup:get_memory_data(), + ?line ok = application:set_env(os_mon, memsup_system_only, false), + ?line [] = memsup:get_system_memory_data(), + ?line 0 = memsup:get_os_wordsize(), + ?line 60000 = memsup:get_check_interval(), + ?line ok = memsup:set_check_interval(2), + ?line 5 = memsup:get_procmem_high_watermark(), + ?line ok = memsup:set_procmem_high_watermark(0.10), + ?line 80 = memsup:get_sysmem_high_watermark(), + ?line ok = memsup:set_sysmem_high_watermark(0.90), + ?line 30 = memsup:get_helper_timeout(), + ?line ok = memsup:set_helper_timeout(35), + + %% Start memsup again, + ?line ok = application:set_env(os_mon, start_memsup, true), + ?line {ok, _Child} = supervisor:restart_child(os_mon_sup, memsup), + + ok. + +timeout(suite) -> + []; +timeout(doc) -> + ["Test stability of memsup when data collection times out"]; +timeout(Config) when is_list(Config) -> + + %% Set a long memory check interval and memsup_helper timeout, + %% we will force memory checks instead and fake timeouts + ?line ok = memsup:set_check_interval(60), + ?line ok = memsup:set_helper_timeout(3600), + + %% Provoke a timeout during memory collection + ?line memsup ! time_to_collect, + ?line memsup ! reg_collection_timeout, + + %% Not much we can check though, except that memsup is still running + ?line {_,_,_} = memsup:get_memory_data(), + + %% Provoke a timeout during extensive memory collection + %% We fake a gen_server:call/2 to be able to send a timeout message + %% while the request is being handled + + %% Linux should be handled the same way as solaris. + +% TimeoutMsg = case ?t:os_type() of +% {unix, sunos} -> ext_collection_timeout; +% {unix, linux} -> reg_collection_timeout +% end, + + TimeoutMsg = ext_collection_timeout, + + ?line Pid = whereis(memsup), + ?line Mref = erlang:monitor(process, Pid), + ?line Pid ! {'$gen_call', {self(), Mref}, get_system_memory_data}, + ?line Pid ! TimeoutMsg, + receive + {Mref, []} -> + erlang:demonitor(Mref), + ?line ok; + {Mref, Res} -> + erlang:demonitor(Mref), + ?line ?t:fail({unexpected_result, Res}); + {'DOWN', Mref, _, _, _} -> + ?line ?t:fail(no_result) + end, + + %% Reset memory check interval and memsup_helper timeout + ?line ok = memsup:set_check_interval(1), + ?line ok = memsup:set_helper_timeout(30), + ?line memsup ! time_to_collect, + + ?line [_|_] = memsup:get_system_memory_data(), + + ok. + +port(suite) -> + []; +port(doc) -> + ["Test that memsup handles a terminating port program"]; +port(Config) when is_list(Config) -> + ?line Str = os:cmd("ps -e | grep '[m]emsup'"), + case io_lib:fread("~s", Str) of + {ok, [Pid], _Rest} -> + + %% Monitor memsup + ?line MonRef = erlang:monitor(process, memsup), + ?line {Total1,_Alloc1,_Worst1} = memsup:get_memory_data(), + ?line true = Total1>0, + + %% Kill the port program + case os:cmd("kill -9 " ++ Pid) of + [] -> + + %% memsup should now terminate + receive + {'DOWN', MonRef, _, _, {port_died, _Reason}} -> + ok; + {'DOWN', MonRef, _, _, Reason} -> + ?line ?t:fail({unexpected_exit_reason, Reason}) + after + 3000 -> + ?line ?t:fail(still_alive) + end, + + %% Give os_mon_sup time to restart memsup + ?t:sleep(?t:seconds(3)), + ?line {Total2,_Alloc2,_Worst2} = + memsup:get_memory_data(), + ?line true = Total2>0, + + ok; + + Line -> + erlang:demonitor(MonRef), + {skip, {not_killed, Line}} + end; + _ -> + {skip, {os_pid_not_found, Str}} + end. + +otp_5910(suite) -> + []; +otp_5910(doc) -> + ["Test that alarms are cleared and not set twice"]; +otp_5910(Config) when is_list(Config) -> + Alarms = + [system_memory_high_watermark, process_memory_high_watermark], + + %% Make sure memsup sets both alarms + ?line ok = application:set_env(os_mon, memory_check_interval, 60), + ?line ok = memsup:set_check_interval(60), + ?line SysThreshold = (memsup:get_sysmem_high_watermark()/100), + ?line ProcThreshold = (memsup:get_procmem_high_watermark()/100), + + MemData = memsup:get_memory_data(), + + io:format("otp_5910: memsup:get_memory_data() = ~p~n", [MemData]), + ?line {Total, Alloc, {_Pid, _Bytes}} = MemData, + ?line Pid = spawn_opt(fun() -> + receive + die -> ok + end + end, [{min_heap_size, 1000}]), + %% Create a process guaranteed to live, be constant and + %% break memsup process limit + ?line {memory, Bytes} = erlang:process_info(Pid,memory), + ?line SysUsage = Alloc/Total, + ?line ProcUsage = Bytes/Total, + + if + SysUsage>SysThreshold -> + ok; + SysUsage=<SysThreshold -> + ?line ok = application:set_env(os_mon, + sys_mem_high_watermark, + 0.5 * SysUsage), + ?line ok = memsup:set_sysmem_high_watermark(0.5 * SysUsage) + end, + if + ProcUsage>ProcThreshold -> + ok; + ProcUsage=<ProcThreshold -> + ?line ok = application:set_env(os_mon, + proc_mem_high_watermark, + 0.5 * ProcUsage), + ?line ok = memsup:set_procmem_high_watermark(0.5 *ProcUsage) + end, + ?line ok = force_collection(), + ?t:sleep(?t:seconds(1)), + lists:foreach(fun(AlarmId) -> + case alarm_set(AlarmId) of + {true, _} -> ok; + false -> + ?line ?t:fail({alarm_not_set, + AlarmId}) + end + end, + Alarms), + + %% Kill guaranteed process... + Pid ! die, + %% Kill memsup + exit(whereis(memsup), faked_memsup_crash), + %% Wait a little to make sure memsup has been restarted, + %% then make sure the alarms are set once, but not twice + ?t:sleep(?t:seconds(1)), + ?line MemUsage = memsup:get_memory_data(), + SetAlarms = alarm_handler:get_alarms(), + case lists:foldl(fun(system_memory_high_watermark, {S, P}) -> + {S+1, P}; + (process_memory_high_watermark, {S, P}) -> + {S, P+1}; + (_AlarmId, Acc0) -> + Acc0 + end, + {0, 0}, + SetAlarms) of + {0, 0} -> + ok; + _ -> + ?line ?t:fail({bad_number_of_alarms, SetAlarms, MemUsage}) + end, + + %% Stop OS_Mon and make sure all memsup alarms are cleared + ?line ok = application:stop(os_mon), + ?t:sleep(?t:seconds(1)), + lists:foreach(fun(AlarmId) -> + case alarm_set(AlarmId) of + false -> ok; + {true, _} -> + ?line ?t:fail({alarm_is_set, AlarmId}) + end + end, + Alarms), + + %% Reset configuration and restart OS_Mon + ?line ok = application:set_env(os_mon,memory_check_interval,1), + ?line ok = application:set_env(os_mon,sys_mem_high_watermark,0.8), + ?line ok = application:set_env(os_mon,proc_mem_high_watermark,0.05), + ?line ok = application:start(os_mon), + + ok. + +%%---------------------------------------------------------------------- +%% Auxiliary +%%---------------------------------------------------------------------- + +force_collection() -> + erlang:trace(whereis(memsup), true, ['receive']), + memsup ! time_to_collect, + TimerRef = erlang:send_after(5000, self(), timeout), + force_collection(TimerRef). + +force_collection(TimerRef) -> + receive + {trace, _Pid, 'receive', {collected_sys, _Sys}} -> + erlang:cancel_timer(TimerRef), + erlang:trace(whereis(memsup), false, ['receive']), + flush(), + ok; + {trace, _Pid, 'receive', reg_collection_timeout} -> + erlang:cancel_timer(TimerRef), + erlang:trace(whereis(memsup), false, ['receive']), + flush(), + collection_timeout; + timout -> + erlang:trace(whereis(memsup), false, ['receive']), + flush(), + timeout; + _Msg -> + force_collection(TimerRef) + end. + +flush() -> + receive + {trace, _, _, _} -> + flush(); + timeout -> + flush() + after 0 -> + ok + end. diff --git a/lib/os_mon/test/os_mon.spec b/lib/os_mon/test/os_mon.spec new file mode 100644 index 0000000000..bdae523795 --- /dev/null +++ b/lib/os_mon/test/os_mon.spec @@ -0,0 +1 @@ +{topcase, {dir, "../os_mon_test"}}. diff --git a/lib/os_mon/test/os_mon_SUITE.erl b/lib/os_mon/test/os_mon_SUITE.erl new file mode 100644 index 0000000000..ce52271ff8 --- /dev/null +++ b/lib/os_mon/test/os_mon_SUITE.erl @@ -0,0 +1,89 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2010. 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(os_mon_SUITE). +-include("test_server.hrl"). + +%% Test server specific exports +-export([all/1]). +-export([init_per_testcase/2, fin_per_testcase/2]). + +%% Test cases +-export([app_file/1, config/1]). + +%% Default timetrap timeout (set in init_per_testcase) +-define(default_timeout, ?t:minutes(1)). + +init_per_testcase(_Case, Config) -> + Dog = test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +all(suite) -> + case ?t:os_type() of + {unix, sunos} -> [app_file, config]; + _OS -> [app_file] + end. + +app_file(suite) -> + []; +app_file(doc) -> + ["Testing .app file"]; +app_file(Config) when is_list(Config) -> + ?line ok = test_server:app_test(os_mon), + ok. + +config(suite) -> + []; +config(doc) -> + ["Test OS_Mon configuration"]; +config(Config) when is_list(Config) -> + + IsReg = fun(Name) -> is_pid(whereis(Name)) end, + IsNotReg = fun(Name) -> undefined == whereis(Name) end, + + ?line ok = application:start(os_mon), + ?line true = lists:all(IsReg, [cpu_sup, disksup, memsup]), + ?line ok = application:stop(os_mon), + + ?line ok = application:set_env(os_mon, start_cpu_sup, false), + ?line ok = application:start(os_mon), + ?line true = lists:all(IsReg, [disksup, memsup]), + ?line true = IsNotReg(cpu_sup), + ?line ok = application:stop(os_mon), + ?line ok = application:set_env(os_mon, start_cpu_sup, true), + + ?line ok = application:set_env(os_mon, start_disksup, false), + ?line ok = application:start(os_mon), + ?line true = lists:all(IsReg, [cpu_sup, memsup]), + ?line true = IsNotReg(disksup), + ?line ok = application:stop(os_mon), + ?line ok = application:set_env(os_mon, start_disksup, true), + + ?line ok = application:set_env(os_mon, start_memsup, false), + ?line ok = application:start(os_mon), + ?line true = lists:all(IsReg, [cpu_sup, disksup]), + ?line true = IsNotReg(memsup), + ?line ok = application:stop(os_mon), + ?line ok = application:set_env(os_mon, start_memsup, true), + + ok. diff --git a/lib/os_mon/test/os_mon_conf.erl b/lib/os_mon/test/os_mon_conf.erl new file mode 100644 index 0000000000..5c1fa43047 --- /dev/null +++ b/lib/os_mon/test/os_mon_conf.erl @@ -0,0 +1,28 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2010. 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(os_mon_conf). +-export([init/1,fin/1]). + +init(Conf) -> + RetVal = application:start(os_mon,temporary), + [{os_mon,RetVal}|Conf]. + +fin(Conf) -> + application:stop(os_mon), + lists:keydelete(os_mon,1,Conf). diff --git a/lib/os_mon/test/os_mon_mib_SUITE.erl b/lib/os_mon/test/os_mon_mib_SUITE.erl new file mode 100644 index 0000000000..a1d463030a --- /dev/null +++ b/lib/os_mon/test/os_mon_mib_SUITE.erl @@ -0,0 +1,746 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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(os_mon_mib_SUITE). + +%-define(STANDALONE,1). + +-ifdef(STANDALONE). +-define(line,erlang:display({line,?LINE}),). +-define(config(A,B), config(A,B)). +-else. +-include("test_server.hrl"). +-include_lib("os_mon/include/OTP-OS-MON-MIB.hrl"). +-include_lib("snmp/include/snmp_types.hrl"). +-endif. + +% Test server specific exports +-export([all/1, init_per_suite/1, end_per_suite/1, + init_per_testcase/2, end_per_testcase/2]). + + +% Test cases must be exported. +-export([update_load_table/1]). + +-export([get_mem_sys_mark/1, get_mem_proc_mark/1, get_disk_threshold/1, + get_load_table/1, get_next_load_table/1, get_disk_table/1, + get_next_disk_table/1, real_snmp_request/1, load_unload/1]). + +-export([sys_tot_mem/1, sys_used_mem/1, large_erl_process/1, + large_erl_process_mem/1, cpu_load/1, cpu_load5/1, cpu_load15/1, + os_wordsize/1, sys_tot_mem64/1, sys_used_mem64/1, + large_erl_process_mem64/1, disk_descr/1, disk_kbytes/1, + disk_capacity/1]). + +-export([tickets/1]). +-export([otp_6351/1, otp_7441/1]). + +-define(TRAP_UDP, 5000). +-define(AGENT_UDP, 4000). +-define(CONF_FILE_VER, [v2]). +-define(SYS_NAME, "Test os_mon_mibs"). +-define(MAX_MSG_SIZE, 484). +-define(ENGINE_ID, "mgrEngine"). +-define(MGR_PORT, 5001). + +%%--------------------------------------------------------------------- +-ifdef(STANDALONE). +-export([run/0]). +run() -> + catch init_per_suite([]), + Ret = (catch update_load_table([])), + catch end_per_suite([]), + Ret. +-else. + +init_per_testcase(_Case, Config) when is_list(Config) -> + Dog = test_server:timetrap(test_server:minutes(6)), + [{watchdog, Dog}|Config]. + +end_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + Config. + +all(doc) -> + ["Test os_mon mibs and provided instrumentation functions."]; + +all(suite) -> + [load_unload, get_mem_sys_mark, get_mem_proc_mark, + get_disk_threshold, get_load_table, get_next_load_table, + get_disk_table, get_next_disk_table, real_snmp_request, + update_load_table, tickets]. + +tickets(suite) -> + [otp_6351, otp_7441]. + +-endif. +%%--------------------------------------------------------------------- +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config) -> Config +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + ?line application:start(sasl), + ?line application:start(mnesia), + ?line application:start(os_mon), + + %% Create initial configuration data for the snmp application + ?line PrivDir = ?config(priv_dir, Config), + ?line ConfDir = filename:join(PrivDir, "conf"), + ?line DbDir = filename:join(PrivDir,"db"), + ?line MgrDir = filename:join(PrivDir,"mgr"), + + ?line file:make_dir(ConfDir), + ?line file:make_dir(DbDir), + ?line file:make_dir(MgrDir), + + {ok, HostName} = inet:gethostname(), + {ok, Addr} = inet:getaddr(HostName, inet), + + ?line snmp_config:write_agent_snmp_files(ConfDir, ?CONF_FILE_VER, + tuple_to_list(Addr), ?TRAP_UDP, + tuple_to_list(Addr), + ?AGENT_UDP, ?SYS_NAME), + + ?line snmp_config:write_manager_snmp_files(MgrDir, tuple_to_list(Addr), + ?MGR_PORT, ?MAX_MSG_SIZE, + ?ENGINE_ID, [], [], []), + + %% To make sure application:set_env is not overwritten by any + %% app-file settings. + ?line ok = application:load(snmp), + + ?line application:set_env(snmp, agent, [{db_dir, DbDir}, + {config, [{dir, ConfDir}]}, + {agent_type, master}, + {agent_verbosity, trace}, + {net_if, [{verbosity, trace}]}]), + ?line application:set_env(snmp, manager, [{config, [{dir, MgrDir}, + {db_dir, MgrDir}, + {verbosity, trace}]}, + {server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {versions, [v1, v2, v3]}]), + application:start(snmp), + + %% Load the mibs that should be tested + otp_mib:load(snmp_master_agent), + os_mon_mib:load(snmp_master_agent), + + [{agent_ip, Addr}| Config]. +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config) -> _ +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after the whole suite +%%-------------------------------------------------------------------- +end_per_suite(Config) -> + PrivDir = ?config(priv_dir, Config), + ConfDir = filename:join(PrivDir,"conf"), + DbDir = filename:join(PrivDir,"db"), + MgrDir = filename:join(PrivDir, "mgr"), + + %% Uload mibs + snmpa:unload_mibs(snmp_master_agent,["OTP-OS-MON-MIB"]), + otp_mib:unload(snmp_master_agent), + + %% Clean up + application:stop(snmp), + application:stop(mnesia), + application:stop(os_mon), + + del_dir(ConfDir), + del_dir(DbDir), + (catch del_dir(MgrDir)), + ok. + +%%--------------------------------------------------------------------- +%% Test cases +%%--------------------------------------------------------------------- +load_unload(doc) -> + ["Test to unload and the reload the OTP.mib "]; +load_unload(suite) -> []; +load_unload(Config) when list(Config) -> + ?line os_mon_mib:unload(snmp_master_agent), + ?line os_mon_mib:load(snmp_master_agent), + ok. +%%--------------------------------------------------------------------- + +update_load_table(doc) -> + ["check os_mon_mib:update_load_table error handling"]; +update_load_table(suite) -> + []; +update_load_table(Config) when is_list(Config) -> + ?line Node = start_node(), + ?line ok = rpc:call(Node,application,start,[sasl]), + ?line ok = rpc:call(Node,application,start,[os_mon]), + ?line ok = os_mon_mib:update_load_table(), + ?line rpc:call(Node,application,stop,[os_mon]), + ?line ok = os_mon_mib:update_load_table(), + ?line stop_node(Node), + ok. + +otp_6351(doc) -> + ["like update_load_table, when memsup_system_only==true"]; +otp_6351(suite) -> + []; +otp_6351(Config) when is_list(Config) -> + ?line Node = start_node(), + ?line ok = rpc:call(Node,application,start,[sasl]), + ?line ok = rpc:call(Node,application,load,[os_mon]), + ?line ok = rpc:call(Node,application,set_env, + [os_mon,memsup_system_only,true]), + ?line ok = rpc:call(Node,application,start,[os_mon]), + ?line Res = rpc:call(Node,os_mon_mib,get_load,[Node]), + if + is_tuple(Res), element(1, Res)==loadTable -> + ?line ok; + true -> + ?line ?t:fail(Res) + end, + ?line rpc:call(Node,application,stop,[os_mon]), + ?line stop_node(Node), + ok. + + + + +%%--------------------------------------------------------------------- +get_mem_sys_mark(doc) -> + ["Simulates a get call to test the instrumentation function " + "for the loadMemorySystemWatermark variable."]; +get_mem_sys_mark(suite) -> + []; +get_mem_sys_mark(Config) when is_list(Config) -> + case os_mon_mib:mem_sys_mark(get) of + {value, SysMark} when is_integer(SysMark) -> + ok; + _ -> + ?line test_server:fail(sys_mark_value_not_integer) + end. +%%--------------------------------------------------------------------- +get_mem_proc_mark(doc) -> + ["Simulates a get call to test the instrumentation function " + "for the loadMemoryErlProcWatermark variable."]; +get_mem_proc_mark(suite) -> + []; +get_mem_proc_mark(Config) when is_list(Config) -> + case os_mon_mib:mem_proc_mark(get) of + {value, ProcMark} when is_integer(ProcMark) -> + ok; + _ -> + ?line test_server:fail(proc_mark_value_not_integer) + end. +%%--------------------------------------------------------------------- +get_disk_threshold(doc) -> + ["Simulates a get call to test the instrumentation function " + "for the diskAlmostFullThreshold variable."]; +get_disk_threshold(suite) -> + []; +get_disk_threshold(Config) when is_list(Config) -> + case os_mon_mib:disk_threshold(get) of + {value, ProcMark} when is_integer(ProcMark) -> + ok; + _ -> + ?line test_server:fail(disk_threshold_value_not_integer) + end. +%%--------------------------------------------------------------------- + +%%% Note that when we have a string key, as in loadTable, the +%%% instrumentation will deal with the [length(String), String]. We +%%% have to know about this, when short cutting SNMP and calling +%%% instrumentation functions directly as done in most test cases in +%%% this test suite + +get_load_table(doc) -> + ["Simulates get calls to test the instrumentation function " + "for the loadTable"]; +get_load_table(suite) -> + []; +get_load_table(Config) when is_list(Config) -> + + NodeStr = atom_to_list(node()), + NodeLen = length(NodeStr), + + {_, _, {Pid, _}} = memsup:get_memory_data(), + PidStr = lists:flatten(io_lib:format("~w", [Pid])), + ?line [{value, NodeStr},{value, PidStr}] = + os_mon_mib:load_table(get, [NodeLen | NodeStr], + [?loadErlNodeName, ?loadLargestErlProcess]), + + ?line Values = os_mon_mib:load_table(get, [NodeLen | NodeStr] , + [?loadSystemTotalMemory, + ?loadSystemUsedMemory, + ?loadLargestErlProcessUsedMemory, + ?loadCpuLoad, + ?loadCpuLoad5, + ?loadCpuLoad15, + ?loadOsWordsize, + ?loadSystemTotalMemory64, + ?loadSystemUsedMemory64, + ?loadLargestErlProcessUsedMemory64]), + + IsInt = fun({value, Val}) when is_integer(Val) -> + true; + (_) -> + false + end, + + NewValues = lists:filter(IsInt, Values), + + case length(NewValues) of + 10 -> + ok; + _ -> + ?line test_server:fail(value_not_integer) + end, + + ?line [{noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}] = + os_mon_mib:load_table(get, [3, 102, 111, 111], + [?loadErlNodeName, + ?loadSystemTotalMemory, + ?loadSystemUsedMemory, + ?loadLargestErlProcess, + ?loadLargestErlProcessUsedMemory, + ?loadCpuLoad, + ?loadCpuLoad5, + ?loadCpuLoad15, + ?loadOsWordsize, + ?loadSystemTotalMemory64, + ?loadSystemUsedMemory64, + ?loadLargestErlProcessUsedMemory64]), + + ok. +%%--------------------------------------------------------------------- +get_next_load_table(doc) -> + ["Simulates get_next calls to test the instrumentation function " + "for the loadTable"]; +get_next_load_table(suite) -> + [ sys_tot_mem, + sys_used_mem, + large_erl_process, + large_erl_process_mem, + cpu_load, + cpu_load5, + cpu_load15, + os_wordsize, + sys_tot_mem64, + sys_used_mem64, + large_erl_process_mem64]. + +sys_tot_mem(doc) -> + []; +sys_tot_mem(suite) -> + []; +sys_tot_mem(Config) when is_list(Config) -> + ?line [{[?loadSystemTotalMemory, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Mem of + Mem when is_integer(Mem) -> + ok; + _ -> + ?line test_server:fail(sys_tot_mem_value_not_integer) + end. + +sys_used_mem(doc) -> + []; +sys_used_mem(suite) -> []; +sys_used_mem(Config) when is_list(Config) -> + ?line [{[?loadSystemUsedMemory, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Mem of + Mem when is_integer(Mem) -> + ok; + _ -> + ?line test_server:fail(sys_used_mem_value_not_integer) + end. + +large_erl_process(doc) -> + []; +large_erl_process(suite) -> + []; +large_erl_process(Config) when is_list(Config) -> + {_, _, {Pid, _}} = memsup:get_memory_data(), + PidStr = lists:flatten(io_lib:format("~w", [Pid])), + ?line [{[?loadLargestErlProcess, Len | NodeStr], PidStr}] = + os_mon_mib:load_table(get_next,[], [?loadLargestErlProcess]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + ok. + +large_erl_process_mem(doc) -> + []; +large_erl_process_mem(suite) -> + []; +large_erl_process_mem(Config) when is_list(Config) -> + + ?line [{[?loadLargestErlProcessUsedMemory, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next,[], + [?loadLargestErlProcessUsedMemory]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Mem of + Mem when is_integer(Mem) -> + ok; + _ -> + ?line test_server:fail(erl_pid_mem_value_not_integer) + end. + +cpu_load(doc) -> + []; +cpu_load(suite) -> + []; +cpu_load(Config) when list(Config) -> + ?line [{[?loadCpuLoad, Len | NodeStr], Load}] = + os_mon_mib:load_table(get_next,[], [?loadCpuLoad]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Load of + Load when is_integer(Load) -> + ok; + _ -> + ?line test_server:fail(cpu_load_value_not_integer) + end. + +cpu_load5(doc) -> + []; +cpu_load5(suite) -> + []; +cpu_load5(Config) when is_list(Config) -> + ?line [{[?loadCpuLoad5, Len | NodeStr], Load}] = + os_mon_mib:load_table(get_next,[], [?loadCpuLoad5]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Load of + Load when is_integer(Load) -> + ok; + _ -> + ?line test_server:fail(cpu_load5_value_not_integer) + end. + +cpu_load15(doc) -> + []; +cpu_load15(suite) -> + []; +cpu_load15(Config) when is_list(Config) -> + ?line [{[?loadCpuLoad15, Len | NodeStr], Load}] = + os_mon_mib:load_table(get_next,[], [?loadCpuLoad15]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Load of + Load when is_integer(Load) -> + ok; + _ -> + ?line test_server:fail(cpu_load15_value_not_integer) + end. + +os_wordsize(doc) -> + []; +os_wordsize(suite) -> + []; +os_wordsize(Config) when is_list(Config) -> + ?line [{[?loadOsWordsize, Len | NodeStr], Wordsize}] = + os_mon_mib:load_table(get_next,[], [?loadOsWordsize]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Wordsize of + Wordsize when is_integer(Wordsize) -> + ok; + _ -> + ?line test_server:fail(os_wordsize_value_not_integer) + end. + +sys_tot_mem64(doc) -> + []; +sys_tot_mem64(suite) -> + []; +sys_tot_mem64(Config) when is_list(Config) -> + ?line [{[?loadSystemTotalMemory64, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory64]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Mem of + Mem when is_integer(Mem) -> + ok; + _ -> + ?line test_server:fail(sys_tot_mem_value_not_integer) + end. + +sys_used_mem64(doc) -> + []; +sys_used_mem64(suite) -> []; +sys_used_mem64(Config) when is_list(Config) -> + ?line [{[?loadSystemUsedMemory64, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory64]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Mem of + Mem when is_integer(Mem) -> + ok; + _ -> + ?line test_server:fail(sys_used_mem_value_not_integer) + end. + +large_erl_process_mem64(doc) -> + []; +large_erl_process_mem64(suite) -> + []; +large_erl_process_mem64(Config) when is_list(Config) -> + + ?line [{[?loadLargestErlProcessUsedMemory64, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next,[], + [?loadLargestErlProcessUsedMemory64]), + ?line Len = length(NodeStr), + ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Mem of + Mem when is_integer(Mem) -> + ok; + _ -> + ?line test_server:fail(erl_pid_mem_value_not_integer) + end. +%%--------------------------------------------------------------------- +get_disk_table(doc) -> + ["Simulates get calls to test the instrumentation function " + "for the diskTable."]; +get_disk_table(suite) -> + []; +get_disk_table(Config) when is_list(Config) -> + + DiskData = disksup:get_disk_data(), + DiskDataLen = length(DiskData), + + if + DiskDataLen > 0 -> + ?line [{value, Value}] = + os_mon_mib:disk_table(get, [1,1], [?diskDescr]), + + case is_list(Value) of + true -> + ok; + false -> + ?line test_server:fail(value_not_a_string) + end, + + ?line Values = os_mon_mib:disk_table(get, [1,1], + [?diskId, + ?diskKBytes, + ?diskCapacity]), + + IsInt = fun({value, Val}) when is_integer(Val) -> + true; + (_) -> + false + end, + + NewValues = lists:filter(IsInt, Values), + + case length(NewValues) of + 3 -> + ok; + _ -> + ?line test_server:fail(value_not_integer) + end + end, + + ?line [{noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}] = + os_mon_mib:disk_table(get, [1, DiskDataLen + 1], [?diskId, + ?diskDescr, + ?diskKBytes, + ?diskCapacity]), + + ok. + +%%--------------------------------------------------------------------- +get_next_disk_table(doc) -> + ["Simulates get_next calls to test the instrumentation function " + "for the diskTable."]; +get_next_disk_table(suite) -> + [disk_descr, disk_kbytes, disk_capacity]. + +disk_descr(doc) -> + []; +disk_descr(suite) -> + []; +disk_descr(Config) when is_list(Config) -> + ?line [{[?diskDescr, 1,1], Descr}] = + os_mon_mib:disk_table(get_next, [], [?diskDescr]), + + case Descr of + Descr when is_list(Descr) -> + ok; + _ -> + ?line test_server:fail(disk_descr_value_not_a_string) + end. + +disk_kbytes(doc) -> + []; +disk_kbytes(suite) -> []; +disk_kbytes(Config) when is_list(Config) -> + ?line [{[?diskKBytes, 1,1], Kbytes}] = + os_mon_mib:disk_table(get_next,[], [?diskKBytes]), + + case Kbytes of + Kbytes when is_integer(Kbytes) -> + ok; + _ -> + ?line test_server:fail(disk_kbytes_value_not_integer) + end. + + +disk_capacity(doc) -> + []; +disk_capacity(suite) -> []; +disk_capacity(Config) when is_list(Config) -> + ?line [{[?diskCapacity, 1,1], Capacity}] = + os_mon_mib:disk_table(get_next,[], [?diskCapacity]), + + case Capacity of + Capacity when is_integer(Capacity) -> + ok; + _ -> + ?line test_server:fail(disk_capacity_value_not_integer) + end. + +%%--------------------------------------------------------------------- +real_snmp_request(doc) -> + ["Starts an snmp manager and sends a real snmp-reques. i.e. " + "sends a udp message on the correct format."]; +real_snmp_request(suite) -> []; +real_snmp_request(Config) when list(Config) -> + Agent_ip = ?config(agent_ip, Config), + + ?line ok = snmpm:register_user(os_mon_mib_test, snmpm_user_default, []), + ?line ok = snmpm:register_agent(os_mon_mib_test, Agent_ip, ?AGENT_UDP), + + NodStr = atom_to_list(node()), + Len = length(NodStr), + {_, _, {Pid, _}} = memsup:get_memory_data(), + PidStr = lists:flatten(io_lib:format("~w", [Pid])), + io:format("FOO: ~p~n", [PidStr]), + ?line ok = snmp_get(Agent_ip, + [?loadEntry ++ + [?loadLargestErlProcess, Len | NodStr]], + PidStr), + ?line ok = snmp_get_next(Agent_ip, + [?loadEntry ++ + [?loadSystemUsedMemory, Len | NodStr]], + ?loadEntry ++ [?loadSystemUsedMemory + 1, Len + | NodStr], PidStr), + ?line ok = snmp_set(Agent_ip, [?loadEntry ++ + [?loadLargestErlProcess, Len | NodStr]], + s, "<0.101.0>"), + ok. + +otp_7441(doc) -> + ["Starts an snmp manager and requests total memory. Was previously + integer32 which was errornous on 64 bit machines."]; +otp_7441(suite) -> + []; +otp_7441(Config) when is_list(Config) -> + Agent_ip = ?config(agent_ip, Config), + + + NodStr = atom_to_list(node()), + Len = length(NodStr), + Oids = [Oid|_] = [?loadEntry ++ [?loadSystemTotalMemory, Len | NodStr]], + ?line { ok, {noError,0,[#varbind{oid = Oid, variabletype = 'Unsigned32'}]}, _} = + snmpm:g(os_mon_mib_test, Agent_ip, ?AGENT_UDP, Oids), + + ok. + +%%--------------------------------------------------------------------- +%% Internal functions +%%--------------------------------------------------------------------- +-ifdef(STANDALONE). +config(priv_dir,_) -> + "/tmp". + +start_node() -> + Host = hd(tl(string:tokens(atom_to_list(node()),"@"))), + {ok,Node} = slave:start(Host,testnisse), + net_adm:ping(testnisse), + Node. + + +stop_node(Node) -> + rpc:call(Node,erlang,halt,[]). +-else. +start_node() -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line {ok,Node} = test_server:start_node(testnisse, slave, + [{args, " -pa " ++ Pa}]), + Node. + +stop_node(Node) -> + test_server:stop_node(Node). + +-endif. + +del_dir(Dir) -> + io:format("Deleting: ~s~n",[Dir]), + {ok, Files} = file:list_dir(Dir), + FullPathFiles = lists:map(fun(File) -> filename:join(Dir, File) end, + Files), + lists:foreach({file, delete}, FullPathFiles), + file:del_dir(Dir). + +%%--------------------------------------------------------------------- +snmp_get(Agent_ip, Oids = [Oid |_], Result) -> + ?line {ok,{noError,0,[#varbind{oid = Oid, + variabletype = 'OCTET STRING', + value = Result}]}, _} = + snmpm:g(os_mon_mib_test, Agent_ip, ?AGENT_UDP, Oids), + ok. + +snmp_get_next(Agent_ip, Oids, NextOid, Result) -> + ?line {ok,{noError,0,[#varbind{oid = NextOid, + variabletype = 'OCTET STRING', + value = Result}]},_} = + snmpm:gn(os_mon_mib_test, Agent_ip, ?AGENT_UDP, Oids), + ok. + +snmp_set(Agent_ip, Oid, ValuType, Value) -> + ?line {ok, {notWritable, _, _}, _} = + snmpm:s(os_mon_mib_test,Agent_ip,?AGENT_UDP,[{Oid, ValuType, Value}]), + ok. diff --git a/lib/os_mon/test/os_sup_SUITE.erl b/lib/os_mon/test/os_sup_SUITE.erl new file mode 100644 index 0000000000..25041f968d --- /dev/null +++ b/lib/os_mon/test/os_sup_SUITE.erl @@ -0,0 +1,189 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2010. 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(os_sup_SUITE). +-include("test_server.hrl"). + +%% Test server specific exports +-export([all/1]). +-export([init_per_suite/1, end_per_suite/1]). +-export([init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([message/1]). +-export([config/1, port/1]). + +%% Default timetrap timeout (set in init_per_testcase) +-define(default_timeout, ?t:minutes(1)). + +-define(TAG, test_tag). +-define(MFA, {?MODULE, test_mfa, [?TAG]}). + +-export([test_mfa/2]). + +init_per_suite(Config) when is_list(Config) -> + spawn(fun() -> message_receptor() end), + ?line application:load(os_mon), + ?line ok = application:set_env(os_mon, start_os_sup, true), + ?line ok = application:set_env(os_mon, os_sup_mfa, ?MFA), + ?line ok = application:set_env(os_mon, os_sup_enable, false), + ?line ok = application:start(os_mon), + Config. + +end_per_suite(Config) when is_list(Config) -> + ?line application:stop(os_mon), + ?line ok = application:set_env(os_mon, start_os_sup, false), + MFA = {os_sup, error_report, [std_error]}, + ?line ok = application:set_env(os_mon, os_sup_mfa, MFA), + ?line ok = application:set_env(os_mon, os_sup_enable, true), + ?line exit(whereis(message_receptor), done), + Config. + +init_per_testcase(_Case, Config) -> + Dog = ?t:timetrap(?default_timeout), + [{watchdog,Dog} | Config]. + +end_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +all(suite) -> + case ?t:os_type() of + {unix, sunos} -> + [message, config, port]; + {win32, _OSname} -> + [message]; + OS -> + Str = io_lib:format("os_sup not available for ~p", [OS]), + {skip, lists:flatten(Str)} + end. + +message(suite) -> + []; +message(doc) -> + ["Test OS message handling"]; +message(Config) when is_list(Config) -> + + %% Fake an OS message + Data = "10H11386278426HSystem4HTest5HError5HTesto", + ?line os_sup_server ! {faked_port, {data, Data}}, + + %% Check with message_receptor that it has been received + ?t:sleep(?t:seconds(1)), + Msg = + case ?t:os_type() of + {unix, sunos} -> + {?TAG, Data}; + {win32, _} -> + {?TAG,{{1138,627842,0},"System","Test","Error","Testo"}} + end, + ?line message_receptor ! {check, self(), Msg}, + receive + {result, true} -> + ok; + {result, Rec} -> + ?t:fail({no_message, Rec}) + end, + + ok. + +config(suite) -> + []; +config(doc) -> + ["Test configuration"]; +config(Config) when is_list(Config) -> + + %% os_sup_enable==true and os_sup_own/os_sup_syslogconf cannot + %% be tested as test_server is not running is root + + %% os_sup_mfa is already tested, sort of (in init_per_suite) + + %% os_sup_errortag should be tested, however + + ok. + +port(suite) -> + []; +port(doc) -> + ["Test that os_sup handles a terminating port program"]; +port(Config) when is_list(Config) -> + ?line Str = os:cmd("ps -e | grep '[f]errule'"), + case io_lib:fread("~s", Str) of + {ok, [Pid], _Rest} -> + + %% Monitor os_sup_server + ?line MonRef = erlang:monitor(process, os_sup_server), + + %% Kill the port program + case os:cmd("kill -9 " ++ Pid) of + [] -> + + %% os_sup_server should now terminate + receive + {'DOWN', MonRef, _, _, {port_died, _Reason}} -> + ok; + {'DOWN', MonRef, _, _, Reason} -> + ?line ?t:fail({unexpected_exit_reason, Reason}) + after + 3000 -> + ?line ?t:fail(still_alive) + end, + + %% Give os_mon_sup time to restart os_sup + ?t:sleep(?t:seconds(3)), + ?line true = is_pid(whereis(os_sup_server)), + + ok; + + Line -> + erlang:demonitor(MonRef), + {skip, {not_killed, Line}} + end; + _ -> + {skip, {os_pid_not_found}} + end. + +%%---------------------------------------------------------------------- +%% Auxiliary +%%---------------------------------------------------------------------- + +test_mfa(Message, Tag) -> + message_receptor ! {Tag, Message}. + +message_receptor() -> + register(message_receptor, self()), + message_receptor([]). + +message_receptor(Received) -> + receive + %% Check if a certain message has been received + {check, From, Msg} -> + case lists:member(Msg, Received) of + true -> + From ! {result, true}, + message_receptor(lists:delete(Msg, Received)); + false -> + From ! {result, Received}, + message_receptor(Received) + end; + + %% Save all other messages + Msg -> + message_receptor([Msg|Received]) + end. diff --git a/lib/parsetools/include/yeccpre.hrl b/lib/parsetools/include/yeccpre.hrl index 33a103d95f..39dea0552d 100644 --- a/lib/parsetools/include/yeccpre.hrl +++ b/lib/parsetools/include/yeccpre.hrl @@ -26,8 +26,8 @@ parse(Tokens) -> yeccpars0(Tokens, {no_func, no_line}, 0, [], []). --spec parse_and_scan({function() | {atom(), atom()}, [_]} | {atom(), atom(), [_]}) -> - yecc_ret(). +-spec parse_and_scan({function() | {atom(), atom()}, [_]} + | {atom(), atom(), [_]}) -> yecc_ret(). parse_and_scan({F, A}) -> % Fun or {M, F} yeccpars0([], {{F, A}, no_line}, 0, [], []); parse_and_scan({M, F, A}) -> @@ -44,7 +44,7 @@ format_error(Message) -> %% To be used in grammar files to throw an error message to the parser %% toplevel. Doesn't have to be exported! --compile({nowarn_unused_function,{return_error,2}}). +-compile({nowarn_unused_function, return_error/2}). -spec return_error(integer(), any()) -> no_return(). return_error(Line, Message) -> throw({error, {Line, ?MODULE, Message}}). @@ -57,10 +57,7 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) -> error: Error -> Stacktrace = erlang:get_stacktrace(), try yecc_error_type(Error, Stacktrace) of - {syntax_error, Token} -> - yeccerror(Token); - {missing_in_goto_table=Tag, Symbol, State} -> - Desc = {Symbol, State, Tag}, + Desc -> erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc}, Stacktrace) catch _:_ -> erlang:raise(error, Error, Stacktrace) @@ -70,13 +67,15 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) -> Error end. -yecc_error_type(function_clause, [{?MODULE,F,[State,_,_,_,Token,_,_]} | _]) -> +yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) -> case atom_to_list(F) of - "yeccpars2" ++ _ -> - {syntax_error, Token}; "yeccgoto_" ++ SymbolL -> {ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL), - {missing_in_goto_table, Symbol, State} + State = case ArityOrArgs of + [S,_,_,_,_,_,_] -> S; + _ -> state_is_unknown + end, + {Symbol, State, missing_in_goto_table} end. yeccpars1([Token | Tokens], Tzr, State, States, Vstack) -> @@ -141,11 +140,13 @@ yecctoken_end_location(Token) -> yecctoken_location(Token) end. +-compile({nowarn_unused_function, yeccerror/1}). yeccerror(Token) -> Text = yecctoken_to_string(Token), Location = yecctoken_location(Token), {error, {Location, ?MODULE, ["syntax error before: ", Text]}}. +-compile({nowarn_unused_function, yecctoken_to_string/1}). yecctoken_to_string(Token) -> case catch erl_scan:token_info(Token, text) of {text, Txt} -> Txt; @@ -158,6 +159,7 @@ yecctoken_location(Token) -> _ -> element(2, Token) end. +-compile({nowarn_unused_function, yecctoken2string/1}). yecctoken2string({atom, _, A}) -> io_lib:write(A); yecctoken2string({integer,_,N}) -> io_lib:write(N); yecctoken2string({float,_,F}) -> io_lib:write(F); diff --git a/lib/parsetools/src/yecc.erl b/lib/parsetools/src/yecc.erl index c4a47d008f..4119e2631b 100644 --- a/lib/parsetools/src/yecc.erl +++ b/lib/parsetools/src/yecc.erl @@ -1875,8 +1875,12 @@ format_conflict({Symbol, N, Reduce, Confl}) -> %% - "__Stack" has been substituted for "Stack"; %% - several states can share yeccpars2_S_cont(), which reduces code size; %% - instead if calling lists:nthtail() matching code is emitted. +%% +%% "1.4", parsetools-2.0.4: +%% - yeccerror() is called when a syntax error is found (as in version 1.1). +%% - the include file yeccpre.hrl has been changed. --define(CODE_VERSION, "1.3"). +-define(CODE_VERSION, "1.4"). -define(YECC_BUG(M, A), iolist_to_binary([" erlang:error({yecc_bug,\"",?CODE_VERSION,"\",", io_lib:fwrite(M, A), "}).\n\n"])). @@ -2106,13 +2110,11 @@ output_call_to_includefile(NewState, St) -> fwrite(St, <<" yeccpars1(S, ~w, Ss, Stack, T, Ts, Tzr)">>, [NewState]). -output_state_actions_fini(State, #yecc{includefile_version = {1,1}}=St0) -> - %% Backward compatibility. +output_state_actions_fini(State, St0) -> + %% Backward compatible. St10 = delim(St0, false), St = fwrite(St10, <<"yeccpars2_~w(_, _, _, _, T, _, _) ->\n">>, [State]), - fwrite(St, <<" yeccerror(T).\n\n">>, []); -output_state_actions_fini(_State, St) -> - fwrite(St, <<".\n\n">>, []). + fwrite(St, <<" yeccerror(T).\n\n">>, []). output_reduce(St0, State, Terminal0, #reduce{rule_nmbr = RuleNmbr, @@ -2416,7 +2418,7 @@ include1(Line, Inport, Outport, Nmbr_of_lines) -> include1(io:get_line(Inport, ''), Inport, Outport, Nmbr_of_lines + Incr). includefile_version([]) -> - {1,2}; + {1,4}; includefile_version(Includefile) -> case epp:open(Includefile, []) of {ok, Epp} -> @@ -2432,7 +2434,7 @@ includefile_version(Includefile) -> parse_file(Epp) -> case epp:parse_erl_form(Epp) of {ok, {function,_Line,yeccpars1,7,_Clauses}} -> - {1,2}; + {1,4}; {eof,_Line} -> {1,1}; _Form -> diff --git a/lib/parsetools/src/yeccparser.erl b/lib/parsetools/src/yeccparser.erl index 415547b4ce..63127802ee 100644 --- a/lib/parsetools/src/yeccparser.erl +++ b/lib/parsetools/src/yeccparser.erl @@ -38,16 +38,16 @@ line_of(Token) -> -type yecc_ret() :: {'error', _} | {'ok', _}. --spec parse(_) -> yecc_ret(). +-spec parse(Tokens :: list()) -> yecc_ret(). parse(Tokens) -> - yeccpars0(Tokens, false). + yeccpars0(Tokens, {no_func, no_line}, 0, [], []). --spec parse_and_scan({function() | {atom(), atom()}, [_]} | {atom(), atom(), [_]}) -> - yecc_ret(). +-spec parse_and_scan({function() | {atom(), atom()}, [_]} + | {atom(), atom(), [_]}) -> yecc_ret(). parse_and_scan({F, A}) -> % Fun or {M, F} - yeccpars0([], {F, A}); + yeccpars0([], {{F, A}, no_line}, 0, [], []); parse_and_scan({M, F, A}) -> - yeccpars0([], {{M, F}, A}). + yeccpars0([], {{{M, F}, A}, no_line}, 0, [], []). -spec format_error(any()) -> [char() | list()]. format_error(Message) -> @@ -60,54 +60,58 @@ format_error(Message) -> %% To be used in grammar files to throw an error message to the parser %% toplevel. Doesn't have to be exported! --compile({nowarn_unused_function,{return_error,2}}). +-compile({nowarn_unused_function, return_error/2}). -spec return_error(integer(), any()) -> no_return(). return_error(Line, Message) -> throw({error, {Line, ?MODULE, Message}}). --define(CODE_VERSION, "1.3"). +-define(CODE_VERSION, "1.4"). -yeccpars0(Tokens, MFA) -> - try yeccpars1(Tokens, MFA, 0, [], []) +yeccpars0(Tokens, Tzr, State, States, Vstack) -> + try yeccpars1(Tokens, Tzr, State, States, Vstack) catch error: Error -> Stacktrace = erlang:get_stacktrace(), try yecc_error_type(Error, Stacktrace) of - {syntax_error, Token} -> - yeccerror(Token); - {missing_in_goto_table=Tag, Symbol, State} -> - Desc = {Symbol, State, Tag}, + Desc -> erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc}, - Stacktrace) + Stacktrace) catch _:_ -> erlang:raise(error, Error, Stacktrace) end; - throw: {error, {_Line, ?MODULE, _M}} = Error -> - Error % probably from return_error/2 + %% Probably thrown from return_error/2: + throw: {error, {_Line, ?MODULE, _M}} = Error -> + Error end. -yecc_error_type(function_clause, [{?MODULE,F,[State,_,_,_,Token,_,_]} | _]) -> +yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) -> case atom_to_list(F) of - "yeccpars2" ++ _ -> - {syntax_error, Token}; "yeccgoto_" ++ SymbolL -> {ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL), - {missing_in_goto_table, Symbol, State} + State = case ArityOrArgs of + [S,_,_,_,_,_,_] -> S; + _ -> state_is_unknown + end, + {Symbol, State, missing_in_goto_table} end. -yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) -> - yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, - Tokenizer); -yeccpars1([], {F, A}, State, States, Vstack) -> +yeccpars1([Token | Tokens], Tzr, State, States, Vstack) -> + yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, Tzr); +yeccpars1([], {{F, A},_Line}, State, States, Vstack) -> case apply(F, A) of - {ok, Tokens, _Endline} -> - yeccpars1(Tokens, {F, A}, State, States, Vstack); - {eof, _Endline} -> - yeccpars1([], false, State, States, Vstack); + {ok, Tokens, Endline} -> + yeccpars1(Tokens, {{F, A}, Endline}, State, States, Vstack); + {eof, Endline} -> + yeccpars1([], {no_func, Endline}, State, States, Vstack); {error, Descriptor, _Endline} -> {error, Descriptor} end; -yeccpars1([], false, State, States, Vstack) -> - yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false). +yeccpars1([], {no_func, no_line}, State, States, Vstack) -> + Line = 999999, + yeccpars2(State, '$end', States, Vstack, yecc_end(Line), [], + {no_func, Line}); +yeccpars1([], {no_func, Endline}, State, States, Vstack) -> + yeccpars2(State, '$end', States, Vstack, yecc_end(Endline), [], + {no_func, Endline}). %% yeccpars1/7 is called from generated code. %% @@ -115,48 +119,73 @@ yeccpars1([], false, State, States, Vstack) -> %% yeccpars1/7 can be found by parsing the file without following %% include directives. yecc will otherwise assume that an old %% yeccpre.hrl is included (one which defines yeccpars1/5). -yeccpars1(State1, State, States, Vstack, Stack1, [Token | Tokens], - Tokenizer) -> +yeccpars1(State1, State, States, Vstack, Token0, [Token | Tokens], Tzr) -> yeccpars2(State, element(1, Token), [State1 | States], - [Stack1 | Vstack], Token, Tokens, Tokenizer); -yeccpars1(State1, State, States, Vstack, Stack1, [], {F, A}) -> - case apply(F, A) of - {ok, Tokens, _Endline} -> - yeccpars1(State1, State, States, Vstack, Stack1, Tokens, {F, A}); - {eof, _Endline} -> - yeccpars1(State1, State, States, Vstack, Stack1, [], false); - {error, Descriptor, _Endline} -> - {error, Descriptor} - end; -yeccpars1(State1, State, States, Vstack, Stack1, [], false) -> - yeccpars2(State, '$end', [State1 | States], [Stack1 | Vstack], - {'$end', 999999}, [], false). + [Token0 | Vstack], Token, Tokens, Tzr); +yeccpars1(State1, State, States, Vstack, Token0, [], {{_F,_A}, _Line}=Tzr) -> + yeccpars1([], Tzr, State, [State1 | States], [Token0 | Vstack]); +yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, no_line}) -> + Line = yecctoken_end_location(Token0), + yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack], + yecc_end(Line), [], {no_func, Line}); +yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, Line}) -> + yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack], + yecc_end(Line), [], {no_func, Line}). + +%% For internal use only. +yecc_end({Line,_Column}) -> + {'$end', Line}; +yecc_end(Line) -> + {'$end', Line}. + +yecctoken_end_location(Token) -> + try + {text, Str} = erl_scan:token_info(Token, text), + {line, Line} = erl_scan:token_info(Token, line), + Parts = re:split(Str, "\n"), + Dline = length(Parts) - 1, + Yline = Line + Dline, + case erl_scan:token_info(Token, column) of + {column, Column} -> + Col = byte_size(lists:last(Parts)), + {Yline, Col + if Dline =:= 0 -> Column; true -> 1 end}; + undefined -> + Yline + end + catch _:_ -> + yecctoken_location(Token) + end. -% For internal use only. yeccerror(Token) -> - Text = case catch erl_scan:token_info(Token, text) of - {text, Txt} -> Txt; - _ -> yecctoken2string(Token) - end, - Location = case catch erl_scan:token_info(Token, location) of - {location, Loc} -> Loc; - _ -> element(2, Token) - end, + Text = yecctoken_to_string(Token), + Location = yecctoken_location(Token), {error, {Location, ?MODULE, ["syntax error before: ", Text]}}. +yecctoken_to_string(Token) -> + case catch erl_scan:token_info(Token, text) of + {text, Txt} -> Txt; + _ -> yecctoken2string(Token) + end. + +yecctoken_location(Token) -> + case catch erl_scan:token_info(Token, location) of + {location, Loc} -> Loc; + _ -> element(2, Token) + end. + yecctoken2string({atom, _, A}) -> io_lib:write(A); yecctoken2string({integer,_,N}) -> io_lib:write(N); yecctoken2string({float,_,F}) -> io_lib:write(F); yecctoken2string({char,_,C}) -> io_lib:write_char(C); yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]); yecctoken2string({string,_,S}) -> io_lib:write_unicode_string(S); -yecctoken2string({reserved_symbol, _, A}) -> io_lib:format("~w", [A]); -yecctoken2string({_Cat, _, Val}) -> io_lib:format("~w", [Val]); +yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A); +yecctoken2string({_Cat, _, Val}) -> io_lib:write(Val); yecctoken2string({dot, _}) -> "'.'"; yecctoken2string({'$end', _}) -> []; yecctoken2string({Other, _}) when is_atom(Other) -> - io_lib:format("~w", [Other]); + io_lib:write(Other); yecctoken2string(Other) -> io_lib:write(Other). @@ -164,7 +193,7 @@ yecctoken2string(Other) -> --file("yeccparser.erl", 168). +-file("yeccparser.erl", 196). yeccpars2(0=S, Cat, Ss, Stack, T, Ts, Tzr) -> yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr); @@ -248,7 +277,9 @@ yeccpars2_0(S, integer, Ss, Stack, T, Ts, Tzr) -> yeccpars2_0(S, reserved_word, Ss, Stack, T, Ts, Tzr) -> yeccpars1(S, 8, Ss, Stack, T, Ts, Tzr); yeccpars2_0(S, var, Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 9, Ss, Stack, T, Ts, Tzr). + yeccpars1(S, 9, Ss, Stack, T, Ts, Tzr); +yeccpars2_0(_, _, _, _, T, _, _) -> + yeccerror(T). yeccpars2_1(S, atom, Ss, Stack, T, Ts, Tzr) -> yeccpars1(S, 6, Ss, Stack, T, Ts, Tzr); @@ -267,10 +298,14 @@ yeccpars2_2(_S, Cat, Ss, Stack, T, Ts, Tzr) -> yeccgoto_grammar(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr). yeccpars2_3(S, '->', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr). + yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr); +yeccpars2_3(_, _, _, _, T, _, _) -> + yeccerror(T). -yeccpars2_4(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) -> - {ok, hd(Stack)}. +yeccpars2_4(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) -> + {ok, hd(Stack)}; +yeccpars2_4(_, _, _, _, T, _, _) -> + yeccerror(T). yeccpars2_5(_S, Cat, Ss, Stack, T, Ts, Tzr) -> yeccgoto_grammar(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr). @@ -317,7 +352,9 @@ yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr) -> yeccgoto_symbols(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). yeccpars2_14(S, dot, Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 29, Ss, Stack, T, Ts, Tzr). + yeccpars1(S, 29, Ss, Stack, T, Ts, Tzr); +yeccpars2_14(_, _, _, _, T, _, _) -> + yeccerror(T). yeccpars2_15(S, '->', Ss, Stack, T, Ts, Tzr) -> yeccpars1(S, 18, Ss, Stack, T, Ts, Tzr); @@ -338,7 +375,9 @@ yeccpars2_15(S, reserved_word, Ss, Stack, T, Ts, Tzr) -> yeccpars2_15(S, string, Ss, Stack, T, Ts, Tzr) -> yeccpars1(S, 26, Ss, Stack, T, Ts, Tzr); yeccpars2_15(S, var, Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 27, Ss, Stack, T, Ts, Tzr). + yeccpars1(S, 27, Ss, Stack, T, Ts, Tzr); +yeccpars2_15(_, _, _, _, T, _, _) -> + yeccerror(T). yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr) -> [_|Nss] = Ss, @@ -414,10 +453,14 @@ yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr) -> yeccgoto_rule(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). yeccpars2_30(S, dot, Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr). + yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr); +yeccpars2_30(_, _, _, _, T, _, _) -> + yeccerror(T). yeccpars2_31(S, dot, Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr). + yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr); +yeccpars2_31(_, _, _, _, T, _, _) -> + yeccerror(T). yeccpars2_32(S, string, Ss, Stack, T, Ts, Tzr) -> yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr); @@ -486,7 +529,7 @@ yeccgoto_tokens(15=_S, Cat, Ss, Stack, T, Ts, Tzr) -> yeccgoto_tokens(17=_S, Cat, Ss, Stack, T, Ts, Tzr) -> yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr). --compile({inline,{yeccpars2_6_,1}}). +-compile({inline,yeccpars2_6_/1}). -file("yeccgramm.yrl", 44). yeccpars2_6_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -494,7 +537,7 @@ yeccpars2_6_(__Stack0) -> symbol ( __1 ) end | __Stack]. --compile({inline,{yeccpars2_7_,1}}). +-compile({inline,yeccpars2_7_/1}). -file("yeccgramm.yrl", 45). yeccpars2_7_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -502,7 +545,7 @@ yeccpars2_7_(__Stack0) -> symbol ( __1 ) end | __Stack]. --compile({inline,{yeccpars2_8_,1}}). +-compile({inline,yeccpars2_8_/1}). -file("yeccgramm.yrl", 46). yeccpars2_8_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -510,7 +553,7 @@ yeccpars2_8_(__Stack0) -> symbol ( __1 ) end | __Stack]. --compile({inline,{yeccpars2_9_,1}}). +-compile({inline,yeccpars2_9_/1}). -file("yeccgramm.yrl", 43). yeccpars2_9_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -518,14 +561,14 @@ yeccpars2_9_(__Stack0) -> symbol ( __1 ) end | __Stack]. --compile({inline,{yeccpars2_11_,1}}). +-compile({inline,yeccpars2_11_/1}). -file("yeccgramm.yrl", 40). yeccpars2_11_(__Stack0) -> [begin { erlang_code , [ { atom , 0 , '$undefined' } ] } end | __Stack0]. --compile({inline,{yeccpars2_12_,1}}). +-compile({inline,yeccpars2_12_/1}). -file("yeccgramm.yrl", 35). yeccpars2_12_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -533,7 +576,7 @@ yeccpars2_12_(__Stack0) -> [ __1 ] end | __Stack]. --compile({inline,{yeccpars2_13_,1}}). +-compile({inline,yeccpars2_13_/1}). -file("yeccgramm.yrl", 36). yeccpars2_13_(__Stack0) -> [__2,__1 | __Stack] = __Stack0, @@ -541,7 +584,7 @@ yeccpars2_13_(__Stack0) -> [ __1 | __2 ] end | __Stack]. --compile({inline,{yeccpars2_16_,1}}). +-compile({inline,yeccpars2_16_/1}). -file("yeccgramm.yrl", 39). yeccpars2_16_(__Stack0) -> [__2,__1 | __Stack] = __Stack0, @@ -549,7 +592,7 @@ yeccpars2_16_(__Stack0) -> { erlang_code , __2 } end | __Stack]. --compile({inline,{yeccpars2_17_,1}}). +-compile({inline,yeccpars2_17_/1}). -file("yeccgramm.yrl", 41). yeccpars2_17_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -557,7 +600,7 @@ yeccpars2_17_(__Stack0) -> [ __1 ] end | __Stack]. --compile({inline,{yeccpars2_18_,1}}). +-compile({inline,yeccpars2_18_/1}). -file("yeccgramm.yrl", 55). yeccpars2_18_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -565,7 +608,7 @@ yeccpars2_18_(__Stack0) -> { '->' , line_of ( __1 ) } end | __Stack]. --compile({inline,{yeccpars2_19_,1}}). +-compile({inline,yeccpars2_19_/1}). -file("yeccgramm.yrl", 56). yeccpars2_19_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -573,7 +616,7 @@ yeccpars2_19_(__Stack0) -> { ':' , line_of ( __1 ) } end | __Stack]. --compile({inline,{yeccpars2_24_,1}}). +-compile({inline,yeccpars2_24_/1}). -file("yeccgramm.yrl", 53). yeccpars2_24_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -581,7 +624,7 @@ yeccpars2_24_(__Stack0) -> { value_of ( __1 ) , line_of ( __1 ) } end | __Stack]. --compile({inline,{yeccpars2_25_,1}}). +-compile({inline,yeccpars2_25_/1}). -file("yeccgramm.yrl", 54). yeccpars2_25_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -589,7 +632,7 @@ yeccpars2_25_(__Stack0) -> { value_of ( __1 ) , line_of ( __1 ) } end | __Stack]. --compile({inline,{yeccpars2_28_,1}}). +-compile({inline,yeccpars2_28_/1}). -file("yeccgramm.yrl", 42). yeccpars2_28_(__Stack0) -> [__2,__1 | __Stack] = __Stack0, @@ -597,7 +640,7 @@ yeccpars2_28_(__Stack0) -> [ __1 | __2 ] end | __Stack]. --compile({inline,{yeccpars2_29_,1}}). +-compile({inline,yeccpars2_29_/1}). -file("yeccgramm.yrl", 33). yeccpars2_29_(__Stack0) -> [__5,__4,__3,__2,__1 | __Stack] = __Stack0, @@ -605,7 +648,7 @@ yeccpars2_29_(__Stack0) -> { rule , [ __1 | __3 ] , __4 } end | __Stack]. --compile({inline,{yeccpars2_32_,1}}). +-compile({inline,yeccpars2_32_/1}). -file("yeccgramm.yrl", 37). yeccpars2_32_(__Stack0) -> [__1 | __Stack] = __Stack0, @@ -613,7 +656,7 @@ yeccpars2_32_(__Stack0) -> [ __1 ] end | __Stack]. --compile({inline,{yeccpars2_33_,1}}). +-compile({inline,yeccpars2_33_/1}). -file("yeccgramm.yrl", 38). yeccpars2_33_(__Stack0) -> [__2,__1 | __Stack] = __Stack0, @@ -621,7 +664,7 @@ yeccpars2_33_(__Stack0) -> [ __1 | __2 ] end | __Stack]. --compile({inline,{yeccpars2_34_,1}}). +-compile({inline,yeccpars2_34_/1}). -file("yeccgramm.yrl", 32). yeccpars2_34_(__Stack0) -> [__3,__2,__1 | __Stack] = __Stack0, @@ -629,7 +672,7 @@ yeccpars2_34_(__Stack0) -> { __1 , __2 } end | __Stack]. --compile({inline,{yeccpars2_35_,1}}). +-compile({inline,yeccpars2_35_/1}). -file("yeccgramm.yrl", 31). yeccpars2_35_(__Stack0) -> [__3,__2,__1 | __Stack] = __Stack0, diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl index 61e2456323..93949a074a 100644 --- a/lib/parsetools/test/yecc_SUITE.erl +++ b/lib/parsetools/test/yecc_SUITE.erl @@ -298,8 +298,8 @@ syntax(Config) when is_list(Config) -> {_,[{L1,_,{undefined_function,{yeccpars2_2_,1}}}, {L2,_,{bad_inline,{yeccpars2_2_,1}}}]}], []} = compile:file(Parserfile1, [basic_validation,return]), - ?line L1 = 24 + SzYeccPre, - ?line L2 = 31 + SzYeccPre + ?line L1 = 28 + SzYeccPre, + ?line L2 = 35 + SzYeccPre end(), %% Bad macro in action. OTP-7224. @@ -316,8 +316,8 @@ syntax(Config) when is_list(Config) -> {_,[{L1,_,{undefined_function,{yeccpars2_2_,1}}}, {L2,_,{bad_inline,{yeccpars2_2_,1}}}]}], []} = compile:file(Parserfile1, [basic_validation,return]), - ?line L1 = 24 + SzYeccPre, - ?line L2 = 31 + SzYeccPre + ?line L1 = 28 + SzYeccPre, + ?line L2 = 35 + SzYeccPre end(), %% Check line numbers. OTP-7224. @@ -1584,8 +1584,8 @@ otp_7292(Config) when is_list(Config) -> {L2,_,{bad_inline,{yeccpars2_2_,1}}}]}], [{_,[{16,_,{unused_function,{foo,0}}}]}]} = compile:file(Parserfile1, [basic_validation, return]), - ?line L1 = 34 + SzYeccPre, - ?line L2 = 41 + SzYeccPre + ?line L1 = 38 + SzYeccPre, + ?line L2 = 45 + SzYeccPre end(), YeccPre = filename:join(Dir, "yeccpre.hrl"), @@ -1602,8 +1602,8 @@ otp_7292(Config) when is_list(Config) -> {L2,_,{bad_inline,{yeccpars2_2_,1}}}]}], [{_,[{16,_,{unused_function,{foo,0}}}]}]} = compile:file(Parserfile1, [basic_validation, return]), - ?line L1 = 33 + SzYeccPre, - ?line L2 = 40 + SzYeccPre + ?line L1 = 37 + SzYeccPre, + ?line L2 = 44 + SzYeccPre end(), file:delete(YeccPre), diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk index f3e2dc0fb4..46915baed6 100644 --- a/lib/parsetools/vsn.mk +++ b/lib/parsetools/vsn.mk @@ -1 +1 @@ -PARSETOOLS_VSN = 2.0.3 +PARSETOOLS_VSN = 2.0.4 diff --git a/lib/public_key/doc/src/cert_records.xml b/lib/public_key/doc/src/cert_records.xml index 8cfe57f670..0d6113acef 100644 --- a/lib/public_key/doc/src/cert_records.xml +++ b/lib/public_key/doc/src/cert_records.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> @@ -37,7 +37,7 @@ <p>This chapter briefly describes erlang records derived from asn1 specifications used to handle X509 certificates. The intent is to describe the data types and not to specify the meaning of each - component for this we refer you to RFC 3280. + component for this we refer you to RFC 5280. </p> <p>Use the following include directive to get access to the @@ -45,11 +45,7 @@ <code> -include_lib("public_key/include/public_key.hrl"). </code> - <p>The used specification is available in <c>OTP-PKIX.asn1</c>, - which is an amelioration of - the <c>PKIX1Explicit88.asn1</c>, <c>PKIX1Implicit88.asn1</c> - and <c>PKIX1Algorithms88.asn1</c> modules. - You find all these modules in the <c>asn1</c> subdirectory + <p>The used asn1 specifications are available <c>asn1</c> subdirectory of the application <c>public_key</c>. </p> @@ -62,6 +58,9 @@ marker="public_key">public key reference manual </seealso> or follows here.</p> + <p><c>oid() - a tuple of integers + as generated by the asn1 compiler.</c></p> + <p><c>time() = uct_time() | general_time()</c></p> <p><c>uct_time() = {utcTime, "YYMMDDHHMMSSZ"} </c></p> @@ -119,9 +118,31 @@ algorithm, % oid() parameters % asn1_der_encoded() }. +</code> + +<code> +#'OTPCertificate'{ + tbsCertificate, % #'OTPTBSCertificate'{} + signatureAlgorithm, % #'SignatureAlgorithm' + signature % {0, binary()} - asn1 compact bitstring + }. + +#'OTPTBSCertificate'{ + version, % v1 | v2 | v3 + serialNumber, % integer() + signature, % #'SignatureAlgorithm' + issuer, % {rdnSequence, [#AttributeTypeAndValue'{}]} + validity, % #'Validity'{} + subject, % {rdnSequence, [#AttributeTypeAndValue'{}]} + subjectPublicKeyInfo, % #'SubjectPublicKeyInfo'{} + issuerUniqueID, % binary() | asn1_novalue + subjectUniqueID, % binary() | asn1_novalue + extensions % [#'Extension'{}] + }. + #'SignatureAlgorithm'{ algorithm, % id_signature_algorithm() - parameters % public_key_params() + parameters % asn1_novalue | #'Dss-Parms'{} }. </code> diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index dc9a96906f..c72719fac4 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> @@ -34,11 +34,7 @@ <modulesummary> API module for public key infrastructure.</modulesummary> <description> <p>This module provides functions to handle public key infrastructure - from RFC 3280 - X.509 certificates (will later be upgraded to RFC 5280) - and some parts of the PKCS-standard. - Currently this application is mainly used by the new - ssl implementation. The API is yet under construction - and only a few of the functions are currently documented and thereby supported. + from RFC 5280 - X.509 certificates and some parts of the PKCS-standard. </p> </description> @@ -62,37 +58,37 @@ <p><c>boolean() = true | false</c></p> - <p><c>string = [bytes()]</c></p> - - <p><c>asn1_der_encoded() = binary() | [bytes()]</c></p> + <p><c>string = [bytes()]</c></p> + + <p><c>der_encoded() = binary() </c></p> - <p><c>der_bin() = binary() </c></p> + <p><c>decrypt_der() = binary() </c></p> - <p><c>oid() - a tuple of integers - as generated by the asn1 compiler.</c></p> - - <p><c>public_key() = rsa_public_key() | dsa_public_key()</c></p> + <p><c>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| + 'DSAPrivateKey' | 'DHParameter'</c></p> + <p><c>pem_entry () = {pki_asn1_type(), der_encoded() | decrypt_der(), not_encrypted | + {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}}.</c></p> + <p><c>rsa_public_key() = #'RSAPublicKey'{}</c></p> <p><c>rsa_private_key() = #'RSAPrivateKey'{} </c></p> - <p><c>dsa_public_key() = integer() </c></p> - - <p><c>public_key_params() = dsa_key_params() </c></p> - - <p><c>dsa_key_params() = #'Dss-Parms'{} </c></p> - - <p><c>private_key() = rsa_private_key() | dsa_private_key()</c></p> + <p><c>dsa_public_key() = {integer(), #'Dss-Parms'{}} </c></p> <p><c>rsa_private_key() = #'RSAPrivateKey'{} </c></p> <p><c>dsa_private_key() = #'DSAPrivateKey'{}</c></p> + + <p><c> public_crypt_options() = [{rsa_pad, rsa_padding()}]. </c></p> - <p><c>x509_certificate() = "#Certificate{}"</c></p> - - <p><c>x509_tbs_certificate() = #'TBSCertificate'{} </c></p> - + <p><c> rsa_padding() = 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' + | 'rsa_no_padding'</c></p> + + <p><c> rsa_digest_type() = 'md5' | 'sha' </c></p> + + <p><c> dss_digest_type() = 'none' | 'sha' </c></p> + <!-- <p><c>policy_tree() = [Root, Children]</c></p> --> <!-- <p><c>Root = #policy_tree_node{}</c></p> --> @@ -121,197 +117,301 @@ <!-- that would satisfy this policy in the certificate x+1. </item> --> <!-- </taglist> --> </section> - -<funcs> - <func> - <name>decode_private_key(KeyInfo) -> </name> - <name>decode_private_key(KeyInfo, Password) -> {ok, PrivateKey} | {error, Reason}</name> - <fsummary> Decodes an asn1 der encoded private key.</fsummary> - <type> - <v> KeyInfo = {KeyType, der_bin(), ChipherInfo} </v> - <d> As returned from pem_to_der/1 for private keys</d> - <v> KeyType = rsa_private_key | dsa_private_key </v> - <v> ChipherInfo = opaque() | no_encryption </v> - <d> ChipherInfo may contain encryption parameters if the private key is password - protected, these are opaque to the user just pass the value returned by pem_to_der/1 - to this function.</d> - <v> Password = string() </v> - <d>Must be specified if CipherInfo =/= no_encryption</d> - <v> PrivateKey = private_key() </v> - <v> Reason = term() </v> - </type> - <desc> - <p>Decodes an asn1 der encoded private key.</p> - </desc> - </func> - + +<funcs> + <func> - <name>pem_to_der(File) -> {ok, [Entry]}</name> - <fsummary>Reads a PEM file and translates it into its asn1 der - encoded parts.</fsummary> + <name>decrypt_private(CipherText, Key [, Options]) -> binary()</name> + <fsummary>Public key decryption.</fsummary> <type> - <v>File = path()</v> - <v>Password = string()</v> - <v>Entry = {entry_type(), der_bin(), CipherInfo}</v> - <v> ChipherInfo = opaque() | no_encryption </v> - <d> ChipherInfo may contain encryption parameters if the private key is password - protected, these will be handled by the function decode_private_key/2. </d> - <v>entry_type() = cert | cert_req | rsa_private_key | dsa_private_key | - dh_params </v> + <v>CipherText = binary()</v> + <v>Key = rsa_private_key()</v> + <v>Options = public_crypt_options()</v> </type> <desc> - <p>Reads a PEM file and translates it into its asn1 der - encoded parts.</p> + <p>Public key decryption using the private key.</p> + </desc> + </func> + + <func> + <name>decrypt_public(CipherText, Key [, Options]) - > binary()</name> + <fsummary></fsummary> + <type> + <v>CipherText = binary()</v> + <v>Key = rsa_public_key()</v> + <v>Options = public_crypt_options()</v> + </type> + <desc> + <p> Public key decryption using the public key.</p> </desc> </func> - - <func> - <name>pkix_decode_cert(Cert, Type) -> {ok, DecodedCert} | {error, Reason}</name> - <fsummary> Decodes an asn1 der encoded pkix certificate. </fsummary> - <type> - <v>Cert = asn1_der_encoded() </v> - <v>Type = plain | otp</v> - <v>DecodeCert = x509_certificate() </v> - <d>When type is specified as otp the asn1 spec OTP-PKIX.asn1 is used to decode known - extensions and enhance the signature field in - #'Certificate'{} and '#TBSCertificate'{}. This is currently used by the new ssl - implementation but not documented and supported for the public_key application.</d> - <v>Reason = term() </v> + + <func> + <name>der_decode(Asn1type, Der) -> term()</name> + <fsummary> Decodes a public key asn1 der encoded entity.</fsummary> + <type> + <v>Asn1Type = atom() -</v> + <d> Asn1 type present in the public_key applications + asn1 specifications.</d> + <v>Der = der_encoded()</v> </type> - <desc> - <p> Decodes an asn1 encoded pkix certificate.</p> + <desc> + <p> Decodes a public key asn1 der encoded entity.</p> </desc> </func> + + <func> + <name>der_encode(Asn1Type, Entity) -> der_encoded()</name> + <fsummary> Encodes a public key entity with asn1 DER encoding.</fsummary> + <type> + <v>Asn1Type = atom()</v> + <d> Asn1 type present in the public_key applications + asn1 specifications.</d> + <v>Entity = term() - The erlang representation of <c> Asn1Type</c></v> + </type> + <desc> + <p> Encodes a public key entity with asn1 DER encoding.</p> + </desc> + </func> + + <func> + <name>pem_decode(PemBin) -> [pem_entry()]</name> + <fsummary>Decode PEM binary data and return + entries as asn1 der encoded entities. </fsummary> + <type> + <v>PemBin = binary()</v> + <d>Example {ok, PemBin} = file:read_file("cert.pem").</d> + </type> + <desc> + <p>Decode PEM binary data and return + entries as asn1 der encoded entities.</p> + </desc> + </func> + + <func> + <name>pem_encode(PemEntries) -> binary()</name> + <fsummary>Creates a PEM binary</fsummary> + <type> + <v> PemEntries = [pem_entry()] </v> + </type> + <desc> + <p>Creates a PEM binary</p> + </desc> + </func> + + <func> + <name>pem_entry_decode(PemEntry [, Password]) -> term()</name> + <fsummary>Decodes a pem entry.</fsummary> + <type> + <v> PemEntry = pem_entry() </v> + <v> Password = string() </v> + </type> + <desc> + <p>Decodes a pem entry. pem_decode/1 returns a list of + pem entries.</p> + </desc> + </func> + + <func> + <name>pem_entry_encode(Asn1Type, Entity [,{CipherInfo, Password}]) -> pem_entry()</name> + <fsummary> Creates a pem entry that can be feed to pem_encode/1.</fsummary> + <type> + <v>Asn1Type = atom()</v> + <v>Entity = term()</v> + <v>CipherInfo = {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}</v> + <v>Password = string()</v> + </type> + <desc> + <p> Creates a pem entry that can be feed to pem_encode/1.</p> + </desc> + </func> + + <func> + <name>encrypt_private(PlainText, Key) -> binary()</name> + <fsummary> Public key encryption using the private key.</fsummary> + <type> + <v>PlainText = binary()</v> + <v>Key = rsa_private_key()</v> + </type> + <desc> + <p> Public key encryption using the private key.</p> + </desc> + </func> + + <func> + <name>encrypt_public(PlainText, Key) -> binary()</name> + <fsummary> Public key encryption using the public key.</fsummary> + <type> + <v>PlainText = binary()</v> + <v>Key = rsa_public_key()</v> + </type> + <desc> + <p> Public key encryption using the public key.</p> + </desc> + </func> -<!-- <func> --> -<!-- <name> pkix_encode_cert(Cert) -> {ok, EncodedCert} | {error, Reason}</name> --> -<!-- <fsummary>Encodes a certificate record using asn1. </fsummary> --> -<!-- <type> --> -<!-- <v>Cert = x509_certificate() </v> --> -<!-- <v>EncodedCert = asn1_der_encoded() </v> --> -<!-- <v>Reason = term() </v> --> -<!-- </type> --> -<!-- <desc> --> -<!-- <p> Encodes a certificate record using asn1.</p> --> -<!-- </desc> --> -<!-- </func> --> + <func> + <name> pkix_decode_cert(Cert, otp|plain) -> #'Certificate'{} | #'OTPCertificate'{}</name> + <fsummary> Decodes an asn1 der encoded pkix x509 certificate.</fsummary> + <type> + <v>Cert = der_encoded()</v> + </type> + <desc> + <p>Decodes an asn1 der encoded pkix certificate. The otp option + will use the customized asn1 specification OTP-PKIX.asn1 for + decoding and also recursively decode most of the standard + parts.</p> + </desc> + </func> -<!-- <func> --> -<!-- <name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, Result} | {error, Reason}</name> --> - -<!-- <fsummary>Performs a basic path validation according to RFC 3280</fsummary> --> -<!-- <type> --> -<!-- <v>TrustedCert = asn1_der_encoded()</v> --> -<!-- <v>CertChain = [asn1_der_encoded()]</v> --> -<!-- <v>Options = [{Option, Value}]</v> --> -<!-- <v>Result = {{algorithm(), public_key(), --> -<!-- public_key_params()}, policy_tree()}</v> --> -<!-- </type> --> + <func> + <name>pkix_encode(Asn1Type, Entity, otp | plain) -> der_encoded()</name> + <fsummary>Der encodes a pkix x509 certificate or part of such a + certificate.</fsummary> + <type> + <v>Asn1Type = atom()</v> + <d>The asn1 type can be 'Certificate', 'OTPCertificate' or a subtype of either .</d> + </type> + <desc> + <p>Der encodes a pkix x509 certificate or part of such a + certificate. This function must be used for encoding certificates or parts of certificates + that are decoded/created on the otp format, whereas for the plain format this + function will directly call der_encode/2. </p> + </desc> + </func> + + <func> + <name>pkix_is_issuer(Cert, IssuerCert) -> boolean()</name> + <fsummary> Checks if <c>IssuerCert</c> issued <c>Cert</c> </fsummary> + <type> + <v>Cert = der_encode() | #'OTPCertificate'{}</v> + <v>IssuerCert = der_encode() | #'OTPCertificate'{}</v> + </type> + <desc> + <p> Checks if <c>IssuerCert</c> issued <c>Cert</c> </p> + </desc> + </func> + + <func> + <name>pkix_is_fixed_dh_cert(Cert) -> boolean()</name> + <fsummary> Checks if a Certificate is a fixed Diffie-Hellman Cert.</fsummary> + <type> + <v>Cert = der_encode() | #'OTPCertificate'{}</v> + </type> + <desc> + <p> Checks if a Certificate is a fixed Diffie-Hellman Cert.</p> + </desc> + </func> + + <func> + <name>pkix_is_self_signed(Cert) -> boolean()</name> + <fsummary> Checks if a Certificate is self signed.</fsummary> + <type> + <v>Cert = der_encode() | #'OTPCertificate'{}</v> + </type> + <desc> + <p> Checks if a Certificate is self signed.</p> + </desc> + </func> + + <func> + <name>pkix_issuer_id(Cert, IssuedBy) -> {ok, IssuerID} | {error, Reason}</name> + <fsummary> Returns the issuer id.</fsummary> + <type> + <v>Cert = der_encode() | #'OTPCertificate'{}</v> + <v>IssuedBy = self | other</v> + <v>IssuerID = {integer(), {rdnSequence, [#'AttributeTypeAndValue'{}]}}</v> + <d>The issuer id consists of the serial number and the issuers name.</d> + <v>Reason = term()</v> + </type> + <desc> + <p> Returns the issuer id.</p> + </desc> + </func> -<!-- <desc> --> -<!-- <p>Available options are: </p> --> -<!-- <taglist> --> -<!-- <tag>{validate_extension_fun, fun()}</tag> --> -<!-- <item> A fun behaving according to the following outline: --> -<!-- <code> --> -<!-- [...] --> -<!-- ValidateExtensionFun = fun(Extensions, UserState) -> --> -<!-- validate_extensions(Extensions, UserState, []) --> -<!-- end, --> -<!-- [...] --> + <func> + <name>pkix_normalize_name(Issuer) -> Normalized</name> + <fsummary>Normalizes a issuer name so that it can be easily + compared to another issuer name. </fsummary> + <type> + <v>Issuer = {rdnSequence,[#'AttributeTypeAndValue'{}]}</v> + <v>Normalized = {rdnSequence, [#'AttributeTypeAndValue'{}]}</v> + </type> + <desc> + <p>Normalizes a issuer name so that it can be easily + compared to another issuer name.</p> + </desc> + </func> + + <!-- <func> --> + <!-- <name>pkix_path_validation()</name> --> + <!-- <fsummary> Performs a basic path validation according to RFC 5280.</fsummary> --> + <!-- <type> --> + <!-- <v></v> --> + <!-- </type> --> + <!-- <desc> --> + <!-- <p> Performs a basic path validation according to RFC 5280.</p> --> + <!-- </desc> --> + <!-- </func> --> -<!-- validate_extensions([], UserState, UnknowExtension) -> --> -<!-- {UserState, UnknowExtension}; --> -<!-- validate_extensions([#'Extension'{} = Ext | Rest], UserState, UnknowExtension) -> --> -<!-- case valid_extension(Ext) of --> -<!-- {true, NewUserState} -> --> -<!-- validate_extensions(Rest, NewUserState, UnknowExtension); --> -<!-- unknown -> --> -<!-- validate_extensions(Rest, UserState, [Ext | UnknowExtension]); --> -<!-- {false, Reason} -> --> -<!-- throw(bad_cert, Reason) --> -<!-- end. --> -<!-- </code> --> - -<!-- </item> --> - -<!-- <tag>{policy_set, [oid()]}</tag> --> -<!-- <item>A set of certificate policy --> -<!-- identifiers naming the policies that are acceptable to the --> -<!-- certificate user. If the user is not concerned about --> -<!-- certificate policy there is no need --> -<!-- to set this option. Defaults to the --> -<!-- special value [?anyPolicy]. --> -<!-- </item> --> - -<!-- <tag>{policy_mapping, boolean()}</tag> --> -<!-- <item>Indicates if policy --> -<!-- mapping, initially, is allowed in the certification path. --> -<!-- Defaults to false. --> -<!-- </item> --> - -<!-- <tag> {explicit_policy, boolean()}</tag> --> -<!-- <item>Indicates if the path, initially, must be --> -<!-- valid for at least one of the certificate policies in the user --> -<!-- specified policy set. --> -<!-- Defaults to false. --> -<!-- </item> --> + + <func> + <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encode()</name> + <fsummary>Signs certificate.</fsummary> + <type> + <v>Key = rsa_public_key() | dsa_public_key()</v> + </type> + <desc> + <p>Signs a 'OTPTBSCertificate'. Returns the corresponding + der encoded certificate.</p> + </desc> + </func> -<!-- <tag>{inhibit_any_policy, boolean()}</tag> --> -<!-- <item>Indicates whether the anyPolicy OID, initially, should --> -<!-- be processed if it is included in a certificate. --> -<!-- Defaults to false. --> -<!-- </item> --> - -<!-- </taglist> --> - -<!-- <p>Performs a basic path validation according to RFC 3280, --> -<!-- e.i. signature validation, time validation, issuer validation, --> -<!-- alternative subject name validation, CRL validation, policy --> -<!-- validation and checks that no unknown extensions --> -<!-- are marked as critical. The option <c>validate_extension_fun</c> --> -<!-- may be used to validate application specific extensions. If --> -<!-- a validation criteria is found to be invalid the validation process --> -<!-- will immediately be stopped and this functions will return --> -<!-- {error, Reason}. --> -<!-- </p> --> -<!-- </desc> --> -<!-- </func> --> + <func> + <name>pkix_verify(Cert, Key) -> boolean()</name> + <fsummary> Verify pkix x.509 certificate signature.</fsummary> + <type> + <v>Cert = der_encode()</v> + <v>Key = rsa_public_key() | dsa_public_key()</v> + </type> + <desc> + <p> Verify pkix x.509 certificate signature.</p> + </desc> + </func> -<!-- <func> --> -<!-- <name>sign(DigestOrTBSCert, Key) -> </name> --> -<!-- <name>sign(DigestOrTBSCert, Key, KeyParams) -> {ok, SignatureOrDerCert} | {error, Reason}</name> --> -<!-- <fsummary>Signs Digest/Certificate using Key.</fsummary> --> -<!-- <type> --> -<!-- <v>DigestOrTBSCert = binary() | x509_tbs_certificate()</v> --> -<!-- <v>Key = private_key()</v> --> -<!-- <v>SignatureORDerCert = binary() | der_bin() </v> --> -<!-- <v>Reason = term() </v> --> -<!-- </type> --> -<!-- <desc> --> -<!-- <p> Signs Digest/Certificate using Key, in the later --> -<!-- case a der encoded x509_certificate() will be returned. </p> --> -<!-- </desc> --> -<!-- </func> --> + <func> + <name>sign(Msg, DigestType, Key) -> binary()</name> + <fsummary> Create digital signature.</fsummary> + <type> + <v>Msg = binary()</v> + <d>The msg is either the binary "plain text" data to be + signed or in the case that digest type is <c>none</c> + it is the hashed value of "plain text" i.e. the digest.</d> + <v>DigestType = rsa_digest_type() | dsa_digest_type()</v> + <v>Key = rsa_public_key() | dsa_public_key()</v> + </type> + <desc> + <p> Creates a digital signature.</p> + </desc> + </func> -<!-- <func> --> -<!-- <name>verify_signature(Digest, Signature, Key) -> </name> --> -<!-- <name>verify_signature(DerCert, Key, KeyParams) -> </name> --> -<!-- <name>verify_signature(Digest, Signature, Key, Params) -> Verified </name> --> -<!-- <fsummary> Verifies the signature. </fsummary> --> -<!-- <type> --> -<!-- <v>Digest = binary() </v> --> -<!-- <v>DerCert = der_bin() </v> --> -<!-- <v>Signature = binary() </v> --> -<!-- <v>Key = public_key() </v> --> -<!-- <v>Params = key_params()</v> --> -<!-- <v>Verified = boolean()</v> --> -<!-- </type> --> -<!-- <desc> --> -<!-- <p> Verifies the signature Signature. If the key is an rsa-key no --> -<!-- paramters are neeed.</p> --> -<!-- </desc> --> -<!-- </func> --> + <func> + <name>verify(Msg, DigestType, Signature, Key) -> boolean()</name> + <fsummary>Verifies a digital signature.</fsummary> + <type> + <v>Msg = binary()</v> + <d>The msg is either the binary "plain text" data + or in the case that digest type is <c>none</c> + it is the hashed value of "plain text" i.e. the digest.</d> + <v>DigestType = rsa_digest_type() | dsa_digest_type()</v> + <v>Signature = binary()</v> + <v>Key = rsa_public_key() | dsa_public_key()</v> + </type> + <desc> + <p>Verifies a digital signature</p> + </desc> + </func> + </funcs> </erlref> diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl index fbce10f0eb..82681502ab 100644 --- a/lib/public_key/include/public_key.hrl +++ b/lib/public_key/include/public_key.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2010. 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 @@ -28,6 +28,13 @@ algorithm, parameters = asn1_NOVALUE}). +-define(DEFAULT_VERIFYFUN, + {fun(_,{bad_cert, _} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState} + end, []}). + -record(path_validation_state, { valid_policy_tree, explicit_policy, @@ -42,7 +49,7 @@ working_public_key_parameters, working_issuer_name, max_path_length, - acc_errors, %% If verify_none option is set + verify_fun, user_state }). @@ -59,4 +66,13 @@ interim_reasons_mask }). + +-type der_encoded() :: binary(). +-type decrypt_der() :: binary(). +-type pki_asn1_type() :: 'Certificate' | 'RSAPrivateKey' + | 'DSAPrivateKey' | 'DHParameter'. +-type pem_entry() :: {pki_asn1_type(), der_encoded() | decrypt_der(), + not_encrypted | {Cipher :: string(), Salt :: binary()}}. +-type asn1_type() :: atom(). %% see "OTP-PUB-KEY.hrl + -endif. % -ifdef(public_key). diff --git a/lib/public_key/src/Makefile b/lib/public_key/src/Makefile index c30399f33a..51f405361b 100644 --- a/lib/public_key/src/Makefile +++ b/lib/public_key/src/Makefile @@ -42,8 +42,7 @@ MODULES = \ public_key \ pubkey_pem \ pubkey_cert \ - pubkey_cert_records \ - pubkey_crypto + pubkey_cert_records HRL_FILES = $(INCLUDE)/public_key.hrl diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl index 0651dcec29..b3c230df25 100644 --- a/lib/public_key/src/pubkey_cert.erl +++ b/lib/public_key/src/pubkey_cert.erl @@ -23,14 +23,13 @@ -include("public_key.hrl"). --export([verify_signature/3, - init_validation_state/3, prepare_for_next_cert/2, +-export([init_validation_state/3, prepare_for_next_cert/2, validate_time/3, validate_signature/6, validate_issuer/4, validate_names/6, validate_revoked_status/3, validate_extensions/4, - validate_unknown_extensions/3, normalize_general_name/1, digest_type/1, is_self_signed/1, - is_issuer/2, issuer_id/2, is_fixed_dh_cert/1]). + is_issuer/2, issuer_id/2, is_fixed_dh_cert/1, + verify_data/1]). -define(NULL, 0). @@ -38,10 +37,22 @@ %% Internal application API %%==================================================================== -verify_signature(DerCert, Key, KeyParams) -> - {ok, OtpCert} = pubkey_cert_records:decode_cert(DerCert, otp), - verify_signature(OtpCert, DerCert, Key, KeyParams). +%%-------------------------------------------------------------------- +-spec verify_data(der_encoded()) -> {md5 | sha, binary(), binary()}. +%% +%% Description: Extracts data from DerCert needed to call public_key:verify/4. +%%-------------------------------------------------------------------- +verify_data(DerCert) -> + {ok, OtpCert} = pubkey_cert_records:decode_cert(DerCert), + extract_verify_data(OtpCert, DerCert). +%%-------------------------------------------------------------------- +-spec init_validation_state(#'OTPCertificate'{}, integer(), list()) -> + #path_validation_state{}. +%% +%% Description: Creates inital version of path_validation_state for +%% basic path validation of x509 certificates. +%%-------------------------------------------------------------------- init_validation_state(#'OTPCertificate'{} = OtpCert, DefaultPathLen, Options) -> PolicyTree = #policy_tree_node{valid_policy = ?anyPolicy, @@ -56,16 +67,23 @@ init_validation_state(#'OTPCertificate'{} = OtpCert, DefaultPathLen, Options, false)), PolicyMapping = policy_indicator(MaxLen, proplists:get_value(policy_mapping, Options, false)), - AccErrors = proplists:get_value(acc_errors, Options, []), - State = #path_validation_state{max_path_length = MaxLen, - valid_policy_tree = PolicyTree, - explicit_policy = ExplicitPolicy, - inhibit_any_policy = InhibitAnyPolicy, - policy_mapping = PolicyMapping, - acc_errors = AccErrors, + {VerifyFun, UserState} = proplists:get_value(verify_fun, Options, ?DEFAULT_VERIFYFUN), + State = #path_validation_state{max_path_length = MaxLen, + valid_policy_tree = PolicyTree, + explicit_policy = ExplicitPolicy, + inhibit_any_policy = InhibitAnyPolicy, + policy_mapping = PolicyMapping, + verify_fun = VerifyFun, + user_state = UserState, cert_num = 0}, prepare_for_next_cert(OtpCert, State). +%%-------------------------------------------------------------------- +-spec prepare_for_next_cert(#'OTPCertificate'{}, #path_validation_state{}) -> + #path_validation_state{}. +%% +%% Description: Update path_validation_state for next iteration. +%%-------------------------------------------------------------------- prepare_for_next_cert(OtpCert, ValidationState = #path_validation_state{ working_public_key_algorithm = PrevAlgo, working_public_key_parameters = @@ -92,8 +110,14 @@ prepare_for_next_cert(OtpCert, ValidationState = #path_validation_state{ working_issuer_name = Issuer, cert_num = ValidationState#path_validation_state.cert_num + 1 }. - -validate_time(OtpCert, AccErr, Verify) -> + + %%-------------------------------------------------------------------- +-spec validate_time(#'OTPCertificate'{}, term(), fun()) -> term(). +%% +%% Description: Check that the certificate validity period includes the +%% current time. +%%-------------------------------------------------------------------- +validate_time(OtpCert, UserState, VerifyFun) -> TBSCert = OtpCert#'OTPCertificate'.tbsCertificate, {'Validity', NotBeforeStr, NotAfterStr} = TBSCert#'OTPTBSCertificate'.validity, @@ -103,34 +127,52 @@ validate_time(OtpCert, AccErr, Verify) -> case ((NotBefore =< Now) and (Now =< NotAfter)) of true -> - AccErr; + UserState; false -> - not_valid({bad_cert, cert_expired}, Verify, AccErr) + verify_fun(OtpCert, {bad_cert, cert_expired}, UserState, VerifyFun) end. - -validate_issuer(OtpCert, Issuer, AccErr, Verify) -> +%%-------------------------------------------------------------------- +-spec validate_issuer(#'OTPCertificate'{}, term(), term(), fun()) -> term(). +%% +%% Description: Check that the certificate issuer name is the working_issuer_name +%% in path_validation_state. +%%-------------------------------------------------------------------- +validate_issuer(OtpCert, Issuer, UserState, VerifyFun) -> TBSCert = OtpCert#'OTPCertificate'.tbsCertificate, case is_issuer(Issuer, TBSCert#'OTPTBSCertificate'.issuer) of true -> - AccErr; + UserState; _ -> - not_valid({bad_cert, invalid_issuer}, Verify, AccErr) + verify_fun(OtpCert, {bad_cert, invalid_issuer}, UserState, VerifyFun) end. - +%%-------------------------------------------------------------------- +-spec validate_signature(#'OTPCertificate'{}, der_encoded(), + term(),term(), term(), fun()) -> term(). + +%% +%% Description: Check that the signature on the certificate can be verified using +%% working_public_key_algorithm, the working_public_key, and +%% the working_public_key_parameters in path_validation_state. +%%-------------------------------------------------------------------- validate_signature(OtpCert, DerCert, Key, KeyParams, - AccErr, Verify) -> + UserState, VerifyFun) -> case verify_signature(OtpCert, DerCert, Key, KeyParams) of true -> - AccErr; + UserState; false -> - not_valid({bad_cert, invalid_signature}, Verify, AccErr) + verify_fun(OtpCert, {bad_cert, invalid_signature}, UserState, VerifyFun) end. - -validate_names(OtpCert, Permit, Exclude, Last, AccErr, Verify) -> +%%-------------------------------------------------------------------- +-spec validate_names(#'OTPCertificate'{}, list(), list(), + term(), term(), fun())-> term(). +%% +%% Description: Validate Subject Alternative Name. +%%-------------------------------------------------------------------- +validate_names(OtpCert, Permit, Exclude, Last, UserState, VerifyFun) -> case is_self_signed(OtpCert) andalso (not Last) of true -> - AccErr; + UserState; false -> TBSCert = OtpCert#'OTPCertificate'.tbsCertificate, Subject = TBSCert#'OTPTBSCertificate'.subject, @@ -143,8 +185,10 @@ validate_names(OtpCert, Permit, Exclude, Last, AccErr, Verify) -> Name = [{directoryName, Subject}|EmailAddress], AltNames = case AltSubject of - undefined -> []; - _ -> AltSubject#'Extension'.extnValue + undefined -> + []; + _ -> + AltSubject#'Extension'.extnValue end, case (is_permitted(Name, Permit) andalso @@ -152,65 +196,69 @@ validate_names(OtpCert, Permit, Exclude, Last, AccErr, Verify) -> (not is_excluded(Name, Exclude)) andalso (not is_excluded(AltNames, Exclude))) of true -> - AccErr; + UserState; false -> - not_valid({bad_cert, name_not_permitted}, - Verify, AccErr) + verify_fun(OtpCert, {bad_cert, name_not_permitted}, + UserState, VerifyFun) end end. - -%% See rfc3280 4.1.2.6 Subject: regarding emails. -extract_email({rdnSequence, List}) -> - extract_email2(List). -extract_email2([[#'AttributeTypeAndValue'{type=?'id-emailAddress', - value=Mail}]|_]) -> - [{rfc822Name, Mail}]; -extract_email2([_|Rest]) -> - extract_email2(Rest); -extract_email2([]) -> []. - -validate_revoked_status(_OtpCert, _Verify, AccErr) -> - %% true | +%%-------------------------------------------------------------------- +-spec validate_revoked_status(#'OTPCertificate'{}, term(), fun()) -> + term(). +%% +%% Description: Check if certificate has been revoked. +%%-------------------------------------------------------------------- +validate_revoked_status(_OtpCert, UserState, _VerifyFun) -> + %% TODO: Implement or leave for application?! + %% valid | %% throw({bad_cert, cert_revoked}) - AccErr. - -validate_extensions(OtpCert, ValidationState, Verify, AccErr) -> + UserState. +%%-------------------------------------------------------------------- +-spec validate_extensions(#'OTPCertificate'{}, #path_validation_state{}, + term(), fun())-> + {#path_validation_state{}, UserState :: term()}. +%% +%% Description: Check extensions included in basic path validation. +%%-------------------------------------------------------------------- +validate_extensions(OtpCert, ValidationState, UserState, VerifyFun) -> TBSCert = OtpCert#'OTPCertificate'.tbsCertificate, Extensions = TBSCert#'OTPTBSCertificate'.extensions, - validate_extensions(Extensions, ValidationState, no_basic_constraint, - is_self_signed(OtpCert), [], Verify, AccErr). - -validate_unknown_extensions([], AccErr, _Verify) -> - AccErr; -validate_unknown_extensions([#'Extension'{critical = true} | _], - AccErr, Verify) -> - not_valid({bad_cert, unknown_critical_extension}, Verify, AccErr); -validate_unknown_extensions([#'Extension'{critical = false} | Rest], - AccErr, Verify) -> - validate_unknown_extensions(Rest, AccErr, Verify). + validate_extensions(OtpCert, Extensions, ValidationState, no_basic_constraint, + is_self_signed(OtpCert), UserState, VerifyFun). +%%-------------------------------------------------------------------- +-spec normalize_general_name({rdnSequence, term()}) -> {rdnSequence, term()}. +%% +%% Description: Normalizes a general name so that it can be easily +%% compared to another genral name. +%%-------------------------------------------------------------------- normalize_general_name({rdnSequence, Issuer}) -> - NormIssuer = normalize_general_name(Issuer), - {rdnSequence, NormIssuer}; - -normalize_general_name(Issuer) -> - Normalize = fun([{Description, Type, {printableString, Value}}]) -> - NewValue = string:to_lower(strip_spaces(Value)), - [{Description, Type, {printableString, NewValue}}]; - (Atter) -> - Atter - end, - lists:sort(lists:map(Normalize, Issuer)). + NormIssuer = do_normalize_general_name(Issuer), + {rdnSequence, NormIssuer}. +%%-------------------------------------------------------------------- +-spec is_self_signed(#'OTPCertificate'{}) -> boolean(). +%% +%% Description: Checks if the certificate is self signed. +%%-------------------------------------------------------------------- is_self_signed(#'OTPCertificate'{tbsCertificate= #'OTPTBSCertificate'{issuer = Issuer, subject = Subject}}) -> is_issuer(Issuer, Subject). - +%%-------------------------------------------------------------------- +-spec is_issuer({rdnSequence, term()}, {rdnSequence, term()}) -> boolean(). +%% +%% Description: Checks if <Issuer> issued <Candidate>. +%%-------------------------------------------------------------------- is_issuer({rdnSequence, Issuer}, {rdnSequence, Candidate}) -> is_dir_name(Issuer, Candidate, true). - +%%-------------------------------------------------------------------- +-spec issuer_id(#'OTPCertificate'{}, self | other) -> + {ok, {integer(), term()}} | {error, issuer_not_found}. +%% +%% Description: Extracts the issuer id from a certificate if possible. +%%-------------------------------------------------------------------- issuer_id(Otpcert, other) -> TBSCert = Otpcert#'OTPCertificate'.tbsCertificate, Extensions = extensions_list(TBSCert#'OTPTBSCertificate'.extensions), @@ -227,7 +275,12 @@ issuer_id(Otpcert, self) -> SerialNr = TBSCert#'OTPTBSCertificate'.serialNumber, {ok, {SerialNr, normalize_general_name(Issuer)}}. - +%%-------------------------------------------------------------------- +-spec is_fixed_dh_cert(#'OTPCertificate'{}) -> boolean(). +%% +%% Description: Checks if the certificate can be be used +%% for DH key agreement. +%%-------------------------------------------------------------------- is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate = #'OTPTBSCertificate'{subjectPublicKeyInfo = SubjectPublicKeyInfo, @@ -238,28 +291,66 @@ is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate = %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- +do_normalize_general_name(Issuer) -> + Normalize = fun([{Description, Type, {printableString, Value}}]) -> + NewValue = string:to_lower(strip_spaces(Value)), + [{Description, Type, {printableString, NewValue}}]; + (Atter) -> + Atter + end, + lists:sort(lists:map(Normalize, Issuer)). + +%% See rfc3280 4.1.2.6 Subject: regarding emails. +extract_email({rdnSequence, List}) -> + extract_email2(List). +extract_email2([[#'AttributeTypeAndValue'{type=?'id-emailAddress', + value=Mail}]|_]) -> + [{rfc822Name, Mail}]; +extract_email2([_|Rest]) -> + extract_email2(Rest); +extract_email2([]) -> []. extensions_list(asn1_NOVALUE) -> []; extensions_list(Extensions) -> Extensions. -not_valid(Error, true, _) -> - throw(Error); -not_valid(Error, false, AccErrors) -> - [Error | AccErrors]. +verify_fun(Otpcert, Result, UserState0, VerifyFun) -> + case VerifyFun(Otpcert, Result, UserState0) of + {valid,UserState} -> + UserState; + {fail, Reason} -> + case Result of + {bad_cert, _} -> + throw(Result); + _ -> + throw({bad_cert, Reason}) + end; + {unknown, UserState} -> + case Result of + {extension, #'Extension'{critical = true}} -> + throw({bad_cert, unknown_critical_extension}); + _ -> + UserState + end + end. -verify_signature(OtpCert, DerCert, Key, KeyParams) -> - %% Signature is an ASN1 compact bit string +extract_verify_data(OtpCert, DerCert) -> {0, Signature} = OtpCert#'OTPCertificate'.signature, SigAlgRec = OtpCert#'OTPCertificate'.signatureAlgorithm, SigAlg = SigAlgRec#'SignatureAlgorithm'.algorithm, - EncTBSCert = encoded_tbs_cert(DerCert), - verify(SigAlg, EncTBSCert, Signature, Key, KeyParams). + PlainText = encoded_tbs_cert(DerCert), + DigestType = digest_type(SigAlg), + {DigestType, PlainText, Signature}. -verify(Alg, PlainText, Signature, Key, KeyParams) -> - public_key:verify_signature(PlainText, digest_type(Alg), - Signature, Key, KeyParams). +verify_signature(OtpCert, DerCert, Key, KeyParams) -> + {DigestType, PlainText, Signature} = extract_verify_data(OtpCert, DerCert), + case Key of + #'RSAPublicKey'{} -> + public_key:verify(PlainText, DigestType, Signature, Key); + _ -> + public_key:verify(PlainText, DigestType, Signature, {Key, KeyParams}) + end. encoded_tbs_cert(Cert) -> {ok, PKIXCert} = @@ -369,198 +460,189 @@ select_extension(Id, [_ | Extensions]) -> select_extension(Id, Extensions). %% No extensions present -validate_extensions(asn1_NOVALUE, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr) -> - validate_extensions([], ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr); - -validate_extensions([], ValidationState, basic_constraint, _SelfSigned, - UnknownExtensions, _Verify, AccErr) -> - {ValidationState, UnknownExtensions, AccErr}; -validate_extensions([], ValidationState = - #path_validation_state{max_path_length = Len, - last_cert = Last}, - no_basic_constraint, SelfSigned, UnknownExtensions, - Verify, AccErr0) -> +validate_extensions(OtpCert, asn1_NOVALUE, ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun) -> + validate_extensions(OtpCert, [], ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun); + +validate_extensions(_,[], ValidationState, basic_constraint, _SelfSigned, + UserState, _) -> + {ValidationState, UserState}; +validate_extensions(OtpCert, [], ValidationState = + #path_validation_state{max_path_length = Len, + last_cert = Last}, + no_basic_constraint, SelfSigned, UserState0, VerifyFun) -> case Last of true when SelfSigned -> - {ValidationState, UnknownExtensions, AccErr0}; + {ValidationState, UserState0}; true -> {ValidationState#path_validation_state{max_path_length = Len - 1}, - UnknownExtensions, AccErr0}; + UserState0}; %% basic_constraint must appear in certs used for digital sign %% see 4.2.1.10 in rfc 3280 false -> - AccErr = not_valid({bad_cert, missing_basic_constraint}, - Verify, AccErr0), + UserState = verify_fun(OtpCert, {bad_cert, missing_basic_constraint}, + UserState0, VerifyFun), case SelfSigned of true -> - {ValidationState, UnknownExtensions, AccErr}; + {ValidationState, UserState}; false -> {ValidationState#path_validation_state{max_path_length = - Len - 1}, - UnknownExtensions, AccErr} + Len - 1}, + UserState} end end; -validate_extensions([#'Extension'{extnID = ?'id-ce-basicConstraints', +validate_extensions(OtpCert, + [#'Extension'{extnID = ?'id-ce-basicConstraints', extnValue = - #'BasicConstraints'{cA = true, - pathLenConstraint = N}} | + #'BasicConstraints'{cA = true, + pathLenConstraint = N}} | Rest], - ValidationState = - #path_validation_state{max_path_length = Len}, _, - SelfSigned, UnknownExtensions, Verify, AccErr) -> - Length = if SelfSigned -> min(N, Len); - true -> min(N, Len-1) + ValidationState = + #path_validation_state{max_path_length = Len}, _, + SelfSigned, UserState, VerifyFun) -> + Length = if SelfSigned -> erlang:min(N, Len); + true -> erlang:min(N, Len-1) end, - validate_extensions(Rest, + validate_extensions(OtpCert, Rest, ValidationState#path_validation_state{max_path_length = - Length}, - basic_constraint, SelfSigned, UnknownExtensions, - Verify, AccErr); + Length}, + basic_constraint, SelfSigned, + UserState, VerifyFun); %% The pathLenConstraint field is meaningful only if cA is set to %% TRUE. -validate_extensions([#'Extension'{extnID = ?'id-ce-basicConstraints', - extnValue = - #'BasicConstraints'{cA = false}} | - Rest], ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr) -> - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr); - -%% -validate_extensions([#'Extension'{extnID = ?'id-ce-keyUsage', - extnValue = KeyUse - } | Rest], - #path_validation_state{last_cert=Last} = ValidationState, - ExistBasicCon, SelfSigned, UnknownExtensions, - Verify, AccErr0) -> +validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = + #'BasicConstraints'{cA = false}} | + Rest], ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun) -> + validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun); + +validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-keyUsage', + extnValue = KeyUse + } | Rest], + #path_validation_state{last_cert=Last} = ValidationState, + ExistBasicCon, SelfSigned, + UserState0, VerifyFun) -> case Last orelse is_valid_key_usage(KeyUse, keyCertSign) of true -> - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, - AccErr0); + validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, + SelfSigned, UserState0, VerifyFun); false -> - AccErr = not_valid({bad_cert, invalid_key_usage}, Verify, AccErr0), - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, - AccErr) + UserState = verify_fun(OtpCert, {bad_cert, invalid_key_usage}, + UserState0, VerifyFun), + validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun) end; -validate_extensions([#'Extension'{extnID = ?'id-ce-subjectAltName', - extnValue = Names} | Rest], - ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr0) -> +validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-subjectAltName', + extnValue = Names} | Rest], + ValidationState, ExistBasicCon, + SelfSigned, UserState0, VerifyFun) -> case validate_subject_alt_names(Names) of true when Names =/= [] -> - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, - AccErr0); + validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, + SelfSigned, UserState0, VerifyFun); _ -> - AccErr = - not_valid({bad_cert, invalid_subject_altname}, - Verify, AccErr0), - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, - AccErr) + UserState = verify_fun(OtpCert, {bad_cert, invalid_subject_altname}, + UserState0, VerifyFun), + validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun) end; %% This extension SHOULD NOT be marked critical. Its value %% does not have to be further validated at this point. -validate_extensions([#'Extension'{extnID = ?'id-ce-issuerAltName', - extnValue = _} | Rest], - ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr) -> - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr); +validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-issuerAltName', + extnValue = _} | Rest], + ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun) -> + validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun); %% This extension MUST NOT be marked critical.Its value %% does not have to be further validated at this point. -validate_extensions([#'Extension'{extnID = Id, - extnValue = _, - critical = false} | Rest], +validate_extensions(OtpCert, [#'Extension'{extnID = Id, + extnValue = _, + critical = false} | Rest], ValidationState, - ExistBasicCon, SelfSigned, UnknownExtensions, - Verify, AccErr) + ExistBasicCon, SelfSigned, + UserState, VerifyFun) when Id == ?'id-ce-subjectKeyIdentifier'; Id == ?'id-ce-authorityKeyIdentifier'-> - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr); + validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun); -validate_extensions([#'Extension'{extnID = ?'id-ce-nameConstraints', +validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-nameConstraints', extnValue = NameConst} | Rest], ValidationState, - ExistBasicCon, SelfSigned, UnknownExtensions, - Verify, AccErr) -> + ExistBasicCon, SelfSigned, UserState, VerifyFun) -> Permitted = NameConst#'NameConstraints'.permittedSubtrees, Excluded = NameConst#'NameConstraints'.excludedSubtrees, NewValidationState = add_name_constraints(Permitted, Excluded, ValidationState), - validate_extensions(Rest, NewValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr); + validate_extensions(OtpCert, Rest, NewValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun); -validate_extensions([#'Extension'{extnID = ?'id-ce-certificatePolicies', - critical = true} | Rest], ValidationState, - ExistBasicCon, SelfSigned, - UnknownExtensions, Verify, AccErr0) -> +validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-certificatePolicies', + critical = true} = Ext| Rest], ValidationState, + ExistBasicCon, SelfSigned, UserState0, VerifyFun) -> %% TODO: Remove this clause when policy handling is %% fully implemented - AccErr = - not_valid({bad_cert, unknown_critical_extension}, Verify, AccErr0), - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr); - -validate_extensions([#'Extension'{extnID = ?'id-ce-certificatePolicies', - extnValue = #'PolicyInformation'{ - policyIdentifier = Id, - policyQualifiers = Qualifier}} - | Rest], #path_validation_state{valid_policy_tree = Tree} + UserState = verify_fun(OtpCert, {extension, Ext}, + UserState0, VerifyFun), + validate_extensions(OtpCert,Rest, ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun); + +validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-certificatePolicies', + extnValue = #'PolicyInformation'{ + policyIdentifier = Id, + policyQualifiers = Qualifier}} + | Rest], #path_validation_state{valid_policy_tree = Tree} = ValidationState, - ExistBasicCon, SelfSigned, UnknownExtensions, - Verify, AccErr) -> + ExistBasicCon, SelfSigned, UserState, VerifyFun) -> %% TODO: Policy imp incomplete NewTree = process_policy_tree(Id, Qualifier, Tree), - validate_extensions(Rest, + validate_extensions(OtpCert, Rest, ValidationState#path_validation_state{ valid_policy_tree = NewTree}, - ExistBasicCon, SelfSigned, UnknownExtensions, - Verify, AccErr); + ExistBasicCon, SelfSigned, UserState, VerifyFun); -validate_extensions([#'Extension'{extnID = ?'id-ce-policyConstraints', - critical = true} | Rest], ValidationState, - ExistBasicCon, SelfSigned, UnknownExtensions, Verify, - AccErr0) -> +validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-policyConstraints', + critical = true} = Ext | Rest], ValidationState, + ExistBasicCon, SelfSigned, UserState0, VerifyFun) -> %% TODO: Remove this clause when policy handling is %% fully implemented - AccErr = - not_valid({bad_cert, unknown_critical_extension}, Verify, AccErr0), - validate_extensions(Rest, ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr); -validate_extensions([#'Extension'{extnID = ?'id-ce-policyConstraints', - extnValue = #'PolicyConstraints'{ - requireExplicitPolicy = ExpPolicy, - inhibitPolicyMapping = MapPolicy}} - | Rest], ValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr) -> + UserState = verify_fun(OtpCert, {extension, Ext}, + UserState0, VerifyFun), + validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun); +validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-policyConstraints', + extnValue = #'PolicyConstraints'{ + requireExplicitPolicy = ExpPolicy, + inhibitPolicyMapping = MapPolicy}} + | Rest], ValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun) -> %% TODO: Policy imp incomplete - NewValidationState = add_policy_constraints(ExpPolicy, MapPolicy, + NewValidationState = add_policy_constraints(ExpPolicy, MapPolicy, ValidationState), - validate_extensions(Rest, NewValidationState, ExistBasicCon, - SelfSigned, UnknownExtensions, Verify, AccErr); + validate_extensions(OtpCert, Rest, NewValidationState, ExistBasicCon, + SelfSigned, UserState, VerifyFun); -validate_extensions([Extension | Rest], ValidationState, - ExistBasicCon, SelfSigned, UnknownExtensions, - Verify, AccErr) -> - validate_extensions(Rest, ValidationState, ExistBasicCon, SelfSigned, - [Extension | UnknownExtensions], Verify, AccErr). +validate_extensions(OtpCert, [#'Extension'{} = Extension | Rest], + ValidationState, ExistBasicCon, + SelfSigned, UserState0, VerifyFun) -> + UserState = verify_fun(OtpCert, {extension, Extension}, UserState0, VerifyFun), + validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, SelfSigned, + UserState, VerifyFun). is_valid_key_usage(KeyUse, Use) -> lists:member(Use, KeyUse). @@ -603,11 +685,6 @@ is_valid_subject_alt_name({_, [_|_]}) -> is_valid_subject_alt_name({_, _}) -> false. -min(N, M) when N =< M -> - N; -min(_, M) -> - M. - is_ip_address(Address) -> case inet_parse:address(Address) of {ok, _} -> @@ -670,10 +747,11 @@ split_auth_path(URIPart) -> end. split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) -> - case regexp:first_match(UriPart, SplitChar) of - {match, Match, _} -> - {string:substr(UriPart, 1, Match - SkipLeft), - string:substr(UriPart, Match + SkipRight, length(UriPart))}; + case re:run(UriPart, SplitChar) of + {match,[{Start, _}]} -> + StrPos = Start + 1, + {string:substr(UriPart, 1, StrPos - SkipLeft), + string:substr(UriPart, StrPos + SkipRight, length(UriPart))}; nomatch -> NoMatchResult end. @@ -926,7 +1004,7 @@ add_policy_constraints(ExpPolicy, MapPolicy, policy_constraint(Current, asn1_NOVALUE, _) -> Current; policy_constraint(Current, New, CertNum) -> - min(Current, New + CertNum). + erlang:min(Current, New + CertNum). process_policy_tree(_,_, ?NULL) -> ?NULL; diff --git a/lib/public_key/src/pubkey_cert_records.erl b/lib/public_key/src/pubkey_cert_records.erl index ac04e1c2cb..20b322b4a4 100644 --- a/lib/public_key/src/pubkey_cert_records.erl +++ b/lib/public_key/src/pubkey_cert_records.erl @@ -23,30 +23,61 @@ -include("public_key.hrl"). --export([decode_cert/2, encode_cert/1, encode_tbs_cert/1, transform/2]). +-export([decode_cert/1, transform/2]). %%==================================================================== %% Internal application API %%==================================================================== -decode_cert(DerCert, plain) -> - 'OTP-PUB-KEY':decode('Certificate', DerCert); -decode_cert(DerCert, otp) -> +%%-------------------------------------------------------------------- +-spec decode_cert(der_encoded()) -> {ok, #'OTPCertificate'{}}. +%% +%% Description: Recursively decodes a Certificate. +%%-------------------------------------------------------------------- +decode_cert(DerCert) -> {ok, Cert} = 'OTP-PUB-KEY':decode('OTPCertificate', DerCert), #'OTPCertificate'{tbsCertificate = TBS} = Cert, {ok, Cert#'OTPCertificate'{tbsCertificate = decode_tbs(TBS)}}. -encode_cert(Cert = #'Certificate'{}) -> - {ok, EncCert} = 'OTP-PUB-KEY':encode('Certificate', Cert), - list_to_binary(EncCert); -encode_cert(C = #'OTPCertificate'{tbsCertificate = TBS}) -> - Cert = C#'OTPCertificate'{tbsCertificate=encode_tbs(TBS)}, - {ok, EncCert} = 'OTP-PUB-KEY':encode('OTPCertificate', Cert), - list_to_binary(EncCert). - -encode_tbs_cert(TBS) -> - {ok, EncTBSCert} = 'OTP-PUB-KEY':encode('OTPTBSCertificate', encode_tbs(TBS)), - list_to_binary(EncTBSCert). +%%-------------------------------------------------------------------- +-spec transform(term(), encode | decode) ->term(). +%% +%% Description: Transforms between encoded and decode otp formated +%% certificate parts. +%%-------------------------------------------------------------------- + +transform(#'OTPCertificate'{tbsCertificate = TBS} = Cert, encode) -> + Cert#'OTPCertificate'{tbsCertificate=encode_tbs(TBS)}; +transform(#'OTPCertificate'{tbsCertificate = TBS} = Cert, decode) -> + Cert#'OTPCertificate'{tbsCertificate=decode_tbs(TBS)}; +transform(#'OTPTBSCertificate'{}= TBS, encode) -> + encode_tbs(TBS); +transform(#'OTPTBSCertificate'{}= TBS, decode) -> + decode_tbs(TBS); +transform(#'AttributeTypeAndValue'{type=Id,value=Value0} = ATAV, Func) -> + {ok, Value} = + case attribute_type(Id) of + Type when is_atom(Type) -> 'OTP-PUB-KEY':Func(Type, Value0); + _UnknownType -> {ok, Value0} + end, + ATAV#'AttributeTypeAndValue'{value=Value}; +transform(AKI = #'AuthorityKeyIdentifier'{authorityCertIssuer=ACI},Func) -> + AKI#'AuthorityKeyIdentifier'{authorityCertIssuer=transform(ACI,Func)}; +transform(List = [{directoryName, _}],Func) -> + [{directoryName, transform(Value,Func)} || {directoryName, Value} <- List]; +transform({directoryName, Value},Func) -> + {directoryName, transform(Value,Func)}; +transform({rdnSequence, SeqList},Func) when is_list(SeqList) -> + {rdnSequence, + lists:map(fun(Seq) -> + lists:map(fun(Element) -> transform(Element,Func) end, Seq) + end, SeqList)}; +transform(#'NameConstraints'{permittedSubtrees=Permitted, excludedSubtrees=Excluded}, Func) -> + #'NameConstraints'{permittedSubtrees=transform_sub_tree(Permitted,Func), + excludedSubtrees=transform_sub_tree(Excluded,Func)}; + +transform(Other,_) -> + Other. %%-------------------------------------------------------------------- %%% Internal functions @@ -132,31 +163,6 @@ encode_extensions(Exts) -> end end, Exts). -transform(#'AttributeTypeAndValue'{type=Id,value=Value0} = ATAV, Func) -> - {ok, Value} = - case attribute_type(Id) of - Type when is_atom(Type) -> 'OTP-PUB-KEY':Func(Type, Value0); - _UnknownType -> {ok, Value0} - end, - ATAV#'AttributeTypeAndValue'{value=Value}; -transform(AKI = #'AuthorityKeyIdentifier'{authorityCertIssuer=ACI},Func) -> - AKI#'AuthorityKeyIdentifier'{authorityCertIssuer=transform(ACI,Func)}; -transform(List = [{directoryName, _}],Func) -> - [{directoryName, transform(Value,Func)} || {directoryName, Value} <- List]; -transform({directoryName, Value},Func) -> - {directoryName, transform(Value,Func)}; -transform({rdnSequence, SeqList},Func) when is_list(SeqList) -> - {rdnSequence, - lists:map(fun(Seq) -> - lists:map(fun(Element) -> transform(Element,Func) end, Seq) - end, SeqList)}; -transform(#'NameConstraints'{permittedSubtrees=Permitted, excludedSubtrees=Excluded}, Func) -> - #'NameConstraints'{permittedSubtrees=transform_sub_tree(Permitted,Func), - excludedSubtrees=transform_sub_tree(Excluded,Func)}; - -transform(Other,_) -> - Other. - encode_tbs(TBS=#'OTPTBSCertificate'{issuer=Issuer0, subject=Subject0, subjectPublicKeyInfo=Spki0, diff --git a/lib/public_key/src/pubkey_crypto.erl b/lib/public_key/src/pubkey_crypto.erl deleted file mode 100644 index 7b7abb1c56..0000000000 --- a/lib/public_key/src/pubkey_crypto.erl +++ /dev/null @@ -1,171 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2010. 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% -%% - -%% -%% Description: Functions that call the crypto driver. - --module(pubkey_crypto). - --include("public_key.hrl"). - --export([encrypt_public/3, decrypt_private/3, - encrypt_private/3, decrypt_public/3, - sign/2, sign/3, verify/5, gen_key/2]). - --define(UINT32(X), X:32/unsigned-big-integer). - -%%==================================================================== -%% Internal application API -%%==================================================================== - -%%-------------------------------------------------------------------- -%% Function: encrypt(PlainText, Key, Padding) -> Encrypted -%% -%% PlainText = binary() -%% Key = rsa_public_key() | rsa_private_key() -%% Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding -%% Encrypted = binary() -%% -%% Description: Public key encrypts PlainText. -%%-------------------------------------------------------------------- -encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E}, - Padding) -> - crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)], - Padding); -encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E}, - Padding) -> - crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)], - Padding). - -encrypt_private(PlainText, #'RSAPrivateKey'{modulus = N, - publicExponent = E, - privateExponent = D}, Padding) -> - crypto:rsa_private_encrypt(PlainText, [crypto:mpint(E), - crypto:mpint(N), - crypto:mpint(D)], Padding). - -%%-------------------------------------------------------------------- -%% Function: decrypt(CipherText, Key) -> PlainText -%% -%% ChipherText = binary() -%% Key = rsa_private_key() -%% Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding -%% PlainText = binary() -%% -%% Description: Uses private key to decrypt public key encrypted data. -%%-------------------------------------------------------------------- -decrypt_private(CipherText, - #'RSAPrivateKey'{modulus = N,publicExponent = E, - privateExponent = D}, - Padding) -> - crypto:rsa_private_decrypt(CipherText, - [crypto:mpint(E), crypto:mpint(N), - crypto:mpint(D)], Padding). -decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E}, - Padding) -> - crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)], - Padding); -decrypt_public(CipherText, #'RSAPrivateKey'{modulus = N, publicExponent = E}, - Padding) -> - crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)], - Padding). - -%%-------------------------------------------------------------------- -%% Function: sign(PlainText, Key) -> -%% sign(DigestType, PlainText, Key) -> Signature -%% -%% DigestType = sha | md5 -%% PlainText = binary() -%% Key = rsa_private_key() | dsa_private_key() -%% Signature = binary() -%% -%% Description: Signs PlainText using Key. -%%-------------------------------------------------------------------- -sign(PlainText, Digest) -> - sign(sha, PlainText, Digest). - -sign(DigestType, PlainText, #'RSAPrivateKey'{modulus = N, publicExponent = E, - privateExponent = D}) -> - crypto:rsa_sign(DigestType, sized_binary(PlainText), [crypto:mpint(E), - crypto:mpint(N), - crypto:mpint(D)]); - -sign(none, Hash, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) -> - crypto:dss_sign(none, Hash, - [crypto:mpint(P), crypto:mpint(Q), - crypto:mpint(G), crypto:mpint(X)]); - -sign(sha, PlainText, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) -> - crypto:dss_sign(sized_binary(PlainText), - [crypto:mpint(P), crypto:mpint(Q), - crypto:mpint(G), crypto:mpint(X)]). - -%%-------------------------------------------------------------------- -%% Function: verify(DigestType, PlainText, Signature, Key) -> true | false -%% -%% DigestType = sha | md5 -%% PlainText = binary() -%% Signature = binary() -%% Key = rsa_public_key() | dsa_public_key() -%% -%% Description: Verifies the signature <Signature>. -%%-------------------------------------------------------------------- -verify(DigestType, PlainText, Signature, - #'RSAPublicKey'{modulus = Mod, publicExponent = Exp}, _) -> - crypto:rsa_verify(DigestType, - sized_binary(PlainText), - sized_binary(Signature), - [crypto:mpint(Exp), crypto:mpint(Mod)]); - -verify(none, Hash, Signature, Key, #'Dss-Parms'{p = P, q = Q, g = G}) -> - crypto:dss_verify(none, Hash, - sized_binary(Signature), - [crypto:mpint(P), crypto:mpint(Q), - crypto:mpint(G), crypto:mpint(Key)]); - -verify(sha, PlainText, Signature, Key, #'Dss-Parms'{p = P, q = Q, g = G}) -> - crypto:dss_verify(sized_binary(PlainText), - sized_binary(Signature), - [crypto:mpint(P), crypto:mpint(Q), - crypto:mpint(G), crypto:mpint(Key)]). - - -%%-------------------------------------------------------------------- -%% Function: gen_key(Type, Params) -> -%% Type = diffie_hellman -%% Params = [P,G] | [Y, P, G] -%% Description: Generates keys. -%% ----------------------------------------------------------------- -gen_key(diffie_hellman, [Y, P, G]) -> - crypto:dh_generate_key(crypto:mpint(Y), [crypto:mpint(P), - crypto:mpint(G)]); -gen_key(diffie_hellman, [P, G]) -> - crypto:dh_generate_key([crypto:mpint(P), crypto:mpint(G)]). - -%%% TODO: Support rsa, dss key_gen - -%%-------------------------------------------------------------------- -%%% Internal functions -%%-------------------------------------------------------------------- -sized_binary(Binary) when is_binary(Binary) -> - Size = size(Binary), - <<?UINT32(Size), Binary/binary>>; -sized_binary(List) -> - sized_binary(list_to_binary(List)). - diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl index 65879f1bbe..31d881973a 100644 --- a/lib/public_key/src/pubkey_pem.erl +++ b/lib/public_key/src/pubkey_pem.erl @@ -40,7 +40,10 @@ -module(pubkey_pem). --export([read_file/1, read_file/2, write_file/2, decode/2]). +-include("public_key.hrl"). + +-export([encode/1, decode/1, decipher/2, cipher/3]). +%% Backwards compatibility -export([decode_key/2]). -define(ENCODED_LINE_LENGTH, 64). @@ -48,28 +51,82 @@ %%==================================================================== %% Internal application API %%==================================================================== -read_file(File) -> - read_file(File, no_passwd). -read_file(File, Passwd) -> - {ok, Bin} = file:read_file(File), - decode(Bin, Passwd). +%%-------------------------------------------------------------------- +-spec decode(binary()) -> [pem_entry()]. +%% +%% Description: Decodes a PEM binary. +%%-------------------------------------------------------------------- +decode(Bin) -> + decode_pem_entries(split_bin(Bin), []). -write_file(File, Ds) -> - file:write_file(File, encode_file(Ds)). +%%-------------------------------------------------------------------- +-spec encode([pem_entry()]) -> iolist(). +%% +%% Description: Encodes a list of PEM entries. +%%-------------------------------------------------------------------- +encode(PemEntries) -> + encode_pem_entries(PemEntries). -decode_key({_Type, Bin, not_encrypted}, _) -> - Bin; -decode_key({_Type, Bin, {Chipher,Salt}}, Password) -> - decode_key(Bin, Password, Chipher, Salt). +%%-------------------------------------------------------------------- +-spec decipher({pki_asn1_type(), decrypt_der(),{Cipher :: string(), Salt :: binary()}}, string()) -> + der_encoded(). +%% +%% Description: Deciphers a decrypted pem entry. +%%-------------------------------------------------------------------- +decipher({_, DecryptDer, {Cipher,Salt}}, Password) -> + decode_key(DecryptDer, Password, Cipher, Salt). -decode(Bin, Passwd) -> - decode_file(split_bin(Bin), Passwd). +%%-------------------------------------------------------------------- +-spec cipher(der_encoded(),{Cipher :: string(), Salt :: binary()} , string()) -> binary(). +%% +%% Description: Ciphers a PEM entry +%%-------------------------------------------------------------------- +cipher(Der, {Cipher,Salt}, Password)-> + encode_key(Der, Password, Cipher, Salt). %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- +encode_pem_entries(Entries) -> + [encode_pem_entry(Entry) || Entry <- Entries]. + +encode_pem_entry({Asn1Type, Der, not_encrypted}) -> + StartStr = pem_start(Asn1Type), + [StartStr, "\n", b64encode_and_split(Der), pem_end(StartStr) ,"\n\n"]; +encode_pem_entry({Asn1Type, Der, {Cipher, Salt}}) -> + StartStr = pem_start(Asn1Type), + [StartStr,"\n", pem_decrypt(),"\n", pem_decrypt_info(Cipher, Salt),"\n", + b64encode_and_split(Der), pem_end(StartStr) ,"\n\n"]. + +decode_pem_entries([], Entries) -> + lists:reverse(Entries); +decode_pem_entries([<<>>], Entries) -> + lists:reverse(Entries); +decode_pem_entries([<<>> | Lines], Entries) -> + decode_pem_entries(Lines, Entries); +decode_pem_entries([Start| Lines], Entries) -> + case pem_end(Start) of + undefined -> + decode_pem_entries(Lines, Entries); + _End -> + {Entry, RestLines} = join_entry(Lines, []), + decode_pem_entries(RestLines, [decode_pem_entry(Start, Entry) | Entries]) + end. +decode_pem_entry(Start, [<<"Proc-Type: 4,ENCRYPTED", _/binary>>, Line | Lines]) -> + Asn1Type = asn1_type(Start), + Cs = erlang:iolist_to_binary(Lines), + Decoded = base64:mime_decode(Cs), + [_, DekInfo0] = string:tokens(binary_to_list(Line), ": "), + [Cipher, Salt] = string:tokens(DekInfo0, ","), + {Asn1Type, Decoded, {Cipher, unhex(Salt)}}; +decode_pem_entry(Start, Lines) -> + Asn1Type = asn1_type(Start), + Cs = erlang:iolist_to_binary(Lines), + Der = base64:mime_decode(Cs), + {Asn1Type, Der, not_encrypted}. + split_bin(Bin) -> split_bin(0, Bin). @@ -85,88 +142,26 @@ split_bin(N, Bin) -> split_bin(N+1, Bin) end. -decode_file(Bin, Passwd) -> - decode_file(Bin, [], [Passwd]). - -decode_file([<<"-----BEGIN CERTIFICATE REQUEST-----", _/binary>>|Rest], Ens, Info) -> - decode_file2(Rest, [], Ens, cert_req, Info); -decode_file([<<"-----BEGIN CERTIFICATE-----", _/binary>>|Rest], Ens, Info) -> - decode_file2(Rest, [], Ens, cert, Info); -decode_file([<<"-----BEGIN RSA PRIVATE KEY-----", _/binary>>|Rest], Ens, Info) -> - decode_file2(Rest, [], Ens, rsa_private_key, Info); -decode_file([<<"-----BEGIN DSA PRIVATE KEY-----", _/binary>>|Rest], Ens, Info) -> - decode_file2(Rest, [], Ens, dsa_private_key, Info); -decode_file([<<"-----BEGIN DH PARAMETERS-----", _/binary>>|Rest], Ens, Info) -> - decode_file2(Rest, [], Ens, dh_params, Info); -decode_file([_|Rest], Ens, Info) -> - decode_file(Rest, Ens, Info); -decode_file([], Ens, _Info) -> - {ok, lists:reverse(Ens)}. - -decode_file2([<<"Proc-Type: 4,ENCRYPTED", _/binary>>| Rest0], RLs, Ens, Tag, Info0) -> - [InfoLine|Rest] = Rest0, - Info = dek_info(InfoLine, Info0), - decode_file2(Rest, RLs, Ens, Tag, Info); -decode_file2([<<"-----END", _/binary>>| Rest], RLs, Ens, Tag, Info0) -> - Cs = erlang:iolist_to_binary(lists:reverse(RLs)), - Bin = base64:mime_decode(Cs), - case Info0 of - [Password, Cipher, SaltHex | Info1] -> - Salt = unhex(SaltHex), - Enc = {Cipher, Salt}, - Decoded = decode_key(Bin, Password, Cipher, Salt), - decode_file(Rest, [{Tag, Decoded, Enc}| Ens], Info1); - _ -> - decode_file(Rest, [{Tag, Bin, not_encrypted}| Ens], Info0) - end; -decode_file2([L|Rest], RLs, Ens, Tag, Info0) -> - decode_file2(Rest, [L|RLs], Ens, Tag, Info0); -decode_file2([], _, Ens, _, _) -> - {ok, lists:reverse(Ens)}. - -%% Support same as decode_file -encode_file(Ds) -> - lists:map( - fun({cert, Bin, not_encrypted}) -> - %% PKIX (X.509) - ["-----BEGIN CERTIFICATE-----\n", - b64encode_and_split(Bin), - "-----END CERTIFICATE-----\n\n"]; - ({cert_req, Bin, not_encrypted}) -> - %% PKCS#10 - ["-----BEGIN CERTIFICATE REQUEST-----\n", - b64encode_and_split(Bin), - "-----END CERTIFICATE REQUEST-----\n\n"]; - ({rsa_private_key, Bin, not_encrypted}) -> - %% PKCS#? - ["XXX Following key assumed not encrypted\n", - "-----BEGIN RSA PRIVATE KEY-----\n", - b64encode_and_split(Bin), - "-----END RSA PRIVATE KEY-----\n\n"]; - ({dsa_private_key, Bin, not_encrypted}) -> - %% PKCS#? - ["XXX Following key assumed not encrypted\n", - "-----BEGIN DSA PRIVATE KEY-----\n", - b64encode_and_split(Bin), - "-----END DSA PRIVATE KEY-----\n\n"] - end, Ds). - -dek_info(Line0, Info) -> - Line = binary_to_list(Line0), - [_, DekInfo0] = string:tokens(Line, ": "), - DekInfo1 = string:tokens(DekInfo0, ",\n"), - Info ++ DekInfo1. +b64encode_and_split(Bin) -> + split_lines(base64:encode(Bin)). -unhex(S) -> - unhex(S, []). +split_lines(<<Text:?ENCODED_LINE_LENGTH/binary, Rest/binary>>) -> + [Text, $\n | split_lines(Rest)]; +split_lines(Bin) -> + [Bin, $\n]. -unhex("", Acc) -> - list_to_binary(lists:reverse(Acc)); -unhex([D1, D2 | Rest], Acc) -> - unhex(Rest, [erlang:list_to_integer([D1, D2], 16) | Acc]). +%% Ignore white space at end of line +join_entry([<<"-----END CERTIFICATE-----", _/binary>>| Lines], Entry) -> + {lists:reverse(Entry), Lines}; +join_entry([<<"-----END RSA PRIVATE KEY-----", _/binary>>| Lines], Entry) -> + {lists:reverse(Entry), Lines}; +join_entry([<<"-----END DSA PRIVATE KEY-----", _/binary>>| Lines], Entry) -> + {lists:reverse(Entry), Lines}; +join_entry([<<"-----END DH PARAMETERS-----", _/binary>>| Lines], Entry) -> + {lists:reverse(Entry), Lines}; +join_entry([Line | Lines], Entry) -> + join_entry(Lines, [Line | Entry]). -decode_key(Data, no_passwd, _Alg, _Salt) -> - Data; decode_key(Data, Password, "DES-CBC", Salt) -> Key = password_to_key(Password, Salt, 8), IV = Salt, @@ -177,6 +172,16 @@ decode_key(Data, Password, "DES-EDE3-CBC", Salt) -> <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key, crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data). +encode_key(Data, Password, "DES-CBC", Salt) -> + Key = password_to_key(Password, Salt, 8), + IV = Salt, + crypto:des_cbc_encrypt(Key, IV, Data); +encode_key(Data, Password, "DES-EDE3-CBC", Salt) -> + Key = password_to_key(Password, Salt, 24), + IV = Salt, + <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key, + crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data). + password_to_key(Data, Salt, KeyLen) -> <<Key:KeyLen/binary, _/binary>> = password_to_key(<<>>, Data, Salt, KeyLen, <<>>), @@ -188,11 +193,58 @@ password_to_key(Prev, Data, Salt, Len, Acc) -> M = crypto:md5([Prev, Data, Salt]), password_to_key(M, Data, Salt, Len - size(M), <<Acc/binary, M/binary>>). -b64encode_and_split(Bin) -> - split_lines(base64:encode(Bin)). +unhex(S) -> + unhex(S, []). -split_lines(<<Text:?ENCODED_LINE_LENGTH/binary, Rest/binary>>) -> - [Text, $\n | split_lines(Rest)]; -split_lines(Bin) -> - [Bin, $\n]. +unhex("", Acc) -> + list_to_binary(lists:reverse(Acc)); +unhex([D1, D2 | Rest], Acc) -> + unhex(Rest, [erlang:list_to_integer([D1, D2], 16) | Acc]). + +hexify(L) -> [[hex_byte(B)] || B <- binary_to_list(L)]. + +hex_byte(B) when B < 16#10 -> ["0", erlang:integer_to_list(B, 16)]; +hex_byte(B) -> erlang:integer_to_list(B, 16). + +pem_start('Certificate') -> + <<"-----BEGIN CERTIFICATE-----">>; +pem_start('RSAPrivateKey') -> + <<"-----BEGIN RSA PRIVATE KEY-----">>; +pem_start('DSAPrivateKey') -> + <<"-----BEGIN DSA PRIVATE KEY-----">>; +pem_start('DHParameter') -> + <<"-----BEGIN DH PARAMETERS-----">>. + +pem_end(<<"-----BEGIN CERTIFICATE-----">>) -> + <<"-----END CERTIFICATE-----">>; +pem_end(<<"-----BEGIN RSA PRIVATE KEY-----">>) -> + <<"-----END RSA PRIVATE KEY-----">>; +pem_end(<<"-----BEGIN DSA PRIVATE KEY-----">>) -> + <<"-----END DSA PRIVATE KEY-----">>; +pem_end(<<"-----BEGIN DH PARAMETERS-----">>) -> + <<"-----END DH PARAMETERS-----">>; +pem_end(_) -> + undefined. + +asn1_type(<<"-----BEGIN CERTIFICATE-----">>) -> + 'Certificate'; +asn1_type(<<"-----BEGIN RSA PRIVATE KEY-----">>) -> + 'RSAPrivateKey'; +asn1_type(<<"-----BEGIN DSA PRIVATE KEY-----">>) -> + 'DSAPrivateKey'; +asn1_type(<<"-----BEGIN DH PARAMETERS-----">>) -> + 'DHParameter'. + +pem_decrypt() -> + <<"Proc-Type: 4,ENCRYPTED">>. + +pem_decrypt_info(Cipher, Salt) -> + io_lib:format("DEK-Info: ~s,~s", [Cipher, lists:flatten(hexify(Salt))]). +%%-------------------------------------------------------------------- +%%% Deprecated +%%-------------------------------------------------------------------- +decode_key({_Type, Bin, not_encrypted}, _) -> + Bin; +decode_key({_Type, Bin, {Chipher,Salt}}, Password) -> + decode_key(Bin, Password, Chipher, Salt). diff --git a/lib/public_key/src/public_key.app.src b/lib/public_key/src/public_key.app.src index d5e1705827..60487946fa 100644 --- a/lib/public_key/src/public_key.app.src +++ b/lib/public_key/src/public_key.app.src @@ -4,7 +4,6 @@ {modules, [ public_key, pubkey_pem, - pubkey_crypto, pubkey_cert, pubkey_cert_records, 'OTP-PUB-KEY' diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src index 2eb5750923..c9d15b8747 100644 --- a/lib/public_key/src/public_key.appup.src +++ b/lib/public_key/src/public_key.appup.src @@ -1,6 +1,15 @@ %% -*- erlang -*- {"%VSN%", [ + {"0.7", + [ + {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []}, + {update, public_key, soft, soft_purge, soft_purge, []}, + {update, pubkey_pem, soft, soft_purge, soft_purge, []}, + {update, pubkey_cert_records, soft, soft_purge, soft_purge, []} + {update, pubkey_cert, soft, soft_purge, soft_purge, []} + ] + }, {"0.6", [ {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []}, @@ -22,6 +31,15 @@ } ], [ + {"0.7", + [ + {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []}, + {update, public_key, soft, soft_purge, soft_purge, []}, + {update, pubkey_pem, soft, soft_purge, soft_purge, []}, + {update, pubkey_cert_records, soft, soft_purge, soft_purge, []} + {update, pubkey_cert, soft, soft_purge, soft_purge, []} + ] + }, {"0.6", [ {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []}, diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 12354eee5d..68bf04eeff 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -23,239 +23,395 @@ -include("public_key.hrl"). --export([decode_private_key/1, decode_private_key/2, decode_dhparams/1, - decrypt_private/2, decrypt_private/3, encrypt_public/2, - encrypt_public/3, decrypt_public/2, decrypt_public/3, - encrypt_private/2, encrypt_private/3, gen_key/1, sign/2, sign/3, - verify_signature/3, verify_signature/4, verify_signature/5, - pem_to_der/1, pem_to_der/2, der_to_pem/2, - pkix_decode_cert/2, pkix_encode_cert/1, pkix_transform/2, - pkix_is_self_signed/1, pkix_is_fixed_dh_cert/1, +-export([pem_decode/1, pem_encode/1, + der_decode/2, der_encode/2, + pem_entry_decode/1, + pem_entry_decode/2, + pem_entry_encode/2, + pem_entry_encode/3, + pkix_decode_cert/2, pkix_encode/3, + encrypt_private/2, encrypt_private/3, + decrypt_private/2, decrypt_private/3, + encrypt_public/2, encrypt_public/3, + decrypt_public/2, decrypt_public/3, + sign/3, verify/4, + pkix_sign/2, pkix_verify/2, + pkix_is_self_signed/1, + pkix_is_fixed_dh_cert/1, + pkix_is_issuer/2, pkix_issuer_id/2, - pkix_is_issuer/2, pkix_normalize_general_name/1, + pkix_normalize_name/1, pkix_path_validation/3 ]). +%% Deprecated +-export([decode_private_key/1, decode_private_key/2, pem_to_der/1]). + +-deprecated({pem_to_der, 1, next_major_release}). +-deprecated({decode_private_key, 1, next_major_release}). +-deprecated({decode_private_key, 2, next_major_release}). + +-type rsa_public_key() :: #'RSAPublicKey'{}. +-type rsa_private_key() :: #'RSAPrivateKey'{}. +-type dsa_private_key() :: #'DSAPrivateKey'{}. +-type dsa_public_key() :: {integer(), #'Dss-Parms'{}}. +-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' + | 'rsa_no_padding'. +-type public_crypt_options() :: [{rsa_pad, rsa_padding()}]. +-type rsa_digest_type() :: 'md5' | 'sha'. +-type dss_digest_type() :: 'none' | 'sha'. + +-define(UINT32(X), X:32/unsigned-big-integer). + %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- -%% Function: decode_private_key(KeyInfo [,Password]) -> -%% {ok, PrivateKey} | {error, Reason} -%% -%% KeyInfo = {Type, der_bin(), ChipherInfo} - as returned from -%% pem_to_der/[1,2] for private keys -%% Type = rsa_private_key | dsa_private_key -%% ChipherInfo = opaque() | no_encryption +-spec pem_decode(binary()) -> [pem_entry()]. +%% +%% Description: Decode PEM binary data and return +%% entries as asn1 der encoded entities. +%%-------------------------------------------------------------------- +pem_decode(PemBin) when is_binary(PemBin) -> + pubkey_pem:decode(PemBin). + +%%-------------------------------------------------------------------- +-spec pem_encode([pem_entry()]) -> binary(). %% -%% Description: Decodes an asn1 der encoded private key. +%% Description: Creates a PEM binary. %%-------------------------------------------------------------------- -decode_private_key(KeyInfo) -> - decode_private_key(KeyInfo, no_passwd). +pem_encode(PemEntries) when is_list(PemEntries) -> + iolist_to_binary(pubkey_pem:encode(PemEntries)). -decode_private_key(KeyInfo = {rsa_private_key, _, _}, Password) -> - DerEncoded = pubkey_pem:decode_key(KeyInfo, Password), - 'OTP-PUB-KEY':decode('RSAPrivateKey', DerEncoded); -decode_private_key(KeyInfo = {dsa_private_key, _, _}, Password) -> - DerEncoded = pubkey_pem:decode_key(KeyInfo, Password), - 'OTP-PUB-KEY':decode('DSAPrivateKey', DerEncoded). +%%-------------------------------------------------------------------- +-spec pem_entry_decode(pem_entry(), [string()]) -> term(). +% +%% Description: Decodes a pem entry. pem_decode/1 returns a list of +%% pem entries. +%%-------------------------------------------------------------------- +pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type), + is_binary(Der) -> + der_decode(Asn1Type, Der). +pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type), + is_binary(Der) -> + der_decode(Asn1Type, Der); +pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry, + Password) when is_atom(Asn1Type), + is_binary(CryptDer), + is_list(Cipher), + is_binary(Salt), + erlang:byte_size(Salt) == 8 + -> + Der = pubkey_pem:decipher(PemEntry, Password), + der_decode(Asn1Type, Der). +%%-------------------------------------------------------------------- +-spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry(). +-spec pem_entry_encode(pki_asn1_type(), term(), + {{Cipher :: string(), Salt :: binary()}, string()}) -> + pem_entry(). +% +%% Description: Creates a pem entry that can be feed to pem_encode/1. +%%-------------------------------------------------------------------- +pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) -> + Der = der_encode(Asn1Type, Entity), + {Asn1Type, Der, not_encrypted}. +pem_entry_encode(Asn1Type, Entity, + {{Cipher, Salt}= CipherInfo, Password}) when is_atom(Asn1Type), + is_list(Cipher), + is_binary(Salt), + erlang:byte_size(Salt) == 8, + is_list(Password)-> + Der = der_encode(Asn1Type, Entity), + DecryptDer = pubkey_pem:cipher(Der, CipherInfo, Password), + {Asn1Type, DecryptDer, CipherInfo}. %%-------------------------------------------------------------------- -%% Function: decode_dhparams(DhParamInfo) -> -%% {ok, DhParams} | {error, Reason} +-spec der_decode(asn1_type(), der_encoded()) -> term(). %% -%% DhParamsInfo = {Type, der_bin(), ChipherInfo} - as returned from -%% pem_to_der/[1,2] for DH parameters. -%% Type = dh_params -%% ChipherInfo = opaque() | no_encryption -%% -%% Description: Decodes an asn1 der encoded DH parameters. +%% Description: Decodes a public key asn1 der encoded entity. %%-------------------------------------------------------------------- -decode_dhparams({dh_params, DerEncoded, not_encrypted}) -> - 'OTP-PUB-KEY':decode('DHParameter', DerEncoded). +der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) -> + try + {ok, Decoded} = 'OTP-PUB-KEY':decode(Asn1Type, Der), + Decoded + catch + error:{badmatch, {error, _}} = Error -> + erlang:error(Error) + end. %%-------------------------------------------------------------------- -%% Function: decrypt_private(CipherText, Key) -> -%% decrypt_private(CipherText, Key, Options) -> PlainTex -%% decrypt_public(CipherText, Key) -> -%% decrypt_public(CipherText, Key, Options) -> PlainTex +-spec der_encode(asn1_type(), term()) -> der_encoded(). %% -%% CipherText = binary() -%% Key = rsa_key() -%% PlainText = binary() +%% Description: Encodes a public key entity with asn1 DER encoding. +%%-------------------------------------------------------------------- +der_encode(Asn1Type, Entity) when is_atom(Asn1Type) -> + try + {ok, Encoded} = 'OTP-PUB-KEY':encode(Asn1Type, Entity), + iolist_to_binary(Encoded) + catch + error:{badmatch, {error, _}} = Error -> + erlang:error(Error) + end. + +%%-------------------------------------------------------------------- +-spec pkix_decode_cert(der_encoded(), plain | otp) -> + #'Certificate'{} | #'OTPCertificate'{}. %% -%% Description: Decrypts <CipherText>. +%% Description: Decodes an asn1 der encoded pkix certificate. The otp +%% option will use the customized asn1 specification OTP-PKIX.asn1 for +%% decoding and also recursively decode most of the standard +%% extensions. +%% -------------------------------------------------------------------- +pkix_decode_cert(DerCert, plain) when is_binary(DerCert) -> + der_decode('Certificate', DerCert); +pkix_decode_cert(DerCert, otp) when is_binary(DerCert) -> + try + {ok, #'OTPCertificate'{}= Cert} = + pubkey_cert_records:decode_cert(DerCert), + Cert + catch + error:{badmatch, {error, _}} = Error -> + erlang:error(Error) + end. + +%%-------------------------------------------------------------------- +-spec pkix_encode(asn1_type(), term(), otp | plain) -> der_encoded(). +%% +%% Description: Der encodes a certificate or part of a certificate. +%% This function must be used for encoding certificates or parts of certificates +%% that are decoded with the otp format, whereas for the plain format this +%% function will only call der_encode/2. +%%-------------------------------------------------------------------- +pkix_encode(Asn1Type, Term, plain) when is_atom(Asn1Type) -> + der_encode(Asn1Type, Term); + +pkix_encode(Asn1Type, Term0, otp) when is_atom(Asn1Type) -> + Term = pubkey_cert_records:transform(Term0, encode), + der_encode(Asn1Type, Term). + +%%-------------------------------------------------------------------- +-spec decrypt_private(CipherText :: binary(), rsa_private_key()) -> + PlainText :: binary(). +-spec decrypt_private(CipherText :: binary(), rsa_private_key(), + public_crypt_options()) -> PlainText :: binary(). +%% +%% Description: Public key decryption using the private key. %%-------------------------------------------------------------------- decrypt_private(CipherText, Key) -> decrypt_private(CipherText, Key, []). -decrypt_private(CipherText, Key, Options) -> - Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), - pubkey_crypto:decrypt_private(CipherText, Key, Padding). -decrypt_public(CipherText, Key) -> - decrypt_public(CipherText, Key, []). -decrypt_public(CipherText, Key, Options) -> +decrypt_private(CipherText, + #'RSAPrivateKey'{modulus = N,publicExponent = E, + privateExponent = D}, + Options) when is_binary(CipherText), + is_list(Options) -> Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), - pubkey_crypto:decrypt_public(CipherText, Key, Padding). + crypto:rsa_private_decrypt(CipherText, + [crypto:mpint(E), crypto:mpint(N), + crypto:mpint(D)], Padding). %%-------------------------------------------------------------------- -%% Function: encrypt_public(PlainText, Key, Options) -> CipherText -%% encrypt_private(PlainText, Key, Options) -> CipherText -%% -%% PlainText = iolist() -%% Key = rsa_private_key() -%% CipherText = binary() +-spec decrypt_public(CipherText :: binary(), rsa_public_key()) -> + PlainText :: binary(). +-spec decrypt_public(CipherText :: binary(), rsa_public_key(), + public_crypt_options()) -> PlainText :: binary(). %% -%% Description: Encrypts <Plain> +%% Description: Public key decryption using the public key. %%-------------------------------------------------------------------- -encrypt_public(PlainText, Key) -> - encrypt_public(PlainText, Key, []). -encrypt_public(PlainText, Key, Options) -> - Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), - pubkey_crypto:encrypt_public(PlainText, Key, Padding). +decrypt_public(CipherText, Key) -> + decrypt_public(CipherText, Key, []). -encrypt_private(PlainText, Key) -> - encrypt_private(PlainText, Key, []). -encrypt_private(PlainText, Key, Options) -> - Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), - pubkey_crypto:encrypt_private(PlainText, Key, Padding). +decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E}, + Options) when is_binary(CipherText), is_list(Options) -> + decrypt_public(CipherText, N,E, Options); -%%-------------------------------------------------------------------- -%% Function: gen_key(Params) -> Keys -%% -%% Params = #'DomainParameters'{} - Currently only supported option -%% Keys = {PublicDHKey = integer(), PrivateDHKey = integer()} -%% -%% Description: Generates keys. Currently supports Diffie-Hellman keys. -%%-------------------------------------------------------------------- -gen_key(#'DHParameter'{prime = P, base = G}) when is_integer(P), - is_integer(G) -> - pubkey_crypto:gen_key(diffie_hellman, [P, G]). +decrypt_public(CipherText,#'RSAPrivateKey'{modulus = N, publicExponent = E}, + Options) when is_binary(CipherText), is_list(Options) -> + decrypt_public(CipherText, N,E, Options). %%-------------------------------------------------------------------- -%% Function: pem_to_der(CertSource) -> -%% pem_to_der(CertSource, Password) -> {ok, [Entry]} | -%% {error, Reason} +-spec encrypt_public(PlainText :: binary(), rsa_public_key()) -> + CipherText :: binary(). +-spec encrypt_public(PlainText :: binary(), rsa_public_key(), + public_crypt_options()) -> CipherText :: binary(). %% -%% CertSource = File | CertData -%% CertData = binary() -%% File = path() -%% Entry = {entry_type(), der_bin(), ChipherInfo} -%% ChipherInfo = opague() | no_encryption -%% der_bin() = binary() -%% entry_type() = cert | cert_req | rsa_private_key | dsa_private_key -%% dh_params -%% -%% Description: decode PEM binary data or a PEM file and return -%% entries as asn1 der encoded entities. Currently supported entry -%% types are certificates, certificate requests, rsa private keys and -%% dsa private keys. In the case of a key entry ChipherInfo will be -%% private keys and Diffie Hellam parameters .In the case of a key -%% entry ChipherInfo will be used by decode_private_key/2 if the key -%% is protected by a password. +%% Description: Public key encryption using the public key. %%-------------------------------------------------------------------- -pem_to_der(CertSource) -> - pem_to_der(CertSource, no_passwd). +encrypt_public(PlainText, Key) -> + encrypt_public(PlainText, Key, []). -pem_to_der(File, Password) when is_list(File) -> - pubkey_pem:read_file(File, Password); -pem_to_der(PemBin, Password) when is_binary(PemBin) -> - pubkey_pem:decode(PemBin, Password). +encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E}, + Options) when is_binary(PlainText), is_list(Options) -> + encrypt_public(PlainText, N,E, Options); -der_to_pem(File, TypeDerList) -> - pubkey_pem:write_file(File, TypeDerList). +encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E}, + Options) when is_binary(PlainText), is_list(Options) -> + encrypt_public(PlainText, N,E, Options). %%-------------------------------------------------------------------- -%% Function: pkix_decode_cert(BerCert, Type) -> {ok, Cert} | {error, Reason} +-spec encrypt_private(PlainText :: binary(), rsa_private_key()) -> + CipherText :: binary(). +-spec encrypt_private(PlainText :: binary(), rsa_private_key(), + public_crypt_options()) -> CipherText :: binary(). %% -%% BerCert = binary() -%% Type = plain | otp -%% Cert = certificate() -%% -%% Description: Decodes an asn1 ber encoded pkix certificate. -%% otp - Uses OTP-PKIX.asn1 to decode known extensions and -%% enhance the signature field in #'Certificate'{} and '#TBSCertificate'{}. +%% Description: Public key encryption using the private key. %%-------------------------------------------------------------------- -pkix_decode_cert(BinCert, Type) -> - pubkey_cert_records:decode_cert(BinCert, Type). +encrypt_private(PlainText, Key) -> + encrypt_private(PlainText, Key, []). + +encrypt_private(PlainText, #'RSAPrivateKey'{modulus = N, + publicExponent = E, + privateExponent = D}, + Options) when is_binary(PlainText), is_list(Options) -> + Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), + crypto:rsa_private_encrypt(PlainText, [crypto:mpint(E), + crypto:mpint(N), + crypto:mpint(D)], Padding). %%-------------------------------------------------------------------- -%% Function: pkix_encode_cert(Cert) -> {ok, binary()} | {error, Reason} +-spec sign(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(), + rsa_private_key() | + dsa_private_key()) -> Signature :: binary(). %% -%% Cert = #'Certificate'{} -%% -%% Description: Encodes a certificate record using asn1. +%% Description: Create digital signature. %%-------------------------------------------------------------------- -pkix_encode_cert(Cert) -> - pubkey_cert_records:encode_cert(Cert). +sign(PlainText, DigestType, #'RSAPrivateKey'{modulus = N, publicExponent = E, + privateExponent = D}) + when is_binary(PlainText), + DigestType == md5; + DigestType == sha -> + + crypto:rsa_sign(DigestType, sized_binary(PlainText), [crypto:mpint(E), + crypto:mpint(N), + crypto:mpint(D)]); + +sign(Digest, none, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) + when is_binary(Digest)-> + crypto:dss_sign(none, Digest, + [crypto:mpint(P), crypto:mpint(Q), + crypto:mpint(G), crypto:mpint(X)]); + +sign(PlainText, sha, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) + when is_binary(PlainText) -> + crypto:dss_sign(sized_binary(PlainText), + [crypto:mpint(P), crypto:mpint(Q), + crypto:mpint(G), crypto:mpint(X)]). + +%%-------------------------------------------------------------------- +-spec verify(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(), + Signature :: binary(), rsa_public_key() + | dsa_public_key()) -> boolean(). +%% +%% Description: Verifies a digital signature. +%%-------------------------------------------------------------------- +verify(PlainText, DigestType, Signature, + #'RSAPublicKey'{modulus = Mod, publicExponent = Exp}) + when is_binary (PlainText), DigestType == sha; DigestType == md5 -> + crypto:rsa_verify(DigestType, + sized_binary(PlainText), + sized_binary(Signature), + [crypto:mpint(Exp), crypto:mpint(Mod)]); + +verify(Digest, none, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g = G}}) + when is_integer(Key), is_binary(Digest), is_binary(Signature) -> + crypto:dss_verify(none, + Digest, + sized_binary(Signature), + [crypto:mpint(P), crypto:mpint(Q), + crypto:mpint(G), crypto:mpint(Key)]); +verify(PlainText, sha, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g = G}}) + when is_integer(Key), is_binary(PlainText), is_binary(Signature) -> + crypto:dss_verify(sized_binary(PlainText), + sized_binary(Signature), + [crypto:mpint(P), crypto:mpint(Q), + crypto:mpint(G), crypto:mpint(Key)]). %%-------------------------------------------------------------------- -%% Function: pkix_transform(CertPart, Op) -> TransformedCertPart -%% -%% CertPart = pkix part data -%% Op = encode | decode +-spec pkix_sign(#'OTPTBSCertificate'{}, + rsa_private_key() | dsa_private_key()) -> der_encoded(). %% -%% Description: Transform parts of a pkix certificate between 'plain' format -%% and the internal 'otp' format, see pkix_decode_cert/2. -%% Decode transforms from 'plain' to 'otp' and encode from 'otp' to 'plain' -%% format. +%% Description: Sign a pkix x.509 certificate. Returns the corresponding +%% der encoded 'Certificate'{} %%-------------------------------------------------------------------- -pkix_transform(CertPart, Op) -> - pubkey_cert_records:transform(CertPart, Op). +pkix_sign(#'OTPTBSCertificate'{signature = + #'SignatureAlgorithm'{algorithm = Alg} + = SigAlg} = TBSCert, Key) -> + + Msg = pkix_encode('OTPTBSCertificate', TBSCert, otp), + DigestType = pubkey_cert:digest_type(Alg), + Signature = sign(Msg, DigestType, Key), + Cert = #'OTPCertificate'{tbsCertificate= TBSCert, + signatureAlgorithm = SigAlg, + signature = {0, Signature} + }, + pkix_encode('OTPCertificate', Cert, otp). %%-------------------------------------------------------------------- -%% Function: pkix_path_validation(TrustedCert, CertChain, Options) -> -%% {ok, {{algorithm(), public_key(), public_key_params()} policy_tree()}} | -%% {error, Reason} +-spec pkix_verify(der_encoded(), rsa_public_key()| + dsa_public_key()) -> boolean(). %% -%% Description: Performs a bacis path validation according to RFC 3280. +%% Description: Verify pkix x.509 certificate signature. %%-------------------------------------------------------------------- -pkix_path_validation(TrustedCert, CertChain, Options) - when is_binary(TrustedCert) -> - {ok, OtpCert} = pkix_decode_cert(TrustedCert, otp), - pkix_path_validation(OtpCert, CertChain, Options); +pkix_verify(DerCert, {Key, #'Dss-Parms'{}} = DSAKey) + when is_binary(DerCert), is_integer(Key) -> + {DigestType, PlainText, Signature} = pubkey_cert:verify_data(DerCert), + verify(PlainText, DigestType, Signature, DSAKey); -pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options) - when is_list(CertChain), is_list(Options) -> - MaxPathDefault = length(CertChain), - ValidationState = pubkey_cert:init_validation_state(TrustedCert, - MaxPathDefault, - Options), - Fun = proplists:get_value(validate_extensions_fun, Options, - fun(Extensions, State, _, AccError) -> - {Extensions, State, AccError} - end), - Verify = proplists:get_value(verify, Options, true), - path_validation(CertChain, ValidationState, Fun, Verify). -%%-------------------------------------------------------------------- -%% Function: pkix_is_fixed_dh_cert(Cert) -> true | false +pkix_verify(DerCert, #'RSAPublicKey'{} = RSAKey) + when is_binary(DerCert) -> + {DigestType, PlainText, Signature} = pubkey_cert:verify_data(DerCert), + verify(PlainText, DigestType, Signature, RSAKey). + +%%-------------------------------------------------------------------- +-spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{}, + IssuerCert :: der_encoded()| + #'OTPCertificate'{}) -> boolean(). %% -%% Description: Checks if a Certificate is a fixed Diffie-Hellman Cert +%% Description: Checks if <IssuerCert> issued <Cert>. %%-------------------------------------------------------------------- -pkix_is_fixed_dh_cert(#'OTPCertificate'{} = OTPCert) -> - pubkey_cert:is_fixed_dh_cert(OTPCert); -pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) -> - {ok, OtpCert} = pkix_decode_cert(Cert, otp), - pkix_is_fixed_dh_cert(OtpCert). +pkix_is_issuer(Cert, IssuerCert) when is_binary(Cert) -> + OtpCert = pkix_decode_cert(Cert, otp), + pkix_is_issuer(OtpCert, IssuerCert); +pkix_is_issuer(Cert, IssuerCert) when is_binary(IssuerCert) -> + OtpIssuerCert = pkix_decode_cert(IssuerCert, otp), + pkix_is_issuer(Cert, OtpIssuerCert); +pkix_is_issuer(#'OTPCertificate'{tbsCertificate = TBSCert}, + #'OTPCertificate'{tbsCertificate = Candidate}) -> + pubkey_cert:is_issuer(TBSCert#'OTPTBSCertificate'.issuer, + Candidate#'OTPTBSCertificate'.subject). %%-------------------------------------------------------------------- -%% Function: pkix_is_self_signed(Cert) -> true | false +-spec pkix_is_self_signed(der_encoded()| #'OTPCertificate'{}) -> boolean(). %% %% Description: Checks if a Certificate is self signed. %%-------------------------------------------------------------------- pkix_is_self_signed(#'OTPCertificate'{} = OTPCert) -> pubkey_cert:is_self_signed(OTPCert); pkix_is_self_signed(Cert) when is_binary(Cert) -> - {ok, OtpCert} = pkix_decode_cert(Cert, otp), + OtpCert = pkix_decode_cert(Cert, otp), pkix_is_self_signed(OtpCert). - + %%-------------------------------------------------------------------- -%% Function: pkix_issuer_id(Cert) -> {ok, {SerialNr, Issuer}} | {error, Reason} -%% -%% Cert = asn1_der_encoded() | 'OTPCertificate'{} +-spec pkix_is_fixed_dh_cert(der_encoded()| #'OTPCertificate'{}) -> boolean(). %% +%% Description: Checks if a Certificate is a fixed Diffie-Hellman Cert. +%%-------------------------------------------------------------------- +pkix_is_fixed_dh_cert(#'OTPCertificate'{} = OTPCert) -> + pubkey_cert:is_fixed_dh_cert(OTPCert); +pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) -> + OtpCert = pkix_decode_cert(Cert, otp), + pkix_is_fixed_dh_cert(OtpCert). + +%%-------------------------------------------------------------------- +-spec pkix_issuer_id(der_encoded()| #'OTPCertificate'{}, + IssuedBy :: self | other) -> + {ok, {SerialNr :: integer(), + Issuer :: {rdnSequence, + [#'AttributeTypeAndValue'{}]}}} + | {error, Reason :: term()}. +% %% Description: Returns the issuer id. %%-------------------------------------------------------------------- pkix_issuer_id(#'OTPCertificate'{} = OtpCert, self) -> @@ -265,153 +421,113 @@ pkix_issuer_id(#'OTPCertificate'{} = OtpCert, other) -> pubkey_cert:issuer_id(OtpCert, other); pkix_issuer_id(Cert, Signed) when is_binary(Cert) -> - {ok, OtpCert} = pkix_decode_cert(Cert, otp), + OtpCert = pkix_decode_cert(Cert, otp), pkix_issuer_id(OtpCert, Signed). %%-------------------------------------------------------------------- -%% Function: pkix_is_issuer(Cert, IssuerCert) -> true | false -%% -%% Cert = asn1_der_encoded() | 'OTPCertificate'{} -%% IssuerCert = asn1_der_encoded() | 'OTPCertificate'{} +-spec pkix_normalize_name({rdnSequence, + [#'AttributeTypeAndValue'{}]}) -> + {rdnSequence, + [#'AttributeTypeAndValue'{}]}. %% -%% Description: Checks if <IssuerCert> issued <Cert>. +%% Description: Normalizes a issuer name so that it can be easily +%% compared to another issuer name. %%-------------------------------------------------------------------- -pkix_is_issuer(Cert, IssuerCert) when is_binary(Cert) -> - {ok, OtpCert} = pkix_decode_cert(Cert, otp), - pkix_is_issuer(OtpCert, IssuerCert); +pkix_normalize_name(Issuer) -> + pubkey_cert:normalize_general_name(Issuer). -pkix_is_issuer(Cert, IssuerCert) when is_binary(IssuerCert) -> - {ok, OtpIssuerCert} = pkix_decode_cert(IssuerCert, otp), - pkix_is_issuer(Cert, OtpIssuerCert); +%%-------------------------------------------------------------------- +-spec pkix_path_validation(der_encoded()| #'OTPCertificate'{} | unknown_ca, + CertChain :: [der_encoded()] , + Options :: list()) -> + {ok, {PublicKeyInfo :: term(), + PolicyTree :: term()}} | + {error, {bad_cert, Reason :: term()}}. +%% Description: Performs a basic path validation according to RFC 5280. +%%-------------------------------------------------------------------- +pkix_path_validation(unknown_ca, [Cert | Chain], Options0) -> + {VerifyFun, Userstat0} = + proplists:get_value(verify_fun, Options0, ?DEFAULT_VERIFYFUN), + Otpcert = pkix_decode_cert(Cert, otp), + Reason = {bad_cert, unknown_ca}, + try VerifyFun(Otpcert, Reason, Userstat0) of + {valid, Userstate} -> + Options = proplists:delete(verify_fun, Options0), + pkix_path_validation(Otpcert, Chain, [{verify_fun, + {VerifyFun, Userstate}}| Options]); + {fail, _} -> + {error, Reason} + catch + _:_ -> + {error, Reason} + end; +pkix_path_validation(TrustedCert, CertChain, Options) when + is_binary(TrustedCert) -> OtpCert = pkix_decode_cert(TrustedCert, + otp), pkix_path_validation(OtpCert, CertChain, Options); -pkix_is_issuer(#'OTPCertificate'{tbsCertificate = TBSCert}, - #'OTPCertificate'{tbsCertificate = Candidate}) -> - pubkey_cert:is_issuer(TBSCert#'OTPTBSCertificate'.issuer, - Candidate#'OTPTBSCertificate'.subject). - -%%-------------------------------------------------------------------- -%% Function: pkix_normalize_general_name(Issuer) -> -%% -%% Issuer = general_name() - see PKIX -%% -%% Description: Normalizes a general name so that it can be easily -%% compared to another genral name. -%%-------------------------------------------------------------------- -pkix_normalize_general_name(Issuer) -> - pubkey_cert:normalize_general_name(Issuer). +pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options) + when is_list(CertChain), is_list(Options) -> + MaxPathDefault = length(CertChain), + ValidationState = pubkey_cert:init_validation_state(TrustedCert, + MaxPathDefault, + Options), + path_validation(CertChain, ValidationState). %%-------------------------------------------------------------------- -%% Function:sign(Msg, Key) -> {ok, Signature} -%% sign(Msg, Key, KeyParams) -> {ok, Signature} -%% -%% Msg = binary() | #'TBSCertificate'{} -%% Key = private_key() -%% KeyParams = key_params() -%% Signature = binary() -%% -%% Description: Signs plaintext Msg or #TBSCertificate{}, in the later -%% case a der encoded "#Certificate{}" will be returned. +%%% Internal functions %%-------------------------------------------------------------------- -sign(Msg, #'RSAPrivateKey'{} = Key) when is_binary(Msg) -> - pubkey_crypto:sign(Msg, Key); - -sign(Msg, #'DSAPrivateKey'{} = Key) when is_binary(Msg) -> - pubkey_crypto:sign(Msg, Key); -sign(#'OTPTBSCertificate'{signature = #'SignatureAlgorithm'{algorithm = Alg} - = SigAlg} = TBSCert, Key) -> - Msg = pubkey_cert_records:encode_tbs_cert(TBSCert), - DigestType = pubkey_cert:digest_type(Alg), - Signature = pubkey_crypto:sign(DigestType, Msg, Key), - Cert = #'OTPCertificate'{tbsCertificate= TBSCert, - signatureAlgorithm = SigAlg, - signature = {0, Signature} - }, - pkix_encode_cert(Cert). +encrypt_public(PlainText, N, E, Options)-> + Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), + crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)], + Padding). -sign(DigestType, Msg, Key) -> - pubkey_crypto:sign(DigestType, Msg, Key). +decrypt_public(CipherText, N,E, Options) -> + Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), + crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)], + Padding). -%%-------------------------------------------------------------------- -%% Function: verify_signature(PlainText, DigestType, Signature, Key) -> -%% verify_signature(PlainText, DigestType, -%% Signature, Key, KeyParams) -> -%% verify_signature(DerCert, Key, KeyParams) -> -%% -%% PlainText = binary() -%% DigestType = md5 | sha -%% DerCert = asn1_der_encoded() -%% Signature = binary() -%% Key = public_key() -%% KeyParams = key_params() -%% Verified = boolean() -%% -%% Description: Verifies the signature <Signature>. -%%-------------------------------------------------------------------- -verify_signature(PlainText, DigestType, Signature, #'RSAPublicKey'{} = Key) - when is_binary(PlainText), is_binary(Signature), DigestType == sha; - DigestType == md5 -> - pubkey_crypto:verify(DigestType, PlainText, Signature, Key, undefined). - -verify_signature(PlainText, DigestType, Signature, #'RSAPublicKey'{} = Key, - KeyParams) - when is_binary(PlainText), is_binary(Signature), DigestType == sha; - DigestType == md5 -> - pubkey_crypto:verify(DigestType, PlainText, Signature, Key, KeyParams); -verify_signature(PlainText, sha, Signature, Key, #'Dss-Parms'{} = KeyParams) - when is_binary(PlainText), is_binary(Signature), is_integer(Key) -> - pubkey_crypto:verify(sha, PlainText, Signature, Key, KeyParams); -verify_signature(Hash, none, Signature, Key, KeyParams) -> - pubkey_crypto:verify(none, Hash, Signature, Key, KeyParams). - -verify_signature(DerCert, Key, #'Dss-Parms'{} = KeyParams) - when is_binary(DerCert), is_integer(Key) -> - pubkey_cert:verify_signature(DerCert, Key, KeyParams); -verify_signature(DerCert, #'RSAPublicKey'{} = Key, KeyParams) - when is_binary(DerCert) -> - pubkey_cert:verify_signature(DerCert, Key, KeyParams). -%%-------------------------------------------------------------------- -%%% Internal functions -%%-------------------------------------------------------------------- path_validation([], #path_validation_state{working_public_key_algorithm = Algorithm, working_public_key = PublicKey, working_public_key_parameters = PublicKeyParams, - valid_policy_tree = Tree, - acc_errors = AccErrors - }, _, _) -> - {ok, {{Algorithm, PublicKey, PublicKeyParams}, Tree, AccErrors}}; + valid_policy_tree = Tree + }) -> + {ok, {{Algorithm, PublicKey, PublicKeyParams}, Tree}}; path_validation([DerCert | Rest], ValidationState = #path_validation_state{ - max_path_length = Len}, - Fun, Verify) when Len >= 0 -> - try validate(DerCert, - ValidationState#path_validation_state{last_cert=Rest=:=[]}, - Fun, Verify) of + max_path_length = Len}) when Len >= 0 -> + try validate(DerCert, + ValidationState#path_validation_state{last_cert=Rest=:=[]}) of #path_validation_state{} = NewValidationState -> - path_validation(Rest, NewValidationState, Fun, Verify) + path_validation(Rest, NewValidationState) catch throw:Reason -> {error, Reason} end; -path_validation(_, _, _, true) -> - {error, {bad_cert, max_path_length_reached}}; +path_validation([DerCert | _] = Path, + #path_validation_state{user_state = UserState0, + verify_fun = VerifyFun} = + ValidationState) -> + Reason = {bad_cert, max_path_length_reached}, + OtpCert = pkix_decode_cert(DerCert, otp), + try VerifyFun(OtpCert, Reason, UserState0) of + {valid, UserState} -> + path_validation(Path, + ValidationState#path_validation_state{ + max_path_length = 0, + user_state = UserState}); + {fail, _} -> + {error, Reason} + catch + _:_ -> + {error, Reason} + end. -path_validation(_, #path_validation_state{working_public_key_algorithm - = Algorithm, - working_public_key = - PublicKey, - working_public_key_parameters - = PublicKeyParams, - valid_policy_tree = Tree, - acc_errors = AccErrors - }, _, false) -> - {ok, {{Algorithm, PublicKey, PublicKeyParams}, Tree, - [{bad_cert, max_path_length_reached}|AccErrors]}}. validate(DerCert, #path_validation_state{working_issuer_name = Issuer, working_public_key = Key, @@ -421,38 +537,50 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer, excluded_subtrees = Exclude, last_cert = Last, user_state = UserState0, - acc_errors = AccErr0} = - ValidationState0, ValidateExtensionFun, Verify) -> - {ok, OtpCert} = pkix_decode_cert(DerCert, otp), - %% All validate functions will throw {bad_cert, Reason} if they - %% fail and Verify = true if Verify = false errors - %% will be accumulated in the validationstate - AccErr1 = pubkey_cert:validate_time(OtpCert, AccErr0, Verify), - - AccErr2 = pubkey_cert:validate_issuer(OtpCert, Issuer, AccErr1, Verify), - - AccErr3 = pubkey_cert:validate_names(OtpCert, Permit, Exclude, Last, - AccErr2, Verify), - AccErr4 = - pubkey_cert:validate_revoked_status(OtpCert, Verify, AccErr3), + verify_fun = VerifyFun} = + ValidationState0) -> + OtpCert = pkix_decode_cert(DerCert, otp), + + UserState1 = pubkey_cert:validate_time(OtpCert, UserState0, VerifyFun), + + UserState2 = pubkey_cert:validate_issuer(OtpCert, Issuer, UserState1, VerifyFun), + + UserState3 = pubkey_cert:validate_names(OtpCert, Permit, Exclude, Last, + UserState2,VerifyFun), + + UserState4 = pubkey_cert:validate_revoked_status(OtpCert, UserState3, VerifyFun), - {ValidationState1, UnknownExtensions0, AccErr5} = - pubkey_cert:validate_extensions(OtpCert, ValidationState0, Verify, - AccErr4), - %% We want the key_usage extension to be checked before we validate + {ValidationState1, UserState5} = + pubkey_cert:validate_extensions(OtpCert, ValidationState0, UserState4, + VerifyFun), + + %% We want the key_usage extension to be checked before we validate %% the signature. - AccErr6 = - pubkey_cert:validate_signature(OtpCert, DerCert, Key, KeyParams, - AccErr5, Verify), - - {UnknownExtensions, UserState, AccErr7} = - ValidateExtensionFun(UnknownExtensions0, UserState0, Verify, AccErr6), - - %% Check that all critical extensions have been handled - AccErr = - pubkey_cert:validate_unknown_extensions(UnknownExtensions, AccErr7, - Verify), + UserState = pubkey_cert:validate_signature(OtpCert, DerCert, + Key, KeyParams, UserState5, VerifyFun), ValidationState = - ValidationState1#path_validation_state{user_state = UserState, - acc_errors = AccErr}, + ValidationState1#path_validation_state{user_state = UserState}, pubkey_cert:prepare_for_next_cert(OtpCert, ValidationState). + +sized_binary(Binary) when is_binary(Binary) -> + Size = size(Binary), + <<?UINT32(Size), Binary/binary>>; +sized_binary(List) -> + sized_binary(list_to_binary(List)). + +%%-------------------------------------------------------------------- +%%% Deprecated functions +%%-------------------------------------------------------------------- +pem_to_der(CertSource) -> + {ok, Bin} = file:read_file(CertSource), + pubkey_pem:decode(Bin). + +decode_private_key(KeyInfo) -> + decode_private_key(KeyInfo, no_passwd). + +decode_private_key(KeyInfo = {'RSAPrivateKey', _, _}, Password) -> + DerEncoded = pubkey_pem:decode_key(KeyInfo, Password), + 'OTP-PUB-KEY':decode('RSAPrivateKey', DerEncoded); +decode_private_key(KeyInfo = {'DSAPrivateKey', _, _}, Password) -> + DerEncoded = pubkey_pem:decode_key(KeyInfo, Password), + 'OTP-PUB-KEY':decode('DSAPrivateKey', DerEncoded). diff --git a/lib/public_key/test/Makefile b/lib/public_key/test/Makefile index 5544339ff2..e20b903942 100644 --- a/lib/public_key/test/Makefile +++ b/lib/public_key/test/Makefile @@ -28,7 +28,7 @@ INCLUDES= -I. -I ../include # ---------------------------------------------------- MODULES= \ - pkey_test \ + erl_make_certs \ public_key_SUITE \ pkits_SUITE diff --git a/lib/public_key/test/pkey_test.erl b/lib/public_key/test/erl_make_certs.erl index 4cf20f0174..e31e5552d3 100644 --- a/lib/public_key/test/pkey_test.erl +++ b/lib/public_key/test/erl_make_certs.erl @@ -19,7 +19,7 @@ %% Create test certificates --module(pkey_test). +-module(erl_make_certs). -include_lib("public_key/include/public_key.hrl"). -export([make_cert/1, gen_rsa/1, verify_signature/3, write_pem/3]). @@ -34,7 +34,7 @@ %% version 3 %% subject [] list of the following content %% {name, Name} -%% {email, Email} +%% {email, Email} %% {city, City} %% {state, State} %% {org, Org} @@ -56,7 +56,7 @@ make_cert(Opts) -> SubjectPrivateKey = get_key(Opts), {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts), - Cert = public_key:sign(TBSCert, IssuerKey), + Cert = public_key:pkix_sign(TBSCert, IssuerKey), true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok {Cert, encode_key(SubjectPrivateKey)}. @@ -66,8 +66,9 @@ make_cert(Opts) -> %% @end %%-------------------------------------------------------------------- write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) -> - ok = public_key:der_to_pem(filename:join(Dir, FileName ++ ".pem"), [{cert, Cert, not_encrypted}]), - ok = public_key:der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]). + ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"), + [{'Certificate', Cert, not_encrypted}]), + ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]). %%-------------------------------------------------------------------- %% @doc Creates a rsa key (OBS: for testing only) @@ -94,18 +95,14 @@ gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) -> %% @spec (::binary(), ::tuple()) -> ::boolean() %% @end %%-------------------------------------------------------------------- -verify_signature(DerEncodedCert, DerKey, KeyParams) -> +verify_signature(DerEncodedCert, DerKey, _KeyParams) -> Key = decode_key(DerKey), case Key of #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} -> - public_key:verify_signature(DerEncodedCert, - #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}, - 'NULL'); + public_key:pkix_verify(DerEncodedCert, + #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}); #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} -> - public_key:verify_signature(DerEncodedCert, Y, #'Dss-Parms'{p=P, q=Q, g=G}); - - _ -> - public_key:verify_signature(DerEncodedCert, Key, KeyParams) + public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}}) end. %%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -132,59 +129,63 @@ decode_key(#'RSAPrivateKey'{} = Key,_) -> Key; decode_key(#'DSAPrivateKey'{} = Key,_) -> Key; -decode_key(Der = {_,_,_}, Pw) -> - {ok, Key} = public_key:decode_private_key(Der, Pw), - Key; -decode_key(FileOrDer, Pw) -> - {ok, [KeyInfo]} = public_key:pem_to_der(FileOrDer), +decode_key(PemEntry = {_,_,_}, Pw) -> + public_key:pem_entry_decode(PemEntry, Pw); +decode_key(PemBin, Pw) -> + [KeyInfo] = public_key:pem_decode(PemBin), decode_key(KeyInfo, Pw). encode_key(Key = #'RSAPrivateKey'{}) -> {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key), - {rsa_private_key, list_to_binary(Der), not_encrypted}; + {'RSAPrivateKey', list_to_binary(Der), not_encrypted}; encode_key(Key = #'DSAPrivateKey'{}) -> {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key), - {dsa_private_key, list_to_binary(Der), not_encrypted}. + {'DSAPrivateKey', list_to_binary(Der), not_encrypted}. make_tbs(SubjectKey, Opts) -> Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))), - {Issuer, IssuerKey} = issuer(Opts, SubjectKey), + + IssuerProp = proplists:get_value(issuer, Opts, true), + {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey), {Algo, Parameters} = sign_algorithm(IssuerKey, Opts), SignAlgo = #'SignatureAlgorithm'{algorithm = Algo, parameters = Parameters}, - + Subject = case IssuerProp of + true -> %% Is a Root Ca + Issuer; + _ -> + subject(proplists:get_value(subject, Opts),false) + end, + {#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1, signature = SignAlgo, issuer = Issuer, validity = validity(Opts), - subject = subject(proplists:get_value(subject, Opts),false), + subject = Subject, subjectPublicKeyInfo = publickey(SubjectKey), version = Version, extensions = extensions(Opts) }, IssuerKey}. -issuer(Opts, SubjectKey) -> - IssuerProp = proplists:get_value(issuer, Opts, true), - case IssuerProp of - true -> %% Self signed - {subject(proplists:get_value(subject, Opts), true), SubjectKey}; - {Issuer, IssuerKey} when is_binary(Issuer) -> - {issuer_der(Issuer), decode_key(IssuerKey)}; - {File, IssuerKey} when is_list(File) -> - {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File), - {issuer_der(Cert), decode_key(IssuerKey)} - end. +issuer(true, Opts, SubjectKey) -> + %% Self signed + {subject(proplists:get_value(subject, Opts), true), SubjectKey}; +issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) -> + {issuer_der(Issuer), decode_key(IssuerKey)}; +issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) -> + {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File), + {issuer_der(Cert), decode_key(IssuerKey)}. issuer_der(Issuer) -> - {ok, Decoded} = public_key:pkix_decode_cert(Issuer, otp), + Decoded = public_key:pkix_decode_cert(Issuer, otp), #'OTPCertificate'{tbsCertificate=Tbs} = Decoded, #'OTPTBSCertificate'{subject=Subject} = Tbs, Subject. -subject(undefined, IsCA) -> - User = if IsCA -> "CA"; true -> os:getenv("USER") end, +subject(undefined, IsRootCA) -> + User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end, Opts = [{email, User ++ "@erlang.org"}, {name, User}, {city, "Stockholm"}, @@ -410,3 +411,11 @@ extended_gcd(A, B) -> {X, Y} = extended_gcd(B, N), {Y, X-Y*(A div B)} end. + +pem_to_der(File) -> + {ok, PemBin} = file:read_file(File), + public_key:pem_decode(PemBin). + +der_to_pem(File, Entries) -> + PemBin = public_key:pem_encode(Entries), + file:write_file(File, PemBin). diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl index 5d58b39e26..1d75e1aed2 100644 --- a/lib/public_key/test/pkits_SUITE.erl +++ b/lib/public_key/test/pkits_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2010. 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 @@ -187,9 +187,9 @@ run([],_) -> ok. read_certs(Test) -> File = test_file(Test), %% io:format("Read ~p ",[File]), - {ok, Ders} = public_key:pem_to_der(File), + Ders = erl_make_certs:pem_to_der(File), %% io:format("Ders ~p ~n",[length(Ders)]), - [Cert || {cert,Cert,not_encrypted} <- Ders]. + [Cert || {'Certificate', Cert, not_encrypted} <- Ders]. test_file(Test) -> file(?CONV, lists:append(string:tokens(Test, " -")) ++ ".pem"). diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl index dc1015969a..46b8c3db8b 100644 --- a/lib/public_key/test/public_key_SUITE.erl +++ b/lib/public_key/test/public_key_SUITE.erl @@ -101,13 +101,12 @@ all(doc) -> all(suite) -> [app, - dh, - pem_to_der, - decode_private_key, + pk_decode_encode, encrypt_decrypt, sign_verify, pkix, - pkix_path_validation + pkix_path_validation, + deprecated ]. %% Test cases starts here. @@ -120,85 +119,100 @@ app(suite) -> app(Config) when is_list(Config) -> ok = test_server:app_test(public_key). -dh(doc) -> - "Test diffie-hellman functions file is ok"; -dh(suite) -> +pk_decode_encode(doc) -> + ["Tests pem_decode/1, pem_encode/1, " + "der_decode/2, der_encode/2, " + "pem_entry_decode/1, pem_entry_decode/2," + "pem_entry_encode/2, pem_entry_encode/3."]; + +pk_decode_encode(suite) -> []; -dh(Config) when is_list(Config) -> +pk_decode_encode(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), - {ok,[DerDHparams = {dh_params, _, _}]} = - public_key:pem_to_der(filename:join(Datadir, "dh.pem")), - {ok, DHps = #'DHParameter'{prime=P,base=G}} = public_key:decode_dhparams(DerDHparams), - DHKeys = {Private,_Public} = public_key:gen_key(DHps), - test_server:format("DHparams = ~p~nDH Keys~p~n", [DHps, DHKeys]), - {_Private,_Public2} = pubkey_crypto:gen_key(diffie_hellman, [crypto:erlint(Private), P, G]), - ok. + + [{'DSAPrivateKey', DerDSAKey, not_encrypted} = Entry0 ] = + erl_make_certs:pem_to_der(filename:join(Datadir, "dsa.pem")), + + DSAKey = public_key:der_decode('DSAPrivateKey', DerDSAKey), + + DSAKey = public_key:pem_entry_decode(Entry0), + + [{'RSAPrivateKey', DerRSAKey, not_encrypted} = Entry1 ] = + erl_make_certs:pem_to_der(filename:join(Datadir, "client_key.pem")), + + RSAKey0 = public_key:der_decode('RSAPrivateKey', DerRSAKey), + + RSAKey0 = public_key:pem_entry_decode(Entry1), + + [{'RSAPrivateKey', _, {_,_}} = Entry2] = + erl_make_certs:pem_to_der(filename:join(Datadir, "rsa.pem")), + true = check_entry_type(public_key:pem_entry_decode(Entry2, "abcd1234"), + 'RSAPrivateKey'), -pem_to_der(doc) -> - ["Check that supported PEM files are decoded into the expected entry type"]; -pem_to_der(suite) -> - []; -pem_to_der(Config) when is_list(Config) -> - Datadir = ?config(data_dir, Config), - {ok,DSAKey =[{dsa_private_key, _, not_encrypted}]} = - public_key:pem_to_der(filename:join(Datadir, "dsa.pem")), - {ok,[{rsa_private_key, _, _}]} = - public_key:pem_to_der(filename:join(Datadir, "client_key.pem")), - {ok, [{rsa_private_key, _, _}]} = - public_key:pem_to_der(filename:join(Datadir, "rsa.pem")), - {ok,[{rsa_private_key, _, _}]} = - public_key:pem_to_der(filename:join(Datadir, "rsa.pem"), "abcd1234"), - {ok, Bin0} = file:read_file(filename:join(Datadir, "rsa.pem")), - {ok, [{rsa_private_key, _, _}]} = public_key:pem_to_der(Bin0, "abcd1234"), - - {ok,[{dh_params, _, _}]} = - public_key:pem_to_der(filename:join(Datadir, "dh.pem")), - {ok,[{cert, _, not_encrypted}]} = - public_key:pem_to_der(filename:join(Datadir, "client_cert.pem")), - {ok,[{cert_req, _, _}]} = - public_key:pem_to_der(filename:join(Datadir, "req.pem")), - {ok, Certs = [{cert, _, _}, {cert, _, _}]} = - public_key:pem_to_der(filename:join(Datadir, "cacerts.pem")), - - {ok, Bin1} = file:read_file(filename:join(Datadir, "cacerts.pem")), - {ok, [{cert, _, _}, {cert, _, _}]} = public_key:pem_to_der(Bin1), - - ok = public_key:der_to_pem(filename:join(Datadir, "wcacerts.pem"), Certs), - ok = public_key:der_to_pem(filename:join(Datadir, "wdsa.pem"), DSAKey), + Salt0 = crypto:rand_bytes(8), + Entry3 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey0, + {{"DES-EDE3-CBC", Salt0}, "1234abcd"}), + + RSAKey0 = public_key:pem_entry_decode(Entry3,"1234abcd"), - {ok, Certs} = public_key:pem_to_der(filename:join(Datadir, "wcacerts.pem")), - {ok, DSAKey} = public_key:pem_to_der(filename:join(Datadir, "wdsa.pem")), + Des3KeyFile = filename:join(Datadir, "des3_client_key.pem"), - ok. -%%-------------------------------------------------------------------- -decode_private_key(doc) -> - ["Check that private keys are decode to the expected key type."]; -decode_private_key(suite) -> - []; -decode_private_key(Config) when is_list(Config) -> - Datadir = ?config(data_dir, Config), - {ok,[DsaKey = {dsa_private_key, _DsaKey, _}]} = - public_key:pem_to_der(filename:join(Datadir, "dsa.pem")), - {ok,[RsaKey = {rsa_private_key, _RsaKey,_}]} = - public_key:pem_to_der(filename:join(Datadir, "client_key.pem")), - {ok,[ProtectedRsaKey1 = {rsa_private_key, _ProtectedRsaKey1,_}]} = - public_key:pem_to_der(filename:join(Datadir, "rsa.pem"), "abcd1234"), - {ok,[ProtectedRsaKey2 = {rsa_private_key, _ProtectedRsaKey2,_}]} = - public_key:pem_to_der(filename:join(Datadir, "rsa.pem")), + erl_make_certs:der_to_pem(Des3KeyFile, [Entry3]), - {ok, #'DSAPrivateKey'{}} = public_key:decode_private_key(DsaKey), - {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(RsaKey), - {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey1), - {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey2, "abcd1234"), + [{'RSAPrivateKey', _, {"DES-EDE3-CBC", Salt0}}] = erl_make_certs:pem_to_der(Des3KeyFile), + + Salt1 = crypto:rand_bytes(8), + Entry4 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey0, + {{"DES-CBC", Salt1}, "4567efgh"}), + + + DesKeyFile = filename:join(Datadir, "des_client_key.pem"), + + erl_make_certs:der_to_pem(DesKeyFile, [Entry4]), + + [{'RSAPrivateKey', _, {"DES-CBC", Salt1}} =Entry5] = erl_make_certs:pem_to_der(DesKeyFile), + + + true = check_entry_type(public_key:pem_entry_decode(Entry5, "4567efgh"), + 'RSAPrivateKey'), + + [{'DHParameter', DerDH, not_encrypted} = Entry6] = + erl_make_certs:pem_to_der(filename:join(Datadir, "dh.pem")), + + erl_make_certs:der_to_pem(filename:join(Datadir, "new_dh.pem"), [Entry6]), + + DHParameter = public_key:der_decode('DHParameter', DerDH), + DHParameter = public_key:pem_entry_decode(Entry6), + + Entry6 = public_key:pem_entry_encode('DHParameter', DHParameter), + + [{'Certificate', DerCert, not_encrypted} = Entry7] = + erl_make_certs:pem_to_der(filename:join(Datadir, "client_cert.pem")), + + Cert = public_key:der_decode('Certificate', DerCert), + Cert = public_key:pem_entry_decode(Entry7), + + CertEntries = [{'Certificate', _, not_encrypted} = CertEntry0, + {'Certificate', _, not_encrypted} = CertEntry1] = + erl_make_certs:pem_to_der(filename:join(Datadir, "cacerts.pem")), + + ok = erl_make_certs:der_to_pem(filename:join(Datadir, "wcacerts.pem"), CertEntries), + ok = erl_make_certs:der_to_pem(filename:join(Datadir, "wdsa.pem"), [Entry0]), + + NewCertEntries = erl_make_certs:pem_to_der(filename:join(Datadir, "wcacerts.pem")), + true = lists:member(CertEntry0, NewCertEntries), + true = lists:member(CertEntry1, NewCertEntries), + [Entry0] = erl_make_certs:pem_to_der(filename:join(Datadir, "wdsa.pem")), ok. + %%-------------------------------------------------------------------- encrypt_decrypt(doc) -> [""]; encrypt_decrypt(suite) -> []; encrypt_decrypt(Config) when is_list(Config) -> - {PrivateKey, _DerKey} = pkey_test:gen_rsa(64), + {PrivateKey, _DerKey} = erl_make_certs:gen_rsa(64), #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} = PrivateKey, PublicKey = #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}, Msg = list_to_binary(lists:duplicate(5, "Foo bar 100")), @@ -219,69 +233,81 @@ sign_verify(suite) -> []; sign_verify(Config) when is_list(Config) -> %% Make cert signs and validates the signature using RSA and DSA - Ca = {_, CaKey} = pkey_test:make_cert([]), - {ok, PrivateRSA = #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp}} = - public_key:decode_private_key(CaKey), + Ca = {_, CaKey} = erl_make_certs:make_cert([]), + PrivateRSA = #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} = + public_key:pem_entry_decode(CaKey), - CertInfo = {Cert1,CertKey1} = pkey_test:make_cert([{key, dsa}, {issuer, Ca}]), + CertInfo = {Cert1,CertKey1} = erl_make_certs:make_cert([{key, dsa}, {issuer, Ca}]), PublicRSA = #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}, - true = public_key:verify_signature(Cert1, PublicRSA, undefined), + true = public_key:pkix_verify(Cert1, PublicRSA), - {Cert2,_CertKey} = pkey_test:make_cert([{issuer, CertInfo}]), + {Cert2,_CertKey} = erl_make_certs:make_cert([{issuer, CertInfo}]), - {ok, #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y, x=_X}} = - public_key:decode_private_key(CertKey1), - true = public_key:verify_signature(Cert2, Y, #'Dss-Parms'{p=P, q=Q, g=G}), + #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y, x=_X} = + public_key:pem_entry_decode(CertKey1), + true = public_key:pkix_verify(Cert2, {Y, #'Dss-Parms'{p=P, q=Q, g=G}}), %% RSA sign Msg0 = lists:duplicate(5, "Foo bar 100"), Msg = list_to_binary(Msg0), - RSASign = public_key:sign(sha, Msg0, PrivateRSA), - RSASign = public_key:sign(Msg, PrivateRSA), - true = public_key:verify_signature(Msg, sha, RSASign, PublicRSA), - false = public_key:verify_signature(<<1:8, Msg/binary>>, sha, RSASign, PublicRSA), - false = public_key:verify_signature(Msg, sha, <<1:8, RSASign/binary>>, PublicRSA), - RSASign = public_key:sign(sha, Msg, PrivateRSA), - - RSASign1 = public_key:sign(md5, Msg, PrivateRSA), - true = public_key:verify_signature(Msg, md5, RSASign1, PublicRSA), + + RSASign = public_key:sign(Msg0, sha, PrivateRSA), + RSASign = public_key:sign(Msg, sha, PrivateRSA), + true = public_key:verify(Msg, sha, RSASign, PublicRSA), + false = public_key:verify(<<1:8, Msg/binary>>, sha, RSASign, PublicRSA), + false = public_key:verify(Msg, sha, <<1:8, RSASign/binary>>, PublicRSA), + + RSASign1 = public_key:sign(Msg, md5, PrivateRSA), + true = public_key:verify(Msg, md5, RSASign1, PublicRSA), %% DSA sign Datadir = ?config(data_dir, Config), - {ok,[DsaKey = {dsa_private_key, _, _}]} = - public_key:pem_to_der(filename:join(Datadir, "dsa.pem")), - {ok, DSAPrivateKey} = public_key:decode_private_key(DsaKey), + [DsaKey = {'DSAPrivateKey', _, _}] = + erl_make_certs:pem_to_der(filename:join(Datadir, "dsa.pem")), + DSAPrivateKey = public_key:pem_entry_decode(DsaKey), #'DSAPrivateKey'{p=P1, q=Q1, g=G1, y=Y1, x=_X1} = DSAPrivateKey, - DSASign = public_key:sign(Msg, DSAPrivateKey), + DSASign = public_key:sign(Msg, sha, DSAPrivateKey), DSAPublicKey = Y1, DSAParams = #'Dss-Parms'{p=P1, q=Q1, g=G1}, - true = public_key:verify_signature(Msg, sha, DSASign, DSAPublicKey, DSAParams), - false = public_key:verify_signature(<<1:8, Msg/binary>>, sha, DSASign, DSAPublicKey, DSAParams), - false = public_key:verify_signature(Msg, sha, <<1:8, DSASign/binary>>, DSAPublicKey, DSAParams), + true = public_key:verify(Msg, sha, DSASign, {DSAPublicKey, DSAParams}), + false = public_key:verify(<<1:8, Msg/binary>>, sha, DSASign, + {DSAPublicKey, DSAParams}), + false = public_key:verify(Msg, sha, <<1:8, DSASign/binary>>, + {DSAPublicKey, DSAParams}), + + Digest = crypto:sha(Msg), + DigestSign = public_key:sign(Digest, none, DSAPrivateKey), + true = public_key:verify(Digest, none, DigestSign, {DSAPublicKey, DSAParams}), + <<_:8, RestDigest/binary>> = Digest, + false = public_key:verify(<<1:8, RestDigest/binary>>, none, DigestSign, + {DSAPublicKey, DSAParams}), + false = public_key:verify(Digest, none, <<1:8, DigestSign/binary>>, + {DSAPublicKey, DSAParams}), ok. - +%%-------------------------------------------------------------------- pkix(doc) -> "Misc pkix tests not covered elsewhere"; pkix(suite) -> []; pkix(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), - {ok,Certs0} = public_key:pem_to_der(filename:join(Datadir, "cacerts.pem")), - {ok,Certs1} = public_key:pem_to_der(filename:join(Datadir, "client_cert.pem")), - TestTransform = fun({cert, CertDer, not_encrypted}) -> - {ok, PlainCert} = public_key:pkix_decode_cert(CertDer, plain), - {ok, OtpCert} = public_key:pkix_decode_cert(CertDer, otp), - CertDer = public_key:pkix_encode_cert(OtpCert), - CertDer = public_key:pkix_encode_cert(PlainCert), - - OTPSubj = (OtpCert#'OTPCertificate'.tbsCertificate)#'OTPTBSCertificate'.subject, - Subj = public_key:pkix_transform(OTPSubj, encode), - {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj), - Subj2 = (PlainCert#'Certificate'.tbsCertificate)#'TBSCertificate'.subject, - {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj2), - OTPSubj = public_key:pkix_transform(Subj2, decode), + Certs0 = erl_make_certs:pem_to_der(filename:join(Datadir, "cacerts.pem")), + Certs1 = erl_make_certs:pem_to_der(filename:join(Datadir, "client_cert.pem")), + TestTransform = fun({'Certificate', CertDer, not_encrypted}) -> + PlainCert = public_key:pkix_decode_cert(CertDer, plain), + OtpCert = public_key:pkix_decode_cert(CertDer, otp), + CertDer = + public_key:pkix_encode('OTPCertificate', OtpCert, otp), + CertDer = + public_key:pkix_encode('Certificate', PlainCert, plain), + OTPTBS = OtpCert#'OTPCertificate'.tbsCertificate, + OTPSubj = OTPTBS#'OTPTBSCertificate'.subject, + DNEncoded = public_key:pkix_encode('Name', OTPSubj, otp), + PlainTBS = PlainCert#'Certificate'.tbsCertificate, + Subj2 = PlainTBS#'TBSCertificate'.subject, + DNEncoded = public_key:pkix_encode('Name', Subj2, plain), false = public_key:pkix_is_fixed_dh_cert(CertDer) end, @@ -290,26 +316,31 @@ pkix(Config) when is_list(Config) -> true = public_key:pkix_is_self_signed(element(2,hd(Certs0))), false = public_key:pkix_is_self_signed(element(2,hd(Certs1))), - CaIds = [element(2, public_key:pkix_issuer_id(Cert, self)) || {cert, Cert, _} <- Certs0], - {ok, IssuerId = {_, IssuerName}} = public_key:pkix_issuer_id(element(2,hd(Certs1)), other), + CaIds = [element(2, public_key:pkix_issuer_id(Cert, self)) || + {'Certificate', Cert, _} <- Certs0], + {ok, IssuerId = {_, _IssuerName}} = + public_key:pkix_issuer_id(element(2,hd(Certs1)), other), + true = lists:member(IssuerId, CaIds), %% Should be normalized allready - TestStr = {rdnSequence, [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"ERLANGCA"}}], - [{'AttributeTypeAndValue', {2,5,4,3},{printableString," erlang ca "}}]]}, - VerifyStr = {rdnSequence, [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlang ca"}}], - [{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlangca"}}]]}, - VerifyStr = public_key:pkix_normalize_general_name(TestStr), + TestStr = {rdnSequence, + [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"ERLANGCA"}}], + [{'AttributeTypeAndValue', {2,5,4,3},{printableString," erlang ca "}}]]}, + VerifyStr = {rdnSequence, + [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlang ca"}}], + [{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlangca"}}]]}, + VerifyStr = public_key:pkix_normalize_name(TestStr), ok. - +%%-------------------------------------------------------------------- pkix_path_validation(doc) -> "Misc pkix tests not covered elsewhere"; pkix_path_validation(suite) -> []; pkix_path_validation(Config) when is_list(Config) -> CaK = {Trusted,_} = - pkey_test:make_cert([{key, dsa}, + erl_make_certs:make_cert([{key, dsa}, {subject, [ {name, "Public Key"}, {?'id-at-name', {printableString, "public_key"}}, @@ -320,26 +351,83 @@ pkix_path_validation(Config) when is_list(Config) -> {org_unit, "testing dep"} ]} ]), - ok = pkey_test:write_pem("./", "public_key_cacert", CaK), + ok = erl_make_certs:write_pem("./", "public_key_cacert", CaK), - CertK1 = {Cert1, _} = pkey_test:make_cert([{issuer, CaK}]), - CertK2 = {Cert2,_} = pkey_test:make_cert([{issuer, CertK1}, {digest, md5}, {extensions, false}]), - ok = pkey_test:write_pem("./", "public_key_cert", CertK2), + CertK1 = {Cert1, _} = erl_make_certs:make_cert([{issuer, CaK}]), + CertK2 = {Cert2,_} = erl_make_certs:make_cert([{issuer, CertK1}, + {digest, md5}, {extensions, false}]), + ok = erl_make_certs:write_pem("./", "public_key_cert", CertK2), {ok, _} = public_key:pkix_path_validation(Trusted, [Cert1], []), - {error, {bad_cert,invalid_issuer}} = public_key:pkix_path_validation(Trusted, [Cert2], []), - %%{error, {bad_cert,invalid_issuer}} = public_key:pkix_path_validation(Trusted, [Cert2], [{verify,false}]), + {error, {bad_cert,invalid_issuer}} = + public_key:pkix_path_validation(Trusted, [Cert2], []), {ok, _} = public_key:pkix_path_validation(Trusted, [Cert1, Cert2], []), {error, issuer_not_found} = public_key:pkix_issuer_id(Cert2, other), - CertK3 = {Cert3,_} = pkey_test:make_cert([{issuer, CertK1}, {extensions, [{basic_constraints, false}]}]), - {Cert4,_} = pkey_test:make_cert([{issuer, CertK3}]), - {error, E={bad_cert,missing_basic_constraint}} = + CertK3 = {Cert3,_} = erl_make_certs:make_cert([{issuer, CertK1}, + {extensions, [{basic_constraints, false}]}]), + {Cert4,_} = erl_make_certs:make_cert([{issuer, CertK3}]), + {error, {bad_cert,missing_basic_constraint}} = public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4], []), - - {ok, {_,_,[E]}} = public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4], [{verify,false}]), - % test_server:format("PV ~p ~n", [Result]), + VerifyFunAndState0 = {fun(_,{bad_cert, missing_basic_constraint}, UserState) -> + {valid, UserState}; + (_,{bad_cert, _} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState} + end, []}, + {ok, _} = + public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4], + [{verify_fun, VerifyFunAndState0}]), + + {error, {bad_cert, unknown_ca}} = + public_key:pkix_path_validation(unknown_ca, [Cert1, Cert3, Cert4], []), + + VerifyFunAndState1 = + {fun(_,{bad_cert, unknown_ca}, UserState) -> + {valid, UserState}; + (_,{bad_cert, _} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState} + end, []}, + + {ok, _} = + public_key:pkix_path_validation(unknown_ca, [Cert1], [{verify_fun, + VerifyFunAndState1}]), ok. + +%%-------------------------------------------------------------------- +deprecated(doc) -> + ["Check deprecated functions."]; +deprecated(suite) -> + []; +deprecated(Config) when is_list(Config) -> + Datadir = ?config(data_dir, Config), + [DsaKey = {'DSAPrivateKey', _DsaKey, _}] = + public_key:pem_to_der(filename:join(Datadir, "dsa.pem")), + [RsaKey = {'RSAPrivateKey', _RsaKey,_}] = + public_key:pem_to_der(filename:join(Datadir, "client_key.pem")), + [ProtectedRsaKey = {'RSAPrivateKey', _ProtectedRsaKey,_}] = + public_key:pem_to_der(filename:join(Datadir, "rsa.pem")), + + {ok, #'DSAPrivateKey'{}} = public_key:decode_private_key(DsaKey), + {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(RsaKey), + {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey, "abcd1234"), + ok. + +%%-------------------------------------------------------------------- + +check_entry_type(#'DSAPrivateKey'{}, 'DSAPrivateKey') -> + true; +check_entry_type(#'RSAPrivateKey'{}, 'RSAPrivateKey') -> + true; +check_entry_type(#'DHParameter'{}, 'DHParameter') -> + true; +check_entry_type(#'Certificate'{}, 'Certificate') -> + true; +check_entry_type(_,_) -> + false. diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index 4b3071a85b..f70209d891 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1,11 +1 @@ -PUBLIC_KEY_VSN = 0.7 - -TICKETS = OTP-8626 OTP-8649 - -#TICKETS_0.6 = OTP-7046 \ -# OTP-8553 -#TICKETS_0.5 = OTP-8372 -#TICKETS_0.4 = OTP-8250 -#TICKETS_0.3 = OTP-8100 OTP-8142 -#TICKETS_0.2 = OTP-7860 -#TICKETS_0.1 = OTP-7637
\ No newline at end of file +PUBLIC_KEY_VSN = 0.8 diff --git a/lib/reltool/test/Makefile b/lib/reltool/test/Makefile index 34781ae720..5109058797 100644 --- a/lib/reltool/test/Makefile +++ b/lib/reltool/test/Makefile @@ -74,7 +74,8 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) reltool.spec $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR) - $(INSTALL_PROGRAM) rtt $(INSTALL_PROGS) $(RELSYSDIR) + $(INSTALL_SCRIPT) rtt $(INSTALL_PROGS) $(RELSYSDIR) + $(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR) # chmod -f -R u+w $(RELSYSDIR) # @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk index f23a7e84a2..9e0bce1d01 100644 --- a/lib/reltool/vsn.mk +++ b/lib/reltool/vsn.mk @@ -1,28 +1 @@ -# This is an -*-makefile-*- file. -# %CopyrightBegin% -# -# Copyright Ericsson AB 2009-2010. 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% - RELTOOL_VSN = 0.5.4 - -TICKETS = OTP-8521 OTP-8590 -TICKETS_0_5_3 = OTP-8057 -TICKETS_0_5_2 = OTP-8254 -TICKETS_0_5_1 = OTP-8199 -TICKETS_0_5 = OTP-7949 -TICKETS_0_2_2 = OTP-7999 -TICKETS_2_2_1 = OTP-7840 -TICKETS_0_2 = OTP-7805 diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c index 482fcc0288..cd54f36af0 100644 --- a/lib/runtime_tools/c_src/trace_file_drv.c +++ b/lib/runtime_tools/c_src/trace_file_drv.c @@ -520,7 +520,7 @@ static int do_write(FILETYPE fd, unsigned char *buff, int siz) { */ static int my_write(TraceFileData *data, unsigned char *buff, int siz) { - int wrote, w; + int wrote; if (data->buff_siz - data->buff_pos >= siz) { memcpy(data->buff + data->buff_pos, buff, siz); diff --git a/lib/runtime_tools/src/inviso_autostart.erl b/lib/runtime_tools/src/inviso_autostart.erl index 134133ad1f..787292e244 100644 --- a/lib/runtime_tools/src/inviso_autostart.erl +++ b/lib/runtime_tools/src/inviso_autostart.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% Copyright Ericsson AB 2006-2010. 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 @@ -59,17 +59,10 @@ autostart(_AutoModArgs) -> case try_load_module(FileNames) of ok -> autostart_apply(M,F); + false -> % No such module available "inviso_autostart.config" end; - {ok,{gettia_asc,asc_file}} -> % Uggly hack to not have to change in GSN-CPS. - case try_load_module(["/tmp/DPE_COMMONLOG/gettia_asc", - "/tmp/DPE_COMMONLOG/gettia_overload"]) of - ok -> - autostart_apply(gettia_asc,asc_file); - false -> % No such module available - false - end; {ok,{M,F}} -> % Use M:F(node()) autostart_apply(M,F); {ok,no_autostart} -> diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile new file mode 100644 index 0000000000..873d395277 --- /dev/null +++ b/lib/runtime_tools/test/Makefile @@ -0,0 +1,65 @@ +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +MODULES = \ + runtime_tools_SUITE \ + inviso_testmodule1_foo \ + inviso_SUITE \ + dbg_SUITE \ + erts_alloc_config_SUITE + +ERL_FILES= $(MODULES:%=%.erl) + +TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) +INSTALL_PROGS= $(TARGET_FILES) + +EMAKEFILE=Emakefile + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/runtime_tools_test + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +ERL_MAKE_FLAGS += +ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include + +EBIN = . + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +make_emakefile: + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\ + > $(EMAKEFILE) + +tests debug opt: make_emakefile + erl $(ERL_MAKE_FLAGS) -make + +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) + rm -f core + +docs: + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + +release_tests_spec: make_emakefile + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) runtime_tools.spec $(ERL_FILES) $(RELSYSDIR) + $(INSTALL_DATA) $(EMAKEFILE) runtime_tools.cover $(RELSYSDIR) + chmod -f -R u+w $(RELSYSDIR) + @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + +release_docs_spec: diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl new file mode 100644 index 0000000000..ff96af5e86 --- /dev/null +++ b/lib/runtime_tools/test/dbg_SUITE.erl @@ -0,0 +1,901 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(dbg_SUITE). + +%% Test functions +-export([all/1, big/1, tiny/1, simple/1, message/1, distributed/1, + ip_port/1, file_port/1, file_port2/1, file_port_schedfix/1, + ip_port_busy/1, wrap_port/1, wrap_port_time/1, + with_seq_trace/1, dead_suspend/1, local_trace/1, + saved_patterns/1]). +-export([init_per_testcase/2, fin_per_testcase/2]). +-export([tracee1/1, tracee2/1]). +-export([dummy/0, exported/1]). + +-include("test_server.hrl"). +-define(default_timeout, ?t:minutes(1)). + +init_per_testcase(_Case, Config) -> + ?line Dog=test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +all(suite) -> [big, tiny, simple, message, distributed, + ip_port, file_port, file_port2, file_port_schedfix, + ip_port_busy, wrap_port, wrap_port_time, + with_seq_trace, dead_suspend, local_trace, saved_patterns]. + +big(suite) -> []; +big(doc) -> ["Rudimentary interface test"]; +big(Config) when is_list(Config) -> + ?line {ok,OldCurDir} = file:get_cwd(), + Datadir=?config(data_dir, Config), + Privdir=?config(priv_dir, Config), + ?line ok=file:set_cwd(Privdir), + try + %% make sure dbg is stopped (and returns correctly) + ?line ok = dbg:stop(), + + %% compile test module and make sure it is loaded. + ?line {ok,Mod} = compile:file(Datadir++"/dbg_test",[trace]), + ?line code:purge(dbg_test), + ?line {module, Mod}=code:load_file(dbg_test), + + %% run/debug a named test function. + ?line Pid = spawn_link(dbg_test, loop, [Config]), + ?line true = register(dbg_test_loop, Pid), + ?line {ok,_} = dbg:tracer(), + ?line {ok,[{matched, _node, 1}]} = dbg:p(dbg_test_loop, [m,p,c]), + ?line ok = dbg:c(dbg_test, test, [Config]), + ?line ok = dbg:i(), + ?line dbg_test_loop ! {dbg_test, stop}, + unregister(dbg_test_loop), + ?line ok = dbg:stop(), + + %% run/debug a Pid. + ?line Pid2=spawn_link(dbg_test,loop,[Config]), + ?line {ok,_} = dbg:tracer(), + ?line {ok,[{matched, _node, 1}]} = dbg:p(Pid2,[s,r,p]), + ?line ok = dbg:c(dbg_test, test, [Config]), + ?line ok = dbg:i(), + ?line Pid2 ! {dbg_test, stop}, + + ?line ok=file:set_cwd(OldCurDir) + after + ?line dbg:stop() + end, + ok. + + +tiny(suite) -> []; +tiny(doc) -> ["Rudimentary interface test"]; +tiny(Config) when is_list(Config) -> + ?line {ok,OldCurDir} = file:get_cwd(), + Datadir=?config(data_dir, Config), + Privdir=?config(priv_dir, Config), + ?line ok=file:set_cwd(Privdir), + try + %% compile test module and make sure it is loaded. + ?line {ok, Mod} = compile:file(Datadir++"/dbg_test",[trace]), + ?line code:purge(dbg_test), + ?line {module, Mod}=code:load_file(dbg_test), + + ?line Pid=spawn_link(dbg_test,loop,[Config]), + if + is_pid(Pid) -> + ?line dbg:tracer(), + ?line {ok,[{matched, _node, 1}]} = dbg:p(Pid,[s,r,m,p,c]), + ?line ok = dbg:c(dbg_test,test,[Config]), + ?line ok = dbg:i(), + ?line Pid ! {dbg_test, stop}; + true -> + ?line ok=file:set_cwd(OldCurDir), + ?t:fail("Could not spawn external test process.~n"), + failure + end + after + ?line ok = dbg:stop(), + ?line ok = file:set_cwd(OldCurDir) + end, + ok. + +simple(suite) -> + []; +simple(doc) -> + ["Simple interface test with own handler"]; +simple(Config) when is_list(Config) -> + try + ?line start(), + ?line dbg:p(self(),call), + ?line dbg:tp(dbg,ltp,[]), + ?line dbg:ltp(), + ?line stop(), + ?line S = self(), + ?line [{trace,S,call,{dbg,ltp,[]}}] = flush() + after + ?line dbg:stop() + end, + ok. + +message(suite) -> + []; +message(doc) -> + ["Simple interface test with pam code that appends a message"]; +message(Config) when is_list(Config) -> + ?line {ok, _} = start(), + try + ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + ?line {ok, X} = dbg:tp(dbg,ltp,[{'_',[],[{message, {self}}]}]), + ?line {value, {saved, Saved}} = lists:keysearch(saved, 1, X), + ?line {ok, Y} = dbg:tp(dbg,ln,Saved), + ?line {value, {saved, Saved}} = lists:keysearch(saved, 1, Y), + ?line ok = dbg:ltp(), + ?line ok = dbg:ln() + after + ?line stop() + end, + ?line S = self(), + ?line [{trace,S,call,{dbg,ltp,[]},S}, + {trace,S,call,{dbg,ln,[]},S}] = flush(), + ok. + +distributed(suite) -> + []; +distributed(doc) -> + ["Simple test of distributed tracing"]; +distributed(Config) when is_list(Config) -> + ?line {ok, _} = start(), + ?line Node = start_slave(), + try + ?line RexPid = rpc:call(Node, erlang, whereis, [rex]), + ?line RexPidList = pid_to_list(RexPid), + ?line {ok, Node} = dbg:n(Node), + ?line {ok, X} = dbg:p(all,call), + ?line {value, {matched, Node, _}} = lists:keysearch(Node, 2, X), + ?line {ok, Y} = dbg:p(RexPidList, s), + ?line {value, {matched, Node, 1}} = lists:keysearch(Node, 2, Y), + ?line {ok, Z} = dbg:tp(dbg,ltp,[]), + ?line {value, {matched, Node, 1}} = lists:keysearch(Node, 2, Z), + ?line dbg:cn(Node), + ?line dbg:tp(dbg,ln,[]), + ?line ok = rpc:call(Node, dbg, ltp, []), + ?line ok = rpc:call(Node, dbg, ln, []), + ?line ok = dbg:ln(), + ?line S = self(), + ?line {TraceSend, TraceCall} = + lists:partition(fun ({trace,RP,send,_,_}) when RP =:= RexPid -> true; + (_) -> false end, + flush()), + ?line [_|_] = TraceSend, + ?line [{trace,Pid,call,{dbg,ltp,[]}}, + {trace,S,call,{dbg,ln,[]}}] = TraceCall, + ?line Node = node(Pid), + %% + ?line stop() + after + ?line stop_slave(Node), + ?line stop() + end, + ok. + + +local_trace(suite) -> + []; +local_trace(doc) -> + ["Tests tracing of local function calls."]; +local_trace(Config) when is_list(Config) -> + ?line {ok, _} = start(), + try + ?line S = self(), + ?line %% Split "<X.Y.Z>" into {X, Y, Z} + ?line "<"++L1 = L = pid_to_list(S), + ?line NoDot = fun ($.) -> false; (_) -> true end, + ?line {LX,"."++L2} = lists:splitwith(NoDot, L1), + ?line {LY,"."++L3} = lists:splitwith(NoDot, L2), + ?line ">"++L4 = lists:reverse(L3), + ?line LZ = lists:reverse(L4), + ?line X = 0 = list_to_integer(LX), + ?line Y = list_to_integer(LY), + ?line Z = list_to_integer(LZ), + ?line XYZ = {X, Y, Z}, + ?line io:format("Self = ~w = ~w~n", [S,XYZ]), + ?line {ok, [{matched, _node, 1}]} = dbg:p(S,call), + ?line {ok, [{matched, _node, 1}]} = dbg:p(XYZ,call), + if Z =:= 0 -> + ?line {ok, [{matched, _node, 1}]} = dbg:p(Y,call); + true -> ok + end, + ?line {ok, [{matched, _node, 1}]} = dbg:p(L,call), + ?line {ok, _} = dbg:tpl(?MODULE,not_exported,[]), + ?line 4 = not_exported(2), + ?line [{trace,S,call,{?MODULE,not_exported,[2]}}] = flush(), + ?line {ok, _} = dbg:tp(?MODULE,exported,[]), + ?line 4 = ?MODULE:exported(2), + ?line [{trace,S,call,{?MODULE,exported,[2]}}, + {trace,S,call,{?MODULE,not_exported,[2]}}] = flush(), + ?line {ok, _} = dbg:ctpl(?MODULE), + ?line 4 = ?MODULE:exported(2), + ?line [{trace,S,call,{?MODULE,exported,[2]}}] = flush(), + ?line {ok, _} = dbg:tpl(?MODULE,not_exported,[]), + ?line {ok, _} = dbg:ctp(?MODULE), + ?line 4 = ?MODULE:exported(2), + ?line [] = flush(), + ?line {ok, _} = dbg:tpl(?MODULE,not_exported,x), + ?line catch ?MODULE:exported(x), + ?line [{trace,S,call,{dbg_SUITE,not_exported,[x]}}, + {trace,S,exception_from, + {dbg_SUITE,not_exported,1}, + {error,badarith}}] = flush() + after + ?line stop() + end, + ok. + +saved_patterns(suite) -> + []; +saved_patterns(doc) -> + ["Tests saving of match_spec's."]; +saved_patterns(Config) when is_list(Config) -> + ?line dbg:stop(), + ?line {ok,[{saved,1}]} = + dbg:tp(dbg,ctp,1,[{'_',[],[{message, blahonga}]}]), + ?line {ok,[{saved,2}]} = + dbg:tp(dbg,ctp,1,[{['_'],[],[{message, blahonga}]}]), + ?line Privdir=?config(priv_dir, Config), + ?line file:make_dir(Privdir), + ?line File = filename:join([Privdir, "blahonga.ms"]), + ?line dbg:wtp(File), + ?line dbg:stop(), + ?line dbg:ctp('_','_','_'), + ?line {ok, _} = start(), + try + ?line dbg:rtp(File), + ?line {ok,[{matched,_node,1},{saved,1}]} = dbg:tp(dbg,ltp,0,1), + ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + ?line dbg:ltp(), + ?line S = self(), + ?line [{trace,S,call,{dbg,ltp,[]},blahonga}] = flush() + after + ?line stop() + end, + ok. + + + +not_exported(N) -> + N * 2. + +exported(N) -> + not_exported(N). + +ip_port(suite) -> + []; +ip_port(doc) -> + ["Test tracing to IP port"]; +ip_port(Config) when is_list(Config) -> + ?line stop(), + ?line Port = dbg:trace_port(ip, 0), + ?line {ok, _} = dbg:tracer(port, Port), + try + ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + ?line {ok, X} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), + ?line {value, {saved, _Saved}} = lists:keysearch(saved, 1, X), + ?line {ok, Y} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), + ?line {value, {saved, _}} = lists:keysearch(saved, 1, Y), + ?line ok = dbg:ltp(), + ?line ok = dbg:ln(), + ?line {ok, IpPort} = dbg:trace_port_control(get_listen_port), + ?line io:format("IpPort = ~p~n", [IpPort]), + ?line dbg:trace_client(ip, IpPort, {fun myhandler/2, self()}), + ?line S = self(), + ?line [{trace,S,call,{dbg,ltp,[]},S}, + {trace,S,call,{dbg,ln,[]},hej}] = flush() + after + ?line stop() + end, + ok. + + + +ip_port_busy(suite) -> + []; +ip_port_busy(doc) -> + ["Test that the dbg server does not hang if the tracer don't start ", + "(OTP-3592)"]; +ip_port_busy(Config) when is_list(Config) -> + ?line stop(), + ?line Tracer = dbg:trace_port(ip, 4745), + ?line Port = Tracer(), + ?line {error, Reason} = dbg:tracer(port, Tracer), + try + ?line io:format("Error reason = ~p~n", [Reason]), + ?line true = port_close(Port) + after + ?line dbg:stop() + end, + ?line ok. + + + +file_port(suite) -> + []; +file_port(doc) -> + ["Test tracing to file port (simple)"]; +file_port(Config) when is_list(Config) -> + ?line stop(), + ?line {A,B,C} = erlang:now(), + ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++ + integer_to_list(B) ++ "-" ++ integer_to_list(C), + ?line FName = filename:join([?config(data_dir, Config), FTMP]), + ?line Port = dbg:trace_port(file, FName), + ?line {ok, _} = dbg:tracer(port, Port), + try + ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + ?line {ok, X} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), + ?line {value, {saved, _Saved}} = lists:keysearch(saved, 1, X), + ?line {ok, Y} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), + ?line {value, {saved, _}} = lists:keysearch(saved, 1, Y), + ?line ok = dbg:ltp(), + ?line ok = dbg:ln(), + ?line stop(), + ?line dbg:trace_client(file, FName, {fun myhandler/2, self()}), + ?line S = self(), + ?line [{trace,S,call,{dbg,ltp,[]},S}, + {trace,S,call,{dbg,ln,[]},hej}, + end_of_trace] = flush() + after + ?line stop(), + ?line file:delete(FName) + end, + ok. + +file_port2(suite) -> + []; +file_port2(doc) -> + ["Test tracing to file port with 'follow_file'"]; +file_port2(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skipped, "VxWorks NFS cache ruins it all."}; + _ -> + ?line stop(), + ?line {A,B,C} = erlang:now(), + ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ + "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C), + ?line FName = filename:join([?config(data_dir, Config), FTMP]), + %% Ok, lets try with flush and follow_file, not a chance on VxWorks + %% with NFS caching... + ?line Port2 = dbg:trace_port(file, FName), + ?line {ok, _} = dbg:tracer(port, Port2), + try + ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + ?line {ok, _} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), + ?line {ok, _} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), + ?line ok = dbg:ltp(), + ?line ok = dbg:flush_trace_port(), + ?line dbg:trace_client(follow_file, FName, + {fun myhandler/2, self()}), + ?line S = self(), + ?line [{trace,S,call,{dbg,ltp,[]},S}] = flush(), + ?line ok = dbg:ln(), + ?line ok = dbg:flush_trace_port(), + ?line receive after 1000 -> ok end, %% Polls every second... + ?line [{trace,S,call,{dbg,ln,[]},hej}] = flush(), + ?line stop(), + ?line [] = flush() + after + ?line stop(), + ?line file:delete(FName) + end, + ok + end. + +file_port_schedfix(suite) -> + []; +file_port_schedfix(doc) -> + ["Test that the scheduling timestamp fix for trace flag 'running' works."]; +file_port_schedfix(Config) when is_list(Config) -> + ?line case (catch erlang:system_info(smp_support)) of + true -> + {skip, "No schedule fix on SMP"}; + _ -> + try + file_port_schedfix1(Config) + after + dbg:stop() + end + end. +file_port_schedfix1(Config) when is_list(Config) -> + ?line stop(), + ?line {A,B,C} = erlang:now(), + ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ + "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C), + ?line FName = filename:join([?config(data_dir, Config), FTMP]), + %% + ?line Port = dbg:trace_port(file, {FName, wrap, ".wraplog", 8*1024, 4}), + ?line {ok, _} = dbg:tracer(port, Port), + ?line {ok,[{matched,_node,0}]} = dbg:p(new,[running,procs,send,timestamp]), + %% + %% Generate the trace data + %% + %% This starts 3 processes that sends a message to each other in a ring, + %% 4 laps. Prior to sending the message to the next in the ring, each + %% process send 8 messages to itself, just to generate some trace data, + %% and to lower the possibility that the trace log wraps just after + %% a schedule out message (which would not burden any process and hence + %% not show up in the result) + %% + %% The wrap file trace is used because it burns a lot of time when the + %% driver swaps files, a lot more than the regular file trace. The test + %% case is dimensioned so that the log fills two files and just starts + %% on the third (out of four wrap files). This gives two file swaps, + %% and there are three processes, so one process will NOT be burdened. + %% The criterion for trace success is then that the max process + %% execution time must not be more than twice the min process + %% execution time. Wallclock. A normal result is about 10 times more + %% without schedule in - schedule out compensation (OTP-3938). + %% + ?line ok = token_volleyball(3, 4, 8), + %% + ?line {ok,[{matched,_,_}]} = dbg:p(all, [clear]), + ?line stop(), + % Some debug code to run on all platforms, for finding the fault on genny + % Dont touch please /PaN + ?line io:format("Trace dump by PaN BEGIN~n"), + ?line dbg:trace_client(file,{FName, wrap, ".wraplog"},{fun(end_of_trace,Pid)-> Pid ! done; (Mesg,Pid) -> io:format("~w~n",[Mesg]),Pid end,self()}), + receive done -> ok end, + ?line io:format("Trace dump by PaN END~n"), + %% + %% Get the trace result + %% + ?line Tag = make_ref(), + ?line dbg:trace_client(file, {FName, wrap, ".wraplog"}, + {fun schedstat_handler/2, {self(), Tag, []}}), + ?line Result = + receive + {Tag, D} -> + lists:map( + fun({Pid, {A1, B1, C1}}) -> + {Pid, C1/1000000 + B1 + A1*1000000} + end, + D) + end, + ?line ok = io:format("Result=~p", [Result]), +% erlang:display({?MODULE, ?LINE, Result}), + %% + %% Analyze the result + %% + ?line {Min, Max} = + lists:foldl( + fun({_Pid, M}, {Mi, Ma}) -> + {if M < Mi -> M; true -> Mi end, + if M > Ma -> M; true -> Ma end} + end, + {void, 0}, + Result), + % More PaN debug + ?line io:format("Min = ~f, Max = ~f~n",[Min,Max]), + %% + %% Cleanup + %% + ?line ToBeDeleted = filelib:wildcard(FName++"*"++".wraplog"), + ?line lists:map({file, delete}, ToBeDeleted), +% io:format("ToBeDeleted=~p", [ToBeDeleted]), + %% + %% Present the result + %% + P = (Max / Min - 1) * 100, + BottomLine = lists:flatten(io_lib:format("~.2f %", [P])), + if P > 100 -> + Reason = {BottomLine, '>', "100%"}, + erlang:display({file_port_schedfix, fail, Reason}), + test_server:fail(Reason); + true -> + {comment, BottomLine} + end. + +wrap_port(suite) -> + []; +wrap_port(doc) -> + ["Test tracing to wrapping file port"]; +wrap_port(Config) when is_list(Config) -> + ?line Self = self(), + ?line stop(), + ?line {A,B,C} = erlang:now(), + ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++ + integer_to_list(B) ++ "-" ++ integer_to_list(C) ++ "-", + ?line FName = filename:join([?config(data_dir, Config), FTMP]), + ?line FNameWildcard = FName++"*"++".trace", + %% WrapSize=0 and WrapCnt=11 will force the trace to wrap after + %% every trace message, and to contain only the last 10 entries + %% after trace stop since the last file will be empty waiting + %% for its first trace message. + ?line WrapSize = 0, + ?line WrapCnt = 11, + ?line WrapFilesSpec = {FName, wrap, ".trace", WrapSize, WrapCnt}, + ?line wrap_port_init(WrapFilesSpec), + %% The number of iterations, N, is tested to place wrap the log, + %% giving a gap in the filename sequence at index 3. + %% This should be a difficult case for + %% the trace_client file sorting functionality. + N = 7, + ?line lists:foreach( + fun(Cnt) -> + ?MODULE:tracee1(Cnt), + ?MODULE:tracee2(Cnt) + end, + lists:seq(1, N)), + ?line stop(), + try + ?line Files1 = filelib:wildcard(FNameWildcard), + ?line io:format("~p~n", [Files1]), + ?line Tc1 = dbg:trace_client(file, WrapFilesSpec, + {fun myhandler/2, {wait_for_go,Self}}), + ?line Tref1 = erlang:monitor(process, Tc1), + Tc1 ! {go,Self}, + ?line [{'DOWN',Tref1,_,_,normal}, + end_of_trace + |Result] = lists:reverse(flush()), + ?line M = N - (WrapCnt-1) div 2, + ?line M = wrap_port_result(Result, Self, N), + %% + %% Start a new wrap log with the same name to verify that + %% all files are cleared at wrap log start. Only produce + %% two trace messages to also place the gap at index 3, + %% so the trace log will be misinterpreted. + %% + ?line wrap_port_init(WrapFilesSpec), + ?line Files2 = filelib:wildcard(FNameWildcard), + ?line io:format("~p~n", [Files2]), + ?line -1 = ?MODULE:tracee1(-1), + ?line -1 = ?MODULE:tracee2(-1), + ?line stop(), + ?line Files = filelib:wildcard(FNameWildcard), + ?line io:format("~p~n", [Files]), + ?line Tc2 = dbg:trace_client(file, WrapFilesSpec, + {fun myhandler/2, {wait_for_go,Self}}), + ?line Tref2 = erlang:monitor(process, Tc2), + Tc2 ! {go,Self}, + ?line [{trace,Self,call,{?MODULE,tracee1,[-1]},Self}, + {trace,Self,call,{?MODULE,tracee2,[-1]},hej}, + end_of_trace, + {'DOWN',Tref2,_,_,normal}] = flush(), + %% + ?line lists:map(fun(F) -> file:delete(F) end, Files) + after + ?line stop() + end, + ok. + +wrap_port_init(WrapFilesSpec) -> + ?line Port = dbg:trace_port(file, WrapFilesSpec), + ?line {ok, _} = dbg:tracer(port, Port), + ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + ?line {ok, X} = dbg:tp(?MODULE, tracee1,[{'_',[],[{message, {self}}]}]), + ?line {value, {saved, _Saved}} = lists:keysearch(saved, 1, X), + ?line {ok, Y} = dbg:tp(?MODULE, tracee2, [{'_',[],[{message, hej}]}]), + ?line {value, {saved, _}} = lists:keysearch(saved, 1, Y), + ok. + +tracee1(X) -> + X. + +tracee2(X) -> + X. + +wrap_port_result([], _S, M) -> + M; +wrap_port_result([{trace, S, call, {?MODULE, tracee2, [M]}, hej}, + {trace, S, call, {?MODULE, tracee1, [M]}, S} | Tail], + S, + M) -> + wrap_port_result(Tail, S, M-1). + + +wrap_port_time(suite) -> + []; +wrap_port_time(doc) -> + ["Test tracing to time limited wrapping file port"]; +wrap_port_time(Config) when is_list(Config) -> + ?line stop(), + ?line {A,B,C} = erlang:now(), + ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++ + integer_to_list(B) ++ "-" ++ integer_to_list(C) ++ "-", + ?line FName = filename:join([?config(data_dir, Config), FTMP]), + %% WrapTime=2 and WrapCnt=4 will force the trace to wrap after + %% every 2 seconds, and to contain between 3*2 and 4*2 seconds + %% of trace entries. + ?line WrapFilesSpec = {FName, wrap, ".trace", {time, 2000}, 4}, + ?line Port = dbg:trace_port(file, WrapFilesSpec), + ?line {ok, _} = dbg:tracer(port, Port), + try + ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + ?line {ok, X} = dbg:tp(?MODULE, tracee1,[{'_',[],[{message, {self}}]}]), + ?line {value, {saved, _Saved1}} = lists:keysearch(saved, 1, X), + ?line {ok, Y} = dbg:tp(?MODULE, tracee2, [{'_',[],[{message, hej}]}]), + ?line {value, {saved, _Saved2}} = lists:keysearch(saved, 1, Y), + %% The delays in the iterations places two trace messages in each + %% trace file, but the last which is empty waiting for its first + %% trace message. The number of iterations is chosen so that + %% one trace file has been wasted, and therefore the first pair + %% of trace messages. + ?line lists:foreach( + fun(Cnt) -> + receive after 1000 -> ok end, + ?MODULE:tracee1(Cnt), + ?MODULE:tracee2(Cnt), + receive after 1100 -> ok end + end, + lists:seq(1, 4)), + ?line stop(), + ?line Files = filelib:wildcard(FName ++ "*" ++ ".trace"), + ?line io:format("~p~n", [Files]), + ?line dbg:trace_client(file, WrapFilesSpec, {fun myhandler/2, self()}), + ?line S = self(), + ?line [{trace, S, call, {?MODULE, tracee1, [2]}, S}, + {trace, S, call, {?MODULE, tracee2, [2]}, hej}, + {trace, S, call, {?MODULE, tracee1, [3]}, S}, + {trace, S, call, {?MODULE, tracee2, [3]}, hej}, + {trace, S, call, {?MODULE, tracee1, [4]}, S}, + {trace, S, call, {?MODULE, tracee2, [4]}, hej}, + end_of_trace] = flush(), + ?line lists:map(fun(F) -> file:delete(F) end, Files) + after + ?line stop() + end, + ok. + +with_seq_trace(suite) -> + []; +with_seq_trace(doc) -> + ["Test ordinary tracing combined with seq_trace"]; +with_seq_trace(Config) when is_list(Config) -> + try + ?line {ok, Server} = start(), + ?line {ok, Tracer} = dbg:get_tracer(), + ?line {ok, X} = dbg:tp(dbg, get_tracer, [{[],[], + [{set_seq_token, send, true}]}]), + ?line {value, {saved, _}} = lists:keysearch(saved, 1, X), + ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + ?line seq_trace:set_system_tracer(Tracer), + ?line dbg:get_tracer(), + receive + after 1 -> + ok + end, + ?line S = self(), + ?line ThisNode = node(), + ?line [{trace,S,call,{dbg,get_tracer,[]}}, + {seq_trace,0,{send,_,S,Server,{S,{get_tracer,ThisNode}}}}, + {seq_trace,0,{send,_,Server,S,{dbg,{ok,Tracer}}}}] = + flush() + after + ?line stop() + end, + ok. + +dead_suspend(suite) -> + []; +dead_suspend(doc) -> + ["Test that trace messages concerning a now dead process does " + "not crash dbg."]; + +dead_suspend(Config) when is_list(Config) -> + ?line start(), + try + survived = run_dead_suspend() + after + ?line stop() + end. + +run_dead_suspend() -> + dbg:p(new, call), + dbg:tp(?MODULE, dummy, []), + spawn(?MODULE, dummy, []), + spawn(?MODULE, dummy, []), + spawn(?MODULE, dummy, []), + spawn(?MODULE, dummy, []), + spawn(?MODULE, dummy, []), + receive after 1000 -> ok end, + case whereis(dbg) of + undefined -> + died; + _ -> + survived + end. + +dummy() -> + ok. + + +%% +%% Support functions +%% + +start_slave() -> + {A, B, C} = now(), + Name = "asdkxlkmd" ++ integer_to_list(A+B+C), + {ok, Node} = test_server:start_node(Name,slave,[]), + ok = wait_node(Node, 15), + Node. + +stop_slave(Node) -> + test_server:stop_node(Node). + +wait_node(_,0) -> + no; +wait_node(Node, N) -> + case net_adm:ping(Node) of + pong -> + ok; + pang -> + receive + after 1000 -> + ok + end, + wait_node(Node, N - 1) + end. + +myhandler(Message, {wait_for_go,Pid}) -> + receive + {go,Pid} -> + myhandler(Message, Pid) + end; +myhandler(Message, Relay) -> + Relay ! Message, + case Message of + end_of_trace -> + ok; + _ -> + Relay + end. + +flush() -> + flush([]). +flush(Acc) -> + receive + X -> + flush(Acc ++ [X]) + after 1000 -> + Acc + end. + +start() -> + stop(), + dbg:tracer(process, {fun myhandler/2, self()}). + +stop() -> + dbg:stop(). + + + +schedstat_handler(TraceMsg, {Parent, Tag, Data} = State) -> + case TraceMsg of + {trace_ts, Pid, in, _, Ts} -> + NewData = + case lists:keysearch(Pid, 1, Data) of + {value, {Pid, Acc}} -> + [{Pid, Acc, Ts} | lists:keydelete(Pid, 1, Data)]; + false -> + [{Pid, {0, 0, 0}, Ts} | Data]; + Other -> + exit(Parent, {?MODULE, ?LINE, Other}), + erlang:display({?MODULE, ?LINE, Other}), + Data + end, + {Parent, Tag, NewData}; + {trace_ts, Pid, out, _, {A3, B3, C3}} -> + NewData = + case lists:keysearch(Pid, 1, Data) of + {value, {Pid, {A1, B1, C1}, {A2, B2, C2}}} -> + [{Pid, {A3-A2+A1, B3-B2+B1, C3-C2+C1}} | + lists:keydelete(Pid, 1, Data)]; + Other -> + exit(Parent, {?MODULE, ?LINE, Other}), + erlang:display({?MODULE, ?LINE, Other}), + Data + end, + {Parent, Tag, NewData}; + {trace_ts, Pid, exit, normal, {A3, B3, C3}} -> + NewData = + case lists:keysearch(Pid, 1, Data) of + {value, {Pid, {A1, B1, C1}, {A2, B2, C2}}} -> + [{Pid, {A3-A2+A1, B3-B2+B1, C3-C2+C1}} | + lists:keydelete(Pid, 1, Data)]; + {value, {Pid, _Acc}} -> + Data; + false -> + [{Pid, {0, 0, 0}} | Data]; + Other -> + exit(Parent, {?MODULE, ?LINE, Other}), + erlang:display({?MODULE, ?LINE, Other}), + Data + end, + {Parent, Tag, NewData}; + {trace_ts, _Pid, send, _Msg, _OtherPid, _Ts} -> + State; + end_of_trace -> + Parent ! {Tag, Data}, + State + end. + + + +pass_token(Token, Next, Loops) -> + receive + {Token, 1} = Msg -> + sendloop(Loops), + Next ! Msg; + {Token, _Cnt} = Msg-> + sendloop(Loops), + Next ! Msg, + pass_token(Token, Next, Loops) + end. + +pass_token(Token, Final, Cnt, Loops) -> + receive + {Token, start, Next} -> + sendloop(Loops), + Msg = {Token, Cnt}, + Next ! Msg, + pass_token(Token, Final, Next, Cnt, Loops) + end. + +pass_token(Token, Final, Next, Cnt, Loops) -> + receive + {Token, 1} -> + sendloop(Loops), + Msg = {Token, done}, + Final ! Msg; + {Token, Cnt} -> + sendloop(Loops), + NextCnt = Cnt-1, + Msg = {Token, NextCnt}, + Next ! Msg, + pass_token(Token, Final, Next, NextCnt, Loops) + end. + +sendloop(Loops) -> + sendloop(make_ref(), Loops). + +sendloop(_Tag, 0) -> + ok; +sendloop(Tag, Loops) -> + self() ! {Tag, Loops}, + receive {Tag, Loops} -> ok end, + sendloop(Tag, Loops-1). + +token_volleyball(N, Cnt, Loops) + when is_integer(N), N >= 1, is_integer(Cnt), Cnt >= 1, + is_integer(Loops), Loops >= 0 -> + Self = self(), + Token = make_ref(), + Last = spawn_link(fun() -> pass_token(Token, Self, Cnt, Loops) end), + First = token_volleyball(Token, Last, N-1, Loops), + Last ! {Token, start, First}, + receive {Token, done} -> ok end. + +token_volleyball(Token, Next, 1, Loops) -> + spawn_link(fun() -> pass_token(Token, Next, Loops) end); +token_volleyball(Token, Next, N, Loops) -> + Pid = spawn_link(fun() -> pass_token(Token, Next, Loops) end), + token_volleyball(Token, Pid, N-1, Loops). diff --git a/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl b/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl new file mode 100644 index 0000000000..2edbf6f99a --- /dev/null +++ b/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl @@ -0,0 +1,87 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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% +%% +%%%---------------------------------------------------------------------- +%%% Purpose : A priority queue. +%%%---------------------------------------------------------------------- +%%% This module implements a priority queue as defined in +%%% "Priority Queues and the STL" by Mark Nelson in Dr.Dobb's Journal, Jan 1996 +%%% see http://web2.airmail.net/markn/articles/pq_stl/priority.htm for more +%%% information. (A heap implementation is planned aswell) +%%%---------------------------------------------------------------------- +%%% The items of the queue is kept priority sorted, and because of that, +%%% a push() operation costs more than a pop() operation (wich only +%%% needs to return the top item of the queue(read: list)). +%%%---------------------------------------------------------------------- +%%% The priority queue can be deceptively nice to use when creating for +%%% example a Huffman coding tree. +%%% See http://web2.airmail.net/markn/articles/pq_stl/priority.htm or +%%% Dr.Dobb's Journal Jan, 96 for more information on this. +%%%---------------------------------------------------------------------- + +%%% Used here strictly as something for dbg_SUITE to run. + +-module(dbg_test). +-export([test/1, loop/1]). +-export([new/0, push/3, pop/1]). + +loop(Config) -> + test(Config), + receive + {dbg_test, stop} -> + ok; + Other -> + loop(Config) + end, + ok. + +test(Config) -> + Q1=new(), + Q2=push(Q1, "monkey", 3), + Q3=push(Q2, "banana", 4), + Q4=push(Q3, "jungle", 2), + Q5=push(Q4, "world", 5), + Q6=push(Q5, "universe",6), + Q7=push(Q6, "peanut", 1), +% io:format("~p~n",[Q7]), + {Itm, Q8}=pop(Q7), + ok. + +%% Returns a new priority queue. +new() -> + []. + +%% Pushes a new item with a set priority into the queue. +push(Queue, Itm, Pri) -> + insert(Queue, Itm, Pri, []). + +%% Pops the item with the highest priority out of the queue. +pop([{Itm, Pri}|Queue]) -> + {Itm, Queue}. + +%% --- -- - +%% Support functions. +insert([], Itm, Pri, NewQ) -> + lists:flatten([lists:reverse(NewQ)|[{Itm, Pri}]]); +% Itm>QItm>NewQ>Queue +insert([{QItm,QPri}|Queue], Itm, Pri, NewQ) when Pri>QPri-> + A = [{Itm, Pri}|[{QItm, QPri}]], + lists:flatten([[A|NewQ]|Queue]); +insert([QItm|Rest], Itm, Pri, NewQ) -> + insert(Rest, Itm, Pri, [QItm|NewQ]). +%% --- -- - diff --git a/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl b/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl new file mode 100644 index 0000000000..85faf620aa --- /dev/null +++ b/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl @@ -0,0 +1,50 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(exref_td). + +-export([a/1,b/1,c/1,d/1,e/1,my_analyse/1]). + +a("edcba") -> + true; +a(_) -> + lists:reverse("abcde"). + +b(_) -> + a(nil). + +c(_) -> + nonexistentmodule:f(). + +d(_) -> + lists:nonexistentfunction(). + +e(_) -> + [a(x),b(x),c(x)]. + +localfuncnotcalled() -> + true. + +localfunccalledbyf(A) -> + A. + +f() -> + lists:filter(fun localfunccalledbyf/1,"aaabba"), + F = fun localfuncnotcalled/0. + +my_analyse(Graph) -> ok. diff --git a/lib/runtime_tools/test/erts_alloc_config_SUITE.erl b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl new file mode 100644 index 0000000000..32483dbe73 --- /dev/null +++ b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl @@ -0,0 +1,206 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(erts_alloc_config_SUITE). + +%-define(line_trace, 1). + +-include("test_server.hrl"). + +%-compile(export_all). +-export([all/1, init_per_testcase/2, fin_per_testcase/2]). + +%% Testcases +-export([basic/1]). + +%% internal export +-export([make_basic_config/1]). + +-define(DEFAULT_TIMEOUT, ?t:minutes(2)). + +all(doc) -> []; +all(suite) -> [basic]. + +init_per_testcase(Case, Config) when is_list(Config) -> + [{testcase, Case}, + {watchdog, ?t:timetrap(?DEFAULT_TIMEOUT)}, + {erl_flags_env, save_env()} | Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + ?t:timetrap_cancel(?config(watchdog, Config)), + restore_env(?config(erl_flags_env, Config)), + ok. + +%%% +%%% The test cases ------------------------------------------------------------ +%%% + +basic(doc) -> []; +basic(suite) -> []; +basic(Config) when is_list(Config) -> + ?line ErtsAllocConfig = privfile("generated", Config), + + SbctMod = " +MBsbct 1024 +MHsbct 4096", + + %% Make sure we have enabled allocators + ZFlgs = case os:getenv("ERL_ZFLAGS") of + FlgString when is_list(FlgString) -> + FlgString; + _ -> + "" + end ++ " +Mea max +Mea config", + + ?line os:putenv("ERL_ZFLAGS", ZFlgs ++ SbctMod), + + ?line {ok, Node1} = start_node(Config), + ?line ok = rpc:call(Node1, ?MODULE, make_basic_config, [ErtsAllocConfig]), + ?line stop_node(Node1), + + ?line display_file(ErtsAllocConfig), + + ?line ManualConfig = privfile("manual", Config), + ?line {ok, IOD} = file:open(ManualConfig, [write]), + ?line io:format(IOD, "~s", ["+MBsbct 2048"]), + ?line file:close(IOD), + ?line display_file(ManualConfig), + + ?line os:putenv("ERL_ZFLAGS", ZFlgs), + + ?line {ok, Node2} = start_node(Config, + "-args_file " ++ ErtsAllocConfig + ++ " -args_file " ++ ManualConfig), + + ?line {_, _, _, Cfg} = rpc:call(Node2, erlang, system_info, [allocator]), + + ?line stop_node(Node2), + + ?line {value,{binary_alloc, BCfg}} = lists:keysearch(binary_alloc, 1, Cfg), + ?line {value,{sbct, 2097152}} = lists:keysearch(sbct, 1, BCfg), + ?line {value,{eheap_alloc, HCfg}} = lists:keysearch(eheap_alloc, 1, Cfg), + ?line {value,{sbct, 4194304}} = lists:keysearch(sbct, 1, HCfg), + + ?line ok. + +make_basic_config(ErtsAllocConfig) -> + %% Save some different scenarios + Tester = self(), + SSBegun = make_ref(), + SSDone = make_ref(), + SSFun = fun (F) -> + receive + SSDone -> + ok = erts_alloc_config:save_scenario(), + Tester ! SSDone + after 500 -> + ok = erts_alloc_config:save_scenario(), + F(F) + end + end, + SS = spawn_link(fun () -> + ok = erts_alloc_config:save_scenario(), + Tester ! SSBegun, + SSFun(SSFun) + end), + receive SSBegun -> ok end, + Ref = make_ref(), + Tab = ets:new(?MODULE, [bag, public]), + Ps = lists:map( + fun (_) -> + spawn_link( + fun () -> + ets:insert(Tab, + {self(), + lists:seq(1, 1000)}), + receive after 1000 -> ok end, + Tester ! {Ref, self()} + end) + end, + lists:seq(1, 10000)), + lists:foreach(fun (P) -> receive {Ref, P} -> ok end end, Ps), + ets:delete(Tab), + SS ! SSDone, + receive SSDone -> ok end, + + ok = erts_alloc_config:make_config(ErtsAllocConfig). + + + +%% +%% Utils ---------------------------------------------------------------------- +%% + +display_file(FileName) -> + ?t:format("filename: ~s~n", [FileName]), + {ok, Bin} = file:read_file(FileName), + io:format("~s", [binary_to_list(Bin)]), + ?t:format("eof: ~s~n", [FileName]), + ok. + +mk_name(Config) when is_list(Config) -> + {A, B, C} = now(), + list_to_atom(atom_to_list(?MODULE) + ++ "-" ++ atom_to_list(?config(testcase, Config)) + ++ "-" ++ integer_to_list(A) + ++ "-" ++ integer_to_list(B) + ++ "-" ++ integer_to_list(C)). + +start_node(Config) -> + start_node(Config, ""). + +start_node(Config, Args) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line ?t:start_node(mk_name(Config), + slave, + [{args, "-pa " ++ Pa ++ " " ++ Args}]). + +stop_node(Node) -> + ?line true = ?t:stop_node(Node). + +privfile(Name, Config) -> + filename:join([?config(priv_dir, Config), + atom_to_list(?config(testcase, Config)) ++ "." ++ Name]). + +save_env() -> + {erl_flags, + os:getenv("ERL_AFLAGS"), + os:getenv("ERL_FLAGS"), + os:getenv("ERL_"++erlang:system_info(otp_release)++"_FLAGS"), + os:getenv("ERL_ZFLAGS")}. + +restore_env(EVar, false) when is_list(EVar) -> + restore_env(EVar, ""); +restore_env(EVar, "") when is_list(EVar) -> + case os:getenv(EVar) of + false -> ok; + "" -> ok; + " " -> ok; + _ -> os:putenv(EVar, " ") + end; +restore_env(EVar, Value) when is_list(EVar), is_list(Value) -> + case os:getenv(EVar) of + Value -> ok; + _ -> os:putenv(EVar, Value) + end. + +restore_env({erl_flags, AFlgs, Flgs, RFlgs, ZFlgs}) -> + restore_env("ERL_AFLAGS", AFlgs), + restore_env("ERL_FLAGS", Flgs), + restore_env("ERL_"++erlang:system_info(otp_release)++"_FLAGS", RFlgs), + restore_env("ERL_ZFLAGS", ZFlgs), + ok. diff --git a/lib/runtime_tools/test/inviso_SUITE.erl b/lib/runtime_tools/test/inviso_SUITE.erl new file mode 100644 index 0000000000..1c5c887b62 --- /dev/null +++ b/lib/runtime_tools/test/inviso_SUITE.erl @@ -0,0 +1,2840 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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% +%% +%% Description: +%% Test suite for inviso (basic parts, i.e not inviso tools). Note that +%% inviso basic parts have modules in both the runtime_tools and +%% inviso applications. +%% +%% Authors: +%% Ann-Marie L�f, [email protected] +%% Lennart �hman, [email protected] +%% ----------------------------------------------------------------------------- + +-module(inviso_SUITE). +-compile(export_all). + +-include("test_server.hrl"). +-include_lib("kernel/include/file.hrl"). + +-define(l,?line). + +all(suite) -> + [ + basic_dist_trace_1, + basic_dist_trace_2, + basic_dist_trace_3, + basic_dist_trace_ti_1, + basic_dist_trace_ti_2, + basic_dist_trace_ti_3, + suspend_dist_trace_ti_1, + suspend_dist_trace_ti_2, + meta_cleanfunc_dist_1, + basic_handlerfun_dist_1, + delete_log_dist_1, + autostart_dist_1, + autostart_dist_2, + autostart_dist_3, + running_alone_dist_1, + running_alone_dist_2, + running_alone_dist_3, + running_alone_dist_4, + running_alone_dist_5, + overload_dist_1, + overload_dist_2, + overload_dist_3, + overload_dist_4, + overload_dist_5, + subscribe_dist_1, + lfm_trace_dist_1, + lfm_trace_ti_dist_2, + handle_logfile_sort_wrapset, + fetch_log_dist_trace_1, + fetch_log_dist_trace_2, + fetch_log_dist_trace_3, + fetch_log_dist_error_1, + fetch_log_dist_error_2, + expand_regexp_dist_1, + only_loaded_dist_1 + ]. + + +init_per_suite(Config) -> + %% No never know who skrewed up this node before this suite! :-) + erlang:trace_pattern({'_','_','_'},[],[local]), + erlang:trace_pattern({'_','_','_'},[],[global]), + erlang:trace(all,false,[all]), + + ?l ok=application:start(runtime_tools), + Config. + +end_per_suite(_Config) -> + ?l ok=application:stop(runtime_tools). + + +%% For each distributed testcase, we need two other distributed nodes to run the +%% runtime components on. Since they are freshly started every time there is no +%% need to clean them up first. +init_per_testcase(_Case,Config) -> + ?l TH=test_server:timetrap(100000), + ?l {ok,Node1}=test_server:start_node(inviso1,peer,[]), + ?l {ok,Node2}=test_server:start_node(inviso2,peer,[]), + ?l SuiteDir=filename:dirname(code:which(?MODULE)), + + %% Otherwise peer nodes will not find this module! + ?l true=rpc:call(Node1,code,add_patha,[SuiteDir]), + ?l true=rpc:call(Node2,code,add_patha,[SuiteDir]), + + ?l start_side_effect_logger(node()), + ?l start_side_effect_logger(Node1), + ?l start_side_effect_logger(Node2), + + + %% SPECIAL FOR MY PRIVATE TEST ENVIROMENT +% ?l rpc:call(Node1,code,add_patha,["/clearcase/otp/tools/runtime_tools/ebin"]), +% ?l rpc:call(Node1,code,add_patha,["/clearcase/otp/tools/inviso/ebin"]), +% ?l rpc:call(Node2,code,add_patha,["/clearcase/otp/tools/runtime_tools/ebin"]), +% ?l rpc:call(Node2,code,add_patha,["/clearcase/otp/tools/inviso/ebin"]), + +% %% SPECIAL FOR MY PRIVATE TEST ENVIROMENT, windows. +% ?l rpc:call(Node1,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/runtime_tools/ebin"]), +% ?l rpc:call(Node1,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/inviso/ebin"]), +% ?l rpc:call(Node2,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/runtime_tools/ebin"]), +% ?l rpc:call(Node2,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/inviso/ebin"]), + + ?l ok=rpc:call(Node1,application,start,[runtime_tools]), + ?l ok=rpc:call(Node2,application,start,[runtime_tools]), + ?l timer:sleep(100), % Problem with autostarted runtime. + %% The following is a test that the inviso_rt processes which are autostarted + %% are now gone. + + ?l ok=poll(rpc,call,[Node1,erlang,whereis,[inviso_rt]],undefined,20), + ?l ok=poll(rpc,call,[Node2,erlang,whereis,[inviso_rt]],undefined,20), + +% ?l ok=poll(rpc,call,[Node1,supervisor,which_children,[runtime_tools_sup]],[],20), +% ?l ok=poll(rpc,call,[Node2,supervisor,which_children,[runtime_tools_sup]],[],20), + NewConfig1=insert_remotenode_config(inviso1,Node1,Config), + NewConfig2=insert_remotenode_config(inviso2,Node2,NewConfig1), + insert_timetraphandle_config(TH,NewConfig2). +%% ----------------------------------------------------------------------------- + +fin_per_testcase(Case,Config) -> + ?l test_server:stop_node(get_remotenode_config(inviso1,Config)), + ?l test_server:stop_node(get_remotenode_config(inviso2,Config)), + + case whereis(inviso_c) of + undefined -> % Should not exist. + true; + Pid when is_pid(Pid) -> % But if it exists... + exit(Pid,kill), % Remove it! + io:format("Had to kill the control component in fin_per_testcase,~p.~n",[Case]) + end, + case whereis(inviso_rt) of + undefined -> % Should not exist. + true; + Pid2 when is_pid(Pid2) -> % But if it exists... + exit(Pid2,kill), % Remove it! + io:format("Had to kill local runtime component in fin_per_testcase,~p.~n",[Case]) + end, + ?l process_killer([inviso_test_proc, + inviso_tab_proc, + inviso_collector_proc, + global_inviso_test_proc]), + ?l test_server:timetrap_cancel(get_timetraphandle_config(Config)), + + NewConfig1=remove_remotenode_config(inviso1,Config), + NewConfig2=remove_remotenode_config(inviso2,NewConfig1), + remove_timetraphandle_config(NewConfig2). +%% ----------------------------------------------------------------------------- + +%% ============================================================================== +%% Testcases. +%% ============================================================================== + +%% TEST CASE: Basic, distributed, trace only. +basic_dist_trace_1(suite) -> []; +basic_dist_trace_1(doc) -> + ["Basic case, start of distributed tracing, using only trac."]; +basic_dist_trace_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir, + "tf1_"++ + atom_to_list(N) + ])}} end, + Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), + activate_local_tracing(Nodes), + deactivate_local_tracing(Nodes), + stop_tracing(Nodes), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + + +%% TEST CASE: Basic, distributed, activate global tracing for functions in modules +%% pointed out using a regexp. No tracing will be done. +basic_dist_trace_2(suite) -> []; +basic_dist_trace_2(doc) -> + [""]; +basic_dist_trace_2(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir, + "tf1a_"++ + atom_to_list(N) + ])}} end, + Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), + Funcs1=activate_global_tracing_regexp(Nodes), + deactivate_global_tracing_regexp(Nodes,Funcs1), + stop_tracing(Nodes), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Basic, distributed, activate global tracing for functions in modules +%% pointed out using a dir-regexp. No tracing will be done. +basic_dist_trace_3(suite) -> []; +basic_dist_trace_3(doc) -> + [""]; +basic_dist_trace_3(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir, + "tf1b_"++ + atom_to_list(N) + ])}} end, + Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), + Funcs1=activate_global_tracing_regexp_dir(Nodes), + deactivate_global_tracing_regexp_dir(Nodes,Funcs1), + stop_tracing(Nodes), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Basic, distributed, trace and ti. +basic_dist_trace_ti_1(suite) -> []; +basic_dist_trace_ti_1(doc) -> + [""]; +basic_dist_trace_ti_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataFun= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf2_"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"tf2_"++atom_to_list(N)++".ti"])}}]} + end, + TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + activate_local_tracing(Nodes), + activate_meta_tracing(Nodes), + ?l true=(is_pid(whereis(inviso_rt))), + ?l true=(is_pid(whereis(inviso_rt_meta))), + deactivate_meta_tracing(Nodes), + deactivate_local_tracing(Nodes), + stop_tracing(Nodes), + ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running. + ?l ok=poll(erlang,whereis,[inviso_rt_meta],undefined,3), + stop(Nodes), + timer:sleep(200), % Give it time to terminate. + ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now. + ?l undefined=whereis(inviso_rt_meta), % Still gone. + ok. +%% ----------------------------------------------------------------------------- + +%% Test CASE: Testing that the tpm_tracer functionality works. That is appending +%% {tracer,Tracer} to a meta match spec. +basic_dist_trace_ti_2(suite) -> []; +basic_dist_trace_ti_2(doc) -> + [""]; +basic_dist_trace_ti_2(Config) when is_list(Config) -> + case erlang:system_info(version) of + "5.4"++_ -> % Perhaps not perfect, but work now :-) + {skip,"Old emulator"}; + _ -> + basic_dist_trace_ti_2_do(Config) + end. + +basic_dist_trace_ti_2_do(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataFun= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf3_"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"tf3_"++atom_to_list(N)++".ti"])}}]} + end, + TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + activate_deactivate_meta_tracing_tracer(Nodes), + stop_tracing(Nodes), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Basic, distributed, trace and ti, where we try to use ctp_all to +%% check that all global and local patterns are removed but that meta patterns +%% remain. +%% This test also checks that if the meta tracer is terminated an error value +%% is generated when trying to do meta tracing at that node. +basic_dist_trace_ti_3(suite) -> []; +basic_dist_trace_ti_3(doc) -> + [""]; +basic_dist_trace_ti_3(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataFun= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf4_"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"tf4_"++atom_to_list(N)++".ti"])}}]} + end, + TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + activate_local_tracing(Nodes), + activate_global_tracing(Nodes), + activate_meta_tracing(Nodes), + ?l true=(is_pid(whereis(inviso_rt))), + ?l true=(is_pid(whereis(inviso_rt_meta))), + ?l {ok,NodeResults1}=inviso:ctp_all(Nodes), % Removes local and global patterns. + ?l true=check_noderesults(Nodes,ok,NodeResults1), + ?l true=check_on_nodes(Nodes,erlang,trace_info,[{code,which,1},traced],{traced,false}), + ?l true=check_on_nodes(Nodes,erlang,trace_info,[{code,get_path,0},traced],{traced,false}), + %% But meta patters shall remain. + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{lists,module_info,0},meta_match_spec], + fun({meta_match_spec,L})when length(L)>0 ->true end), + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{lists,module_info,0},meta], + fun({meta,P})when is_pid(P) -> + P=rpc:call(node(P),erlang,whereis,[inviso_rt_meta]), + true + end), + %% Now kill the meta tracer somewhere and try to activate meta tracing. + ?l [ANode|_]=Nodes, + ?l AMetaPid=rpc:call(ANode,erlang,whereis,[inviso_rt_meta]), + ?l rpc:call(ANode,erlang,exit,[AMetaPid,kill]), + ?l {ok,NodeResults2}=inviso:tpm(Nodes,math,pi,0,[],void), + ?l {value,{ANode,{error,_}}}=lists:keysearch(ANode,1,NodeResults2), + + ?l stop_tracing(Nodes), + ?l stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% ----------------------------------------------------------------------------- +%% Test cases for SUSPEND +%% ----------------------------------------------------------------------------- + +%% TEST CASE: In this test case a trace with ti is started. Trace flags are set, +%% trace patterns are set and meta trace patterns. We then check that the trace +%% flags and the meta patterns are removed when tracing suspended. +%% The suspension is cancelled and we check that it is possible to reactivate +%% tracing by setting the process flags and meta patterns again. +suspend_dist_trace_ti_1(suite) -> []; +suspend_dist_trace_ti_1(doc) -> + [""]; +suspend_dist_trace_ti_1(Config) when is_list(Config) -> + ?l RemoteNodes=get_remotenodes_config(Config), + ?l Nodes=[node()|RemoteNodes], + ?l PrivDir=filename:join(?config(priv_dir,Config),""), + ?l TracerDataFun= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend1_"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"tf_suspend1_"++atom_to_list(N)++".ti"])}}]} + end, + ?l TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + activate_local_tracing(Nodes), + activate_meta_tracing(Nodes), + ?l true=(is_pid(whereis(inviso_rt))), + ?l true=(is_pid(whereis(inviso_rt_meta))), + %% Set some trace flags on some newly started test procs. + activate_traceflags(Nodes), + + %% Now suspend the tracing on all nodes. That shall result in the removal + %% of trace flags and meta trace patterns, but not local trace patterns. + ?l {ok,NodeResults1}=inviso:suspend(Nodes,test), + ?l true=check_noderesults(Nodes,ok,NodeResults1), + %% Trace flags gone? + ?l TestProcs=lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_test_proc]) end,Nodes), + ?l lists:foreach(fun(P)-> + {flags,[]}= + rpc:call(node(P),erlang,trace_info,[P,flags]) + end, + TestProcs), + %% Meta patterns shall be gone too, but local functions still there. + ?l lists:foreach(fun(N)-> + {meta,false}= + rpc:call(N, + erlang, + trace_info, + [{math,module_info,1},meta]), + {traced,local}= + rpc:call(N, + erlang, + trace_info, + [{code,which,1},traced]) + end, + Nodes), + + %% Try to activate trace flags, trace patterns and meta tracing while + %% suspended. Should not succeed of course! + ?l ThisNode=node(), + ?l {ok,[{ThisNode,{error,suspended}}]}= + inviso:tf([ThisNode],inviso_test_proc,[call]), + ?l {ok,[{ThisNode,{error,suspended}}]}= + inviso:tpl([ThisNode],math,module_info,1,[]), + ?l {ok,[{ThisNode,{error,suspended}}]}= + inviso:init_tpm([ThisNode], + math, + module_info, + 1, + {?MODULE,tpm_init_func2}, % Does not exist on purpose. + {?MODULE,tpm_call_func2}, % Does not exist on purpose. + {?MODULE,tpm_return_func2}, % Does not exist on purpose. + {?MODULE,tpm_remove_func2}), % Does not exist on purpose. + + %% Now we want to cancel suspension and see that we can reactivate tracing. + ?l {ok,NodeResults2}=inviso:cancel_suspension(Nodes), + ?l true=check_noderesults(Nodes,ok,NodeResults2), + + ?l {ok,NodeResults3}= + inviso:init_tpm(math, + module_info, + 1, + {?MODULE,tpm_init_func2}, % Does not exist on purpose. + {?MODULE,tpm_call_func2}, % Does not exist on purpose. + {?MODULE,tpm_return_func2}, % Does not exist on purpose. + {?MODULE,tpm_remove_func2}), % Does not exist on purpose. + ?l true=check_noderesults(Nodes,ok,NodeResults3), + ?l {ok,NodeResults5}= + inviso:tpm_ms(math,module_info,1,ms1,[{'_',[],[{return_trace}]}]), + ?l true=check_noderesults(Nodes,{ok,1},NodeResults5), + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{math,module_info,1},meta_match_spec], + {meta_match_spec,[{'_',[],[{return_trace}]}]}), + ?l {ok,NodeResults6}=inviso:tf(Nodes,inviso_test_proc,[call]), + ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults6), + + %deactivate_meta_tracing(Nodes), + %deactivate_local_tracing(Nodes), + stop_tracing(Nodes), + ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running. + ?l ok=poll(erlang,whereis,[inviso_rt_meta],undefined,3), + stop(Nodes), + ?l timer:sleep(200), % Give it time to terminate. + ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now. + ?l undefined=whereis(inviso_rt_meta), % Still gone. + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: In this test case a trace with ti is started. Trace flags are set, +%% trace patterns are set and meta trace patterns. We then suspend tracing at +%% all nodes, then stop tracing which shall be allowed. We then try to initiate +%% tracing again which shall not be possible. +suspend_dist_trace_ti_2(suite) -> []; +suspend_dist_trace_ti_2(doc) -> + [""]; +suspend_dist_trace_ti_2(Config) when is_list(Config) -> + ?l RemoteNodes=get_remotenodes_config(Config), + ?l Nodes=[node()|RemoteNodes], + ?l PrivDir=filename:join(?config(priv_dir,Config),""), + ?l TracerDataFun= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend2_"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"tf_suspend2_"++atom_to_list(N)++".ti"])}}]} + end, + ?l TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + activate_local_tracing(Nodes), + activate_meta_tracing(Nodes), + ?l true=(is_pid(whereis(inviso_rt))), + ?l true=(is_pid(whereis(inviso_rt_meta))), + %% Set some trace flags on some newly started test procs. + activate_traceflags(Nodes), + + %% Now suspend the tracing on all nodes. That shall result in the removal + %% of trace flags and meta trace patterns, but not local trace patterns. + ?l {ok,NodeResults1}=inviso:suspend(Nodes,test), + ?l true=check_noderesults(Nodes,ok,NodeResults1), + + %% Now stop tracing. + ?l {ok,NodeResults3}=inviso:stop_tracing(Nodes), + ?l true=check_noderesults(Nodes,{ok,idle},NodeResults3), + %% Now try to initiate tracing again. + ThisNode=node(), + ?l {ok,[{ThisNode,{error,suspended}}]}= + inviso:init_tracing([ThisNode], + [{trace,{file,filename:join([PrivDir,"tf_suspend3_"++ + atom_to_list(ThisNode)])}}, + {ti,{file,{filename:join([PrivDir,"tf_suspend3_"++ + atom_to_list(ThisNode)])}}}]), + + %% Cancel the suspension and initiate tracing again. + ?l {ok,NodeResults2}=inviso:cancel_suspension(Nodes), + ?l true=check_noderesults(Nodes,ok,NodeResults2), + ?l TracerDataFun2= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend4_"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"tf_suspend4_"++atom_to_list(N)++".ti"])}}]} + end, + ?l TracerDataList2=lists:map(TracerDataFun2,Nodes), + ?l {ok,NodeResults4}=inviso:init_tracing(TracerDataList2), + ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok},{ti_log,ok}]},NodeResults4), + stop_tracing(Nodes), + ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running. + stop(Nodes), + ?l timer:sleep(200), % Give it time to terminate. + ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now. + ok. +%% ----------------------------------------------------------------------------- + + + +%% TEST CASE: This test case tests that the clean function removes (prosumed) +%% expired data from the internal public-loopdata structure in the inviso_rt_meta +%% process. +meta_cleanfunc_dist_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataFun= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"mcf1_"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"mcf1_"++atom_to_list(N)++".ti"])}}]} + end, + TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + %% Now initialize meta tracing, but the call_func is a bit "fixed". + ?l {ok,NodeResults1}= + inviso:tpm(Nodes,math,module_info,1,[], + {?MODULE,meta_cleanfunc_initfunc_1}, + {?MODULE,meta_cleanfunc_callfunc_1}, + void,void), + ?l true=check_noderesults(Nodes,{ok,1},NodeResults1), + %% Nothing in the "our" part of the public loop data. + ?l true=check_on_nodes(Nodes, + inviso_rt_meta,get_state,[inviso_rt_meta], + fun({ok,_LD,{{_,[]},_}})->true end), + ?l lists:foreach(fun(N)->rpc:call(N,math,module_info,[exports]) end,Nodes), + %% Check that it has been added to the public loopdata structure. + ?l true=check_on_nodes(Nodes, + ?MODULE,poll,[inviso_rt_meta, + get_state, + [inviso_rt_meta], + fun({ok,_LD,{{_,[{meta_cleanfunc_test1,_Now}]},_}})-> + true; + (_)->false + end, + 20], + ok), + %% While we wait for 60 seconds to pass, we test a few other things. + ?l {ok,NodeResults2}= + inviso:tpm(Nodes,?MODULE,slowfunction2,0,[{'_',[],[{return_trace}]}], + {?MODULE,meta_cleanfunc_initfunc_2}, + {?MODULE,meta_cleanfunc_callfunc_2}, + {?MODULE,meta_cleanfunc_returnfunc_2}, + void), + ?l true=check_noderesults(Nodes,{ok,1},NodeResults2), + ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,slowfunction,[]) end,Nodes), + %% Believe it or not but slowfunction is still running, in its own process, + %% we are therefore free now to examine the meta tracer. + ?l true=check_on_nodes(Nodes, + ?MODULE,poll,[inviso_rt_meta, + get_state, + [inviso_rt_meta], + fun({ok,_LD,{{[],Tuples},_}})-> + {value,_}= + lists:keysearch(meta_cleanfunc_test2, + 1, + Tuples), + {value,_}= + lists:keysearch(meta_cleanfunc_test1, + 1, + Tuples), + true; + (_)-> + false + end, + 20], + ok), + %% Now we wait for slowfunction to return and that the meta_cleanfunc_test2 + %% to be removed from public loopdata strucuture. + ?l timer:sleep(10000), + %% The only thing remaining should be the meta_cleanfunc_test1 which will not + %% go away for less than that the clean functionality removes it. + ?l true=check_on_nodes(Nodes, + ?MODULE,poll,[inviso_rt_meta, + get_state, + [inviso_rt_meta], + fun({ok,_LD,{{_,[{meta_cleanfunc_test1,_Now}]},_}})-> + true; + (_)-> + false + end, + 20], + ok), + %% Wait for the clean function to clean meta_cleanfunc_test1 away. + ?l timer:sleep(51000), % Shall be gone after 5 seconds. + ?l true=check_on_nodes(Nodes, + ?MODULE,poll,[inviso_rt_meta, + get_state, + [inviso_rt_meta], + fun({ok,_LD,{{_,[]},_}})->true; + (_)->false + end, + 20], + ok), + stop_tracing(Nodes), + stop(Nodes), + ok. + +%% This function acts as tpm initialization function when we are going to test +%% that the clean function works. Note that we here assume standard public loop +%% datastructure. +meta_cleanfunc_initfunc_1(_M,_F,_Arity,{E1,_E2}) -> + {ok,{E1,[]},void}. +%% Function that is supposed to be called when the meta traced function is +%% called. +meta_cleanfunc_callfunc_1(_Pid,_Args,{{E1,E2},Global}) -> + {ok,{{E1,[{meta_cleanfunc_test1,now()}|E2]},Global},void}. + +meta_cleanfunc_initfunc_2(_M,_F,_Arity,PublLD) -> + {ok,PublLD,void}. +meta_cleanfunc_callfunc_2(_Pid,_Args,{{E1,E2},Global}) -> + {ok,{{E1,[{meta_cleanfunc_test2,now()}|E2]},Global},void}. +meta_cleanfunc_returnfunc_2(_Pid,_,{{E1,E2},Global}) -> + {value,_}=lists:keysearch(meta_cleanfunc_test2,1,E2), + {ok,{{E1,lists:keydelete(meta_cleanfunc_test2,1,E2)},Global},void}. + +slowfunction() -> + spawn(?MODULE,slowfunction1,[]). +slowfunction1() -> + slowfunction2(). % Meta trace on this function call. +slowfunction2() -> + timer:sleep(2000), + true. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Testing that a runtime component can be started instructing it +%% to use a handler fun. Checks that the handler fun is called if a trace +%% message comes in. +basic_handlerfun_dist_1(suite) -> []; +basic_handlerfun_dist_1(doc) -> + [""]; +basic_handlerfun_dist_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + ?l lists:foreach(fun(N)->rpc:call(N,ets,insert,[inviso_sideeffect_tab,{bhf1,0}]) end, + Nodes), + TracerDataFun= + fun(N)->{N,{fun basic_handlerfun_dist_1_fun/2,inviso_sideeffect_tab}} end, + TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), + activate_local_tracing(Nodes), + activate_traceflags(Nodes), + ?l lists:foreach(fun(N)->[{bhf1,0}]= + rpc:call(N,ets,lookup,[inviso_sideeffect_tab,bhf1]) + end, + Nodes), + ?l inviso_test_proc ! {apply,code,which,[lists]}, + ok=poll(ets,lookup,[inviso_sideeffect_tab,bhf1],[{bhf1,1}],20), + deactivate_traceflags(Nodes), + deactivate_local_tracing(Nodes), + stop_tracing(Nodes), + timer:sleep(100), + ?l [{bhf1,1}]=ets:lookup(inviso_sideeffect_tab,bhf1), + stop(Nodes), + ok. + +%% Function used as handler fun for testcase above. +basic_handlerfun_dist_1_fun(_Msg,TId) -> + ets:update_counter(TId,bhf1,1), + TId. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Here we test that delete_log removes the files at the involved +%% runtime nodes. In this case we test that we remove logs according to last +%% used tracer data. +delete_log_dist_1(suite) -> []; +delete_log_dist_1(doc) -> [""]; +delete_log_dist_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataFun= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"dl1_"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"dl1_"++atom_to_list(N)++".ti"])}}]} + end, + TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + ?l Files=lists:map(fun({N,TD})-> + ?l {value,{_,{_,TraceFile}}}=lists:keysearch(trace,1,TD), + ?l {value,{_,{_,TiFile}}}=lists:keysearch(ti,1,TD), + ?l {N,{TraceFile,TiFile}} + end, + TracerDataList), + io:format("The Files is:~w~n",[Files]), + ?l {ok,NodeResults1}=inviso:delete_log(Nodes), % Should not work! + ?l true=check_noderesults(Nodes,{error,tracing},NodeResults1), + stop_tracing(Nodes), + %% Files still here. + ?l lists:foreach(fun({N,{F1,F2}})-> + ?l {ok,_}=rpc:call(N,file,read_file_info,[F1]), + ?l {ok,_}=rpc:call(N,file,read_file_info,[F2]) + end, + Files), + ?l {ok,NodeResults2}=inviso:delete_log(Nodes), + ?l true=check_noderesults(Nodes, + fun({_N,{ok,LogInfos}})-> + ?l {value,{_,[{ok,_FName1}]}}= + lists:keysearch(trace_log,1,LogInfos), + ?l {value,{_,[{ok,_FName2}]}}= + lists:keysearch(ti_log,1,LogInfos), + true + end, + NodeResults2), + %% The files shall be gone now. + ?l lists:foreach(fun({N,{F1,F2}})-> + ?l {error,enoent}=rpc:call(N,file,read_file_info,[F1]), + ?l {error,enoent}=rpc:call(N,file,read_file_info,[F2]) + end, + Files), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + + +%% TEST CASE: Test of the autostart behaviour of the runtime component. +%% Here we test that a runtime component is started according to the autostart.conf +%% file. Note that the repeat parameter is set to 2. +autostart_dist_1(suite) -> []; +autostart_dist_1(doc) -> + [""]; +autostart_dist_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + PrivDir=filename:join(?config(priv_dir,Config),""), + AutoConfFile=filename:join(PrivDir,"autostart1.conf"), + [RNode|_]=RemoteNodes, + ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), + ?l ok=rpc:call(RNode,application,set_env,[runtime_tools, + inviso_autostart_conf, + AutoConfFile]), + ?l {ok,FD}=file:open(AutoConfFile,[write]), + ?l ok=io:format(FD,"~w.~n~w.~n",[{repeat,2},{tag,c_ref}]), + ?l file:close(FD), + ?l ok=rpc:call(RNode,application,start,[runtime_tools]), + timer:sleep(1000), + ?l P1=rpc:call(RNode,erlang,whereis,[inviso_rt]), + ?l true=is_pid(P1), + ?l rpc:call(RNode,erlang,exit,[P1,kill]), + ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), + ?l ok=rpc:call(RNode,application,start,[runtime_tools]), + timer:sleep(1000), + ?l P2=rpc:call(RNode,erlang,whereis,[inviso_rt]), + ?l true=is_pid(P2), + ?l rpc:call(RNode,erlang,exit,[P2,kill]), + ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), + ?l ok=rpc:call(RNode,application,start,[runtime_tools]), + timer:sleep(1000), + ?l undefined=rpc:call(RNode,erlang,whereis,[inviso_rt]), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Test of autostart. Here we focus on that an autostarted +%% runtime component actually follows the trace case command file and +%% initiates tracing. +autostart_dist_2(suite) -> []; +autostart_dist_2(doc) -> + [""]; +autostart_dist_2(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + PrivDir=filename:join(?config(priv_dir,Config),""), + AutoConfFile=filename:join(PrivDir,"autostart2.conf"), + [RNode|_]=RemoteNodes, + ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), + ?l ok=rpc:call(RNode,application,set_env,[runtime_tools, + inviso_autostart_conf, + AutoConfFile]), + ?l CmdFileName=filename:join(PrivDir,"autostart_cmd_as1"), + ?l {ok,FD}=file:open(CmdFileName,[write]), + ?l ok=io:format(FD, + "inviso:tpl(Nodes,M,F,Arity,[]).~n" + "inviso:tf(Nodes,inviso_test_proc,[call]).~n", + []), + ?l file:close(FD), + ?l TraceFileName=filename:join([PrivDir,"as1_"++atom_to_list(RNode)]), + ?l TiFileName=filename:join([PrivDir,"as1_"++atom_to_list(RNode)++".ti"]), + ?l inviso_as_lib:setup_autostart(RNode, + 2, + [], + [{trace,{file,TraceFileName}}, + {ti,{file,TiFileName}}], + [[CmdFileName]], + [{'M',code},{'F',which},{'Arity',1}], + [{{inviso,tpl,5},{inviso_rt,tpl,{erlang,tl}}}, + {{inviso,tf,3},{inviso_rt,tf,{erlang,tl}}}]), + ?l TestP=spawn(RNode,?MODULE,test_proc_init,[]), + ?l ok=rpc:call(RNode,application,start,[runtime_tools]), + ?l timer:sleep(1000), + ?l {ok,_}=file:read_file_info(TraceFileName), + ?l {ok,_}=file:read_file_info(TiFileName), + ?l true=is_pid(P=rpc:call(RNode,erlang,whereis,[inviso_rt])), + ?l ok=poll(rpc,call,[RNode,erlang,trace_info,[{code,which,1},traced]],{traced,local},10), + ?l {flags,[call]}=rpc:call(RNode,erlang,trace_info,[TestP,flags]), + ?l rpc:call(RNode,erlang,exit,[P,kill]), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Here we test that an autostarted runtime component with a dependency +%% to a specific control component tries to connect to that control component +%% during its start-up. +autostart_dist_3(suite) -> []; +autostart_dist_3(doc) -> + [""]; +autostart_dist_3(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + PrivDir=filename:join(?config(priv_dir,Config),""), + AutoConfFile=filename:join(PrivDir,"autostart3.conf"), + [RNode|_]=RemoteNodes, + ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), + ?l ok=rpc:call(RNode,application,set_env,[runtime_tools, + inviso_autostart_conf, + AutoConfFile]), + ?l {ok,FD}=file:open(AutoConfFile,[write]), + ?l ok=io:format(FD,"~w.~n~w.~n~w.~n", + [{options,[{dependency,{infinity,node()}}]},{repeat,2},{tag,c_ref}]), + ?l file:close(FD), + %% Now start inviso at this node here for the runtime to connect. + ?l {ok,_Pid}=inviso:start(), + ?l ok=poll(erlang,whereis,[inviso_c],fun(P) when is_pid(P)->true;(_)->false end,10), + %% Make the runtime component start. + ?l ok=rpc:call(RNode,application,start,[runtime_tools]), + ?l ok=poll(rpc,call,[RNode,erlang,whereis,[inviso_rt]], + fun(P) when is_pid(P)->true;(_)->false end,10), + %% Check that the runtime component started. + ?l ok=poll(inviso,get_status,[[RNode]],{ok,[{RNode,{ok,{new,running}}}]},20), +% ?l {ok,[{RNode,{ok,{new,running}}}]}=inviso:get_status([RNode]), + stop([RNode]), + ok. +%% ----------------------------------------------------------------------------- + + + +%% TEST CASE: Test of the dependency mechanism in the runtime component. +%% Default behaviour is dependency=infinity, i.e the runtime components remains. +%% We also test here that we can reconnect to the runtime. +running_alone_dist_1(suite) -> []; +running_alone_dist_1(doc) -> + [""]; +running_alone_dist_1(Config) when is_list(Config) -> + ?l {ok,_Pid1}=inviso:start(), % Start a control component. + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l shutdown=inviso:stop(), % Stop the control component! + ?l undefined=whereis(inviso_c), + timer:sleep(3000), % How long shall we wait? :-) + ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, + Nodes), + ?l {ok,_Pid2}=inviso:start(), + ?l {ok,NodeResults2}=inviso:add_nodes(Nodes,b_ref,[]), + ?l true=check_noderesults(Nodes,{ok,{adopted,new,running,a_ref}},NodeResults2), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Test of the dependency mechanism in the runtime component. +%% Test that the runtime components terminates after the specified 5000 ms. +running_alone_dist_2(suite) -> []; +running_alone_dist_2(doc) -> + [""]; +running_alone_dist_2(Config) when is_list(Config) -> + ?l {ok,_Pid1}=inviso:start(), % Start a control component. + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[{dependency,5000}]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l shutdown=inviso:stop(), % Stop the control component! + ?l undefined=whereis(inviso_c), + timer:sleep(2000), + ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, + Nodes), + timer:sleep(4000), % Now they shall be dead! + ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, + Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Test of the dependency mechanism in the runtime component. +%% Test that the runtime components terminates after the specified 5000 ms. +running_alone_dist_3(suite) -> []; +running_alone_dist_3(doc) -> + [""]; +running_alone_dist_3(Config) when is_list(Config) -> + ?l {ok,_Pid1}=inviso:start(), % Start a control component. + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[{dependency,1000}]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l {ok,NodeResults2}=inviso:change_options(Nodes,[{dependency,5000}]), + ?l true=check_noderesults(Nodes,ok,NodeResults2), + ?l shutdown=inviso:stop(), % Stop the control component! + ?l undefined=whereis(inviso_c), + timer:sleep(3000), + ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, + Nodes), + timer:sleep(3000), % Now they shall be dead! + ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, + Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Test of the dependency mechanism in the runtime component. +%% Test that the runtime components terminates after the specified 5000 ms, +%% like we did in running_alone_dist_2. But now we also start tracing and checks +%% that all inviso processes actually disappears when the time-out is reached. +running_alone_dist_4(suite) -> []; +running_alone_dist_4(doc) -> + [""]; +running_alone_dist_4(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + %% Start some tracing! + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataFun= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_ra4"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"tf_ra4_"++atom_to_list(N)++".ti"])}}]} + end, + TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes, + [{dependency,5000}], + TracerDataList, + {ok,[{trace_log,ok},{ti_log,ok}]}), + + ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, + Nodes), + ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end, + Nodes), + %% Stop control component and wait for the runtimes to terminate after + %% running alone timer has expired. + ?l shutdown=inviso:stop(), % Stop the control component! + ?l undefined=whereis(inviso_c), + timer:sleep(2000), + ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, + Nodes), + ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end, + Nodes), + timer:sleep(4000), % Now they shall be dead! + ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, + Nodes), + ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt_meta]) end, + Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Test of the dependency mechanism in the runtime component. +%% Test that the runtime components terminates imeediately when the control +%% component is stopped. Check that all processes are gone. +running_alone_dist_5(suite) -> []; +running_alone_dist_5(doc) -> + [""]; +running_alone_dist_5(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + %% Start some tracing! + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataFun= + fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_ra5"++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir,"tf_ra5_"++atom_to_list(N)++".ti"])}}]} + end, + TracerDataList=lists:map(TracerDataFun,Nodes), + start_and_init_tracing2(Nodes, + [{dependency,0}], + TracerDataList, + {ok,[{trace_log,ok},{ti_log,ok}]}), + + ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, + Nodes), + ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end, + Nodes), + %% Stop control component and check that all runtime component processes have + %% terminate more or less immediately afterwards, since dependency==0. + ?l shutdown=inviso:stop(), % Stop the control component! + timer:sleep(100), + ?l undefined=whereis(inviso_c), + timer:sleep(500), + ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, + Nodes), + ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt_meta]) end, + Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Test of the overload protection mechanism. The mechanism checks +%% for overload using the callback approximately at the interval specified. +%% Check that it does not start protection until start of tracing. +overload_dist_1(suite) -> []; +overload_dist_1(doc) -> + [""]; +overload_dist_1(Config) when is_list(Config) -> + ?l {ok,_Pid1}=inviso:start(), % Start a control component. + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + ?l lists:foreach(fun(N)->true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl1,0}]) end, + Nodes), % Initiate the counter. + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, + a_ref, + [{overload,{{?MODULE,overload1},500}}]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + timer:sleep(1000), % Give the loadcheck time to perform. + ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl1), % Nothing should have happened. + + %% Overload check shall not start until we start tracing. + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList=lists:map(fun(N)->{N,[{trace, + {file,filename:join([PrivDir, + "tf_ovl1."++atom_to_list(N) + ])}}]} + end, + Nodes), + ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), + ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), + timer:sleep(1500), % Give the loadcheck time to perform. + ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl1), + ?l true=(N>=2), % After 1,5 seconds, at least 2 checks. + + %% Now change options and remove overload checking! + ?l {ok,NodeResults3}=inviso:change_options(Nodes,[overload]), + ?l true=check_noderesults(Nodes,ok,NodeResults3), + ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl1), + timer:sleep(1000), + ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl1), % No more loadchecks! + + stop_tracing(Nodes), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Test of the overload protection mechanism. In this case we focus +%% in that the init and remove functions are carried out at change_options and +%% when starting and stoping the runtime component. +overload_dist_2(suite) -> []; +overload_dist_2(doc) -> + [""]; +overload_dist_2(Config) when is_list(Config) -> + ?l {ok,_Pid1}=inviso:start(), % Start a control component. + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, + a_ref, + [{overload,{{?MODULE,overload2}, + 500, + {?MODULE,overload2i,[]}, + {?MODULE,overload2r,[]}}}]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl2), + + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList=lists:map(fun(N)->{N,[{trace, + {file,filename:join([PrivDir, + "tf_ovl2."++atom_to_list(N) + ])}}]} + end, + Nodes), + ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), + ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), + timer:sleep(1500), % Give the loadcheck time to perform. + ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl2), + io:format("� is:~p~n",[N]), + ?l true=(N>=2), % After 1,5 seconds, at least 2 checks. + ?l {ok,NodeResults3}=inviso:change_options(Nodes,[{overload,{{?MODULE,overload3}, + 500, + {?MODULE,overload3i,[]}, + {?MODULE,overload3r,[]}}}]), + ?l true=check_noderesults(Nodes,ok,NodeResults3), + ?l []=ets:lookup(inviso_sideeffect_tab,ovl2), + timer:sleep(1500), + ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl3), + ?l true=(N2>=2), % After 1,5 seconds, at least 2 checks. + stop_tracing(Nodes), + ?l []=ets:lookup(inviso_sideeffect_tab,ovl3r), % Remove function shall not be called. + ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl3), + timer:sleep(1000), % Check that overloadchecking has stopped. + ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl3), + stop(Nodes), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl3r],[{ovl3r,done}],20), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Test of the overload protections mechanism. Here we focus on testing +%% that if overload is reached tracing is really suspended. +overload_dist_3(suite) -> []; +overload_dist_3(doc) -> + [""]; +overload_dist_3(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList= + lists:map(fun(N)->{N,[{trace,{file,filename:join([PrivDir, + "tf_ovl3."++atom_to_list(N)])}}, + {ti,{file,filename:join([PrivDir, + "tf_ovl3_ti."++atom_to_list(N)])}}]} + end, + Nodes), + ?l lists:foreach(fun(N)-> + true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl4,0}]) + end, + Nodes), + start_and_init_tracing2(Nodes, + [{overload,{{?MODULE,overload4},500}}], + TracerDataList, + {ok,[{trace_log,ok},{ti_log,ok}]}), + activate_local_tracing(Nodes), + activate_meta_tracing(Nodes), + activate_traceflags(Nodes), + timer:sleep(600), + ?l [{_,N1}]=ets:lookup(inviso_sideeffect_tab,ovl4), + ?l true=(N1>=1), % Overload check has been done! + ?l Node=node(), + ?l {ok,[{Node,{ok,{tracing,running}}}]}=inviso:get_status([node()]), + ?l true=ets:insert(inviso_sideeffect_tab,{ovl4_suspend,true}), + timer:sleep(600), + ?l {ok,[{Node,{ok,{tracing,{suspended,test}}}}]}=inviso:get_status([node()]), + ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl4), + ?l {flags,[]}=erlang:trace_info(whereis(inviso_test_proc),flags), + ?l {meta,false}=erlang:trace_info({lists,module_info,0},meta), + ?l {traced,local}=erlang:trace_info({code,which,1},traced), + ?l true=(is_pid(whereis(inviso_rt_meta))), + ?l true=ets:delete(inviso_sideeffect_tab,ovl4_suspend), + timer:sleep(600), + ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl4), % No checking while suspended! + ?l {ok,[{Node,ok}]}=inviso:cancel_suspension([node()]), + ?l {ok,NodeResults1}=inviso:get_status(Nodes), + ?l true=check_noderesults(Nodes,{ok,{tracing,running}},NodeResults1), + timer:sleep(600), + ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl4), + ?l true=(N3>N2), + ?l deactivate_local_tracing(Nodes), + ?l stop_tracing(Nodes), + ?l stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE. Test that the overload mechanism is triggered by to the runtime +%% component incomming messages, and nothing else. +overload_dist_4(suite) -> []; +overload_dist_4(doc) -> + [""]; +overload_dist_4(Config) when is_list(Config) -> + ?l {ok,_Pid1}=inviso:start(), % Start a control component. + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, + a_ref, + [{overload,{{?MODULE,overload5}, + infinity, + {?MODULE,overload5i,[]}, + {?MODULE,overload5r,[]}}}]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl5), + + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList=lists:map(fun(N)->{N,[{trace, + {file,filename:join([PrivDir, + "tf_ovl4."++atom_to_list(N) + ])}}]} + end, + Nodes), + ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), + ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), + timer:sleep(2000), % Give the loadcheck time to perform. + ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl5), + ?l true=(N==0), % And nothing shall have happend! + %% Now we send a message to the inviso_rt, then the load check function + %% shall be called. + ?l whereis(inviso_rt) ! test_of_loadcheck, + timer:sleep(200), % Make sure the inviso_rt gets scheduled. + ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,ovl5), + stop_tracing(Nodes), + ?l []=ets:lookup(inviso_sideeffect_tab,ovl5r), % Remove function shall not be called. + ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl5), + ?l whereis(inviso_rt) ! test_of_loadcheck, + timer:sleep(1000), % Check that overloadchecking has stopped. + ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl5), + stop(Nodes), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl5r],[{ovl5r,done}],20), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE. Test that the overload mechanism correctly calculates remaining time +%% to next load check if a message comes into the runtime component "interupting" +%% the waiting for loadcheck timeout. (Loadcheck timeout is implemented as an after +%% in the receive). +overload_dist_5(suite) -> []; +overload_dist_5(doc) -> + [""]; +overload_dist_5(Config) when is_list(Config) -> + ?l {ok,_Pid1}=inviso:start(), % Start a control component. + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + ?l lists:foreach(fun(N)->true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl6,0}]) end, + Nodes), % Initiate the counter. + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, + a_ref, + [{overload,{{?MODULE,overload6},1000}}]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + %% Overload check shall not start until we start tracing. + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList=lists:map(fun(N)->{N,[{trace, + {file,filename:join([PrivDir, + "tf_ovl5."++atom_to_list(N) + ])}}]} + end, + Nodes), + ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), + ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl6],[{ovl6,2}],25), + %% Now we know that exactly 2 checks have been made. Try to Distract the runtime :-) + ?l inviso_rt:state(whereis(inviso_rt)), % Make it have to receive a message. + timer:sleep(500), + ?l [{_,2}]=ets:lookup(inviso_sideeffect_tab,ovl6), % Should still be 2. + timer:sleep(600), + ?l [{_,3}]=ets:lookup(inviso_sideeffect_tab,ovl6), % We expect yet one check. + timer:sleep(1100), + ?l [{_,4}]=ets:lookup(inviso_sideeffect_tab,ovl6), + + stop_tracing(Nodes), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + + +%% TEST CASE: Test of the subscription mechanism. +subscribe_dist_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + Pid=spawn(?MODULE,inviso_msg_collector,[]), + CtrlPid=whereis(inviso_c), + + ?l {ok,_Pid}=inviso:start(), % Start a control component. + ?l ok=inviso:subscribe(Pid), + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l {ok,NodeResults2}=inviso:get_status(Nodes), + ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2), + check_msg_collector(Nodes, + fun({inviso_event,CP,_,{connected,N,{_Tag,{idle,running}}}}) + when CP==CtrlPid -> + {true,N}; + (_) -> + false + end, + 13), + TracerDataList=lists:map(fun(N)->{N,{file, + filename:join([PrivDir, + "tf_sub1"++atom_to_list(N)])}} + end, + Nodes), + ?l {ok,NodeResults3}=inviso:init_tracing(TracerDataList), + ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults3), + check_msg_collector(Nodes, + fun({inviso_event,CP,_,{state_change,N,{tracing,running}}}) + when CP==CtrlPid -> + {true,N}; + (_) -> + false + end, + 13), + ?l {ok,NodeResults4}=inviso:suspend(Nodes,test), + ?l true=check_noderesults(Nodes,ok,NodeResults4), + check_msg_collector(Nodes, + fun({inviso_event,CP,_,{state_change,N,{tracing,{suspended,test}}}}) + when CP==CtrlPid -> + {true,N}; + (_) -> + false + end, + 13), + ?l [RNode|_]=RemoteNodes, + ?l RInvisoPid=rpc:call(RNode,erlang,whereis,[inviso_rt]), + ?l rpc:call(RNode,erlang,exit,[RInvisoPid,kill]), + check_msg_collector([RNode], + fun({inviso_event,CP,_,{disconnected,N,_Info}}) + when CP==CtrlPid -> + {true,N}; + (_) -> + false + end, + 11), + + ?l {ok,_NodeResults5}=inviso:stop_tracing(Nodes), + ?l {ok,_NodeResults6}=inviso:stop_nodes(Nodes), + ?l shutdown=inviso:stop(), + ok. +%% ----------------------------------------------------------------------------- + + +%% TEST CASE: fetch_log test of single straight trace_log file in distributed +%% environment. +fetch_log_dist_trace_1(suite) -> []; +fetch_log_dist_trace_1(doc) -> + ["fetch_log test of single straight trace_log file in distributed" + "environment."]; +fetch_log_dist_trace_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList=lists:map(fun(N)->{N,[{trace,{file,filename:join([PrivDir, + "testfile1."++ + atom_to_list(N) + ])}}]} end, + Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), + + %% Put some output in the logs. + ?l inviso:tp(Nodes,math,module_info,0,[]), + ?l inviso:tf(Nodes,all,[call]), + ?l lists:foreach(fun(N)->rpc:call(N,math,module_info,[]) end,Nodes), + + stop_tracing(Nodes), + {H,M,S}=time(), + FetchToDir=filename:join([PrivDir, + "fetch_log_test1_"++integer_to_list(H)++"_"++ + integer_to_list(M)++"_"++integer_to_list(S)]), + ?l ok=file:make_dir(FetchToDir), + ?l {ok,NodeResults}=inviso:fetch_log(RemoteNodes,FetchToDir,"p1"), + io:format("~p~n",[NodeResults]), + ?l true=check_noderesults(RemoteNodes, + fun({N,{complete,[{trace_log,[{ok,File}]},{ti_log,[]}]}}) -> + ?l File="p1testfile1."++atom_to_list(N), + true; + (_)-> + false + end, + NodeResults), + ?l ON=filename:join(PrivDir,"testfile1."), + ?l FN=filename:join(FetchToDir,"p1testfile1."), + ?l lists:foreach(fun(N)-> + {ok,#file_info{size=Size}}= + file:read_file_info(ON++atom_to_list(N)), + {ok,#file_info{size=Size}}= + file:read_file_info(FN++atom_to_list(N)) + end, + RemoteNodes), + %% Now we wish to see that we get an incomplete if we try to fetch to a + %% directory that does not exist. + ?l FetchToErrorDir=filename:join([PrivDir,nonexistingingdir]), + ?l {ok,NodeResults2}=inviso:fetch_log(RemoteNodes,FetchToErrorDir,"p1"), + ?l io:format("NodeResults2:~w~n",[NodeResults2]), + ?l true=check_noderesults(RemoteNodes, + fun({_,{incomplete,_}}) -> + true; + (_)-> + false + end, + NodeResults2), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +fetch_log_dist_trace_2(suite) -> []; +fetch_log_dist_trace_2(doc) -> + [""]; +fetch_log_dist_trace_2(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + + {H,M,S}=time(), + ?l Name="wrap"++integer_to_list(H)++"_"++integer_to_list(M)++"_"++integer_to_list(S), + ?l BaseName=filename:join(PrivDir,Name), + Fun=fun(N)->{N,[{trace,{file,{BaseName++atom_to_list(N),wrap,".log",512,2}}}, + {ti,{file,BaseName++"_ti_"++atom_to_list(N)++".ti"}}]} + end, + ?l TracerDataList=lists:map(Fun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + fill_and_reach_two_wrapfiles(PrivDir,"^"++Name,Nodes), + + stop_tracing(Nodes), + FetchToDir=filename:join([PrivDir, + "fetch_log_test2_"++integer_to_list(H)++"_"++ + integer_to_list(M)++"_"++integer_to_list(S)]), + ?l ok=file:make_dir(FetchToDir), + ?l {ok,NodeResults}=inviso:fetch_log(RemoteNodes,FetchToDir,"p1"), + io:format("~p~n",[NodeResults]), + CheckFun=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) -> + Fun2=fun({ok,File}) -> + {match,1,_}= + regexp:first_match(File, + "^"++"p1"++Name++atom_to_list(N)), + true; + (_) -> + false + end, + ?l true=lists:all(Fun2,FileResults1), + ?l TiFile="p1"++Name++"_ti_"++atom_to_list(N)++".ti", + true; + (_)-> + false + end, + ?l true=check_noderesults(RemoteNodes,CheckFun,NodeResults), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +fetch_log_dist_trace_3(suite) -> []; +fetch_log_dist_trace_3(doc) -> + [""]; +fetch_log_dist_trace_3(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + + {H,M,S}=time(), + ?l Name="wrap2_"++integer_to_list(H)++"_"++integer_to_list(M)++"_"++integer_to_list(S), + ?l BaseName=filename:join(PrivDir,Name), + Fun=fun(N)->{N,[{trace,{file,{BaseName++atom_to_list(N),wrap,".log",512,2}}}, + {ti,{file,BaseName++"_ti_"++atom_to_list(N)++".ti"}}]} + end, + ?l TracerDataList=lists:map(Fun,Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + fill_and_reach_two_wrapfiles(PrivDir,"^"++Name,Nodes), + + stop_tracing(Nodes), + FetchToDir=filename:join([PrivDir, + "fetch_log_test3_"++integer_to_list(H)++"_"++ + integer_to_list(M)++"_"++integer_to_list(S)]), + ?l ok=file:make_dir(FetchToDir), + ?l {ok,NodeResults1}=inviso:list_logs(Nodes), + CheckFun=fun({N,{ok,[{trace_log,PrivDir2,[F1,F2]},{ti_log,PrivDir2,[F3]}]}})-> + PrivDir2=PrivDir, + RegExp="^"++Name++atom_to_list(N)++"[0-9]+"++"\.log", + {match,1,_}=regexp:first_match(F1,RegExp), + {match,1,_}=regexp:first_match(F2,RegExp), + F3=Name++"_ti_"++atom_to_list(N)++".ti", + true; + (_) -> + false + end, + ?l true=check_noderesults(Nodes,CheckFun,NodeResults1), + ?l NodeFileSpecList=lists:map(fun({N,{ok,L}})->{N,L} end, + lists:keydelete(node(),1,NodeResults1)), + ?l {ok,NodeResults2}=inviso:fetch_log(NodeFileSpecList,FetchToDir,"p1"), +io:format("~p~n",[NodeResults2]), + CheckFun2=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) -> + Fun2=fun({ok,File}) -> + {match,1,_}= + regexp:first_match(File, + "^"++"p1"++Name++atom_to_list(N)), + true; + (_) -> + false + end, + ?l true=lists:all(Fun2,FileResults1), + ?l TiFile="p1"++Name++"_ti_"++atom_to_list(N)++".ti", + true; + (_)-> + false + end, + ?l true=check_noderesults(RemoteNodes,CheckFun2,NodeResults2), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +fetch_log_dist_error_1(suite) -> []; +fetch_log_dist_error_1(doc) -> + [""]; +fetch_log_dist_error_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + ?l {ok,_Pid}=inviso:start(), % Start a control component. + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l {ok,NodeResults2}=inviso:fetch_log(RemoteNodes,"foo","bar"), +io:format("~p~n",[NodeResults2]), + ?l true=check_noderesults(RemoteNodes, + fun({_N,{error,no_tracerdata}})->true; + (_)->false + end, + NodeResults2), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +fetch_log_dist_error_2(suite) -> []; +fetch_log_dist_error_2(doc) -> + [""]; +fetch_log_dist_error_2(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + PrivDir=filename:join(?config(priv_dir,Config),""), + ?l {ok,_Pid}=inviso:start(), % Start a control component. + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l NodeLogList=lists:map(fun(N)->{N,[{trace_log, + PrivDir, + ["f1,fil","f2.fil"]}, + {ti_log, + PrivDir, + ["f.ti"]}]} + end, + RemoteNodes), + ?l {ok,NodeResults2}=inviso:fetch_log(NodeLogList,"foo","bar"), + io:format("~p~n",[NodeResults2]), + ?l true=check_noderesults(RemoteNodes, + fun({_N,{incomplete,_}}) -> + true; + (_) -> + false + end, + NodeResults2), + ?l NodeTracerData=lists:map(fun(N)->{N, + [{trace,{file,filename:join(PrivDir,"foo")}}, + {ti,{file,filename:join(PrivDir,"bar.ti")}}]} + end, + RemoteNodes), + {ok,NodeResults3}=inviso:fetch_log(NodeTracerData,"foo","bar"), + io:format("~p~n",[NodeResults3]), +%% This should work this way. Now it says complete [], which is not entirely +%% incorrect. But to follow the sematics of when fetching named files should +%% say incomplete. +%% Must do some rework to make that work. No real danger leaving it this way +%% for now. +% ?l true=check_noderesults(RemoteNodes, +% fun({_N,{incomplete,_}}) -> +% true; +% (_) -> +% false +% end, +% NodeResults3), + stop(Nodes), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: This case tests that the log file merger merges files in the +%% correct order, based on the timestamps. +lfm_trace_dist_1(suite) -> []; +lfm_trace_dist_1(doc) -> + [""]; +lfm_trace_dist_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + [RNode1,RNode2|_]=RemoteNodes, + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList= + lists:map(fun(N)->{N,{file,filename:join([PrivDir,"lfm1_"++atom_to_list(N)])}} end, + Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), + activate_local_tracing(Nodes), + activate_traceflags(Nodes), + + {inviso_test_proc,RNode2} ! {apply,code,which,[lists]}, + timer:sleep(300), + {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, + timer:sleep(300), + {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, + timer:sleep(300), + inviso_test_proc ! {apply,code,which,[lists]}, + timer:sleep(300), + {inviso_test_proc,RNode2} ! {apply,code,which,[lists]}, + timer:sleep(300), + inviso_test_proc ! {apply,code,which,[lists]}, + + deactivate_traceflags(Nodes), + deactivate_local_tracing(Nodes), + stop_tracing(Nodes), + stop(Nodes), + + DestFile=filename:join(PrivDir,"lfm1_out.txt"), + ?l {ok,6}= + inviso_lfm:merge([{node(), + [{trace_log, + [filename:join(PrivDir,"lfm1_"++atom_to_list(node()))]}]}, + {RNode1, + [{trace_log, + [filename:join(PrivDir,"lfm1_"++atom_to_list(RNode1))]}]}, + {RNode2, + [{trace_log, + [filename:join(PrivDir,"lfm1_"++atom_to_list(RNode2))]}]}], + DestFile), + ?l {ok,FD}=file:open(DestFile,[read]), + ?l S1=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode2),S1), + ?l S2=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode1),S2), + ?l S3=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode1),S3), + ?l S4=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(node()),S4), + ?l S5=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode2),S5), + ?l S6=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(node()),S6), + ?l file:close(FD), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: Testing to the full extent that pid-mappings work with both +%% local and global registration. Also checks that pidmappings can be removed +%% and that consequently the mappings in the resulting merged file stops. +lfm_trace_ti_dist_2(suite) -> []; +lfm_trace_ti_dist_2(doc) -> + [""]; +lfm_trace_ti_dist_2(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + [RNode1,RNode2|_]=RemoteNodes, + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList= + lists:map(fun(N)->{N,[{trace,{file,filename:join(PrivDir,"lfm2_"++atom_to_list(N))}}, + {ti,{file,filename:join(PrivDir,"lfm2_ti_"++atom_to_list(N))}}]} + end, + Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), + activate_local_tracing(Nodes), + activate_meta_tracing(Nodes), + activate_traceflags(Nodes), + + {inviso_test_proc,RNode2} ! {apply,code,which,[lists]}, + timer:sleep(300), + {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, + timer:sleep(300), + {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, + timer:sleep(300), + inviso_test_proc ! {apply,code,which,[lists]}, + timer:sleep(300), + + P2=spawn(RNode2,?MODULE,test_proc_loop,[]), + P1=spawn(RNode1,?MODULE,test_proc_loop,[]), + P0=spawn_link(?MODULE,test_proc_loop,[]), + ThisNode=node(), + ?l {ok,[{ThisNode,{ok,[1]}}]}=inviso:tf([node()],P0,[call,timestamp]), + ?l {ok,[{RNode1,{ok,[1]}}]}=inviso:tf([RNode1],P1,[call,timestamp]), + ?l {ok,[{RNode2,{ok,[1]}}]}=inviso:tf([RNode2],P2,[call,timestamp]), + P2 ! {apply,code,which,[lists]}, + timer:sleep(300), + P1 ! {apply,code,which,[lists]}, + timer:sleep(300), + P0 ! {apply,code,which,[lists]}, + timer:sleep(300), + + P3=spawn(RNode2,?MODULE,test_proc_loop,[]), + ?l yes=global:register_name(inviso_test_proc_globalname,P3), + ?l {ok,[{RNode2,{ok,[1]}}]}=inviso:tf([RNode2],P3,[call,timestamp]), + timer:sleep(300), + P3 ! {apply,code,which,[lists]}, + timer:sleep(300), + + P4=rpc:call(RNode1,erlang,whereis,[inviso_test_proc]), + ?l true=rpc:call(RNode1,erlang,unregister,[inviso_test_proc]), + timer:sleep(300), + P4 ! {apply,code,which,[lists]}, + timer:sleep(300), + + ?l true=rpc:call(RNode1,erlang,register,[inviso_test_proc,P4]), + + ?l global:unregister_name(inviso_test_proc_globalname), + timer:sleep(300), + ?l P3 ! {apply,code,which,[lists]}, + timer:sleep(300), + + deactivate_traceflags(Nodes), + deactivate_local_tracing(Nodes), + stop_tracing(Nodes), + stop(Nodes), + + DestFile=filename:join(PrivDir,"lfm2_out.txt"), + ?l {ok,10}= + inviso_lfm:merge([ + {node(), + [{trace_log, + [filename:join(PrivDir,"lfm2_"++atom_to_list(node()))]}, + {ti_log, + [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(node()))]}]}, + {RNode1, + [{trace_log, + [filename:join(PrivDir,"lfm2_"++atom_to_list(RNode1))]}, + {ti_log, + [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(RNode1))]}]}, + {RNode2, + [{trace_log, + [filename:join(PrivDir,"lfm2_"++atom_to_list(RNode2))]}, + {ti_log, + [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(RNode2))]}]} + ], + DestFile), + ?l {ok,FD}=file:open(DestFile,[read]), + ?l S1=io:get_line(FD,""), +io:format("S1 is:~p~n",[S1]), + ?l true=lists:prefix(atom_to_list(RNode2)++" [inviso_test_proc",S1), + ?l S2=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode1)++" [inviso_test_proc",S2), + ?l S3=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode1)++" [inviso_test_proc",S3), + ?l S4=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(node())++" [inviso_test_proc",S4), + ?l S5=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode2)++" []",S5), + ?l S6=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode1)++" []",S6), + ?l S7=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(node())++" []",S7), + ?l S8=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode2)++" [{global,inviso_test_proc_globalname}]",S8), + ?l S9=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode1)++" []",S9), + ?l S10=io:get_line(FD,""), + ?l true=lists:prefix(atom_to_list(RNode2)++" []",S10), + ?l file:close(FD), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: This tests that the wrapset sorter works. +handle_logfile_sort_wrapset(suite) -> []; +handle_logfile_sort_wrapset(doc) -> + [""]; +handle_logfile_sort_wrapset(Config) when is_list(Config) -> + File0="prefix10.fil", + File1="prefix11.fil", + File2="prefix12.fil", + File3="prefix13.fil", + ?l [File0,File1,File2,File3]= + inviso_lfm_tpfreader:handle_logfile_sort_wrapset([File2,File1,File0,File3]), + File5="prefix15.fil", + ?l [File5,File0,File1,File2,File3]= + inviso_lfm_tpfreader:handle_logfile_sort_wrapset([File2,File5,File1,File0,File3]), + ok. +%% ----------------------------------------------------------------------------- + +%% TEST CASE: This case tests that the regexp mechanism in the inviso_rt_lib can +%% find modules using regexps and that its only_loaded mechanism works. +%% This test case can not be run when using cover because cover will make the +%% modules no longer loaded from the path containing "runtime_tools". +expand_regexp_dist_1(suite) -> []; +expand_regexp_dist_1(doc) -> + [""]; +expand_regexp_dist_1(Config) when is_list(Config) -> + case ?t:is_cover() of + true -> + {skip,"Cover is running"}; + false -> + expand_regexp_dist_1_nocover(Config) + end. + +expand_regexp_dist_1_nocover(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + [RNode1|_]=RemoteNodes, + ?l NodeResults1=inviso_rt_lib:expand_regexp(Nodes,"^inviso_rt.*",[]), + ?l L1=length(Nodes), + ?l L1=length(NodeResults1), + ?l true=lists:all(fun({_,Mods})-> + ?l 3=length(Mods), + ?l true=lists:member(inviso_rt,Mods), + ?l true=lists:member(inviso_rt_lib,Mods), + ?l true=lists:member(inviso_rt_meta,Mods), + true; + (_) -> + false + end, + NodeResults1), + %% Check the dir-option. In the following inviso_tool_lib shall not be found. + ?l NodeResults2=inviso_rt_lib:expand_regexp(Nodes,"runtime_tools","invi.*lib.*",[]), +?l io:format("NodeResults2:~w~n",[NodeResults2]), + ?l L1=length(NodeResults2), % Same number of nodes replying. + ?l true=lists:all(fun({_,Mods})-> + 2=length(Mods), + true=lists:member(inviso_as_lib,Mods), + true=lists:member(inviso_rt_lib,Mods), + true; + (_) -> + false + end, + NodeResults2), + ?l [{RNode1,[]}]= + inviso_rt_lib:expand_regexp([RNode1],"^inviso_testmodule1.*",[only_loaded]), + ?l [{RNode1,[inviso_testmodule1_foo]}]= + inviso_rt_lib:expand_regexp([RNode1],"^inviso_testmodule1.*",[]), + ok. +%% ----------------------------------------------------------------------------- + + +only_loaded_dist_1(suite) -> []; +only_loaded_dist_1(doc) -> + [""]; +only_loaded_dist_1(Config) when is_list(Config) -> + RemoteNodes=get_remotenodes_config(Config), + Nodes=[node()|RemoteNodes], + [RNode1|_]=RemoteNodes, + PrivDir=filename:join(?config(priv_dir,Config),""), + TracerDataList= + lists:map(fun(N)->{N,[{trace,{file,filename:join(PrivDir,"ol_1_"++atom_to_list(N))}}]} + end, + Nodes), + start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), + ?l false=rpc:call(RNode1,erlang,module_loaded,[inviso_testmodule1_foo]), + ?l {ok,[{RNode1,{ok,[0]}}]}= + inviso:tpl([RNode1],inviso_testmodule1_foo,'_','_',[],[only_loaded]), + ?l false=rpc:call(RNode1,erlang,module_loaded,[inviso_testmodule1_foo]), + ?l {ok,[{RNode1,{ok,[3]}}]}= + inviso:tpl([RNode1],inviso_testmodule1_foo,'_','_',[],[]), + stop_tracing(Nodes), + stop(Nodes), + ok. + + +%% ============================================================================== +%% Common functions setting up inviso. +%% ============================================================================== + +%% Starts controlcomponent and adds runtime components on the nodes specified. +%% Also initiates tracing on the nodes. +start_and_init_tracing1(Nodes,Options,TracerData,Reply) when is_list(Nodes) -> + ?l {ok,_Pid}=inviso:start(), % Start a control component. + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,Options), + io:format("~p~n",[NodeResults1]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l {ok,NodeResults2}=inviso:get_status(Nodes), + ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2), + ?l {ok,NodeResults3}=inviso:init_tracing(Nodes,TracerData), + ?l true=check_noderesults(Nodes,Reply,NodeResults3), + ok. +start_and_init_tracing2(Nodes,Options,TracerDataList,Reply) -> + ?l {ok,_Pid}=inviso:start(), % Start a control component. + ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,Options), + io:format("~p~n",[NodeResults1]), + ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), + ?l {ok,NodeResults2}=inviso:get_status(Nodes), + ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2), + ?l {ok,NodeResults4}=inviso:get_tracerdata(Nodes), + ?l true=check_noderesults(Nodes,{ok,no_tracerdata},NodeResults4), + ?l {ok,NodeResults3}=inviso:init_tracing(TracerDataList), + io:format("Tracerdatalist:~p~n",[TracerDataList]), + ?l true=check_noderesults(Nodes,Reply,NodeResults3), + + ?l Fun1=fun({N,{ok,TD}}) when is_list(TD)-> + ?l {value,{trace,Trace}}=lists:keysearch(trace,1,TD), + ?l {value,{N,TD2}}=lists:keysearch(N,1,TracerDataList), + ?l true=lists:member({trace,Trace},TD2), + %% Check that the trace file really exists. + ?l case Trace of % Trace={file,FilePortParameters} + {file,FileName1} when is_list(FileName1) -> + ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName1]); + _ -> % This should be extended with more cases. + true + end, + ?l case lists:keysearch(ti,1,TD2) of + {value,{_,Ti}} -> % Ok, we have ti too. + ?l {value,{_,Ti}}=lists:keysearch(ti,1,TD), + ?l FileName2=element(2,Ti), + ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName2]), + true; + false -> % No ti, we are done now. + true + end; + ({N,{ok,{file,FileName}}}) -> + ?l {value,{N,{file,FileName}}}=lists:keysearch(N,1,TracerDataList), + ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName]), + true; + ({N,{ok,LogTD}}) -> % The case using a fun. + ?l {value,{N,LogTD}}=lists:keysearch(N,1,TracerDataList), + true + end, + ?l {ok,NodeResults5}=inviso:get_tracerdata(Nodes), + ?l true=check_noderesults(Nodes,Fun1,NodeResults5), + ok. +%% ------------------------------------------------------------------------------ + +%% Stops tracing on Nodes. +stop_tracing(Nodes) when is_list(Nodes) -> + ?l {ok,NodeResults1}=inviso:stop_tracing(Nodes), + ?l true=check_noderesults(Nodes,{ok,idle},NodeResults1), + ?l {ok,NodeResults2}=inviso:get_status(Nodes), + ?l true=check_noderesults(Nodes,{ok,{idle,running}},NodeResults2), + %% The implementation says that the meta tracer shall be stopped when + %% tracing is stopped. Check that. + ?l lists:foreach(fun(N)-> + ok=poll(erlang,whereis,[inviso_rt_meta],undefined,20) + end, + Nodes). +%% ------------------------------------------------------------------------------ + +%% Stops the runtime components on Nodes and stops the control component at this +%% Erlang node. +stop(Nodes) when is_list(Nodes) -> + ?l true=check_on_nodes(Nodes,erlang,whereis,[inviso_rt],fun(P) when is_pid(P)->true end), + ?l {ok,NodeResults}=inviso:stop_nodes(Nodes), + ?l true=check_noderesults(Nodes,ok,NodeResults), + ?l true=check_on_nodes(Nodes,erlang,whereis,[inviso_rt],fun(undefined)->true end), + ?l true=is_pid(whereis(inviso_c)), + ?l shutdown=inviso:stop(), + ?l ok=poll(erlang,whereis,[inviso_c],undefined,20). +%% ------------------------------------------------------------------------------ + +%% Help function activating local tracing. +activate_local_tracing(Nodes) when is_list(Nodes) -> + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{code,which,1},traced], + {traced,false}), + ?l {ok,NodeResults}=inviso:tpl(Nodes,code,which,1,[]), + ?l true=check_noderesults(Nodes,fun({_,{ok,[1]}})->true end,NodeResults), + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{code,which,1},traced], + {traced,local}). +%% ------------------------------------------------------------------------------ + +%% Help function activating global tracing. +activate_global_tracing(Nodes) when is_list(Nodes) -> + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{code,get_path,0},traced], + {traced,false}), + ?l {ok,NodeResults}=inviso:tp(Nodes,code,get_path,0,[]), + ?l true=check_noderesults(Nodes,fun({_,{ok,[1]}})->true end,NodeResults), + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{code,get_path,0},traced], + {traced,global}). +%% ------------------------------------------------------------------------------ + + +%% Help function activating local tracing and using a regexp to point out modules. +%% Returns the structure of modules and functions that were activated. Must be used +%% when deactivating. +activate_global_tracing_regexp(Nodes) when is_list(Nodes) -> + %% First find out which modules will be effected. + ?l Mods1=inviso_rt_lib:expand_regexp("application.*",[]), + ?l true=(length(Mods1)>1), % Should find more than one module! + ?l Funcs1=lists:foldl(fun(M,Acc)->[{M,M:module_info(exports)}|Acc] end,[],Mods1), + %% Check that these functions are not traced. + io:format("Modules:~w~n",[Mods1]), + ?l {ok,NodeResults}=inviso:tp(Nodes,"application.*",'_','_',[],[]), + io:format("Here 2~w~n",[NodeResults]), + ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), + ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), + io:format("Here 3~n",[]), + %% Check again! + ?l lists:foreach(fun({M,Funcs})-> + lists:foreach(fun({F,Arity})-> + true=check_on_nodes(Nodes, + erlang, + trace_info, + [{M,F,Arity},traced], + {traced,global}) + end, + Funcs) + end, + Funcs1), + Funcs1. +%% ------------------------------------------------------------------------------ + +%% Help function as above but uses the dir feature as well. +activate_global_tracing_regexp_dir(Nodes) when is_list(Nodes) -> + %% First find out which modules will be effected. + ?l Mods1=inviso_rt_lib:expand_regexp(".*kernel.*","application.*",[]), + ?l true=(length(Mods1)>1), % Should find more than one module! + ?l Funcs1=lists:foldl(fun(M,Acc)->[{M,M:module_info(exports)}|Acc] end,[],Mods1), + %% Check that these functions are not traced. + io:format("Modules:~w~n",[Mods1]), + ?l {ok,NodeResults}=inviso:tp(Nodes,{".*kernel.*","application.*"},'_','_',[],[]), + io:format("Here 2~w~n",[NodeResults]), + ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), + ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), + io:format("Here 3~n",[]), + %% Check again! + ?l lists:foreach(fun({M,Funcs})-> + lists:foreach(fun({F,Arity})-> + true=check_on_nodes(Nodes, + erlang, + trace_info, + [{M,F,Arity},traced], + {traced,global}) + end, + Funcs) + end, + Funcs1), + Funcs1. +%% ------------------------------------------------------------------------------ + +deactivate_local_tracing(Nodes) when is_list(Nodes) -> + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{code,which,1},traced], + {traced,local}), + ?l {ok,NodeResults}=inviso:ctpl(Nodes,code,'_','_'), + ?l true=check_noderesults(Nodes,fun({_,{ok,[N]}})when is_integer(N)->true end,NodeResults), + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{code,which,1},traced], + {traced,false}). +%% ------------------------------------------------------------------------------ + +deactivate_global_tracing(Nodes) when is_list(Nodes) -> + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{code,get_path,0},traced], + {traced,global}), + ?l {ok,NodeResults}=inviso:ctp(Nodes,code,'_','_'), + ?l true=check_noderesults(Nodes,fun({_,{ok,[N]}})when is_integer(N)->true end,NodeResults), + ?l true=check_on_nodes(Nodes, + erlang, + trace_info, + [{code,get_path,0},traced], + {traced,false}). +%% ------------------------------------------------------------------------------ + + +%% Function deactivating the functions activated by activate_global_tracing_regexp/1. +deactivate_global_tracing_regexp(Nodes,Funcs1) -> + ?l lists:foreach(fun({M,Funcs})-> + lists:foreach(fun({F,Arity})-> + true=check_on_nodes(Nodes, + erlang, + trace_info, + [{M,F,Arity},traced], + {traced,global}) + end, + Funcs) + end, + Funcs1), + ?l {ok,NodeResults}=inviso:ctp(Nodes,"application.*",'_','_'), + ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), + io:format("Noderesult from deactivate;~w~n",[NodeResults]), + ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), + ?l lists:foreach(fun({M,Funcs})-> + lists:foreach(fun({F,Arity})-> + true=check_on_nodes(Nodes, + erlang, + trace_info, + [{M,F,Arity},traced], + {traced,false}) + end, + Funcs) + end, + Funcs1). +%% ------------------------------------------------------------------------------ + +%% Function deactivating the functions activated by activate_global_tracing_regexp_dir/1. +deactivate_global_tracing_regexp_dir(Nodes,Funcs1) -> + ?l lists:foreach(fun({M,Funcs})-> + lists:foreach(fun({F,Arity})-> + true=check_on_nodes(Nodes, + erlang, + trace_info, + [{M,F,Arity},traced], + {traced,global}) + end, + Funcs) + end, + Funcs1), + ?l {ok,NodeResults}=inviso:ctp(Nodes,{".*kernel.*","application.*"},'_','_'), + ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), + io:format("Noderesult from deactivate;~w~n",[NodeResults]), + ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), + ?l lists:foreach(fun({M,Funcs})-> + lists:foreach(fun({F,Arity})-> + true=check_on_nodes(Nodes, + erlang, + trace_info, + [{M,F,Arity},traced], + {traced,false}) + end, + Funcs) + end, + Funcs1). +%% ------------------------------------------------------------------------------ + +%% Help function which starts the inviso_test_proc on all nodes and then sets +%% the call flag on that process. +activate_traceflags(Nodes) -> + ?l lists:foreach(fun(N)->spawn(N,?MODULE,test_proc_init,[]) end,Nodes), + ?l lists:foreach(fun(N)-> + P=rpc:call(N,erlang,whereis,[inviso_test_proc]), + {flags,[]}=rpc:call(N,erlang,trace_info,[P,flags]) + end, + Nodes), + ?l {ok,NodeResults}=inviso:tf(Nodes,inviso_test_proc,[call,timestamp]), + ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults), + ?l lists:foreach(fun(N)-> + P=rpc:call(N,erlang,whereis,[inviso_test_proc]), + {flags,Flags}=rpc:call(N,erlang,trace_info,[P,flags]), + true=lists:member(call,Flags), + true=lists:member(timestamp,Flags) + end, + Nodes), + %% Now try a globally registered process. + ?l [ANode|_]=Nodes, + ?l GPid=spawn(ANode,?MODULE,global_test_proc_init,[]), + ?l ok=poll(global,whereis_name,[global_inviso_test_proc], + fun(P) when is_pid(P)->true;(_)->false end, + 10), + ?l {ok,NodeResults2}= + inviso:tf(Nodes,{global,global_inviso_test_proc},[call,timestamp]), + ?l true=check_noderesults(Nodes, + fun({N,{ok,[1]}}) when N==ANode->true; + ({_,{ok,[0]}})->true; + (_)->false + end, + NodeResults2), + ?l {flags,Flags2}=rpc:call(ANode,erlang,trace_info,[GPid,flags]), + ?l 2=length(Flags2), + ?l true=lists:member(call,Flags2), + ?l true=lists:member(timestamp,Flags2), + true. +%% ------------------------------------------------------------------------------ + +deactivate_traceflags(Nodes) -> + ?l lists:foreach(fun(N)-> + P=rpc:call(N,erlang,whereis,[inviso_test_proc]), + {flags,Flags}=rpc:call(N,erlang,trace_info,[P,flags]), + true=lists:member(call,Flags), + true=lists:member(timestamp,Flags) + end, + Nodes), + ?l {ok,NodeResults}=inviso:ctf(Nodes,inviso_test_proc,[call,timestamp]), + ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults), + ?l lists:foreach(fun(N)-> + P=rpc:call(N,erlang,whereis,[inviso_test_proc]), + {flags,[]}=rpc:call(N,erlang,trace_info,[P,flags]) + end, + Nodes), + ?l GPid=global:whereis_name(global_inviso_test_proc), + ?l ANode=node(GPid), + ?l {flags,Flags2}=rpc:call(ANode,erlang,trace_info,[GPid,flags]), + ?l 2=length(Flags2), + ?l {ok,NodeResults2}=inviso:ctf(Nodes,{global,global_inviso_test_proc},[call,timestamp]), + ?l true=check_noderesults(Nodes, + fun({N,{ok,[1]}}) when N==ANode->true; + ({_,{ok,[0]}})->true; + (_)->false + end, + NodeResults2). +%% ------------------------------------------------------------------------------ + + +activate_meta_tracing(Nodes) -> + ?l {ok,NodeResults1}=inviso:tpm_localnames(), + ?l true=check_noderesults(Nodes,{{ok,1},{ok,1}},NodeResults1), + ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), + {meta,P}=rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]) + end, + Nodes), + ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), + {meta,P}=rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]) + end, + Nodes), + ?l {ok,NodeResults2}=inviso:tpm_globalnames(), + ?l true=check_noderesults(Nodes,{{ok,1},{ok,1}},NodeResults2), + ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), + {meta,P}=rpc:call(N, + erlang, + trace_info, + [{global,handle_call,3},meta]) + end, + Nodes), + ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), + {meta,P}=rpc:call(N, + erlang, + trace_info, + [{global,delete_global_name,2},meta]) + end, + Nodes), + + ?l lists:foreach(fun(N)->true=rpc:call(N, + ets, + insert, + [inviso_sideeffect_tab,{tpm_init_func1,0}]), + true=rpc:call(N, + ets, + insert, + [inviso_sideeffect_tab,{tpm_call_func1,0}]), + true=rpc:call(N, + ets, + insert, + [inviso_sideeffect_tab,{tpm_return_func1,0}]) + end, + Nodes), + ?l {ok,NodeResults3}= + inviso:init_tpm(lists, + module_info, + 0, + {?MODULE,tpm_init_func1}, + {?MODULE,tpm_call_func1}, + {?MODULE,tpm_return_func1}, + {?MODULE,tpm_remove_func1}), + ?l true=check_noderesults(Nodes,ok,NodeResults3), + ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1), + ?l {ok,NodeResults3a}= + inviso:init_tpm(lists, + module_info, + 0, + {?MODULE,tpm_init_func1}, + {?MODULE,tpm_call_func1}, + {?MODULE,tpm_return_func1}, + {?MODULE,tpm_remove_func1}), + ?l true=check_noderesults(Nodes,{error,already_initiated},NodeResults3a), +% %% Try more forbidden things. Wildcards not allowed in meta tracing! +% ?l {ok,NodeResults3b}=inviso:tpm(Nodes,lists,'_',0,[{'_',[],[{return_trace}]}]), +% io:format("The noderesults3b is:~w~n",[NodeResults3b]), +% ?l true=check_noderesults(Nodes,{error,bad_mfa},NodeResults3b), + ?l {ok,NodeResults3c}=inviso:tpm(Nodes,lists,module_info,0,[{'_',[],[{return_trace}]}]), + ?l true=check_noderesults(Nodes,{ok,1},NodeResults3c), + ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), + {meta,P}=rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) + end, + Nodes), + ?l lists:foreach(fun(N)->rpc:call(N,lists,module_info,[]) end,Nodes), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,1}],20), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,1}],20), + ?l lists:foreach(fun(N)->rpc:call(N,lists,module_info,[]) end,Nodes), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,2}],20), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,2}],20), + + ?l {ok,NodeResults4}= + inviso:init_tpm(math, + module_info, + 1, + {?MODULE,tpm_init_func2}, % Does not exist on purpose. + {?MODULE,tpm_call_func2}, % Does not exist on purpose. + {?MODULE,tpm_return_func2}, % Does not exist on purpose. + {?MODULE,tpm_remove_func2}), % Does not exist on purpose. + ?l true=check_noderesults(Nodes,ok,NodeResults4), + ?l {ok,NodeResults5}= + inviso:tpm_ms(math,module_info,1,ms1,[{'_',[],[{return_trace}]}]), + ?l true=check_noderesults(Nodes,{ok,1},NodeResults5), + ?l lists:foreach(fun(N)->{meta_match_spec,[{'_',[],[{return_trace}]}]}= + rpc:call(N,erlang,trace_info,[{math,module_info,1}, + meta_match_spec]) + end, + Nodes), + + ?l {ok,NodeResults6}=inviso:tpm_ms(math,module_info,1,ms2,[{[exports],[],[]}]), + ?l true=check_noderesults(Nodes,{ok,1},NodeResults6), + ?l lists:foreach(fun(N)->{meta_match_spec,[{[exports],[],[]},{'_',[],[{return_trace}]}]}= + rpc:call(N,erlang,trace_info,[{math,module_info,1}, + meta_match_spec]) + end, + Nodes), + ?l {ok,NodeResults7}=inviso:tpm_ms(math,module_info,1,ms3,[{[attributes],[],[]}]), + ?l true=check_noderesults(Nodes,{ok,1},NodeResults7), + ?l lists:foreach(fun(N)->{meta_match_spec,[{[attributes],[],[]}, + {[exports],[],[]}, + {'_',[],[{return_trace}]}]}= + rpc:call(N,erlang,trace_info,[{math,module_info,1}, + meta_match_spec]) + end, + Nodes), + ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms2), + ?l true=check_noderesults(Nodes,ok,NodeResults8), + ?l lists:foreach(fun(N)->{meta_match_spec,[{[attributes],[],[]}, + {'_',[],[{return_trace}]}]}= + rpc:call(N,erlang,trace_info,[{math,module_info,1}, + meta_match_spec]) + end, + Nodes), + ?l io:format("whereis:~w~n",[lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,Nodes)]), + ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms3), + ?l io:format("whereis:~w~n",[lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,Nodes)]), + ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms1), + ?l lists:foreach(fun(N)->{meta_match_spec,false}= + rpc:call(N,erlang,trace_info,[{math,module_info,1}, + meta_match_spec]) + end, + Nodes), + + %% Now try to do this with exception tracing instead. + %% Reset the side effect tables. + ?l lists:foreach(fun(N)->true=rpc:call(N, + ets, + insert, + [inviso_sideeffect_tab,{tpm_init_func1,0}]), + true=rpc:call(N, + ets, + insert, + [inviso_sideeffect_tab,{tpm_call_func1,0}]), + true=rpc:call(N, + ets, + insert, + [inviso_sideeffect_tab,{tpm_return_func1,0}]) + end, + Nodes), + ?l {ok,NodeResults9}= + inviso:init_tpm(?MODULE, + failing_function, + 1, + {?MODULE,tpm_init_func1}, + {?MODULE,tpm_call_func1}, + {?MODULE,tpm_return_func1}, + {?MODULE,tpm_remove_func1}), + ?l true=check_noderesults(Nodes,ok,NodeResults9), + ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1), + ?l {ok,NodeResults10}=inviso:tpm(Nodes,?MODULE,failing_function,1,[{'_',[],[{exception_trace}]}]), + ?l true=check_noderesults(Nodes,{ok,1},NodeResults10), + ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), + {meta,P}=rpc:call(N,erlang,trace_info,[{?MODULE,failing_function,1},meta]) + end, + Nodes), + ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,failing_function,[nofailure]) end,Nodes), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,1}],20), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,1}],20), + ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,failing_function,[failure]) end,Nodes), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,2}],20), + ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,3}],20), + + ok. +%% ------------------------------------------------------------------------------ + +%% This function is for testing that appending the tracer to a trace action term +%% works. +activate_deactivate_meta_tracing_tracer(Nodes) -> + ?l {ok,NodeResults}= + inviso:tpm_tracer(Nodes,lists,module_info,0,[{'_',[],[{trace,[all],[call]}]}],void), + ?l true=check_noderesults(Nodes,{ok,1},NodeResults), + ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), + {meta,P}=rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]), + {meta_match_spec,[{'_',[],[{trace,[all],Enable}]}]}= + rpc:call(N,erlang,trace_info,[{lists,module_info,0}, + meta_match_spec]), + true=list_search(Enable,fun({{tracer,P}}) when is_port(P)->true; + (_) -> false + end) + end, + Nodes), + ?l {ok,NodeResults2}= + inviso:ctpm(Nodes,lists,module_info,0), + ?l true=check_noderesults(Nodes,ok,NodeResults2), + ?l lists:foreach(fun(N)->{meta,false}= + rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) + end, + Nodes), + ok. +%% ------------------------------------------------------------------------------ + +deactivate_meta_tracing(Nodes) -> + ?l lists:foreach(fun(N)->{meta,P}= + rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]), + true=is_pid(P) + end, + Nodes), + ?l lists:foreach(fun(N)->{meta,P}= + rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]), + true=is_pid(P) + end, + Nodes), + ?l {ok,NodeResults1}=inviso:ctpm_localnames(), + ?l lists:foreach(fun(N)->{meta,false}= + rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]) end, + Nodes), + ?l lists:foreach(fun(N)->{meta,false}= + rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]) + end, + Nodes), + ?l true=check_noderesults(Nodes,{ok,ok},NodeResults1), + + ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), + {meta,P}=rpc:call(N, + erlang, + trace_info, + [{global,handle_call,3},meta]) + end, + Nodes), + ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), + {meta,P}=rpc:call(N, + erlang, + trace_info, + [{global,delete_global_name,2},meta]) + end, + Nodes), + ?l {ok,NodeResults1b}=inviso:ctpm_globalnames(), + ?l true=check_noderesults(Nodes,{ok,ok},NodeResults1b), + ?l lists:foreach(fun(N)-> + {meta,false}=rpc:call(N, + erlang, + trace_info, + [{global,handle_call,3},meta]) + end, + Nodes), + ?l lists:foreach(fun(N)-> + {meta,false}=rpc:call(N, + erlang, + trace_info, + [{global,delete_global_name,2},meta]) + end, + Nodes), + + ?l lists:foreach(fun(N)->{meta,P}= + rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]), + true=is_pid(P) + end, + Nodes), + ?l {ok,NodeResults2}=inviso:ctpm(lists,module_info,0), + ?l true=check_noderesults(Nodes,ok,NodeResults2), + ?l lists:foreach(fun(N)->{meta,false}= + rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) end, + Nodes), + ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1), + ?l {ok,NodeResults3}=inviso:ctpm(math,module_info,1), + ?l true=check_noderesults(Nodes,ok,NodeResults3), + ok. +%% ------------------------------------------------------------------------------ + +%% Functions acting as callbacks for testing the meta tracing mechanisms. +tpm_init_func1(_M,_F,_Arity,PublLD) -> + ets:update_counter(inviso_sideeffect_tab,tpm_init_func1,1), + {ok,PublLD,void}. +tpm_call_func1(_Pid,{call,_Args,_TS},PublLD) -> + ets:update_counter(inviso_sideeffect_tab,tpm_call_func1,1), + {ok,PublLD,void}. +tpm_return_func1(_Pid,{return_from,_ReturnVal,_TS},PublLD) -> + ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1), + {ok,PublLD,void}; +tpm_return_func1(_Pid,{exception_from,_ReturnVal,_TS},PublLD) -> + ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1), + ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1), + {ok,PublLD,void}. +tpm_remove_func1(_M,_F,_Arity,PublLD) -> + ets:update_counter(inviso_sideeffect_tab,tpm_init_func1,-1), + {ok,PublLD}. +%% ------------------------------------------------------------------------------ + + +%% Help function which traces on a function and makes function calls until there +%% are two files in the wrap-set. +fill_and_reach_two_wrapfiles(PrivDir,RegExp,Nodes) -> + ?l lists:foreach(fun(N)->spawn(N,?MODULE,test_proc_init,[]) end,Nodes), + ?l {ok,NodeResults1}=inviso:tpl(Nodes,?MODULE,test_function,0,[]), + ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults1), + ?l {ok,NodeResults2}=inviso:tf(Nodes,inviso_test_proc,[call]), + ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults2), + fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,Nodes), + ?l {ok,NodeResults3}=inviso:ctf(Nodes,inviso_test_proc,[call]), + ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults3), + ?l {ok,NodeResults4}=inviso:ctpl(Nodes,?MODULE,test_function,0), + ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults4), + ok. + +fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,[Node|Rest]) -> + ?l ok=rpc:call(Node,?MODULE,fill_and_reach_two_wrapfiles_3,[PrivDir,RegExp]), + fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,Rest); +fill_and_reach_two_wrapfiles_2(_,_,[]) -> + ok. + +fill_and_reach_two_wrapfiles_3(Dir,RegExp) -> + ok=send_to_test_proc({apply,?MODULE,test_function,[]}, + fun reach_two_wraps_stopfun/1, + {Dir,RegExp++atom_to_list(node())}, + 100). + +%% Help function intended to be used as fun in a send_to_test_proc/4 call. +%% The function lists the content of Dir and looks for occurancies of String. +%% If two files containing the string String are found, 'done' is returned. +%% Otherwise 'continue'. +reach_two_wraps_stopfun({Dir,RegExp}) -> + case file:list_dir(Dir) of + {ok,FileNames} -> + case how_many_files_regexp(FileNames,RegExp,0) of + {ok,2} -> + done; + _ -> + continue + end; + {error,_Reason} -> + error + end. +%% ------------------------------------------------------------------------------ + +%% ------------------------------------------------------------------------------ +%% Help function for the overload tests. These functions are used as callbacks. +%% ------------------------------------------------------------------------------ + +overload1(_) -> + ets:update_counter(inviso_sideeffect_tab,ovl1,1), + ok. +%% This function is used when timeout occurs inside the runtime component. +%% That is it is time to check for overload. +overload2({timeout,overload2i_data}) -> + ets:update_counter(inviso_sideeffect_tab,ovl2,1), + ok. +overload2i() -> + ets:insert(inviso_sideeffect_tab,{ovl2,0}), + {ok,overload2i_data}. +overload2r(overload2i_data) -> + ets:delete(inviso_sideeffect_tab,ovl2). + +%% This function is used when timeout occurs inside the runtime component. +%% That is it is time to check for overload. +overload3({timeout,overload3i_data}) -> + ets:update_counter(inviso_sideeffect_tab,ovl3,1), + ok; +overload3(_) -> % Must handle garbage too. + ignore. +overload3i() -> + ets:insert(inviso_sideeffect_tab,{ovl3,0}), + {ok,overload3i_data}. +overload3r(overload3i_data) -> + ets:insert(inviso_sideeffect_tab,{ovl3r,done}), + ets:delete(inviso_sideeffect_tab,ovl3). + +overload4(_) -> + case ets:lookup(inviso_sideeffect_tab,ovl4_suspend) of + [] -> % We are supposed to be running. + ets:update_counter(inviso_sideeffect_tab,ovl4,1), + ok; + [_] -> + {suspend,test} + end. + +%% This function is used when overload check is done by icomming message. +overload5({msg,{test_of_loadcheck,overload5i_data}}) -> + ets:update_counter(inviso_sideeffect_tab,ovl5,1), + ok; +overload5(_) -> + ignore. +overload5i() -> + ets:insert(inviso_sideeffect_tab,{ovl5,0}), + {ok,overload5i_data}. +overload5r(overload5i_data) -> + ets:delete(inviso_sideeffect_tab,ovl5), + ets:insert(inviso_sideeffect_tab,{ovl5r,done}); +overload5r(X) -> + erlang:display({'***',overload5r,X}). + +overload6(_) -> + ets:update_counter(inviso_sideeffect_tab,ovl6,1), + ok. +%% ------------------------------------------------------------------------------ + +%% ------------------------------------------------------------------------------ +%% Help function for the subscription tests. These function implements a collector +%% process which will subscribe to inviso_events from the control component. +%% ------------------------------------------------------------------------------ + +%% Function which can be used to check if an inviso_event has arrived. The function +%% takes a fun which tests the messages. +check_msg_collector([],_,_) -> + true; +check_msg_collector(_,_,0) -> + false; +check_msg_collector(Nodes,Fun,T) -> + Ref=make_ref(), + inviso_collector_proc ! {fetch_message,self(),Ref,Fun}, + receive + {inviso,Ref,{true,Node}} -> + check_msg_collector(lists:delete(Node,Nodes),Fun,T-1); + {inviso,Ref,false} -> + timer:sleep(100), + check_msg_collector(Nodes,Fun,T-1) + end. + +%% Spawn on this function to get a subscriber. +inviso_msg_collector() -> + register(inviso_collector_proc,self()), + inviso_msg_collector_loop([]). + +inviso_msg_collector_loop(Msgs) -> + receive + {fetch_message,From,Ref,Fun} -> + {NewMsgs,Reply}=inviso_msg_collector_selector(Msgs,Fun,[]), + From ! {inviso,Ref,Reply}, + inviso_msg_collector_loop(NewMsgs); + Msg -> + inviso_msg_collector_loop([Msg|Msgs]) + end. + +inviso_msg_collector_selector([M|Rest],Fun,Accum) -> + case Fun(M) of + {true,X} -> + {Rest++Accum,{true,X}}; + _ -> + inviso_msg_collector_selector(Rest,Fun,[M|Accum]) + end; +inviso_msg_collector_selector([],_,Accum) -> + {Accum,false}. +%% ------------------------------------------------------------------------------ + + +%% ============================================================================== +%% Help functions +%% ============================================================================== + +list_search([E|Rest],Fun) -> + case Fun(E) of + true -> + true; + false -> + list_search(Rest,Fun) + end; +list_search([],_Fun) -> + false. +%% ------------------------------------------------------------------------------ + +%% Help function checking that there is a Result for each node in Nodes. +%% Returns 'true' if successful. +check_noderesults(Nodes,Fun,[{Node,Result}|Rest]) when is_function(Fun) -> + case Fun({Node,Result}) of + true -> + case lists:member(Node,Nodes) of + true -> + check_noderesults(lists:delete(Node,Nodes),Fun,Rest); + false -> % Not good. + unknown_node_in_returnvalue + end; + _ -> + illegal_result + end; +check_noderesults(Nodes,Result,[{Node,Result}|Rest]) -> + case lists:member(Node,Nodes) of + true -> + check_noderesults(lists:delete(Node,Nodes),Result,Rest); + false -> % Not good. + unknown_node_in_returnvalue + end; +check_noderesults([],_,[]) -> + true; +check_noderesults(X,Y,Z) -> + io:format("Bad arguments to check noderesults:~w~n~w~n~w~n",[X,Y,Z]), + false. +%% ------------------------------------------------------------------------------ + +%% Help function doing rpc on all nodes in Nodes calling M:F. Returns 'true' if +%% successful. +check_on_nodes([Node|Rest],M,F,Args,Result) when Node==node() -> + if + is_function(Result) -> + ?l true=Result(apply(M,F,Args)); + true -> + ?l Result=apply(M,F,Args) + end, + check_on_nodes(Rest,M,F,Args,Result); +check_on_nodes([Node|Rest],M,F,Args,Result) -> + if + is_function(Result) -> + ?l true=Result(rpc:call(Node,M,F,Args)); + true -> + ?l Result=rpc:call(Node,M,F,Args) + end, + check_on_nodes(Rest,M,F,Args,Result); +check_on_nodes([],_,_,_,_) -> + true. +%% ------------------------------------------------------------------------------ + +%% Help function which given a list of files searches through it and returns +%% how many satisfies the RegExp. +%% Returns {ok,N}. +how_many_files_regexp([],_,N) -> + {ok,N}; +how_many_files_regexp([FName|Rest],RegExp,N) -> + case regexp:first_match(FName,RegExp) of + {match,1,_} -> + how_many_files_regexp(Rest,RegExp,N+1); + nomatch -> + how_many_files_regexp(Rest,RegExp,N); + {error,Reason} -> + test_server:fail(Reason) + end. +%% ------------------------------------------------------------------------------ + +%% Help function killing a bunch of registered processes. +process_killer([RegName|Rest]) -> + case whereis(RegName) of + undefined -> + case global:whereis_name(RegName) of + undefined -> + process_killer(Rest); + P when is_pid(P) -> + if + node()==node(P) -> + exit(P,kill); + true -> + true + end, + process_killer(Rest) + end; + P when is_pid(P) -> + exit(P,kill), + process_killer(Rest) + end; +process_killer([]) -> + true. +%% ------------------------------------------------------------------------------ + +%% Help function which waits for a function call to become Result. This is useful +%% if what we are waiting for can happend independantly of indications we have +%% access to. +poll(_,_,_,_,0) -> + error; +poll(M,F,Args,Result,Times) -> + try apply(M,F,Args) of + What when is_function(Result) -> + case Result(What) of + true -> + ok; + _ -> + timer:sleep(100), + poll(M,F,Args,Result,Times-1) + end; + Result -> + ok; + _ -> + timer:sleep(100), + poll(M,F,Args,Result,Times-1) + catch + error:Reason -> + io:format("Apply in suite-function poll/5 failed, ~w~n",[Reason]), + timer:sleep(100), + poll(M,F,Args,Result,Times-1) + end. +%% ------------------------------------------------------------------------------ + +insert_remotenode_config(Name,Node,Config) -> + [{remotenode,{Name,Node}}|Config]. +%% ------------------------------------------------------------------------------ + +insert_timetraphandle_config(Handle,Config) -> + [{timetraphandle,Handle}|Config]. +%% ------------------------------------------------------------------------------ + +get_remotenode_config(Name, [{remotenode, {Name, Node}}| _Cs]) -> + Node; +get_remotenode_config(Name, [_ | Cs]) -> + get_remotenode_config(Name, Cs); +get_remotenode_config(Name, []) -> + exit({no_remotenode, Name}). + +%% ------------------------------------------------------------------------------ + +get_timetraphandle_config(Config) -> + {value,{_,Handle}}=lists:keysearch(timetraphandle,1,Config), + Handle. +%% ------------------------------------------------------------------------------ + +get_remotenodes_config([{remotenode,{_Name,Node}}|Config]) -> + [Node|get_remotenodes_config(Config)]; +get_remotenodes_config([_|Config]) -> + get_remotenodes_config(Config); +get_remotenodes_config([]) -> + []. +%% ------------------------------------------------------------------------------ + +remove_remotenode_config(Name, [{remotenode, {Name, _}} | Cs]) -> + Cs; +remove_remotenode_config(Name, [C | Cs]) -> + [C | remove_remotenode_config(Name, Cs)]; +remove_remotenode_config(_Name, []) -> + []. + +%% ------------------------------------------------------------------------------ + +remove_timetraphandle_config(Config) -> + lists:keydelete(timetraphandle,1,Config). +%% ------------------------------------------------------------------------------ + +%% This function can be meta traced in order to check that exception_trace works. +%% Must be exported. +failing_function(nofailure) -> + true; +failing_function(failure) -> + exit(failure). +%% ------------------------------------------------------------------------------ + +%% ============================================================================== +%% Code for a test process which can be started. +%% ============================================================================== + +test_proc_init() -> + register(inviso_test_proc,self()), + test_proc_loop(). + +test_proc_loop() -> + receive + {apply,M,F,Args} -> + apply(M,F,Args), + test_proc_loop(); + X -> + io:format("Got ~w~n",[X]), + test_proc_loop() + end. + +global_test_proc_init() -> + global:register_name(global_inviso_test_proc,self()), + test_proc_loop(). +%% ------------------------------------------------------------------------------ + +send_to_test_proc(_,_,_,0) -> + error; +send_to_test_proc(Msg,Fun,FunArg,N) -> + inviso_test_proc ! Msg, + case Fun(FunArg) of + done -> + ok; + error -> + test_server:fail(send_to_test_proc); + _ -> + send_to_test_proc(Msg,Fun,FunArg,N-1) + end. +%% ------------------------------------------------------------------------------ + + +%% This function is here to be traced on by the inviso_test_proc. Must be exported. +test_function() -> + 1+1. +%% ------------------------------------------------------------------------------ + + +%% ============================================================================== +%% Code for a test side effect table process. +%% ============================================================================== + +%% The side effect logger is a process owning a public ETS table. The idea is that +%% various callback functions can write in the table when called. In that way +%% correct calling of the call-backs can be verified. +start_side_effect_logger(Node) -> + ?l true=is_pid(spawn(Node,?MODULE,side_effect_logger_proc,[])), + ?l ok=poll(rpc,call,[Node,ets,lookup,[inviso_sideeffect_tab,foo]],[],20). + +%% This one must be exported. +side_effect_logger_proc() -> + register(inviso_tab_proc,self()), % So we can kill it later. + ets:new(inviso_sideeffect_tab,[public,named_table]), + side_effect_logger_proc_2(). + +side_effect_logger_proc_2() -> + receive + _X -> % This process is not expecting anything! + side_effect_logger_proc_2() + end. +%% ------------------------------------------------------------------------------ diff --git a/lib/runtime_tools/test/inviso_testmodule1_foo.erl b/lib/runtime_tools/test/inviso_testmodule1_foo.erl new file mode 100644 index 0000000000..a7a22cad39 --- /dev/null +++ b/lib/runtime_tools/test/inviso_testmodule1_foo.erl @@ -0,0 +1,9 @@ +-module(inviso_testmodule1_foo). + +-compile(export_all). + +%% The purpose of this module is simply to have a module that is +%% guaranteed not loaded. + +foo() -> + true. diff --git a/lib/runtime_tools/test/runtime_tools.cover b/lib/runtime_tools/test/runtime_tools.cover new file mode 100644 index 0000000000..2d62ebe6ac --- /dev/null +++ b/lib/runtime_tools/test/runtime_tools.cover @@ -0,0 +1 @@ +{exclude,[observer_backend]}. diff --git a/lib/runtime_tools/test/runtime_tools.spec b/lib/runtime_tools/test/runtime_tools.spec new file mode 100644 index 0000000000..a60a533ce2 --- /dev/null +++ b/lib/runtime_tools/test/runtime_tools.spec @@ -0,0 +1 @@ +{topcase, {dir, "../runtime_tools_test"}}. diff --git a/lib/runtime_tools/test/runtime_tools_SUITE.erl b/lib/runtime_tools/test/runtime_tools_SUITE.erl new file mode 100644 index 0000000000..84e255e126 --- /dev/null +++ b/lib/runtime_tools/test/runtime_tools_SUITE.erl @@ -0,0 +1,50 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(runtime_tools_SUITE). +-include("test_server.hrl"). + +%% Test server specific exports +-export([all/1]). +-export([init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([app_file/1]). + +%% Default timetrap timeout (set in init_per_testcase) +-define(default_timeout, ?t:minutes(1)). + +init_per_testcase(_Case, Config) -> + Dog = test_server:timetrap(?default_timeout), + [{watchdog, Dog} | Config]. + +end_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +all(suite) -> + [app_file]. + +app_file(suite) -> + []; +app_file(doc) -> + ["Testing .app file"]; +app_file(Config) when is_list(Config) -> + ?line ok = ?t:app_test(runtime_tools), + ok. diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 3f4954cfbd..d5d6605b64 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -13,12 +13,12 @@ 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. - + </legalnotice> <title>SNMP Release Notes</title> @@ -33,6 +33,34 @@ </header> <section> + <title>SNMP Development Toolkit 4.17.1</title> + <p>Version 4.17.1 supports code replacement in runtime from/to + version 4.17, 4.16.2, 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p> + + <section> + <title>Improvements and new features</title> + <p>-</p> + </section> + + <section> + <title>Reported Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>When the function FilterMod:accept_recv/2 + returned false the SNMP agent stopped collecting messages from UDP.</p> + <p>Own Id: OTP-8761</p> + </item> + </list> + </section> + + <section> + <title>Incompatibilities</title> + <p>-</p> + </section> + </section> <!-- 4.17.1 --> + + + <section> <title>SNMP Development Toolkit 4.17</title> <p>Version 4.17 supports code replacement in runtime from/to version 4.16.2, 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p> diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl index 3a91cf4033..97a7a63dee 100644 --- a/lib/snmp/src/agent/snmpa_net_if.erl +++ b/lib/snmp/src/agent/snmpa_net_if.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2004-2010. 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(snmpa_net_if). @@ -478,12 +478,13 @@ update_req_counter_outgoing(#state{limit = Limit, rcnt = RCnt} = S, S#state{rcnt = NewRCnt}. -maybe_handle_recv(#state{filter = FilterMod} = S, +maybe_handle_recv(#state{usock = Sock, filter = FilterMod} = S, Ip, Port, Packet) -> case (catch FilterMod:accept_recv(Ip, Port)) of false -> %% Drop the received packet inc(netIfMsgInDrops), + active_once(Sock), S; _ -> handle_recv(S, Ip, Port, Packet) diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 9ad16ffad2..2bd26e11db 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 1999-2010. 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% %% @@ -22,6 +22,11 @@ %% ----- U p g r a d e ------------------------------------------------------- [ + {"4.17", + [ + {load_module, snmpa_net_if, soft_purge, soft_purge, []} + ] + }, {"4.16.2", [ {load_module, snmp_log, soft_purge, soft_purge, []}, @@ -29,6 +34,7 @@ {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm_mpd, soft_purge, soft_purge, []} ] @@ -44,6 +50,7 @@ {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm_mpd, soft_purge, soft_purge, []}, {update, snmpm_server, soft, soft_purge, soft_purge, []} @@ -61,6 +68,7 @@ {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm_mpd, soft_purge, soft_purge, []}, {update, snmpm_net_if, soft, soft_purge, soft_purge, []}, @@ -149,6 +157,11 @@ %% ------D o w n g r a d e --------------------------------------------------- [ + {"4.17", + [ + {load_module, snmpa_net_if, soft_purge, soft_purge, []} + ] + }, {"4.16.2", [ {load_module, snmp_log, soft_purge, soft_purge, []}, @@ -157,6 +170,7 @@ {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm_mpd, soft_purge, soft_purge, []} ] @@ -172,6 +186,7 @@ {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm_mpd, soft_purge, soft_purge, []}, {update, snmpm_server, soft, soft_purge, soft_purge, []} @@ -189,6 +204,7 @@ {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm_mpd, soft_purge, soft_purge, []}, {update, snmpm_net_if, soft, soft_purge, soft_purge, []}, diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index 4ca1fb7901..95103433a4 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -1,57 +1,3 @@ -#-*-makefile-*- ; force emacs to enter makefile-mode - -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2010. 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% - -SNMP_VSN = 4.17 +SNMP_VSN = 4.17.1 PRE_VSN = APP_VSN = "snmp-$(SNMP_VSN)$(PRE_VSN)" - -TICKETS = OTP-8478 - -TICKETS_4_16_2 = \ - OTP-8563 \ - OTP-8574 \ - OTP-8594 \ - OTP-8595 \ - OTP-8646 \ - OTP-8648 - -TICKETS_4_16_1 = \ - OTP-8480 \ - OTP-8481 - -TICKETS_4_16 = \ - OTP-8395 \ - OTP-8433 \ - OTP-8442 - -TICKETS_4_15 = \ - OTP-8229 \ - OTP-8249 - -TICKETS_4_14 = \ - OTP-8223 \ - OTP-8228 \ - OTP-8237 - -TICKETS_4_13_5 = \ - OTP-8116 \ - OTP-8120 \ - OTP-8181 \ - OTP-8182 - diff --git a/lib/ssh/src/ssh_channel.erl b/lib/ssh/src/ssh_channel.erl index 8a49a44a6c..dcb2d69290 100644 --- a/lib/ssh/src/ssh_channel.erl +++ b/lib/ssh/src/ssh_channel.erl @@ -238,9 +238,19 @@ handle_info(Msg, #state{cm = ConnectionManager, channel_cb = Module, {noreply, State#state{channel_state = ChannelState}}; {ok, ChannelState, Timeout} -> {noreply, State#state{channel_state = ChannelState}, Timeout}; + {stop, Reason, ChannelState} when is_atom(Reason)-> + {stop, Reason, State#state{close_sent = true, + channel_state = ChannelState}}; {stop, ChannelId, ChannelState} -> - ssh_connection:close(ConnectionManager, ChannelId), - {stop, normal, State#state{close_sent = true, + Reason = + case Msg of + {'EXIT', _Pid, shutdown} -> + shutdown; + _ -> + normal + end, + (catch ssh_connection:close(ConnectionManager, ChannelId)), + {stop, Reason, State#state{close_sent = true, channel_state = ChannelState}} end. diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl index e3b6ffa125..cb78acb84c 100644 --- a/lib/ssh/src/ssh_cli.erl +++ b/lib/ssh/src/ssh_cli.erl @@ -415,14 +415,12 @@ start_shell(ConnectionManager, State) -> Shell = State#state.shell, ShellFun = case is_function(Shell) of true -> + {ok, User} = + ssh_userreg:lookup_user(ConnectionManager), case erlang:fun_info(Shell, arity) of {arity, 1} -> - {ok, User} = - ssh_userreg:lookup_user(ConnectionManager), fun() -> Shell(User) end; {arity, 2} -> - {ok, User} = - ssh_userreg:lookup_user(ConnectionManager), {ok, PeerAddr} = ssh_connection_manager:peer_addr(ConnectionManager), fun() -> Shell(User, PeerAddr) end; @@ -437,10 +435,28 @@ start_shell(ConnectionManager, State) -> State#state{group = Group, buf = empty_buf()}. start_shell(_ConnectionManager, Cmd, #state{exec={M, F, A}} = State) -> - Group = group:start(self(), {M, F, A++[Cmd]}, [{echo,false}]), + Group = group:start(self(), {M, F, A++[Cmd]}, [{echo, false}]), + State#state{group = Group, buf = empty_buf()}; +start_shell(ConnectionManager, Cmd, #state{exec=Shell} = State) when is_function(Shell) -> + {ok, User} = + ssh_userreg:lookup_user(ConnectionManager), + ShellFun = + case erlang:fun_info(Shell, arity) of + {arity, 1} -> + fun() -> Shell(Cmd) end; + {arity, 2} -> + fun() -> Shell(Cmd, User) end; + {arity, 3} -> + {ok, PeerAddr} = + ssh_connection_manager:peer_addr(ConnectionManager), + fun() -> Shell(Cmd, User, PeerAddr) end; + _ -> + Shell + end, + Echo = get_echo(State#state.pty), + Group = group:start(self(), ShellFun, [{echo,Echo}]), State#state{group = Group, buf = empty_buf()}. - % Pty can be undefined if the client never sets any pty options before % starting the shell. get_echo(undefined) -> diff --git a/lib/ssh/src/ssh_connection_controler.erl b/lib/ssh/src/ssh_connection_controler.erl index 636ecba532..ca3e62dc83 100644 --- a/lib/ssh/src/ssh_connection_controler.erl +++ b/lib/ssh/src/ssh_connection_controler.erl @@ -126,8 +126,8 @@ handle_cast(_, State) -> %% handle_info(ssh_connected, State) -> %% {stop, normal, State}; %% Servant termination. -handle_info({'EXIT', _Pid, normal}, State) -> - {stop, normal, State}. +handle_info({'EXIT', _Pid, Reason}, State) -> + {stop, Reason, State}. %%----------------------------------------------------------------- %% Func: code_change/3 diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl index cffeade485..6bf89224cf 100644 --- a/lib/ssh/src/ssh_connection_manager.erl +++ b/lib/ssh/src/ssh_connection_manager.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2008-2010. 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% %% %% @@ -146,6 +146,8 @@ adjust_window(ConnectionManager, Channel, Bytes) -> close(ConnectionManager, ChannelId) -> try call(ConnectionManager, {close, ChannelId}) of ok -> + ok; + {error,normal} -> ok catch exit:{noproc, _} -> @@ -155,6 +157,8 @@ close(ConnectionManager, ChannelId) -> stop(ConnectionManager) -> try call(ConnectionManager, stop) of ok -> + ok; + {error,normal} -> ok catch exit:{noproc, _} -> @@ -556,13 +560,18 @@ handle_info({'EXIT', _, _}, State) -> %% The return value is ignored. %%-------------------------------------------------------------------- terminate(Reason, #state{connection_state = - #connection{requests = Requests}, + #connection{requests = Requests, + sub_system_supervisor = SubSysSup}, opts = Opts}) -> SSHOpts = proplists:get_value(ssh_opts, Opts), disconnect_fun(Reason, SSHOpts), (catch lists:foreach(fun({_, From}) -> gen_server:reply(From, {error, connection_closed}) end, Requests)), + Address = proplists:get_value(address, Opts), + Port = proplists:get_value(port, Opts), + SystemSup = ssh_system_sup:system_supervisor(Address, Port), + ssh_system_sup:stop_subsystem(SystemSup, SubSysSup), ok. %%-------------------------------------------------------------------- @@ -593,7 +602,9 @@ call(Pid, Msg, Timeout) -> Result catch exit:{timeout, _} -> - {error, timeout} + {error, timeout}; + exit:{normal, _} -> + {error, normal} end. cast(Pid, Msg) -> diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl index 40db2e4adf..f4570b8a48 100644 --- a/lib/ssh/src/ssh_system_sup.erl +++ b/lib/ssh/src/ssh_system_sup.erl @@ -33,7 +33,8 @@ stop_system/2, system_supervisor/2, subsystem_supervisor/1, channel_supervisor/1, connection_supervisor/1, - acceptor_supervisor/1, start_subsystem/2, restart_subsystem/2, restart_acceptor/2]). + acceptor_supervisor/1, start_subsystem/2, restart_subsystem/2, + restart_acceptor/2, stop_subsystem/2]). %% Supervisor callback -export([init/1]). @@ -83,6 +84,23 @@ start_subsystem(SystemSup, Options) -> Spec = ssh_subsystem_child_spec(Options), supervisor:start_child(SystemSup, Spec). +stop_subsystem(SystemSup, SubSys) -> + case lists:keyfind(SubSys, 2, supervisor:which_children(SystemSup)) of + false -> + {error, not_found}; + {Id, _, _, _} -> + spawn(fun() -> supervisor:terminate_child(SystemSup, Id), + supervisor:delete_child(SystemSup, Id) end), + ok; + {'EXIT', {noproc, _}} -> + %% Already terminated; probably shutting down. + ok; + {'EXIT', {shutdown, _}} -> + %% Already shutting down. + ok + end. + + restart_subsystem(Address, Port) -> SysSupName = make_name(Address, Port), SubSysName = id(ssh_subsystem_sup, Address, Port), diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index ccdbfe4f9a..a8821625a2 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -2,83 +2,3 @@ SSH_VSN = 2.0 APP_VSN = "ssh-$(SSH_VSN)" - -TICKETS = OTP-8524 \ - OTP-8534 \ - OTP-8535 \ - OTP-8550 \ - OTP-8596 \ - OTP-8644 \ - OTP-8645 - -TICKETS_1.1.8 = OTP-8356 \ - OTP-8401 - -TICKETS_1.1.7 = OTP-8121 \ - OTP-8277 \ - OTP-8278 \ - OTP-8201 - -TICKETS_1.1.6 = OTP-8110 \ - OTP-8162 \ - OTP-8173 \ - OTP-8174 \ - OTP-8175 \ - OTP-8176 - -TICKETS_1.1.5 = OTP-8159 \ - OTP-8160 \ - OTP-8161 - -TICKETS_1.1.4 = OTP-8071 - -TICKETS_1.1.3 = OTP-7996 \ - OTP-8034 \ - OTP-8035 - -TICKETS_1.1.2 = OTP-7914 \ - OTP-7917 \ - OTP-7918 \ - OTP-7921 \ - OTP-7919 \ - OTP-7930 \ - OTP-7957 - -TICKETS_1.1.1 = OTP-7828 \ - OTP-7795 \ - OTP-7807 \ - OTP-7808 \ - OTP-7809 - -TICKETS_1.1 = OTP-7676 \ - OTP-7683 \ - OTP-7685 \ - OTP-7766 \ - OTP-7767 \ - OTP-7768 \ - OTP-7770 \ - OTP-7456 \ - OTP-7769 \ - OTP-7516 \ - OTP-7645 \ - -TICKETS_1.0.2 = \ - OTP-7141\ - -TICKETS_1.0.1 = \ - OTP-7318 \ - OTP-7305 \ - OTP-7564 \ - OTP-7565 \ - OTP-7566 \ - -TICKETS_1.0 = \ - OTP-7485 \ - OTP-7504 \ - OTP-7356 \ - OTP-7502 \ - OTP-7503 - -TICKETS_0.9.9.6 = \ - OTP-7246 \ - OTP-7247 \
\ No newline at end of file diff --git a/lib/ssl/Makefile b/lib/ssl/Makefile index b8b51270c9..daad7dc3e6 100644 --- a/lib/ssl/Makefile +++ b/lib/ssl/Makefile @@ -24,22 +24,8 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # # Macros # -ifeq ($(findstring win32,$(TARGET)),win32) -ifeq ($(HOST_OS),) -HOST_OS := $(shell $(ERL_TOP)/erts/autoconf/config.guess) -endif -ifeq ($(findstring solaris,$(HOST_OS)),solaris) -SKIP_BUILDING_BINARIES := true -endif -else -SKIP_BUILDING_BINARIES := false -endif - -ifeq ($(SKIP_BUILDING_BINARIES), true) -SUB_DIRECTORIES = src c_src doc/src -else + SUB_DIRECTORIES = src c_src doc/src examples/certs examples/src -endif include vsn.mk VSN = $(SSL_VSN) diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index def61bcf03..0f3054aec3 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> @@ -69,10 +69,13 @@ </p> <p> <c>ssloption() = {verify, verify_type()} | + {verify_fun, {fun(), term()}} | {fail_if_no_peer_cert, boolean()} {depth, integer()} | - {certfile, path()} | {keyfile, path()} | {password, string()} | - {cacertfile, path()} | {dhfile, path()} | {ciphers, ciphers()} | + {cert, der_bin()}| {certfile, path()} | + {key, der_bin()} | {keyfile, path()} | {password, string()} | + {cacerts, [der_bin()]} | {cacertfile, path()} | + |{dh, der_bin()} | {dhfile, path()} | {ciphers, ciphers()} | {ssl_imp, ssl_imp()} | {reuse_sessions, boolean()} | {reuse_session, fun()} </c></p> @@ -91,6 +94,8 @@ <p><c>verify_type() = verify_none | verify_peer</c></p> <p><c>path() = string() - representing a file path.</c></p> + + <p><c>der_bin() = binary() -Asn1 DER encoded entity as an erlang binary.</c></p> <p><c>host() = hostname() | ipaddress()</c></p> @@ -121,115 +126,52 @@ <p><c>ssl_imp() = new | old - default is new.</c></p> </section> - -<section> - <title>SSL OPTION DESCRIPTIONS</title> + + <section> + <title>SSL OPTION DESCRIPTIONS - COMMON for SERVER and CLIENT</title> + + <p>Options described here are options that are have the same + meaning in the client and the server. + </p> <taglist> - <tag>{verify, verify_type()}</tag> - <item> If <c>verify_none</c> is specified x509-certificate - path validation errors at the client side - will not automatically cause the connection to fail, as - it will if the verify type is <c>verify_peer</c>. See also - the option verify_fun. - Servers only do the path validation if <c>verify_peer</c> is set to - true, as it then will - send a certificate request to - the client (this message is not sent if the verify option is - <c>verify_none</c>) and you may then also want to specify - the option <c>fail_if_no_peer_cert</c>. - </item> - <tag>{fail_if_no_peer_cert, boolean()}</tag> - <item>Used together with {verify, verify_peer} by a ssl server. - If set to true, - the server will fail if the client does not have a certificate - to send, e.i sends a empty certificate, if set to false it will - only fail if the client sends a invalid certificate (an empty - certificate is considered valid). - </item> + <tag>{cert, der_bin()}</tag> + <item> The DER encoded users certificate. If this option + is supplied it will override the certfile option.</item> - <tag>{verify_fun, fun(ErrorList) -> boolean()}</tag> - <item>Used by the ssl client to determine if - x509-certificate path validations errors are acceptable or - if the connection should fail. Defaults to: - -<code> -fun(ErrorList) -> - case lists:foldl(fun({bad_cert,unknown_ca}, Acc) -> - Acc; - (Other, Acc) -> - [Other | Acc] - end, [], ErrorList) of - [] -> - true; - [_|_] -> - false - end -end -</code> - I.e. by default if the only error found was that the CA-certificate - holder was unknown this will be accepted. - - Possible errors in the error list are: - {bad_cert, cert_expired}, {bad_cert, invalid_issuer}, - {bad_cert, invalid_signature}, {bad_cert, name_not_permitted}, - {bad_cert, unknown_ca}, - {bad_cert, cert_expired}, {bad_cert, invalid_issuer}, - {bad_cert, invalid_signature}, {bad_cert, name_not_permitted}, - {bad_cert, cert_revoked} (not implemented yet), - {bad_cert, unknown_critical_extension} or {bad_cert, term()} - </item> - + <tag>{certfile, path()}</tag> + <item>Path to a file containing the user's certificate.</item> - <tag>{validate_extensions_fun, fun()}</tag> - <item> - This options makes it possible to supply a fun to validate - possible application specific certificate extensions - during the certificat path validation. This option - will be better documented onec the public_key API is more - mature. - </item> + <tag>{key, der_bin()}</tag> + <item> The DER encoded users private key. If this option + is supplied it will override the keyfile option.</item> - <tag>{depth, integer()}</tag> - <item>Specifies the maximum - verification depth, i.e. how far in a chain of certificates the - verification process can proceed before the verification is - considered to fail. Peer certificate = 0, CA certificate = 1, - higher level CA certificate = 2, etc. The value 2 thus means - that a chain can at most contain peer cert, CA cert, next CA - cert, and an additional CA cert. The default value is 1. - </item> - - <tag>{certfile, path()}</tag> - <item>Path to a file containing the - user's certificate. Optional for clients but note - that some servers requires that the client can certify - itself. </item> <tag>{keyfile, path()}</tag> <item>Path to file containing user's private PEM encoded key. As PEM-files may contain several entries this option defaults to the same file as given by certfile option.</item> + <tag>{password, string()}</tag> <item>String containing the user's password. Only used if the private keyfile is password protected. </item> + + <tag>{cacerts, [der_bin()]}</tag> + <item> The DER encoded trusted certificates. If this option + is supplied it will override the cacertfile option.</item> + <tag>{cacertfile, path()}</tag> <item>Path to file containing PEM encoded CA certificates (trusted certificates used for verifying a peer certificate). May be omitted if you do not want to verify the peer.</item> - <tag>{dhfile, path()}</tag> - <item>Path to file containing PEM encoded Diffie Hellman parameters, - for the server to use if a cipher suite using Diffie Hellman key exchange - is negotiated. If not specified hardcode parameters will be used. - </item> - <tag>{ciphers, ciphers()}</tag> - <item>The function <c>ciphers_suites/0</c> can - be used to find all available ciphers. + <item>The cipher suites that should be supported. The function + <c>ciphers_suites/0</c> can be used to find all available + ciphers. </item> <tag>{ssl_imp, ssl_imp()}</tag> @@ -237,13 +179,152 @@ end new. </item> + <tag>{secure_renegotiate, boolean()}</tag> + <item>Specifies if to reject renegotiation attempt that does + not live up to RFC 5746. By default secure_renegotiate is + set to false i.e. secure renegotiation will be used if possible + but it will fallback to unsecure renegotiation if the peer + does not support RFC 5746. + </item> + + <tag>{depth, integer()}</tag> + <item>Specifies the maximum + verification depth, i.e. how far in a chain of certificates the + verification process can proceed before the verification is + considered to fail. Peer certificate = 0, CA certificate = 1, + higher level CA certificate = 2, etc. The value 2 thus means + that a chain can at most contain peer cert, CA cert, next CA + cert, and an additional CA cert. The default value is 1. + </item> + + <tag>{verify_fun, {Verifyfun :: fun(), InitialUserState :: term()}}</tag> + <item> + <p>The verification fun should be defined as:</p> + + <code> + fun(OtpCert :: #'OtpCertificate'{}, + Event :: {bad_cert, Reason :: atom()} | + {extension, #'Extension'{}}, InitialUserState :: term()) -> + {valid, UserState :: term()} | {fail, Reason :: term()} | + {unknown, UserState :: term()}. + </code> + + <p>The verify fun will be called during the X509-path + validation when an error or an extension unknown to the ssl + application is encountered. See + <seealso marker="public_key:application">public_key(3)</seealso> + for definition of #'OtpCertificate'{} and #'Extension'{}.</p> + + <p>If the verify callback fun returns {fail, Reason}, the + verification process is immediately stopped and an alert is + sent to the peer and the TLS/SSL handshake is terminated. If + the verify callback fun returns {valid, UserState}, the + verification process is continued. If the verify callback fun + always returns {valid, UserState}, the TLS/SSL handshake will + not be terminated with respect to verification failures and + the connection will be established. If called with an + extension unknown to the user application the return value + {unknown, UserState} should be used.</p> + + <p>The default verify_fun option in verify_peer mode:</p> + + <code> + {fun(_,{bad_cert, _} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState} + end, []} + </code> + + <p>The default verify_fun option in verify_none mode:</p> + + <code> + {fun(_,{bad_cert, unknown_ca}, UserState) -> + {valid, UserState}; + (_,{bad_cert, _} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState} + end, []} + </code> + + <p> Possible path validation errors: + {bad_cert, cert_expired}, + {bad_cert, invalid_issuer}, + {bad_cert, invalid_signature}, + {bad_cert, unknown_ca}, + {bad_cert, name_not_permitted}, + {bad_cert, missing_basic_constraint}, + {bad_cert, invalid_key_usage}, + {bad_cert, invalid_subject_altname}</p> + </item> + + </taglist> + + </section> + + <section> + <title>SSL OPTION DESCRIPTIONS - CLIENT SIDE</title> + + <p>Option described here are client specific or has a slightly different + meaning in the client than in the server.</p> + + <taglist> + <tag>{verify, verify_type()}</tag> + <item> In verify_none mode the x509-path validation error {bad_cert, unknown_ca} + will automatically be accepted. See also the verify_fun option. + </item> + <tag>{reuse_sessions, boolean()}</tag> + <item>Specifies if client should try to reuse sessions + when possible. + </item> + + </taglist> + </section> + + <section> + <title>SSL OPTION DESCRIPTIONS - SERVER SIDE</title> + + <p>Option described here are server specific or has a slightly different + meaning in the server than in the client.</p> + + <taglist> + + <tag>{dh, der_bin()}</tag> + <item>The DER encoded Diffie Hellman parameters. If this option + is supplied it will override the dhfile option. + </item> + + <tag>{dhfile, path()}</tag> + <item>Path to file containing PEM encoded Diffie Hellman parameters, + for the server to use if a cipher suite using Diffie Hellman key exchange + is negotiated. If not specified default parameters will be used. + </item> + + <tag>{verify, verify_type()}</tag> + <item>Servers only do the x509-path validation in verify_peer + mode, as it then will send a certificate request to the client + (this message is not sent if the verify option is verify_none) + and you may then also want to specify the option + fail_if_no_peer_cert. + </item> + + <tag>{fail_if_no_peer_cert, boolean()}</tag> + <item>Used together with {verify, verify_peer} by a ssl server. + If set to true, the server will fail if the client does not have + a certificate to send, i.e. sends a empty certificate, if set to + false it will only fail if the client sends a invalid + certificate (an empty certificate is considered valid). + </item> + <tag>{reuse_sessions, boolean()}</tag> - <item>Specifies if ssl sessions should be reused - when possible. + <item>Specifies if the server should agree to reuse sessions + when the clients request to do so. See also the reuse_session + option. </item> - <tag>{reuse_session, fun(SuggestedSessionId, - PeerCert, Compression, CipherSuite) -> boolean()}</tag> + <tag>{reuse_session, fun(SuggestedSessionId, + PeerCert, Compression, CipherSuite) -> boolean()}</tag> <item>Enables the ssl server to have a local policy for deciding if a session should be reused or not, only meaning full if <c>reuse_sessions</c> is set to true. @@ -252,14 +333,6 @@ end and CipherSuite of type ciphersuite(). </item> - <tag>{secure_renegotiate, boolean()}</tag> - <item>Specifies if to reject renegotiation attempt that does - not live up to RFC 5746. By default secure_renegotiate is - set to false e.i. secure renegotiation will be used if possible - but it will fallback to unsecure renegotiation if the peer - does not support RFC 5746. - </item> - </taglist> </section> @@ -316,7 +389,7 @@ end <v>Reason = term()</v> </type> <desc> <p>Upgrades a gen_tcp, or equivalent, - connected socket to a ssl socket e.i performs the + connected socket to a ssl socket i.e. performs the client-side ssl handshake.</p> </desc> </func> @@ -559,12 +632,12 @@ end </type> <desc> <p> Upgrades a gen_tcp, or - equivalent, socket to a ssl socket e.i performs the + equivalent, socket to a ssl socket i.e. performs the ssl server-side handshake.</p> - <p><note>Note that the listen socket should be in {active, false} mode + <p><warning>Note that the listen socket should be in {active, false} mode before telling the client that the server is ready to upgrade and calling this function, otherwise the upgrade may - or may not succeed depending on timing.</note></p> + or may not succeed depending on timing.</warning></p> </desc> </func> diff --git a/lib/ssl/doc/src/ssl_distribution.xml b/lib/ssl/doc/src/ssl_distribution.xml index 4067fb8a22..7bcc12eb5f 100644 --- a/lib/ssl/doc/src/ssl_distribution.xml +++ b/lib/ssl/doc/src/ssl_distribution.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2000</year><year>2009</year> + <year>2000</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -36,7 +36,7 @@ <note><p>Note this documentation is written for the old ssl implementation and - will be updated for the new one once this functionallity is + will be updated for the new one once this functionality is supported by the new implementation.</p></note> </p> @@ -55,7 +55,7 @@ all participating Erlang nodes in a distributed system must use this distribution module.</p> <p>The security depends on how the connections are set up, one can - use key files or certificates to just get a crypted + use key files or certificates to just get a encrypted connection. One can also make the SSL package verify the certificates of other nodes to get additional security. Cookies are however always used as they can be used to @@ -179,7 +179,7 @@ Eshell V5.0 (abort with ^G) <c>certfile</c> can (and usually needs to) be specified as <c>client_certfile</c> and <c>server_certfile</c>. The <c>client_certfile</c> is used when the distribution initiates a - connection to another node and the <c>server_cerfile</c> is used + connection to another node and the <c>server_certfile</c> is used when accepting a connection from a remote node. </p> <p>The command line argument for specifying the SSL options is named <c>-ssl_dist_opt</c> and should be followed by an even number of diff --git a/lib/ssl/doc/src/ssl_protocol.xml b/lib/ssl/doc/src/ssl_protocol.xml index 726b9a4eeb..6936408881 100644 --- a/lib/ssl/doc/src/ssl_protocol.xml +++ b/lib/ssl/doc/src/ssl_protocol.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2003</year><year>2009</year> + <year>2003</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -44,7 +44,7 @@ <section> <title>Security overview</title> - <p>To achive authentication and privacy the client and server will + <p>To achieve authentication and privacy the client and server will perform a TLS Handshake procedure before transmitting or receiving any data. During the handshake they agree on a protocol version and cryptographic algorithms, they generate shared secrets using public @@ -56,7 +56,7 @@ <title>Data Privacy and Integrity</title> <p>A <em>symmetric key</em> algorithm has one key only. The key is - used for both encryption and decryption. These algoritms are fast + used for both encryption and decryption. These algorithms are fast compared to public key algorithms (using two keys, a public and a private one) and are therefore typically used for encrypting bulk data. @@ -66,7 +66,7 @@ for each connection and are based on a secret negotiated in the TLS handshake. </p> - <p>The TLS handsake protocol and data transfer is run on top of + <p>The TLS handshake protocol and data transfer is run on top of the TLS Record Protocol that uses a keyed-hash MAC (Message Authenticity Code), or HMAC, to protect the message's data integrity. From the TLS RFC "A Message Authentication Code is a @@ -85,7 +85,7 @@ with the private key of the issuer of the certificate. A chain of trust is build by having the issuer in its turn being certified by an other certificate and so on until you reach the - so called root certificate that is self signed e.i. issued + so called root certificate that is self signed i.e. issued by itself.</p> <p>Certificates are issued by <em>certification diff --git a/lib/ssl/doc/src/ssl_session_cache_api.xml b/lib/ssl/doc/src/ssl_session_cache_api.xml index 7b70c6cf34..e0b07961fb 100644 --- a/lib/ssl/doc/src/ssl_session_cache_api.xml +++ b/lib/ssl/doc/src/ssl_session_cache_api.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> @@ -25,7 +25,7 @@ </header> <module>ssl_session_cache_api</module> <modulesummary>Defines the API for the TLS session cache so - that the datastorge scheme can be replaced by + that the data storage scheme can be replaced by defining a new callback module implementing this API.</modulesummary> <section> @@ -56,7 +56,7 @@ <v> Key = key()</v> </type> <desc> - <p> Delets a cache entry. Will only be called from the cache + <p> Deletes a cache entry. Will only be called from the cache handling process. </p> </desc> @@ -85,10 +85,10 @@ <v></v> </type> <desc> - <p>Performes possible initializations of the cache and returns + <p>Performs possible initializations of the cache and returns a reference to it that will be used as parameter to the other api functions. Will be called by the cache handling processes - init function, hence puting the same requierments on it as + init function, hence putting the same requirements on it as a normal process init function. </p> </desc> @@ -96,16 +96,16 @@ <func> <name>lookup(Cache, Key) -> Entry</name> - <fsummary> Looks up a cach entry.</fsummary> + <fsummary> Looks up a cache entry.</fsummary> <type> <v> Cache = cache_ref()</v> <v> Key = key()</v> <v> Entry = session() | undefined </v> </type> <desc> - <p>Looks up a cach entry. Should be callable from any - process. - </p> + <p>Looks up a cache entry. Should be callable from any + process. + </p> </desc> </func> @@ -127,7 +127,7 @@ <func> <name>terminate(Cache) -> _</name> <fsummary>Called by the process that handles the cache when it - is aboute to terminat.</fsummary> + is about to terminate.</fsummary> <type> <v>Cache = term() - as returned by init/0</v> </type> diff --git a/lib/ssl/examples/certs/Makefile b/lib/ssl/examples/certs/Makefile index 121fcc6950..b811b461dc 100644 --- a/lib/ssl/examples/certs/Makefile +++ b/lib/ssl/examples/certs/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2003-2009. All Rights Reserved. +# Copyright Ericsson AB 2003-2010. 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,4 +21,41 @@ # Invoke with GNU make or clearmake -C gnu. # -include $(ERL_TOP)/make/run_make.mk +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../../vsn.mk +VSN=$(SSL_VSN) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN) + +TARGET_FILES= + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +debug opt: $(TARGET_FILES) + +clean: + rm -fr $(TARGET_FILES) *~ *.beam + +docs: + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + $(INSTALL_DIR) $(RELSYSDIR)/examples/certs + tar cf - etc | \ + (cd $(RELSYSDIR)/examples/certs; tar xf -) + chmod -f -R ug+rw $(RELSYSDIR)/examples +release_docs_spec: diff --git a/lib/ssl/examples/certs/Makefile.in b/lib/ssl/examples/certs/Makefile.in deleted file mode 100644 index 4ea7aaf6dc..0000000000 --- a/lib/ssl/examples/certs/Makefile.in +++ /dev/null @@ -1,80 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2003-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% -# - -# - -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -include ../../vsn.mk -VSN=$(SSL_VSN) - -RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN) - -EBIN = ebin -ETC = etc -SRC = src - -OPENSSL_CMD = @OPENSSL_CMD@ - -# We are generating more files than in the following list, but we take -# there existence as successful execution of make rules - -PEMS = cacerts.pem cert.pem key.pem - -PEMFILES = $(PEMS:%=$(ETC)/client/%) $(PEMS:%=$(ETC)/server/%) - -debug opt: $(PEMFILES) - -$(PEMFILES): done - -done: $(EBIN)/make_certs.beam - erl -noinput -pa $(EBIN) -run make_certs all $(OPENSSL_CMD) \ - -s erlang halt - echo >done - -$(EBIN)/make_certs.beam: $(SRC)/make_certs.erl - cd src; erlc -W -o ../$(EBIN) make_certs.erl - -clean: - rm -fr $(EBIN)/* $(SRC)/*~ $(SRC)/*.beam $(ETC) done \ - stderr.txt erl_crash.dump *~ - -docs: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) $(RELSYSDIR)/examples/certs - tar cf - Makefile ebin etc rnd src | \ - (cd $(RELSYSDIR)/examples/certs; tar xf -) - chmod -f -R ug+rw $(RELSYSDIR)/examples - -release_docs_spec: - - - - - - - - diff --git a/lib/ssl/examples/certs/ebin/.gitignore b/lib/ssl/examples/certs/ebin/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/ssl/examples/certs/ebin/.gitignore +++ /dev/null diff --git a/lib/ssl/examples/certs/etc/client/cacerts.pem b/lib/ssl/examples/certs/etc/client/cacerts.pem new file mode 100644 index 0000000000..cb19d3d41e --- /dev/null +++ b/lib/ssl/examples/certs/etc/client/cacerts.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIICizCCAfSgAwIBAgIFdMMs9fEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI +ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD +VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS +BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw +MDAwMDBaMH0xETAPBgNVBAMTCGVybGFuZ0NBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0 +ZXJAZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEP +MA0GA1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAgmHw2xApZqdzZOOPTzwHr1hRYd1OqbLOsXbAq6kJ +Kuu+qe5jAlMF3vnUhiHomuZeNZVJe3SP+JfBt3BHMjm2CLChCuNgfctKURMlEc/L +xo8fO1Jk9MD5mbG2Utx3m3gM6Liwt9fHVABlCTyB6/jXrK1tYpEG5CrwUXyy8Htl +jHECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAl +0tMEXWPgzXTpDuNmuKh6aGq9CuExUuEXXQQWPThzEuluA3aHFmObziQlMY1+KeO1 +AL0kpx0Yhvju/rfAJ+OF6MMni6hJoKlYTVml+fCY89A3nmY1rJHJavjHp0OIPGxh +4Sr+EcjROkqe8jE0DmbwmM6lzpwSJscxte+V6HvGRw== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIICiDCCAfGgAwIBAgIFSHyFNTEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI +ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD +VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS +BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw +MDAwMDBaMHoxDjAMBgNVBAMTBW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJA +ZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0G +A1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAjEt9iy365+mTialKDKb3l2QPg71yavJA1ZC6aGC14X7x +KCm1FhUYsVKOlWjmC1VYJiCS01gvKqMXiogreHJGM93E+URlKkOm9kmOWQwLfFb8 +JLzafPi3/8TUdjl8UuIDHyPsoQiM2ZBDUVWezfl+CBsTYFO3U4Lqf9OKbCxTF78C +AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAv6vHw +wK3MvxzlhDJIx7rUasOYJDZJyOt71KdOKeA7+ocbvDIblmV7sTbe3oQNqbSATZ6H +RUqHZdPhKIZ9wjEBSKdBTL8rc0TvbztMvd+i0rkTCL/bspQYchA2zCcjgkWqpaN4 +OhOjQR1+9/ntmaU/r5Ca7KmrXEf5XSQIGLSMag== +-----END CERTIFICATE----- + diff --git a/lib/ssl/examples/certs/etc/client/cert.pem b/lib/ssl/examples/certs/etc/client/cert.pem new file mode 100644 index 0000000000..a2f53aaf82 --- /dev/null +++ b/lib/ssl/examples/certs/etc/client/cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAfCgAwIBAgIGAIsapa8BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT +BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE +BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD +VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw +MDAwWjB7MQ8wDQYDVQQDEwZjbGllbnQxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl +cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD +VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSV +wC+n0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53 +h2Zr3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwID +AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAG8t6f1A +PF7xayGxtUpG2r6W5ETylC3ZIKPS2kfJk9aYi7AZNTp7/xTU6SgqvFBN8aBPzxCD +4jHrSNC8DSb4X1x9uimarb6qdZDHEdij+DRAd2eygJHZxEf7+8B4Fx34thQeU9hZ +S1Izke5AlsyFMkvB7h0anE4k9BfuU70vl6v5 +-----END CERTIFICATE----- + diff --git a/lib/ssl/examples/certs/etc/client/key.pem b/lib/ssl/examples/certs/etc/client/key.pem new file mode 100644 index 0000000000..4d55b08f4c --- /dev/null +++ b/lib/ssl/examples/certs/etc/client/key.pem @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSVwC+n +0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53h2Zr +3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwIDAQAB +AoGACdIVYe/LTeydUihtInC8lZ2QuPgJmoBNocRjqJFipEihoL4scHAx25n1bBvB +I0HZphffzBkGp28oBAtl2LRPWXqu527unc/RWRfLMqSK1xNSq1DxD1a30zkrZPna +QiV65vEJuNSJTtlDy/Zqc/BVZXCpxWlzYQedZgkmf0Qse8ECQQCmaz02Yur8zC9f +eSQKU5OSzGw3bSIumEzziCfHdTheK6MEoccf5TCAyLXhZwA7QlKja4tFXfeyVxws +/LlnUJN9AkEA4j+xnOeYUyGKXL5i+BAbnqpI4MzPiq+IoCYkaRlD/wAws24r5HNI +ZQmEHWqD/NNzOf/A2XuyLtMiTGJPW/DftwJBAKKpJP6Ytuh6xz8BUCnLwO12Y7vV +LtjuQiCzD3aUa5EYA9HOMqxJPxxRkf0LyR0i2VUkE8+sZiPpov+R0cJa7p0CQQCj +40GUiArGRSiF7/+e84QeVfl+pb29F1QftiFv5DZmFEwy3Z572KpbTh5edJbxYHY6 +UDHxGHJFCvnwXNJhpkVXAkBJqfEfiMJ3Q/E5Gpf3sQizacouW92iiN8ojlF1oB80 +t34RysJH7SgI3gdMhTribCo2UUaV0StjR6yodPN+TB2J +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssl/examples/certs/etc/erlangCA/cert.pem b/lib/ssl/examples/certs/etc/erlangCA/cert.pem new file mode 100644 index 0000000000..c4386494dc --- /dev/null +++ b/lib/ssl/examples/certs/etc/erlangCA/cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICizCCAfSgAwIBAgIFdMMs9fEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI +ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD +VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS +BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw +MDAwMDBaMH0xETAPBgNVBAMTCGVybGFuZ0NBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0 +ZXJAZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEP +MA0GA1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAgmHw2xApZqdzZOOPTzwHr1hRYd1OqbLOsXbAq6kJ +Kuu+qe5jAlMF3vnUhiHomuZeNZVJe3SP+JfBt3BHMjm2CLChCuNgfctKURMlEc/L +xo8fO1Jk9MD5mbG2Utx3m3gM6Liwt9fHVABlCTyB6/jXrK1tYpEG5CrwUXyy8Htl +jHECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAl +0tMEXWPgzXTpDuNmuKh6aGq9CuExUuEXXQQWPThzEuluA3aHFmObziQlMY1+KeO1 +AL0kpx0Yhvju/rfAJ+OF6MMni6hJoKlYTVml+fCY89A3nmY1rJHJavjHp0OIPGxh +4Sr+EcjROkqe8jE0DmbwmM6lzpwSJscxte+V6HvGRw== +-----END CERTIFICATE----- + diff --git a/lib/ssl/examples/certs/etc/otpCA/cert.pem b/lib/ssl/examples/certs/etc/otpCA/cert.pem new file mode 100644 index 0000000000..8610621695 --- /dev/null +++ b/lib/ssl/examples/certs/etc/otpCA/cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICiDCCAfGgAwIBAgIFSHyFNTEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI +ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD +VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS +BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw +MDAwMDBaMHoxDjAMBgNVBAMTBW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJA +ZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0G +A1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAjEt9iy365+mTialKDKb3l2QPg71yavJA1ZC6aGC14X7x +KCm1FhUYsVKOlWjmC1VYJiCS01gvKqMXiogreHJGM93E+URlKkOm9kmOWQwLfFb8 +JLzafPi3/8TUdjl8UuIDHyPsoQiM2ZBDUVWezfl+CBsTYFO3U4Lqf9OKbCxTF78C +AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAv6vHw +wK3MvxzlhDJIx7rUasOYJDZJyOt71KdOKeA7+ocbvDIblmV7sTbe3oQNqbSATZ6H +RUqHZdPhKIZ9wjEBSKdBTL8rc0TvbztMvd+i0rkTCL/bspQYchA2zCcjgkWqpaN4 +OhOjQR1+9/ntmaU/r5Ca7KmrXEf5XSQIGLSMag== +-----END CERTIFICATE----- + diff --git a/lib/ssl/examples/certs/etc/server/cacerts.pem b/lib/ssl/examples/certs/etc/server/cacerts.pem new file mode 100644 index 0000000000..cb19d3d41e --- /dev/null +++ b/lib/ssl/examples/certs/etc/server/cacerts.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIICizCCAfSgAwIBAgIFdMMs9fEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI +ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD +VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS +BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw +MDAwMDBaMH0xETAPBgNVBAMTCGVybGFuZ0NBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0 +ZXJAZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEP +MA0GA1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAgmHw2xApZqdzZOOPTzwHr1hRYd1OqbLOsXbAq6kJ +Kuu+qe5jAlMF3vnUhiHomuZeNZVJe3SP+JfBt3BHMjm2CLChCuNgfctKURMlEc/L +xo8fO1Jk9MD5mbG2Utx3m3gM6Liwt9fHVABlCTyB6/jXrK1tYpEG5CrwUXyy8Htl +jHECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAl +0tMEXWPgzXTpDuNmuKh6aGq9CuExUuEXXQQWPThzEuluA3aHFmObziQlMY1+KeO1 +AL0kpx0Yhvju/rfAJ+OF6MMni6hJoKlYTVml+fCY89A3nmY1rJHJavjHp0OIPGxh +4Sr+EcjROkqe8jE0DmbwmM6lzpwSJscxte+V6HvGRw== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIICiDCCAfGgAwIBAgIFSHyFNTEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI +ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD +VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS +BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw +MDAwMDBaMHoxDjAMBgNVBAMTBW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJA +ZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0G +A1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAjEt9iy365+mTialKDKb3l2QPg71yavJA1ZC6aGC14X7x +KCm1FhUYsVKOlWjmC1VYJiCS01gvKqMXiogreHJGM93E+URlKkOm9kmOWQwLfFb8 +JLzafPi3/8TUdjl8UuIDHyPsoQiM2ZBDUVWezfl+CBsTYFO3U4Lqf9OKbCxTF78C +AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAv6vHw +wK3MvxzlhDJIx7rUasOYJDZJyOt71KdOKeA7+ocbvDIblmV7sTbe3oQNqbSATZ6H +RUqHZdPhKIZ9wjEBSKdBTL8rc0TvbztMvd+i0rkTCL/bspQYchA2zCcjgkWqpaN4 +OhOjQR1+9/ntmaU/r5Ca7KmrXEf5XSQIGLSMag== +-----END CERTIFICATE----- + diff --git a/lib/ssl/examples/certs/etc/server/cert.pem b/lib/ssl/examples/certs/etc/server/cert.pem new file mode 100644 index 0000000000..f26adb7f5c --- /dev/null +++ b/lib/ssl/examples/certs/etc/server/cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAfCgAwIBAgIGANUxXM9BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT +BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE +BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD +VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw +MDAwWjB7MQ8wDQYDVQQDEwZzZXJ2ZXIxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl +cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD +VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9 +Adq67k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ +4UAtNHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQID +AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAGF5Pfwk +QDdwJup/mVITPxbBls4Yl7anDooUQsq8066lA1g54H/PRfXscGkyCFGh1ifXvf1L +psMRoBAdDHL/wSJplk3rRavkC94eBgnTFZmfKL6844g1j53yameiYL8IEVExYMBg +/XGyc0qwq57WT8B/K4aElrvlBlQ0wF3wN54M +-----END CERTIFICATE----- + diff --git a/lib/ssl/examples/certs/etc/server/key.pem b/lib/ssl/examples/certs/etc/server/key.pem new file mode 100644 index 0000000000..c1392ca557 --- /dev/null +++ b/lib/ssl/examples/certs/etc/server/key.pem @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9Adq6 +7k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ4UAt +NHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQIDAQAB +AoGAQIlma0r6W6bcRj4+Wd4fXCFvHuq5Psu1fYEeC5Yvz8761xVjjSfbrDHJZ9pm +FjOEgedK+s5lbDXqYVyjbdyZSugStBRocSmbG8SQHcAsxR2ZIkNzX2hYzB+lslWo +T3YJojDyB134O7XJznCu+ZFXP86jyJ1JT6k6a+OIHcwnJ+ECQQDYn57dY4Px3mEd +VBLStN3YkRF5oFyT+xk7IaKeLLB6n4gCnoVbBoHut7PFbPYPzoNzEwPk3MQKDIHb +Kig3S5CpAkEAvPA1VmoJWAlN6kUi+F2L8HXEArzE8x7vwdsslrwMKUe4dFS+ZC/7 +5iDOaxcZ7TYkCgwzBt341++DCgP6j3fY1QJBALB6AcOcwi52m6l4B8mu3ZkEPjdX +BHTuONTqhv/TqoaLlxODL2NDvvDKqeMp7KBd/srt79swW2lQXS4+fvrlTdkCQQCm +zxj4O1QWkthkfje6ubSkTwUIOatUzrp1F9GNH2dJRtX2dx9FCwxGCC7WY6XzRXqa +GF0wsedSllbGD+82nWQlAkAicMGqCqRq4hKR/cVmFatOqKVWCVkx6OFF2FhuiI5Z +h5eIOPGCt8dVRs1P9DNSld/D98Sfm65m85z8BtXovvYV +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssl/examples/certs/rnd/RAND b/lib/ssl/examples/certs/rnd/RAND Binary files differdeleted file mode 100644 index 70997bd01f..0000000000 --- a/lib/ssl/examples/certs/rnd/RAND +++ /dev/null diff --git a/lib/ssl/examples/certs/src/make_certs.erl b/lib/ssl/examples/certs/src/make_certs.erl index c374836568..fe267bed28 100644 --- a/lib/ssl/examples/certs/src/make_certs.erl +++ b/lib/ssl/examples/certs/src/make_certs.erl @@ -1,261 +1,48 @@ -%% The purpose of this module is to create example certificates for -%% testing. -%% Run it as: -%% -%% erl -noinput -run make_certs all "/path/to/openssl" -s erlang halt -%% +%% The purpose of this module is to log how the example certs where created, +%% it requires erl_make_certs found in the test directory. -module(make_certs). --export([all/0, all/1]). - --record(dn, {commonName, - organizationalUnitName = "Erlang OTP", - organizationName = "Ericsson AB", - localityName = "Stockholm", - countryName = "SE", - emailAddress = "[email protected]"}). +-export([all/0]). all() -> - all(["openssl"]). - -all([OpenSSLCmd]) -> - Root = filename:dirname(filename:dirname((code:which(?MODULE)))), - %% io:fwrite("Root : ~s~n", [Root]), - NRoot = filename:join([Root, "etc"]), - file:make_dir(NRoot), - create_rnd(Root, "etc"), % For all requests - rootCA(NRoot, OpenSSLCmd, "erlangCA"), - intermediateCA(NRoot, OpenSSLCmd, "otpCA", "erlangCA"), - endusers(NRoot, OpenSSLCmd, "otpCA", ["client", "server"]), - collect_certs(NRoot, ["erlangCA", "otpCA"], ["client", "server"]), - remove_rnd(Root, "etc"). - -rootCA(Root, OpenSSLCmd, Name) -> - create_ca_dir(Root, Name, ca_cnf(Name)), - DN = #dn{commonName = Name}, - create_self_signed_cert(Root, OpenSSLCmd, Name, req_cnf(DN)), - ok. - -intermediateCA(Root, OpenSSLCmd, CA, ParentCA) -> - CA = "otpCA", - create_ca_dir(Root, CA, ca_cnf(CA)), - CARoot = filename:join([Root, CA]), - DN = #dn{commonName = CA}, - CnfFile = filename:join([CARoot, "req.cnf"]), - file:write_file(CnfFile, req_cnf(DN)), - KeyFile = filename:join([CARoot, "private", "key.pem"]), - ReqFile = filename:join([CARoot, "req.pem"]), - create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile), - CertFile = filename:join([CARoot, "cert.pem"]), - sign_req(Root, OpenSSLCmd, ParentCA, "ca_cert", ReqFile, CertFile). - -endusers(Root, OpenSSLCmd, CA, Users) -> - lists:foreach(fun(User) -> enduser(Root, OpenSSLCmd, CA, User) end, Users). - -enduser(Root, OpenSSLCmd, CA, User) -> - UsrRoot = filename:join([Root, User]), - file:make_dir(UsrRoot), - CnfFile = filename:join([UsrRoot, "req.cnf"]), - DN = #dn{commonName = User}, - file:write_file(CnfFile, req_cnf(DN)), - KeyFile = filename:join([UsrRoot, "key.pem"]), - ReqFile = filename:join([UsrRoot, "req.pem"]), - create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile), - CertFile = filename:join([UsrRoot, "cert.pem"]), - sign_req(Root, OpenSSLCmd, CA, "user_cert", ReqFile, CertFile). - -collect_certs(Root, CAs, Users) -> - Bins = lists:foldr( - fun(CA, Acc) -> - File = filename:join([Root, CA, "cert.pem"]), - {ok, Bin} = file:read_file(File), - [Bin, "\n" | Acc] - end, [], CAs), - lists:foreach( - fun(User) -> - File = filename:join([Root, User, "cacerts.pem"]), - file:write_file(File, Bins) - end, Users). - -create_self_signed_cert(Root, OpenSSLCmd, CAName, Cnf) -> - CARoot = filename:join([Root, CAName]), - CnfFile = filename:join([CARoot, "req.cnf"]), - file:write_file(CnfFile, Cnf), - KeyFile = filename:join([CARoot, "private", "key.pem"]), - CertFile = filename:join([CARoot, "cert.pem"]), - Cmd = [OpenSSLCmd, " req" - " -new" - " -x509" - " -config ", CnfFile, - " -keyout ", KeyFile, - " -out ", CertFile], - Env = [{"ROOTDIR", Root}], - cmd(Cmd, Env). - -create_ca_dir(Root, CAName, Cnf) -> - CARoot = filename:join([Root, CAName]), - file:make_dir(CARoot), - create_dirs(CARoot, ["certs", "crl", "newcerts", "private"]), - create_rnd(Root, filename:join([CAName, "private"])), - create_files(CARoot, [{"serial", "01\n"}, - {"index.txt", ""}, - {"ca.cnf", Cnf}]). - -create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile) -> - Cmd = [OpenSSLCmd, " req" - " -new" - " -config ", CnfFile, - " -keyout ", KeyFile, - " -out ", ReqFile], - Env = [{"ROOTDIR", Root}], - cmd(Cmd, Env). - -sign_req(Root, OpenSSLCmd, CA, CertType, ReqFile, CertFile) -> - CACnfFile = filename:join([Root, CA, "ca.cnf"]), - Cmd = [OpenSSLCmd, " ca" - " -batch" - " -notext" - " -config ", CACnfFile, - " -extensions ", CertType, - " -in ", ReqFile, - " -out ", CertFile], - Env = [{"ROOTDIR", Root}], - cmd(Cmd, Env). + LongTime = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+15*365), + Validity = {date(), LongTime}, + Subject = [{email, "[email protected]"}, + {city, "Stockholm"}, + {country, "SE"}, + {org, "erlang"}, + {org_unit, "testing dep"}], + + RootCa = erl_make_certs:make_cert([{validity, Validity}, {subject, [{name, "erlangCA"}|Subject]}]), + ImedCa = erl_make_certs:make_cert([{issuer, RootCa}, {validity, Validity}, + {subject, [{name, "otpCA"}|Subject]}]), + ClientCa = erl_make_certs:make_cert([{issuer, ImedCa}, {validity, Validity}, + {subject, [{name, "client"}|Subject]}]), + ServerCa = erl_make_certs:make_cert([{issuer, ImedCa}, {validity, Validity}, + {subject, [{name, "server"}|Subject]}]), + + Root0 = filename:dirname(filename:dirname((code:which(?MODULE)))), + Root = filename:join([Root0, "etc"]), file:make_dir(Root), + CaPath = filename:join([Root, "erlangCA"]), file:make_dir(CaPath), + IPath = filename:join([Root, "otpCA"]), file:make_dir(IPath), + CPath = filename:join([Root, "client"]), file:make_dir(CPath), + SPath = filename:join([Root, "server"]), file:make_dir(SPath), + + erl_make_certs:write_pem(CaPath,"cert", RootCa), + erl_make_certs:write_pem(IPath, "cert", ImedCa), + + {ok, CaBin0} = file:read_file(filename:join(CaPath, "cert.pem")), + {ok, CaBin1} = file:read_file(filename:join(IPath, "cert.pem")), + CaBin = <<CaBin0/binary, CaBin1/binary>>, + + erl_make_certs:write_pem(CPath, "cert", ClientCa), + ok = file:write_file(filename:join(CPath, "cacerts.pem"), CaBin), + erl_make_certs:write_pem(SPath, "cert", ServerCa), + ok = file:write_file(filename:join(SPath, "cacerts.pem"), CaBin), -%% -%% Misc -%% - -create_dirs(Root, Dirs) -> - lists:foreach(fun(Dir) -> - file:make_dir(filename:join([Root, Dir])) end, - Dirs). - -create_files(Root, NameContents) -> - lists:foreach( - fun({Name, Contents}) -> - file:write_file(filename:join([Root, Name]), Contents) end, - NameContents). - -create_rnd(Root, Dir) -> - From = filename:join([Root, "rnd", "RAND"]), - To = filename:join([Root, Dir, "RAND"]), - file:copy(From, To). - -remove_rnd(Root, Dir) -> - File = filename:join([Root, Dir, "RAND"]), - file:delete(File). - -cmd(Cmd, Env) -> - FCmd = lists:flatten(Cmd), - Port = open_port({spawn, FCmd}, [stream, eof, exit_status, - {env, Env}]), - eval_cmd(Port). - -eval_cmd(Port) -> - receive - {Port, {data, _}} -> - eval_cmd(Port); - {Port, eof} -> - ok - end, - receive - {Port, {exit_status, Status}} when Status /= 0 -> - %% io:fwrite("exit status: ~w~n", [Status]), - erlang:halt(Status) - after 0 -> - ok - end. - -%% -%% Contents of configuration files -%% - -req_cnf(DN) -> - ["# Purpose: Configuration for requests (end users and CAs)." - "\n" - "ROOTDIR = $ENV::ROOTDIR\n" - "\n" - - "[req]\n" - "input_password = secret\n" - "output_password = secret\n" - "default_bits = 1024\n" - "RANDFILE = $ROOTDIR/RAND\n" - "encrypt_key = no\n" - "default_md = sha1\n" - "#string_mask = pkix\n" - "x509_extensions = ca_ext\n" - "prompt = no\n" - "distinguished_name= name\n" - "\n" - - "[name]\n" - "commonName = ", DN#dn.commonName, "\n" - "organizationalUnitName = ", DN#dn.organizationalUnitName, "\n" - "organizationName = ", DN#dn.organizationName, "\n" - "localityName = ", DN#dn.localityName, "\n" - "countryName = ", DN#dn.countryName, "\n" - "emailAddress = ", DN#dn.emailAddress, "\n" - "\n" - - "[ca_ext]\n" - "basicConstraints = critical, CA:true\n" - "keyUsage = cRLSign, keyCertSign\n" - "subjectKeyIdentifier = hash\n" - "subjectAltName = email:copy\n"]. - - -ca_cnf(CA) -> - ["# Purpose: Configuration for CAs.\n" - "\n" - "ROOTDIR = $ENV::ROOTDIR\n" - "default_ca = ca\n" - "\n" - - "[ca]\n" - "dir = $ROOTDIR/", CA, "\n" - "certs = $dir/certs\n" - "crl_dir = $dir/crl\n" - "database = $dir/index.txt\n" - "new_certs_dir = $dir/newcerts\n" - "certificate = $dir/cert.pem\n" - "serial = $dir/serial\n" - "crl = $dir/crl.pem\n" - "private_key = $dir/private/key.pem\n" - "RANDFILE = $dir/private/RAND\n" - "\n" - "x509_extensions = user_cert\n" - "default_days = 3600\n" - "default_md = sha1\n" - "preserve = no\n" - "policy = policy_match\n" - "\n" - - "[policy_match]\n" - "commonName = supplied\n" - "organizationalUnitName = optional\n" - "organizationName = match\n" - "countryName = match\n" - "localityName = match\n" - "emailAddress = supplied\n" - "\n" - - "[user_cert]\n" - "basicConstraints = CA:false\n" - "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n" - "subjectKeyIdentifier = hash\n" - "authorityKeyIdentifier = keyid,issuer:always\n" - "subjectAltName = email:copy\n" - "issuerAltName = issuer:copy\n" - "\n" - - "[ca_cert]\n" - "basicConstraints = critical,CA:true\n" - "keyUsage = cRLSign, keyCertSign\n" - "subjectKeyIdentifier = hash\n" - "authorityKeyIdentifier = keyid:always,issuer:always\n" - "subjectAltName = email:copy\n" - "issuerAltName = issuer:copy\n"]. - + file:delete(filename:join(CaPath, "cert_key.pem")), + file:delete(filename:join(IPath, "cert_key.pem")), + file:rename(filename:join(CPath, "cert_key.pem"), filename:join(CPath, "key.pem")), + file:rename(filename:join(SPath, "cert_key.pem"), filename:join(SPath, "key.pem")), + ok. diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src index 65f23e2f74..88cd73be74 100644 --- a/lib/ssl/src/ssl.appup.src +++ b/lib/ssl/src/ssl.appup.src @@ -1,6 +1,7 @@ %% -*- erlang -*- {"%VSN%", [ + {"4.0", [{restart_application, ssl}]}, {"3.11.1", [{restart_application, ssl}]}, {"3.11", [{restart_application, ssl}]}, {"3.10", [{restart_application, ssl}]}, @@ -15,6 +16,7 @@ {"3.10.9", [{restart_application, ssl}]} ], [ + {"4.0", [{restart_application, ssl}]}, {"3.11.1", [{restart_application, ssl}]}, {"3.11", [{restart_application, ssl}]}, {"3.10", [{restart_application, ssl}]}, diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index df4cd7c84d..cc01b35b64 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -77,8 +77,10 @@ stop() -> application:stop(ssl). %%-------------------------------------------------------------------- --spec connect(host() | port(), port_num(), list()) -> {ok, #sslsocket{}}. --spec connect(host() | port(), port_num(), list(), timeout()) -> {ok, #sslsocket{}}. +-spec connect(host() | port(), list()) -> {ok, #sslsocket{}}. +-spec connect(host() | port(), list() | port_num(), timeout() | list()) -> {ok, #sslsocket{}}. +-spec connect(host() | port(), port_num(), list(), timeout()) -> {ok, #sslsocket{}}. + %% %% Description: Connect to a ssl server. %%-------------------------------------------------------------------- @@ -215,8 +217,8 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) -> {ok, #config{cb=CbInfo,ssl=SslOpts, emulated=EmOpts}} -> {ok, Port} = inet:port(Socket), ssl_connection:ssl_accept(Port, Socket, - {SslOpts, EmOpts}, - self(), CbInfo, Timeout) + {SslOpts, EmOpts}, + self(), CbInfo, Timeout) catch Error = {error, _Reason} -> Error end. @@ -326,7 +328,7 @@ decode_peercert(BinCert, Opts) -> {ok, BinCert} end. -select_part(otp, {ok, Cert}, Opts) -> +select_part(otp, Cert, Opts) -> case lists:member(subject, Opts) of true -> TBS = Cert#'OTPCertificate'.tbsCertificate, @@ -335,7 +337,7 @@ select_part(otp, {ok, Cert}, Opts) -> {ok, Cert} end; -select_part(plain, {ok, Cert}, Opts) -> +select_part(plain, Cert, Opts) -> case lists:member(subject, Opts) of true -> TBS = Cert#'Certificate'.tbsCertificate, @@ -374,7 +376,7 @@ cipher_suites(openssl) -> [ssl_cipher:openssl_suite_name(S) || S <- ssl_cipher:suites(Version)]. %%-------------------------------------------------------------------- --spec getopts(#sslsocket{}, [atom()]) -> {ok, [{atom(), term()}]}| {error, reason()}. +-spec getopts(#sslsocket{}, [atom()]) -> {ok, [{atom(), term()}]}| {error, reason()}. %% %% Description: %%-------------------------------------------------------------------- @@ -446,8 +448,8 @@ session_info(#sslsocket{pid = Pid, fd = new_ssl}) -> ssl_connection:session_info(Pid). %%--------------------------------------------------------------- --spec versions() -> [{{ssl_app, string()}, {supported, [tls_version()]}, - {available, [tls_version()]}}]. +-spec versions() -> [{ssl_app, string()} | {supported, [tls_atom_version()]} | + {available, [tls_atom_version()]}]. %% %% Description: Returns a list of relevant versions. %%-------------------------------------------------------------------- @@ -457,6 +459,7 @@ versions() -> AvailableVsns = ?DEFAULT_SUPPORTED_VERSIONS, [{ssl_app, ?VSN}, {supported, SupportedVsns}, {available, AvailableVsns}]. + %%--------------------------------------------------------------- -spec renegotiate(#sslsocket{}) -> ok | {error, reason()}. %% @@ -520,59 +523,64 @@ old_listen(Port, Options) -> {ok, Pid} = ssl_broker:start_broker(listener), ssl_broker:listen(Pid, Port, Options). -handle_options(Opts0, Role) -> +handle_options(Opts0, _Role) -> Opts = proplists:expand([{binary, [{mode, binary}]}, {list, [{mode, list}]}], Opts0), ReuseSessionFun = fun(_, _, _, _) -> true end, - AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc; - (Other, Acc) -> [Other | Acc] - end, - - VerifyFun = - fun(ErrorList) -> - case lists:foldl(AcceptBadCa, [], ErrorList) of - [] -> true; - [_|_] -> false - end - end, + VerifyNoneFun = + {fun(_,{bad_cert, unknown_ca}, UserState) -> + {valid, UserState}; + (_,{bad_cert, _} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState} + end, []}, - UserFailIfNoPeerCert = validate_option(fail_if_no_peer_cert, - proplists:get_value(fail_if_no_peer_cert, Opts, false)), + UserFailIfNoPeerCert = handle_option(fail_if_no_peer_cert, Opts, false), + UserVerifyFun = handle_option(verify_fun, Opts, undefined), + CaCerts = handle_option(cacerts, Opts, undefined), - {Verify, FailIfNoPeerCert, CaCertDefault} = + {Verify, FailIfNoPeerCert, CaCertDefault, VerifyFun} = %% Handle 0, 1, 2 for backwards compatibility case proplists:get_value(verify, Opts, verify_none) of 0 -> - {verify_none, false, ca_cert_default(verify_none, Role)}; + {verify_none, false, + ca_cert_default(verify_none, VerifyNoneFun, CaCerts), VerifyNoneFun}; 1 -> - {verify_peer, false, ca_cert_default(verify_peer, Role)}; + {verify_peer, false, + ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun}; 2 -> - {verify_peer, true, ca_cert_default(verify_peer, Role)}; + {verify_peer, true, + ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun}; verify_none -> - {verify_none, false, ca_cert_default(verify_none, Role)}; + {verify_none, false, + ca_cert_default(verify_none, VerifyNoneFun, CaCerts), VerifyNoneFun}; verify_peer -> - {verify_peer, UserFailIfNoPeerCert, ca_cert_default(verify_peer, Role)}; + {verify_peer, UserFailIfNoPeerCert, + ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun}; Value -> throw({error, {eoptions, {verify, Value}}}) - end, + end, CertFile = handle_option(certfile, Opts, ""), SSLOptions = #ssl_options{ versions = handle_option(versions, Opts, []), verify = validate_option(verify, Verify), - verify_fun = handle_option(verify_fun, Opts, VerifyFun), + verify_fun = VerifyFun, fail_if_no_peer_cert = FailIfNoPeerCert, verify_client_once = handle_option(verify_client_once, Opts, false), - validate_extensions_fun = handle_option(validate_extensions_fun, Opts, undefined), depth = handle_option(depth, Opts, 1), + cert = handle_option(cert, Opts, undefined), certfile = CertFile, - keyfile = handle_option(keyfile, Opts, CertFile), key = handle_option(key, Opts, undefined), + keyfile = handle_option(keyfile, Opts, CertFile), password = handle_option(password, Opts, ""), + cacerts = CaCerts, cacertfile = handle_option(cacertfile, Opts, CaCertDefault), + dh = handle_option(dh, Opts, undefined), dhfile = handle_option(dhfile, Opts, undefined), ciphers = handle_option(ciphers, Opts, []), %% Server side option @@ -584,10 +592,10 @@ handle_options(Opts0, Role) -> }, CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}), - SslOptions = [versions, verify, verify_fun, validate_extensions_fun, + SslOptions = [versions, verify, verify_fun, fail_if_no_peer_cert, verify_client_once, - depth, certfile, keyfile, - key, password, cacertfile, dhfile, ciphers, + depth, cert, certfile, key, keyfile, + password, cacerts, cacertfile, dh, dhfile, ciphers, debug, reuse_session, reuse_sessions, ssl_imp, cb_info, renegotiate_at, secure_renegotiate], @@ -611,7 +619,21 @@ validate_option(ssl_imp, Value) when Value == new; Value == old -> validate_option(verify, Value) when Value == verify_none; Value == verify_peer -> Value; -validate_option(verify_fun, Value) when is_function(Value) -> +validate_option(verify_fun, undefined) -> + undefined; +%% Backwards compatibility +validate_option(verify_fun, Fun) when is_function(Fun) -> + {fun(_,{bad_cert, _} = Reason, OldFun) -> + case OldFun([Reason]) of + true -> + {valid, OldFun}; + false -> + {fail, Reason} + end; + (_,{extension, _}, UserState) -> + {unknown, UserState} + end, Fun}; +validate_option(verify_fun, {Fun, _} = Value) when is_function(Fun) -> Value; validate_option(fail_if_no_peer_cert, Value) when Value == true; Value == false -> @@ -619,29 +641,38 @@ validate_option(fail_if_no_peer_cert, Value) validate_option(verify_client_once, Value) when Value == true; Value == false -> Value; - -validate_option(validate_extensions_fun, Value) when Value == undefined; is_function(Value) -> - Value; validate_option(depth, Value) when is_integer(Value), Value >= 0, Value =< 255-> Value; +validate_option(cert, Value) when Value == undefined; + is_binary(Value) -> + Value; validate_option(certfile, Value) when is_list(Value) -> Value; + +validate_option(key, undefined) -> + undefined; +validate_option(key, {KeyType, Value}) when is_binary(Value), + KeyType == rsa; + KeyType == dsa -> + {KeyType, Value}; validate_option(keyfile, Value) when is_list(Value) -> Value; -validate_option(key, Value) when Value == undefined; - is_tuple(Value) -> - %% element(1, Value)=='RSAPrivateKey' -> - Value; validate_option(password, Value) when is_list(Value) -> Value; +validate_option(cacerts, Value) when Value == undefined; + is_list(Value) -> + Value; %% certfile must be present in some cases otherwhise it can be set %% to the empty string. validate_option(cacertfile, undefined) -> ""; validate_option(cacertfile, Value) when is_list(Value), Value =/= "" -> Value; +validate_option(dh, Value) when Value == undefined; + is_binary(Value) -> + Value; validate_option(dhfile, undefined = Value) -> Value; validate_option(dhfile, Value) when is_list(Value), Value =/= "" -> @@ -699,14 +730,16 @@ validate_inet_option(active, Value) validate_inet_option(_, _) -> ok. -ca_cert_default(verify_none, _) -> +%% The option cacerts overrides cacertsfile +ca_cert_default(_,_, [_|_]) -> + undefined; +ca_cert_default(verify_none, _, _) -> undefined; -%% Client may leave verification up to the user -ca_cert_default(verify_peer, client) -> +ca_cert_default(verify_peer, {Fun,_}, _) when is_function(Fun) -> undefined; -%% Server that wants to verify_peer must have +%% Server that wants to verify_peer and has no verify_fun must have %% some trusted certs. -ca_cert_default(verify_peer, server) -> +ca_cert_default(verify_peer, undefined, _) -> "". emulated_options() -> diff --git a/lib/ssl/src/ssl_app.erl b/lib/ssl/src/ssl_app.erl index d9a354086d..8d50fd7bdb 100644 --- a/lib/ssl/src/ssl_app.erl +++ b/lib/ssl/src/ssl_app.erl @@ -29,14 +29,14 @@ %%-------------------------------------------------------------------- -spec start(normal | {takeover, node()} | {failover, node()}, list()) -> - {ok, pid()} | {ok, pid(), term()} | {error, term()}. + ignore | {ok, pid()} | {error, term()}. %%-------------------------------------------------------------------- start(_Type, _StartArgs) -> ssl_sup:start_link(). %-------------------------------------------------------------------- -spec stop(term())-> ok. -%%-------------------------------------------------------------------- +%%-------------------------------------------------------------------- stop(_State) -> ok. diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl index 8a79f75725..6cf57ced81 100644 --- a/lib/ssl/src/ssl_certificate.erl +++ b/lib/ssl/src/ssl_certificate.erl @@ -31,10 +31,11 @@ -include("ssl_debug.hrl"). -include_lib("public_key/include/public_key.hrl"). --export([trusted_cert_and_path/3, +-export([trusted_cert_and_path/2, certificate_chain/2, file_to_certificats/1, - validate_extensions/6, + %validate_extensions/6, + validate_extension/3, is_valid_extkey_usage/2, is_valid_key_usage/2, select_extension/2, @@ -47,61 +48,59 @@ %%==================================================================== %%-------------------------------------------------------------------- --spec trusted_cert_and_path([der_cert()], certdb_ref(), boolean()) -> - {der_cert(), [der_cert()], list()}. +-spec trusted_cert_and_path([der_cert()], certdb_ref()) -> + {der_cert() | unknown_ca, [der_cert()]}. %% %% Description: Extracts the root cert (if not presents tries to %% look it up, if not found {bad_cert, unknown_ca} will be added verification %% errors. Returns {RootCert, Path, VerifyErrors} %%-------------------------------------------------------------------- -trusted_cert_and_path(CertChain, CertDbRef, Verify) -> - [Cert | RestPath] = lists:reverse(CertChain), - {ok, OtpCert} = public_key:pkix_decode_cert(Cert, otp), - IssuerAnPath = +trusted_cert_and_path(CertChain, CertDbRef) -> + Path = [Cert | _] = lists:reverse(CertChain), + OtpCert = public_key:pkix_decode_cert(Cert, otp), + IssuerID = case public_key:pkix_is_self_signed(OtpCert) of true -> {ok, IssuerId} = public_key:pkix_issuer_id(OtpCert, self), - {IssuerId, RestPath}; - false -> + IssuerId; + false -> case public_key:pkix_issuer_id(OtpCert, other) of {ok, IssuerId} -> - {IssuerId, [Cert | RestPath]}; + IssuerId; {error, issuer_not_found} -> case find_issuer(OtpCert, no_candidate) of {ok, IssuerId} -> - {IssuerId, [Cert | RestPath]}; + IssuerId; Other -> - {Other, RestPath} + Other end end end, - case IssuerAnPath of - {{error, issuer_not_found}, _ } -> - %% The root CA was not sent and can not be found, we fail if verify = true - not_valid(?ALERT_REC(?FATAL, ?UNKNOWN_CA), Verify, {Cert, RestPath}); - {{SerialNr, Issuer}, Path} -> - case ssl_manager:lookup_trusted_cert(CertDbRef, - SerialNr, Issuer) of + case IssuerID of + {error, issuer_not_found} -> + %% The root CA was not sent and can not be found. + {unknown_ca, Path}; + {SerialNr, Issuer} -> + case ssl_manager:lookup_trusted_cert(CertDbRef, SerialNr, Issuer) of {ok, {BinCert,_}} -> - {BinCert, Path, []}; + {BinCert, Path}; _ -> - %% Fail if verify = true - not_valid(?ALERT_REC(?FATAL, ?UNKNOWN_CA), - Verify, {Cert, RestPath}) + %% Root CA could not be verified + {unknown_ca, Path} end end. %%-------------------------------------------------------------------- -spec certificate_chain(undefined | binary(), certdb_ref()) -> - {error, no_cert} | [der_cert()]. + {error, no_cert} | {ok, [der_cert()]}. %% %% Description: Return the certificate chain to send to peer. %%-------------------------------------------------------------------- certificate_chain(undefined, _CertsDbRef) -> {error, no_cert}; certificate_chain(OwnCert, CertsDbRef) -> - {ok, ErlCert} = public_key:pkix_decode_cert(OwnCert, otp), + ErlCert = public_key:pkix_decode_cert(OwnCert, otp), certificate_chain(ErlCert, OwnCert, CertsDbRef, [OwnCert]). %%-------------------------------------------------------------------- -spec file_to_certificats(string()) -> [der_cert()]. @@ -110,34 +109,27 @@ certificate_chain(OwnCert, CertsDbRef) -> %%-------------------------------------------------------------------- file_to_certificats(File) -> {ok, List} = ssl_manager:cache_pem_file(File), - [Bin || {cert, Bin, not_encrypted} <- List]. + [Bin || {'Certificate', Bin, not_encrypted} <- List]. %%-------------------------------------------------------------------- --spec validate_extensions([#'Extension'{}], term(), [#'Extension'{}], - boolean(), list(), client | server) -> {[#'Extension'{}], term(), list()}. +-spec validate_extension(term(), #'Extension'{}, term()) -> {valid, term()} | + {fail, tuple()} | + {unknown, term()}. %% %% Description: Validates ssl/tls specific extensions %%-------------------------------------------------------------------- -validate_extensions([], ValidationState, UnknownExtensions, _, AccErr, _) -> - {UnknownExtensions, ValidationState, AccErr}; - -validate_extensions([#'Extension'{extnID = ?'id-ce-extKeyUsage', - extnValue = KeyUse, - critical = true} | Rest], - ValidationState, UnknownExtensions, Verify, AccErr0, Role) -> +validate_extension(_,{extension, #'Extension'{extnID = ?'id-ce-extKeyUsage', + extnValue = KeyUse, + critical = true}}, Role) -> case is_valid_extkey_usage(KeyUse, Role) of true -> - validate_extensions(Rest, ValidationState, UnknownExtensions, - Verify, AccErr0, Role); + {valid, Role}; false -> - AccErr = - not_valid_extension({bad_cert, invalid_ext_key_usage}, Verify, AccErr0), - validate_extensions(Rest, ValidationState, UnknownExtensions, Verify, AccErr, Role) + {fail, {bad_cert, invalid_ext_key_usage}} end; - -validate_extensions([Extension | Rest], ValidationState, UnknownExtensions, - Verify, AccErr, Role) -> - validate_extensions(Rest, ValidationState, [Extension | UnknownExtensions], - Verify, AccErr, Role). +validate_extension(_, {bad_cert, _} = Reason, _) -> + {fail, Reason}; +validate_extension(_, _, Role) -> + {unknown, Role}. %%-------------------------------------------------------------------- -spec is_valid_key_usage(list(), term()) -> boolean(). @@ -219,7 +211,7 @@ certificate_chain(CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) -> case ssl_manager:lookup_trusted_cert(CertsDbRef, SerialNr, Issuer) of {ok, {IssuerCert, ErlCert}} -> - {ok, ErlCert} = public_key:pkix_decode_cert(IssuerCert, otp), + ErlCert = public_key:pkix_decode_cert(IssuerCert, otp), certificate_chain(ErlCert, IssuerCert, CertsDbRef, [IssuerCert | Chain]); _ -> @@ -244,19 +236,9 @@ find_issuer(OtpCert, PrevCandidateKey) -> end end. -not_valid(Alert, true, _) -> - throw(Alert); -not_valid(_, false, {ErlCert, Path}) -> - {ErlCert, Path, [{bad_cert, unknown_ca}]}. - is_valid_extkey_usage(KeyUse, client) -> %% Client wants to verify server is_valid_key_usage(KeyUse,?'id-kp-serverAuth'); is_valid_extkey_usage(KeyUse, server) -> %% Server wants to verify client is_valid_key_usage(KeyUse, ?'id-kp-clientAuth'). - -not_valid_extension(Error, true, _) -> - throw(Error); -not_valid_extension(Error, false, AccErrors) -> - [Error | AccErrors]. diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl index e953821057..86477f369d 100644 --- a/lib/ssl/src/ssl_certificate_db.erl +++ b/lib/ssl/src/ssl_certificate_db.erl @@ -54,10 +54,9 @@ remove(Dbs) -> lists:foreach(fun(Db) -> true = ets:delete(Db) end, Dbs). %%-------------------------------------------------------------------- --spec lookup_trusted_cert(reference(), serialnumber(), issuer()) -> {der_cert(), #'OTPCertificate'{}}. +-spec lookup_trusted_cert(reference(), serialnumber(), issuer()) -> + undefined | {ok, {der_cert(), #'OTPCertificate'{}}}. -%% SerialNumber = integer() -%% Issuer = {rdnSequence, IssuerAttrs} %% %% Description: Retrives the trusted certificate identified by %% <SerialNumber, Issuer>. Ref is used as it is specified @@ -75,12 +74,16 @@ lookup_cached_certs(File) -> ets:lookup(certificate_db_name(), {file, File}). %%-------------------------------------------------------------------- --spec add_trusted_certs(pid(), string(), certdb_ref()) -> {ok, certdb_ref()}. +-spec add_trusted_certs(pid(), string() | {der, list()}, certdb_ref()) -> {ok, certdb_ref()}. %% %% Description: Adds the trusted certificates from file <File> to the %% runtime database. Returns Ref that should be handed to lookup_trusted_cert %% together with the cert serialnumber and issuer. %%-------------------------------------------------------------------- +add_trusted_certs(_Pid, {der, DerList}, [CerDb, _,_]) -> + NewRef = make_ref(), + add_certs_from_der(DerList, NewRef, CerDb), + {ok, NewRef}; add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) -> Ref = case lookup(File, FileToRefDb) of undefined -> @@ -94,17 +97,17 @@ add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) -> end, insert(Pid, File, PidToFileDb), {ok, Ref}. - %%-------------------------------------------------------------------- -spec cache_pem_file(pid(), string(), certdb_ref()) -> term(). %% %% Description: Cache file as binary in DB %%-------------------------------------------------------------------- cache_pem_file(Pid, File, [CertsDb, _FileToRefDb, PidToFileDb]) -> - Res = {ok, Content} = public_key:pem_to_der(File), + {ok, PemBin} = file:read_file(File), + Content = public_key:pem_decode(PemBin), insert({file, File}, Content, CertsDb), insert(Pid, File, PidToFileDb), - Res. + {ok, Content}. %%-------------------------------------------------------------------- -spec remove_trusted_certs(pid(), certdb_ref()) -> term(). @@ -138,13 +141,13 @@ remove_trusted_certs(Pid, [CertsDb, FileToRefDb, PidToFileDb]) -> end. %%-------------------------------------------------------------------- --spec issuer_candidate(no_candidate | cert_key()) -> - {cert_key(), der_cert()} | no_more_candidates. +-spec issuer_candidate(no_candidate | cert_key() | {file, term()}) -> + {cert_key(),{der_cert(), #'OTPCertificate'{}}} | no_more_candidates. %% %% Description: If a certificat does not define its issuer through %% the extension 'ce-authorityKeyIdentifier' we can %% try to find the issuer in the database over known -%% certificates. +%% certificates. %%-------------------------------------------------------------------- issuer_candidate(no_candidate) -> Db = certificate_db_name(), @@ -202,15 +205,20 @@ lookup(Key, Db) -> remove_certs(Ref, CertsDb) -> ets:match_delete(CertsDb, {{Ref, '_', '_'}, '_'}). +add_certs_from_der(DerList, Ref, CertsDb) -> + Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end, + [Add(Cert) || Cert <- DerList]. + add_certs_from_file(File, Ref, CertsDb) -> - Decode = fun(Cert) -> - {ok, ErlCert} = public_key:pkix_decode_cert(Cert, otp), - TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate, - SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber, - Issuer = public_key:pkix_normalize_general_name( - TBSCertificate#'OTPTBSCertificate'.issuer), - insert({Ref, SerialNumber, Issuer}, {Cert,ErlCert}, CertsDb) - end, - {ok,Der} = public_key:pem_to_der(File), - [Decode(Cert) || {cert, Cert, not_encrypted} <- Der]. + Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end, + {ok, PemBin} = file:read_file(File), + PemEntries = public_key:pem_decode(PemBin), + [Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries]. +add_certs(Cert, Ref, CertsDb) -> + ErlCert = public_key:pkix_decode_cert(Cert, otp), + TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate, + SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber, + Issuer = public_key:pkix_normalize_name( + TBSCertificate#'OTPTBSCertificate'.issuer), + insert({Ref, SerialNumber, Issuer}, {Cert,ErlCert}, CertsDb). diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index a6e80047c2..8230149304 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -40,7 +40,7 @@ -compile(inline). %%-------------------------------------------------------------------- --spec security_parameters(erl_cipher_suite(), #security_parameters{}) -> +-spec security_parameters(cipher_suite(), #security_parameters{}) -> #security_parameters{}. %% %% Description: Returns a security parameters record where the @@ -119,7 +119,7 @@ block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0, %%-------------------------------------------------------------------- -spec decipher(cipher_enum(), integer(), #cipher_state{}, binary(), tls_version()) -> - {binary(), #cipher_state{}}. + {binary(), binary(), #cipher_state{}} | #alert{}. %% %% Description: Decrypts the data and the MAC using cipher described %% by cipher_enum() and updating the cipher state. @@ -370,7 +370,7 @@ openssl_suite_name(Cipher) -> filter(undefined, Ciphers) -> Ciphers; filter(DerCert, Ciphers) -> - {ok, OtpCert} = public_key:pkix_decode_cert(DerCert, otp), + OtpCert = public_key:pkix_decode_cert(DerCert, otp), SigAlg = OtpCert#'OTPCertificate'.signatureAlgorithm, case ssl_certificate:signature_type(SigAlg#'SignatureAlgorithm'.algorithm) of rsa -> @@ -506,6 +506,12 @@ generic_stream_cipher_from_bin(T, HashSz) -> is_correct_padding(_, {3, 0}) -> true; +%% For interoperability reasons we do not check the padding in TLS 1.0 as it +%% is not strictly required and breaks interopability with for instance +%% Google. +is_correct_padding(_, {3, 1}) -> + true; +%% Padding must be check in TLS 1.1 and after is_correct_padding(#generic_block_cipher{padding_length = Len, padding = Padding}, _) -> list_to_binary(lists:duplicate(Len, Len)) == Padding. diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl index 19de709d9c..8bd68cc190 100644 --- a/lib/ssl/src/ssl_cipher.hrl +++ b/lib/ssl/src/ssl_cipher.hrl @@ -28,7 +28,7 @@ -type cipher() :: null |rc4_128 | idea_cbc | des40_cbc | des_cbc | '3des_ede_cbc' | aes_128_cbc | aes_256_cbc. --type hash() :: sha | md5. +-type hash() :: null | sha | md5. -type erl_cipher_suite() :: {key_algo(), cipher(), hash()}. -type cipher_suite() :: binary(). -type cipher_enum() :: integer(). diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 5b4b129e30..c94199c336 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -125,8 +125,9 @@ send(Pid, Data) -> recv(Pid, Length, Timeout) -> sync_send_all_state_event(Pid, {recv, Length}, Timeout). %%-------------------------------------------------------------------- --spec connect(host(), port_num(), port(), list(), pid(), tuple(), timeout()) -> - {ok, #sslsocket{}} | {error, reason()}. +-spec connect(host(), port_num(), port(), {#ssl_options{}, #socket_options{}}, + pid(), tuple(), timeout()) -> + {ok, #sslsocket{}} | {error, reason()}. %% %% Description: Connect to a ssl server. %%-------------------------------------------------------------------- @@ -138,7 +139,8 @@ connect(Host, Port, Socket, Options, User, CbInfo, Timeout) -> {error, ssl_not_started} end. %%-------------------------------------------------------------------- --spec ssl_accept(port_num(), port(), list(), pid(), tuple(), timeout()) -> +-spec ssl_accept(port_num(), port(), {#ssl_options{}, #socket_options{}}, + pid(), tuple(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% %% Description: Performs accept on a ssl listen socket. e.i. performs @@ -253,7 +255,7 @@ session_info(ConnectionPid) -> sync_send_all_state_event(ConnectionPid, session_info). %%-------------------------------------------------------------------- --spec peer_certificate(pid()) -> {ok, binary()} | {error, reason()}. +-spec peer_certificate(pid()) -> {ok, binary()| undefined} | {error, reason()}. %% %% Description: Returns the peer cert %%-------------------------------------------------------------------- @@ -288,9 +290,10 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) -> %% gen_fsm callbacks %%==================================================================== %%-------------------------------------------------------------------- --spec init(list()) -> {ok, state_name(), #state{}} - | {ok, state_name(), #state{}, timeout()} | - ignore | {stop, term()}. +-spec init(list()) -> {ok, state_name(), #state{}} | {stop, term()}. +%% Possible return values not used now. +%% | {ok, state_name(), #state{}, timeout()} | +%% ignore %% Description:Whenever a gen_fsm is started using gen_fsm:start/[3,4] or %% gen_fsm:start_link/3,4, this function is called by the new process to %% initialize. @@ -331,14 +334,12 @@ hello(start, #state{host = Host, port = Port, role = client, ssl_options = SslOpts, transport_cb = Transport, socket = Socket, connection_states = ConnectionStates, - own_cert = Cert, renegotiation = {Renegotiation, _}} = State0) -> Hello = ssl_handshake:client_hello(Host, Port, ConnectionStates, - SslOpts, Cert, - Renegotiation), + SslOpts, Renegotiation), Version = Hello#client_hello.client_version, Hashes0 = ssl_handshake:init_hashes(), @@ -350,7 +351,7 @@ hello(start, #state{host = Host, port = Port, role = client, session = #session{session_id = Hello#client_hello.session_id, is_resumable = false}, - tls_handshake_hashes = Hashes1}, + tls_handshake_hashes = Hashes1}, {Record, State} = next_record(State1), next_state(hello, Record, State); @@ -499,8 +500,7 @@ certify(#certificate{} = Cert, ssl_options = Opts} = State) -> case ssl_handshake:certify(Cert, CertDbRef, Opts#ssl_options.depth, Opts#ssl_options.verify, - Opts#ssl_options.verify_fun, - Opts#ssl_options.validate_extensions_fun, Role) of + Opts#ssl_options.verify_fun, Role) of {PeerCert, PublicKeyInfo} -> handle_peer_cert(PeerCert, PublicKeyInfo, State#state{client_certificate_requested = false}); @@ -576,58 +576,61 @@ certify(#client_key_exchange{} = Msg, %% We expect a certificate here handle_unexpected_message(Msg, certify_client_key_exchange, State); -certify(#client_key_exchange{exchange_keys - = #encrypted_premaster_secret{premaster_secret - = EncPMS}}, - #state{negotiated_version = Version, - connection_states = ConnectionStates0, - session = Session0, - private_key = Key} = State0) -> - try ssl_handshake:decrypt_premaster_secret(EncPMS, Key) of - PremasterSecret -> - case ssl_handshake:master_secret(Version, PremasterSecret, - ConnectionStates0, server) of - {MasterSecret, ConnectionStates} -> - Session = Session0#session{master_secret = MasterSecret}, - State1 = State0#state{connection_states = ConnectionStates, - session = Session}, - {Record, State} = next_record(State1), - next_state(cipher, Record, State); - #alert{} = Alert -> - handle_own_alert(Alert, Version, - certify_client_key_exchange, State0), - {stop, normal, State0} - end +certify(#client_key_exchange{exchange_keys = Keys}, + State = #state{key_algorithm = KeyAlg, negotiated_version = Version}) -> + try + certify_client_key_exchange(ssl_handshake:decode_client_key(Keys, KeyAlg, Version), State) catch #alert{} = Alert -> - handle_own_alert(Alert, Version, certify_client_key_exchange, - State0), + handle_own_alert(Alert, Version, certify_client_key_exchange, State), + {stop, normal, State} + end; + +certify(Msg, State) -> + handle_unexpected_message(Msg, certify, State). + +certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS}, + #state{negotiated_version = Version, + connection_states = ConnectionStates0, + session = Session0, + private_key = Key} = State0) -> + PremasterSecret = ssl_handshake:decrypt_premaster_secret(EncPMS, Key), + case ssl_handshake:master_secret(Version, PremasterSecret, + ConnectionStates0, server) of + {MasterSecret, ConnectionStates} -> + Session = Session0#session{master_secret = MasterSecret}, + State1 = State0#state{connection_states = ConnectionStates, + session = Session}, + {Record, State} = next_record(State1), + next_state(cipher, Record, State); + #alert{} = Alert -> + handle_own_alert(Alert, Version, + certify_client_key_exchange, State0), {stop, normal, State0} end; -certify(#client_key_exchange{exchange_keys = #client_diffie_hellman_public{ - dh_public = ClientPublicDhKey}}, - #state{negotiated_version = Version, - diffie_hellman_params = #'DHParameter'{prime = P, - base = G}, - diffie_hellman_keys = {_, ServerDhPrivateKey}, - role = Role, - session = Session, - connection_states = ConnectionStates0} = State0) -> - +certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey}, + #state{negotiated_version = Version, + diffie_hellman_params = #'DHParameter'{prime = P, + base = G}, + diffie_hellman_keys = {_, ServerDhPrivateKey}, + role = Role, + session = Session, + connection_states = ConnectionStates0} = State0) -> + PMpint = crypto:mpint(P), GMpint = crypto:mpint(G), PremasterSecret = crypto:dh_compute_key(mpint_binary(ClientPublicDhKey), ServerDhPrivateKey, [PMpint, GMpint]), - + case ssl_handshake:master_secret(Version, PremasterSecret, ConnectionStates0, Role) of {MasterSecret, ConnectionStates} -> State1 = State0#state{session = - Session#session{master_secret - = MasterSecret}, - connection_states = ConnectionStates}, + Session#session{master_secret + = MasterSecret}, + connection_states = ConnectionStates}, {Record, State} = next_record(State1), next_state(cipher, Record, State); @@ -635,10 +638,7 @@ certify(#client_key_exchange{exchange_keys = #client_diffie_hellman_public{ handle_own_alert(Alert, Version, certify_client_key_exchange, State0), {stop, normal, State0} - end; - -certify(Msg, State) -> - handle_unexpected_message(Msg, certify, State). + end. %%-------------------------------------------------------------------- -spec cipher(#hello_request{} | #certificate_verify{} | #finished{} | term(), @@ -698,14 +698,13 @@ connection(#hello_request{}, #state{host = Host, port = Port, socket = Socket, ssl_options = SslOpts, negotiated_version = Version, - own_cert = Cert, transport_cb = Transport, connection_states = ConnectionStates0, renegotiation = {Renegotiation, _}, tls_handshake_hashes = Hashes0} = State0) -> - Hello = ssl_handshake:client_hello(Host, Port, - ConnectionStates0, SslOpts, Cert, Renegotiation), + Hello = ssl_handshake:client_hello(Host, Port, ConnectionStates0, + SslOpts, Renegotiation), {BinMsg, ConnectionStates1, Hashes1} = encode_handshake(Hello, Version, ConnectionStates0, Hashes0), @@ -720,7 +719,9 @@ connection(#client_hello{} = Hello, #state{role = server} = State) -> connection(Msg, State) -> handle_unexpected_message(Msg, connection, State). %%-------------------------------------------------------------------- --spec handle_event(term(), state_name(), #state{}) -> gen_fsm_state_return(). +-spec handle_event(term(), state_name(), #state{}) -> term(). +%% As it is not currently used gen_fsm_state_return() makes +%% dialyzer unhappy! %% %% Description: Whenever a gen_fsm receives an event sent using %% gen_fsm:send_all_state_event/2, this function is called to handle @@ -1033,29 +1034,40 @@ ssl_init(SslOpts, Role) -> PrivateKey = init_private_key(SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile, SslOpts#ssl_options.password, Role), - DHParams = init_diffie_hellman(SslOpts#ssl_options.dhfile, Role), + DHParams = init_diffie_hellman(SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role), {ok, CertDbRef, CacheRef, OwnCert, PrivateKey, DHParams}. -init_certificates(#ssl_options{cacertfile = CACertFile, - certfile = CertFile}, Role) -> - case ssl_manager:connection_init(CACertFile, Role) of - {ok, CertDbRef, CacheRef} -> - init_certificates(CertDbRef, CacheRef, CertFile, Role); - {error, Reason} -> - handle_file_error(?LINE, error, Reason, CACertFile, ecacertfile, - erlang:get_stacktrace()) - end. +init_certificates(#ssl_options{cacerts = CaCerts, + cacertfile = CACertFile, + certfile = CertFile, + cert = Cert}, Role) -> + {ok, CertDbRef, CacheRef} = + try + Certs = case CaCerts of + undefined -> + CACertFile; + _ -> + {der, CaCerts} + end, + {ok, _, _} = ssl_manager:connection_init(Certs, Role) + catch + Error:Reason -> + handle_file_error(?LINE, Error, Reason, CACertFile, ecacertfile, + erlang:get_stacktrace()) + end, + init_certificates(Cert, CertDbRef, CacheRef, CertFile, Role). + -init_certificates(CertDbRef, CacheRef, CertFile, client) -> +init_certificates(undefined, CertDbRef, CacheRef, CertFile, client) -> try [OwnCert] = ssl_certificate:file_to_certificats(CertFile), {ok, CertDbRef, CacheRef, OwnCert} - catch _E:_R -> + catch _Error:_Reason -> {ok, CertDbRef, CacheRef, undefined} end; -init_certificates(CertDbRef, CacheRef, CertFile, server) -> +init_certificates(undefined, CertDbRef, CacheRef, CertFile, server) -> try [OwnCert] = ssl_certificate:file_to_certificats(CertFile), {ok, CertDbRef, CacheRef, OwnCert} @@ -1063,53 +1075,61 @@ init_certificates(CertDbRef, CacheRef, CertFile, server) -> Error:Reason -> handle_file_error(?LINE, Error, Reason, CertFile, ecertfile, erlang:get_stacktrace()) - end. + end; +init_certificates(Cert, CertDbRef, CacheRef, _, _) -> + {ok, CertDbRef, CacheRef, Cert}. init_private_key(undefined, "", _Password, client) -> undefined; init_private_key(undefined, KeyFile, Password, _) -> - case ssl_manager:cache_pem_file(KeyFile) of - {ok, List} -> - [Der] = [Der || Der = {PKey, _ , _} <- List, - PKey =:= rsa_private_key orelse - PKey =:= dsa_private_key], - {ok, Decoded} = public_key:decode_private_key(Der,Password), - Decoded; - {error, Reason} -> - handle_file_error(?LINE, error, Reason, KeyFile, ekeyfile, + try + {ok, List} = ssl_manager:cache_pem_file(KeyFile), + [PemEntry] = [PemEntry || PemEntry = {PKey, _ , _} <- List, + PKey =:= 'RSAPrivateKey' orelse + PKey =:= 'DSAPrivateKey'], + public_key:pem_entry_decode(PemEntry, Password) + catch + Error:Reason -> + handle_file_error(?LINE, Error, Reason, KeyFile, ekeyfile, erlang:get_stacktrace()) end; -init_private_key(PrivateKey, _, _,_) -> - PrivateKey. +init_private_key({rsa, PrivateKey}, _, _,_) -> + public_key:der_decode('RSAPrivateKey', PrivateKey); +init_private_key({dsa, PrivateKey},_,_,_) -> + public_key:der_decode('DSAPrivateKey', PrivateKey). handle_file_error(Line, Error, {badmatch, Reason}, File, Throw, Stack) -> file_error(Line, Error, Reason, File, Throw, Stack); handle_file_error(Line, Error, Reason, File, Throw, Stack) -> file_error(Line, Error, Reason, File, Throw, Stack). +-spec(file_error/6 :: (_,_,_,_,_,_) -> no_return()). file_error(Line, Error, Reason, File, Throw, Stack) -> Report = io_lib:format("SSL: ~p: ~p:~p ~s~n ~p~n", [Line, Error, Reason, File, Stack]), error_logger:error_report(Report), throw(Throw). -init_diffie_hellman(_, client) -> +init_diffie_hellman(Params, _,_) when is_binary(Params)-> + public_key:der_decode('DHParameter', Params); +init_diffie_hellman(_,_, client) -> undefined; -init_diffie_hellman(undefined, _) -> +init_diffie_hellman(_,undefined, _) -> ?DEFAULT_DIFFIE_HELLMAN_PARAMS; -init_diffie_hellman(DHParamFile, server) -> - case ssl_manager:cache_pem_file(DHParamFile) of - {ok, List} -> - case [Der || Der = {dh_params, _ , _} <- List] of - [Der] -> - {ok, Decoded} = public_key:decode_dhparams(Der), - Decoded; - [] -> - ?DEFAULT_DIFFIE_HELLMAN_PARAMS - end; - {error, Reason} -> - handle_file_error(?LINE, error, Reason, DHParamFile, edhfile, erlang:get_stacktrace()) +init_diffie_hellman(_, DHParamFile, server) -> + try + {ok, List} = ssl_manager:cache_pem_file(DHParamFile), + case [Entry || Entry = {'DHParameter', _ , _} <- List] of + [Entry] -> + public_key:pem_entry_decode(Entry); + [] -> + ?DEFAULT_DIFFIE_HELLMAN_PARAMS + end + catch + Error:Reason -> + handle_file_error(?LINE, Error, Reason, + DHParamFile, edhfile, erlang:get_stacktrace()) end. sync_send_all_state_event(FsmPid, Event) -> @@ -1178,7 +1198,7 @@ verify_client_cert(#state{client_certificate_requested = true, role = client, tls_handshake_hashes = Hashes1}; ignore -> State; - #alert{} = Alert -> + #alert{} = Alert -> handle_own_alert(Alert, Version, certify, State) end; @@ -1186,18 +1206,19 @@ verify_client_cert(#state{client_certificate_requested = false} = State) -> State. do_server_hello(Type, #state{negotiated_version = Version, - session = Session, + session = #session{session_id = SessId} = Session, connection_states = ConnectionStates0, renegotiation = {Renegotiation, _}} = State0) when is_atom(Type) -> + ServerHello = - ssl_handshake:server_hello(Session#session.session_id, Version, + ssl_handshake:server_hello(SessId, Version, ConnectionStates0, Renegotiation), State1 = server_hello(ServerHello, State0), case Type of new -> - do_server_hello(ServerHello, State1); + new_server_hello(ServerHello, State1); resumed -> ConnectionStates1 = State1#state.connection_states, case ssl_handshake:master_secret(Version, Session, @@ -1216,9 +1237,9 @@ do_server_hello(Type, #state{negotiated_version = Version, handle_own_alert(Alert, Version, hello, State1), {stop, normal, State1} end - end; + end. -do_server_hello(#server_hello{cipher_suite = CipherSuite, +new_server_hello(#server_hello{cipher_suite = CipherSuite, compression_method = Compression, session_id = SessionId}, #state{session = Session0, @@ -1343,7 +1364,7 @@ certify_server(#state{transport_cb = Transport, key_exchange(#state{role = server, key_algorithm = rsa} = State) -> State; key_exchange(#state{role = server, key_algorithm = Algo, - diffie_hellman_params = Params, + diffie_hellman_params = #'DHParameter'{prime = P, base = G} = Params, private_key = PrivateKey, connection_states = ConnectionStates0, negotiated_version = Version, @@ -1354,7 +1375,7 @@ key_exchange(#state{role = server, key_algorithm = Algo, when Algo == dhe_dss; Algo == dhe_rsa -> - Keys = public_key:gen_key(Params), + Keys = crypto:dh_generate_key([crypto:mpint(P), crypto:mpint(G)]), ConnectionState = ssl_record:pending_connection_state(ConnectionStates0, read), SecParams = ConnectionState#connection_state.security_parameters, @@ -1406,6 +1427,8 @@ key_exchange(#state{role = client, State#state{connection_states = ConnectionStates1, tls_handshake_hashes = Hashes1}. +-spec(rsa_key_exchange/2 :: (_,_) -> no_return()). + rsa_key_exchange(PremasterSecret, PublicKeyInfo = {Algorithm, _, _}) when Algorithm == ?rsaEncryption; Algorithm == ?md2WithRSAEncryption; @@ -1536,7 +1559,7 @@ verify_dh_params(Signed, Hashes, {?rsaEncryption, PubKey, _PubKeyParams}) -> false end; verify_dh_params(Signed, Hash, {?'id-dsa', PublicKey, PublicKeyParams}) -> - public_key:verify_signature(Hash, none, Signed, PublicKey, PublicKeyParams). + public_key:verify(Hash, none, Signed, {PublicKey, PublicKeyParams}). cipher_role(client, Data, Session, #state{connection_states = ConnectionStates0} = State) -> @@ -1563,7 +1586,7 @@ encode_change_cipher(#change_cipher_spec{}, Version, ConnectionStates) -> ssl_record:encode_change_cipher_spec(Version, ConnectionStates). encode_handshake(HandshakeRec, Version, ConnectionStates, Hashes) -> - encode_handshake(HandshakeRec, undefined, Version, + encode_handshake(HandshakeRec, null, Version, ConnectionStates, Hashes). encode_handshake(HandshakeRec, SigAlg, Version, ConnectionStates0, Hashes0) -> @@ -1626,8 +1649,6 @@ application_data(Data, #state{user_application = {_Mon, Pid}, true -> <<Buffer0/binary, Data/binary>> end, case get_data(SOpts, BytesToRead, Buffer1) of - {ok, <<>>, Buffer} -> % no reply, we need more data - next_record(State0#state{user_data_buffer = Buffer}); {ok, ClientData, Buffer} -> % Send data SocketOpt = deliver_app_data(SOpts, ClientData, Pid, From), State = State0#state{user_data_buffer = Buffer, @@ -1643,12 +1664,16 @@ application_data(Data, #state{user_application = {_Mon, Pid}, true -> %% We have more data application_data(<<>>, State) end; + {more, Buffer} -> % no reply, we need more data + next_record(State0#state{user_data_buffer = Buffer}); {error,_Reason} -> %% Invalid packet in packet mode deliver_packet_error(SOpts, Buffer1, Pid, From), {stop, normal, State0} end. %% Picks ClientData +get_data(_, _, <<>>) -> + {more, <<>>}; get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Buffer) when Raw =:= raw; Raw =:= 0 -> %% Raw Mode if @@ -1661,13 +1686,13 @@ get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Buffer) {ok, Data, Rest}; true -> %% Passive Mode not enough data - {ok, <<>>, Buffer} + {more, Buffer} end; get_data(#socket_options{packet=Type, packet_size=Size}, _, Buffer) -> PacketOpts = [{packet_size, Size}], case decode_packet(Type, Buffer, PacketOpts) of {more, _} -> - {ok, <<>>, Buffer}; + {more, Buffer}; Decoded -> Decoded end. @@ -1726,11 +1751,13 @@ format_packet_error(#socket_options{active = _, mode = Mode}, Data) -> format_reply(binary, _, N, Data) when N > 0 -> % Header mode header(N, Data); -format_reply(binary, _, _, Data) -> Data; -format_reply(list, Packet, _, Data) when is_integer(Packet); Packet == raw -> - binary_to_list(Data); +format_reply(binary, _, _, Data) -> + Data; +format_reply(list, Packet, _, Data) + when Packet == http; Packet == {http, headers}; Packet == http_bin; Packet == {http_bin, headers} -> + Data; format_reply(list, _,_, Data) -> - Data. + binary_to_list(Data). header(0, <<>>) -> <<>>; @@ -1780,9 +1807,7 @@ next_state(Next, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, State) -> handle_alerts(Alerts, {next_state, Next, State}); next_state(StateName, #ssl_tls{type = ?HANDSHAKE, fragment = Data}, - State0 = #state{key_algorithm = KeyAlg, - tls_handshake_buffer = Buf0, - negotiated_version = Version}) -> + State0 = #state{tls_handshake_buffer = Buf0, negotiated_version = Version}) -> Handle = fun({#hello_request{} = Packet, _}, {next_state, connection = SName, State}) -> %% This message should not be included in handshake @@ -1805,7 +1830,7 @@ next_state(StateName, #ssl_tls{type = ?HANDSHAKE, fragment = Data}, (_, StopState) -> StopState end, try - {Packets, Buf} = ssl_handshake:get_tls_handshake(Data,Buf0, KeyAlg,Version), + {Packets, Buf} = ssl_handshake:get_tls_handshake(Data,Buf0), State = State0#state{tls_packets = Packets, tls_handshake_buffer = Buf}, handle_tls_handshake(Handle, StateName, State) catch throw:#alert{} = Alert -> @@ -1817,7 +1842,7 @@ next_state(StateName, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, State case application_data(Data, State0) of Stop = {stop,_,_} -> Stop; - {Record, State} -> + {Record, State} -> next_state(StateName, Record, State) end; next_state(StateName, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = <<1>>} = @@ -2154,7 +2179,7 @@ renegotiate(#state{role = server, negotiated_version = Version, connection_states = ConnectionStates0} = State0) -> HelloRequest = ssl_handshake:hello_request(), - Frag = ssl_handshake:encode_handshake(HelloRequest, Version, undefined), + Frag = ssl_handshake:encode_handshake(HelloRequest, Version, null), Hs0 = ssl_handshake:init_hashes(), {BinMsg, ConnectionStates} = ssl_record:encode_handshake(Frag, Version, ConnectionStates0), diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index fcc30f6137..99bc47f04b 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -31,32 +31,32 @@ -include("ssl_debug.hrl"). -include_lib("public_key/include/public_key.hrl"). --export([master_secret/4, client_hello/6, server_hello/4, hello/4, - hello_request/0, certify/7, certificate/3, - client_certificate_verify/6, - certificate_verify/6, certificate_request/2, - key_exchange/2, server_key_exchange_hash/2, finished/4, - verify_connection/5, - get_tls_handshake/4, - server_hello_done/0, sig_alg/1, - encode_handshake/3, init_hashes/0, - update_hashes/2, decrypt_premaster_secret/2]). - --type tls_handshake() :: #client_hello{} | #server_hello{} | #server_hello_done{} | -#certificate{} | #client_key_exchange{} | #finished{} | #certificate_verify{}. +-export([master_secret/4, client_hello/5, server_hello/4, hello/4, + hello_request/0, certify/6, certificate/3, + client_certificate_verify/6, certificate_verify/6, + certificate_request/2, key_exchange/2, server_key_exchange_hash/2, + finished/4, verify_connection/5, get_tls_handshake/2, + decode_client_key/3, server_hello_done/0, sig_alg/1, + encode_handshake/3, init_hashes/0, update_hashes/2, + decrypt_premaster_secret/2]). + +-type tls_handshake() :: #client_hello{} | #server_hello{} | + #server_hello_done{} | #certificate{} | #certificate_request{} | + #client_key_exchange{} | #finished{} | #certificate_verify{} | + #hello_request{}. %%==================================================================== %% Internal application API %%==================================================================== %%-------------------------------------------------------------------- -spec client_hello(host(), port_num(), #connection_states{}, - #ssl_options{}, binary(), boolean()) -> #client_hello{}. + #ssl_options{}, boolean()) -> #client_hello{}. %% %% Description: Creates a client hello message. %%-------------------------------------------------------------------- client_hello(Host, Port, ConnectionStates, #ssl_options{versions = Versions, ciphers = UserSuites} - = SslOpts, Cert, Renegotiation) -> + = SslOpts, Renegotiation) -> Fun = fun(Version) -> ssl_record:protocol_version(Version) @@ -64,7 +64,7 @@ client_hello(Host, Port, ConnectionStates, #ssl_options{versions = Versions, Version = ssl_record:highest_protocol_version(lists:map(Fun, Versions)), Pending = ssl_record:pending_connection_state(ConnectionStates, read), SecParams = Pending#connection_state.security_parameters, - Ciphers = available_suites(Cert, UserSuites, Version), + Ciphers = available_suites(UserSuites, Version), Id = ssl_manager:client_session_id(Host, Port, SslOpts), @@ -110,7 +110,7 @@ hello_request() -> #connection_states{} | {port_num(), #session{}, cache_ref(), atom(), #connection_states{}, binary()}, boolean()) -> {tls_version(), session_id(), #connection_states{}}| - {tls_version(), {resumed | new, session_id()}, + {tls_version(), {resumed | new, #session{}}, #connection_states{}} | #alert{}. %% %% Description: Handles a recieved hello message @@ -175,64 +175,57 @@ hello(#client_hello{client_version = ClientVersion, random = Random, %%-------------------------------------------------------------------- -spec certify(#certificate{}, term(), integer() | nolimit, - verify_peer | verify_none, fun(), fun(), + verify_peer | verify_none, {fun(), term}, client | server) -> {der_cert(), public_key_info()} | #alert{}. %% %% Description: Handles a certificate handshake message %%-------------------------------------------------------------------- -certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef, - MaxPathLen, Verify, VerifyFun, ValidateFun, Role) -> +certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef, + MaxPathLen, _Verify, VerifyFunAndState, Role) -> [PeerCert | _] = ASN1Certs, - VerifyBool = verify_bool(Verify), - ValidateExtensionFun = - case ValidateFun of + ValidationFunAndState = + case VerifyFunAndState of undefined -> - fun(Extensions, ValidationState, Verify0, AccError) -> - ssl_certificate:validate_extensions(Extensions, ValidationState, - [], Verify0, AccError, Role) - end; - Fun -> - fun(Extensions, ValidationState, Verify0, AccError) -> - {NewExtensions, NewValidationState, NewAccError} - = ssl_certificate:validate_extensions(Extensions, ValidationState, - [], Verify0, AccError, Role), - Fun(NewExtensions, NewValidationState, Verify0, NewAccError) - end + {fun(OtpCert, ExtensionOrError, SslState) -> + ssl_certificate:validate_extension(OtpCert, + ExtensionOrError, SslState) + end, Role}; + {Fun, UserState0} -> + {fun(OtpCert, ExtensionOrError, {SslState, UserState}) -> + case ssl_certificate:validate_extension(OtpCert, + ExtensionOrError, + SslState) of + {valid, _} -> + apply_user_fun(Fun, OtpCert, + ExtensionOrError, UserState, + SslState); + {fail, Reason} -> + apply_user_fun(Fun, OtpCert, Reason, UserState, + SslState); + {unknown, _} -> + apply_user_fun(Fun, OtpCert, + ExtensionOrError, UserState, SslState) + end + end, {Role, UserState0}} end, - try - %% Allow missing root_cert and check that with VerifyFun - ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbRef, false) of - {TrustedErlCert, CertPath, VerifyErrors} -> - Result = public_key:pkix_path_validation(TrustedErlCert, - CertPath, - [{max_path_length, - MaxPathLen}, - {verify, VerifyBool}, - {validate_extensions_fun, - ValidateExtensionFun}, - {acc_errors, - VerifyErrors}]), - case Result of - {error, Reason} -> - path_validation_alert(Reason, Verify); - {ok, {PublicKeyInfo,_, []}} -> - {PeerCert, PublicKeyInfo}; - {ok, {PublicKeyInfo,_, AccErrors = [Error | _]}} -> - case VerifyFun(AccErrors) of - true -> - {PeerCert, PublicKeyInfo}; - false -> - path_validation_alert(Error, Verify) - end - end - catch - throw:Alert -> - Alert + + {TrustedErlCert, CertPath} = + ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbRef), + + case public_key:pkix_path_validation(TrustedErlCert, + CertPath, + [{max_path_length, + MaxPathLen}, + {verify_fun, ValidationFunAndState}]) of + {ok, {PublicKeyInfo,_}} -> + {PeerCert, PublicKeyInfo}; + {error, Reason} -> + path_validation_alert(Reason) end. - + %%-------------------------------------------------------------------- --spec certificate(der_cert(), term(), client | server) -> #certificate{}. +-spec certificate(der_cert(), term(), client | server) -> #certificate{} | #alert{}. %% %% Description: Creates a certificate message. %%-------------------------------------------------------------------- @@ -260,8 +253,8 @@ certificate(OwnCert, CertDbRef, server) -> %%-------------------------------------------------------------------- -spec client_certificate_verify(undefined | der_cert(), binary(), tls_version(), key_algo(), private_key(), - {binary(), binary()}) -> - #certificate_verify{} | ignore. + {{binary(), binary()},{binary(), binary()}}) -> + #certificate_verify{} | ignore | #alert{}. %% %% Description: Creates a certificate_verify message, called by the client. %%-------------------------------------------------------------------- @@ -283,9 +276,9 @@ client_certificate_verify(OwnCert, MasterSecret, Version, Algorithm, end. %%-------------------------------------------------------------------- --spec certificate_verify(binary(), public_key_info(), tls_version(), - binary(), key_algo(), - {binary(), binary()}) -> valid | #alert{}. +%% -spec certificate_verify(binary(), public_key_info(), tls_version(), +%% binary(), key_algo(), +%% {_, {binary(), binary()}}) -> valid | #alert{}. %% %% Description: Checks that the certificate_verify message is valid. %%-------------------------------------------------------------------- @@ -306,7 +299,7 @@ certificate_verify(Signature, {_, PublicKey, PublicKeyParams}, Version, MasterSecret, dhe_dss = Algorithm, {_, Hashes0}) -> Hashes = calc_certificate_verify(Version, MasterSecret, Algorithm, Hashes0), - case public_key:verify_signature(Hashes, none, Signature, PublicKey, PublicKeyParams) of + case public_key:verify(Hashes, none, Signature, {PublicKey, PublicKeyParams}) of true -> valid; false -> @@ -335,7 +328,7 @@ certificate_request(ConnectionStates, CertDbRef) -> -spec key_exchange(client | server, {premaster_secret, binary(), public_key_info()} | {dh, binary()} | - {dh, binary(), #'DHParameter'{}, key_algo(), + {dh, {binary(), binary()}, #'DHParameter'{}, key_algo(), binary(), binary(), private_key()}) -> #client_key_exchange{} | #server_key_exchange{}. %% @@ -412,7 +405,7 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) -> end. %%-------------------------------------------------------------------- --spec finished(tls_version(), client | server, binary(), {binary(), binary()}) -> +-spec finished(tls_version(), client | server, binary(), {{binary(), binary()},_}) -> #finished{}. %% %% Description: Creates a handshake finished message @@ -423,7 +416,7 @@ finished(Version, Role, MasterSecret, {Hashes, _}) -> % use the current hashes %%-------------------------------------------------------------------- -spec verify_connection(tls_version(), #finished{}, client | server, binary(), - {binary(), binary()}) -> verified | #alert{}. + {_, {binary(), binary()}}) -> verified | #alert{}. %% %% Description: Checks the ssl handshake finished message to verify %% the connection. @@ -448,7 +441,7 @@ server_hello_done() -> #server_hello_done{}. %%-------------------------------------------------------------------- --spec encode_handshake(tls_handshake(), tls_version(), key_algo()) -> binary(). +-spec encode_handshake(tls_handshake(), tls_version(), key_algo()) -> iolist(). %% %% Description: Encode a handshake packet to binary %%-------------------------------------------------------------------- @@ -459,49 +452,53 @@ encode_handshake(Package, Version, KeyAlg) -> [MsgType, ?uint24(Len), Bin]. %%-------------------------------------------------------------------- --spec get_tls_handshake(binary(), binary(), key_algo(), tls_version()) -> - {[tls_handshake()], [binary()], binary()}. +-spec get_tls_handshake(binary(), binary() | iolist()) -> + {[tls_handshake()], binary()}. %% %% Description: Given buffered and new data from ssl_record, collects %% and returns it as a list of handshake messages, also returns leftover %% data. %%-------------------------------------------------------------------- -get_tls_handshake(Data, <<>>, KeyAlg, Version) -> - get_tls_handshake_aux(Data, KeyAlg, Version, []); -get_tls_handshake(Data, Buffer, KeyAlg, Version) -> - get_tls_handshake_aux(list_to_binary([Buffer, Data]), - KeyAlg, Version, []). +get_tls_handshake(Data, <<>>) -> + get_tls_handshake_aux(Data, []); +get_tls_handshake(Data, Buffer) -> + get_tls_handshake_aux(list_to_binary([Buffer, Data]), []). + +%%-------------------------------------------------------------------- +-spec decode_client_key(binary(), key_algo(), tls_version()) -> + #encrypted_premaster_secret{} | #client_diffie_hellman_public{}. +%% +%% Description: Decode client_key data and return appropriate type +%%-------------------------------------------------------------------- +decode_client_key(ClientKey, Type, Version) -> + dec_client_key(ClientKey, key_exchange_alg(Type), Version). %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- get_tls_handshake_aux(<<?BYTE(Type), ?UINT24(Length), - Body:Length/binary,Rest/binary>>, KeyAlg, - Version, Acc) -> + Body:Length/binary,Rest/binary>>, Acc) -> Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>, - H = dec_hs(Type, Body, key_exchange_alg(KeyAlg), Version), - get_tls_handshake_aux(Rest, KeyAlg, Version, [{H,Raw} | Acc]); -get_tls_handshake_aux(Data, _KeyAlg, _Version, Acc) -> + H = dec_hs(Type, Body), + get_tls_handshake_aux(Rest, [{H,Raw} | Acc]); +get_tls_handshake_aux(Data, Acc) -> {lists:reverse(Acc), Data}. -verify_bool(verify_peer) -> - true; -verify_bool(verify_none) -> - false. - -path_validation_alert({bad_cert, cert_expired}, _) -> +path_validation_alert({bad_cert, cert_expired}) -> ?ALERT_REC(?FATAL, ?CERTIFICATE_EXPIRED); -path_validation_alert({bad_cert, invalid_issuer}, _) -> +path_validation_alert({bad_cert, invalid_issuer}) -> ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE); -path_validation_alert({bad_cert, invalid_signature} , _) -> +path_validation_alert({bad_cert, invalid_signature}) -> ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE); -path_validation_alert({bad_cert, name_not_permitted}, _) -> +path_validation_alert({bad_cert, name_not_permitted}) -> ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE); -path_validation_alert({bad_cert, unknown_critical_extension}, _) -> +path_validation_alert({bad_cert, unknown_critical_extension}) -> ?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE); -path_validation_alert({bad_cert, cert_revoked}, _) -> +path_validation_alert({bad_cert, cert_revoked}) -> ?ALERT_REC(?FATAL, ?CERTIFICATE_REVOKED); -path_validation_alert(_, _) -> +path_validation_alert({bad_cert, unknown_ca}) -> + ?ALERT_REC(?FATAL, ?UNKNOWN_CA); +path_validation_alert(_) -> ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE). select_session(Hello, Port, Session, Version, @@ -524,13 +521,16 @@ select_session(Hello, Port, Session, Version, {resumed, CacheCb:lookup(Cache, {Port, SessionId})} end. -available_suites(Cert, UserSuites, Version) -> +available_suites(UserSuites, Version) -> case UserSuites of [] -> - ssl_cipher:filter(Cert, ssl_cipher:suites(Version)); + ssl_cipher:suites(Version); _ -> - ssl_cipher:filter(Cert, UserSuites) + UserSuites end. + +available_suites(ServerCert, UserSuites, Version) -> + ssl_cipher:filter(ServerCert, available_suites(UserSuites, Version)). cipher_suites(Suites, false) -> [?TLS_EMPTY_RENEGOTIATION_INFO_SCSV | Suites]; @@ -724,7 +724,7 @@ master_secret(Version, MasterSecret, #security_parameters{ ServerCipherState, Role)}. -dec_hs(?HELLO_REQUEST, <<>>, _, _) -> +dec_hs(?HELLO_REQUEST, <<>>) -> #hello_request{}; %% Client hello v2. @@ -734,8 +734,7 @@ dec_hs(?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), ?UINT16(CSLength), ?UINT16(0), ?UINT16(CDLength), CipherSuites:CSLength/binary, - ChallengeData:CDLength/binary>>, - _, _) -> + ChallengeData:CDLength/binary>>) -> ?DBG_HEX(CipherSuites), ?DBG_HEX(CipherSuites), #client_hello{client_version = {Major, Minor}, @@ -749,8 +748,7 @@ dec_hs(?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, ?BYTE(SID_length), Session_ID:SID_length/binary, ?UINT16(Cs_length), CipherSuites:Cs_length/binary, ?BYTE(Cm_length), Comp_methods:Cm_length/binary, - Extensions/binary>>, - _, _) -> + Extensions/binary>>) -> RenegotiationInfo = proplists:get_value(renegotiation_info, dec_hello_extensions(Extensions), undefined), @@ -765,7 +763,7 @@ dec_hs(?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, ?BYTE(SID_length), Session_ID:SID_length/binary, - Cipher_suite:2/binary, ?BYTE(Comp_method)>>, _, _) -> + Cipher_suite:2/binary, ?BYTE(Comp_method)>>) -> #server_hello{ server_version = {Major,Minor}, random = Random, @@ -777,7 +775,7 @@ dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, ?BYTE(SID_length), Session_ID:SID_length/binary, Cipher_suite:2/binary, ?BYTE(Comp_method), - ?UINT16(ExtLen), Extensions:ExtLen/binary>>, _, _) -> + ?UINT16(ExtLen), Extensions:ExtLen/binary>>) -> RenegotiationInfo = proplists:get_value(renegotiation_info, dec_hello_extensions(Extensions, []), undefined), @@ -788,44 +786,42 @@ dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, cipher_suite = Cipher_suite, compression_method = Comp_method, renegotiation_info = RenegotiationInfo}; -dec_hs(?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>, _, _) -> +dec_hs(?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>) -> #certificate{asn1_certificates = certs_to_list(ASN1Certs)}; dec_hs(?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary, ?UINT16(GLen), G:GLen/binary, ?UINT16(YLen), Y:YLen/binary, - ?UINT16(Len), Sig:Len/binary>>, - ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) -> + ?UINT16(Len), Sig:Len/binary>>) -> #server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G, dh_y = Y}, signed_params = Sig}; dec_hs(?CERTIFICATE_REQUEST, <<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary, - ?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>, _, _) -> + ?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>) -> #certificate_request{certificate_types = CertTypes, certificate_authorities = CertAuths}; -dec_hs(?SERVER_HELLO_DONE, <<>>, _, _) -> +dec_hs(?SERVER_HELLO_DONE, <<>>) -> #server_hello_done{}; -dec_hs(?CERTIFICATE_VERIFY,<<?UINT16(_), Signature/binary>>, _, _)-> +dec_hs(?CERTIFICATE_VERIFY,<<?UINT16(_), Signature/binary>>)-> #certificate_verify{signature = Signature}; -dec_hs(?CLIENT_KEY_EXCHANGE, PKEPMS, ?KEY_EXCHANGE_RSA, {3, 0}) -> - PreSecret = #encrypted_premaster_secret{premaster_secret = PKEPMS}, - #client_key_exchange{exchange_keys = PreSecret}; -dec_hs(?CLIENT_KEY_EXCHANGE, <<?UINT16(_), PKEPMS/binary>>, - ?KEY_EXCHANGE_RSA, _) -> - PreSecret = #encrypted_premaster_secret{premaster_secret = PKEPMS}, - #client_key_exchange{exchange_keys = PreSecret}; -dec_hs(?CLIENT_KEY_EXCHANGE, <<>>, ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) -> - throw(?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE)); -dec_hs(?CLIENT_KEY_EXCHANGE, <<?UINT16(DH_YLen), DH_Y:DH_YLen/binary>>, - ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) -> - #client_key_exchange{exchange_keys = - #client_diffie_hellman_public{dh_public = DH_Y}}; -dec_hs(?FINISHED, VerifyData, _, _) -> +dec_hs(?CLIENT_KEY_EXCHANGE, PKEPMS) -> + #client_key_exchange{exchange_keys = PKEPMS}; +dec_hs(?FINISHED, VerifyData) -> #finished{verify_data = VerifyData}; -dec_hs(_, _, _, _) -> +dec_hs(_, _) -> throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)). +dec_client_key(PKEPMS, ?KEY_EXCHANGE_RSA, {3, 0}) -> + #encrypted_premaster_secret{premaster_secret = PKEPMS}; +dec_client_key(<<?UINT16(_), PKEPMS/binary>>, ?KEY_EXCHANGE_RSA, _) -> + #encrypted_premaster_secret{premaster_secret = PKEPMS}; +dec_client_key(<<>>, ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) -> + throw(?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE)); +dec_client_key(<<?UINT16(DH_YLen), DH_Y:DH_YLen/binary>>, + ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) -> + #client_diffie_hellman_public{dh_public = DH_Y}. + dec_hello_extensions(<<>>) -> []; dec_hello_extensions(<<?UINT16(ExtLen), Extensions:ExtLen/binary>>) -> @@ -1042,9 +1038,10 @@ certificate_authorities(CertDbRef) -> Authorities = certificate_authorities_from_db(CertDbRef), Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) -> OTPSubj = TBSCert#'OTPTBSCertificate'.subject, - Subj = public_key:pkix_transform(OTPSubj, encode), - {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj), - DNEncodedBin = iolist_to_binary(DNEncoded), + DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp), + %%Subj = public_key:pkix_transform(OTPSubj, encode), + %% {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj), + %% DNEncodedBin = iolist_to_binary(DNEncoded), DNEncodedLen = byte_size(DNEncodedBin), <<?UINT16(DNEncodedLen), DNEncodedBin/binary>> end, @@ -1068,7 +1065,7 @@ digitally_signed(Hash, #'RSAPrivateKey'{} = Key) -> public_key:encrypt_private(Hash, Key, [{rsa_pad, rsa_pkcs1_padding}]); digitally_signed(Hash, #'DSAPrivateKey'{} = Key) -> - public_key:sign(none, Hash, Key). + public_key:sign(Hash, none, Key). calc_master_secret({3,0}, PremasterSecret, ClientRandom, ServerRandom) -> ssl_ssl3:master_secret(PremasterSecret, ClientRandom, ServerRandom); @@ -1120,7 +1117,17 @@ sig_alg(_) -> key_exchange_alg(rsa) -> ?KEY_EXCHANGE_RSA; key_exchange_alg(Alg) when Alg == dhe_rsa; Alg == dhe_dss; - Alg == dh_dss; Alg == dh_rsa; Alg == dh_anon -> + Alg == dh_dss; Alg == dh_rsa -> ?KEY_EXCHANGE_DIFFIE_HELLMAN; key_exchange_alg(_) -> ?NULL. + +apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState) -> + case Fun(OtpCert, ExtensionOrError, UserState0) of + {valid, UserState} -> + {valid, {SslState, UserState}}; + {fail, _} = Fail -> + Fail; + {unknown, UserState} -> + {unknown, {SslState, UserState}} + end. diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index ddace02dea..ddb05e70f6 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -63,10 +63,13 @@ validate_extensions_fun, depth, % integer() certfile, % file() + cert, % der_encoded() keyfile, % file() - key, % + key, % der_encoded() password, % + cacerts, % [der_encoded()] cacertfile, % file() + dh, % der_encoded() dhfile, % file() ciphers, % %% Local policy for the server if it want's to reuse the session @@ -96,12 +99,12 @@ -type from() :: term(). -type host() :: string() | tuple(). -type port_num() :: integer(). --type session_id() :: binary(). +-type session_id() :: 0 | binary(). -type tls_version() :: {integer(), integer()}. -type tls_atom_version() :: sslv3 | tlsv1. -type cache_ref() :: term(). -type certdb_ref() :: term(). --type key_algo() :: rsa | dhe_rsa | dhe_dss. +-type key_algo() :: null | rsa | dhe_rsa | dhe_dss. -type enum_algo() :: integer(). -type public_key() :: #'RSAPublicKey'{} | integer(). -type public_key_params() :: #'Dss-Parms'{} | term(). diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index af30f78dbf..0116466677 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -29,7 +29,8 @@ %% Internal application API -export([start_link/1, connection_init/2, cache_pem_file/1, - lookup_trusted_cert/3, issuer_candidate/1, client_session_id/3, server_session_id/3, + lookup_trusted_cert/3, issuer_candidate/1, client_session_id/3, + server_session_id/3, register_session/2, register_session/3, invalidate_session/2, invalidate_session/3]). @@ -68,12 +69,12 @@ start_link(Opts) -> gen_server:start_link({local, ?MODULE}, ?MODULE, [Opts], []). %%-------------------------------------------------------------------- --spec connection_init(string(), client | server) -> {ok, reference(), cache_ref()}. +-spec connection_init(string()| {der, list()}, client | server) -> {ok, reference(), cache_ref()}. %% %% Description: Do necessary initializations for a new connection. %%-------------------------------------------------------------------- -connection_init(TrustedcertsFile, Role) -> - call({connection_init, TrustedcertsFile, Role}). +connection_init(Trustedcerts, Role) -> + call({connection_init, Trustedcerts, Role}). %%-------------------------------------------------------------------- -spec cache_pem_file(string()) -> {ok, term()}. %% @@ -88,14 +89,17 @@ cache_pem_file(File) -> end. %%-------------------------------------------------------------------- -spec lookup_trusted_cert(reference(), serialnumber(), issuer()) -> - {der_cert(), #'OTPCertificate'{}}. + undefined | + {ok, {der_cert(), #'OTPCertificate'{}}}. %% -%% Description: Lookup the trusted cert with Key = {reference(), serialnumber(), issuer()}. -%%-------------------------------------------------------------------- +%% Description: Lookup the trusted cert with Key = {reference(), +%% serialnumber(), issuer()}. +%% -------------------------------------------------------------------- lookup_trusted_cert(Ref, SerialNumber, Issuer) -> ssl_certificate_db:lookup_trusted_cert(Ref, SerialNumber, Issuer). %%-------------------------------------------------------------------- --spec issuer_candidate(cert_key()) -> {cert_key(), der_cert()} | no_more_candidates. +-spec issuer_candidate(cert_key() | no_candidate) -> + {cert_key(), {der_cert(), #'OTPCertificate'{}}} | no_more_candidates. %% %% Description: Return next issuer candidate. %%-------------------------------------------------------------------- @@ -143,8 +147,9 @@ invalidate_session(Port, Session) -> %%==================================================================== %%-------------------------------------------------------------------- --spec init(list()) -> {ok, #state{}} | {ok, #state{}, timeout()} | - ignore | {stop, term()}. +-spec init(list()) -> {ok, #state{}}. +%% Possible return values not used now. +%% | {ok, #state{}, timeout()} | ignore | {stop, term()}. %% %% Description: Initiates the server %%-------------------------------------------------------------------- @@ -164,12 +169,13 @@ init([Opts]) -> session_validation_timer = Timer}}. %%-------------------------------------------------------------------- --spec handle_call(msg(), from(), #state{}) -> {reply, reply(), #state{}} | - {reply, reply(), #state{}, timeout()} | - {noreply, #state{}} | - {noreply, #state{}, timeout()} | - {stop, reason(), reply(), #state{}} | - {stop, reason(), #state{}}. +-spec handle_call(msg(), from(), #state{}) -> {reply, reply(), #state{}}. +%% Possible return values not used now. +%% {reply, reply(), #state{}, timeout()} | +%% {noreply, #state{}} | +%% {noreply, #state{}, timeout()} | +%% {stop, reason(), reply(), #state{}} | +%% {stop, reason(), #state{}}. %% %% Description: Handling call messages %%-------------------------------------------------------------------- @@ -179,13 +185,13 @@ handle_call({{connection_init, "", _Role}, Pid}, _From, Result = {ok, make_ref(), Cache}, {reply, Result, State}; -handle_call({{connection_init, TrustedcertsFile, _Role}, Pid}, _From, +handle_call({{connection_init, Trustedcerts, _Role}, Pid}, _From, #state{certificate_db = Db, session_cache = Cache} = State) -> erlang:monitor(process, Pid), Result = try - {ok, Ref} = ssl_certificate_db:add_trusted_certs(Pid, TrustedcertsFile, Db), + {ok, Ref} = ssl_certificate_db:add_trusted_certs(Pid, Trustedcerts, Db), {ok, Ref, Cache} catch _:Reason -> @@ -216,9 +222,10 @@ handle_call({{cache_pem, File},Pid}, _, State = #state{certificate_db = Db}) -> {reply, {error, Reason}, State} end. %%-------------------------------------------------------------------- --spec handle_cast(msg(), #state{}) -> {noreply, #state{}} | - {noreply, #state{}, timeout()} | - {stop, reason(), #state{}}. +-spec handle_cast(msg(), #state{}) -> {noreply, #state{}}. +%% Possible return values not used now. +%% | {noreply, #state{}, timeout()} | +%% {stop, reason(), #state{}}. %% %% Description: Handling cast messages %%-------------------------------------------------------------------- @@ -253,9 +260,10 @@ handle_cast({invalidate_session, Port, #session{session_id = ID}}, {noreply, State}. %%-------------------------------------------------------------------- --spec handle_info(msg(), #state{}) -> {noreply, #state{}} | - {noreply, #state{}, timeout()} | - {stop, reason(), #state{}}. +-spec handle_info(msg(), #state{}) -> {noreply, #state{}}. +%% Possible return values not used now. +%% |{noreply, #state{}, timeout()} | +%% {stop, reason(), #state{}}. %% %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl index 90615c22a1..acd0d49c19 100644 --- a/lib/ssl/src/ssl_record.erl +++ b/lib/ssl/src/ssl_record.erl @@ -149,7 +149,7 @@ set_mac_secret(ReadMacSecret, WriteMacSecret, %%-------------------------------------------------------------------- --spec set_master_secret(binary(), #connection_state{}) -> #connection_states{}. +-spec set_master_secret(binary(), #connection_states{}) -> #connection_states{}. %% %% Description: Set master_secret in pending connection states %%-------------------------------------------------------------------- @@ -306,7 +306,7 @@ set_pending_cipher_state(#connection_states{pending_read = Read, pending_write = Write#connection_state{cipher_state = ClientState}}. %%-------------------------------------------------------------------- --spec get_tls_records(binary(), binary()) -> {[binary()], binary()}. +-spec get_tls_records(binary(), binary()) -> {[binary()], binary()} | #alert{}. %% %% Description: Given old buffer and new data from TCP, packs up a records %% and returns it as a list of tls_compressed binaries also returns leftover @@ -372,7 +372,8 @@ get_tls_records_aux(Data, Acc) -> {lists:reverse(Acc), Data}. %%-------------------------------------------------------------------- --spec protocol_version(tls_atom_version()) -> tls_version(). +-spec protocol_version(tls_atom_version() | tls_version()) -> + tls_version() | tls_atom_version(). %% %% Description: Creates a protocol version record from a version atom %% or vice versa. @@ -467,7 +468,7 @@ is_acceptable_version(_) -> false. %%-------------------------------------------------------------------- --spec compressions() -> binary(). +-spec compressions() -> [binary()]. %% %% Description: return a list of compressions supported (currently none) %%-------------------------------------------------------------------- @@ -476,7 +477,7 @@ compressions() -> %%-------------------------------------------------------------------- -spec decode_cipher_text(#ssl_tls{}, #connection_states{}) -> - {#ssl_tls{}, #connection_states{}}. + {#ssl_tls{}, #connection_states{}}| #alert{}. %% %% Description: Decode cipher text %%-------------------------------------------------------------------- diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl index e9755cb0e1..25e7445180 100644 --- a/lib/ssl/src/ssl_session.erl +++ b/lib/ssl/src/ssl_session.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2010. 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,7 +35,7 @@ -type seconds() :: integer(). %%-------------------------------------------------------------------- --spec is_new(binary(), binary()) -> boolean(). +-spec is_new(session_id(), session_id()) -> boolean(). %% %% Description: Checks if the session id decided by the server is a %% new or resumed sesion id. @@ -113,7 +113,7 @@ select_session(Sessions, #ssl_options{ciphers = Ciphers, List -> hd(List) end. - + %% If we can not generate a not allready in use session ID in %% ?GEN_UNIQUE_ID_MAX_TRIES we make the new session uncacheable The %% value of ?GEN_UNIQUE_ID_MAX_TRIES is stolen from open SSL which diff --git a/lib/ssl/src/ssl_ssl3.erl b/lib/ssl/src/ssl_ssl3.erl index 375adf263a..1add203fb0 100644 --- a/lib/ssl/src/ssl_ssl3.erl +++ b/lib/ssl/src/ssl_ssl3.erl @@ -121,9 +121,10 @@ mac_hash(Method, Mac_write_secret, Seq_num, Type, Length, Fragment) -> ?DBG_HEX(Mac), Mac. --spec setup_keys(binary(), binary(), binary(), binary(), - integer(), integer(), binary()) -> {binary(), binary(), binary(), - binary(), binary(), binary()}. +-spec setup_keys(binary(), binary(), binary(), + integer(), integer(), term(), integer()) -> + {binary(), binary(), binary(), + binary(), binary(), binary()}. setup_keys(MasterSecret, ServerRandom, ClientRandom, HS, KML, _EKML, IVS) -> KeyBlock = generate_keyblock(MasterSecret, ServerRandom, ClientRandom, diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl index b7cb5c3ab3..316ed8a4e9 100644 --- a/lib/ssl/src/ssl_sup.erl +++ b/lib/ssl/src/ssl_sup.erl @@ -32,14 +32,17 @@ %%%========================================================================= %%% API %%%========================================================================= + +-spec start_link() -> {ok, pid()} | ignore | {error, term()}. + start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). %%%========================================================================= %%% Supervisor callback %%%========================================================================= -%% init([]) -> {ok, {SupFlags, [ChildSpec]}} -%% +-spec init([]) -> {ok, {SupFlags :: tuple(), [ChildSpec :: tuple()]}}. + init([]) -> %% OLD ssl - moved start to ssl.erl only if old %% ssl is acctualy run! diff --git a/lib/ssl/test/erl_make_certs.erl b/lib/ssl/test/erl_make_certs.erl index 1d2cea6c72..f8aef55754 100644 --- a/lib/ssl/test/erl_make_certs.erl +++ b/lib/ssl/test/erl_make_certs.erl @@ -56,7 +56,7 @@ make_cert(Opts) -> SubjectPrivateKey = get_key(Opts), {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts), - Cert = public_key:sign(TBSCert, IssuerKey), + Cert = public_key:pkix_sign(TBSCert, IssuerKey), true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok {Cert, encode_key(SubjectPrivateKey)}. @@ -66,8 +66,9 @@ make_cert(Opts) -> %% @end %%-------------------------------------------------------------------- write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) -> - ok = public_key:der_to_pem(filename:join(Dir, FileName ++ ".pem"), [{cert, Cert, not_encrypted}]), - ok = public_key:der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]). + ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"), + [{'Certificate', Cert, not_encrypted}]), + ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]). %%-------------------------------------------------------------------- %% @doc Creates a rsa key (OBS: for testing only) @@ -94,18 +95,14 @@ gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) -> %% @spec (::binary(), ::tuple()) -> ::boolean() %% @end %%-------------------------------------------------------------------- -verify_signature(DerEncodedCert, DerKey, KeyParams) -> +verify_signature(DerEncodedCert, DerKey, _KeyParams) -> Key = decode_key(DerKey), case Key of #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} -> - public_key:verify_signature(DerEncodedCert, - #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}, - 'NULL'); + public_key:pkix_verify(DerEncodedCert, + #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}); #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} -> - public_key:verify_signature(DerEncodedCert, Y, #'Dss-Parms'{p=P, q=Q, g=G}); - - _ -> - public_key:verify_signature(DerEncodedCert, Key, KeyParams) + public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}}) end. %%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -132,59 +129,63 @@ decode_key(#'RSAPrivateKey'{} = Key,_) -> Key; decode_key(#'DSAPrivateKey'{} = Key,_) -> Key; -decode_key(Der = {_,_,_}, Pw) -> - {ok, Key} = public_key:decode_private_key(Der, Pw), - Key; -decode_key(FileOrDer, Pw) -> - {ok, [KeyInfo]} = public_key:pem_to_der(FileOrDer), +decode_key(PemEntry = {_,_,_}, Pw) -> + public_key:pem_entry_decode(PemEntry, Pw); +decode_key(PemBin, Pw) -> + [KeyInfo] = public_key:pem_decode(PemBin), decode_key(KeyInfo, Pw). encode_key(Key = #'RSAPrivateKey'{}) -> {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key), - {rsa_private_key, list_to_binary(Der), not_encrypted}; + {'RSAPrivateKey', list_to_binary(Der), not_encrypted}; encode_key(Key = #'DSAPrivateKey'{}) -> {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key), - {dsa_private_key, list_to_binary(Der), not_encrypted}. + {'DSAPrivateKey', list_to_binary(Der), not_encrypted}. make_tbs(SubjectKey, Opts) -> Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))), - {Issuer, IssuerKey} = issuer(Opts, SubjectKey), + + IssuerProp = proplists:get_value(issuer, Opts, true), + {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey), {Algo, Parameters} = sign_algorithm(IssuerKey, Opts), SignAlgo = #'SignatureAlgorithm'{algorithm = Algo, parameters = Parameters}, - + Subject = case IssuerProp of + true -> %% Is a Root Ca + Issuer; + _ -> + subject(proplists:get_value(subject, Opts),false) + end, + {#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1, signature = SignAlgo, issuer = Issuer, validity = validity(Opts), - subject = subject(proplists:get_value(subject, Opts),false), + subject = Subject, subjectPublicKeyInfo = publickey(SubjectKey), version = Version, extensions = extensions(Opts) }, IssuerKey}. -issuer(Opts, SubjectKey) -> - IssuerProp = proplists:get_value(issuer, Opts, true), - case IssuerProp of - true -> %% Self signed - {subject(proplists:get_value(subject, Opts), true), SubjectKey}; - {Issuer, IssuerKey} when is_binary(Issuer) -> - {issuer_der(Issuer), decode_key(IssuerKey)}; - {File, IssuerKey} when is_list(File) -> - {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File), - {issuer_der(Cert), decode_key(IssuerKey)} - end. +issuer(true, Opts, SubjectKey) -> + %% Self signed + {subject(proplists:get_value(subject, Opts), true), SubjectKey}; +issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) -> + {issuer_der(Issuer), decode_key(IssuerKey)}; +issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) -> + {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File), + {issuer_der(Cert), decode_key(IssuerKey)}. issuer_der(Issuer) -> - {ok, Decoded} = public_key:pkix_decode_cert(Issuer, otp), + Decoded = public_key:pkix_decode_cert(Issuer, otp), #'OTPCertificate'{tbsCertificate=Tbs} = Decoded, #'OTPTBSCertificate'{subject=Subject} = Tbs, Subject. -subject(undefined, IsCA) -> - User = if IsCA -> "CA"; true -> os:getenv("USER") end, +subject(undefined, IsRootCA) -> + User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end, Opts = [{email, User ++ "@erlang.org"}, {name, User}, {city, "Stockholm"}, @@ -271,7 +272,7 @@ publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) -> #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}. validity(Opts) -> - DefFrom0 = date(), + DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1), DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7), {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}), Format = fun({Y,M,D}) -> lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) end, @@ -410,3 +411,11 @@ extended_gcd(A, B) -> {X, Y} = extended_gcd(B, N), {Y, X-Y*(A div B)} end. + +pem_to_der(File) -> + {ok, PemBin} = file:read_file(File), + public_key:pem_decode(PemBin). + +der_to_pem(File, Entries) -> + PemBin = public_key:pem_encode(Entries), + file:write_file(File, PemBin). diff --git a/lib/ssl/test/make_certs.erl b/lib/ssl/test/make_certs.erl index 0cdf33c3e2..3c18a905b4 100644 --- a/lib/ssl/test/make_certs.erl +++ b/lib/ssl/test/make_certs.erl @@ -90,8 +90,10 @@ enduser(Root, OpenSSLCmd, CA, User) -> KeyFile = filename:join([UsrRoot, "key.pem"]), ReqFile = filename:join([UsrRoot, "req.pem"]), create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile), - CertFile = filename:join([UsrRoot, "cert.pem"]), - sign_req(Root, OpenSSLCmd, CA, "user_cert", ReqFile, CertFile). + CertFileAllUsage = filename:join([UsrRoot, "cert.pem"]), + sign_req(Root, OpenSSLCmd, CA, "user_cert", ReqFile, CertFileAllUsage), + CertFileDigitalSigOnly = filename:join([UsrRoot, "digital_signature_only_cert.pem"]), + sign_req(Root, OpenSSLCmd, CA, "user_cert_digital_signature_only", ReqFile, CertFileDigitalSigOnly). collect_certs(Root, CAs, Users) -> Bins = lists:foldr( @@ -255,6 +257,7 @@ ca_cnf(CA) -> "RANDFILE = $dir/private/RAND\n" "\n" "x509_extensions = user_cert\n" + "unique_subject = no\n" "default_days = 3600\n" "default_md = sha1\n" "preserve = no\n" @@ -279,6 +282,15 @@ ca_cnf(CA) -> "issuerAltName = issuer:copy\n" "\n" + "[user_cert_digital_signature_only]\n" + "basicConstraints = CA:false\n" + "keyUsage = digitalSignature\n" + "subjectKeyIdentifier = hash\n" + "authorityKeyIdentifier = keyid,issuer:always\n" + "subjectAltName = email:copy\n" + "issuerAltName = issuer:copy\n" + "\n" + "[ca_cert]\n" "basicConstraints = critical,CA:true\n" "keyUsage = cRLSign, keyCertSign\n" diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 8a1b90ed98..1e96880801 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -7,7 +7,7 @@ %% 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/. +%% 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 @@ -232,8 +232,11 @@ all(suite) -> server_renegotiate, client_renegotiate_reused_session, server_renegotiate_reused_session, client_no_wrap_sequence_number, server_no_wrap_sequence_number, extended_key_usage, - validate_extensions_fun, no_authority_key_identifier, - invalid_signature_client, invalid_signature_server, cert_expired + no_authority_key_identifier, + invalid_signature_client, invalid_signature_server, cert_expired, + client_with_cert_cipher_suites_handshake, unknown_server_ca_fail, + der_input, unknown_server_ca_accept_verify_none, unknown_server_ca_accept_verify_peer, + unknown_server_ca_accept_backwardscompatibilty ]. %% Test cases starts here. @@ -578,8 +581,8 @@ peercert(Config) when is_list(Config) -> {options, ClientOpts}]), CertFile = proplists:get_value(certfile, ServerOpts), - {ok, [{cert, BinCert, _}]} = public_key:pem_to_der(CertFile), - {ok, ErlCert} = public_key:pkix_decode_cert(BinCert, otp), + [{'Certificate', BinCert, _}]= ssl_test_lib:pem_to_der(CertFile), + ErlCert = public_key:pkix_decode_cert(BinCert, otp), ServerMsg = {{error, no_peercert}, {error, no_peercert}}, ClientMsg = {{ok, BinCert}, {ok, ErlCert}}, @@ -1258,7 +1261,6 @@ eoptions(Config) when is_list(Config) -> {verify_fun, function}, {fail_if_no_peer_cert, 0}, {verify_client_once, 1}, - {validate_extensions_fun, function}, {depth, four}, {certfile, 'cert.pem'}, {keyfile,'key.pem' }, @@ -1552,25 +1554,26 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) -> process_flag(trap_exit, true), test_server:format("Testing CipherSuite ~p~n", [CipherSuite]), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + ErlangCipherSuite = erlang_cipher_suite(CipherSuite), + + ConnectionInfo = {ok, {Version, ErlangCipherSuite}}, + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, connection_info_result, []}}, + {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, connection_info_result, []}}, + {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}}, {options, [{ciphers,[CipherSuite]} | ClientOpts]}]), - - ErlangCipherSuite = erlang_cipher_suite(CipherSuite), - - ServerMsg = ClientMsg = {ok, {Version, ErlangCipherSuite}}, - - Result = ssl_test_lib:wait_for_result(Server, ServerMsg, - Client, ClientMsg), + + Result = ssl_test_lib:wait_for_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), receive {'EXIT', Server, normal} -> @@ -2268,14 +2271,7 @@ client_verify_none_active_once(Config) when is_list(Config) -> {mfa, {?MODULE, send_recv_result_active_once, []}}, {options, [{active, once} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - %% TODO: send message to test process to make sure - %% verifyfun has beeen run as it has the same behavior as - %% the default fun - VerifyFun = fun([{bad_cert, unknown_ca}]) -> - true; - (_) -> - false - end, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, @@ -2283,8 +2279,7 @@ client_verify_none_active_once(Config) when is_list(Config) -> send_recv_result_active_once, []}}, {options, [{active, once}, - {verify, verify_none}, - {verify_fun, VerifyFun} + {verify, verify_none} | ClientOpts]}]), ssl_test_lib:check_result(Server, ok, Client, ok), @@ -2525,35 +2520,35 @@ extended_key_usage(Config) when is_list(Config) -> PrivDir = ?config(priv_dir, Config), KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), - {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile), - {ok, Key} = public_key:decode_private_key(KeyInfo), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = public_key:pem_entry_decode(KeyEntry), ServerCertFile = proplists:get_value(certfile, ServerOpts), NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"), - {ok, [{cert, ServerDerCert, _}]} = public_key:pem_to_der(ServerCertFile), - {ok, ServerOTPCert} = public_key:pkix_decode_cert(ServerDerCert, otp), + [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), + ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp), ServerExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-serverAuth']}, ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate, ServerExtensions = ServerOTPTbsCert#'OTPTBSCertificate'.extensions, NewServerOTPTbsCert = ServerOTPTbsCert#'OTPTBSCertificate'{extensions = [ServerExtKeyUsageExt | ServerExtensions]}, - NewServerDerCert = public_key:sign(NewServerOTPTbsCert, Key), - public_key:der_to_pem(NewServerCertFile, [{cert, NewServerDerCert, not_encrypted}]), + NewServerDerCert = public_key:pkix_sign(NewServerOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], ClientCertFile = proplists:get_value(certfile, ClientOpts), NewClientCertFile = filename:join(PrivDir, "client/new_cert.pem"), - {ok, [{cert, ClientDerCert, _}]} = public_key:pem_to_der(ClientCertFile), - {ok, ClientOTPCert} = public_key:pkix_decode_cert(ClientDerCert, otp), + [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile), + ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp), ClientExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-clientAuth']}, ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate, ClientExtensions = ClientOTPTbsCert#'OTPTBSCertificate'.extensions, NewClientOTPTbsCert = ClientOTPTbsCert#'OTPTBSCertificate'{extensions = [ClientExtKeyUsageExt | ClientExtensions]}, - NewClientDerCert = public_key:sign(NewClientOTPTbsCert, Key), - public_key:der_to_pem(NewClientCertFile, [{cert, NewClientDerCert, not_encrypted}]), + NewClientDerCert = public_key:pkix_sign(NewClientOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]), NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)], {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -2575,59 +2570,25 @@ extended_key_usage(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -validate_extensions_fun(doc) -> - ["Test that it is possible to specify a validate_extensions_fun"]; - -validate_extensions_fun(suite) -> - []; - -validate_extensions_fun(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - - Fun = fun(Extensions, State, _, AccError) -> - {Extensions, State, AccError} - end, - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{validate_extensions_fun, Fun}, - {verify, verify_peer} | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options,[{validate_extensions_fun, Fun} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- no_authority_key_identifier(doc) -> - ["Test cert that does not have authorityKeyIdentifier extension"]; + ["Test cert that does not have authorityKeyIdentifier extension" + " but are present in trusted certs db."]; no_authority_key_identifier(suite) -> []; no_authority_key_identifier(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), + ClientOpts = ?config(client_verification_opts, Config), ServerOpts = ?config(server_opts, Config), PrivDir = ?config(priv_dir, Config), KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), - {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile), - {ok, Key} = public_key:decode_private_key(KeyInfo), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = public_key:pem_entry_decode(KeyEntry), CertFile = proplists:get_value(certfile, ServerOpts), NewCertFile = filename:join(PrivDir, "server/new_cert.pem"), - {ok, [{cert, DerCert, _}]} = public_key:pem_to_der(CertFile), - {ok, OTPCert} = public_key:pkix_decode_cert(DerCert, otp), + [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(CertFile), + OTPCert = public_key:pkix_decode_cert(DerCert, otp), OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate, Extensions = OTPTbsCert#'OTPTBSCertificate'.extensions, NewExtensions = delete_authority_key_extension(Extensions, []), @@ -2635,8 +2596,8 @@ no_authority_key_identifier(Config) when is_list(Config) -> test_server:format("Extensions ~p~n, NewExtensions: ~p~n", [Extensions, NewExtensions]), - NewDerCert = public_key:sign(NewOTPTbsCert, Key), - public_key:der_to_pem(NewCertFile, [{cert, NewDerCert, not_encrypted}]), + NewDerCert = public_key:pkix_sign(NewOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewCertFile, [{'Certificate', NewDerCert, not_encrypted}]), NewServerOpts = [{certfile, NewCertFile} | proplists:delete(certfile, ServerOpts)], {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -2674,21 +2635,21 @@ invalid_signature_server(suite) -> []; invalid_signature_server(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), + ClientOpts = ?config(client_verification_opts, Config), ServerOpts = ?config(server_verification_opts, Config), PrivDir = ?config(priv_dir, Config), KeyFile = filename:join(PrivDir, "server/key.pem"), - {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile), - {ok, Key} = public_key:decode_private_key(KeyInfo), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = public_key:pem_entry_decode(KeyEntry), ServerCertFile = proplists:get_value(certfile, ServerOpts), NewServerCertFile = filename:join(PrivDir, "server/invalid_cert.pem"), - {ok, [{cert, ServerDerCert, _}]} = public_key:pem_to_der(ServerCertFile), - {ok, ServerOTPCert} = public_key:pkix_decode_cert(ServerDerCert, otp), + [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), + ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp), ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate, - NewServerDerCert = public_key:sign(ServerOTPTbsCert, Key), - public_key:der_to_pem(NewServerCertFile, [{cert, NewServerDerCert, not_encrypted}]), + NewServerDerCert = public_key:pkix_sign(ServerOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -2719,16 +2680,16 @@ invalid_signature_client(Config) when is_list(Config) -> PrivDir = ?config(priv_dir, Config), KeyFile = filename:join(PrivDir, "client/key.pem"), - {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile), - {ok, Key} = public_key:decode_private_key(KeyInfo), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = public_key:pem_entry_decode(KeyEntry), ClientCertFile = proplists:get_value(certfile, ClientOpts), NewClientCertFile = filename:join(PrivDir, "client/invalid_cert.pem"), - {ok, [{cert, ClientDerCert, _}]} = public_key:pem_to_der(ClientCertFile), - {ok, ClientOTPCert} = public_key:pkix_decode_cert(ClientDerCert, otp), + [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile), + ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp), ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate, - NewClientDerCert = public_key:sign(ClientOTPTbsCert, Key), - public_key:der_to_pem(NewClientCertFile, [{cert, NewClientDerCert, not_encrypted}]), + NewClientDerCert = public_key:pkix_sign(ClientOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]), NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)], {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -2745,7 +2706,7 @@ invalid_signature_client(Config) when is_list(Config) -> tcp_delivery_workaround(Server, {error, "bad certificate"}, Client, {error,"bad certificate"}). -tcp_delivery_workaround(Server, ServMsg, Client, ClientMsg) -> +tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) -> receive {Server, ServerMsg} -> receive @@ -2791,18 +2752,18 @@ cert_expired(suite) -> []; cert_expired(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), + ClientOpts = ?config(client_verification_opts, Config), ServerOpts = ?config(server_verification_opts, Config), PrivDir = ?config(priv_dir, Config), KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), - {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile), - {ok, Key} = public_key:decode_private_key(KeyInfo), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = public_key:pem_entry_decode(KeyEntry), ServerCertFile = proplists:get_value(certfile, ServerOpts), NewServerCertFile = filename:join(PrivDir, "server/expired_cert.pem"), - {ok, [{cert, DerCert, _}]} = public_key:pem_to_der(ServerCertFile), - {ok, OTPCert} = public_key:pkix_decode_cert(DerCert, otp), + [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), + OTPCert = public_key:pkix_decode_cert(DerCert, otp), OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate, {Year, Month, Day} = date(), @@ -2825,8 +2786,8 @@ cert_expired(Config) when is_list(Config) -> [OTPTbsCert#'OTPTBSCertificate'.validity, NewValidity]), NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{validity = NewValidity}, - NewServerDerCert = public_key:sign(NewOTPTbsCert, Key), - public_key:der_to_pem(NewServerCertFile, [{cert, NewServerDerCert, not_encrypted}]), + NewServerDerCert = public_key:pkix_sign(NewOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -2849,6 +2810,233 @@ two_digits_str(N) -> lists:flatten(io_lib:format("~p", [N])). %%-------------------------------------------------------------------- + +client_with_cert_cipher_suites_handshake(doc) -> + ["Test that client with a certificate without keyEncipherment usage " + " extension can connect to a server with restricted cipher suites "]; + +client_with_cert_cipher_suites_handshake(suite) -> + []; + +client_with_cert_cipher_suites_handshake(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts_digital_signature_only, Config), + ServerOpts = ?config(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, + send_recv_result_active, []}}, + {options, [{active, true}, + {ciphers, ssl_test_lib:rsa_non_signed_suites()} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, + send_recv_result_active, []}}, + {options, [{active, true} + | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). +%%-------------------------------------------------------------------- +unknown_server_ca_fail(doc) -> + ["Test that the client fails if the ca is unknown in verify_peer mode"]; +unknown_server_ca_fail(suite) -> + []; +unknown_server_ca_fail(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + FunAndState = {fun(_,{bad_cert, _} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState} + end, []}, + + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, FunAndState} + | ClientOpts]}]), + + ssl_test_lib:check_result(Server, {error,"unknown ca"}, + Client, {error, "unknown ca"}), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +unknown_server_ca_accept_verify_none(doc) -> + ["Test that the client succeds if the ca is unknown in verify_none mode"]; +unknown_server_ca_accept_verify_none(suite) -> + []; +unknown_server_ca_accept_verify_none(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, + send_recv_result_active, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, + send_recv_result_active, []}}, + {options, + [{verify, verify_none}| ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). +%%-------------------------------------------------------------------- +unknown_server_ca_accept_verify_peer(doc) -> + ["Test that the client succeds if the ca is unknown in verify_peer mode" + " with a verify_fun that accepts the unknown ca error"]; +unknown_server_ca_accept_verify_peer(suite) -> + []; +unknown_server_ca_accept_verify_peer(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, + send_recv_result_active, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + FunAndState = {fun(_,{bad_cert, unknown_ca}, UserState) -> + {valid, UserState}; + (_,{bad_cert, _} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState} + end, []}, + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, + send_recv_result_active, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, FunAndState}| ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +unknown_server_ca_accept_backwardscompatibilty(doc) -> + ["Test that the client succeds if the ca is unknown in verify_none mode"]; +unknown_server_ca_accept_backwardscompatibilty(suite) -> + []; +unknown_server_ca_accept_backwardscompatibilty(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, + send_recv_result_active, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc; + (Other, Acc) -> [Other | Acc] + end, + VerifyFun = + fun(ErrorList) -> + case lists:foldl(AcceptBadCa, [], ErrorList) of + [] -> true; + [_|_] -> false + end + end, + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, + send_recv_result_active, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, VerifyFun}| ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +der_input(doc) -> + ["Test to input certs and key as der"]; + +der_input(suite) -> + []; + +der_input(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + DHParamFile = filename:join(DataDir, "dHParam.pem"), + + SeverVerifyOpts = ?config(server_verification_opts, Config), + {ServerCert, ServerKey, ServerCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} | + SeverVerifyOpts]), + ClientVerifyOpts = ?config(client_verification_opts, Config), + {ClientCert, ClientKey, ClientCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} | + ClientVerifyOpts]), + ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}, + {dh, DHParams}, + {cert, ServerCert}, {key, ServerKey}, {cacerts, ServerCaCerts}], + ClientOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}, + {dh, DHParams}, + {cert, ClientCert}, {key, ClientKey}, {cacerts, ClientCaCerts}], + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +der_input_opts(Opts) -> + Certfile = proplists:get_value(certfile, Opts), + CaCertsfile = proplists:get_value(cacertfile, Opts), + Keyfile = proplists:get_value(keyfile, Opts), + Dhfile = proplists:get_value(dhfile, Opts), + [{_, Cert, _}] = ssl_test_lib:pem_to_der(Certfile), + [{_, Key, _}] = ssl_test_lib:pem_to_der(Keyfile), + [{_, DHParams, _}] = ssl_test_lib:pem_to_der(Dhfile), + CaCerts = + lists:map(fun(Entry) -> + {_, CaCert, _} = Entry, + CaCert + end, ssl_test_lib:pem_to_der(CaCertsfile)), + {Cert, {rsa, Key}, CaCerts, DHParams}. + +%%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- send_recv_result(Socket) -> @@ -2873,6 +3061,7 @@ send_recv_result_active_once(Socket) -> result_ok(_Socket) -> ok. + renegotiate(Socket, Data) -> test_server:format("Renegotiating ~n", []), Result = ssl:renegotiate(Socket), diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl index 1b8754afe9..88d2d99ef8 100644 --- a/lib/ssl/test/ssl_packet_SUITE.erl +++ b/lib/ssl/test/ssl_packet_SUITE.erl @@ -145,14 +145,20 @@ all(suite) -> packet_baddata_passive, packet_baddata_active, packet_size_passive, packet_size_active, packet_cdr_decode, + packet_cdr_decode_list, packet_http_decode, packet_http_decode_list, packet_http_bin_decode_multi, + packet_http_error_passive, packet_line_decode, - packet_asn1_decode, + packet_line_decode_list, + packet_asn1_decode, + packet_asn1_decode_list, packet_tpkt_decode, + packet_tpkt_decode_list, %packet_fcgi_decode, packet_sunrm_decode, + packet_sunrm_decode_list, header_decode_one_byte, header_decode_two_bytes, header_decode_two_bytes_one_sent, @@ -1429,7 +1435,7 @@ packet_size_passive(Config) when is_list(Config) -> %%-------------------------------------------------------------------- packet_cdr_decode(doc) -> - ["Test setting the packet option {packet, cdr}"]; + ["Test setting the packet option {packet, cdr}, {mode, binary}"]; packet_cdr_decode(suite) -> []; packet_cdr_decode(Config) when is_list(Config) -> @@ -1463,8 +1469,44 @@ packet_cdr_decode(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- +packet_cdr_decode_list(doc) -> + ["Test setting the packet option {packet, cdr} {mode, list}"]; +packet_cdr_decode_list(suite) -> + []; +packet_cdr_decode_list(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + %% A valid cdr packet + Data = [71,73,79,80,1,2,2,1,0,0,0,41,0,0,0,0,0,0,0,0,0,0,0,1,78, + 69,79,0,0,0,0,2,0,10,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,4,49], + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_packet_decode, + [Data]}}, + {options, [{active, true}, list, + {packet, cdr}|ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_packet_decode, + [Data]}}, + {options, [{active, true}, {packet, cdr}, + list | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- packet_http_decode(doc) -> - ["Test setting the packet option {packet, http} {mode, binary}"]; + ["Test setting the packet option {packet, http} {mode, binary} " + "(Body will be binary http strings are lists)"]; packet_http_decode(suite) -> []; @@ -1485,7 +1527,7 @@ packet_http_decode(Config) when is_list(Config) -> {from, self()}, {mfa, {?MODULE, server_http_decode, [Response]}}, - {options, [{active, true}, binary, + {options, [{active, true},binary, {packet, http} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), @@ -1494,7 +1536,7 @@ packet_http_decode(Config) when is_list(Config) -> {from, self()}, {mfa, {?MODULE, client_http_decode, [Request]}}, - {options, [{active, true}, binary, + {options, [{active, true}, binary, {packet, http} | ClientOpts]}]), @@ -1548,7 +1590,8 @@ client_http_decode(Socket, HttpRequest) -> %%-------------------------------------------------------------------- packet_http_decode_list(doc) -> - ["Test setting the packet option {packet, http}, {mode, list}"]; + ["Test setting the packet option {packet, http}, {mode, list}" + "(Body will be litst too)"]; packet_http_decode_list(suite) -> []; packet_http_decode_list(Config) when is_list(Config) -> @@ -1695,9 +1738,74 @@ client_http_bin_decode(Socket, HttpRequest, Count) when Count > 0 -> client_http_bin_decode(Socket, HttpRequest, Count - 1); client_http_bin_decode(_, _, _) -> ok. + +%%-------------------------------------------------------------------- +packet_http_error_passive(doc) -> + ["Test setting the packet option {packet, http}, {active, false}" + " with a incorrect http header." ]; +packet_http_error_passive(suite) -> + []; +packet_http_error_passive(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Request = "GET / HTTP/1.1\r\n" + "host: www.example.com\r\n" + "user-agent HttpTester\r\n" + "\r\n", + Response = "HTTP/1.1 200 OK\r\n" + "\r\n" + "Hello!", + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_http_decode_error, + [Response]}}, + {options, [{active, false}, binary, + {packet, http} | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_decode_list, + [Request]}}, + {options, [{active, true}, list, + {packet, http} | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + +server_http_decode_error(Socket, HttpResponse) -> + assert_packet_opt(Socket, http), + + {ok, {http_request, 'GET', _, {1,1}}} = ssl:recv(Socket, 0), + + assert_packet_opt(Socket, http), + + {ok, {http_header, _, 'Host', _, "www.example.com"}} = ssl:recv(Socket, 0), + assert_packet_opt(Socket, http), + + {ok, {http_error, _}} = ssl:recv(Socket, 0), + + assert_packet_opt(Socket, http), + + {ok, http_eoh} = ssl:recv(Socket, 0), + + assert_packet_opt(Socket, http), + ok = ssl:send(Socket, HttpResponse), + ok. + + %%-------------------------------------------------------------------- packet_line_decode(doc) -> - ["Test setting the packet option {packet, line}"]; + ["Test setting the packet option {packet, line}, {mode, binary}"]; packet_line_decode(suite) -> []; packet_line_decode(Config) when is_list(Config) -> @@ -1731,30 +1839,44 @@ packet_line_decode(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). +%%-------------------------------------------------------------------- -server_line_packet_decode(Socket, Lines) -> - receive - {ssl, Socket, <<"Line ends here.\n">>} -> ok; - Other1 -> exit({?LINE, Other1}) - end, - receive - {ssl, Socket, <<"Now it is a new line.\n">>} -> ok; - Other2 -> exit({?LINE, Other2}) - end, - ok = ssl:send(Socket, Lines). +packet_line_decode_list(doc) -> + ["Test setting the packet option {packet, line}, {mode, list}"]; +packet_line_decode_list(suite) -> + []; +packet_line_decode_list(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Data = lists:flatten(io_lib:format("Line ends here.~n" + "Now it is a new line.~n", [])), + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, + server_line_packet_decode, + [Data]}}, + {options, [{active, true}, list, + {packet, line}|ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, + client_line_packet_decode, + [Data]}}, + {options, [{active, true}, + {packet, line}, + list | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). -client_line_packet_decode(Socket, Lines) -> - <<P1:10/binary, P2/binary>> = Lines, - ok = ssl:send(Socket, P1), - ok = ssl:send(Socket, P2), - receive - {ssl, Socket, <<"Line ends here.\n">>} -> ok; - Other1 -> exit({?LINE, Other1}) - end, - receive - {ssl, Socket, <<"Now it is a new line.\n">>} -> ok; - Other2 -> exit({?LINE, Other2}) - end. %%-------------------------------------------------------------------- @@ -1770,7 +1892,7 @@ packet_asn1_decode(Config) when is_list(Config) -> File = proplists:get_value(certfile, ServerOpts), %% A valid asn1 BER packet (DER is stricter BER) - {ok,[{cert, Data, _}]} = public_key:pem_to_der(File), + [{'Certificate', Data, _}] = ssl_test_lib:pem_to_der(File), Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, {from, self()}, @@ -1794,6 +1916,44 @@ packet_asn1_decode(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- +packet_asn1_decode_list(doc) -> + ["Test setting the packet option {packet, asn1}"]; +packet_asn1_decode_list(suite) -> + []; +packet_asn1_decode_list(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + File = proplists:get_value(certfile, ServerOpts), + + %% A valid asn1 BER packet (DER is stricter BER) + [{'Certificate', BinData, _}] = ssl_test_lib:pem_to_der(File), + + Data = binary_to_list(BinData), + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_packet_decode, + [Data]}}, + {options, [{active, true}, list, + {packet, asn1}|ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_packet_decode, + [Data]}}, + {options, [{active, true}, {packet, asn1}, + list | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- packet_tpkt_decode(doc) -> ["Test setting the packet option {packet, tpkt}"]; packet_tpkt_decode(suite) -> @@ -1826,6 +1986,38 @@ packet_tpkt_decode(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). +%%-------------------------------------------------------------------- +packet_tpkt_decode_list(doc) -> + ["Test setting the packet option {packet, tpkt}"]; +packet_tpkt_decode_list(suite) -> + []; +packet_tpkt_decode_list(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Data = binary_to_list(list_to_binary(add_tpkt_header("TPKT data"))), + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_packet_decode, + [Data]}}, + {options, [{active, true}, list, + {packet, tpkt}|ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_packet_decode, + [Data]}}, + {options, [{active, true}, {packet, tpkt}, + list | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). %%-------------------------------------------------------------------- @@ -1895,6 +2087,39 @@ packet_sunrm_decode(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +packet_sunrm_decode_list(doc) -> + ["Test setting the packet option {packet, sunrm}"]; +packet_sunrm_decode_list(suite) -> + []; +packet_sunrm_decode_list(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Data = binary_to_list(list_to_binary([<<11:32>>, "Hello world"])), + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_packet_decode, + [Data]}}, + {options, [{active, true}, list, + {packet, sunrm}|ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_packet_decode, + [Data]}}, + {options, [{active, true}, {packet, sunrm}, + list | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). %%-------------------------------------------------------------------- header_decode_one_byte(doc) -> @@ -2037,21 +2262,29 @@ header_decode_two_bytes_one_sent(Config) when is_list(Config) -> %%-------------------------------------------------------------------- %% Internal functions -send_raw(_,_, 0) -> +send_raw(Socket,_, 0) -> + ssl:send(Socket, <<>>), no_result_msg; send_raw(Socket, Data, N) -> ssl:send(Socket, Data), send_raw(Socket, Data, N-1). -passive_raw(_, _, 0) -> +passive_raw(Socket, _, 0) -> + {error, timeout} = ssl:recv(Socket, 0, 500), ok; passive_raw(Socket, Data, N) -> Length = length(Data), {ok, Data} = ssl:recv(Socket, Length), passive_raw(Socket, Data, N-1). -passive_recv_packet(_, _, 0) -> - ok; +passive_recv_packet(Socket, _, 0) -> + case ssl:recv(Socket, 0) of + {ok, []} -> + {error, timeout} = ssl:recv(Socket, 0, 500), + ok; + Other -> + {other, Other, ssl:session_info(Socket), 0} + end; passive_recv_packet(Socket, Data, N) -> case ssl:recv(Socket, 0) of {ok, Data} -> @@ -2060,7 +2293,8 @@ passive_recv_packet(Socket, Data, N) -> {other, Other, ssl:session_info(Socket), N} end. -send(_,_, 0) -> +send(Socket,_, 0) -> + ssl:send(Socket, <<>>), no_result_msg; send(Socket, Data, N) -> case ssl:send(Socket, [Data]) of @@ -2074,6 +2308,7 @@ send_incomplete(Socket, Data, N) -> send_incomplete(Socket, Data, N, <<>>). send_incomplete(Socket, _Data, 0, Prev) -> ssl:send(Socket, Prev), + ssl:send(Socket, [?uint32(0)]), no_result_msg; send_incomplete(Socket, Data, N, Prev) -> Length = size(Data), @@ -2102,8 +2337,13 @@ active_once_raw(Socket, Data, N, Acc) -> end end. -active_once_packet(_,_, 0) -> - ok; +active_once_packet(Socket,_, 0) -> + receive + {ssl, Socket, []} -> + ok; + {ssl, Socket, Other} -> + {other, Other, ssl:session_info(Socket), 0} + end; active_once_packet(Socket, Data, N) -> receive {ssl, Socket, Data} -> @@ -2115,7 +2355,7 @@ active_once_packet(Socket, Data, N) -> active_raw(Socket, Data, N) -> active_raw(Socket, Data, N, []). -active_raw(_, _, 0, _) -> +active_raw(_Socket, _, 0, _) -> ok; active_raw(Socket, Data, N, Acc) -> receive @@ -2130,8 +2370,13 @@ active_raw(Socket, Data, N, Acc) -> end end. -active_packet(_, _, 0) -> - ok; +active_packet(Socket, _, 0) -> + receive + {ssl, Socket, []} -> + ok; + Other -> + {other, Other, ssl:session_info(Socket), 0} + end; active_packet(Socket, Data, N) -> receive {ssl, Socket, Data} -> @@ -2155,8 +2400,14 @@ server_packet_decode(Socket, Packet) -> end, ok = ssl:send(Socket, Packet). -client_packet_decode(Socket, Packet) -> +client_packet_decode(Socket, Packet) when is_binary(Packet)-> <<P1:10/binary, P2/binary>> = Packet, + client_packet_decode(Socket, P1, P2, Packet); +client_packet_decode(Socket, [Head | Tail] = Packet) -> + client_packet_decode(Socket, [Head], Tail, Packet). + +client_packet_decode(Socket, P1, P2, Packet) -> + test_server:format("Packet: ~p ~n", [Packet]), ok = ssl:send(Socket, P1), ok = ssl:send(Socket, P2), receive @@ -2176,7 +2427,7 @@ server_header_decode(Socket, Packet, Result) -> end, ok = ssl:send(Socket, Packet), receive - {ssl, Socket, Result} -> ok; + {ssl, Socket, Result} -> ok; Other2 -> exit({?LINE, Other2}) end, ok = ssl:send(Socket, Packet). @@ -2192,6 +2443,44 @@ client_header_decode(Socket, Packet, Result) -> {ssl, Socket, Result} -> ok; Other2 -> exit({?LINE, Other2}) end. + +server_line_packet_decode(Socket, Packet) when is_binary(Packet) -> + [L1, L2] = string:tokens(binary_to_list(Packet), "\n"), + server_line_packet_decode(Socket, list_to_binary(L1 ++ "\n"), list_to_binary(L2 ++ "\n"), Packet); +server_line_packet_decode(Socket, Packet) -> + [L1, L2] = string:tokens(Packet, "\n"), + server_line_packet_decode(Socket, L1 ++ "\n", L2 ++ "\n", Packet). + +server_line_packet_decode(Socket, L1, L2, Packet) -> + receive + {ssl, Socket, L1} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + receive + {ssl, Socket, L2} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + ok = ssl:send(Socket, Packet). + +client_line_packet_decode(Socket, Packet) when is_binary(Packet)-> + <<P1:10/binary, P2/binary>> = Packet, + [L1, L2] = string:tokens(binary_to_list(Packet), "\n"), + client_line_packet_decode(Socket, P1, P2, list_to_binary(L1 ++ "\n"), list_to_binary(L2 ++ "\n")); +client_line_packet_decode(Socket, [Head | Tail] = Packet) -> + [L1, L2] = string:tokens(Packet, "\n"), + client_line_packet_decode(Socket, [Head], Tail, L1 ++ "\n", L2 ++ "\n"). + +client_line_packet_decode(Socket, P1, P2, L1, L2) -> + ok = ssl:send(Socket, P1), + ok = ssl:send(Socket, P2), + receive + {ssl, Socket, L1} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + receive + {ssl, Socket, L2} -> ok; + Other2 -> exit({?LINE, Other2}) + end. add_tpkt_header(Data) when is_binary(Data) -> L = size(Data) + 4, diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index dd0818827a..ce164f7e4c 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -268,6 +268,8 @@ cert_options(Config) -> "client", "cacerts.pem"]), ClientCertFile = filename:join([?config(priv_dir, Config), "client", "cert.pem"]), + ClientCertFileDigitalSignatureOnly = filename:join([?config(priv_dir, Config), + "client", "digital_signature_only_cert.pem"]), ServerCaCertFile = filename:join([?config(priv_dir, Config), "server", "cacerts.pem"]), ServerCertFile = filename:join([?config(priv_dir, Config), @@ -292,6 +294,10 @@ cert_options(Config) -> {certfile, ClientCertFile}, {keyfile, ClientKeyFile}, {ssl_imp, new}]}, + {client_verification_opts_digital_signature_only, [{cacertfile, ClientCaCertFile}, + {certfile, ClientCertFileDigitalSignatureOnly}, + {keyfile, ClientKeyFile}, + {ssl_imp, new}]}, {server_opts, [{ssl_imp, new},{reuseaddr, true}, {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]}, {server_verification_opts, [{ssl_imp, new},{reuseaddr, true}, @@ -326,7 +332,7 @@ make_dsa_cert(Config) -> {cacertfile, ServerCaCertFile}, {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]}, {server_dsa_verify_opts, [{ssl_imp, new},{reuseaddr, true}, - {cacertfile, ServerCaCertFile}, + {cacertfile, ClientCaCertFile}, {certfile, ServerCertFile}, {keyfile, ServerKeyFile}, {verify, verify_peer}]}, {client_dsa_opts, [{ssl_imp, new},{reuseaddr, true}, @@ -346,9 +352,9 @@ make_dsa_cert_files(RoleStr, Config) -> KeyFile = filename:join([?config(priv_dir, Config), RoleStr, "dsa_key.pem"]), - public_key:der_to_pem(CaCertFile, [{cert, CaCert, not_encrypted}]), - public_key:der_to_pem(CertFile, [{cert, Cert, not_encrypted}]), - public_key:der_to_pem(KeyFile, [CertKey]), + der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]), + der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]), + der_to_pem(KeyFile, [CertKey]), {CaCertFile, CertFile, KeyFile}. start_upgrade_server(Args) -> @@ -571,6 +577,14 @@ rsa_suites() -> end, ssl:cipher_suites()). +rsa_non_signed_suites() -> + lists:filter(fun({rsa, _, _}) -> + true; + (_) -> + false + end, + ssl:cipher_suites()). + dsa_suites() -> lists:filter(fun({dhe_dss, _, _}) -> true; @@ -601,3 +615,28 @@ openssl_dsa_suites() -> true end end, Ciphers). + +pem_to_der(File) -> + {ok, PemBin} = file:read_file(File), + public_key:pem_decode(PemBin). + +der_to_pem(File, Entries) -> + PemBin = public_key:pem_encode(Entries), + file:write_file(File, PemBin). + +cipher_result(Socket, Result) -> + Result = ssl:connection_info(Socket), + test_server:format("Successfull connect: ~p~n", [Result]), + %% Importante to send two packets here + %% to properly test "cipher state" handling + ssl:send(Socket, "Hello\n"), + receive + {ssl, Socket, "Hello\n"} -> + ssl:send(Socket, " world\n"), + receive + {ssl, Socket, " world\n"} -> + ok + end; + Other -> + {unexpected, Other} + end. diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 75cfce0052..7f512f2ab9 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -1136,17 +1136,31 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) -> wait_for_openssl_server(), + ConnectionInfo = {ok, {Version, CipherSuite}}, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, connection_info_result, []}}, + {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}}, {options, [{ciphers,[CipherSuite]} | ClientOpts]}]), - - ClientMsg = {ok, {Version, CipherSuite}}, - - Result = ssl_test_lib:wait_for_result(Client, ClientMsg), + + port_command(OpenSslPort, "Hello\n"), + + receive + {Port, {data, _}} when is_port(Port) -> + ok + after 500 -> + test_server:format("Time out on openssl port, check that" + " the messages Hello and world are received" + " during close of port" , []), + ok + end, + + port_command(OpenSslPort, " world\n"), + + Result = ssl_test_lib:wait_for_result(Client, ok), close_port(OpenSslPort), %% Clean close down! diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 254ee8b986..709a089892 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1,63 +1 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1999-2010. 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% -# - SSL_VSN = 4.0.1 - -TICKETS = OTP-8721 - -#TICKETS_4.0 = OTP-8587\ -# OTP-8695 - -#TICKETS_3.11.1 = OTP-8679 \ -# OTP-7047 \ -# OTP-7049 \ -# OTP-8568 \ -# OTP-8588 - -#TICKETS_3.11 = OTP-8517 \ -# OTP-7046 \ -# OTP-8557 \ -# OTP-8560 \ -# OTP-8545 \ -# OTP-8554 - -#TICKETS_3.10.9 = OTP-8510 - -#TICKETS_3.10.8 = OTP-8372 OTP-8441 OTP-8459 -#TICKETS_3.10.7 = OTP-8260 OTP-8218 OTP-8250 - -#TICKETS_3.10.6 = OTP-8275 - -#TICKETS_3.10.5 = OTP-8224 OTP-8244 - -#TICKETS_3.10.4 = OTP-8137 - -#TICKETS_3.10.3 = OTP-8011 -#TICKETS_3.10.2 = OTP-7963 - -# TICKETS_3.10.1 = OTP-7878 \ -# OTP-7656 \ -# OTP-7870 \ -# OTP-7871 - -# TICKETS_3.10 = OTP-7258 \ -# OTP-6894 \ -# OTP-7037 \ -# OTP-7039 \ -# OTP-7150 diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml index 8d1398d3b7..ad100d2cf5 100644 --- a/lib/stdlib/doc/src/dets.xml +++ b/lib/stdlib/doc/src/dets.xml @@ -109,7 +109,7 @@ bool() = true | false file() = string() int() = integer() >= 0 keypos() = integer() >= 1 -name() = atom() | ref() +name() = atom() | reference() no_slots() = integer() >= 0 | default object() = tuple() object_cont() = tuple() @@ -759,7 +759,7 @@ ok <fsummary>Open an existing Dets table.</fsummary> <type> <v>FileName = file()</v> - <v>Reference = ref()</v> + <v>Reference = reference()</v> </type> <desc> <p>Opens an existing table. If the table has not been properly diff --git a/lib/stdlib/doc/src/erl_id_trans.xml b/lib/stdlib/doc/src/erl_id_trans.xml index 7c821d2efc..cfb18ec131 100644 --- a/lib/stdlib/doc/src/erl_id_trans.xml +++ b/lib/stdlib/doc/src/erl_id_trans.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1996</year> - <year>2007</year> + <year>2010</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -70,7 +70,8 @@ <section> <title>See Also</title> - <p><seealso marker="erl_parse">erl_parse(3)</seealso>, compile(3).</p> + <p><seealso marker="erl_parse">erl_parse(3)</seealso>, + <seealso marker="compiler:compile">compile(3)</seealso>.</p> </section> </erlref> diff --git a/lib/stdlib/doc/src/erl_lint.xml b/lib/stdlib/doc/src/erl_lint.xml index 6a7d37765c..8639d678fa 100644 --- a/lib/stdlib/doc/src/erl_lint.xml +++ b/lib/stdlib/doc/src/erl_lint.xml @@ -96,8 +96,8 @@ <p>The <c>AbsForms</c> of a module which comes from a file that is read through <c>epp</c>, the Erlang pre-processor, can come from many files. This means that any references to - errors must include the file name (see <seealso marker="epp">epp(3)</seealso>, or parser <seealso marker="erl_parse">erl_parse(3)</seealso> The warnings and - errors returned have the following format: + errors must include the file name (see <seealso marker="epp">epp(3)</seealso>, or parser <seealso marker="erl_parse">erl_parse(3)</seealso>). + The warnings and errors returned have the following format: </p> <code type="none"> [{FileName2,[ErrorInfo]}] </code> diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml index ae8a8afd5c..18b592deea 100644 --- a/lib/stdlib/doc/src/erl_parse.xml +++ b/lib/stdlib/doc/src/erl_parse.xml @@ -39,7 +39,7 @@ expressions, or terms. The Abstract Format is described in the ERTS User's Guide. Note that a token list must end with the <em>dot</em> token in order - to be acceptable to the parse functions (see erl_scan).</p> + to be acceptable to the parse functions (see <seealso marker="erl_scan">erl_scan(3)</seealso>).</p> </description> <funcs> <func> diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index 5df60a92e5..dd4a289c61 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -1385,6 +1385,28 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code> </desc> </func> <func> + <name>select_count(Tab, MatchSpec) -> NumMatched</name> + <fsummary>Match the objects in an ETS table against a match_spec and returns the number of objects for which the match_spec returned 'true'</fsummary> + <type> + <v>Tab = tid() | atom()</v> + <v>Object = tuple()</v> + <v>MatchSpec = match_spec()</v> + <v>NumMatched = integer()</v> + </type> + <desc> + <p>Matches the objects in the table <c>Tab</c> using a + <seealso marker="#match_spec">match_spec</seealso>. If the + match_spec returns <c>true</c> for an object, that object + considered a match and is counted. For any other result from + the match_spec the object is not considered a match and is + therefore not counted.</p> + <p>The function could be described as a <c>match_delete/2</c> + that does not actually delete any elements, but only counts + them.</p> + <p>The function returns the number of objects matched.</p> + </desc> + </func> + <func> <name>select_delete(Tab, MatchSpec) -> NumDeleted</name> <fsummary>Match the objects in an ETS table against a match_spec and deletes objects where the match_spec returns 'true'</fsummary> <type> @@ -1411,25 +1433,82 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code> </desc> </func> <func> - <name>select_count(Tab, MatchSpec) -> NumMatched</name> - <fsummary>Match the objects in an ETS table against a match_spec and returns the number of objects for which the match_spec returned 'true'</fsummary> + <name>select_reverse(Tab, MatchSpec) -> [Match]</name> + <fsummary>Match the objects in an ETS table against a match_spec.</fsummary> <type> <v>Tab = tid() | atom()</v> - <v>Object = tuple()</v> + <v>Match = term()</v> <v>MatchSpec = match_spec()</v> - <v>NumMatched = integer()</v> </type> <desc> - <p>Matches the objects in the table <c>Tab</c> using a - <seealso marker="#match_spec">match_spec</seealso>. If the - match_spec returns <c>true</c> for an object, that object - considered a match and is counted. For any other result from - the match_spec the object is not considered a match and is - therefore not counted.</p> - <p>The function could be described as a <c>match_delete/2</c> - that does not actually delete any elements, but only counts - them.</p> - <p>The function returns the number of objects matched.</p> + + <p>Works like <c>select/2</c>, but returns the list in reverse + order for the <c>ordered_set</c> table type. For all other table + types, the return value is identical to that of <c>select/2</c>.</p> + + </desc> + </func> + <func> + <name>select_reverse(Tab, MatchSpec, Limit) -> {[Match],Continuation} | '$end_of_table'</name> + <fsummary>Match the objects in an ETS table against a match_spec and returns part of the answers.</fsummary> + <type> + <v>Tab = tid() | atom()</v> + <v>Match = term()</v> + <v>MatchSpec = match_spec()</v> + <v>Continuation = term()</v> + </type> + <desc> + + <p>Works like <c>select/3</c>, but for the <c>ordered_set</c> + table type, traversing is done starting at the last object in + Erlang term order and moves towards the first. For all other + table types, the return value is identical to that of + <c>select/3</c>.</p> + + <p>Note that this is <em>not</em> equivalent to + reversing the result list of a <c>select/3</c> call, as the result list + is not only reversed, but also contains the last <c>Limit</c> + matching objects in the table, not the first.</p> + + </desc> + </func> + <func> + <name>select_reverse(Continuation) -> {[Match],Continuation} | '$end_of_table'</name> + <fsummary>Continue matching objects in an ETS table.</fsummary> + <type> + <v>Match = term()</v> + <v>Continuation = term()</v> + </type> + <desc> + + <p>Continues a match started with + <c>ets:select_reverse/3</c>. If the table is an + <c>ordered_set</c>, the traversal of the table will continue + towards objects with keys earlier in the Erlang term order. The + returned list will also contain objects with keys in reverse + order.</p> + + <p>For all other table types, the behaviour is exatly that of <c>select/1</c>.</p> + <p>Example:</p> + <code> +1> T = ets:new(x,[ordered_set]). +2> [ ets:insert(T,{N}) || N <- lists:seq(1,10) ]. +... +3> {R0,C0} = ets:select_reverse(T,[{'_',[],['$_']}],4). +... +4> R0. +[{10},{9},{8},{7}] +5> {R1,C1} = ets:select_reverse(C0). +... +6> R1. +[{6},{5},{4},{3}] +7> {R2,C2} = ets:select_reverse(C1). +... +8> R2. +[{2},{1}] +9> '$end_of_table' = ets:select_reverse(C2). +... + </code> </desc> </func> <func> diff --git a/lib/stdlib/doc/src/io_protocol.xml b/lib/stdlib/doc/src/io_protocol.xml index b52e862a5c..a97d996d98 100644 --- a/lib/stdlib/doc/src/io_protocol.xml +++ b/lib/stdlib/doc/src/io_protocol.xml @@ -79,7 +79,7 @@ sends the reply to.</item> io_reply. The io-module in the Erlang standard library simply uses the pid() of the io_server as the ReplyAs datum, but a more complicated client could have several outstanding io-requests to the same server and -would then use i.e. a ref() or something else to differentiate among +would then use i.e. a reference() or something else to differentiate among the incoming io_reply's. The ReplyAs element should be considered opaque by the io_server. Note that the pid() of the server is not explicitly present in the io_reply. The reply can be sent from any diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml index b3ad7aaf46..92c4eb4f4c 100644 --- a/lib/stdlib/doc/src/lists.xml +++ b/lib/stdlib/doc/src/lists.xml @@ -220,7 +220,7 @@ follows:</p> <code type="none"> flatmap(Fun, List1) -> - append(map(Fun, List1))</code> + append(map(Fun, List1)).</code> <p>Example:</p> <pre> > <input>lists:flatmap(fun(X)->[X,X] end, [a,b,c]).</input> @@ -523,7 +523,7 @@ flatmap(Fun, List1) -> <v> A = B = term()</v> </type> <desc> - <p><c>mapfold</c> combines the operations of <c>map/2</c> and + <p><c>mapfoldl</c> combines the operations of <c>map/2</c> and <c>foldl/3</c> into one pass. An example, summing the elements in a list and double them at the same time:</p> <pre> @@ -543,7 +543,7 @@ flatmap(Fun, List1) -> <v> A = B = term()</v> </type> <desc> - <p><c>mapfold</c> combines the operations of <c>map/2</c> and + <p><c>mapfoldr</c> combines the operations of <c>map/2</c> and <c>foldr/3</c> into one pass.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index 10ead62073..8cbfb9387b 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -34,7 +34,7 @@ <module>sys</module> <modulesummary>A Functional Interface to System Messages</modulesummary> <description> - <p>This module contains functions for sending system messages used by programs, and messaged used for debugging purposes. + <p>This module contains functions for sending system messages used by programs, and messages used for debugging purposes. </p> <p>Functions used for implementation of processes should also understand system messages such as debugging diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl index 78b1de6e16..a249dea525 100644 --- a/lib/stdlib/src/ms_transform.erl +++ b/lib/stdlib/src/ms_transform.erl @@ -43,6 +43,7 @@ -define(ERR_GENREMOTECALL,22). -define(ERR_GENBINCONSTRUCT,23). -define(ERR_GENDISALLOWEDOP,24). +-define(WARN_SHADOW_VAR,50). -define(ERR_GUARDMATCH,?ERR_GENMATCH+?ERROR_BASE_GUARD). -define(ERR_BODYMATCH,?ERR_GENMATCH+?ERROR_BASE_BODY). -define(ERR_GUARDLOCALCALL,?ERR_GENLOCALCALL+?ERROR_BASE_GUARD). @@ -63,8 +64,13 @@ -define(ERR_BODYDISALLOWEDOP,?ERR_GENDISALLOWEDOP+?ERROR_BASE_BODY). %% -%% Called by compiler or ets/dbg:fun2ms when errors occur +%% Called by compiler or ets/dbg:fun2ms when errors/warnings occur %% +format_error({?WARN_SHADOW_VAR,Name}) -> + lists:flatten( + io_lib:format("variable ~p shadowed in ms_transform fun head", + [Name])); + format_error(?ERR_NOFUN) -> "Parameter of ets/dbg:fun2ms/1 is not a literal fun"; format_error(?ERR_ETS_HEAD) -> @@ -182,7 +188,7 @@ format_error(Else) -> %% transform_from_shell(Dialect, Clauses, BoundEnvironment) -> SaveFilename = setup_filename(), - case catch ms_clause_list(1,Clauses,Dialect) of + case catch ms_clause_list(1,Clauses,Dialect,gb_sets:new()) of {'EXIT',Reason} -> cleanup_filename(SaveFilename), exit(Reason); @@ -207,6 +213,7 @@ transform_from_shell(Dialect, Clauses, BoundEnvironment) -> %% parse_transform(Forms, _Options) -> SaveFilename = setup_filename(), + %io:format("Forms: ~p~n",[Forms]), case catch forms(Forms) of {'EXIT',Reason} -> cleanup_filename(SaveFilename), @@ -215,12 +222,31 @@ parse_transform(Forms, _Options) -> {error, [{cleanup_filename(SaveFilename), [{Line, ?MODULE, R}]}], []}; Else -> - cleanup_filename(SaveFilename), + %io:format("Transformed into: ~p~n",[Else]), + case get_warnings() of + [] -> + cleanup_filename(SaveFilename), + Else; + WL -> + FName = cleanup_filename(SaveFilename) , + WList = [ {FName, [{L, ?MODULE, R}]} || {L,R} <- WL ], + {warning, Else, WList} + end + end. + +get_warnings() -> + case get(warnings) of + undefined -> + []; + Else -> Else end. +add_warning(Line,R) -> + put(warnings,[{Line,R}| get_warnings()]). + setup_filename() -> - {erase(filename),erase(records)}. + {erase(filename),erase(records),erase(warnings)}. put_filename(Name) -> put(filename,Name). @@ -235,7 +261,7 @@ get_records() -> Else -> Else end. -cleanup_filename({Old,OldRec}) -> +cleanup_filename({Old,OldRec,OldWarnings}) -> Ret = case erase(filename) of undefined -> "TOP_LEVEL"; @@ -248,6 +274,12 @@ cleanup_filename({Old,OldRec}) -> Rec -> put(records,Rec) end, + case OldWarnings of + undefined -> + erase(warnings); + Warn -> + put(warnings,Warn) + end, case Old of undefined -> Ret; @@ -285,42 +317,77 @@ form({function,Line,Name0,Arity0,Clauses0}) -> form(AnyOther) -> AnyOther. function(Name, Arity, Clauses0) -> - Clauses1 = clauses(Clauses0), + {Clauses1,_} = clauses(Clauses0,gb_sets:new()), {Name,Arity,Clauses1}. -clauses([C0|Cs]) -> - C1 = clause(C0), - [C1|clauses(Cs)]; -clauses([]) -> []. -clause({clause,Line,H0,G0,B0}) -> - B1 = copy(B0), - {clause,Line,H0,G0,B1}. +clauses([C0|Cs],Bound) -> + {C1,Bound1} = clause(C0,Bound), + {C2,Bound2} = clauses(Cs,Bound1), + {[C1|C2],Bound2}; +clauses([],Bound) -> {[],Bound}. +clause({clause,Line,H0,G0,B0},Bound) -> + {H1,Bound1} = copy(H0,Bound), + {B1,Bound2} = copy(B0,Bound1), + {{clause,Line,H1,G0,B1},Bound2}. copy({call,Line,{remote,_Line2,{atom,_Line3,ets},{atom,_Line4,fun2ms}}, - As0}) -> - transform_call(ets,Line,As0); + As0},Bound) -> + {transform_call(ets,Line,As0,Bound),Bound}; copy({call,Line,{remote,_Line2,{record_field,_Line3, {atom,_Line4,''},{atom,_Line5,ets}}, - {atom,_Line6,fun2ms}}, As0}) -> + {atom,_Line6,fun2ms}}, As0},Bound) -> %% Packages... - transform_call(ets,Line,As0); + {transform_call(ets,Line,As0,Bound),Bound}; copy({call,Line,{remote,_Line2,{atom,_Line3,dbg},{atom,_Line4,fun2ms}}, - As0}) -> - transform_call(dbg,Line,As0); -copy(T) when is_tuple(T) -> - list_to_tuple(copy_list(tuple_to_list(T))); -copy(L) when is_list(L) -> - copy_list(L); -copy(AnyOther) -> - AnyOther. + As0},Bound) -> + {transform_call(dbg,Line,As0,Bound),Bound}; +copy({match,Line,A,B},Bound) -> + {B1,Bound1} = copy(B,Bound), + {A1,Bound2} = copy(A,Bound), + {{match,Line,A1,B1},gb_sets:union(Bound1,Bound2)}; +copy({var,_Line,'_'} = VarDef,Bound) -> + {VarDef,Bound}; +copy({var,_Line,Name} = VarDef,Bound) -> + Bound1 = gb_sets:add(Name,Bound), + {VarDef,Bound1}; +copy({'fun',Line,{clauses,Clauses}},Bound) -> % Dont export bindings from funs + {NewClauses,_IgnoredBindings} = copy_list(Clauses,Bound), + {{'fun',Line,{clauses,NewClauses}},Bound}; +copy({'case',Line,Of,ClausesList},Bound) -> % Dont export bindings from funs + {NewOf,NewBind0} = copy(Of,Bound), + {NewClausesList,NewBindings} = copy_case_clauses(ClausesList,NewBind0,[]), + {{'case',Line,NewOf,NewClausesList},NewBindings}; +copy(T,Bound) when is_tuple(T) -> + {L,Bound1} = copy_list(tuple_to_list(T),Bound), + {list_to_tuple(L),Bound1}; +copy(L,Bound) when is_list(L) -> + copy_list(L,Bound); +copy(AnyOther,Bound) -> + {AnyOther,Bound}. -copy_list([H|T]) -> - [copy(H)|copy_list(T)]; -copy_list([]) -> - []. +copy_case_clauses([],Bound,AddSets) -> + ReallyAdded = gb_sets:intersection(AddSets), + {[],gb_sets:union(Bound,ReallyAdded)}; +copy_case_clauses([{clause,Line,Match,Guard,Clauses}|T],Bound,AddSets) -> + {NewMatch,MatchBinds} = copy(Match,Bound), + {NewGuard,GuardBinds} = copy(Guard,MatchBinds), %% Really no new binds + {NewClauses,AllBinds} = copy(Clauses,GuardBinds), + %% To limit the setsizes, I subtract what I had before the case clause + %% and add it in the end + AddedBinds = gb_sets:subtract(AllBinds,Bound), + {NewTail,ExportedBindings} = + copy_case_clauses(T,Bound,[AddedBinds | AddSets]), + {[{clause,Line,NewMatch,NewGuard,NewClauses}|NewTail],ExportedBindings}. -transform_call(Type,_Line,[{'fun',Line2,{clauses, ClauseList}}]) -> - ms_clause_list(Line2, ClauseList,Type); -transform_call(_Type,Line,_NoAbstractFun) -> +copy_list([H|T],Bound) -> + {C1,Bound1} = copy(H,Bound), + {C2,Bound2} = copy_list(T,Bound1), + {[C1|C2],Bound2}; +copy_list([],Bound) -> + {[],Bound}. + +transform_call(Type,_Line,[{'fun',Line2,{clauses, ClauseList}}],Bound) -> + ms_clause_list(Line2, ClauseList,Type,Bound); +transform_call(_Type,Line,_NoAbstractFun,_) -> throw({error,Line,?ERR_NOFUN}). % Fixup semicolons in guards @@ -329,18 +396,19 @@ ms_clause_expand({clause, Line, Parameters, Guard = [_,_|_], Body}) -> ms_clause_expand(_Other) -> false. -ms_clause_list(Line,[H|T],Type) -> +ms_clause_list(Line,[H|T],Type,Bound) -> case ms_clause_expand(H) of NewHead when is_list(NewHead) -> - ms_clause_list(Line,NewHead ++ T, Type); + ms_clause_list(Line,NewHead ++ T, Type, Bound); false -> - {cons, Line, ms_clause(H,Type), ms_clause_list(Line, T,Type)} + {cons, Line, ms_clause(H, Type, Bound), + ms_clause_list(Line, T, Type, Bound)} end; -ms_clause_list(Line,[],_) -> +ms_clause_list(Line,[],_,_) -> {nil,Line}. -ms_clause({clause, Line, Parameters, Guards, Body},Type) -> +ms_clause({clause, Line, Parameters, Guards, Body},Type,Bound) -> check_type(Line,Parameters,Type), - {MSHead,Bindings} = transform_head(Parameters), + {MSHead,Bindings} = transform_head(Parameters,Bound), MSGuards = transform_guards(Line, Guards, Bindings), MSBody = transform_body(Line,Body,Bindings), {tuple, Line, [MSHead,MSGuards,MSBody]}. @@ -627,29 +695,31 @@ tg(Other,B) -> Element = io_lib:format("unknown element ~w", [Other]), throw({error,unknown,{?ERR_GENELEMENT+B#tgd.eb,Element}}). -transform_head([V]) -> +transform_head([V],OuterBound) -> Bind = cre_bind(), - {NewV,NewBind} = toplevel_head_match(V,Bind), - th(NewV,NewBind). + {NewV,NewBind} = toplevel_head_match(V,Bind,OuterBound), + th(NewV,NewBind,OuterBound). -toplevel_head_match({match,_,{var,_,VName},Expr},B) -> +toplevel_head_match({match,Line,{var,_,VName},Expr},B,OB) -> + warn_var_clash(Line,VName,OB), {Expr,new_bind({VName,'$_'},B)}; -toplevel_head_match({match,_,Expr,{var,_,VName}},B) -> +toplevel_head_match({match,Line,Expr,{var,_,VName}},B,OB) -> + warn_var_clash(Line,VName,OB), {Expr,new_bind({VName,'$_'},B)}; -toplevel_head_match(Other,B) -> +toplevel_head_match(Other,B,_OB) -> {Other,B}. -th({record,Line,RName,RFields},B) -> +th({record,Line,RName,RFields},B,OB) -> % youch... RDefs = get_records(), {KeyList0,NewB} = lists:foldl(fun({record_field,_,{atom,_,Key},Value}, {L,B0}) -> - {NV,B1} = th(Value,B0), + {NV,B1} = th(Value,B0,OB), {[{Key,NV}|L],B1}; ({record_field,_,{var,_,'_'},Value}, {L,B0}) -> - {NV,B1} = th(Value,B0), + {NV,B1} = th(Value,B0,OB), {[{{default},NV}|L],B1}; (_,_) -> throw({error,Line,{?ERR_HEADBADREC, @@ -692,9 +762,9 @@ th({record,Line,RName,RFields},B) -> _ -> throw({error,Line,{?ERR_HEADBADREC,RName}}) end; -th({match,Line,_,_},_) -> +th({match,Line,_,_},_,_) -> throw({error,Line,?ERR_HEADMATCH}); -th({atom,Line,A},B) -> +th({atom,Line,A},B,_OB) -> case atom_to_list(A) of [$$|NL] -> case (catch list_to_integer(NL)) of @@ -706,10 +776,11 @@ th({atom,Line,A},B) -> _ -> {{atom,Line,A},B} end; -th({bin_element,_Line0,{var, Line, A},_,_},_) -> +th({bin_element,_Line0,{var, Line, A},_,_},_,_) -> throw({error,Line,{?ERR_HEADBINMATCH,A}}); -th({var,Line,Name},B) -> +th({var,Line,Name},B,OB) -> + warn_var_clash(Line,Name,OB), case lkup_bind(Name,B) of undefined -> NewB = new_bind(Name,B), @@ -717,16 +788,24 @@ th({var,Line,Name},B) -> Trans -> {{atom,Line,Trans},B} end; -th([H|T],B) -> - {NH,NB} = th(H,B), - {NT,NNB} = th(T,NB), +th([H|T],B,OB) -> + {NH,NB} = th(H,B,OB), + {NT,NNB} = th(T,NB,OB), {[NH|NT],NNB}; -th(T,B) when is_tuple(T) -> - {L,NB} = th(tuple_to_list(T),B), +th(T,B,OB) when is_tuple(T) -> + {L,NB} = th(tuple_to_list(T),B,OB), {list_to_tuple(L),NB}; -th(Nonstruct,B) -> +th(Nonstruct,B,_OB) -> {Nonstruct,B}. +warn_var_clash(Line,Name,OuterBound) -> + case gb_sets:is_member(Name,OuterBound) of + true -> + add_warning(Line,{?WARN_SHADOW_VAR,Name}); + _ -> + ok + end. + %% Could be more efficient... check_multi_field(_, _, [], _) -> ok; diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 1514414e48..5c52dfcbf0 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -361,6 +361,12 @@ obsolete_1(erlang, concat_binary, 1) -> obsolete_1(ssl, peercert, 2) -> {deprecated,"deprecated (will be removed in R15A); use ssl:peercert/1 and public_key:pkix_decode_cert/2 instead"}; +%% Added in R14B. +obsolete_1(public_key, pem_to_der, 1) -> + {deprecated,"deprecated (will be removed in R15A); use file:read_file/1 and public_key:pem_decode/1"}; +obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 -> + {deprecated,{public_key,pem_entry_decode,1},"R15A"}; + obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 5d7e558601..7f39dbe21f 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -94,6 +94,8 @@ do_heavy_concurrent/1 ]). +-export([t_select_reverse/1]). + -include("test_server.hrl"). init_per_testcase(Case, Config) -> @@ -128,7 +130,7 @@ all(suite) -> match_heavy, fold, member, t_delete_object, t_init_table, t_whitebox, t_delete_all_objects, t_insert_list, t_test_ms, - t_select_delete, t_ets_dets, memory, + t_select_delete, t_ets_dets, memory, t_select_reverse, t_bucket_disappears, select_fail,t_insert_new, t_repair_continuation, otp_5340, otp_6338, otp_6842_select_1000, otp_7665, otp_8732, @@ -393,7 +395,7 @@ memory(Config) when is_list(Config) -> ?line erts_debug:set_internal_state(available_internal_state, true), ?line ok = chk_normal_tab_struct_size(), ?line L = [T1,T2,T3,T4] = fill_sets_int(1000), - ?line XRes1 = adjust_xmem(L, {14862,14072,14072,14078}), + ?line XRes1 = adjust_xmem(L, {13862,13072,13072,13078}), ?line Res1 = {?S(T1),?S(T2),?S(T3),?S(T4)}, ?line lists:foreach(fun(T) -> Before = ets:info(T,size), @@ -404,7 +406,7 @@ memory(Config) when is_list(Config) -> [Key, ets:info(T,type), Before, ets:info(T,size), Objs]) end, L), - ?line XRes2 = adjust_xmem(L, {14851,14062,14052,14058}), + ?line XRes2 = adjust_xmem(L, {13852,13063,13054,13060}), ?line Res2 = {?S(T1),?S(T2),?S(T3),?S(T4)}, ?line lists:foreach(fun(T) -> Before = ets:info(T,size), @@ -415,7 +417,7 @@ memory(Config) when is_list(Config) -> [Key, ets:info(T,type), Before, ets:info(T,size), Objs]) end, L), - ?line XRes3 = adjust_xmem(L, {14840,14052,14032,14038}), + ?line XRes3 = adjust_xmem(L, {13842,13054,13036,13042}), ?line Res3 = {?S(T1),?S(T2),?S(T3),?S(T4)}, ?line lists:foreach(fun(T) -> ?line ets:delete_all_objects(T) @@ -788,6 +790,67 @@ t_test_ms(Config) when is_list(Config) -> ?line true = (if is_list(String) -> true; true -> false end), ?line verify_etsmem(EtsMem). +t_select_reverse(doc) -> + ["Test the select reverse BIF's"]; +t_select_reverse(suite) -> + []; +t_select_reverse(Config) when is_list(Config) -> + ?line Table = ets:new(xxx, [ordered_set]), + ?line filltabint(Table,1000), + ?line A = lists:reverse(ets:select(Table,[{{'$1', '_'}, + [{'>', + {'rem', + '$1', 5}, + 2}], + ['$_']}])), + ?line A = ets:select_reverse(Table,[{{'$1', '_'}, + [{'>', + {'rem', + '$1', 5}, + 2}], + ['$_']}]), + ?line A = reverse_chunked(Table,[{{'$1', '_'}, + [{'>', + {'rem', + '$1', 5}, + 2}], + ['$_']}],3), + % A set/bag/duplicate_bag should get the same result regardless + % of select or select_reverse + ?line Table2 = ets:new(xxx, [set]), + ?line filltabint(Table2,1000), + ?line Table3 = ets:new(xxx, [bag]), + ?line filltabint(Table3,1000), + ?line Table4 = ets:new(xxx, [duplicate_bag]), + ?line filltabint(Table4,1000), + ?line lists:map(fun(Tab) -> + B = ets:select(Tab,[{{'$1', '_'}, + [{'>', + {'rem', + '$1', 5}, + 2}], + ['$_']}]), + B = ets:select_reverse(Tab,[{{'$1', '_'}, + [{'>', + {'rem', + '$1', 5}, + 2}], + ['$_']}]) + end,[Table2, Table3, Table4]), + ok. + + + +reverse_chunked(T,MS,N) -> + do_reverse_chunked(ets:select_reverse(T,MS,N),[]). + +do_reverse_chunked('$end_of_table',Acc) -> + lists:reverse(Acc); +do_reverse_chunked({L,C},Acc) -> + NewAcc = lists:reverse(L)++Acc, + do_reverse_chunked(ets:select_reverse(C), NewAcc). + + t_select_delete(doc) -> ["Test the ets:select_delete/2 and ets:select_count/2 BIF's"]; t_select_delete(suite) -> @@ -3942,7 +4005,7 @@ do_lookup_element(Tab, N, M) -> end. -heavy_concurrent(Config) -> +heavy_concurrent(_Config) -> repeat_for_opts(do_heavy_concurrent). do_heavy_concurrent(Opts) -> @@ -3961,7 +4024,7 @@ do_heavy_concurrent(Opts) -> ?line lists:foreach(fun (P) -> M = erlang:monitor(process, P), receive - {'DOWN', Mon, process, P, _} -> + {'DOWN', M, process, P, _} -> ok end end, diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl index 79a0a9af89..2d90d5b823 100644 --- a/lib/stdlib/test/ms_transform_SUITE.erl +++ b/lib/stdlib/test/ms_transform_SUITE.erl @@ -37,6 +37,7 @@ -export([andalso_orelse/1]). -export([float_1_function/1]). -export([action_function/1]). +-export([warnings/1]). -export([init_per_testcase/2, fin_per_testcase/2]). init_per_testcase(_Func, Config) -> @@ -50,8 +51,90 @@ fin_per_testcase(_Func, Config) -> all(suite) -> [from_shell,basic_ets,basic_dbg,records,record_index,multipass, bitsyntax, record_defaults, andalso_orelse, float_1_function, action_function, + warnings, top_match, old_guards, autoimported, semicolon]. +%% This may be subject to change +-define(WARN_NUMBER_SHADOW,50). +warnings(suite) -> + []; +warnings(doc) -> + ["Check that shadowed variables in fun head generate warning"]; +warnings(Config) when is_list(Config) -> + ?line setup(Config), + Prog = <<"A=5, " + "ets:fun2ms(fun({A,B}) " + " when is_integer(A) and (A+5 > B) -> " + " A andalso B " + " end)">>, + ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}}]}] = + compile_ww(Prog), + Prog2 = <<"C=5, " + "ets:fun2ms(fun({A,B} = C) " + " when is_integer(A) and (A+5 > B) -> " + " {A andalso B,C} " + " end)">>, + ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] = + compile_ww(Prog2), + Rec3 = <<"-record(a,{a,b,c,d=foppa}).">>, + Prog3 = <<"A=3,C=5, " + "ets:fun2ms(fun(#a{a = A, b = B} = C) " + " when is_integer(A) and (A+5 > B) -> " + " {A andalso B,C} " + " end)">>, + ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}}, + {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] = + compile_ww(Rec3,Prog3), + Rec4 = <<"-record(a,{a,b,c,d=foppa}).">>, + Prog4 = <<"A=3,C=5, " + "F = fun(B) -> B*3 end," + "erlang:display(F(A))," + "ets:fun2ms(fun(#a{a = A, b = B} = C) " + " when is_integer(A) and (A+5 > B) -> " + " {A andalso B,C} " + " end)">>, + ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}}, + {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] = + compile_ww(Rec4,Prog4), + Rec5 = <<"-record(a,{a,b,c,d=foppa}).">>, + Prog5 = <<"A=3,C=5, " + "F = fun(B) -> B*3 end," + "erlang:display(F(A))," + "B = ets:fun2ms(fun(#a{a = A, b = B} = C) " + " when is_integer(A) and (A+5 > B) -> " + " {A andalso B,C} " + " end)">>, + ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}}, + {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] = + compile_ww(Rec5,Prog5), + Prog6 = <<" X=bar, " + " A = case X of" + " foo ->" + " foo;" + " Y ->" + " ets:fun2ms(fun(Y) ->" % This is a warning + " 3*Y" + " end)" + " end," + " ets:fun2ms(fun(Y) ->" % Y out of "scope" here, so no warning + " {3*Y,A}" + " end)">>, + ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'Y'}}]}] = + compile_ww(Prog6), + Prog7 = <<" X=bar, " + " A = case X of" + " foo ->" + " Y = foo;" + " Y ->" + " bar" + " end," + " ets:fun2ms(fun(Y) ->" % Y exported from case and safe, so warn + " {3*Y,A}" + " end)">>, + ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'Y'}}]}] = + compile_ww(Prog7), + ok. + andalso_orelse(suite) -> []; andalso_orelse(doc) -> @@ -721,6 +804,24 @@ compile_and_run(Records,Expr) -> code:load_binary(tmp,FN,Bin), tmp:tmp(). +compile_ww(Expr) -> + compile_ww(<<>>,Expr). +compile_ww(Records,Expr) -> + Prog = << + "-module(tmp).\n", + "-include_lib(\"stdlib/include/ms_transform.hrl\").\n", + "-export([tmp/0]).\n", + Records/binary,"\n", + "tmp() ->\n", + Expr/binary,".\n">>, + FN=temp_name(), + file:write_file(FN,Prog), + {ok,Forms} = epp:parse_file(FN,"",""), + {ok,tmp,_Bin,Wlist} = compile:forms(Forms,[return_warnings, + nowarn_unused_vars, + nowarn_unused_record]), + Wlist. + do_eval(String) -> {done,{ok,T,_},[]} = erl_scan:tokens( [], diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index 02ea6d9d68..1757d35160 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1,20 +1 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2010. 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% -# - STDLIB_VSN = 1.17.1 diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile index d55a3a597d..3dca55178d 100644 --- a/lib/test_server/src/Makefile +++ b/lib/test_server/src/Makefile @@ -139,7 +139,7 @@ release_tests_spec: opt $(TARGET_FILES) $(TS_TARGET_FILES) \ $(AUTOCONF_FILES) $(C_FILES) $(COVER_FILES) $(CONFIG) \ $(RELEASE_PATH)/test_server - $(INSTALL_PROGRAM) $(PROGRAMS) $(RELEASE_PATH)/test_server + $(INSTALL_SCRIPT) $(PROGRAMS) $(RELEASE_PATH)/test_server release_docs_spec: diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile index 702d73f5af..fcb1282d16 100644 --- a/lib/test_server/test/Makefile +++ b/lib/test_server/test/Makefile @@ -88,7 +88,7 @@ release_spec: opt release_tests_spec: make_emakefile $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR) - $(INSTALL_PROGRAM) test_server.spec $(RELSYSDIR) + $(INSTALL_DATA) test_server.spec $(RELSYSDIR) chmod -f -R u+w $(RELSYSDIR) @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) diff --git a/lib/tools/doc/src/erlang_mode.xml b/lib/tools/doc/src/erlang_mode.xml index 912c442153..c21afc1f9b 100644 --- a/lib/tools/doc/src/erlang_mode.xml +++ b/lib/tools/doc/src/erlang_mode.xml @@ -173,7 +173,7 @@ sum(L) -> sum(L, 0). sum([H|T], Sum) -> sum(T, Sum + H); - sum([], Sum) -> Sum."</code> + sum([], Sum) -> Sum.</code> </item> </list> </section> diff --git a/lib/tools/doc/src/erlang_mode_chapter.xml b/lib/tools/doc/src/erlang_mode_chapter.xml index b22c6b1809..8aabd6ae74 100644 --- a/lib/tools/doc/src/erlang_mode_chapter.xml +++ b/lib/tools/doc/src/erlang_mode_chapter.xml @@ -45,7 +45,7 @@ <section> <title>Elisp</title> - <p>There are two Elsip modules include in this tool package + <p>There are two Elisp modules included in this tool package for Emacs. There is erlang.el that defines the actual erlang mode and there is erlang-start.el that makes some nice initializations.</p> </section> diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 6501e05a6e..c4d1bd1d2f 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -2174,6 +2174,8 @@ escape_lt_and_gt1([$<|T],Acc) -> escape_lt_and_gt1(T,[$;,$t,$l,$&|Acc]); escape_lt_and_gt1([$>|T],Acc) -> escape_lt_and_gt1(T,[$;,$t,$g,$&|Acc]); +escape_lt_and_gt1([$&|T],Acc) -> + escape_lt_and_gt1(T,[$;,$p,$m,$a,$&|Acc]); escape_lt_and_gt1([],Acc) -> lists:reverse(Acc); escape_lt_and_gt1([H|T],Acc) -> diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index abe9a804f0..7a6f8c92a2 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1,19 +1 @@ -# This is an -*-makefile-*- file. -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2010. 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% - TOOLS_VSN = 2.6.6 diff --git a/lib/tv/vsn.mk b/lib/tv/vsn.mk index 93973489bc..d344c676a3 100644 --- a/lib/tv/vsn.mk +++ b/lib/tv/vsn.mk @@ -1,20 +1 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2010. 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% -# - TV_VSN = 2.1.4.5 diff --git a/lib/wx/.gitignore b/lib/wx/.gitignore new file mode 100644 index 0000000000..fd76f078d7 --- /dev/null +++ b/lib/wx/.gitignore @@ -0,0 +1,2 @@ +test_log_* +wx_test_case_info diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index c91a9d7fff..6bafda5b9d 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -902,8 +902,8 @@ ['wxTreeCtrl','~wxTreeCtrl','AddRoot','AppendItem', %% Not on Windows 'AssignButtonsImageList','GetButtonsImageList','SetButtonsImageList' 'AssignImageList','AssignStateImageList','Collapse','CollapseAndReset', - 'Create','Delete','DeleteAllItems','DeleteChildren',{'EditLabel',1}, - %'EndEditLabel', + 'Create','Delete','DeleteAllItems','DeleteChildren', + {'EditLabel', [{"textCtrlClass", [nowhere]}]}, %'EndEditLabel', 'EnsureVisible','Expand','GetBoundingRect', 'GetChildrenCount','GetCount','GetEditControl', {'GetFirstChild',[{"cookie", out}]}, {'GetNextChild',[{"cookie", [both]}]}, @@ -1740,6 +1740,11 @@ %% 'GetItemRect', 'SetItemRect', 'GetToolId', 'SetToolId' %% ]}. +{class, wxSystemSettings, object, [], + [ + 'GetColour','GetFont','GetMetric','GetScreenType' + ]}. + {class, wxAuiNotebookEvent, wxNotifyEvent, [{acc, [{old_selection, "GetOldSelection()"}, {selection, "GetSelection()"}, diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h index 57b0faa2cb..ad46a98c90 100644 --- a/lib/wx/c_src/gen/wxe_derived_dest.h +++ b/lib/wx/c_src/gen/wxe_derived_dest.h @@ -736,7 +736,7 @@ void WxeApp::delete_object(void *ptr, wxeRefData *refd) { case 211: /* delete (wxFileDataObject *) ptr;These objects must be deleted by owner object */ break; case 212: /* delete (wxTextDataObject *) ptr;These objects must be deleted by owner object */ break; case 213: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break; - case 222: delete (wxLogNull *) ptr; break; + case 223: delete (wxLogNull *) ptr; break; default: delete (wxObject *) ptr; }} diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp index a6857442c9..692eef858c 100644 --- a/lib/wx/c_src/gen/wxe_events.cpp +++ b/lib/wx/c_src/gen/wxe_events.cpp @@ -266,41 +266,41 @@ void initEventTable() {wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 217, "command_splitter_doubleclicked"}, {wxEVT_COMMAND_SPLITTER_UNSPLIT, 217, "command_splitter_unsplit"}, {wxEVT_COMMAND_HTML_LINK_CLICKED, 219, "command_html_link_clicked"}, - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 220, "command_auinotebook_page_close"}, - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 220, "command_auinotebook_page_changed"}, - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 220, "command_auinotebook_page_changing"}, - {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 220, "command_auinotebook_button"}, - {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 220, "command_auinotebook_begin_drag"}, - {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 220, "command_auinotebook_end_drag"}, - {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 220, "command_auinotebook_drag_motion"}, - {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 220, "command_auinotebook_allow_dnd"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 221, "command_auinotebook_page_close"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 221, "command_auinotebook_page_changed"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 221, "command_auinotebook_page_changing"}, + {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 221, "command_auinotebook_button"}, + {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 221, "command_auinotebook_begin_drag"}, + {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 221, "command_auinotebook_end_drag"}, + {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 221, "command_auinotebook_drag_motion"}, + {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 221, "command_auinotebook_allow_dnd"}, #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 220, "command_auinotebook_tab_middle_down"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 221, "command_auinotebook_tab_middle_down"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 220, "command_auinotebook_tab_middle_up"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 221, "command_auinotebook_tab_middle_up"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 220, "command_auinotebook_tab_right_down"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 221, "command_auinotebook_tab_right_down"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 220, "command_auinotebook_tab_right_up"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 221, "command_auinotebook_tab_right_up"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 220, "command_auinotebook_page_closed"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 221, "command_auinotebook_page_closed"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 220, "command_auinotebook_drag_done"}, + {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 221, "command_auinotebook_drag_done"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 220, "command_auinotebook_bg_dclick"}, + {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 221, "command_auinotebook_bg_dclick"}, #endif - {wxEVT_AUI_PANE_BUTTON, 221, "aui_pane_button"}, - {wxEVT_AUI_PANE_CLOSE, 221, "aui_pane_close"}, - {wxEVT_AUI_PANE_MAXIMIZE, 221, "aui_pane_maximize"}, - {wxEVT_AUI_PANE_RESTORE, 221, "aui_pane_restore"}, - {wxEVT_AUI_RENDER, 221, "aui_render"}, - {wxEVT_AUI_FIND_MANAGER, 221, "aui_find_manager"}, + {wxEVT_AUI_PANE_BUTTON, 222, "aui_pane_button"}, + {wxEVT_AUI_PANE_CLOSE, 222, "aui_pane_close"}, + {wxEVT_AUI_PANE_MAXIMIZE, 222, "aui_pane_maximize"}, + {wxEVT_AUI_PANE_RESTORE, 222, "aui_pane_restore"}, + {wxEVT_AUI_RENDER, 222, "aui_render"}, + {wxEVT_AUI_FIND_MANAGER, 222, "aui_find_manager"}, {-1, 0, } }; for(int i=0; event_types[i].ev_type != -1; i++) { @@ -778,7 +778,7 @@ case 219: {// wxHtmlLinkEvent rt.addTupleCount(3); break; } -case 220: {// wxAuiNotebookEvent +case 221: {// wxAuiNotebookEvent wxAuiNotebookEvent * ev = (wxAuiNotebookEvent *) event; wxAuiNotebook * GetDragSource = ev->GetDragSource(); evClass = (char*)"wxAuiNotebookEvent"; @@ -790,7 +790,7 @@ case 220: {// wxAuiNotebookEvent rt.addTupleCount(5); break; } -case 221: {// wxAuiManagerEvent +case 222: {// wxAuiManagerEvent wxAuiManagerEvent * ev = (wxAuiManagerEvent *) event; wxAuiManager * GetManager = ev->GetManager(); wxAuiPaneInfo * GetPane = ev->GetPane(); diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index fd496c2ccc..8c056bbb91 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -18501,6 +18501,15 @@ case wxTreeCtrl_DeleteChildren: { // wxTreeCtrl::DeleteChildren This->DeleteChildren(item); break; } +case wxTreeCtrl_EditLabel: { // wxTreeCtrl::EditLabel + wxTreeCtrl *This = (wxTreeCtrl *) getPtr(bp,memenv); bp += 4; + bp += 4; /* Align */ + wxTreeItemId item = wxTreeItemId((void *) *(wxUint64 *) bp); bp += 8; + if(!This) throw wxe_badarg(0); + wxTextCtrl * Result = (wxTextCtrl*)This->EditLabel(item); + rt.addRef(getRef((void *)Result,memenv), "wxTextCtrl"); + break; +} case wxTreeCtrl_EnsureVisible: { // wxTreeCtrl::EnsureVisible wxTreeCtrl *This = (wxTreeCtrl *) getPtr(bp,memenv); bp += 4; bp += 4; /* Align */ @@ -30976,6 +30985,36 @@ case wxHtmlLinkEvent_GetLinkInfo: { // wxHtmlLinkEvent::GetLinkInfo rt.add(Result); break; } +case wxSystemSettings_GetColour: { // wxSystemSettings::GetColour + wxSystemColour index = *(wxSystemColour *) bp; bp += 4;; + wxColour Result = wxSystemSettings::GetColour((wxSystemColour) index); + rt.add(Result); + break; +} +case wxSystemSettings_GetFont: { // wxSystemSettings::GetFont + wxSystemFont index = *(wxSystemFont *) bp; bp += 4;; + wxFont * Result = new wxFont(wxSystemSettings::GetFont((wxSystemFont) index)); newPtr((void *) Result,3, memenv);; + rt.addRef(getRef((void *)Result,memenv), "wxFont"); + break; +} +case wxSystemSettings_GetMetric: { // wxSystemSettings::GetMetric + wxWindow * win=NULL; + wxSystemMetric index = *(wxSystemMetric *) bp; bp += 4;; + bp += 4; /* Align */ + while( * (int*) bp) { switch (* (int*) bp) { + case 1: {bp += 4; +win = (wxWindow *) getPtr(bp,memenv); bp += 4; + } break; + }}; + int Result = wxSystemSettings::GetMetric((wxSystemMetric) index,win); + rt.addInt(Result); + break; +} +case wxSystemSettings_GetScreenType: { // wxSystemSettings::GetScreenType + int Result = wxSystemSettings::GetScreenType(); + rt.addInt(Result); + break; +} case wxAuiNotebookEvent_SetSelection: { // wxAuiNotebookEvent::SetSelection wxAuiNotebookEvent *This = (wxAuiNotebookEvent *) getPtr(bp,memenv); bp += 4; int * s = (int *) bp; bp += 4; @@ -31110,7 +31149,7 @@ case wxAuiManagerEvent_CanVeto: { // wxAuiManagerEvent::CanVeto } case wxLogNull_new: { // wxLogNull::wxLogNull wxLogNull * Result = new wxLogNull(); - newPtr((void *) Result, 222, memenv); + newPtr((void *) Result, 223, memenv); rt.addRef(getRef((void *)Result,memenv), "wxLogNull"); break; } diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h index 415b7f0b29..4fb76f960b 100644 --- a/lib/wx/c_src/gen/wxe_macros.h +++ b/lib/wx/c_src/gen/wxe_macros.h @@ -1882,1444 +1882,1449 @@ #define wxTreeCtrl_Delete 2007 #define wxTreeCtrl_DeleteAllItems 2008 #define wxTreeCtrl_DeleteChildren 2009 -#define wxTreeCtrl_EnsureVisible 2010 -#define wxTreeCtrl_Expand 2011 -#define wxTreeCtrl_GetBoundingRect 2012 -#define wxTreeCtrl_GetChildrenCount 2014 -#define wxTreeCtrl_GetCount 2015 -#define wxTreeCtrl_GetEditControl 2016 -#define wxTreeCtrl_GetFirstChild 2017 -#define wxTreeCtrl_GetNextChild 2018 -#define wxTreeCtrl_GetFirstVisibleItem 2019 -#define wxTreeCtrl_GetImageList 2020 -#define wxTreeCtrl_GetIndent 2021 -#define wxTreeCtrl_GetItemBackgroundColour 2022 -#define wxTreeCtrl_GetItemData 2023 -#define wxTreeCtrl_GetItemFont 2024 -#define wxTreeCtrl_GetItemImage_1 2025 -#define wxTreeCtrl_GetItemImage_2 2026 -#define wxTreeCtrl_GetItemText 2027 -#define wxTreeCtrl_GetItemTextColour 2028 -#define wxTreeCtrl_GetLastChild 2029 -#define wxTreeCtrl_GetNextSibling 2030 -#define wxTreeCtrl_GetNextVisible 2031 -#define wxTreeCtrl_GetItemParent 2032 -#define wxTreeCtrl_GetPrevSibling 2033 -#define wxTreeCtrl_GetPrevVisible 2034 -#define wxTreeCtrl_GetRootItem 2035 -#define wxTreeCtrl_GetSelection 2036 -#define wxTreeCtrl_GetSelections 2037 -#define wxTreeCtrl_GetStateImageList 2038 -#define wxTreeCtrl_HitTest 2039 -#define wxTreeCtrl_InsertItem 2041 -#define wxTreeCtrl_IsBold 2042 -#define wxTreeCtrl_IsExpanded 2043 -#define wxTreeCtrl_IsSelected 2044 -#define wxTreeCtrl_IsVisible 2045 -#define wxTreeCtrl_ItemHasChildren 2046 -#define wxTreeCtrl_PrependItem 2047 -#define wxTreeCtrl_ScrollTo 2048 -#define wxTreeCtrl_SelectItem_1 2049 -#define wxTreeCtrl_SelectItem_2 2050 -#define wxTreeCtrl_SetIndent 2051 -#define wxTreeCtrl_SetImageList 2052 -#define wxTreeCtrl_SetItemBackgroundColour 2053 -#define wxTreeCtrl_SetItemBold 2054 -#define wxTreeCtrl_SetItemData 2055 -#define wxTreeCtrl_SetItemDropHighlight 2056 -#define wxTreeCtrl_SetItemFont 2057 -#define wxTreeCtrl_SetItemHasChildren 2058 -#define wxTreeCtrl_SetItemImage_2 2059 -#define wxTreeCtrl_SetItemImage_3 2060 -#define wxTreeCtrl_SetItemText 2061 -#define wxTreeCtrl_SetItemTextColour 2062 -#define wxTreeCtrl_SetStateImageList 2063 -#define wxTreeCtrl_SetWindowStyle 2064 -#define wxTreeCtrl_SortChildren 2065 -#define wxTreeCtrl_Toggle 2066 -#define wxTreeCtrl_ToggleItemSelection 2067 -#define wxTreeCtrl_Unselect 2068 -#define wxTreeCtrl_UnselectAll 2069 -#define wxTreeCtrl_UnselectItem 2070 -#define wxScrollBar_new_0 2071 -#define wxScrollBar_new_3 2072 -#define wxScrollBar_destruct 2073 -#define wxScrollBar_Create 2074 -#define wxScrollBar_GetRange 2075 -#define wxScrollBar_GetPageSize 2076 -#define wxScrollBar_GetThumbPosition 2077 -#define wxScrollBar_GetThumbSize 2078 -#define wxScrollBar_SetThumbPosition 2079 -#define wxScrollBar_SetScrollbar 2080 -#define wxSpinButton_new_2 2082 -#define wxSpinButton_new_0 2083 -#define wxSpinButton_Create 2084 -#define wxSpinButton_GetMax 2085 -#define wxSpinButton_GetMin 2086 -#define wxSpinButton_GetValue 2087 -#define wxSpinButton_SetRange 2088 -#define wxSpinButton_SetValue 2089 -#define wxSpinButton_destroy 2090 -#define wxSpinCtrl_new_0 2091 -#define wxSpinCtrl_new_2 2092 -#define wxSpinCtrl_Create 2094 -#define wxSpinCtrl_SetValue_1_1 2097 -#define wxSpinCtrl_SetValue_1_0 2098 -#define wxSpinCtrl_GetValue 2100 -#define wxSpinCtrl_SetRange 2102 -#define wxSpinCtrl_SetSelection 2103 -#define wxSpinCtrl_GetMin 2105 -#define wxSpinCtrl_GetMax 2107 -#define wxSpinCtrl_destroy 2108 -#define wxStaticText_new_0 2109 -#define wxStaticText_new_4 2110 -#define wxStaticText_Create 2111 -#define wxStaticText_GetLabel 2112 -#define wxStaticText_SetLabel 2113 -#define wxStaticText_Wrap 2114 -#define wxStaticText_destroy 2115 -#define wxStaticBitmap_new_0 2116 -#define wxStaticBitmap_new_4 2117 -#define wxStaticBitmap_Create 2118 -#define wxStaticBitmap_GetBitmap 2119 -#define wxStaticBitmap_SetBitmap 2120 -#define wxStaticBitmap_destroy 2121 -#define wxRadioBox_new 2122 -#define wxRadioBox_destruct 2124 -#define wxRadioBox_Create 2125 -#define wxRadioBox_Enable_2 2126 -#define wxRadioBox_Enable_1 2127 -#define wxRadioBox_GetSelection 2128 -#define wxRadioBox_GetString 2129 -#define wxRadioBox_SetSelection 2130 -#define wxRadioBox_Show_2 2131 -#define wxRadioBox_Show_1 2132 -#define wxRadioBox_GetColumnCount 2133 -#define wxRadioBox_GetItemHelpText 2134 -#define wxRadioBox_GetItemToolTip 2135 -#define wxRadioBox_GetItemFromPoint 2137 -#define wxRadioBox_GetRowCount 2138 -#define wxRadioBox_IsItemEnabled 2139 -#define wxRadioBox_IsItemShown 2140 -#define wxRadioBox_SetItemHelpText 2141 -#define wxRadioBox_SetItemToolTip 2142 -#define wxRadioButton_new_0 2143 -#define wxRadioButton_new_4 2144 -#define wxRadioButton_Create 2145 -#define wxRadioButton_GetValue 2146 -#define wxRadioButton_SetValue 2147 -#define wxRadioButton_destroy 2148 -#define wxSlider_new_6 2150 -#define wxSlider_new_0 2151 -#define wxSlider_Create 2152 -#define wxSlider_GetLineSize 2153 -#define wxSlider_GetMax 2154 -#define wxSlider_GetMin 2155 -#define wxSlider_GetPageSize 2156 -#define wxSlider_GetThumbLength 2157 -#define wxSlider_GetValue 2158 -#define wxSlider_SetLineSize 2159 -#define wxSlider_SetPageSize 2160 -#define wxSlider_SetRange 2161 -#define wxSlider_SetThumbLength 2162 -#define wxSlider_SetValue 2163 -#define wxSlider_destroy 2164 -#define wxDialog_new_4 2166 -#define wxDialog_new_0 2167 -#define wxDialog_destruct 2169 -#define wxDialog_Create 2170 -#define wxDialog_CreateButtonSizer 2171 -#define wxDialog_CreateStdDialogButtonSizer 2172 -#define wxDialog_EndModal 2173 -#define wxDialog_GetAffirmativeId 2174 -#define wxDialog_GetReturnCode 2175 -#define wxDialog_IsModal 2176 -#define wxDialog_SetAffirmativeId 2177 -#define wxDialog_SetReturnCode 2178 -#define wxDialog_Show 2179 -#define wxDialog_ShowModal 2180 -#define wxColourDialog_new_0 2181 -#define wxColourDialog_new_2 2182 -#define wxColourDialog_destruct 2183 -#define wxColourDialog_Create 2184 -#define wxColourDialog_GetColourData 2185 -#define wxColourData_new_0 2186 -#define wxColourData_new_1 2187 -#define wxColourData_destruct 2188 -#define wxColourData_GetChooseFull 2189 -#define wxColourData_GetColour 2190 -#define wxColourData_GetCustomColour 2192 -#define wxColourData_SetChooseFull 2193 -#define wxColourData_SetColour 2194 -#define wxColourData_SetCustomColour 2195 -#define wxPalette_new_0 2196 -#define wxPalette_new_4 2197 -#define wxPalette_destruct 2199 -#define wxPalette_Create 2200 -#define wxPalette_GetColoursCount 2201 -#define wxPalette_GetPixel 2202 -#define wxPalette_GetRGB 2203 -#define wxPalette_IsOk 2204 -#define wxDirDialog_new 2208 -#define wxDirDialog_destruct 2209 -#define wxDirDialog_GetPath 2210 -#define wxDirDialog_GetMessage 2211 -#define wxDirDialog_SetMessage 2212 -#define wxDirDialog_SetPath 2213 -#define wxFileDialog_new 2217 -#define wxFileDialog_destruct 2218 -#define wxFileDialog_GetDirectory 2219 -#define wxFileDialog_GetFilename 2220 -#define wxFileDialog_GetFilenames 2221 -#define wxFileDialog_GetFilterIndex 2222 -#define wxFileDialog_GetMessage 2223 -#define wxFileDialog_GetPath 2224 -#define wxFileDialog_GetPaths 2225 -#define wxFileDialog_GetWildcard 2226 -#define wxFileDialog_SetDirectory 2227 -#define wxFileDialog_SetFilename 2228 -#define wxFileDialog_SetFilterIndex 2229 -#define wxFileDialog_SetMessage 2230 -#define wxFileDialog_SetPath 2231 -#define wxFileDialog_SetWildcard 2232 -#define wxPickerBase_SetInternalMargin 2233 -#define wxPickerBase_GetInternalMargin 2234 -#define wxPickerBase_SetTextCtrlProportion 2235 -#define wxPickerBase_SetPickerCtrlProportion 2236 -#define wxPickerBase_GetTextCtrlProportion 2237 -#define wxPickerBase_GetPickerCtrlProportion 2238 -#define wxPickerBase_HasTextCtrl 2239 -#define wxPickerBase_GetTextCtrl 2240 -#define wxPickerBase_IsTextCtrlGrowable 2241 -#define wxPickerBase_SetPickerCtrlGrowable 2242 -#define wxPickerBase_SetTextCtrlGrowable 2243 -#define wxPickerBase_IsPickerCtrlGrowable 2244 -#define wxFilePickerCtrl_new_0 2245 -#define wxFilePickerCtrl_new_3 2246 -#define wxFilePickerCtrl_Create 2247 -#define wxFilePickerCtrl_GetPath 2248 -#define wxFilePickerCtrl_SetPath 2249 -#define wxFilePickerCtrl_destroy 2250 -#define wxDirPickerCtrl_new_0 2251 -#define wxDirPickerCtrl_new_3 2252 -#define wxDirPickerCtrl_Create 2253 -#define wxDirPickerCtrl_GetPath 2254 -#define wxDirPickerCtrl_SetPath 2255 -#define wxDirPickerCtrl_destroy 2256 -#define wxColourPickerCtrl_new_0 2257 -#define wxColourPickerCtrl_new_3 2258 -#define wxColourPickerCtrl_Create 2259 -#define wxColourPickerCtrl_GetColour 2260 -#define wxColourPickerCtrl_SetColour_1_1 2261 -#define wxColourPickerCtrl_SetColour_1_0 2262 -#define wxColourPickerCtrl_destroy 2263 -#define wxDatePickerCtrl_new_0 2264 -#define wxDatePickerCtrl_new_3 2265 -#define wxDatePickerCtrl_GetRange 2266 -#define wxDatePickerCtrl_GetValue 2267 -#define wxDatePickerCtrl_SetRange 2268 -#define wxDatePickerCtrl_SetValue 2269 -#define wxDatePickerCtrl_destroy 2270 -#define wxFontPickerCtrl_new_0 2271 -#define wxFontPickerCtrl_new_3 2272 -#define wxFontPickerCtrl_Create 2273 -#define wxFontPickerCtrl_GetSelectedFont 2274 -#define wxFontPickerCtrl_SetSelectedFont 2275 -#define wxFontPickerCtrl_GetMaxPointSize 2276 -#define wxFontPickerCtrl_SetMaxPointSize 2277 -#define wxFontPickerCtrl_destroy 2278 -#define wxFindReplaceDialog_new_0 2281 -#define wxFindReplaceDialog_new_4 2282 -#define wxFindReplaceDialog_destruct 2283 -#define wxFindReplaceDialog_Create 2284 -#define wxFindReplaceDialog_GetData 2285 -#define wxFindReplaceData_new_0 2286 -#define wxFindReplaceData_new_1 2287 -#define wxFindReplaceData_GetFindString 2288 -#define wxFindReplaceData_GetReplaceString 2289 -#define wxFindReplaceData_GetFlags 2290 -#define wxFindReplaceData_SetFlags 2291 -#define wxFindReplaceData_SetFindString 2292 -#define wxFindReplaceData_SetReplaceString 2293 -#define wxFindReplaceData_destroy 2294 -#define wxMultiChoiceDialog_new_0 2295 -#define wxMultiChoiceDialog_new_5 2297 -#define wxMultiChoiceDialog_GetSelections 2298 -#define wxMultiChoiceDialog_SetSelections 2299 -#define wxMultiChoiceDialog_destroy 2300 -#define wxSingleChoiceDialog_new_0 2301 -#define wxSingleChoiceDialog_new_5 2303 -#define wxSingleChoiceDialog_GetSelection 2304 -#define wxSingleChoiceDialog_GetStringSelection 2305 -#define wxSingleChoiceDialog_SetSelection 2306 -#define wxSingleChoiceDialog_destroy 2307 -#define wxTextEntryDialog_new 2308 -#define wxTextEntryDialog_GetValue 2309 -#define wxTextEntryDialog_SetValue 2310 -#define wxTextEntryDialog_destroy 2311 -#define wxPasswordEntryDialog_new 2312 -#define wxPasswordEntryDialog_destroy 2313 -#define wxFontData_new_0 2314 -#define wxFontData_new_1 2315 -#define wxFontData_destruct 2316 -#define wxFontData_EnableEffects 2317 -#define wxFontData_GetAllowSymbols 2318 -#define wxFontData_GetColour 2319 -#define wxFontData_GetChosenFont 2320 -#define wxFontData_GetEnableEffects 2321 -#define wxFontData_GetInitialFont 2322 -#define wxFontData_GetShowHelp 2323 -#define wxFontData_SetAllowSymbols 2324 -#define wxFontData_SetChosenFont 2325 -#define wxFontData_SetColour 2326 -#define wxFontData_SetInitialFont 2327 -#define wxFontData_SetRange 2328 -#define wxFontData_SetShowHelp 2329 -#define wxFontDialog_new_0 2333 -#define wxFontDialog_new_2 2335 -#define wxFontDialog_Create 2337 -#define wxFontDialog_GetFontData 2338 -#define wxFontDialog_destroy 2340 -#define wxProgressDialog_new 2341 -#define wxProgressDialog_destruct 2342 -#define wxProgressDialog_Resume 2343 -#define wxProgressDialog_Update_2 2344 -#define wxProgressDialog_Update_0 2345 -#define wxMessageDialog_new 2346 -#define wxMessageDialog_destruct 2347 -#define wxPageSetupDialog_new 2348 -#define wxPageSetupDialog_destruct 2349 -#define wxPageSetupDialog_GetPageSetupData 2350 -#define wxPageSetupDialog_ShowModal 2351 -#define wxPageSetupDialogData_new_0 2352 -#define wxPageSetupDialogData_new_1_0 2353 -#define wxPageSetupDialogData_new_1_1 2354 -#define wxPageSetupDialogData_destruct 2355 -#define wxPageSetupDialogData_EnableHelp 2356 -#define wxPageSetupDialogData_EnableMargins 2357 -#define wxPageSetupDialogData_EnableOrientation 2358 -#define wxPageSetupDialogData_EnablePaper 2359 -#define wxPageSetupDialogData_EnablePrinter 2360 -#define wxPageSetupDialogData_GetDefaultMinMargins 2361 -#define wxPageSetupDialogData_GetEnableMargins 2362 -#define wxPageSetupDialogData_GetEnableOrientation 2363 -#define wxPageSetupDialogData_GetEnablePaper 2364 -#define wxPageSetupDialogData_GetEnablePrinter 2365 -#define wxPageSetupDialogData_GetEnableHelp 2366 -#define wxPageSetupDialogData_GetDefaultInfo 2367 -#define wxPageSetupDialogData_GetMarginTopLeft 2368 -#define wxPageSetupDialogData_GetMarginBottomRight 2369 -#define wxPageSetupDialogData_GetMinMarginTopLeft 2370 -#define wxPageSetupDialogData_GetMinMarginBottomRight 2371 -#define wxPageSetupDialogData_GetPaperId 2372 -#define wxPageSetupDialogData_GetPaperSize 2373 -#define wxPageSetupDialogData_GetPrintData 2375 -#define wxPageSetupDialogData_IsOk 2376 -#define wxPageSetupDialogData_SetDefaultInfo 2377 -#define wxPageSetupDialogData_SetDefaultMinMargins 2378 -#define wxPageSetupDialogData_SetMarginTopLeft 2379 -#define wxPageSetupDialogData_SetMarginBottomRight 2380 -#define wxPageSetupDialogData_SetMinMarginTopLeft 2381 -#define wxPageSetupDialogData_SetMinMarginBottomRight 2382 -#define wxPageSetupDialogData_SetPaperId 2383 -#define wxPageSetupDialogData_SetPaperSize_1_1 2384 -#define wxPageSetupDialogData_SetPaperSize_1_0 2385 -#define wxPageSetupDialogData_SetPrintData 2386 -#define wxPrintDialog_new_2_0 2387 -#define wxPrintDialog_new_2_1 2388 -#define wxPrintDialog_destruct 2389 -#define wxPrintDialog_GetPrintDialogData 2390 -#define wxPrintDialog_GetPrintDC 2391 -#define wxPrintDialogData_new_0 2392 -#define wxPrintDialogData_new_1_1 2393 -#define wxPrintDialogData_new_1_0 2394 -#define wxPrintDialogData_destruct 2395 -#define wxPrintDialogData_EnableHelp 2396 -#define wxPrintDialogData_EnablePageNumbers 2397 -#define wxPrintDialogData_EnablePrintToFile 2398 -#define wxPrintDialogData_EnableSelection 2399 -#define wxPrintDialogData_GetAllPages 2400 -#define wxPrintDialogData_GetCollate 2401 -#define wxPrintDialogData_GetFromPage 2402 -#define wxPrintDialogData_GetMaxPage 2403 -#define wxPrintDialogData_GetMinPage 2404 -#define wxPrintDialogData_GetNoCopies 2405 -#define wxPrintDialogData_GetPrintData 2406 -#define wxPrintDialogData_GetPrintToFile 2407 -#define wxPrintDialogData_GetSelection 2408 -#define wxPrintDialogData_GetToPage 2409 -#define wxPrintDialogData_IsOk 2410 -#define wxPrintDialogData_SetCollate 2411 -#define wxPrintDialogData_SetFromPage 2412 -#define wxPrintDialogData_SetMaxPage 2413 -#define wxPrintDialogData_SetMinPage 2414 -#define wxPrintDialogData_SetNoCopies 2415 -#define wxPrintDialogData_SetPrintData 2416 -#define wxPrintDialogData_SetPrintToFile 2417 -#define wxPrintDialogData_SetSelection 2418 -#define wxPrintDialogData_SetToPage 2419 -#define wxPrintData_new_0 2420 -#define wxPrintData_new_1 2421 -#define wxPrintData_destruct 2422 -#define wxPrintData_GetCollate 2423 -#define wxPrintData_GetBin 2424 -#define wxPrintData_GetColour 2425 -#define wxPrintData_GetDuplex 2426 -#define wxPrintData_GetNoCopies 2427 -#define wxPrintData_GetOrientation 2428 -#define wxPrintData_GetPaperId 2429 -#define wxPrintData_GetPrinterName 2430 -#define wxPrintData_GetQuality 2431 -#define wxPrintData_IsOk 2432 -#define wxPrintData_SetBin 2433 -#define wxPrintData_SetCollate 2434 -#define wxPrintData_SetColour 2435 -#define wxPrintData_SetDuplex 2436 -#define wxPrintData_SetNoCopies 2437 -#define wxPrintData_SetOrientation 2438 -#define wxPrintData_SetPaperId 2439 -#define wxPrintData_SetPrinterName 2440 -#define wxPrintData_SetQuality 2441 -#define wxPrintPreview_new_2 2444 -#define wxPrintPreview_new_3 2445 -#define wxPrintPreview_destruct 2447 -#define wxPrintPreview_GetCanvas 2448 -#define wxPrintPreview_GetCurrentPage 2449 -#define wxPrintPreview_GetFrame 2450 -#define wxPrintPreview_GetMaxPage 2451 -#define wxPrintPreview_GetMinPage 2452 -#define wxPrintPreview_GetPrintout 2453 -#define wxPrintPreview_GetPrintoutForPrinting 2454 -#define wxPrintPreview_IsOk 2455 -#define wxPrintPreview_PaintPage 2456 -#define wxPrintPreview_Print 2457 -#define wxPrintPreview_RenderPage 2458 -#define wxPrintPreview_SetCanvas 2459 -#define wxPrintPreview_SetCurrentPage 2460 -#define wxPrintPreview_SetFrame 2461 -#define wxPrintPreview_SetPrintout 2462 -#define wxPrintPreview_SetZoom 2463 -#define wxPreviewFrame_new 2464 -#define wxPreviewFrame_destruct 2465 -#define wxPreviewFrame_CreateControlBar 2466 -#define wxPreviewFrame_CreateCanvas 2467 -#define wxPreviewFrame_Initialize 2468 -#define wxPreviewFrame_OnCloseWindow 2469 -#define wxPreviewControlBar_new 2470 -#define wxPreviewControlBar_destruct 2471 -#define wxPreviewControlBar_CreateButtons 2472 -#define wxPreviewControlBar_GetPrintPreview 2473 -#define wxPreviewControlBar_GetZoomControl 2474 -#define wxPreviewControlBar_SetZoomControl 2475 -#define wxPrinter_new 2477 -#define wxPrinter_CreateAbortWindow 2478 -#define wxPrinter_GetAbort 2479 -#define wxPrinter_GetLastError 2480 -#define wxPrinter_GetPrintDialogData 2481 -#define wxPrinter_Print 2482 -#define wxPrinter_PrintDialog 2483 -#define wxPrinter_ReportError 2484 -#define wxPrinter_Setup 2485 -#define wxPrinter_destroy 2486 -#define wxXmlResource_new_1 2487 -#define wxXmlResource_new_2 2488 -#define wxXmlResource_destruct 2489 -#define wxXmlResource_AttachUnknownControl 2490 -#define wxXmlResource_ClearHandlers 2491 -#define wxXmlResource_CompareVersion 2492 -#define wxXmlResource_Get 2493 -#define wxXmlResource_GetFlags 2494 -#define wxXmlResource_GetVersion 2495 -#define wxXmlResource_GetXRCID 2496 -#define wxXmlResource_InitAllHandlers 2497 -#define wxXmlResource_Load 2498 -#define wxXmlResource_LoadBitmap 2499 -#define wxXmlResource_LoadDialog_2 2500 -#define wxXmlResource_LoadDialog_3 2501 -#define wxXmlResource_LoadFrame_2 2502 -#define wxXmlResource_LoadFrame_3 2503 -#define wxXmlResource_LoadIcon 2504 -#define wxXmlResource_LoadMenu 2505 -#define wxXmlResource_LoadMenuBar_2 2506 -#define wxXmlResource_LoadMenuBar_1 2507 -#define wxXmlResource_LoadPanel_2 2508 -#define wxXmlResource_LoadPanel_3 2509 -#define wxXmlResource_LoadToolBar 2510 -#define wxXmlResource_Set 2511 -#define wxXmlResource_SetFlags 2512 -#define wxXmlResource_Unload 2513 -#define wxXmlResource_xrcctrl 2514 -#define wxHtmlEasyPrinting_new 2515 -#define wxHtmlEasyPrinting_destruct 2516 -#define wxHtmlEasyPrinting_GetPrintData 2517 -#define wxHtmlEasyPrinting_GetPageSetupData 2518 -#define wxHtmlEasyPrinting_PreviewFile 2519 -#define wxHtmlEasyPrinting_PreviewText 2520 -#define wxHtmlEasyPrinting_PrintFile 2521 -#define wxHtmlEasyPrinting_PrintText 2522 -#define wxHtmlEasyPrinting_PageSetup 2523 -#define wxHtmlEasyPrinting_SetFonts 2524 -#define wxHtmlEasyPrinting_SetHeader 2525 -#define wxHtmlEasyPrinting_SetFooter 2526 -#define wxGLCanvas_new_2 2528 -#define wxGLCanvas_new_3_1 2529 -#define wxGLCanvas_new_3_0 2530 -#define wxGLCanvas_GetContext 2531 -#define wxGLCanvas_SetCurrent 2533 -#define wxGLCanvas_SwapBuffers 2534 -#define wxGLCanvas_destroy 2535 -#define wxAuiManager_new 2536 -#define wxAuiManager_destruct 2537 -#define wxAuiManager_AddPane_2_1 2538 -#define wxAuiManager_AddPane_3 2539 -#define wxAuiManager_AddPane_2_0 2540 -#define wxAuiManager_DetachPane 2541 -#define wxAuiManager_GetAllPanes 2542 -#define wxAuiManager_GetArtProvider 2543 -#define wxAuiManager_GetDockSizeConstraint 2544 -#define wxAuiManager_GetFlags 2545 -#define wxAuiManager_GetManagedWindow 2546 -#define wxAuiManager_GetManager 2547 -#define wxAuiManager_GetPane_1_1 2548 -#define wxAuiManager_GetPane_1_0 2549 -#define wxAuiManager_HideHint 2550 -#define wxAuiManager_InsertPane 2551 -#define wxAuiManager_LoadPaneInfo 2552 -#define wxAuiManager_LoadPerspective 2553 -#define wxAuiManager_SavePaneInfo 2554 -#define wxAuiManager_SavePerspective 2555 -#define wxAuiManager_SetArtProvider 2556 -#define wxAuiManager_SetDockSizeConstraint 2557 -#define wxAuiManager_SetFlags 2558 -#define wxAuiManager_SetManagedWindow 2559 -#define wxAuiManager_ShowHint 2560 -#define wxAuiManager_UnInit 2561 -#define wxAuiManager_Update 2562 -#define wxAuiPaneInfo_new_0 2563 -#define wxAuiPaneInfo_new_1 2564 -#define wxAuiPaneInfo_destruct 2565 -#define wxAuiPaneInfo_BestSize_1 2566 -#define wxAuiPaneInfo_BestSize_2 2567 -#define wxAuiPaneInfo_Bottom 2568 -#define wxAuiPaneInfo_BottomDockable 2569 -#define wxAuiPaneInfo_Caption 2570 -#define wxAuiPaneInfo_CaptionVisible 2571 -#define wxAuiPaneInfo_Centre 2572 -#define wxAuiPaneInfo_CentrePane 2573 -#define wxAuiPaneInfo_CloseButton 2574 -#define wxAuiPaneInfo_DefaultPane 2575 -#define wxAuiPaneInfo_DestroyOnClose 2576 -#define wxAuiPaneInfo_Direction 2577 -#define wxAuiPaneInfo_Dock 2578 -#define wxAuiPaneInfo_Dockable 2579 -#define wxAuiPaneInfo_Fixed 2580 -#define wxAuiPaneInfo_Float 2581 -#define wxAuiPaneInfo_Floatable 2582 -#define wxAuiPaneInfo_FloatingPosition_1 2583 -#define wxAuiPaneInfo_FloatingPosition_2 2584 -#define wxAuiPaneInfo_FloatingSize_1 2585 -#define wxAuiPaneInfo_FloatingSize_2 2586 -#define wxAuiPaneInfo_Gripper 2587 -#define wxAuiPaneInfo_GripperTop 2588 -#define wxAuiPaneInfo_HasBorder 2589 -#define wxAuiPaneInfo_HasCaption 2590 -#define wxAuiPaneInfo_HasCloseButton 2591 -#define wxAuiPaneInfo_HasFlag 2592 -#define wxAuiPaneInfo_HasGripper 2593 -#define wxAuiPaneInfo_HasGripperTop 2594 -#define wxAuiPaneInfo_HasMaximizeButton 2595 -#define wxAuiPaneInfo_HasMinimizeButton 2596 -#define wxAuiPaneInfo_HasPinButton 2597 -#define wxAuiPaneInfo_Hide 2598 -#define wxAuiPaneInfo_IsBottomDockable 2599 -#define wxAuiPaneInfo_IsDocked 2600 -#define wxAuiPaneInfo_IsFixed 2601 -#define wxAuiPaneInfo_IsFloatable 2602 -#define wxAuiPaneInfo_IsFloating 2603 -#define wxAuiPaneInfo_IsLeftDockable 2604 -#define wxAuiPaneInfo_IsMovable 2605 -#define wxAuiPaneInfo_IsOk 2606 -#define wxAuiPaneInfo_IsResizable 2607 -#define wxAuiPaneInfo_IsRightDockable 2608 -#define wxAuiPaneInfo_IsShown 2609 -#define wxAuiPaneInfo_IsToolbar 2610 -#define wxAuiPaneInfo_IsTopDockable 2611 -#define wxAuiPaneInfo_Layer 2612 -#define wxAuiPaneInfo_Left 2613 -#define wxAuiPaneInfo_LeftDockable 2614 -#define wxAuiPaneInfo_MaxSize_1 2615 -#define wxAuiPaneInfo_MaxSize_2 2616 -#define wxAuiPaneInfo_MaximizeButton 2617 -#define wxAuiPaneInfo_MinSize_1 2618 -#define wxAuiPaneInfo_MinSize_2 2619 -#define wxAuiPaneInfo_MinimizeButton 2620 -#define wxAuiPaneInfo_Movable 2621 -#define wxAuiPaneInfo_Name 2622 -#define wxAuiPaneInfo_PaneBorder 2623 -#define wxAuiPaneInfo_PinButton 2624 -#define wxAuiPaneInfo_Position 2625 -#define wxAuiPaneInfo_Resizable 2626 -#define wxAuiPaneInfo_Right 2627 -#define wxAuiPaneInfo_RightDockable 2628 -#define wxAuiPaneInfo_Row 2629 -#define wxAuiPaneInfo_SafeSet 2630 -#define wxAuiPaneInfo_SetFlag 2631 -#define wxAuiPaneInfo_Show 2632 -#define wxAuiPaneInfo_ToolbarPane 2633 -#define wxAuiPaneInfo_Top 2634 -#define wxAuiPaneInfo_TopDockable 2635 -#define wxAuiPaneInfo_Window 2636 -#define wxAuiNotebook_new_0 2637 -#define wxAuiNotebook_new_2 2638 -#define wxAuiNotebook_AddPage 2639 -#define wxAuiNotebook_Create 2640 -#define wxAuiNotebook_DeletePage 2641 -#define wxAuiNotebook_GetArtProvider 2642 -#define wxAuiNotebook_GetPage 2643 -#define wxAuiNotebook_GetPageBitmap 2644 -#define wxAuiNotebook_GetPageCount 2645 -#define wxAuiNotebook_GetPageIndex 2646 -#define wxAuiNotebook_GetPageText 2647 -#define wxAuiNotebook_GetSelection 2648 -#define wxAuiNotebook_InsertPage 2649 -#define wxAuiNotebook_RemovePage 2650 -#define wxAuiNotebook_SetArtProvider 2651 -#define wxAuiNotebook_SetFont 2652 -#define wxAuiNotebook_SetPageBitmap 2653 -#define wxAuiNotebook_SetPageText 2654 -#define wxAuiNotebook_SetSelection 2655 -#define wxAuiNotebook_SetTabCtrlHeight 2656 -#define wxAuiNotebook_SetUniformBitmapSize 2657 -#define wxAuiNotebook_destroy 2658 -#define wxMDIParentFrame_new_0 2659 -#define wxMDIParentFrame_new_4 2660 -#define wxMDIParentFrame_destruct 2661 -#define wxMDIParentFrame_ActivateNext 2662 -#define wxMDIParentFrame_ActivatePrevious 2663 -#define wxMDIParentFrame_ArrangeIcons 2664 -#define wxMDIParentFrame_Cascade 2665 -#define wxMDIParentFrame_Create 2666 -#define wxMDIParentFrame_GetActiveChild 2667 -#define wxMDIParentFrame_GetClientWindow 2668 -#define wxMDIParentFrame_Tile 2669 -#define wxMDIChildFrame_new_0 2670 -#define wxMDIChildFrame_new_4 2671 -#define wxMDIChildFrame_destruct 2672 -#define wxMDIChildFrame_Activate 2673 -#define wxMDIChildFrame_Create 2674 -#define wxMDIChildFrame_Maximize 2675 -#define wxMDIChildFrame_Restore 2676 -#define wxMDIClientWindow_new_0 2677 -#define wxMDIClientWindow_new_2 2678 -#define wxMDIClientWindow_destruct 2679 -#define wxMDIClientWindow_CreateClient 2680 -#define wxLayoutAlgorithm_new 2681 -#define wxLayoutAlgorithm_LayoutFrame 2682 -#define wxLayoutAlgorithm_LayoutMDIFrame 2683 -#define wxLayoutAlgorithm_LayoutWindow 2684 -#define wxLayoutAlgorithm_destroy 2685 -#define wxEvent_GetId 2686 -#define wxEvent_GetSkipped 2687 -#define wxEvent_GetTimestamp 2688 -#define wxEvent_IsCommandEvent 2689 -#define wxEvent_ResumePropagation 2690 -#define wxEvent_ShouldPropagate 2691 -#define wxEvent_Skip 2692 -#define wxEvent_StopPropagation 2693 -#define wxCommandEvent_getClientData 2694 -#define wxCommandEvent_GetExtraLong 2695 -#define wxCommandEvent_GetInt 2696 -#define wxCommandEvent_GetSelection 2697 -#define wxCommandEvent_GetString 2698 -#define wxCommandEvent_IsChecked 2699 -#define wxCommandEvent_IsSelection 2700 -#define wxCommandEvent_SetInt 2701 -#define wxCommandEvent_SetString 2702 -#define wxScrollEvent_GetOrientation 2703 -#define wxScrollEvent_GetPosition 2704 -#define wxScrollWinEvent_GetOrientation 2705 -#define wxScrollWinEvent_GetPosition 2706 -#define wxMouseEvent_AltDown 2707 -#define wxMouseEvent_Button 2708 -#define wxMouseEvent_ButtonDClick 2709 -#define wxMouseEvent_ButtonDown 2710 -#define wxMouseEvent_ButtonUp 2711 -#define wxMouseEvent_CmdDown 2712 -#define wxMouseEvent_ControlDown 2713 -#define wxMouseEvent_Dragging 2714 -#define wxMouseEvent_Entering 2715 -#define wxMouseEvent_GetButton 2716 -#define wxMouseEvent_GetPosition 2719 -#define wxMouseEvent_GetLogicalPosition 2720 -#define wxMouseEvent_GetLinesPerAction 2721 -#define wxMouseEvent_GetWheelRotation 2722 -#define wxMouseEvent_GetWheelDelta 2723 -#define wxMouseEvent_GetX 2724 -#define wxMouseEvent_GetY 2725 -#define wxMouseEvent_IsButton 2726 -#define wxMouseEvent_IsPageScroll 2727 -#define wxMouseEvent_Leaving 2728 -#define wxMouseEvent_LeftDClick 2729 -#define wxMouseEvent_LeftDown 2730 -#define wxMouseEvent_LeftIsDown 2731 -#define wxMouseEvent_LeftUp 2732 -#define wxMouseEvent_MetaDown 2733 -#define wxMouseEvent_MiddleDClick 2734 -#define wxMouseEvent_MiddleDown 2735 -#define wxMouseEvent_MiddleIsDown 2736 -#define wxMouseEvent_MiddleUp 2737 -#define wxMouseEvent_Moving 2738 -#define wxMouseEvent_RightDClick 2739 -#define wxMouseEvent_RightDown 2740 -#define wxMouseEvent_RightIsDown 2741 -#define wxMouseEvent_RightUp 2742 -#define wxMouseEvent_ShiftDown 2743 -#define wxSetCursorEvent_GetCursor 2744 -#define wxSetCursorEvent_GetX 2745 -#define wxSetCursorEvent_GetY 2746 -#define wxSetCursorEvent_HasCursor 2747 -#define wxSetCursorEvent_SetCursor 2748 -#define wxKeyEvent_AltDown 2749 -#define wxKeyEvent_CmdDown 2750 -#define wxKeyEvent_ControlDown 2751 -#define wxKeyEvent_GetKeyCode 2752 -#define wxKeyEvent_GetModifiers 2753 -#define wxKeyEvent_GetPosition 2756 -#define wxKeyEvent_GetRawKeyCode 2757 -#define wxKeyEvent_GetRawKeyFlags 2758 -#define wxKeyEvent_GetUnicodeKey 2759 -#define wxKeyEvent_GetX 2760 -#define wxKeyEvent_GetY 2761 -#define wxKeyEvent_HasModifiers 2762 -#define wxKeyEvent_MetaDown 2763 -#define wxKeyEvent_ShiftDown 2764 -#define wxSizeEvent_GetSize 2765 -#define wxMoveEvent_GetPosition 2766 -#define wxEraseEvent_GetDC 2767 -#define wxFocusEvent_GetWindow 2768 -#define wxChildFocusEvent_GetWindow 2769 -#define wxMenuEvent_GetMenu 2770 -#define wxMenuEvent_GetMenuId 2771 -#define wxMenuEvent_IsPopup 2772 -#define wxCloseEvent_CanVeto 2773 -#define wxCloseEvent_GetLoggingOff 2774 -#define wxCloseEvent_SetCanVeto 2775 -#define wxCloseEvent_SetLoggingOff 2776 -#define wxCloseEvent_Veto 2777 -#define wxShowEvent_SetShow 2778 -#define wxShowEvent_GetShow 2779 -#define wxIconizeEvent_Iconized 2780 -#define wxJoystickEvent_ButtonDown 2781 -#define wxJoystickEvent_ButtonIsDown 2782 -#define wxJoystickEvent_ButtonUp 2783 -#define wxJoystickEvent_GetButtonChange 2784 -#define wxJoystickEvent_GetButtonState 2785 -#define wxJoystickEvent_GetJoystick 2786 -#define wxJoystickEvent_GetPosition 2787 -#define wxJoystickEvent_GetZPosition 2788 -#define wxJoystickEvent_IsButton 2789 -#define wxJoystickEvent_IsMove 2790 -#define wxJoystickEvent_IsZMove 2791 -#define wxUpdateUIEvent_CanUpdate 2792 -#define wxUpdateUIEvent_Check 2793 -#define wxUpdateUIEvent_Enable 2794 -#define wxUpdateUIEvent_Show 2795 -#define wxUpdateUIEvent_GetChecked 2796 -#define wxUpdateUIEvent_GetEnabled 2797 -#define wxUpdateUIEvent_GetShown 2798 -#define wxUpdateUIEvent_GetSetChecked 2799 -#define wxUpdateUIEvent_GetSetEnabled 2800 -#define wxUpdateUIEvent_GetSetShown 2801 -#define wxUpdateUIEvent_GetSetText 2802 -#define wxUpdateUIEvent_GetText 2803 -#define wxUpdateUIEvent_GetMode 2804 -#define wxUpdateUIEvent_GetUpdateInterval 2805 -#define wxUpdateUIEvent_ResetUpdateTime 2806 -#define wxUpdateUIEvent_SetMode 2807 -#define wxUpdateUIEvent_SetText 2808 -#define wxUpdateUIEvent_SetUpdateInterval 2809 -#define wxMouseCaptureChangedEvent_GetCapturedWindow 2810 -#define wxPaletteChangedEvent_SetChangedWindow 2811 -#define wxPaletteChangedEvent_GetChangedWindow 2812 -#define wxQueryNewPaletteEvent_SetPaletteRealized 2813 -#define wxQueryNewPaletteEvent_GetPaletteRealized 2814 -#define wxNavigationKeyEvent_GetDirection 2815 -#define wxNavigationKeyEvent_SetDirection 2816 -#define wxNavigationKeyEvent_IsWindowChange 2817 -#define wxNavigationKeyEvent_SetWindowChange 2818 -#define wxNavigationKeyEvent_IsFromTab 2819 -#define wxNavigationKeyEvent_SetFromTab 2820 -#define wxNavigationKeyEvent_GetCurrentFocus 2821 -#define wxNavigationKeyEvent_SetCurrentFocus 2822 -#define wxHelpEvent_GetOrigin 2823 -#define wxHelpEvent_GetPosition 2824 -#define wxHelpEvent_SetOrigin 2825 -#define wxHelpEvent_SetPosition 2826 -#define wxContextMenuEvent_GetPosition 2827 -#define wxContextMenuEvent_SetPosition 2828 -#define wxIdleEvent_CanSend 2829 -#define wxIdleEvent_GetMode 2830 -#define wxIdleEvent_RequestMore 2831 -#define wxIdleEvent_MoreRequested 2832 -#define wxIdleEvent_SetMode 2833 -#define wxGridEvent_AltDown 2834 -#define wxGridEvent_ControlDown 2835 -#define wxGridEvent_GetCol 2836 -#define wxGridEvent_GetPosition 2837 -#define wxGridEvent_GetRow 2838 -#define wxGridEvent_MetaDown 2839 -#define wxGridEvent_Selecting 2840 -#define wxGridEvent_ShiftDown 2841 -#define wxNotifyEvent_Allow 2842 -#define wxNotifyEvent_IsAllowed 2843 -#define wxNotifyEvent_Veto 2844 -#define wxSashEvent_GetEdge 2845 -#define wxSashEvent_GetDragRect 2846 -#define wxSashEvent_GetDragStatus 2847 -#define wxListEvent_GetCacheFrom 2848 -#define wxListEvent_GetCacheTo 2849 -#define wxListEvent_GetKeyCode 2850 -#define wxListEvent_GetIndex 2851 -#define wxListEvent_GetColumn 2852 -#define wxListEvent_GetPoint 2853 -#define wxListEvent_GetLabel 2854 -#define wxListEvent_GetText 2855 -#define wxListEvent_GetImage 2856 -#define wxListEvent_GetData 2857 -#define wxListEvent_GetMask 2858 -#define wxListEvent_GetItem 2859 -#define wxListEvent_IsEditCancelled 2860 -#define wxDateEvent_GetDate 2861 -#define wxCalendarEvent_GetWeekDay 2862 -#define wxFileDirPickerEvent_GetPath 2863 -#define wxColourPickerEvent_GetColour 2864 -#define wxFontPickerEvent_GetFont 2865 -#define wxStyledTextEvent_GetPosition 2866 -#define wxStyledTextEvent_GetKey 2867 -#define wxStyledTextEvent_GetModifiers 2868 -#define wxStyledTextEvent_GetModificationType 2869 -#define wxStyledTextEvent_GetText 2870 -#define wxStyledTextEvent_GetLength 2871 -#define wxStyledTextEvent_GetLinesAdded 2872 -#define wxStyledTextEvent_GetLine 2873 -#define wxStyledTextEvent_GetFoldLevelNow 2874 -#define wxStyledTextEvent_GetFoldLevelPrev 2875 -#define wxStyledTextEvent_GetMargin 2876 -#define wxStyledTextEvent_GetMessage 2877 -#define wxStyledTextEvent_GetWParam 2878 -#define wxStyledTextEvent_GetLParam 2879 -#define wxStyledTextEvent_GetListType 2880 -#define wxStyledTextEvent_GetX 2881 -#define wxStyledTextEvent_GetY 2882 -#define wxStyledTextEvent_GetDragText 2883 -#define wxStyledTextEvent_GetDragAllowMove 2884 -#define wxStyledTextEvent_GetDragResult 2885 -#define wxStyledTextEvent_GetShift 2886 -#define wxStyledTextEvent_GetControl 2887 -#define wxStyledTextEvent_GetAlt 2888 -#define utils_wxGetKeyState 2889 -#define utils_wxGetMousePosition 2890 -#define utils_wxGetMouseState 2891 -#define utils_wxSetDetectableAutoRepeat 2892 -#define utils_wxBell 2893 -#define utils_wxFindMenuItemId 2894 -#define utils_wxGenericFindWindowAtPoint 2895 -#define utils_wxFindWindowAtPoint 2896 -#define utils_wxBeginBusyCursor 2897 -#define utils_wxEndBusyCursor 2898 -#define utils_wxIsBusy 2899 -#define utils_wxShutdown 2900 -#define utils_wxShell 2901 -#define utils_wxLaunchDefaultBrowser 2902 -#define utils_wxGetEmailAddress 2903 -#define utils_wxGetUserId 2904 -#define utils_wxGetHomeDir 2905 -#define utils_wxNewId 2906 -#define utils_wxRegisterId 2907 -#define utils_wxGetCurrentId 2908 -#define utils_wxGetOsDescription 2909 -#define utils_wxIsPlatformLittleEndian 2910 -#define utils_wxIsPlatform64Bit 2911 -#define wxPrintout_new 2912 -#define wxPrintout_destruct 2913 -#define wxPrintout_GetDC 2914 -#define wxPrintout_GetPageSizeMM 2915 -#define wxPrintout_GetPageSizePixels 2916 -#define wxPrintout_GetPaperRectPixels 2917 -#define wxPrintout_GetPPIPrinter 2918 -#define wxPrintout_GetPPIScreen 2919 -#define wxPrintout_GetTitle 2920 -#define wxPrintout_IsPreview 2921 -#define wxPrintout_FitThisSizeToPaper 2922 -#define wxPrintout_FitThisSizeToPage 2923 -#define wxPrintout_FitThisSizeToPageMargins 2924 -#define wxPrintout_MapScreenSizeToPaper 2925 -#define wxPrintout_MapScreenSizeToPage 2926 -#define wxPrintout_MapScreenSizeToPageMargins 2927 -#define wxPrintout_MapScreenSizeToDevice 2928 -#define wxPrintout_GetLogicalPaperRect 2929 -#define wxPrintout_GetLogicalPageRect 2930 -#define wxPrintout_GetLogicalPageMarginsRect 2931 -#define wxPrintout_SetLogicalOrigin 2932 -#define wxPrintout_OffsetLogicalOrigin 2933 -#define wxStyledTextCtrl_new_2 2934 -#define wxStyledTextCtrl_new_0 2935 -#define wxStyledTextCtrl_destruct 2936 -#define wxStyledTextCtrl_Create 2937 -#define wxStyledTextCtrl_AddText 2938 -#define wxStyledTextCtrl_AddStyledText 2939 -#define wxStyledTextCtrl_InsertText 2940 -#define wxStyledTextCtrl_ClearAll 2941 -#define wxStyledTextCtrl_ClearDocumentStyle 2942 -#define wxStyledTextCtrl_GetLength 2943 -#define wxStyledTextCtrl_GetCharAt 2944 -#define wxStyledTextCtrl_GetCurrentPos 2945 -#define wxStyledTextCtrl_GetAnchor 2946 -#define wxStyledTextCtrl_GetStyleAt 2947 -#define wxStyledTextCtrl_Redo 2948 -#define wxStyledTextCtrl_SetUndoCollection 2949 -#define wxStyledTextCtrl_SelectAll 2950 -#define wxStyledTextCtrl_SetSavePoint 2951 -#define wxStyledTextCtrl_GetStyledText 2952 -#define wxStyledTextCtrl_CanRedo 2953 -#define wxStyledTextCtrl_MarkerLineFromHandle 2954 -#define wxStyledTextCtrl_MarkerDeleteHandle 2955 -#define wxStyledTextCtrl_GetUndoCollection 2956 -#define wxStyledTextCtrl_GetViewWhiteSpace 2957 -#define wxStyledTextCtrl_SetViewWhiteSpace 2958 -#define wxStyledTextCtrl_PositionFromPoint 2959 -#define wxStyledTextCtrl_PositionFromPointClose 2960 -#define wxStyledTextCtrl_GotoLine 2961 -#define wxStyledTextCtrl_GotoPos 2962 -#define wxStyledTextCtrl_SetAnchor 2963 -#define wxStyledTextCtrl_GetCurLine 2964 -#define wxStyledTextCtrl_GetEndStyled 2965 -#define wxStyledTextCtrl_ConvertEOLs 2966 -#define wxStyledTextCtrl_GetEOLMode 2967 -#define wxStyledTextCtrl_SetEOLMode 2968 -#define wxStyledTextCtrl_StartStyling 2969 -#define wxStyledTextCtrl_SetStyling 2970 -#define wxStyledTextCtrl_GetBufferedDraw 2971 -#define wxStyledTextCtrl_SetBufferedDraw 2972 -#define wxStyledTextCtrl_SetTabWidth 2973 -#define wxStyledTextCtrl_GetTabWidth 2974 -#define wxStyledTextCtrl_SetCodePage 2975 -#define wxStyledTextCtrl_MarkerDefine 2976 -#define wxStyledTextCtrl_MarkerSetForeground 2977 -#define wxStyledTextCtrl_MarkerSetBackground 2978 -#define wxStyledTextCtrl_MarkerAdd 2979 -#define wxStyledTextCtrl_MarkerDelete 2980 -#define wxStyledTextCtrl_MarkerDeleteAll 2981 -#define wxStyledTextCtrl_MarkerGet 2982 -#define wxStyledTextCtrl_MarkerNext 2983 -#define wxStyledTextCtrl_MarkerPrevious 2984 -#define wxStyledTextCtrl_MarkerDefineBitmap 2985 -#define wxStyledTextCtrl_MarkerAddSet 2986 -#define wxStyledTextCtrl_MarkerSetAlpha 2987 -#define wxStyledTextCtrl_SetMarginType 2988 -#define wxStyledTextCtrl_GetMarginType 2989 -#define wxStyledTextCtrl_SetMarginWidth 2990 -#define wxStyledTextCtrl_GetMarginWidth 2991 -#define wxStyledTextCtrl_SetMarginMask 2992 -#define wxStyledTextCtrl_GetMarginMask 2993 -#define wxStyledTextCtrl_SetMarginSensitive 2994 -#define wxStyledTextCtrl_GetMarginSensitive 2995 -#define wxStyledTextCtrl_StyleClearAll 2996 -#define wxStyledTextCtrl_StyleSetForeground 2997 -#define wxStyledTextCtrl_StyleSetBackground 2998 -#define wxStyledTextCtrl_StyleSetBold 2999 -#define wxStyledTextCtrl_StyleSetItalic 3000 -#define wxStyledTextCtrl_StyleSetSize 3001 -#define wxStyledTextCtrl_StyleSetFaceName 3002 -#define wxStyledTextCtrl_StyleSetEOLFilled 3003 -#define wxStyledTextCtrl_StyleResetDefault 3004 -#define wxStyledTextCtrl_StyleSetUnderline 3005 -#define wxStyledTextCtrl_StyleSetCase 3006 -#define wxStyledTextCtrl_StyleSetHotSpot 3007 -#define wxStyledTextCtrl_SetSelForeground 3008 -#define wxStyledTextCtrl_SetSelBackground 3009 -#define wxStyledTextCtrl_GetSelAlpha 3010 -#define wxStyledTextCtrl_SetSelAlpha 3011 -#define wxStyledTextCtrl_SetCaretForeground 3012 -#define wxStyledTextCtrl_CmdKeyAssign 3013 -#define wxStyledTextCtrl_CmdKeyClear 3014 -#define wxStyledTextCtrl_CmdKeyClearAll 3015 -#define wxStyledTextCtrl_SetStyleBytes 3016 -#define wxStyledTextCtrl_StyleSetVisible 3017 -#define wxStyledTextCtrl_GetCaretPeriod 3018 -#define wxStyledTextCtrl_SetCaretPeriod 3019 -#define wxStyledTextCtrl_SetWordChars 3020 -#define wxStyledTextCtrl_BeginUndoAction 3021 -#define wxStyledTextCtrl_EndUndoAction 3022 -#define wxStyledTextCtrl_IndicatorSetStyle 3023 -#define wxStyledTextCtrl_IndicatorGetStyle 3024 -#define wxStyledTextCtrl_IndicatorSetForeground 3025 -#define wxStyledTextCtrl_IndicatorGetForeground 3026 -#define wxStyledTextCtrl_SetWhitespaceForeground 3027 -#define wxStyledTextCtrl_SetWhitespaceBackground 3028 -#define wxStyledTextCtrl_GetStyleBits 3029 -#define wxStyledTextCtrl_SetLineState 3030 -#define wxStyledTextCtrl_GetLineState 3031 -#define wxStyledTextCtrl_GetMaxLineState 3032 -#define wxStyledTextCtrl_GetCaretLineVisible 3033 -#define wxStyledTextCtrl_SetCaretLineVisible 3034 -#define wxStyledTextCtrl_GetCaretLineBackground 3035 -#define wxStyledTextCtrl_SetCaretLineBackground 3036 -#define wxStyledTextCtrl_AutoCompShow 3037 -#define wxStyledTextCtrl_AutoCompCancel 3038 -#define wxStyledTextCtrl_AutoCompActive 3039 -#define wxStyledTextCtrl_AutoCompPosStart 3040 -#define wxStyledTextCtrl_AutoCompComplete 3041 -#define wxStyledTextCtrl_AutoCompStops 3042 -#define wxStyledTextCtrl_AutoCompSetSeparator 3043 -#define wxStyledTextCtrl_AutoCompGetSeparator 3044 -#define wxStyledTextCtrl_AutoCompSelect 3045 -#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3046 -#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3047 -#define wxStyledTextCtrl_AutoCompSetFillUps 3048 -#define wxStyledTextCtrl_AutoCompSetChooseSingle 3049 -#define wxStyledTextCtrl_AutoCompGetChooseSingle 3050 -#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3051 -#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3052 -#define wxStyledTextCtrl_UserListShow 3053 -#define wxStyledTextCtrl_AutoCompSetAutoHide 3054 -#define wxStyledTextCtrl_AutoCompGetAutoHide 3055 -#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3056 -#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3057 -#define wxStyledTextCtrl_RegisterImage 3058 -#define wxStyledTextCtrl_ClearRegisteredImages 3059 -#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3060 -#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3061 -#define wxStyledTextCtrl_AutoCompSetMaxWidth 3062 -#define wxStyledTextCtrl_AutoCompGetMaxWidth 3063 -#define wxStyledTextCtrl_AutoCompSetMaxHeight 3064 -#define wxStyledTextCtrl_AutoCompGetMaxHeight 3065 -#define wxStyledTextCtrl_SetIndent 3066 -#define wxStyledTextCtrl_GetIndent 3067 -#define wxStyledTextCtrl_SetUseTabs 3068 -#define wxStyledTextCtrl_GetUseTabs 3069 -#define wxStyledTextCtrl_SetLineIndentation 3070 -#define wxStyledTextCtrl_GetLineIndentation 3071 -#define wxStyledTextCtrl_GetLineIndentPosition 3072 -#define wxStyledTextCtrl_GetColumn 3073 -#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3074 -#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3075 -#define wxStyledTextCtrl_SetIndentationGuides 3076 -#define wxStyledTextCtrl_GetIndentationGuides 3077 -#define wxStyledTextCtrl_SetHighlightGuide 3078 -#define wxStyledTextCtrl_GetHighlightGuide 3079 -#define wxStyledTextCtrl_GetLineEndPosition 3080 -#define wxStyledTextCtrl_GetCodePage 3081 -#define wxStyledTextCtrl_GetCaretForeground 3082 -#define wxStyledTextCtrl_GetReadOnly 3083 -#define wxStyledTextCtrl_SetCurrentPos 3084 -#define wxStyledTextCtrl_SetSelectionStart 3085 -#define wxStyledTextCtrl_GetSelectionStart 3086 -#define wxStyledTextCtrl_SetSelectionEnd 3087 -#define wxStyledTextCtrl_GetSelectionEnd 3088 -#define wxStyledTextCtrl_SetPrintMagnification 3089 -#define wxStyledTextCtrl_GetPrintMagnification 3090 -#define wxStyledTextCtrl_SetPrintColourMode 3091 -#define wxStyledTextCtrl_GetPrintColourMode 3092 -#define wxStyledTextCtrl_FindText 3093 -#define wxStyledTextCtrl_FormatRange 3094 -#define wxStyledTextCtrl_GetFirstVisibleLine 3095 -#define wxStyledTextCtrl_GetLine 3096 -#define wxStyledTextCtrl_GetLineCount 3097 -#define wxStyledTextCtrl_SetMarginLeft 3098 -#define wxStyledTextCtrl_GetMarginLeft 3099 -#define wxStyledTextCtrl_SetMarginRight 3100 -#define wxStyledTextCtrl_GetMarginRight 3101 -#define wxStyledTextCtrl_GetModify 3102 -#define wxStyledTextCtrl_SetSelection 3103 -#define wxStyledTextCtrl_GetSelectedText 3104 -#define wxStyledTextCtrl_GetTextRange 3105 -#define wxStyledTextCtrl_HideSelection 3106 -#define wxStyledTextCtrl_LineFromPosition 3107 -#define wxStyledTextCtrl_PositionFromLine 3108 -#define wxStyledTextCtrl_LineScroll 3109 -#define wxStyledTextCtrl_EnsureCaretVisible 3110 -#define wxStyledTextCtrl_ReplaceSelection 3111 -#define wxStyledTextCtrl_SetReadOnly 3112 -#define wxStyledTextCtrl_CanPaste 3113 -#define wxStyledTextCtrl_CanUndo 3114 -#define wxStyledTextCtrl_EmptyUndoBuffer 3115 -#define wxStyledTextCtrl_Undo 3116 -#define wxStyledTextCtrl_Cut 3117 -#define wxStyledTextCtrl_Copy 3118 -#define wxStyledTextCtrl_Paste 3119 -#define wxStyledTextCtrl_Clear 3120 -#define wxStyledTextCtrl_SetText 3121 -#define wxStyledTextCtrl_GetText 3122 -#define wxStyledTextCtrl_GetTextLength 3123 -#define wxStyledTextCtrl_GetOvertype 3124 -#define wxStyledTextCtrl_SetCaretWidth 3125 -#define wxStyledTextCtrl_GetCaretWidth 3126 -#define wxStyledTextCtrl_SetTargetStart 3127 -#define wxStyledTextCtrl_GetTargetStart 3128 -#define wxStyledTextCtrl_SetTargetEnd 3129 -#define wxStyledTextCtrl_GetTargetEnd 3130 -#define wxStyledTextCtrl_ReplaceTarget 3131 -#define wxStyledTextCtrl_SearchInTarget 3132 -#define wxStyledTextCtrl_SetSearchFlags 3133 -#define wxStyledTextCtrl_GetSearchFlags 3134 -#define wxStyledTextCtrl_CallTipShow 3135 -#define wxStyledTextCtrl_CallTipCancel 3136 -#define wxStyledTextCtrl_CallTipActive 3137 -#define wxStyledTextCtrl_CallTipPosAtStart 3138 -#define wxStyledTextCtrl_CallTipSetHighlight 3139 -#define wxStyledTextCtrl_CallTipSetBackground 3140 -#define wxStyledTextCtrl_CallTipSetForeground 3141 -#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3142 -#define wxStyledTextCtrl_CallTipUseStyle 3143 -#define wxStyledTextCtrl_VisibleFromDocLine 3144 -#define wxStyledTextCtrl_DocLineFromVisible 3145 -#define wxStyledTextCtrl_WrapCount 3146 -#define wxStyledTextCtrl_SetFoldLevel 3147 -#define wxStyledTextCtrl_GetFoldLevel 3148 -#define wxStyledTextCtrl_GetLastChild 3149 -#define wxStyledTextCtrl_GetFoldParent 3150 -#define wxStyledTextCtrl_ShowLines 3151 -#define wxStyledTextCtrl_HideLines 3152 -#define wxStyledTextCtrl_GetLineVisible 3153 -#define wxStyledTextCtrl_SetFoldExpanded 3154 -#define wxStyledTextCtrl_GetFoldExpanded 3155 -#define wxStyledTextCtrl_ToggleFold 3156 -#define wxStyledTextCtrl_EnsureVisible 3157 -#define wxStyledTextCtrl_SetFoldFlags 3158 -#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3159 -#define wxStyledTextCtrl_SetTabIndents 3160 -#define wxStyledTextCtrl_GetTabIndents 3161 -#define wxStyledTextCtrl_SetBackSpaceUnIndents 3162 -#define wxStyledTextCtrl_GetBackSpaceUnIndents 3163 -#define wxStyledTextCtrl_SetMouseDwellTime 3164 -#define wxStyledTextCtrl_GetMouseDwellTime 3165 -#define wxStyledTextCtrl_WordStartPosition 3166 -#define wxStyledTextCtrl_WordEndPosition 3167 -#define wxStyledTextCtrl_SetWrapMode 3168 -#define wxStyledTextCtrl_GetWrapMode 3169 -#define wxStyledTextCtrl_SetWrapVisualFlags 3170 -#define wxStyledTextCtrl_GetWrapVisualFlags 3171 -#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3172 -#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3173 -#define wxStyledTextCtrl_SetWrapStartIndent 3174 -#define wxStyledTextCtrl_GetWrapStartIndent 3175 -#define wxStyledTextCtrl_SetLayoutCache 3176 -#define wxStyledTextCtrl_GetLayoutCache 3177 -#define wxStyledTextCtrl_SetScrollWidth 3178 -#define wxStyledTextCtrl_GetScrollWidth 3179 -#define wxStyledTextCtrl_TextWidth 3180 -#define wxStyledTextCtrl_GetEndAtLastLine 3181 -#define wxStyledTextCtrl_TextHeight 3182 -#define wxStyledTextCtrl_SetUseVerticalScrollBar 3183 -#define wxStyledTextCtrl_GetUseVerticalScrollBar 3184 -#define wxStyledTextCtrl_AppendText 3185 -#define wxStyledTextCtrl_GetTwoPhaseDraw 3186 -#define wxStyledTextCtrl_SetTwoPhaseDraw 3187 -#define wxStyledTextCtrl_TargetFromSelection 3188 -#define wxStyledTextCtrl_LinesJoin 3189 -#define wxStyledTextCtrl_LinesSplit 3190 -#define wxStyledTextCtrl_SetFoldMarginColour 3191 -#define wxStyledTextCtrl_SetFoldMarginHiColour 3192 -#define wxStyledTextCtrl_LineDown 3193 -#define wxStyledTextCtrl_LineDownExtend 3194 -#define wxStyledTextCtrl_LineUp 3195 -#define wxStyledTextCtrl_LineUpExtend 3196 -#define wxStyledTextCtrl_CharLeft 3197 -#define wxStyledTextCtrl_CharLeftExtend 3198 -#define wxStyledTextCtrl_CharRight 3199 -#define wxStyledTextCtrl_CharRightExtend 3200 -#define wxStyledTextCtrl_WordLeft 3201 -#define wxStyledTextCtrl_WordLeftExtend 3202 -#define wxStyledTextCtrl_WordRight 3203 -#define wxStyledTextCtrl_WordRightExtend 3204 -#define wxStyledTextCtrl_Home 3205 -#define wxStyledTextCtrl_HomeExtend 3206 -#define wxStyledTextCtrl_LineEnd 3207 -#define wxStyledTextCtrl_LineEndExtend 3208 -#define wxStyledTextCtrl_DocumentStart 3209 -#define wxStyledTextCtrl_DocumentStartExtend 3210 -#define wxStyledTextCtrl_DocumentEnd 3211 -#define wxStyledTextCtrl_DocumentEndExtend 3212 -#define wxStyledTextCtrl_PageUp 3213 -#define wxStyledTextCtrl_PageUpExtend 3214 -#define wxStyledTextCtrl_PageDown 3215 -#define wxStyledTextCtrl_PageDownExtend 3216 -#define wxStyledTextCtrl_EditToggleOvertype 3217 -#define wxStyledTextCtrl_Cancel 3218 -#define wxStyledTextCtrl_DeleteBack 3219 -#define wxStyledTextCtrl_Tab 3220 -#define wxStyledTextCtrl_BackTab 3221 -#define wxStyledTextCtrl_NewLine 3222 -#define wxStyledTextCtrl_FormFeed 3223 -#define wxStyledTextCtrl_VCHome 3224 -#define wxStyledTextCtrl_VCHomeExtend 3225 -#define wxStyledTextCtrl_ZoomIn 3226 -#define wxStyledTextCtrl_ZoomOut 3227 -#define wxStyledTextCtrl_DelWordLeft 3228 -#define wxStyledTextCtrl_DelWordRight 3229 -#define wxStyledTextCtrl_LineCut 3230 -#define wxStyledTextCtrl_LineDelete 3231 -#define wxStyledTextCtrl_LineTranspose 3232 -#define wxStyledTextCtrl_LineDuplicate 3233 -#define wxStyledTextCtrl_LowerCase 3234 -#define wxStyledTextCtrl_UpperCase 3235 -#define wxStyledTextCtrl_LineScrollDown 3236 -#define wxStyledTextCtrl_LineScrollUp 3237 -#define wxStyledTextCtrl_DeleteBackNotLine 3238 -#define wxStyledTextCtrl_HomeDisplay 3239 -#define wxStyledTextCtrl_HomeDisplayExtend 3240 -#define wxStyledTextCtrl_LineEndDisplay 3241 -#define wxStyledTextCtrl_LineEndDisplayExtend 3242 -#define wxStyledTextCtrl_HomeWrapExtend 3243 -#define wxStyledTextCtrl_LineEndWrap 3244 -#define wxStyledTextCtrl_LineEndWrapExtend 3245 -#define wxStyledTextCtrl_VCHomeWrap 3246 -#define wxStyledTextCtrl_VCHomeWrapExtend 3247 -#define wxStyledTextCtrl_LineCopy 3248 -#define wxStyledTextCtrl_MoveCaretInsideView 3249 -#define wxStyledTextCtrl_LineLength 3250 -#define wxStyledTextCtrl_BraceHighlight 3251 -#define wxStyledTextCtrl_BraceBadLight 3252 -#define wxStyledTextCtrl_BraceMatch 3253 -#define wxStyledTextCtrl_GetViewEOL 3254 -#define wxStyledTextCtrl_SetViewEOL 3255 -#define wxStyledTextCtrl_SetModEventMask 3256 -#define wxStyledTextCtrl_GetEdgeColumn 3257 -#define wxStyledTextCtrl_SetEdgeColumn 3258 -#define wxStyledTextCtrl_GetEdgeMode 3259 -#define wxStyledTextCtrl_GetEdgeColour 3260 -#define wxStyledTextCtrl_SetEdgeColour 3261 -#define wxStyledTextCtrl_SearchAnchor 3262 -#define wxStyledTextCtrl_SearchNext 3263 -#define wxStyledTextCtrl_SearchPrev 3264 -#define wxStyledTextCtrl_LinesOnScreen 3265 -#define wxStyledTextCtrl_UsePopUp 3266 -#define wxStyledTextCtrl_SelectionIsRectangle 3267 -#define wxStyledTextCtrl_SetZoom 3268 -#define wxStyledTextCtrl_GetZoom 3269 -#define wxStyledTextCtrl_GetModEventMask 3270 -#define wxStyledTextCtrl_SetSTCFocus 3271 -#define wxStyledTextCtrl_GetSTCFocus 3272 -#define wxStyledTextCtrl_SetStatus 3273 -#define wxStyledTextCtrl_GetStatus 3274 -#define wxStyledTextCtrl_SetMouseDownCaptures 3275 -#define wxStyledTextCtrl_GetMouseDownCaptures 3276 -#define wxStyledTextCtrl_SetSTCCursor 3277 -#define wxStyledTextCtrl_GetSTCCursor 3278 -#define wxStyledTextCtrl_SetControlCharSymbol 3279 -#define wxStyledTextCtrl_GetControlCharSymbol 3280 -#define wxStyledTextCtrl_WordPartLeft 3281 -#define wxStyledTextCtrl_WordPartLeftExtend 3282 -#define wxStyledTextCtrl_WordPartRight 3283 -#define wxStyledTextCtrl_WordPartRightExtend 3284 -#define wxStyledTextCtrl_SetVisiblePolicy 3285 -#define wxStyledTextCtrl_DelLineLeft 3286 -#define wxStyledTextCtrl_DelLineRight 3287 -#define wxStyledTextCtrl_GetXOffset 3288 -#define wxStyledTextCtrl_ChooseCaretX 3289 -#define wxStyledTextCtrl_SetXCaretPolicy 3290 -#define wxStyledTextCtrl_SetYCaretPolicy 3291 -#define wxStyledTextCtrl_GetPrintWrapMode 3292 -#define wxStyledTextCtrl_SetHotspotActiveForeground 3293 -#define wxStyledTextCtrl_SetHotspotActiveBackground 3294 -#define wxStyledTextCtrl_SetHotspotActiveUnderline 3295 -#define wxStyledTextCtrl_SetHotspotSingleLine 3296 -#define wxStyledTextCtrl_ParaDownExtend 3297 -#define wxStyledTextCtrl_ParaUp 3298 -#define wxStyledTextCtrl_ParaUpExtend 3299 -#define wxStyledTextCtrl_PositionBefore 3300 -#define wxStyledTextCtrl_PositionAfter 3301 -#define wxStyledTextCtrl_CopyRange 3302 -#define wxStyledTextCtrl_CopyText 3303 -#define wxStyledTextCtrl_SetSelectionMode 3304 -#define wxStyledTextCtrl_GetSelectionMode 3305 -#define wxStyledTextCtrl_LineDownRectExtend 3306 -#define wxStyledTextCtrl_LineUpRectExtend 3307 -#define wxStyledTextCtrl_CharLeftRectExtend 3308 -#define wxStyledTextCtrl_CharRightRectExtend 3309 -#define wxStyledTextCtrl_HomeRectExtend 3310 -#define wxStyledTextCtrl_VCHomeRectExtend 3311 -#define wxStyledTextCtrl_LineEndRectExtend 3312 -#define wxStyledTextCtrl_PageUpRectExtend 3313 -#define wxStyledTextCtrl_PageDownRectExtend 3314 -#define wxStyledTextCtrl_StutteredPageUp 3315 -#define wxStyledTextCtrl_StutteredPageUpExtend 3316 -#define wxStyledTextCtrl_StutteredPageDown 3317 -#define wxStyledTextCtrl_StutteredPageDownExtend 3318 -#define wxStyledTextCtrl_WordLeftEnd 3319 -#define wxStyledTextCtrl_WordLeftEndExtend 3320 -#define wxStyledTextCtrl_WordRightEnd 3321 -#define wxStyledTextCtrl_WordRightEndExtend 3322 -#define wxStyledTextCtrl_SetWhitespaceChars 3323 -#define wxStyledTextCtrl_SetCharsDefault 3324 -#define wxStyledTextCtrl_AutoCompGetCurrent 3325 -#define wxStyledTextCtrl_Allocate 3326 -#define wxStyledTextCtrl_FindColumn 3327 -#define wxStyledTextCtrl_GetCaretSticky 3328 -#define wxStyledTextCtrl_SetCaretSticky 3329 -#define wxStyledTextCtrl_ToggleCaretSticky 3330 -#define wxStyledTextCtrl_SetPasteConvertEndings 3331 -#define wxStyledTextCtrl_GetPasteConvertEndings 3332 -#define wxStyledTextCtrl_SelectionDuplicate 3333 -#define wxStyledTextCtrl_SetCaretLineBackAlpha 3334 -#define wxStyledTextCtrl_GetCaretLineBackAlpha 3335 -#define wxStyledTextCtrl_StartRecord 3336 -#define wxStyledTextCtrl_StopRecord 3337 -#define wxStyledTextCtrl_SetLexer 3338 -#define wxStyledTextCtrl_GetLexer 3339 -#define wxStyledTextCtrl_Colourise 3340 -#define wxStyledTextCtrl_SetProperty 3341 -#define wxStyledTextCtrl_SetKeyWords 3342 -#define wxStyledTextCtrl_SetLexerLanguage 3343 -#define wxStyledTextCtrl_GetProperty 3344 -#define wxStyledTextCtrl_GetStyleBitsNeeded 3345 -#define wxStyledTextCtrl_GetCurrentLine 3346 -#define wxStyledTextCtrl_StyleSetSpec 3347 -#define wxStyledTextCtrl_StyleSetFont 3348 -#define wxStyledTextCtrl_StyleSetFontAttr 3349 -#define wxStyledTextCtrl_StyleSetCharacterSet 3350 -#define wxStyledTextCtrl_StyleSetFontEncoding 3351 -#define wxStyledTextCtrl_CmdKeyExecute 3352 -#define wxStyledTextCtrl_SetMargins 3353 -#define wxStyledTextCtrl_GetSelection 3354 -#define wxStyledTextCtrl_PointFromPosition 3355 -#define wxStyledTextCtrl_ScrollToLine 3356 -#define wxStyledTextCtrl_ScrollToColumn 3357 -#define wxStyledTextCtrl_SendMsg 3358 -#define wxStyledTextCtrl_SetVScrollBar 3359 -#define wxStyledTextCtrl_SetHScrollBar 3360 -#define wxStyledTextCtrl_GetLastKeydownProcessed 3361 -#define wxStyledTextCtrl_SetLastKeydownProcessed 3362 -#define wxStyledTextCtrl_SaveFile 3363 -#define wxStyledTextCtrl_LoadFile 3364 -#define wxStyledTextCtrl_DoDragOver 3365 -#define wxStyledTextCtrl_DoDropText 3366 -#define wxStyledTextCtrl_GetUseAntiAliasing 3367 -#define wxStyledTextCtrl_AddTextRaw 3368 -#define wxStyledTextCtrl_InsertTextRaw 3369 -#define wxStyledTextCtrl_GetCurLineRaw 3370 -#define wxStyledTextCtrl_GetLineRaw 3371 -#define wxStyledTextCtrl_GetSelectedTextRaw 3372 -#define wxStyledTextCtrl_GetTextRangeRaw 3373 -#define wxStyledTextCtrl_SetTextRaw 3374 -#define wxStyledTextCtrl_GetTextRaw 3375 -#define wxStyledTextCtrl_AppendTextRaw 3376 -#define wxArtProvider_GetBitmap 3377 -#define wxArtProvider_GetIcon 3378 -#define wxTreeEvent_GetKeyCode 3379 -#define wxTreeEvent_GetItem 3380 -#define wxTreeEvent_GetKeyEvent 3381 -#define wxTreeEvent_GetLabel 3382 -#define wxTreeEvent_GetOldItem 3383 -#define wxTreeEvent_GetPoint 3384 -#define wxTreeEvent_IsEditCancelled 3385 -#define wxTreeEvent_SetToolTip 3386 -#define wxNotebookEvent_GetOldSelection 3387 -#define wxNotebookEvent_GetSelection 3388 -#define wxNotebookEvent_SetOldSelection 3389 -#define wxNotebookEvent_SetSelection 3390 -#define wxFileDataObject_new 3391 -#define wxFileDataObject_AddFile 3392 -#define wxFileDataObject_GetFilenames 3393 -#define wxFileDataObject_destroy 3394 -#define wxTextDataObject_new 3395 -#define wxTextDataObject_GetTextLength 3396 -#define wxTextDataObject_GetText 3397 -#define wxTextDataObject_SetText 3398 -#define wxTextDataObject_destroy 3399 -#define wxBitmapDataObject_new_1_1 3400 -#define wxBitmapDataObject_new_1_0 3401 -#define wxBitmapDataObject_GetBitmap 3402 -#define wxBitmapDataObject_SetBitmap 3403 -#define wxBitmapDataObject_destroy 3404 -#define wxClipboard_new 3406 -#define wxClipboard_destruct 3407 -#define wxClipboard_AddData 3408 -#define wxClipboard_Clear 3409 -#define wxClipboard_Close 3410 -#define wxClipboard_Flush 3411 -#define wxClipboard_GetData 3412 -#define wxClipboard_IsOpened 3413 -#define wxClipboard_Open 3414 -#define wxClipboard_SetData 3415 -#define wxClipboard_UsePrimarySelection 3417 -#define wxClipboard_IsSupported 3418 -#define wxClipboard_Get 3419 -#define wxSpinEvent_GetPosition 3420 -#define wxSpinEvent_SetPosition 3421 -#define wxSplitterWindow_new_0 3422 -#define wxSplitterWindow_new_2 3423 -#define wxSplitterWindow_destruct 3424 -#define wxSplitterWindow_Create 3425 -#define wxSplitterWindow_GetMinimumPaneSize 3426 -#define wxSplitterWindow_GetSashGravity 3427 -#define wxSplitterWindow_GetSashPosition 3428 -#define wxSplitterWindow_GetSplitMode 3429 -#define wxSplitterWindow_GetWindow1 3430 -#define wxSplitterWindow_GetWindow2 3431 -#define wxSplitterWindow_Initialize 3432 -#define wxSplitterWindow_IsSplit 3433 -#define wxSplitterWindow_ReplaceWindow 3434 -#define wxSplitterWindow_SetSashGravity 3435 -#define wxSplitterWindow_SetSashPosition 3436 -#define wxSplitterWindow_SetSashSize 3437 -#define wxSplitterWindow_SetMinimumPaneSize 3438 -#define wxSplitterWindow_SetSplitMode 3439 -#define wxSplitterWindow_SplitHorizontally 3440 -#define wxSplitterWindow_SplitVertically 3441 -#define wxSplitterWindow_Unsplit 3442 -#define wxSplitterWindow_UpdateSize 3443 -#define wxSplitterEvent_GetSashPosition 3444 -#define wxSplitterEvent_GetX 3445 -#define wxSplitterEvent_GetY 3446 -#define wxSplitterEvent_GetWindowBeingRemoved 3447 -#define wxSplitterEvent_SetSashPosition 3448 -#define wxHtmlWindow_new_0 3449 -#define wxHtmlWindow_new_2 3450 -#define wxHtmlWindow_AppendToPage 3451 -#define wxHtmlWindow_GetOpenedAnchor 3452 -#define wxHtmlWindow_GetOpenedPage 3453 -#define wxHtmlWindow_GetOpenedPageTitle 3454 -#define wxHtmlWindow_GetRelatedFrame 3455 -#define wxHtmlWindow_HistoryBack 3456 -#define wxHtmlWindow_HistoryCanBack 3457 -#define wxHtmlWindow_HistoryCanForward 3458 -#define wxHtmlWindow_HistoryClear 3459 -#define wxHtmlWindow_HistoryForward 3460 -#define wxHtmlWindow_LoadFile 3461 -#define wxHtmlWindow_LoadPage 3462 -#define wxHtmlWindow_SelectAll 3463 -#define wxHtmlWindow_SelectionToText 3464 -#define wxHtmlWindow_SelectLine 3465 -#define wxHtmlWindow_SelectWord 3466 -#define wxHtmlWindow_SetBorders 3467 -#define wxHtmlWindow_SetFonts 3468 -#define wxHtmlWindow_SetPage 3469 -#define wxHtmlWindow_SetRelatedFrame 3470 -#define wxHtmlWindow_SetRelatedStatusBar 3471 -#define wxHtmlWindow_ToText 3472 -#define wxHtmlWindow_destroy 3473 -#define wxHtmlLinkEvent_GetLinkInfo 3474 -#define wxAuiNotebookEvent_SetSelection 3475 -#define wxAuiNotebookEvent_GetSelection 3476 -#define wxAuiNotebookEvent_SetOldSelection 3477 -#define wxAuiNotebookEvent_GetOldSelection 3478 -#define wxAuiNotebookEvent_SetDragSource 3479 -#define wxAuiNotebookEvent_GetDragSource 3480 -#define wxAuiManagerEvent_SetManager 3481 -#define wxAuiManagerEvent_GetManager 3482 -#define wxAuiManagerEvent_SetPane 3483 -#define wxAuiManagerEvent_GetPane 3484 -#define wxAuiManagerEvent_SetButton 3485 -#define wxAuiManagerEvent_GetButton 3486 -#define wxAuiManagerEvent_SetDC 3487 -#define wxAuiManagerEvent_GetDC 3488 -#define wxAuiManagerEvent_Veto 3489 -#define wxAuiManagerEvent_GetVeto 3490 -#define wxAuiManagerEvent_SetCanVeto 3491 -#define wxAuiManagerEvent_CanVeto 3492 -#define wxLogNull_new 3493 -#define wxLogNull_destroy 3494 +#define wxTreeCtrl_EditLabel 2010 +#define wxTreeCtrl_EnsureVisible 2011 +#define wxTreeCtrl_Expand 2012 +#define wxTreeCtrl_GetBoundingRect 2013 +#define wxTreeCtrl_GetChildrenCount 2015 +#define wxTreeCtrl_GetCount 2016 +#define wxTreeCtrl_GetEditControl 2017 +#define wxTreeCtrl_GetFirstChild 2018 +#define wxTreeCtrl_GetNextChild 2019 +#define wxTreeCtrl_GetFirstVisibleItem 2020 +#define wxTreeCtrl_GetImageList 2021 +#define wxTreeCtrl_GetIndent 2022 +#define wxTreeCtrl_GetItemBackgroundColour 2023 +#define wxTreeCtrl_GetItemData 2024 +#define wxTreeCtrl_GetItemFont 2025 +#define wxTreeCtrl_GetItemImage_1 2026 +#define wxTreeCtrl_GetItemImage_2 2027 +#define wxTreeCtrl_GetItemText 2028 +#define wxTreeCtrl_GetItemTextColour 2029 +#define wxTreeCtrl_GetLastChild 2030 +#define wxTreeCtrl_GetNextSibling 2031 +#define wxTreeCtrl_GetNextVisible 2032 +#define wxTreeCtrl_GetItemParent 2033 +#define wxTreeCtrl_GetPrevSibling 2034 +#define wxTreeCtrl_GetPrevVisible 2035 +#define wxTreeCtrl_GetRootItem 2036 +#define wxTreeCtrl_GetSelection 2037 +#define wxTreeCtrl_GetSelections 2038 +#define wxTreeCtrl_GetStateImageList 2039 +#define wxTreeCtrl_HitTest 2040 +#define wxTreeCtrl_InsertItem 2042 +#define wxTreeCtrl_IsBold 2043 +#define wxTreeCtrl_IsExpanded 2044 +#define wxTreeCtrl_IsSelected 2045 +#define wxTreeCtrl_IsVisible 2046 +#define wxTreeCtrl_ItemHasChildren 2047 +#define wxTreeCtrl_PrependItem 2048 +#define wxTreeCtrl_ScrollTo 2049 +#define wxTreeCtrl_SelectItem_1 2050 +#define wxTreeCtrl_SelectItem_2 2051 +#define wxTreeCtrl_SetIndent 2052 +#define wxTreeCtrl_SetImageList 2053 +#define wxTreeCtrl_SetItemBackgroundColour 2054 +#define wxTreeCtrl_SetItemBold 2055 +#define wxTreeCtrl_SetItemData 2056 +#define wxTreeCtrl_SetItemDropHighlight 2057 +#define wxTreeCtrl_SetItemFont 2058 +#define wxTreeCtrl_SetItemHasChildren 2059 +#define wxTreeCtrl_SetItemImage_2 2060 +#define wxTreeCtrl_SetItemImage_3 2061 +#define wxTreeCtrl_SetItemText 2062 +#define wxTreeCtrl_SetItemTextColour 2063 +#define wxTreeCtrl_SetStateImageList 2064 +#define wxTreeCtrl_SetWindowStyle 2065 +#define wxTreeCtrl_SortChildren 2066 +#define wxTreeCtrl_Toggle 2067 +#define wxTreeCtrl_ToggleItemSelection 2068 +#define wxTreeCtrl_Unselect 2069 +#define wxTreeCtrl_UnselectAll 2070 +#define wxTreeCtrl_UnselectItem 2071 +#define wxScrollBar_new_0 2072 +#define wxScrollBar_new_3 2073 +#define wxScrollBar_destruct 2074 +#define wxScrollBar_Create 2075 +#define wxScrollBar_GetRange 2076 +#define wxScrollBar_GetPageSize 2077 +#define wxScrollBar_GetThumbPosition 2078 +#define wxScrollBar_GetThumbSize 2079 +#define wxScrollBar_SetThumbPosition 2080 +#define wxScrollBar_SetScrollbar 2081 +#define wxSpinButton_new_2 2083 +#define wxSpinButton_new_0 2084 +#define wxSpinButton_Create 2085 +#define wxSpinButton_GetMax 2086 +#define wxSpinButton_GetMin 2087 +#define wxSpinButton_GetValue 2088 +#define wxSpinButton_SetRange 2089 +#define wxSpinButton_SetValue 2090 +#define wxSpinButton_destroy 2091 +#define wxSpinCtrl_new_0 2092 +#define wxSpinCtrl_new_2 2093 +#define wxSpinCtrl_Create 2095 +#define wxSpinCtrl_SetValue_1_1 2098 +#define wxSpinCtrl_SetValue_1_0 2099 +#define wxSpinCtrl_GetValue 2101 +#define wxSpinCtrl_SetRange 2103 +#define wxSpinCtrl_SetSelection 2104 +#define wxSpinCtrl_GetMin 2106 +#define wxSpinCtrl_GetMax 2108 +#define wxSpinCtrl_destroy 2109 +#define wxStaticText_new_0 2110 +#define wxStaticText_new_4 2111 +#define wxStaticText_Create 2112 +#define wxStaticText_GetLabel 2113 +#define wxStaticText_SetLabel 2114 +#define wxStaticText_Wrap 2115 +#define wxStaticText_destroy 2116 +#define wxStaticBitmap_new_0 2117 +#define wxStaticBitmap_new_4 2118 +#define wxStaticBitmap_Create 2119 +#define wxStaticBitmap_GetBitmap 2120 +#define wxStaticBitmap_SetBitmap 2121 +#define wxStaticBitmap_destroy 2122 +#define wxRadioBox_new 2123 +#define wxRadioBox_destruct 2125 +#define wxRadioBox_Create 2126 +#define wxRadioBox_Enable_2 2127 +#define wxRadioBox_Enable_1 2128 +#define wxRadioBox_GetSelection 2129 +#define wxRadioBox_GetString 2130 +#define wxRadioBox_SetSelection 2131 +#define wxRadioBox_Show_2 2132 +#define wxRadioBox_Show_1 2133 +#define wxRadioBox_GetColumnCount 2134 +#define wxRadioBox_GetItemHelpText 2135 +#define wxRadioBox_GetItemToolTip 2136 +#define wxRadioBox_GetItemFromPoint 2138 +#define wxRadioBox_GetRowCount 2139 +#define wxRadioBox_IsItemEnabled 2140 +#define wxRadioBox_IsItemShown 2141 +#define wxRadioBox_SetItemHelpText 2142 +#define wxRadioBox_SetItemToolTip 2143 +#define wxRadioButton_new_0 2144 +#define wxRadioButton_new_4 2145 +#define wxRadioButton_Create 2146 +#define wxRadioButton_GetValue 2147 +#define wxRadioButton_SetValue 2148 +#define wxRadioButton_destroy 2149 +#define wxSlider_new_6 2151 +#define wxSlider_new_0 2152 +#define wxSlider_Create 2153 +#define wxSlider_GetLineSize 2154 +#define wxSlider_GetMax 2155 +#define wxSlider_GetMin 2156 +#define wxSlider_GetPageSize 2157 +#define wxSlider_GetThumbLength 2158 +#define wxSlider_GetValue 2159 +#define wxSlider_SetLineSize 2160 +#define wxSlider_SetPageSize 2161 +#define wxSlider_SetRange 2162 +#define wxSlider_SetThumbLength 2163 +#define wxSlider_SetValue 2164 +#define wxSlider_destroy 2165 +#define wxDialog_new_4 2167 +#define wxDialog_new_0 2168 +#define wxDialog_destruct 2170 +#define wxDialog_Create 2171 +#define wxDialog_CreateButtonSizer 2172 +#define wxDialog_CreateStdDialogButtonSizer 2173 +#define wxDialog_EndModal 2174 +#define wxDialog_GetAffirmativeId 2175 +#define wxDialog_GetReturnCode 2176 +#define wxDialog_IsModal 2177 +#define wxDialog_SetAffirmativeId 2178 +#define wxDialog_SetReturnCode 2179 +#define wxDialog_Show 2180 +#define wxDialog_ShowModal 2181 +#define wxColourDialog_new_0 2182 +#define wxColourDialog_new_2 2183 +#define wxColourDialog_destruct 2184 +#define wxColourDialog_Create 2185 +#define wxColourDialog_GetColourData 2186 +#define wxColourData_new_0 2187 +#define wxColourData_new_1 2188 +#define wxColourData_destruct 2189 +#define wxColourData_GetChooseFull 2190 +#define wxColourData_GetColour 2191 +#define wxColourData_GetCustomColour 2193 +#define wxColourData_SetChooseFull 2194 +#define wxColourData_SetColour 2195 +#define wxColourData_SetCustomColour 2196 +#define wxPalette_new_0 2197 +#define wxPalette_new_4 2198 +#define wxPalette_destruct 2200 +#define wxPalette_Create 2201 +#define wxPalette_GetColoursCount 2202 +#define wxPalette_GetPixel 2203 +#define wxPalette_GetRGB 2204 +#define wxPalette_IsOk 2205 +#define wxDirDialog_new 2209 +#define wxDirDialog_destruct 2210 +#define wxDirDialog_GetPath 2211 +#define wxDirDialog_GetMessage 2212 +#define wxDirDialog_SetMessage 2213 +#define wxDirDialog_SetPath 2214 +#define wxFileDialog_new 2218 +#define wxFileDialog_destruct 2219 +#define wxFileDialog_GetDirectory 2220 +#define wxFileDialog_GetFilename 2221 +#define wxFileDialog_GetFilenames 2222 +#define wxFileDialog_GetFilterIndex 2223 +#define wxFileDialog_GetMessage 2224 +#define wxFileDialog_GetPath 2225 +#define wxFileDialog_GetPaths 2226 +#define wxFileDialog_GetWildcard 2227 +#define wxFileDialog_SetDirectory 2228 +#define wxFileDialog_SetFilename 2229 +#define wxFileDialog_SetFilterIndex 2230 +#define wxFileDialog_SetMessage 2231 +#define wxFileDialog_SetPath 2232 +#define wxFileDialog_SetWildcard 2233 +#define wxPickerBase_SetInternalMargin 2234 +#define wxPickerBase_GetInternalMargin 2235 +#define wxPickerBase_SetTextCtrlProportion 2236 +#define wxPickerBase_SetPickerCtrlProportion 2237 +#define wxPickerBase_GetTextCtrlProportion 2238 +#define wxPickerBase_GetPickerCtrlProportion 2239 +#define wxPickerBase_HasTextCtrl 2240 +#define wxPickerBase_GetTextCtrl 2241 +#define wxPickerBase_IsTextCtrlGrowable 2242 +#define wxPickerBase_SetPickerCtrlGrowable 2243 +#define wxPickerBase_SetTextCtrlGrowable 2244 +#define wxPickerBase_IsPickerCtrlGrowable 2245 +#define wxFilePickerCtrl_new_0 2246 +#define wxFilePickerCtrl_new_3 2247 +#define wxFilePickerCtrl_Create 2248 +#define wxFilePickerCtrl_GetPath 2249 +#define wxFilePickerCtrl_SetPath 2250 +#define wxFilePickerCtrl_destroy 2251 +#define wxDirPickerCtrl_new_0 2252 +#define wxDirPickerCtrl_new_3 2253 +#define wxDirPickerCtrl_Create 2254 +#define wxDirPickerCtrl_GetPath 2255 +#define wxDirPickerCtrl_SetPath 2256 +#define wxDirPickerCtrl_destroy 2257 +#define wxColourPickerCtrl_new_0 2258 +#define wxColourPickerCtrl_new_3 2259 +#define wxColourPickerCtrl_Create 2260 +#define wxColourPickerCtrl_GetColour 2261 +#define wxColourPickerCtrl_SetColour_1_1 2262 +#define wxColourPickerCtrl_SetColour_1_0 2263 +#define wxColourPickerCtrl_destroy 2264 +#define wxDatePickerCtrl_new_0 2265 +#define wxDatePickerCtrl_new_3 2266 +#define wxDatePickerCtrl_GetRange 2267 +#define wxDatePickerCtrl_GetValue 2268 +#define wxDatePickerCtrl_SetRange 2269 +#define wxDatePickerCtrl_SetValue 2270 +#define wxDatePickerCtrl_destroy 2271 +#define wxFontPickerCtrl_new_0 2272 +#define wxFontPickerCtrl_new_3 2273 +#define wxFontPickerCtrl_Create 2274 +#define wxFontPickerCtrl_GetSelectedFont 2275 +#define wxFontPickerCtrl_SetSelectedFont 2276 +#define wxFontPickerCtrl_GetMaxPointSize 2277 +#define wxFontPickerCtrl_SetMaxPointSize 2278 +#define wxFontPickerCtrl_destroy 2279 +#define wxFindReplaceDialog_new_0 2282 +#define wxFindReplaceDialog_new_4 2283 +#define wxFindReplaceDialog_destruct 2284 +#define wxFindReplaceDialog_Create 2285 +#define wxFindReplaceDialog_GetData 2286 +#define wxFindReplaceData_new_0 2287 +#define wxFindReplaceData_new_1 2288 +#define wxFindReplaceData_GetFindString 2289 +#define wxFindReplaceData_GetReplaceString 2290 +#define wxFindReplaceData_GetFlags 2291 +#define wxFindReplaceData_SetFlags 2292 +#define wxFindReplaceData_SetFindString 2293 +#define wxFindReplaceData_SetReplaceString 2294 +#define wxFindReplaceData_destroy 2295 +#define wxMultiChoiceDialog_new_0 2296 +#define wxMultiChoiceDialog_new_5 2298 +#define wxMultiChoiceDialog_GetSelections 2299 +#define wxMultiChoiceDialog_SetSelections 2300 +#define wxMultiChoiceDialog_destroy 2301 +#define wxSingleChoiceDialog_new_0 2302 +#define wxSingleChoiceDialog_new_5 2304 +#define wxSingleChoiceDialog_GetSelection 2305 +#define wxSingleChoiceDialog_GetStringSelection 2306 +#define wxSingleChoiceDialog_SetSelection 2307 +#define wxSingleChoiceDialog_destroy 2308 +#define wxTextEntryDialog_new 2309 +#define wxTextEntryDialog_GetValue 2310 +#define wxTextEntryDialog_SetValue 2311 +#define wxTextEntryDialog_destroy 2312 +#define wxPasswordEntryDialog_new 2313 +#define wxPasswordEntryDialog_destroy 2314 +#define wxFontData_new_0 2315 +#define wxFontData_new_1 2316 +#define wxFontData_destruct 2317 +#define wxFontData_EnableEffects 2318 +#define wxFontData_GetAllowSymbols 2319 +#define wxFontData_GetColour 2320 +#define wxFontData_GetChosenFont 2321 +#define wxFontData_GetEnableEffects 2322 +#define wxFontData_GetInitialFont 2323 +#define wxFontData_GetShowHelp 2324 +#define wxFontData_SetAllowSymbols 2325 +#define wxFontData_SetChosenFont 2326 +#define wxFontData_SetColour 2327 +#define wxFontData_SetInitialFont 2328 +#define wxFontData_SetRange 2329 +#define wxFontData_SetShowHelp 2330 +#define wxFontDialog_new_0 2334 +#define wxFontDialog_new_2 2336 +#define wxFontDialog_Create 2338 +#define wxFontDialog_GetFontData 2339 +#define wxFontDialog_destroy 2341 +#define wxProgressDialog_new 2342 +#define wxProgressDialog_destruct 2343 +#define wxProgressDialog_Resume 2344 +#define wxProgressDialog_Update_2 2345 +#define wxProgressDialog_Update_0 2346 +#define wxMessageDialog_new 2347 +#define wxMessageDialog_destruct 2348 +#define wxPageSetupDialog_new 2349 +#define wxPageSetupDialog_destruct 2350 +#define wxPageSetupDialog_GetPageSetupData 2351 +#define wxPageSetupDialog_ShowModal 2352 +#define wxPageSetupDialogData_new_0 2353 +#define wxPageSetupDialogData_new_1_0 2354 +#define wxPageSetupDialogData_new_1_1 2355 +#define wxPageSetupDialogData_destruct 2356 +#define wxPageSetupDialogData_EnableHelp 2357 +#define wxPageSetupDialogData_EnableMargins 2358 +#define wxPageSetupDialogData_EnableOrientation 2359 +#define wxPageSetupDialogData_EnablePaper 2360 +#define wxPageSetupDialogData_EnablePrinter 2361 +#define wxPageSetupDialogData_GetDefaultMinMargins 2362 +#define wxPageSetupDialogData_GetEnableMargins 2363 +#define wxPageSetupDialogData_GetEnableOrientation 2364 +#define wxPageSetupDialogData_GetEnablePaper 2365 +#define wxPageSetupDialogData_GetEnablePrinter 2366 +#define wxPageSetupDialogData_GetEnableHelp 2367 +#define wxPageSetupDialogData_GetDefaultInfo 2368 +#define wxPageSetupDialogData_GetMarginTopLeft 2369 +#define wxPageSetupDialogData_GetMarginBottomRight 2370 +#define wxPageSetupDialogData_GetMinMarginTopLeft 2371 +#define wxPageSetupDialogData_GetMinMarginBottomRight 2372 +#define wxPageSetupDialogData_GetPaperId 2373 +#define wxPageSetupDialogData_GetPaperSize 2374 +#define wxPageSetupDialogData_GetPrintData 2376 +#define wxPageSetupDialogData_IsOk 2377 +#define wxPageSetupDialogData_SetDefaultInfo 2378 +#define wxPageSetupDialogData_SetDefaultMinMargins 2379 +#define wxPageSetupDialogData_SetMarginTopLeft 2380 +#define wxPageSetupDialogData_SetMarginBottomRight 2381 +#define wxPageSetupDialogData_SetMinMarginTopLeft 2382 +#define wxPageSetupDialogData_SetMinMarginBottomRight 2383 +#define wxPageSetupDialogData_SetPaperId 2384 +#define wxPageSetupDialogData_SetPaperSize_1_1 2385 +#define wxPageSetupDialogData_SetPaperSize_1_0 2386 +#define wxPageSetupDialogData_SetPrintData 2387 +#define wxPrintDialog_new_2_0 2388 +#define wxPrintDialog_new_2_1 2389 +#define wxPrintDialog_destruct 2390 +#define wxPrintDialog_GetPrintDialogData 2391 +#define wxPrintDialog_GetPrintDC 2392 +#define wxPrintDialogData_new_0 2393 +#define wxPrintDialogData_new_1_1 2394 +#define wxPrintDialogData_new_1_0 2395 +#define wxPrintDialogData_destruct 2396 +#define wxPrintDialogData_EnableHelp 2397 +#define wxPrintDialogData_EnablePageNumbers 2398 +#define wxPrintDialogData_EnablePrintToFile 2399 +#define wxPrintDialogData_EnableSelection 2400 +#define wxPrintDialogData_GetAllPages 2401 +#define wxPrintDialogData_GetCollate 2402 +#define wxPrintDialogData_GetFromPage 2403 +#define wxPrintDialogData_GetMaxPage 2404 +#define wxPrintDialogData_GetMinPage 2405 +#define wxPrintDialogData_GetNoCopies 2406 +#define wxPrintDialogData_GetPrintData 2407 +#define wxPrintDialogData_GetPrintToFile 2408 +#define wxPrintDialogData_GetSelection 2409 +#define wxPrintDialogData_GetToPage 2410 +#define wxPrintDialogData_IsOk 2411 +#define wxPrintDialogData_SetCollate 2412 +#define wxPrintDialogData_SetFromPage 2413 +#define wxPrintDialogData_SetMaxPage 2414 +#define wxPrintDialogData_SetMinPage 2415 +#define wxPrintDialogData_SetNoCopies 2416 +#define wxPrintDialogData_SetPrintData 2417 +#define wxPrintDialogData_SetPrintToFile 2418 +#define wxPrintDialogData_SetSelection 2419 +#define wxPrintDialogData_SetToPage 2420 +#define wxPrintData_new_0 2421 +#define wxPrintData_new_1 2422 +#define wxPrintData_destruct 2423 +#define wxPrintData_GetCollate 2424 +#define wxPrintData_GetBin 2425 +#define wxPrintData_GetColour 2426 +#define wxPrintData_GetDuplex 2427 +#define wxPrintData_GetNoCopies 2428 +#define wxPrintData_GetOrientation 2429 +#define wxPrintData_GetPaperId 2430 +#define wxPrintData_GetPrinterName 2431 +#define wxPrintData_GetQuality 2432 +#define wxPrintData_IsOk 2433 +#define wxPrintData_SetBin 2434 +#define wxPrintData_SetCollate 2435 +#define wxPrintData_SetColour 2436 +#define wxPrintData_SetDuplex 2437 +#define wxPrintData_SetNoCopies 2438 +#define wxPrintData_SetOrientation 2439 +#define wxPrintData_SetPaperId 2440 +#define wxPrintData_SetPrinterName 2441 +#define wxPrintData_SetQuality 2442 +#define wxPrintPreview_new_2 2445 +#define wxPrintPreview_new_3 2446 +#define wxPrintPreview_destruct 2448 +#define wxPrintPreview_GetCanvas 2449 +#define wxPrintPreview_GetCurrentPage 2450 +#define wxPrintPreview_GetFrame 2451 +#define wxPrintPreview_GetMaxPage 2452 +#define wxPrintPreview_GetMinPage 2453 +#define wxPrintPreview_GetPrintout 2454 +#define wxPrintPreview_GetPrintoutForPrinting 2455 +#define wxPrintPreview_IsOk 2456 +#define wxPrintPreview_PaintPage 2457 +#define wxPrintPreview_Print 2458 +#define wxPrintPreview_RenderPage 2459 +#define wxPrintPreview_SetCanvas 2460 +#define wxPrintPreview_SetCurrentPage 2461 +#define wxPrintPreview_SetFrame 2462 +#define wxPrintPreview_SetPrintout 2463 +#define wxPrintPreview_SetZoom 2464 +#define wxPreviewFrame_new 2465 +#define wxPreviewFrame_destruct 2466 +#define wxPreviewFrame_CreateControlBar 2467 +#define wxPreviewFrame_CreateCanvas 2468 +#define wxPreviewFrame_Initialize 2469 +#define wxPreviewFrame_OnCloseWindow 2470 +#define wxPreviewControlBar_new 2471 +#define wxPreviewControlBar_destruct 2472 +#define wxPreviewControlBar_CreateButtons 2473 +#define wxPreviewControlBar_GetPrintPreview 2474 +#define wxPreviewControlBar_GetZoomControl 2475 +#define wxPreviewControlBar_SetZoomControl 2476 +#define wxPrinter_new 2478 +#define wxPrinter_CreateAbortWindow 2479 +#define wxPrinter_GetAbort 2480 +#define wxPrinter_GetLastError 2481 +#define wxPrinter_GetPrintDialogData 2482 +#define wxPrinter_Print 2483 +#define wxPrinter_PrintDialog 2484 +#define wxPrinter_ReportError 2485 +#define wxPrinter_Setup 2486 +#define wxPrinter_destroy 2487 +#define wxXmlResource_new_1 2488 +#define wxXmlResource_new_2 2489 +#define wxXmlResource_destruct 2490 +#define wxXmlResource_AttachUnknownControl 2491 +#define wxXmlResource_ClearHandlers 2492 +#define wxXmlResource_CompareVersion 2493 +#define wxXmlResource_Get 2494 +#define wxXmlResource_GetFlags 2495 +#define wxXmlResource_GetVersion 2496 +#define wxXmlResource_GetXRCID 2497 +#define wxXmlResource_InitAllHandlers 2498 +#define wxXmlResource_Load 2499 +#define wxXmlResource_LoadBitmap 2500 +#define wxXmlResource_LoadDialog_2 2501 +#define wxXmlResource_LoadDialog_3 2502 +#define wxXmlResource_LoadFrame_2 2503 +#define wxXmlResource_LoadFrame_3 2504 +#define wxXmlResource_LoadIcon 2505 +#define wxXmlResource_LoadMenu 2506 +#define wxXmlResource_LoadMenuBar_2 2507 +#define wxXmlResource_LoadMenuBar_1 2508 +#define wxXmlResource_LoadPanel_2 2509 +#define wxXmlResource_LoadPanel_3 2510 +#define wxXmlResource_LoadToolBar 2511 +#define wxXmlResource_Set 2512 +#define wxXmlResource_SetFlags 2513 +#define wxXmlResource_Unload 2514 +#define wxXmlResource_xrcctrl 2515 +#define wxHtmlEasyPrinting_new 2516 +#define wxHtmlEasyPrinting_destruct 2517 +#define wxHtmlEasyPrinting_GetPrintData 2518 +#define wxHtmlEasyPrinting_GetPageSetupData 2519 +#define wxHtmlEasyPrinting_PreviewFile 2520 +#define wxHtmlEasyPrinting_PreviewText 2521 +#define wxHtmlEasyPrinting_PrintFile 2522 +#define wxHtmlEasyPrinting_PrintText 2523 +#define wxHtmlEasyPrinting_PageSetup 2524 +#define wxHtmlEasyPrinting_SetFonts 2525 +#define wxHtmlEasyPrinting_SetHeader 2526 +#define wxHtmlEasyPrinting_SetFooter 2527 +#define wxGLCanvas_new_2 2529 +#define wxGLCanvas_new_3_1 2530 +#define wxGLCanvas_new_3_0 2531 +#define wxGLCanvas_GetContext 2532 +#define wxGLCanvas_SetCurrent 2534 +#define wxGLCanvas_SwapBuffers 2535 +#define wxGLCanvas_destroy 2536 +#define wxAuiManager_new 2537 +#define wxAuiManager_destruct 2538 +#define wxAuiManager_AddPane_2_1 2539 +#define wxAuiManager_AddPane_3 2540 +#define wxAuiManager_AddPane_2_0 2541 +#define wxAuiManager_DetachPane 2542 +#define wxAuiManager_GetAllPanes 2543 +#define wxAuiManager_GetArtProvider 2544 +#define wxAuiManager_GetDockSizeConstraint 2545 +#define wxAuiManager_GetFlags 2546 +#define wxAuiManager_GetManagedWindow 2547 +#define wxAuiManager_GetManager 2548 +#define wxAuiManager_GetPane_1_1 2549 +#define wxAuiManager_GetPane_1_0 2550 +#define wxAuiManager_HideHint 2551 +#define wxAuiManager_InsertPane 2552 +#define wxAuiManager_LoadPaneInfo 2553 +#define wxAuiManager_LoadPerspective 2554 +#define wxAuiManager_SavePaneInfo 2555 +#define wxAuiManager_SavePerspective 2556 +#define wxAuiManager_SetArtProvider 2557 +#define wxAuiManager_SetDockSizeConstraint 2558 +#define wxAuiManager_SetFlags 2559 +#define wxAuiManager_SetManagedWindow 2560 +#define wxAuiManager_ShowHint 2561 +#define wxAuiManager_UnInit 2562 +#define wxAuiManager_Update 2563 +#define wxAuiPaneInfo_new_0 2564 +#define wxAuiPaneInfo_new_1 2565 +#define wxAuiPaneInfo_destruct 2566 +#define wxAuiPaneInfo_BestSize_1 2567 +#define wxAuiPaneInfo_BestSize_2 2568 +#define wxAuiPaneInfo_Bottom 2569 +#define wxAuiPaneInfo_BottomDockable 2570 +#define wxAuiPaneInfo_Caption 2571 +#define wxAuiPaneInfo_CaptionVisible 2572 +#define wxAuiPaneInfo_Centre 2573 +#define wxAuiPaneInfo_CentrePane 2574 +#define wxAuiPaneInfo_CloseButton 2575 +#define wxAuiPaneInfo_DefaultPane 2576 +#define wxAuiPaneInfo_DestroyOnClose 2577 +#define wxAuiPaneInfo_Direction 2578 +#define wxAuiPaneInfo_Dock 2579 +#define wxAuiPaneInfo_Dockable 2580 +#define wxAuiPaneInfo_Fixed 2581 +#define wxAuiPaneInfo_Float 2582 +#define wxAuiPaneInfo_Floatable 2583 +#define wxAuiPaneInfo_FloatingPosition_1 2584 +#define wxAuiPaneInfo_FloatingPosition_2 2585 +#define wxAuiPaneInfo_FloatingSize_1 2586 +#define wxAuiPaneInfo_FloatingSize_2 2587 +#define wxAuiPaneInfo_Gripper 2588 +#define wxAuiPaneInfo_GripperTop 2589 +#define wxAuiPaneInfo_HasBorder 2590 +#define wxAuiPaneInfo_HasCaption 2591 +#define wxAuiPaneInfo_HasCloseButton 2592 +#define wxAuiPaneInfo_HasFlag 2593 +#define wxAuiPaneInfo_HasGripper 2594 +#define wxAuiPaneInfo_HasGripperTop 2595 +#define wxAuiPaneInfo_HasMaximizeButton 2596 +#define wxAuiPaneInfo_HasMinimizeButton 2597 +#define wxAuiPaneInfo_HasPinButton 2598 +#define wxAuiPaneInfo_Hide 2599 +#define wxAuiPaneInfo_IsBottomDockable 2600 +#define wxAuiPaneInfo_IsDocked 2601 +#define wxAuiPaneInfo_IsFixed 2602 +#define wxAuiPaneInfo_IsFloatable 2603 +#define wxAuiPaneInfo_IsFloating 2604 +#define wxAuiPaneInfo_IsLeftDockable 2605 +#define wxAuiPaneInfo_IsMovable 2606 +#define wxAuiPaneInfo_IsOk 2607 +#define wxAuiPaneInfo_IsResizable 2608 +#define wxAuiPaneInfo_IsRightDockable 2609 +#define wxAuiPaneInfo_IsShown 2610 +#define wxAuiPaneInfo_IsToolbar 2611 +#define wxAuiPaneInfo_IsTopDockable 2612 +#define wxAuiPaneInfo_Layer 2613 +#define wxAuiPaneInfo_Left 2614 +#define wxAuiPaneInfo_LeftDockable 2615 +#define wxAuiPaneInfo_MaxSize_1 2616 +#define wxAuiPaneInfo_MaxSize_2 2617 +#define wxAuiPaneInfo_MaximizeButton 2618 +#define wxAuiPaneInfo_MinSize_1 2619 +#define wxAuiPaneInfo_MinSize_2 2620 +#define wxAuiPaneInfo_MinimizeButton 2621 +#define wxAuiPaneInfo_Movable 2622 +#define wxAuiPaneInfo_Name 2623 +#define wxAuiPaneInfo_PaneBorder 2624 +#define wxAuiPaneInfo_PinButton 2625 +#define wxAuiPaneInfo_Position 2626 +#define wxAuiPaneInfo_Resizable 2627 +#define wxAuiPaneInfo_Right 2628 +#define wxAuiPaneInfo_RightDockable 2629 +#define wxAuiPaneInfo_Row 2630 +#define wxAuiPaneInfo_SafeSet 2631 +#define wxAuiPaneInfo_SetFlag 2632 +#define wxAuiPaneInfo_Show 2633 +#define wxAuiPaneInfo_ToolbarPane 2634 +#define wxAuiPaneInfo_Top 2635 +#define wxAuiPaneInfo_TopDockable 2636 +#define wxAuiPaneInfo_Window 2637 +#define wxAuiNotebook_new_0 2638 +#define wxAuiNotebook_new_2 2639 +#define wxAuiNotebook_AddPage 2640 +#define wxAuiNotebook_Create 2641 +#define wxAuiNotebook_DeletePage 2642 +#define wxAuiNotebook_GetArtProvider 2643 +#define wxAuiNotebook_GetPage 2644 +#define wxAuiNotebook_GetPageBitmap 2645 +#define wxAuiNotebook_GetPageCount 2646 +#define wxAuiNotebook_GetPageIndex 2647 +#define wxAuiNotebook_GetPageText 2648 +#define wxAuiNotebook_GetSelection 2649 +#define wxAuiNotebook_InsertPage 2650 +#define wxAuiNotebook_RemovePage 2651 +#define wxAuiNotebook_SetArtProvider 2652 +#define wxAuiNotebook_SetFont 2653 +#define wxAuiNotebook_SetPageBitmap 2654 +#define wxAuiNotebook_SetPageText 2655 +#define wxAuiNotebook_SetSelection 2656 +#define wxAuiNotebook_SetTabCtrlHeight 2657 +#define wxAuiNotebook_SetUniformBitmapSize 2658 +#define wxAuiNotebook_destroy 2659 +#define wxMDIParentFrame_new_0 2660 +#define wxMDIParentFrame_new_4 2661 +#define wxMDIParentFrame_destruct 2662 +#define wxMDIParentFrame_ActivateNext 2663 +#define wxMDIParentFrame_ActivatePrevious 2664 +#define wxMDIParentFrame_ArrangeIcons 2665 +#define wxMDIParentFrame_Cascade 2666 +#define wxMDIParentFrame_Create 2667 +#define wxMDIParentFrame_GetActiveChild 2668 +#define wxMDIParentFrame_GetClientWindow 2669 +#define wxMDIParentFrame_Tile 2670 +#define wxMDIChildFrame_new_0 2671 +#define wxMDIChildFrame_new_4 2672 +#define wxMDIChildFrame_destruct 2673 +#define wxMDIChildFrame_Activate 2674 +#define wxMDIChildFrame_Create 2675 +#define wxMDIChildFrame_Maximize 2676 +#define wxMDIChildFrame_Restore 2677 +#define wxMDIClientWindow_new_0 2678 +#define wxMDIClientWindow_new_2 2679 +#define wxMDIClientWindow_destruct 2680 +#define wxMDIClientWindow_CreateClient 2681 +#define wxLayoutAlgorithm_new 2682 +#define wxLayoutAlgorithm_LayoutFrame 2683 +#define wxLayoutAlgorithm_LayoutMDIFrame 2684 +#define wxLayoutAlgorithm_LayoutWindow 2685 +#define wxLayoutAlgorithm_destroy 2686 +#define wxEvent_GetId 2687 +#define wxEvent_GetSkipped 2688 +#define wxEvent_GetTimestamp 2689 +#define wxEvent_IsCommandEvent 2690 +#define wxEvent_ResumePropagation 2691 +#define wxEvent_ShouldPropagate 2692 +#define wxEvent_Skip 2693 +#define wxEvent_StopPropagation 2694 +#define wxCommandEvent_getClientData 2695 +#define wxCommandEvent_GetExtraLong 2696 +#define wxCommandEvent_GetInt 2697 +#define wxCommandEvent_GetSelection 2698 +#define wxCommandEvent_GetString 2699 +#define wxCommandEvent_IsChecked 2700 +#define wxCommandEvent_IsSelection 2701 +#define wxCommandEvent_SetInt 2702 +#define wxCommandEvent_SetString 2703 +#define wxScrollEvent_GetOrientation 2704 +#define wxScrollEvent_GetPosition 2705 +#define wxScrollWinEvent_GetOrientation 2706 +#define wxScrollWinEvent_GetPosition 2707 +#define wxMouseEvent_AltDown 2708 +#define wxMouseEvent_Button 2709 +#define wxMouseEvent_ButtonDClick 2710 +#define wxMouseEvent_ButtonDown 2711 +#define wxMouseEvent_ButtonUp 2712 +#define wxMouseEvent_CmdDown 2713 +#define wxMouseEvent_ControlDown 2714 +#define wxMouseEvent_Dragging 2715 +#define wxMouseEvent_Entering 2716 +#define wxMouseEvent_GetButton 2717 +#define wxMouseEvent_GetPosition 2720 +#define wxMouseEvent_GetLogicalPosition 2721 +#define wxMouseEvent_GetLinesPerAction 2722 +#define wxMouseEvent_GetWheelRotation 2723 +#define wxMouseEvent_GetWheelDelta 2724 +#define wxMouseEvent_GetX 2725 +#define wxMouseEvent_GetY 2726 +#define wxMouseEvent_IsButton 2727 +#define wxMouseEvent_IsPageScroll 2728 +#define wxMouseEvent_Leaving 2729 +#define wxMouseEvent_LeftDClick 2730 +#define wxMouseEvent_LeftDown 2731 +#define wxMouseEvent_LeftIsDown 2732 +#define wxMouseEvent_LeftUp 2733 +#define wxMouseEvent_MetaDown 2734 +#define wxMouseEvent_MiddleDClick 2735 +#define wxMouseEvent_MiddleDown 2736 +#define wxMouseEvent_MiddleIsDown 2737 +#define wxMouseEvent_MiddleUp 2738 +#define wxMouseEvent_Moving 2739 +#define wxMouseEvent_RightDClick 2740 +#define wxMouseEvent_RightDown 2741 +#define wxMouseEvent_RightIsDown 2742 +#define wxMouseEvent_RightUp 2743 +#define wxMouseEvent_ShiftDown 2744 +#define wxSetCursorEvent_GetCursor 2745 +#define wxSetCursorEvent_GetX 2746 +#define wxSetCursorEvent_GetY 2747 +#define wxSetCursorEvent_HasCursor 2748 +#define wxSetCursorEvent_SetCursor 2749 +#define wxKeyEvent_AltDown 2750 +#define wxKeyEvent_CmdDown 2751 +#define wxKeyEvent_ControlDown 2752 +#define wxKeyEvent_GetKeyCode 2753 +#define wxKeyEvent_GetModifiers 2754 +#define wxKeyEvent_GetPosition 2757 +#define wxKeyEvent_GetRawKeyCode 2758 +#define wxKeyEvent_GetRawKeyFlags 2759 +#define wxKeyEvent_GetUnicodeKey 2760 +#define wxKeyEvent_GetX 2761 +#define wxKeyEvent_GetY 2762 +#define wxKeyEvent_HasModifiers 2763 +#define wxKeyEvent_MetaDown 2764 +#define wxKeyEvent_ShiftDown 2765 +#define wxSizeEvent_GetSize 2766 +#define wxMoveEvent_GetPosition 2767 +#define wxEraseEvent_GetDC 2768 +#define wxFocusEvent_GetWindow 2769 +#define wxChildFocusEvent_GetWindow 2770 +#define wxMenuEvent_GetMenu 2771 +#define wxMenuEvent_GetMenuId 2772 +#define wxMenuEvent_IsPopup 2773 +#define wxCloseEvent_CanVeto 2774 +#define wxCloseEvent_GetLoggingOff 2775 +#define wxCloseEvent_SetCanVeto 2776 +#define wxCloseEvent_SetLoggingOff 2777 +#define wxCloseEvent_Veto 2778 +#define wxShowEvent_SetShow 2779 +#define wxShowEvent_GetShow 2780 +#define wxIconizeEvent_Iconized 2781 +#define wxJoystickEvent_ButtonDown 2782 +#define wxJoystickEvent_ButtonIsDown 2783 +#define wxJoystickEvent_ButtonUp 2784 +#define wxJoystickEvent_GetButtonChange 2785 +#define wxJoystickEvent_GetButtonState 2786 +#define wxJoystickEvent_GetJoystick 2787 +#define wxJoystickEvent_GetPosition 2788 +#define wxJoystickEvent_GetZPosition 2789 +#define wxJoystickEvent_IsButton 2790 +#define wxJoystickEvent_IsMove 2791 +#define wxJoystickEvent_IsZMove 2792 +#define wxUpdateUIEvent_CanUpdate 2793 +#define wxUpdateUIEvent_Check 2794 +#define wxUpdateUIEvent_Enable 2795 +#define wxUpdateUIEvent_Show 2796 +#define wxUpdateUIEvent_GetChecked 2797 +#define wxUpdateUIEvent_GetEnabled 2798 +#define wxUpdateUIEvent_GetShown 2799 +#define wxUpdateUIEvent_GetSetChecked 2800 +#define wxUpdateUIEvent_GetSetEnabled 2801 +#define wxUpdateUIEvent_GetSetShown 2802 +#define wxUpdateUIEvent_GetSetText 2803 +#define wxUpdateUIEvent_GetText 2804 +#define wxUpdateUIEvent_GetMode 2805 +#define wxUpdateUIEvent_GetUpdateInterval 2806 +#define wxUpdateUIEvent_ResetUpdateTime 2807 +#define wxUpdateUIEvent_SetMode 2808 +#define wxUpdateUIEvent_SetText 2809 +#define wxUpdateUIEvent_SetUpdateInterval 2810 +#define wxMouseCaptureChangedEvent_GetCapturedWindow 2811 +#define wxPaletteChangedEvent_SetChangedWindow 2812 +#define wxPaletteChangedEvent_GetChangedWindow 2813 +#define wxQueryNewPaletteEvent_SetPaletteRealized 2814 +#define wxQueryNewPaletteEvent_GetPaletteRealized 2815 +#define wxNavigationKeyEvent_GetDirection 2816 +#define wxNavigationKeyEvent_SetDirection 2817 +#define wxNavigationKeyEvent_IsWindowChange 2818 +#define wxNavigationKeyEvent_SetWindowChange 2819 +#define wxNavigationKeyEvent_IsFromTab 2820 +#define wxNavigationKeyEvent_SetFromTab 2821 +#define wxNavigationKeyEvent_GetCurrentFocus 2822 +#define wxNavigationKeyEvent_SetCurrentFocus 2823 +#define wxHelpEvent_GetOrigin 2824 +#define wxHelpEvent_GetPosition 2825 +#define wxHelpEvent_SetOrigin 2826 +#define wxHelpEvent_SetPosition 2827 +#define wxContextMenuEvent_GetPosition 2828 +#define wxContextMenuEvent_SetPosition 2829 +#define wxIdleEvent_CanSend 2830 +#define wxIdleEvent_GetMode 2831 +#define wxIdleEvent_RequestMore 2832 +#define wxIdleEvent_MoreRequested 2833 +#define wxIdleEvent_SetMode 2834 +#define wxGridEvent_AltDown 2835 +#define wxGridEvent_ControlDown 2836 +#define wxGridEvent_GetCol 2837 +#define wxGridEvent_GetPosition 2838 +#define wxGridEvent_GetRow 2839 +#define wxGridEvent_MetaDown 2840 +#define wxGridEvent_Selecting 2841 +#define wxGridEvent_ShiftDown 2842 +#define wxNotifyEvent_Allow 2843 +#define wxNotifyEvent_IsAllowed 2844 +#define wxNotifyEvent_Veto 2845 +#define wxSashEvent_GetEdge 2846 +#define wxSashEvent_GetDragRect 2847 +#define wxSashEvent_GetDragStatus 2848 +#define wxListEvent_GetCacheFrom 2849 +#define wxListEvent_GetCacheTo 2850 +#define wxListEvent_GetKeyCode 2851 +#define wxListEvent_GetIndex 2852 +#define wxListEvent_GetColumn 2853 +#define wxListEvent_GetPoint 2854 +#define wxListEvent_GetLabel 2855 +#define wxListEvent_GetText 2856 +#define wxListEvent_GetImage 2857 +#define wxListEvent_GetData 2858 +#define wxListEvent_GetMask 2859 +#define wxListEvent_GetItem 2860 +#define wxListEvent_IsEditCancelled 2861 +#define wxDateEvent_GetDate 2862 +#define wxCalendarEvent_GetWeekDay 2863 +#define wxFileDirPickerEvent_GetPath 2864 +#define wxColourPickerEvent_GetColour 2865 +#define wxFontPickerEvent_GetFont 2866 +#define wxStyledTextEvent_GetPosition 2867 +#define wxStyledTextEvent_GetKey 2868 +#define wxStyledTextEvent_GetModifiers 2869 +#define wxStyledTextEvent_GetModificationType 2870 +#define wxStyledTextEvent_GetText 2871 +#define wxStyledTextEvent_GetLength 2872 +#define wxStyledTextEvent_GetLinesAdded 2873 +#define wxStyledTextEvent_GetLine 2874 +#define wxStyledTextEvent_GetFoldLevelNow 2875 +#define wxStyledTextEvent_GetFoldLevelPrev 2876 +#define wxStyledTextEvent_GetMargin 2877 +#define wxStyledTextEvent_GetMessage 2878 +#define wxStyledTextEvent_GetWParam 2879 +#define wxStyledTextEvent_GetLParam 2880 +#define wxStyledTextEvent_GetListType 2881 +#define wxStyledTextEvent_GetX 2882 +#define wxStyledTextEvent_GetY 2883 +#define wxStyledTextEvent_GetDragText 2884 +#define wxStyledTextEvent_GetDragAllowMove 2885 +#define wxStyledTextEvent_GetDragResult 2886 +#define wxStyledTextEvent_GetShift 2887 +#define wxStyledTextEvent_GetControl 2888 +#define wxStyledTextEvent_GetAlt 2889 +#define utils_wxGetKeyState 2890 +#define utils_wxGetMousePosition 2891 +#define utils_wxGetMouseState 2892 +#define utils_wxSetDetectableAutoRepeat 2893 +#define utils_wxBell 2894 +#define utils_wxFindMenuItemId 2895 +#define utils_wxGenericFindWindowAtPoint 2896 +#define utils_wxFindWindowAtPoint 2897 +#define utils_wxBeginBusyCursor 2898 +#define utils_wxEndBusyCursor 2899 +#define utils_wxIsBusy 2900 +#define utils_wxShutdown 2901 +#define utils_wxShell 2902 +#define utils_wxLaunchDefaultBrowser 2903 +#define utils_wxGetEmailAddress 2904 +#define utils_wxGetUserId 2905 +#define utils_wxGetHomeDir 2906 +#define utils_wxNewId 2907 +#define utils_wxRegisterId 2908 +#define utils_wxGetCurrentId 2909 +#define utils_wxGetOsDescription 2910 +#define utils_wxIsPlatformLittleEndian 2911 +#define utils_wxIsPlatform64Bit 2912 +#define wxPrintout_new 2913 +#define wxPrintout_destruct 2914 +#define wxPrintout_GetDC 2915 +#define wxPrintout_GetPageSizeMM 2916 +#define wxPrintout_GetPageSizePixels 2917 +#define wxPrintout_GetPaperRectPixels 2918 +#define wxPrintout_GetPPIPrinter 2919 +#define wxPrintout_GetPPIScreen 2920 +#define wxPrintout_GetTitle 2921 +#define wxPrintout_IsPreview 2922 +#define wxPrintout_FitThisSizeToPaper 2923 +#define wxPrintout_FitThisSizeToPage 2924 +#define wxPrintout_FitThisSizeToPageMargins 2925 +#define wxPrintout_MapScreenSizeToPaper 2926 +#define wxPrintout_MapScreenSizeToPage 2927 +#define wxPrintout_MapScreenSizeToPageMargins 2928 +#define wxPrintout_MapScreenSizeToDevice 2929 +#define wxPrintout_GetLogicalPaperRect 2930 +#define wxPrintout_GetLogicalPageRect 2931 +#define wxPrintout_GetLogicalPageMarginsRect 2932 +#define wxPrintout_SetLogicalOrigin 2933 +#define wxPrintout_OffsetLogicalOrigin 2934 +#define wxStyledTextCtrl_new_2 2935 +#define wxStyledTextCtrl_new_0 2936 +#define wxStyledTextCtrl_destruct 2937 +#define wxStyledTextCtrl_Create 2938 +#define wxStyledTextCtrl_AddText 2939 +#define wxStyledTextCtrl_AddStyledText 2940 +#define wxStyledTextCtrl_InsertText 2941 +#define wxStyledTextCtrl_ClearAll 2942 +#define wxStyledTextCtrl_ClearDocumentStyle 2943 +#define wxStyledTextCtrl_GetLength 2944 +#define wxStyledTextCtrl_GetCharAt 2945 +#define wxStyledTextCtrl_GetCurrentPos 2946 +#define wxStyledTextCtrl_GetAnchor 2947 +#define wxStyledTextCtrl_GetStyleAt 2948 +#define wxStyledTextCtrl_Redo 2949 +#define wxStyledTextCtrl_SetUndoCollection 2950 +#define wxStyledTextCtrl_SelectAll 2951 +#define wxStyledTextCtrl_SetSavePoint 2952 +#define wxStyledTextCtrl_GetStyledText 2953 +#define wxStyledTextCtrl_CanRedo 2954 +#define wxStyledTextCtrl_MarkerLineFromHandle 2955 +#define wxStyledTextCtrl_MarkerDeleteHandle 2956 +#define wxStyledTextCtrl_GetUndoCollection 2957 +#define wxStyledTextCtrl_GetViewWhiteSpace 2958 +#define wxStyledTextCtrl_SetViewWhiteSpace 2959 +#define wxStyledTextCtrl_PositionFromPoint 2960 +#define wxStyledTextCtrl_PositionFromPointClose 2961 +#define wxStyledTextCtrl_GotoLine 2962 +#define wxStyledTextCtrl_GotoPos 2963 +#define wxStyledTextCtrl_SetAnchor 2964 +#define wxStyledTextCtrl_GetCurLine 2965 +#define wxStyledTextCtrl_GetEndStyled 2966 +#define wxStyledTextCtrl_ConvertEOLs 2967 +#define wxStyledTextCtrl_GetEOLMode 2968 +#define wxStyledTextCtrl_SetEOLMode 2969 +#define wxStyledTextCtrl_StartStyling 2970 +#define wxStyledTextCtrl_SetStyling 2971 +#define wxStyledTextCtrl_GetBufferedDraw 2972 +#define wxStyledTextCtrl_SetBufferedDraw 2973 +#define wxStyledTextCtrl_SetTabWidth 2974 +#define wxStyledTextCtrl_GetTabWidth 2975 +#define wxStyledTextCtrl_SetCodePage 2976 +#define wxStyledTextCtrl_MarkerDefine 2977 +#define wxStyledTextCtrl_MarkerSetForeground 2978 +#define wxStyledTextCtrl_MarkerSetBackground 2979 +#define wxStyledTextCtrl_MarkerAdd 2980 +#define wxStyledTextCtrl_MarkerDelete 2981 +#define wxStyledTextCtrl_MarkerDeleteAll 2982 +#define wxStyledTextCtrl_MarkerGet 2983 +#define wxStyledTextCtrl_MarkerNext 2984 +#define wxStyledTextCtrl_MarkerPrevious 2985 +#define wxStyledTextCtrl_MarkerDefineBitmap 2986 +#define wxStyledTextCtrl_MarkerAddSet 2987 +#define wxStyledTextCtrl_MarkerSetAlpha 2988 +#define wxStyledTextCtrl_SetMarginType 2989 +#define wxStyledTextCtrl_GetMarginType 2990 +#define wxStyledTextCtrl_SetMarginWidth 2991 +#define wxStyledTextCtrl_GetMarginWidth 2992 +#define wxStyledTextCtrl_SetMarginMask 2993 +#define wxStyledTextCtrl_GetMarginMask 2994 +#define wxStyledTextCtrl_SetMarginSensitive 2995 +#define wxStyledTextCtrl_GetMarginSensitive 2996 +#define wxStyledTextCtrl_StyleClearAll 2997 +#define wxStyledTextCtrl_StyleSetForeground 2998 +#define wxStyledTextCtrl_StyleSetBackground 2999 +#define wxStyledTextCtrl_StyleSetBold 3000 +#define wxStyledTextCtrl_StyleSetItalic 3001 +#define wxStyledTextCtrl_StyleSetSize 3002 +#define wxStyledTextCtrl_StyleSetFaceName 3003 +#define wxStyledTextCtrl_StyleSetEOLFilled 3004 +#define wxStyledTextCtrl_StyleResetDefault 3005 +#define wxStyledTextCtrl_StyleSetUnderline 3006 +#define wxStyledTextCtrl_StyleSetCase 3007 +#define wxStyledTextCtrl_StyleSetHotSpot 3008 +#define wxStyledTextCtrl_SetSelForeground 3009 +#define wxStyledTextCtrl_SetSelBackground 3010 +#define wxStyledTextCtrl_GetSelAlpha 3011 +#define wxStyledTextCtrl_SetSelAlpha 3012 +#define wxStyledTextCtrl_SetCaretForeground 3013 +#define wxStyledTextCtrl_CmdKeyAssign 3014 +#define wxStyledTextCtrl_CmdKeyClear 3015 +#define wxStyledTextCtrl_CmdKeyClearAll 3016 +#define wxStyledTextCtrl_SetStyleBytes 3017 +#define wxStyledTextCtrl_StyleSetVisible 3018 +#define wxStyledTextCtrl_GetCaretPeriod 3019 +#define wxStyledTextCtrl_SetCaretPeriod 3020 +#define wxStyledTextCtrl_SetWordChars 3021 +#define wxStyledTextCtrl_BeginUndoAction 3022 +#define wxStyledTextCtrl_EndUndoAction 3023 +#define wxStyledTextCtrl_IndicatorSetStyle 3024 +#define wxStyledTextCtrl_IndicatorGetStyle 3025 +#define wxStyledTextCtrl_IndicatorSetForeground 3026 +#define wxStyledTextCtrl_IndicatorGetForeground 3027 +#define wxStyledTextCtrl_SetWhitespaceForeground 3028 +#define wxStyledTextCtrl_SetWhitespaceBackground 3029 +#define wxStyledTextCtrl_GetStyleBits 3030 +#define wxStyledTextCtrl_SetLineState 3031 +#define wxStyledTextCtrl_GetLineState 3032 +#define wxStyledTextCtrl_GetMaxLineState 3033 +#define wxStyledTextCtrl_GetCaretLineVisible 3034 +#define wxStyledTextCtrl_SetCaretLineVisible 3035 +#define wxStyledTextCtrl_GetCaretLineBackground 3036 +#define wxStyledTextCtrl_SetCaretLineBackground 3037 +#define wxStyledTextCtrl_AutoCompShow 3038 +#define wxStyledTextCtrl_AutoCompCancel 3039 +#define wxStyledTextCtrl_AutoCompActive 3040 +#define wxStyledTextCtrl_AutoCompPosStart 3041 +#define wxStyledTextCtrl_AutoCompComplete 3042 +#define wxStyledTextCtrl_AutoCompStops 3043 +#define wxStyledTextCtrl_AutoCompSetSeparator 3044 +#define wxStyledTextCtrl_AutoCompGetSeparator 3045 +#define wxStyledTextCtrl_AutoCompSelect 3046 +#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3047 +#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3048 +#define wxStyledTextCtrl_AutoCompSetFillUps 3049 +#define wxStyledTextCtrl_AutoCompSetChooseSingle 3050 +#define wxStyledTextCtrl_AutoCompGetChooseSingle 3051 +#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3052 +#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3053 +#define wxStyledTextCtrl_UserListShow 3054 +#define wxStyledTextCtrl_AutoCompSetAutoHide 3055 +#define wxStyledTextCtrl_AutoCompGetAutoHide 3056 +#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3057 +#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3058 +#define wxStyledTextCtrl_RegisterImage 3059 +#define wxStyledTextCtrl_ClearRegisteredImages 3060 +#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3061 +#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3062 +#define wxStyledTextCtrl_AutoCompSetMaxWidth 3063 +#define wxStyledTextCtrl_AutoCompGetMaxWidth 3064 +#define wxStyledTextCtrl_AutoCompSetMaxHeight 3065 +#define wxStyledTextCtrl_AutoCompGetMaxHeight 3066 +#define wxStyledTextCtrl_SetIndent 3067 +#define wxStyledTextCtrl_GetIndent 3068 +#define wxStyledTextCtrl_SetUseTabs 3069 +#define wxStyledTextCtrl_GetUseTabs 3070 +#define wxStyledTextCtrl_SetLineIndentation 3071 +#define wxStyledTextCtrl_GetLineIndentation 3072 +#define wxStyledTextCtrl_GetLineIndentPosition 3073 +#define wxStyledTextCtrl_GetColumn 3074 +#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3075 +#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3076 +#define wxStyledTextCtrl_SetIndentationGuides 3077 +#define wxStyledTextCtrl_GetIndentationGuides 3078 +#define wxStyledTextCtrl_SetHighlightGuide 3079 +#define wxStyledTextCtrl_GetHighlightGuide 3080 +#define wxStyledTextCtrl_GetLineEndPosition 3081 +#define wxStyledTextCtrl_GetCodePage 3082 +#define wxStyledTextCtrl_GetCaretForeground 3083 +#define wxStyledTextCtrl_GetReadOnly 3084 +#define wxStyledTextCtrl_SetCurrentPos 3085 +#define wxStyledTextCtrl_SetSelectionStart 3086 +#define wxStyledTextCtrl_GetSelectionStart 3087 +#define wxStyledTextCtrl_SetSelectionEnd 3088 +#define wxStyledTextCtrl_GetSelectionEnd 3089 +#define wxStyledTextCtrl_SetPrintMagnification 3090 +#define wxStyledTextCtrl_GetPrintMagnification 3091 +#define wxStyledTextCtrl_SetPrintColourMode 3092 +#define wxStyledTextCtrl_GetPrintColourMode 3093 +#define wxStyledTextCtrl_FindText 3094 +#define wxStyledTextCtrl_FormatRange 3095 +#define wxStyledTextCtrl_GetFirstVisibleLine 3096 +#define wxStyledTextCtrl_GetLine 3097 +#define wxStyledTextCtrl_GetLineCount 3098 +#define wxStyledTextCtrl_SetMarginLeft 3099 +#define wxStyledTextCtrl_GetMarginLeft 3100 +#define wxStyledTextCtrl_SetMarginRight 3101 +#define wxStyledTextCtrl_GetMarginRight 3102 +#define wxStyledTextCtrl_GetModify 3103 +#define wxStyledTextCtrl_SetSelection 3104 +#define wxStyledTextCtrl_GetSelectedText 3105 +#define wxStyledTextCtrl_GetTextRange 3106 +#define wxStyledTextCtrl_HideSelection 3107 +#define wxStyledTextCtrl_LineFromPosition 3108 +#define wxStyledTextCtrl_PositionFromLine 3109 +#define wxStyledTextCtrl_LineScroll 3110 +#define wxStyledTextCtrl_EnsureCaretVisible 3111 +#define wxStyledTextCtrl_ReplaceSelection 3112 +#define wxStyledTextCtrl_SetReadOnly 3113 +#define wxStyledTextCtrl_CanPaste 3114 +#define wxStyledTextCtrl_CanUndo 3115 +#define wxStyledTextCtrl_EmptyUndoBuffer 3116 +#define wxStyledTextCtrl_Undo 3117 +#define wxStyledTextCtrl_Cut 3118 +#define wxStyledTextCtrl_Copy 3119 +#define wxStyledTextCtrl_Paste 3120 +#define wxStyledTextCtrl_Clear 3121 +#define wxStyledTextCtrl_SetText 3122 +#define wxStyledTextCtrl_GetText 3123 +#define wxStyledTextCtrl_GetTextLength 3124 +#define wxStyledTextCtrl_GetOvertype 3125 +#define wxStyledTextCtrl_SetCaretWidth 3126 +#define wxStyledTextCtrl_GetCaretWidth 3127 +#define wxStyledTextCtrl_SetTargetStart 3128 +#define wxStyledTextCtrl_GetTargetStart 3129 +#define wxStyledTextCtrl_SetTargetEnd 3130 +#define wxStyledTextCtrl_GetTargetEnd 3131 +#define wxStyledTextCtrl_ReplaceTarget 3132 +#define wxStyledTextCtrl_SearchInTarget 3133 +#define wxStyledTextCtrl_SetSearchFlags 3134 +#define wxStyledTextCtrl_GetSearchFlags 3135 +#define wxStyledTextCtrl_CallTipShow 3136 +#define wxStyledTextCtrl_CallTipCancel 3137 +#define wxStyledTextCtrl_CallTipActive 3138 +#define wxStyledTextCtrl_CallTipPosAtStart 3139 +#define wxStyledTextCtrl_CallTipSetHighlight 3140 +#define wxStyledTextCtrl_CallTipSetBackground 3141 +#define wxStyledTextCtrl_CallTipSetForeground 3142 +#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3143 +#define wxStyledTextCtrl_CallTipUseStyle 3144 +#define wxStyledTextCtrl_VisibleFromDocLine 3145 +#define wxStyledTextCtrl_DocLineFromVisible 3146 +#define wxStyledTextCtrl_WrapCount 3147 +#define wxStyledTextCtrl_SetFoldLevel 3148 +#define wxStyledTextCtrl_GetFoldLevel 3149 +#define wxStyledTextCtrl_GetLastChild 3150 +#define wxStyledTextCtrl_GetFoldParent 3151 +#define wxStyledTextCtrl_ShowLines 3152 +#define wxStyledTextCtrl_HideLines 3153 +#define wxStyledTextCtrl_GetLineVisible 3154 +#define wxStyledTextCtrl_SetFoldExpanded 3155 +#define wxStyledTextCtrl_GetFoldExpanded 3156 +#define wxStyledTextCtrl_ToggleFold 3157 +#define wxStyledTextCtrl_EnsureVisible 3158 +#define wxStyledTextCtrl_SetFoldFlags 3159 +#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3160 +#define wxStyledTextCtrl_SetTabIndents 3161 +#define wxStyledTextCtrl_GetTabIndents 3162 +#define wxStyledTextCtrl_SetBackSpaceUnIndents 3163 +#define wxStyledTextCtrl_GetBackSpaceUnIndents 3164 +#define wxStyledTextCtrl_SetMouseDwellTime 3165 +#define wxStyledTextCtrl_GetMouseDwellTime 3166 +#define wxStyledTextCtrl_WordStartPosition 3167 +#define wxStyledTextCtrl_WordEndPosition 3168 +#define wxStyledTextCtrl_SetWrapMode 3169 +#define wxStyledTextCtrl_GetWrapMode 3170 +#define wxStyledTextCtrl_SetWrapVisualFlags 3171 +#define wxStyledTextCtrl_GetWrapVisualFlags 3172 +#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3173 +#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3174 +#define wxStyledTextCtrl_SetWrapStartIndent 3175 +#define wxStyledTextCtrl_GetWrapStartIndent 3176 +#define wxStyledTextCtrl_SetLayoutCache 3177 +#define wxStyledTextCtrl_GetLayoutCache 3178 +#define wxStyledTextCtrl_SetScrollWidth 3179 +#define wxStyledTextCtrl_GetScrollWidth 3180 +#define wxStyledTextCtrl_TextWidth 3181 +#define wxStyledTextCtrl_GetEndAtLastLine 3182 +#define wxStyledTextCtrl_TextHeight 3183 +#define wxStyledTextCtrl_SetUseVerticalScrollBar 3184 +#define wxStyledTextCtrl_GetUseVerticalScrollBar 3185 +#define wxStyledTextCtrl_AppendText 3186 +#define wxStyledTextCtrl_GetTwoPhaseDraw 3187 +#define wxStyledTextCtrl_SetTwoPhaseDraw 3188 +#define wxStyledTextCtrl_TargetFromSelection 3189 +#define wxStyledTextCtrl_LinesJoin 3190 +#define wxStyledTextCtrl_LinesSplit 3191 +#define wxStyledTextCtrl_SetFoldMarginColour 3192 +#define wxStyledTextCtrl_SetFoldMarginHiColour 3193 +#define wxStyledTextCtrl_LineDown 3194 +#define wxStyledTextCtrl_LineDownExtend 3195 +#define wxStyledTextCtrl_LineUp 3196 +#define wxStyledTextCtrl_LineUpExtend 3197 +#define wxStyledTextCtrl_CharLeft 3198 +#define wxStyledTextCtrl_CharLeftExtend 3199 +#define wxStyledTextCtrl_CharRight 3200 +#define wxStyledTextCtrl_CharRightExtend 3201 +#define wxStyledTextCtrl_WordLeft 3202 +#define wxStyledTextCtrl_WordLeftExtend 3203 +#define wxStyledTextCtrl_WordRight 3204 +#define wxStyledTextCtrl_WordRightExtend 3205 +#define wxStyledTextCtrl_Home 3206 +#define wxStyledTextCtrl_HomeExtend 3207 +#define wxStyledTextCtrl_LineEnd 3208 +#define wxStyledTextCtrl_LineEndExtend 3209 +#define wxStyledTextCtrl_DocumentStart 3210 +#define wxStyledTextCtrl_DocumentStartExtend 3211 +#define wxStyledTextCtrl_DocumentEnd 3212 +#define wxStyledTextCtrl_DocumentEndExtend 3213 +#define wxStyledTextCtrl_PageUp 3214 +#define wxStyledTextCtrl_PageUpExtend 3215 +#define wxStyledTextCtrl_PageDown 3216 +#define wxStyledTextCtrl_PageDownExtend 3217 +#define wxStyledTextCtrl_EditToggleOvertype 3218 +#define wxStyledTextCtrl_Cancel 3219 +#define wxStyledTextCtrl_DeleteBack 3220 +#define wxStyledTextCtrl_Tab 3221 +#define wxStyledTextCtrl_BackTab 3222 +#define wxStyledTextCtrl_NewLine 3223 +#define wxStyledTextCtrl_FormFeed 3224 +#define wxStyledTextCtrl_VCHome 3225 +#define wxStyledTextCtrl_VCHomeExtend 3226 +#define wxStyledTextCtrl_ZoomIn 3227 +#define wxStyledTextCtrl_ZoomOut 3228 +#define wxStyledTextCtrl_DelWordLeft 3229 +#define wxStyledTextCtrl_DelWordRight 3230 +#define wxStyledTextCtrl_LineCut 3231 +#define wxStyledTextCtrl_LineDelete 3232 +#define wxStyledTextCtrl_LineTranspose 3233 +#define wxStyledTextCtrl_LineDuplicate 3234 +#define wxStyledTextCtrl_LowerCase 3235 +#define wxStyledTextCtrl_UpperCase 3236 +#define wxStyledTextCtrl_LineScrollDown 3237 +#define wxStyledTextCtrl_LineScrollUp 3238 +#define wxStyledTextCtrl_DeleteBackNotLine 3239 +#define wxStyledTextCtrl_HomeDisplay 3240 +#define wxStyledTextCtrl_HomeDisplayExtend 3241 +#define wxStyledTextCtrl_LineEndDisplay 3242 +#define wxStyledTextCtrl_LineEndDisplayExtend 3243 +#define wxStyledTextCtrl_HomeWrapExtend 3244 +#define wxStyledTextCtrl_LineEndWrap 3245 +#define wxStyledTextCtrl_LineEndWrapExtend 3246 +#define wxStyledTextCtrl_VCHomeWrap 3247 +#define wxStyledTextCtrl_VCHomeWrapExtend 3248 +#define wxStyledTextCtrl_LineCopy 3249 +#define wxStyledTextCtrl_MoveCaretInsideView 3250 +#define wxStyledTextCtrl_LineLength 3251 +#define wxStyledTextCtrl_BraceHighlight 3252 +#define wxStyledTextCtrl_BraceBadLight 3253 +#define wxStyledTextCtrl_BraceMatch 3254 +#define wxStyledTextCtrl_GetViewEOL 3255 +#define wxStyledTextCtrl_SetViewEOL 3256 +#define wxStyledTextCtrl_SetModEventMask 3257 +#define wxStyledTextCtrl_GetEdgeColumn 3258 +#define wxStyledTextCtrl_SetEdgeColumn 3259 +#define wxStyledTextCtrl_GetEdgeMode 3260 +#define wxStyledTextCtrl_GetEdgeColour 3261 +#define wxStyledTextCtrl_SetEdgeColour 3262 +#define wxStyledTextCtrl_SearchAnchor 3263 +#define wxStyledTextCtrl_SearchNext 3264 +#define wxStyledTextCtrl_SearchPrev 3265 +#define wxStyledTextCtrl_LinesOnScreen 3266 +#define wxStyledTextCtrl_UsePopUp 3267 +#define wxStyledTextCtrl_SelectionIsRectangle 3268 +#define wxStyledTextCtrl_SetZoom 3269 +#define wxStyledTextCtrl_GetZoom 3270 +#define wxStyledTextCtrl_GetModEventMask 3271 +#define wxStyledTextCtrl_SetSTCFocus 3272 +#define wxStyledTextCtrl_GetSTCFocus 3273 +#define wxStyledTextCtrl_SetStatus 3274 +#define wxStyledTextCtrl_GetStatus 3275 +#define wxStyledTextCtrl_SetMouseDownCaptures 3276 +#define wxStyledTextCtrl_GetMouseDownCaptures 3277 +#define wxStyledTextCtrl_SetSTCCursor 3278 +#define wxStyledTextCtrl_GetSTCCursor 3279 +#define wxStyledTextCtrl_SetControlCharSymbol 3280 +#define wxStyledTextCtrl_GetControlCharSymbol 3281 +#define wxStyledTextCtrl_WordPartLeft 3282 +#define wxStyledTextCtrl_WordPartLeftExtend 3283 +#define wxStyledTextCtrl_WordPartRight 3284 +#define wxStyledTextCtrl_WordPartRightExtend 3285 +#define wxStyledTextCtrl_SetVisiblePolicy 3286 +#define wxStyledTextCtrl_DelLineLeft 3287 +#define wxStyledTextCtrl_DelLineRight 3288 +#define wxStyledTextCtrl_GetXOffset 3289 +#define wxStyledTextCtrl_ChooseCaretX 3290 +#define wxStyledTextCtrl_SetXCaretPolicy 3291 +#define wxStyledTextCtrl_SetYCaretPolicy 3292 +#define wxStyledTextCtrl_GetPrintWrapMode 3293 +#define wxStyledTextCtrl_SetHotspotActiveForeground 3294 +#define wxStyledTextCtrl_SetHotspotActiveBackground 3295 +#define wxStyledTextCtrl_SetHotspotActiveUnderline 3296 +#define wxStyledTextCtrl_SetHotspotSingleLine 3297 +#define wxStyledTextCtrl_ParaDownExtend 3298 +#define wxStyledTextCtrl_ParaUp 3299 +#define wxStyledTextCtrl_ParaUpExtend 3300 +#define wxStyledTextCtrl_PositionBefore 3301 +#define wxStyledTextCtrl_PositionAfter 3302 +#define wxStyledTextCtrl_CopyRange 3303 +#define wxStyledTextCtrl_CopyText 3304 +#define wxStyledTextCtrl_SetSelectionMode 3305 +#define wxStyledTextCtrl_GetSelectionMode 3306 +#define wxStyledTextCtrl_LineDownRectExtend 3307 +#define wxStyledTextCtrl_LineUpRectExtend 3308 +#define wxStyledTextCtrl_CharLeftRectExtend 3309 +#define wxStyledTextCtrl_CharRightRectExtend 3310 +#define wxStyledTextCtrl_HomeRectExtend 3311 +#define wxStyledTextCtrl_VCHomeRectExtend 3312 +#define wxStyledTextCtrl_LineEndRectExtend 3313 +#define wxStyledTextCtrl_PageUpRectExtend 3314 +#define wxStyledTextCtrl_PageDownRectExtend 3315 +#define wxStyledTextCtrl_StutteredPageUp 3316 +#define wxStyledTextCtrl_StutteredPageUpExtend 3317 +#define wxStyledTextCtrl_StutteredPageDown 3318 +#define wxStyledTextCtrl_StutteredPageDownExtend 3319 +#define wxStyledTextCtrl_WordLeftEnd 3320 +#define wxStyledTextCtrl_WordLeftEndExtend 3321 +#define wxStyledTextCtrl_WordRightEnd 3322 +#define wxStyledTextCtrl_WordRightEndExtend 3323 +#define wxStyledTextCtrl_SetWhitespaceChars 3324 +#define wxStyledTextCtrl_SetCharsDefault 3325 +#define wxStyledTextCtrl_AutoCompGetCurrent 3326 +#define wxStyledTextCtrl_Allocate 3327 +#define wxStyledTextCtrl_FindColumn 3328 +#define wxStyledTextCtrl_GetCaretSticky 3329 +#define wxStyledTextCtrl_SetCaretSticky 3330 +#define wxStyledTextCtrl_ToggleCaretSticky 3331 +#define wxStyledTextCtrl_SetPasteConvertEndings 3332 +#define wxStyledTextCtrl_GetPasteConvertEndings 3333 +#define wxStyledTextCtrl_SelectionDuplicate 3334 +#define wxStyledTextCtrl_SetCaretLineBackAlpha 3335 +#define wxStyledTextCtrl_GetCaretLineBackAlpha 3336 +#define wxStyledTextCtrl_StartRecord 3337 +#define wxStyledTextCtrl_StopRecord 3338 +#define wxStyledTextCtrl_SetLexer 3339 +#define wxStyledTextCtrl_GetLexer 3340 +#define wxStyledTextCtrl_Colourise 3341 +#define wxStyledTextCtrl_SetProperty 3342 +#define wxStyledTextCtrl_SetKeyWords 3343 +#define wxStyledTextCtrl_SetLexerLanguage 3344 +#define wxStyledTextCtrl_GetProperty 3345 +#define wxStyledTextCtrl_GetStyleBitsNeeded 3346 +#define wxStyledTextCtrl_GetCurrentLine 3347 +#define wxStyledTextCtrl_StyleSetSpec 3348 +#define wxStyledTextCtrl_StyleSetFont 3349 +#define wxStyledTextCtrl_StyleSetFontAttr 3350 +#define wxStyledTextCtrl_StyleSetCharacterSet 3351 +#define wxStyledTextCtrl_StyleSetFontEncoding 3352 +#define wxStyledTextCtrl_CmdKeyExecute 3353 +#define wxStyledTextCtrl_SetMargins 3354 +#define wxStyledTextCtrl_GetSelection 3355 +#define wxStyledTextCtrl_PointFromPosition 3356 +#define wxStyledTextCtrl_ScrollToLine 3357 +#define wxStyledTextCtrl_ScrollToColumn 3358 +#define wxStyledTextCtrl_SendMsg 3359 +#define wxStyledTextCtrl_SetVScrollBar 3360 +#define wxStyledTextCtrl_SetHScrollBar 3361 +#define wxStyledTextCtrl_GetLastKeydownProcessed 3362 +#define wxStyledTextCtrl_SetLastKeydownProcessed 3363 +#define wxStyledTextCtrl_SaveFile 3364 +#define wxStyledTextCtrl_LoadFile 3365 +#define wxStyledTextCtrl_DoDragOver 3366 +#define wxStyledTextCtrl_DoDropText 3367 +#define wxStyledTextCtrl_GetUseAntiAliasing 3368 +#define wxStyledTextCtrl_AddTextRaw 3369 +#define wxStyledTextCtrl_InsertTextRaw 3370 +#define wxStyledTextCtrl_GetCurLineRaw 3371 +#define wxStyledTextCtrl_GetLineRaw 3372 +#define wxStyledTextCtrl_GetSelectedTextRaw 3373 +#define wxStyledTextCtrl_GetTextRangeRaw 3374 +#define wxStyledTextCtrl_SetTextRaw 3375 +#define wxStyledTextCtrl_GetTextRaw 3376 +#define wxStyledTextCtrl_AppendTextRaw 3377 +#define wxArtProvider_GetBitmap 3378 +#define wxArtProvider_GetIcon 3379 +#define wxTreeEvent_GetKeyCode 3380 +#define wxTreeEvent_GetItem 3381 +#define wxTreeEvent_GetKeyEvent 3382 +#define wxTreeEvent_GetLabel 3383 +#define wxTreeEvent_GetOldItem 3384 +#define wxTreeEvent_GetPoint 3385 +#define wxTreeEvent_IsEditCancelled 3386 +#define wxTreeEvent_SetToolTip 3387 +#define wxNotebookEvent_GetOldSelection 3388 +#define wxNotebookEvent_GetSelection 3389 +#define wxNotebookEvent_SetOldSelection 3390 +#define wxNotebookEvent_SetSelection 3391 +#define wxFileDataObject_new 3392 +#define wxFileDataObject_AddFile 3393 +#define wxFileDataObject_GetFilenames 3394 +#define wxFileDataObject_destroy 3395 +#define wxTextDataObject_new 3396 +#define wxTextDataObject_GetTextLength 3397 +#define wxTextDataObject_GetText 3398 +#define wxTextDataObject_SetText 3399 +#define wxTextDataObject_destroy 3400 +#define wxBitmapDataObject_new_1_1 3401 +#define wxBitmapDataObject_new_1_0 3402 +#define wxBitmapDataObject_GetBitmap 3403 +#define wxBitmapDataObject_SetBitmap 3404 +#define wxBitmapDataObject_destroy 3405 +#define wxClipboard_new 3407 +#define wxClipboard_destruct 3408 +#define wxClipboard_AddData 3409 +#define wxClipboard_Clear 3410 +#define wxClipboard_Close 3411 +#define wxClipboard_Flush 3412 +#define wxClipboard_GetData 3413 +#define wxClipboard_IsOpened 3414 +#define wxClipboard_Open 3415 +#define wxClipboard_SetData 3416 +#define wxClipboard_UsePrimarySelection 3418 +#define wxClipboard_IsSupported 3419 +#define wxClipboard_Get 3420 +#define wxSpinEvent_GetPosition 3421 +#define wxSpinEvent_SetPosition 3422 +#define wxSplitterWindow_new_0 3423 +#define wxSplitterWindow_new_2 3424 +#define wxSplitterWindow_destruct 3425 +#define wxSplitterWindow_Create 3426 +#define wxSplitterWindow_GetMinimumPaneSize 3427 +#define wxSplitterWindow_GetSashGravity 3428 +#define wxSplitterWindow_GetSashPosition 3429 +#define wxSplitterWindow_GetSplitMode 3430 +#define wxSplitterWindow_GetWindow1 3431 +#define wxSplitterWindow_GetWindow2 3432 +#define wxSplitterWindow_Initialize 3433 +#define wxSplitterWindow_IsSplit 3434 +#define wxSplitterWindow_ReplaceWindow 3435 +#define wxSplitterWindow_SetSashGravity 3436 +#define wxSplitterWindow_SetSashPosition 3437 +#define wxSplitterWindow_SetSashSize 3438 +#define wxSplitterWindow_SetMinimumPaneSize 3439 +#define wxSplitterWindow_SetSplitMode 3440 +#define wxSplitterWindow_SplitHorizontally 3441 +#define wxSplitterWindow_SplitVertically 3442 +#define wxSplitterWindow_Unsplit 3443 +#define wxSplitterWindow_UpdateSize 3444 +#define wxSplitterEvent_GetSashPosition 3445 +#define wxSplitterEvent_GetX 3446 +#define wxSplitterEvent_GetY 3447 +#define wxSplitterEvent_GetWindowBeingRemoved 3448 +#define wxSplitterEvent_SetSashPosition 3449 +#define wxHtmlWindow_new_0 3450 +#define wxHtmlWindow_new_2 3451 +#define wxHtmlWindow_AppendToPage 3452 +#define wxHtmlWindow_GetOpenedAnchor 3453 +#define wxHtmlWindow_GetOpenedPage 3454 +#define wxHtmlWindow_GetOpenedPageTitle 3455 +#define wxHtmlWindow_GetRelatedFrame 3456 +#define wxHtmlWindow_HistoryBack 3457 +#define wxHtmlWindow_HistoryCanBack 3458 +#define wxHtmlWindow_HistoryCanForward 3459 +#define wxHtmlWindow_HistoryClear 3460 +#define wxHtmlWindow_HistoryForward 3461 +#define wxHtmlWindow_LoadFile 3462 +#define wxHtmlWindow_LoadPage 3463 +#define wxHtmlWindow_SelectAll 3464 +#define wxHtmlWindow_SelectionToText 3465 +#define wxHtmlWindow_SelectLine 3466 +#define wxHtmlWindow_SelectWord 3467 +#define wxHtmlWindow_SetBorders 3468 +#define wxHtmlWindow_SetFonts 3469 +#define wxHtmlWindow_SetPage 3470 +#define wxHtmlWindow_SetRelatedFrame 3471 +#define wxHtmlWindow_SetRelatedStatusBar 3472 +#define wxHtmlWindow_ToText 3473 +#define wxHtmlWindow_destroy 3474 +#define wxHtmlLinkEvent_GetLinkInfo 3475 +#define wxSystemSettings_GetColour 3476 +#define wxSystemSettings_GetFont 3477 +#define wxSystemSettings_GetMetric 3478 +#define wxSystemSettings_GetScreenType 3479 +#define wxAuiNotebookEvent_SetSelection 3480 +#define wxAuiNotebookEvent_GetSelection 3481 +#define wxAuiNotebookEvent_SetOldSelection 3482 +#define wxAuiNotebookEvent_GetOldSelection 3483 +#define wxAuiNotebookEvent_SetDragSource 3484 +#define wxAuiNotebookEvent_GetDragSource 3485 +#define wxAuiManagerEvent_SetManager 3486 +#define wxAuiManagerEvent_GetManager 3487 +#define wxAuiManagerEvent_SetPane 3488 +#define wxAuiManagerEvent_GetPane 3489 +#define wxAuiManagerEvent_SetButton 3490 +#define wxAuiManagerEvent_GetButton 3491 +#define wxAuiManagerEvent_SetDC 3492 +#define wxAuiManagerEvent_GetDC 3493 +#define wxAuiManagerEvent_Veto 3494 +#define wxAuiManagerEvent_GetVeto 3495 +#define wxAuiManagerEvent_SetCanVeto 3496 +#define wxAuiManagerEvent_CanVeto 3497 +#define wxLogNull_new 3498 +#define wxLogNull_destroy 3499 diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index 528a08e654..6d2926ce4e 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -411,7 +411,7 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process) if(event->caller == process || // Callbacks from CB process only event->op == WXE_CB_START || // Recursive event callback allow // Allow connect_cb during CB i.e. msg from wxe_server. - event->caller == memenv->owner) + (memenv && event->caller == memenv->owner)) { switch(event->op) { case WXE_BATCH_END: @@ -669,7 +669,7 @@ void WxeApp::clearPtr(void * ptr) { send_msg("debug", &msg); } - if(refd->pid != -1) { + if(((int) refd->pid) != -1) { // Send terminate pid to owner wxeReturn rt = wxeReturn(WXE_DRV_PORT,refd->memenv->owner, false); rt.addAtom("_wxe_destroy_"); diff --git a/lib/wx/src/gen/wxTreeCtrl.erl b/lib/wx/src/gen/wxTreeCtrl.erl index 4fcbb9366e..e3fe4c9612 100644 --- a/lib/wx/src/gen/wxTreeCtrl.erl +++ b/lib/wx/src/gen/wxTreeCtrl.erl @@ -35,7 +35,7 @@ -include("wxe.hrl"). -export([addRoot/2,addRoot/3,appendItem/3,appendItem/4,assignImageList/2,assignStateImageList/2, collapse/2,collapseAndReset/2,create/2,create/3,delete/2,deleteAllItems/1, - deleteChildren/2,destroy/1,ensureVisible/2,expand/2,getBoundingRect/3, + deleteChildren/2,destroy/1,editLabel/2,ensureVisible/2,expand/2,getBoundingRect/3, getBoundingRect/4,getChildrenCount/2,getChildrenCount/3,getCount/1, getEditControl/1,getFirstChild/2,getFirstVisibleItem/1,getImageList/1, getIndent/1,getItemBackgroundColour/2,getItemData/2,getItemFont/2, @@ -243,6 +243,14 @@ deleteChildren(#wx_ref{type=ThisT,ref=ThisRef},Item) wxe_util:cast(?wxTreeCtrl_DeleteChildren, <<ThisRef:32/?UI,0:32,Item:64/?UI>>). +%% @spec (This::wxTreeCtrl(), Item::integer()) -> wxTextCtrl:wxTextCtrl() +%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrleditlabel">external documentation</a>. +editLabel(#wx_ref{type=ThisT,ref=ThisRef},Item) + when is_integer(Item) -> + ?CLASS(ThisT,wxTreeCtrl), + wxe_util:call(?wxTreeCtrl_EditLabel, + <<ThisRef:32/?UI,0:32,Item:64/?UI>>). + %% @spec (This::wxTreeCtrl(), Item::integer()) -> ok %% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlensurevisible">external documentation</a>. ensureVisible(#wx_ref{type=ThisT,ref=ThisRef},Item) diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl index a3416b75c8..3edfa73599 100644 --- a/lib/wx/src/gen/wxe_debug.hrl +++ b/lib/wx/src/gen/wxe_debug.hrl @@ -1837,1445 +1837,1450 @@ wxdebug_table() -> {2007, {wxTreeCtrl, delete, 1}}, {2008, {wxTreeCtrl, deleteAllItems, 0}}, {2009, {wxTreeCtrl, deleteChildren, 1}}, - {2010, {wxTreeCtrl, ensureVisible, 1}}, - {2011, {wxTreeCtrl, expand, 1}}, - {2012, {wxTreeCtrl, getBoundingRect, 3}}, - {2014, {wxTreeCtrl, getChildrenCount, 2}}, - {2015, {wxTreeCtrl, getCount, 0}}, - {2016, {wxTreeCtrl, getEditControl, 0}}, - {2017, {wxTreeCtrl, getFirstChild, 2}}, - {2018, {wxTreeCtrl, getNextChild, 2}}, - {2019, {wxTreeCtrl, getFirstVisibleItem, 0}}, - {2020, {wxTreeCtrl, getImageList, 0}}, - {2021, {wxTreeCtrl, getIndent, 0}}, - {2022, {wxTreeCtrl, getItemBackgroundColour, 1}}, - {2023, {wxTreeCtrl, getItemData, 1}}, - {2024, {wxTreeCtrl, getItemFont, 1}}, - {2025, {wxTreeCtrl, getItemImage_1, 1}}, - {2026, {wxTreeCtrl, getItemImage_2, 2}}, - {2027, {wxTreeCtrl, getItemText, 1}}, - {2028, {wxTreeCtrl, getItemTextColour, 1}}, - {2029, {wxTreeCtrl, getLastChild, 1}}, - {2030, {wxTreeCtrl, getNextSibling, 1}}, - {2031, {wxTreeCtrl, getNextVisible, 1}}, - {2032, {wxTreeCtrl, getItemParent, 1}}, - {2033, {wxTreeCtrl, getPrevSibling, 1}}, - {2034, {wxTreeCtrl, getPrevVisible, 1}}, - {2035, {wxTreeCtrl, getRootItem, 0}}, - {2036, {wxTreeCtrl, getSelection, 0}}, - {2037, {wxTreeCtrl, getSelections, 1}}, - {2038, {wxTreeCtrl, getStateImageList, 0}}, - {2039, {wxTreeCtrl, hitTest, 1}}, - {2041, {wxTreeCtrl, insertItem, 4}}, - {2042, {wxTreeCtrl, isBold, 1}}, - {2043, {wxTreeCtrl, isExpanded, 1}}, - {2044, {wxTreeCtrl, isSelected, 1}}, - {2045, {wxTreeCtrl, isVisible, 1}}, - {2046, {wxTreeCtrl, itemHasChildren, 1}}, - {2047, {wxTreeCtrl, prependItem, 3}}, - {2048, {wxTreeCtrl, scrollTo, 1}}, - {2049, {wxTreeCtrl, selectItem_1, 1}}, - {2050, {wxTreeCtrl, selectItem_2, 2}}, - {2051, {wxTreeCtrl, setIndent, 1}}, - {2052, {wxTreeCtrl, setImageList, 1}}, - {2053, {wxTreeCtrl, setItemBackgroundColour, 2}}, - {2054, {wxTreeCtrl, setItemBold, 2}}, - {2055, {wxTreeCtrl, setItemData, 2}}, - {2056, {wxTreeCtrl, setItemDropHighlight, 2}}, - {2057, {wxTreeCtrl, setItemFont, 2}}, - {2058, {wxTreeCtrl, setItemHasChildren, 2}}, - {2059, {wxTreeCtrl, setItemImage_2, 2}}, - {2060, {wxTreeCtrl, setItemImage_3, 3}}, - {2061, {wxTreeCtrl, setItemText, 2}}, - {2062, {wxTreeCtrl, setItemTextColour, 2}}, - {2063, {wxTreeCtrl, setStateImageList, 1}}, - {2064, {wxTreeCtrl, setWindowStyle, 1}}, - {2065, {wxTreeCtrl, sortChildren, 1}}, - {2066, {wxTreeCtrl, toggle, 1}}, - {2067, {wxTreeCtrl, toggleItemSelection, 1}}, - {2068, {wxTreeCtrl, unselect, 0}}, - {2069, {wxTreeCtrl, unselectAll, 0}}, - {2070, {wxTreeCtrl, unselectItem, 1}}, - {2071, {wxScrollBar, new_0, 0}}, - {2072, {wxScrollBar, new_3, 3}}, - {2073, {wxScrollBar, destruct, 0}}, - {2074, {wxScrollBar, create, 3}}, - {2075, {wxScrollBar, getRange, 0}}, - {2076, {wxScrollBar, getPageSize, 0}}, - {2077, {wxScrollBar, getThumbPosition, 0}}, - {2078, {wxScrollBar, getThumbSize, 0}}, - {2079, {wxScrollBar, setThumbPosition, 1}}, - {2080, {wxScrollBar, setScrollbar, 5}}, - {2082, {wxSpinButton, new_2, 2}}, - {2083, {wxSpinButton, new_0, 0}}, - {2084, {wxSpinButton, create, 2}}, - {2085, {wxSpinButton, getMax, 0}}, - {2086, {wxSpinButton, getMin, 0}}, - {2087, {wxSpinButton, getValue, 0}}, - {2088, {wxSpinButton, setRange, 2}}, - {2089, {wxSpinButton, setValue, 1}}, - {2090, {wxSpinButton, 'Destroy', undefined}}, - {2091, {wxSpinCtrl, new_0, 0}}, - {2092, {wxSpinCtrl, new_2, 2}}, - {2094, {wxSpinCtrl, create, 2}}, - {2097, {wxSpinCtrl, setValue_1_1, 1}}, - {2098, {wxSpinCtrl, setValue_1_0, 1}}, - {2100, {wxSpinCtrl, getValue, 0}}, - {2102, {wxSpinCtrl, setRange, 2}}, - {2103, {wxSpinCtrl, setSelection, 2}}, - {2105, {wxSpinCtrl, getMin, 0}}, - {2107, {wxSpinCtrl, getMax, 0}}, - {2108, {wxSpinCtrl, 'Destroy', undefined}}, - {2109, {wxStaticText, new_0, 0}}, - {2110, {wxStaticText, new_4, 4}}, - {2111, {wxStaticText, create, 4}}, - {2112, {wxStaticText, getLabel, 0}}, - {2113, {wxStaticText, setLabel, 1}}, - {2114, {wxStaticText, wrap, 1}}, - {2115, {wxStaticText, 'Destroy', undefined}}, - {2116, {wxStaticBitmap, new_0, 0}}, - {2117, {wxStaticBitmap, new_4, 4}}, - {2118, {wxStaticBitmap, create, 4}}, - {2119, {wxStaticBitmap, getBitmap, 0}}, - {2120, {wxStaticBitmap, setBitmap, 1}}, - {2121, {wxStaticBitmap, 'Destroy', undefined}}, - {2122, {wxRadioBox, new, 7}}, - {2124, {wxRadioBox, destruct, 0}}, - {2125, {wxRadioBox, create, 7}}, - {2126, {wxRadioBox, enable_2, 2}}, - {2127, {wxRadioBox, enable_1, 1}}, - {2128, {wxRadioBox, getSelection, 0}}, - {2129, {wxRadioBox, getString, 1}}, - {2130, {wxRadioBox, setSelection, 1}}, - {2131, {wxRadioBox, show_2, 2}}, - {2132, {wxRadioBox, show_1, 1}}, - {2133, {wxRadioBox, getColumnCount, 0}}, - {2134, {wxRadioBox, getItemHelpText, 1}}, - {2135, {wxRadioBox, getItemToolTip, 1}}, - {2137, {wxRadioBox, getItemFromPoint, 1}}, - {2138, {wxRadioBox, getRowCount, 0}}, - {2139, {wxRadioBox, isItemEnabled, 1}}, - {2140, {wxRadioBox, isItemShown, 1}}, - {2141, {wxRadioBox, setItemHelpText, 2}}, - {2142, {wxRadioBox, setItemToolTip, 2}}, - {2143, {wxRadioButton, new_0, 0}}, - {2144, {wxRadioButton, new_4, 4}}, - {2145, {wxRadioButton, create, 4}}, - {2146, {wxRadioButton, getValue, 0}}, - {2147, {wxRadioButton, setValue, 1}}, - {2148, {wxRadioButton, 'Destroy', undefined}}, - {2150, {wxSlider, new_6, 6}}, - {2151, {wxSlider, new_0, 0}}, - {2152, {wxSlider, create, 6}}, - {2153, {wxSlider, getLineSize, 0}}, - {2154, {wxSlider, getMax, 0}}, - {2155, {wxSlider, getMin, 0}}, - {2156, {wxSlider, getPageSize, 0}}, - {2157, {wxSlider, getThumbLength, 0}}, - {2158, {wxSlider, getValue, 0}}, - {2159, {wxSlider, setLineSize, 1}}, - {2160, {wxSlider, setPageSize, 1}}, - {2161, {wxSlider, setRange, 2}}, - {2162, {wxSlider, setThumbLength, 1}}, - {2163, {wxSlider, setValue, 1}}, - {2164, {wxSlider, 'Destroy', undefined}}, - {2166, {wxDialog, new_4, 4}}, - {2167, {wxDialog, new_0, 0}}, - {2169, {wxDialog, destruct, 0}}, - {2170, {wxDialog, create, 4}}, - {2171, {wxDialog, createButtonSizer, 1}}, - {2172, {wxDialog, createStdDialogButtonSizer, 1}}, - {2173, {wxDialog, endModal, 1}}, - {2174, {wxDialog, getAffirmativeId, 0}}, - {2175, {wxDialog, getReturnCode, 0}}, - {2176, {wxDialog, isModal, 0}}, - {2177, {wxDialog, setAffirmativeId, 1}}, - {2178, {wxDialog, setReturnCode, 1}}, - {2179, {wxDialog, show, 1}}, - {2180, {wxDialog, showModal, 0}}, - {2181, {wxColourDialog, new_0, 0}}, - {2182, {wxColourDialog, new_2, 2}}, - {2183, {wxColourDialog, destruct, 0}}, - {2184, {wxColourDialog, create, 2}}, - {2185, {wxColourDialog, getColourData, 0}}, - {2186, {wxColourData, new_0, 0}}, - {2187, {wxColourData, new_1, 1}}, - {2188, {wxColourData, destruct, 0}}, - {2189, {wxColourData, getChooseFull, 0}}, - {2190, {wxColourData, getColour, 0}}, - {2192, {wxColourData, getCustomColour, 1}}, - {2193, {wxColourData, setChooseFull, 1}}, - {2194, {wxColourData, setColour, 1}}, - {2195, {wxColourData, setCustomColour, 2}}, - {2196, {wxPalette, new_0, 0}}, - {2197, {wxPalette, new_4, 4}}, - {2199, {wxPalette, destruct, 0}}, - {2200, {wxPalette, create, 4}}, - {2201, {wxPalette, getColoursCount, 0}}, - {2202, {wxPalette, getPixel, 3}}, - {2203, {wxPalette, getRGB, 4}}, - {2204, {wxPalette, isOk, 0}}, - {2208, {wxDirDialog, new, 2}}, - {2209, {wxDirDialog, destruct, 0}}, - {2210, {wxDirDialog, getPath, 0}}, - {2211, {wxDirDialog, getMessage, 0}}, - {2212, {wxDirDialog, setMessage, 1}}, - {2213, {wxDirDialog, setPath, 1}}, - {2217, {wxFileDialog, new, 2}}, - {2218, {wxFileDialog, destruct, 0}}, - {2219, {wxFileDialog, getDirectory, 0}}, - {2220, {wxFileDialog, getFilename, 0}}, - {2221, {wxFileDialog, getFilenames, 1}}, - {2222, {wxFileDialog, getFilterIndex, 0}}, - {2223, {wxFileDialog, getMessage, 0}}, - {2224, {wxFileDialog, getPath, 0}}, - {2225, {wxFileDialog, getPaths, 1}}, - {2226, {wxFileDialog, getWildcard, 0}}, - {2227, {wxFileDialog, setDirectory, 1}}, - {2228, {wxFileDialog, setFilename, 1}}, - {2229, {wxFileDialog, setFilterIndex, 1}}, - {2230, {wxFileDialog, setMessage, 1}}, - {2231, {wxFileDialog, setPath, 1}}, - {2232, {wxFileDialog, setWildcard, 1}}, - {2233, {wxPickerBase, setInternalMargin, 1}}, - {2234, {wxPickerBase, getInternalMargin, 0}}, - {2235, {wxPickerBase, setTextCtrlProportion, 1}}, - {2236, {wxPickerBase, setPickerCtrlProportion, 1}}, - {2237, {wxPickerBase, getTextCtrlProportion, 0}}, - {2238, {wxPickerBase, getPickerCtrlProportion, 0}}, - {2239, {wxPickerBase, hasTextCtrl, 0}}, - {2240, {wxPickerBase, getTextCtrl, 0}}, - {2241, {wxPickerBase, isTextCtrlGrowable, 0}}, - {2242, {wxPickerBase, setPickerCtrlGrowable, 1}}, - {2243, {wxPickerBase, setTextCtrlGrowable, 1}}, - {2244, {wxPickerBase, isPickerCtrlGrowable, 0}}, - {2245, {wxFilePickerCtrl, new_0, 0}}, - {2246, {wxFilePickerCtrl, new_3, 3}}, - {2247, {wxFilePickerCtrl, create, 3}}, - {2248, {wxFilePickerCtrl, getPath, 0}}, - {2249, {wxFilePickerCtrl, setPath, 1}}, - {2250, {wxFilePickerCtrl, 'Destroy', undefined}}, - {2251, {wxDirPickerCtrl, new_0, 0}}, - {2252, {wxDirPickerCtrl, new_3, 3}}, - {2253, {wxDirPickerCtrl, create, 3}}, - {2254, {wxDirPickerCtrl, getPath, 0}}, - {2255, {wxDirPickerCtrl, setPath, 1}}, - {2256, {wxDirPickerCtrl, 'Destroy', undefined}}, - {2257, {wxColourPickerCtrl, new_0, 0}}, - {2258, {wxColourPickerCtrl, new_3, 3}}, - {2259, {wxColourPickerCtrl, create, 3}}, - {2260, {wxColourPickerCtrl, getColour, 0}}, - {2261, {wxColourPickerCtrl, setColour_1_1, 1}}, - {2262, {wxColourPickerCtrl, setColour_1_0, 1}}, - {2263, {wxColourPickerCtrl, 'Destroy', undefined}}, - {2264, {wxDatePickerCtrl, new_0, 0}}, - {2265, {wxDatePickerCtrl, new_3, 3}}, - {2266, {wxDatePickerCtrl, getRange, 2}}, - {2267, {wxDatePickerCtrl, getValue, 0}}, - {2268, {wxDatePickerCtrl, setRange, 2}}, - {2269, {wxDatePickerCtrl, setValue, 1}}, - {2270, {wxDatePickerCtrl, 'Destroy', undefined}}, - {2271, {wxFontPickerCtrl, new_0, 0}}, - {2272, {wxFontPickerCtrl, new_3, 3}}, - {2273, {wxFontPickerCtrl, create, 3}}, - {2274, {wxFontPickerCtrl, getSelectedFont, 0}}, - {2275, {wxFontPickerCtrl, setSelectedFont, 1}}, - {2276, {wxFontPickerCtrl, getMaxPointSize, 0}}, - {2277, {wxFontPickerCtrl, setMaxPointSize, 1}}, - {2278, {wxFontPickerCtrl, 'Destroy', undefined}}, - {2281, {wxFindReplaceDialog, new_0, 0}}, - {2282, {wxFindReplaceDialog, new_4, 4}}, - {2283, {wxFindReplaceDialog, destruct, 0}}, - {2284, {wxFindReplaceDialog, create, 4}}, - {2285, {wxFindReplaceDialog, getData, 0}}, - {2286, {wxFindReplaceData, new_0, 0}}, - {2287, {wxFindReplaceData, new_1, 1}}, - {2288, {wxFindReplaceData, getFindString, 0}}, - {2289, {wxFindReplaceData, getReplaceString, 0}}, - {2290, {wxFindReplaceData, getFlags, 0}}, - {2291, {wxFindReplaceData, setFlags, 1}}, - {2292, {wxFindReplaceData, setFindString, 1}}, - {2293, {wxFindReplaceData, setReplaceString, 1}}, - {2294, {wxFindReplaceData, 'Destroy', undefined}}, - {2295, {wxMultiChoiceDialog, new_0, 0}}, - {2297, {wxMultiChoiceDialog, new_5, 5}}, - {2298, {wxMultiChoiceDialog, getSelections, 0}}, - {2299, {wxMultiChoiceDialog, setSelections, 1}}, - {2300, {wxMultiChoiceDialog, 'Destroy', undefined}}, - {2301, {wxSingleChoiceDialog, new_0, 0}}, - {2303, {wxSingleChoiceDialog, new_5, 5}}, - {2304, {wxSingleChoiceDialog, getSelection, 0}}, - {2305, {wxSingleChoiceDialog, getStringSelection, 0}}, - {2306, {wxSingleChoiceDialog, setSelection, 1}}, - {2307, {wxSingleChoiceDialog, 'Destroy', undefined}}, - {2308, {wxTextEntryDialog, new, 3}}, - {2309, {wxTextEntryDialog, getValue, 0}}, - {2310, {wxTextEntryDialog, setValue, 1}}, - {2311, {wxTextEntryDialog, 'Destroy', undefined}}, - {2312, {wxPasswordEntryDialog, new, 3}}, - {2313, {wxPasswordEntryDialog, 'Destroy', undefined}}, - {2314, {wxFontData, new_0, 0}}, - {2315, {wxFontData, new_1, 1}}, - {2316, {wxFontData, destruct, 0}}, - {2317, {wxFontData, enableEffects, 1}}, - {2318, {wxFontData, getAllowSymbols, 0}}, - {2319, {wxFontData, getColour, 0}}, - {2320, {wxFontData, getChosenFont, 0}}, - {2321, {wxFontData, getEnableEffects, 0}}, - {2322, {wxFontData, getInitialFont, 0}}, - {2323, {wxFontData, getShowHelp, 0}}, - {2324, {wxFontData, setAllowSymbols, 1}}, - {2325, {wxFontData, setChosenFont, 1}}, - {2326, {wxFontData, setColour, 1}}, - {2327, {wxFontData, setInitialFont, 1}}, - {2328, {wxFontData, setRange, 2}}, - {2329, {wxFontData, setShowHelp, 1}}, - {2333, {wxFontDialog, new_0, 0}}, - {2335, {wxFontDialog, new_2, 2}}, - {2337, {wxFontDialog, create, 2}}, - {2338, {wxFontDialog, getFontData, 0}}, - {2340, {wxFontDialog, 'Destroy', undefined}}, - {2341, {wxProgressDialog, new, 3}}, - {2342, {wxProgressDialog, destruct, 0}}, - {2343, {wxProgressDialog, resume, 0}}, - {2344, {wxProgressDialog, update_2, 2}}, - {2345, {wxProgressDialog, update_0, 0}}, - {2346, {wxMessageDialog, new, 3}}, - {2347, {wxMessageDialog, destruct, 0}}, - {2348, {wxPageSetupDialog, new, 2}}, - {2349, {wxPageSetupDialog, destruct, 0}}, - {2350, {wxPageSetupDialog, getPageSetupData, 0}}, - {2351, {wxPageSetupDialog, showModal, 0}}, - {2352, {wxPageSetupDialogData, new_0, 0}}, - {2353, {wxPageSetupDialogData, new_1_0, 1}}, - {2354, {wxPageSetupDialogData, new_1_1, 1}}, - {2355, {wxPageSetupDialogData, destruct, 0}}, - {2356, {wxPageSetupDialogData, enableHelp, 1}}, - {2357, {wxPageSetupDialogData, enableMargins, 1}}, - {2358, {wxPageSetupDialogData, enableOrientation, 1}}, - {2359, {wxPageSetupDialogData, enablePaper, 1}}, - {2360, {wxPageSetupDialogData, enablePrinter, 1}}, - {2361, {wxPageSetupDialogData, getDefaultMinMargins, 0}}, - {2362, {wxPageSetupDialogData, getEnableMargins, 0}}, - {2363, {wxPageSetupDialogData, getEnableOrientation, 0}}, - {2364, {wxPageSetupDialogData, getEnablePaper, 0}}, - {2365, {wxPageSetupDialogData, getEnablePrinter, 0}}, - {2366, {wxPageSetupDialogData, getEnableHelp, 0}}, - {2367, {wxPageSetupDialogData, getDefaultInfo, 0}}, - {2368, {wxPageSetupDialogData, getMarginTopLeft, 0}}, - {2369, {wxPageSetupDialogData, getMarginBottomRight, 0}}, - {2370, {wxPageSetupDialogData, getMinMarginTopLeft, 0}}, - {2371, {wxPageSetupDialogData, getMinMarginBottomRight, 0}}, - {2372, {wxPageSetupDialogData, getPaperId, 0}}, - {2373, {wxPageSetupDialogData, getPaperSize, 0}}, - {2375, {wxPageSetupDialogData, getPrintData, 0}}, - {2376, {wxPageSetupDialogData, isOk, 0}}, - {2377, {wxPageSetupDialogData, setDefaultInfo, 1}}, - {2378, {wxPageSetupDialogData, setDefaultMinMargins, 1}}, - {2379, {wxPageSetupDialogData, setMarginTopLeft, 1}}, - {2380, {wxPageSetupDialogData, setMarginBottomRight, 1}}, - {2381, {wxPageSetupDialogData, setMinMarginTopLeft, 1}}, - {2382, {wxPageSetupDialogData, setMinMarginBottomRight, 1}}, - {2383, {wxPageSetupDialogData, setPaperId, 1}}, - {2384, {wxPageSetupDialogData, setPaperSize_1_1, 1}}, - {2385, {wxPageSetupDialogData, setPaperSize_1_0, 1}}, - {2386, {wxPageSetupDialogData, setPrintData, 1}}, - {2387, {wxPrintDialog, new_2_0, 2}}, - {2388, {wxPrintDialog, new_2_1, 2}}, - {2389, {wxPrintDialog, destruct, 0}}, - {2390, {wxPrintDialog, getPrintDialogData, 0}}, - {2391, {wxPrintDialog, getPrintDC, 0}}, - {2392, {wxPrintDialogData, new_0, 0}}, - {2393, {wxPrintDialogData, new_1_1, 1}}, - {2394, {wxPrintDialogData, new_1_0, 1}}, - {2395, {wxPrintDialogData, destruct, 0}}, - {2396, {wxPrintDialogData, enableHelp, 1}}, - {2397, {wxPrintDialogData, enablePageNumbers, 1}}, - {2398, {wxPrintDialogData, enablePrintToFile, 1}}, - {2399, {wxPrintDialogData, enableSelection, 1}}, - {2400, {wxPrintDialogData, getAllPages, 0}}, - {2401, {wxPrintDialogData, getCollate, 0}}, - {2402, {wxPrintDialogData, getFromPage, 0}}, - {2403, {wxPrintDialogData, getMaxPage, 0}}, - {2404, {wxPrintDialogData, getMinPage, 0}}, - {2405, {wxPrintDialogData, getNoCopies, 0}}, - {2406, {wxPrintDialogData, getPrintData, 0}}, - {2407, {wxPrintDialogData, getPrintToFile, 0}}, - {2408, {wxPrintDialogData, getSelection, 0}}, - {2409, {wxPrintDialogData, getToPage, 0}}, - {2410, {wxPrintDialogData, isOk, 0}}, - {2411, {wxPrintDialogData, setCollate, 1}}, - {2412, {wxPrintDialogData, setFromPage, 1}}, - {2413, {wxPrintDialogData, setMaxPage, 1}}, - {2414, {wxPrintDialogData, setMinPage, 1}}, - {2415, {wxPrintDialogData, setNoCopies, 1}}, - {2416, {wxPrintDialogData, setPrintData, 1}}, - {2417, {wxPrintDialogData, setPrintToFile, 1}}, - {2418, {wxPrintDialogData, setSelection, 1}}, - {2419, {wxPrintDialogData, setToPage, 1}}, - {2420, {wxPrintData, new_0, 0}}, - {2421, {wxPrintData, new_1, 1}}, - {2422, {wxPrintData, destruct, 0}}, - {2423, {wxPrintData, getCollate, 0}}, - {2424, {wxPrintData, getBin, 0}}, - {2425, {wxPrintData, getColour, 0}}, - {2426, {wxPrintData, getDuplex, 0}}, - {2427, {wxPrintData, getNoCopies, 0}}, - {2428, {wxPrintData, getOrientation, 0}}, - {2429, {wxPrintData, getPaperId, 0}}, - {2430, {wxPrintData, getPrinterName, 0}}, - {2431, {wxPrintData, getQuality, 0}}, - {2432, {wxPrintData, isOk, 0}}, - {2433, {wxPrintData, setBin, 1}}, - {2434, {wxPrintData, setCollate, 1}}, - {2435, {wxPrintData, setColour, 1}}, - {2436, {wxPrintData, setDuplex, 1}}, - {2437, {wxPrintData, setNoCopies, 1}}, - {2438, {wxPrintData, setOrientation, 1}}, - {2439, {wxPrintData, setPaperId, 1}}, - {2440, {wxPrintData, setPrinterName, 1}}, - {2441, {wxPrintData, setQuality, 1}}, - {2444, {wxPrintPreview, new_2, 2}}, - {2445, {wxPrintPreview, new_3, 3}}, - {2447, {wxPrintPreview, destruct, 0}}, - {2448, {wxPrintPreview, getCanvas, 0}}, - {2449, {wxPrintPreview, getCurrentPage, 0}}, - {2450, {wxPrintPreview, getFrame, 0}}, - {2451, {wxPrintPreview, getMaxPage, 0}}, - {2452, {wxPrintPreview, getMinPage, 0}}, - {2453, {wxPrintPreview, getPrintout, 0}}, - {2454, {wxPrintPreview, getPrintoutForPrinting, 0}}, - {2455, {wxPrintPreview, isOk, 0}}, - {2456, {wxPrintPreview, paintPage, 2}}, - {2457, {wxPrintPreview, print, 1}}, - {2458, {wxPrintPreview, renderPage, 1}}, - {2459, {wxPrintPreview, setCanvas, 1}}, - {2460, {wxPrintPreview, setCurrentPage, 1}}, - {2461, {wxPrintPreview, setFrame, 1}}, - {2462, {wxPrintPreview, setPrintout, 1}}, - {2463, {wxPrintPreview, setZoom, 1}}, - {2464, {wxPreviewFrame, new, 3}}, - {2465, {wxPreviewFrame, destruct, 0}}, - {2466, {wxPreviewFrame, createControlBar, 0}}, - {2467, {wxPreviewFrame, createCanvas, 0}}, - {2468, {wxPreviewFrame, initialize, 0}}, - {2469, {wxPreviewFrame, onCloseWindow, 1}}, - {2470, {wxPreviewControlBar, new, 4}}, - {2471, {wxPreviewControlBar, destruct, 0}}, - {2472, {wxPreviewControlBar, createButtons, 0}}, - {2473, {wxPreviewControlBar, getPrintPreview, 0}}, - {2474, {wxPreviewControlBar, getZoomControl, 0}}, - {2475, {wxPreviewControlBar, setZoomControl, 1}}, - {2477, {wxPrinter, new, 1}}, - {2478, {wxPrinter, createAbortWindow, 2}}, - {2479, {wxPrinter, getAbort, 0}}, - {2480, {wxPrinter, getLastError, 0}}, - {2481, {wxPrinter, getPrintDialogData, 0}}, - {2482, {wxPrinter, print, 3}}, - {2483, {wxPrinter, printDialog, 1}}, - {2484, {wxPrinter, reportError, 3}}, - {2485, {wxPrinter, setup, 1}}, - {2486, {wxPrinter, 'Destroy', undefined}}, - {2487, {wxXmlResource, new_1, 1}}, - {2488, {wxXmlResource, new_2, 2}}, - {2489, {wxXmlResource, destruct, 0}}, - {2490, {wxXmlResource, attachUnknownControl, 3}}, - {2491, {wxXmlResource, clearHandlers, 0}}, - {2492, {wxXmlResource, compareVersion, 4}}, - {2493, {wxXmlResource, get, 0}}, - {2494, {wxXmlResource, getFlags, 0}}, - {2495, {wxXmlResource, getVersion, 0}}, - {2496, {wxXmlResource, getXRCID, 2}}, - {2497, {wxXmlResource, initAllHandlers, 0}}, - {2498, {wxXmlResource, load, 1}}, - {2499, {wxXmlResource, loadBitmap, 1}}, - {2500, {wxXmlResource, loadDialog_2, 2}}, - {2501, {wxXmlResource, loadDialog_3, 3}}, - {2502, {wxXmlResource, loadFrame_2, 2}}, - {2503, {wxXmlResource, loadFrame_3, 3}}, - {2504, {wxXmlResource, loadIcon, 1}}, - {2505, {wxXmlResource, loadMenu, 1}}, - {2506, {wxXmlResource, loadMenuBar_2, 2}}, - {2507, {wxXmlResource, loadMenuBar_1, 1}}, - {2508, {wxXmlResource, loadPanel_2, 2}}, - {2509, {wxXmlResource, loadPanel_3, 3}}, - {2510, {wxXmlResource, loadToolBar, 2}}, - {2511, {wxXmlResource, set, 1}}, - {2512, {wxXmlResource, setFlags, 1}}, - {2513, {wxXmlResource, unload, 1}}, - {2514, {wxXmlResource, xrcctrl, 3}}, - {2515, {wxHtmlEasyPrinting, new, 1}}, - {2516, {wxHtmlEasyPrinting, destruct, 0}}, - {2517, {wxHtmlEasyPrinting, getPrintData, 0}}, - {2518, {wxHtmlEasyPrinting, getPageSetupData, 0}}, - {2519, {wxHtmlEasyPrinting, previewFile, 1}}, - {2520, {wxHtmlEasyPrinting, previewText, 2}}, - {2521, {wxHtmlEasyPrinting, printFile, 1}}, - {2522, {wxHtmlEasyPrinting, printText, 2}}, - {2523, {wxHtmlEasyPrinting, pageSetup, 0}}, - {2524, {wxHtmlEasyPrinting, setFonts, 3}}, - {2525, {wxHtmlEasyPrinting, setHeader, 2}}, - {2526, {wxHtmlEasyPrinting, setFooter, 2}}, - {2528, {wxGLCanvas, new_2, 2}}, - {2529, {wxGLCanvas, new_3_1, 3}}, - {2530, {wxGLCanvas, new_3_0, 3}}, - {2531, {wxGLCanvas, getContext, 0}}, - {2533, {wxGLCanvas, setCurrent, 0}}, - {2534, {wxGLCanvas, swapBuffers, 0}}, - {2535, {wxGLCanvas, 'Destroy', undefined}}, - {2536, {wxAuiManager, new, 1}}, - {2537, {wxAuiManager, destruct, 0}}, - {2538, {wxAuiManager, addPane_2_1, 2}}, - {2539, {wxAuiManager, addPane_3, 3}}, - {2540, {wxAuiManager, addPane_2_0, 2}}, - {2541, {wxAuiManager, detachPane, 1}}, - {2542, {wxAuiManager, getAllPanes, 0}}, - {2543, {wxAuiManager, getArtProvider, 0}}, - {2544, {wxAuiManager, getDockSizeConstraint, 2}}, - {2545, {wxAuiManager, getFlags, 0}}, - {2546, {wxAuiManager, getManagedWindow, 0}}, - {2547, {wxAuiManager, getManager, 1}}, - {2548, {wxAuiManager, getPane_1_1, 1}}, - {2549, {wxAuiManager, getPane_1_0, 1}}, - {2550, {wxAuiManager, hideHint, 0}}, - {2551, {wxAuiManager, insertPane, 3}}, - {2552, {wxAuiManager, loadPaneInfo, 2}}, - {2553, {wxAuiManager, loadPerspective, 2}}, - {2554, {wxAuiManager, savePaneInfo, 1}}, - {2555, {wxAuiManager, savePerspective, 0}}, - {2556, {wxAuiManager, setArtProvider, 1}}, - {2557, {wxAuiManager, setDockSizeConstraint, 2}}, - {2558, {wxAuiManager, setFlags, 1}}, - {2559, {wxAuiManager, setManagedWindow, 1}}, - {2560, {wxAuiManager, showHint, 1}}, - {2561, {wxAuiManager, unInit, 0}}, - {2562, {wxAuiManager, update, 0}}, - {2563, {wxAuiPaneInfo, new_0, 0}}, - {2564, {wxAuiPaneInfo, new_1, 1}}, - {2565, {wxAuiPaneInfo, destruct, 0}}, - {2566, {wxAuiPaneInfo, bestSize_1, 1}}, - {2567, {wxAuiPaneInfo, bestSize_2, 2}}, - {2568, {wxAuiPaneInfo, bottom, 0}}, - {2569, {wxAuiPaneInfo, bottomDockable, 1}}, - {2570, {wxAuiPaneInfo, caption, 1}}, - {2571, {wxAuiPaneInfo, captionVisible, 1}}, - {2572, {wxAuiPaneInfo, centre, 0}}, - {2573, {wxAuiPaneInfo, centrePane, 0}}, - {2574, {wxAuiPaneInfo, closeButton, 1}}, - {2575, {wxAuiPaneInfo, defaultPane, 0}}, - {2576, {wxAuiPaneInfo, destroyOnClose, 1}}, - {2577, {wxAuiPaneInfo, direction, 1}}, - {2578, {wxAuiPaneInfo, dock, 0}}, - {2579, {wxAuiPaneInfo, dockable, 1}}, - {2580, {wxAuiPaneInfo, fixed, 0}}, - {2581, {wxAuiPaneInfo, float, 0}}, - {2582, {wxAuiPaneInfo, floatable, 1}}, - {2583, {wxAuiPaneInfo, floatingPosition_1, 1}}, - {2584, {wxAuiPaneInfo, floatingPosition_2, 2}}, - {2585, {wxAuiPaneInfo, floatingSize_1, 1}}, - {2586, {wxAuiPaneInfo, floatingSize_2, 2}}, - {2587, {wxAuiPaneInfo, gripper, 1}}, - {2588, {wxAuiPaneInfo, gripperTop, 1}}, - {2589, {wxAuiPaneInfo, hasBorder, 0}}, - {2590, {wxAuiPaneInfo, hasCaption, 0}}, - {2591, {wxAuiPaneInfo, hasCloseButton, 0}}, - {2592, {wxAuiPaneInfo, hasFlag, 1}}, - {2593, {wxAuiPaneInfo, hasGripper, 0}}, - {2594, {wxAuiPaneInfo, hasGripperTop, 0}}, - {2595, {wxAuiPaneInfo, hasMaximizeButton, 0}}, - {2596, {wxAuiPaneInfo, hasMinimizeButton, 0}}, - {2597, {wxAuiPaneInfo, hasPinButton, 0}}, - {2598, {wxAuiPaneInfo, hide, 0}}, - {2599, {wxAuiPaneInfo, isBottomDockable, 0}}, - {2600, {wxAuiPaneInfo, isDocked, 0}}, - {2601, {wxAuiPaneInfo, isFixed, 0}}, - {2602, {wxAuiPaneInfo, isFloatable, 0}}, - {2603, {wxAuiPaneInfo, isFloating, 0}}, - {2604, {wxAuiPaneInfo, isLeftDockable, 0}}, - {2605, {wxAuiPaneInfo, isMovable, 0}}, - {2606, {wxAuiPaneInfo, isOk, 0}}, - {2607, {wxAuiPaneInfo, isResizable, 0}}, - {2608, {wxAuiPaneInfo, isRightDockable, 0}}, - {2609, {wxAuiPaneInfo, isShown, 0}}, - {2610, {wxAuiPaneInfo, isToolbar, 0}}, - {2611, {wxAuiPaneInfo, isTopDockable, 0}}, - {2612, {wxAuiPaneInfo, layer, 1}}, - {2613, {wxAuiPaneInfo, left, 0}}, - {2614, {wxAuiPaneInfo, leftDockable, 1}}, - {2615, {wxAuiPaneInfo, maxSize_1, 1}}, - {2616, {wxAuiPaneInfo, maxSize_2, 2}}, - {2617, {wxAuiPaneInfo, maximizeButton, 1}}, - {2618, {wxAuiPaneInfo, minSize_1, 1}}, - {2619, {wxAuiPaneInfo, minSize_2, 2}}, - {2620, {wxAuiPaneInfo, minimizeButton, 1}}, - {2621, {wxAuiPaneInfo, movable, 1}}, - {2622, {wxAuiPaneInfo, name, 1}}, - {2623, {wxAuiPaneInfo, paneBorder, 1}}, - {2624, {wxAuiPaneInfo, pinButton, 1}}, - {2625, {wxAuiPaneInfo, position, 1}}, - {2626, {wxAuiPaneInfo, resizable, 1}}, - {2627, {wxAuiPaneInfo, right, 0}}, - {2628, {wxAuiPaneInfo, rightDockable, 1}}, - {2629, {wxAuiPaneInfo, row, 1}}, - {2630, {wxAuiPaneInfo, safeSet, 1}}, - {2631, {wxAuiPaneInfo, setFlag, 2}}, - {2632, {wxAuiPaneInfo, show, 1}}, - {2633, {wxAuiPaneInfo, toolbarPane, 0}}, - {2634, {wxAuiPaneInfo, top, 0}}, - {2635, {wxAuiPaneInfo, topDockable, 1}}, - {2636, {wxAuiPaneInfo, window, 1}}, - {2637, {wxAuiNotebook, new_0, 0}}, - {2638, {wxAuiNotebook, new_2, 2}}, - {2639, {wxAuiNotebook, addPage, 3}}, - {2640, {wxAuiNotebook, create, 2}}, - {2641, {wxAuiNotebook, deletePage, 1}}, - {2642, {wxAuiNotebook, getArtProvider, 0}}, - {2643, {wxAuiNotebook, getPage, 1}}, - {2644, {wxAuiNotebook, getPageBitmap, 1}}, - {2645, {wxAuiNotebook, getPageCount, 0}}, - {2646, {wxAuiNotebook, getPageIndex, 1}}, - {2647, {wxAuiNotebook, getPageText, 1}}, - {2648, {wxAuiNotebook, getSelection, 0}}, - {2649, {wxAuiNotebook, insertPage, 4}}, - {2650, {wxAuiNotebook, removePage, 1}}, - {2651, {wxAuiNotebook, setArtProvider, 1}}, - {2652, {wxAuiNotebook, setFont, 1}}, - {2653, {wxAuiNotebook, setPageBitmap, 2}}, - {2654, {wxAuiNotebook, setPageText, 2}}, - {2655, {wxAuiNotebook, setSelection, 1}}, - {2656, {wxAuiNotebook, setTabCtrlHeight, 1}}, - {2657, {wxAuiNotebook, setUniformBitmapSize, 1}}, - {2658, {wxAuiNotebook, 'Destroy', undefined}}, - {2659, {wxMDIParentFrame, new_0, 0}}, - {2660, {wxMDIParentFrame, new_4, 4}}, - {2661, {wxMDIParentFrame, destruct, 0}}, - {2662, {wxMDIParentFrame, activateNext, 0}}, - {2663, {wxMDIParentFrame, activatePrevious, 0}}, - {2664, {wxMDIParentFrame, arrangeIcons, 0}}, - {2665, {wxMDIParentFrame, cascade, 0}}, - {2666, {wxMDIParentFrame, create, 4}}, - {2667, {wxMDIParentFrame, getActiveChild, 0}}, - {2668, {wxMDIParentFrame, getClientWindow, 0}}, - {2669, {wxMDIParentFrame, tile, 1}}, - {2670, {wxMDIChildFrame, new_0, 0}}, - {2671, {wxMDIChildFrame, new_4, 4}}, - {2672, {wxMDIChildFrame, destruct, 0}}, - {2673, {wxMDIChildFrame, activate, 0}}, - {2674, {wxMDIChildFrame, create, 4}}, - {2675, {wxMDIChildFrame, maximize, 1}}, - {2676, {wxMDIChildFrame, restore, 0}}, - {2677, {wxMDIClientWindow, new_0, 0}}, - {2678, {wxMDIClientWindow, new_2, 2}}, - {2679, {wxMDIClientWindow, destruct, 0}}, - {2680, {wxMDIClientWindow, createClient, 2}}, - {2681, {wxLayoutAlgorithm, new, 0}}, - {2682, {wxLayoutAlgorithm, layoutFrame, 2}}, - {2683, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, - {2684, {wxLayoutAlgorithm, layoutWindow, 2}}, - {2685, {wxLayoutAlgorithm, 'Destroy', undefined}}, - {2686, {wxEvent, getId, 0}}, - {2687, {wxEvent, getSkipped, 0}}, - {2688, {wxEvent, getTimestamp, 0}}, - {2689, {wxEvent, isCommandEvent, 0}}, - {2690, {wxEvent, resumePropagation, 1}}, - {2691, {wxEvent, shouldPropagate, 0}}, - {2692, {wxEvent, skip, 1}}, - {2693, {wxEvent, stopPropagation, 0}}, - {2694, {wxCommandEvent, getClientData, 0}}, - {2695, {wxCommandEvent, getExtraLong, 0}}, - {2696, {wxCommandEvent, getInt, 0}}, - {2697, {wxCommandEvent, getSelection, 0}}, - {2698, {wxCommandEvent, getString, 0}}, - {2699, {wxCommandEvent, isChecked, 0}}, - {2700, {wxCommandEvent, isSelection, 0}}, - {2701, {wxCommandEvent, setInt, 1}}, - {2702, {wxCommandEvent, setString, 1}}, - {2703, {wxScrollEvent, getOrientation, 0}}, - {2704, {wxScrollEvent, getPosition, 0}}, - {2705, {wxScrollWinEvent, getOrientation, 0}}, - {2706, {wxScrollWinEvent, getPosition, 0}}, - {2707, {wxMouseEvent, altDown, 0}}, - {2708, {wxMouseEvent, button, 1}}, - {2709, {wxMouseEvent, buttonDClick, 1}}, - {2710, {wxMouseEvent, buttonDown, 1}}, - {2711, {wxMouseEvent, buttonUp, 1}}, - {2712, {wxMouseEvent, cmdDown, 0}}, - {2713, {wxMouseEvent, controlDown, 0}}, - {2714, {wxMouseEvent, dragging, 0}}, - {2715, {wxMouseEvent, entering, 0}}, - {2716, {wxMouseEvent, getButton, 0}}, - {2719, {wxMouseEvent, getPosition, 0}}, - {2720, {wxMouseEvent, getLogicalPosition, 1}}, - {2721, {wxMouseEvent, getLinesPerAction, 0}}, - {2722, {wxMouseEvent, getWheelRotation, 0}}, - {2723, {wxMouseEvent, getWheelDelta, 0}}, - {2724, {wxMouseEvent, getX, 0}}, - {2725, {wxMouseEvent, getY, 0}}, - {2726, {wxMouseEvent, isButton, 0}}, - {2727, {wxMouseEvent, isPageScroll, 0}}, - {2728, {wxMouseEvent, leaving, 0}}, - {2729, {wxMouseEvent, leftDClick, 0}}, - {2730, {wxMouseEvent, leftDown, 0}}, - {2731, {wxMouseEvent, leftIsDown, 0}}, - {2732, {wxMouseEvent, leftUp, 0}}, - {2733, {wxMouseEvent, metaDown, 0}}, - {2734, {wxMouseEvent, middleDClick, 0}}, - {2735, {wxMouseEvent, middleDown, 0}}, - {2736, {wxMouseEvent, middleIsDown, 0}}, - {2737, {wxMouseEvent, middleUp, 0}}, - {2738, {wxMouseEvent, moving, 0}}, - {2739, {wxMouseEvent, rightDClick, 0}}, - {2740, {wxMouseEvent, rightDown, 0}}, - {2741, {wxMouseEvent, rightIsDown, 0}}, - {2742, {wxMouseEvent, rightUp, 0}}, - {2743, {wxMouseEvent, shiftDown, 0}}, - {2744, {wxSetCursorEvent, getCursor, 0}}, - {2745, {wxSetCursorEvent, getX, 0}}, - {2746, {wxSetCursorEvent, getY, 0}}, - {2747, {wxSetCursorEvent, hasCursor, 0}}, - {2748, {wxSetCursorEvent, setCursor, 1}}, - {2749, {wxKeyEvent, altDown, 0}}, - {2750, {wxKeyEvent, cmdDown, 0}}, - {2751, {wxKeyEvent, controlDown, 0}}, - {2752, {wxKeyEvent, getKeyCode, 0}}, - {2753, {wxKeyEvent, getModifiers, 0}}, - {2756, {wxKeyEvent, getPosition, 0}}, - {2757, {wxKeyEvent, getRawKeyCode, 0}}, - {2758, {wxKeyEvent, getRawKeyFlags, 0}}, - {2759, {wxKeyEvent, getUnicodeKey, 0}}, - {2760, {wxKeyEvent, getX, 0}}, - {2761, {wxKeyEvent, getY, 0}}, - {2762, {wxKeyEvent, hasModifiers, 0}}, - {2763, {wxKeyEvent, metaDown, 0}}, - {2764, {wxKeyEvent, shiftDown, 0}}, - {2765, {wxSizeEvent, getSize, 0}}, - {2766, {wxMoveEvent, getPosition, 0}}, - {2767, {wxEraseEvent, getDC, 0}}, - {2768, {wxFocusEvent, getWindow, 0}}, - {2769, {wxChildFocusEvent, getWindow, 0}}, - {2770, {wxMenuEvent, getMenu, 0}}, - {2771, {wxMenuEvent, getMenuId, 0}}, - {2772, {wxMenuEvent, isPopup, 0}}, - {2773, {wxCloseEvent, canVeto, 0}}, - {2774, {wxCloseEvent, getLoggingOff, 0}}, - {2775, {wxCloseEvent, setCanVeto, 1}}, - {2776, {wxCloseEvent, setLoggingOff, 1}}, - {2777, {wxCloseEvent, veto, 1}}, - {2778, {wxShowEvent, setShow, 1}}, - {2779, {wxShowEvent, getShow, 0}}, - {2780, {wxIconizeEvent, iconized, 0}}, - {2781, {wxJoystickEvent, buttonDown, 1}}, - {2782, {wxJoystickEvent, buttonIsDown, 1}}, - {2783, {wxJoystickEvent, buttonUp, 1}}, - {2784, {wxJoystickEvent, getButtonChange, 0}}, - {2785, {wxJoystickEvent, getButtonState, 0}}, - {2786, {wxJoystickEvent, getJoystick, 0}}, - {2787, {wxJoystickEvent, getPosition, 0}}, - {2788, {wxJoystickEvent, getZPosition, 0}}, - {2789, {wxJoystickEvent, isButton, 0}}, - {2790, {wxJoystickEvent, isMove, 0}}, - {2791, {wxJoystickEvent, isZMove, 0}}, - {2792, {wxUpdateUIEvent, canUpdate, 1}}, - {2793, {wxUpdateUIEvent, check, 1}}, - {2794, {wxUpdateUIEvent, enable, 1}}, - {2795, {wxUpdateUIEvent, show, 1}}, - {2796, {wxUpdateUIEvent, getChecked, 0}}, - {2797, {wxUpdateUIEvent, getEnabled, 0}}, - {2798, {wxUpdateUIEvent, getShown, 0}}, - {2799, {wxUpdateUIEvent, getSetChecked, 0}}, - {2800, {wxUpdateUIEvent, getSetEnabled, 0}}, - {2801, {wxUpdateUIEvent, getSetShown, 0}}, - {2802, {wxUpdateUIEvent, getSetText, 0}}, - {2803, {wxUpdateUIEvent, getText, 0}}, - {2804, {wxUpdateUIEvent, getMode, 0}}, - {2805, {wxUpdateUIEvent, getUpdateInterval, 0}}, - {2806, {wxUpdateUIEvent, resetUpdateTime, 0}}, - {2807, {wxUpdateUIEvent, setMode, 1}}, - {2808, {wxUpdateUIEvent, setText, 1}}, - {2809, {wxUpdateUIEvent, setUpdateInterval, 1}}, - {2810, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, - {2811, {wxPaletteChangedEvent, setChangedWindow, 1}}, - {2812, {wxPaletteChangedEvent, getChangedWindow, 0}}, - {2813, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, - {2814, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, - {2815, {wxNavigationKeyEvent, getDirection, 0}}, - {2816, {wxNavigationKeyEvent, setDirection, 1}}, - {2817, {wxNavigationKeyEvent, isWindowChange, 0}}, - {2818, {wxNavigationKeyEvent, setWindowChange, 1}}, - {2819, {wxNavigationKeyEvent, isFromTab, 0}}, - {2820, {wxNavigationKeyEvent, setFromTab, 1}}, - {2821, {wxNavigationKeyEvent, getCurrentFocus, 0}}, - {2822, {wxNavigationKeyEvent, setCurrentFocus, 1}}, - {2823, {wxHelpEvent, getOrigin, 0}}, - {2824, {wxHelpEvent, getPosition, 0}}, - {2825, {wxHelpEvent, setOrigin, 1}}, - {2826, {wxHelpEvent, setPosition, 1}}, - {2827, {wxContextMenuEvent, getPosition, 0}}, - {2828, {wxContextMenuEvent, setPosition, 1}}, - {2829, {wxIdleEvent, canSend, 1}}, - {2830, {wxIdleEvent, getMode, 0}}, - {2831, {wxIdleEvent, requestMore, 1}}, - {2832, {wxIdleEvent, moreRequested, 0}}, - {2833, {wxIdleEvent, setMode, 1}}, - {2834, {wxGridEvent, altDown, 0}}, - {2835, {wxGridEvent, controlDown, 0}}, - {2836, {wxGridEvent, getCol, 0}}, - {2837, {wxGridEvent, getPosition, 0}}, - {2838, {wxGridEvent, getRow, 0}}, - {2839, {wxGridEvent, metaDown, 0}}, - {2840, {wxGridEvent, selecting, 0}}, - {2841, {wxGridEvent, shiftDown, 0}}, - {2842, {wxNotifyEvent, allow, 0}}, - {2843, {wxNotifyEvent, isAllowed, 0}}, - {2844, {wxNotifyEvent, veto, 0}}, - {2845, {wxSashEvent, getEdge, 0}}, - {2846, {wxSashEvent, getDragRect, 0}}, - {2847, {wxSashEvent, getDragStatus, 0}}, - {2848, {wxListEvent, getCacheFrom, 0}}, - {2849, {wxListEvent, getCacheTo, 0}}, - {2850, {wxListEvent, getKeyCode, 0}}, - {2851, {wxListEvent, getIndex, 0}}, - {2852, {wxListEvent, getColumn, 0}}, - {2853, {wxListEvent, getPoint, 0}}, - {2854, {wxListEvent, getLabel, 0}}, - {2855, {wxListEvent, getText, 0}}, - {2856, {wxListEvent, getImage, 0}}, - {2857, {wxListEvent, getData, 0}}, - {2858, {wxListEvent, getMask, 0}}, - {2859, {wxListEvent, getItem, 0}}, - {2860, {wxListEvent, isEditCancelled, 0}}, - {2861, {wxDateEvent, getDate, 0}}, - {2862, {wxCalendarEvent, getWeekDay, 0}}, - {2863, {wxFileDirPickerEvent, getPath, 0}}, - {2864, {wxColourPickerEvent, getColour, 0}}, - {2865, {wxFontPickerEvent, getFont, 0}}, - {2866, {wxStyledTextEvent, getPosition, 0}}, - {2867, {wxStyledTextEvent, getKey, 0}}, - {2868, {wxStyledTextEvent, getModifiers, 0}}, - {2869, {wxStyledTextEvent, getModificationType, 0}}, - {2870, {wxStyledTextEvent, getText, 0}}, - {2871, {wxStyledTextEvent, getLength, 0}}, - {2872, {wxStyledTextEvent, getLinesAdded, 0}}, - {2873, {wxStyledTextEvent, getLine, 0}}, - {2874, {wxStyledTextEvent, getFoldLevelNow, 0}}, - {2875, {wxStyledTextEvent, getFoldLevelPrev, 0}}, - {2876, {wxStyledTextEvent, getMargin, 0}}, - {2877, {wxStyledTextEvent, getMessage, 0}}, - {2878, {wxStyledTextEvent, getWParam, 0}}, - {2879, {wxStyledTextEvent, getLParam, 0}}, - {2880, {wxStyledTextEvent, getListType, 0}}, - {2881, {wxStyledTextEvent, getX, 0}}, - {2882, {wxStyledTextEvent, getY, 0}}, - {2883, {wxStyledTextEvent, getDragText, 0}}, - {2884, {wxStyledTextEvent, getDragAllowMove, 0}}, - {2885, {wxStyledTextEvent, getDragResult, 0}}, - {2886, {wxStyledTextEvent, getShift, 0}}, - {2887, {wxStyledTextEvent, getControl, 0}}, - {2888, {wxStyledTextEvent, getAlt, 0}}, - {2889, {utils, getKeyState, 1}}, - {2890, {utils, getMousePosition, 2}}, - {2891, {utils, getMouseState, 0}}, - {2892, {utils, setDetectableAutoRepeat, 1}}, - {2893, {utils, bell, 0}}, - {2894, {utils, findMenuItemId, 3}}, - {2895, {utils, genericFindWindowAtPoint, 1}}, - {2896, {utils, findWindowAtPoint, 1}}, - {2897, {utils, beginBusyCursor, 1}}, - {2898, {utils, endBusyCursor, 0}}, - {2899, {utils, isBusy, 0}}, - {2900, {utils, shutdown, 1}}, - {2901, {utils, shell, 1}}, - {2902, {utils, launchDefaultBrowser, 2}}, - {2903, {utils, getEmailAddress, 0}}, - {2904, {utils, getUserId, 0}}, - {2905, {utils, getHomeDir, 0}}, - {2906, {utils, newId, 0}}, - {2907, {utils, registerId, 1}}, - {2908, {utils, getCurrentId, 0}}, - {2909, {utils, getOsDescription, 0}}, - {2910, {utils, isPlatformLittleEndian, 0}}, - {2911, {utils, isPlatform64Bit, 0}}, - {2912, {wxPrintout, new, 1}}, - {2913, {wxPrintout, destruct, 0}}, - {2914, {wxPrintout, getDC, 0}}, - {2915, {wxPrintout, getPageSizeMM, 2}}, - {2916, {wxPrintout, getPageSizePixels, 2}}, - {2917, {wxPrintout, getPaperRectPixels, 0}}, - {2918, {wxPrintout, getPPIPrinter, 2}}, - {2919, {wxPrintout, getPPIScreen, 2}}, - {2920, {wxPrintout, getTitle, 0}}, - {2921, {wxPrintout, isPreview, 0}}, - {2922, {wxPrintout, fitThisSizeToPaper, 1}}, - {2923, {wxPrintout, fitThisSizeToPage, 1}}, - {2924, {wxPrintout, fitThisSizeToPageMargins, 2}}, - {2925, {wxPrintout, mapScreenSizeToPaper, 0}}, - {2926, {wxPrintout, mapScreenSizeToPage, 0}}, - {2927, {wxPrintout, mapScreenSizeToPageMargins, 1}}, - {2928, {wxPrintout, mapScreenSizeToDevice, 0}}, - {2929, {wxPrintout, getLogicalPaperRect, 0}}, - {2930, {wxPrintout, getLogicalPageRect, 0}}, - {2931, {wxPrintout, getLogicalPageMarginsRect, 1}}, - {2932, {wxPrintout, setLogicalOrigin, 2}}, - {2933, {wxPrintout, offsetLogicalOrigin, 2}}, - {2934, {wxStyledTextCtrl, new_2, 2}}, - {2935, {wxStyledTextCtrl, new_0, 0}}, - {2936, {wxStyledTextCtrl, destruct, 0}}, - {2937, {wxStyledTextCtrl, create, 2}}, - {2938, {wxStyledTextCtrl, addText, 1}}, - {2939, {wxStyledTextCtrl, addStyledText, 1}}, - {2940, {wxStyledTextCtrl, insertText, 2}}, - {2941, {wxStyledTextCtrl, clearAll, 0}}, - {2942, {wxStyledTextCtrl, clearDocumentStyle, 0}}, - {2943, {wxStyledTextCtrl, getLength, 0}}, - {2944, {wxStyledTextCtrl, getCharAt, 1}}, - {2945, {wxStyledTextCtrl, getCurrentPos, 0}}, - {2946, {wxStyledTextCtrl, getAnchor, 0}}, - {2947, {wxStyledTextCtrl, getStyleAt, 1}}, - {2948, {wxStyledTextCtrl, redo, 0}}, - {2949, {wxStyledTextCtrl, setUndoCollection, 1}}, - {2950, {wxStyledTextCtrl, selectAll, 0}}, - {2951, {wxStyledTextCtrl, setSavePoint, 0}}, - {2952, {wxStyledTextCtrl, getStyledText, 2}}, - {2953, {wxStyledTextCtrl, canRedo, 0}}, - {2954, {wxStyledTextCtrl, markerLineFromHandle, 1}}, - {2955, {wxStyledTextCtrl, markerDeleteHandle, 1}}, - {2956, {wxStyledTextCtrl, getUndoCollection, 0}}, - {2957, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, - {2958, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, - {2959, {wxStyledTextCtrl, positionFromPoint, 1}}, - {2960, {wxStyledTextCtrl, positionFromPointClose, 2}}, - {2961, {wxStyledTextCtrl, gotoLine, 1}}, - {2962, {wxStyledTextCtrl, gotoPos, 1}}, - {2963, {wxStyledTextCtrl, setAnchor, 1}}, - {2964, {wxStyledTextCtrl, getCurLine, 1}}, - {2965, {wxStyledTextCtrl, getEndStyled, 0}}, - {2966, {wxStyledTextCtrl, convertEOLs, 1}}, - {2967, {wxStyledTextCtrl, getEOLMode, 0}}, - {2968, {wxStyledTextCtrl, setEOLMode, 1}}, - {2969, {wxStyledTextCtrl, startStyling, 2}}, - {2970, {wxStyledTextCtrl, setStyling, 2}}, - {2971, {wxStyledTextCtrl, getBufferedDraw, 0}}, - {2972, {wxStyledTextCtrl, setBufferedDraw, 1}}, - {2973, {wxStyledTextCtrl, setTabWidth, 1}}, - {2974, {wxStyledTextCtrl, getTabWidth, 0}}, - {2975, {wxStyledTextCtrl, setCodePage, 1}}, - {2976, {wxStyledTextCtrl, markerDefine, 3}}, - {2977, {wxStyledTextCtrl, markerSetForeground, 2}}, - {2978, {wxStyledTextCtrl, markerSetBackground, 2}}, - {2979, {wxStyledTextCtrl, markerAdd, 2}}, - {2980, {wxStyledTextCtrl, markerDelete, 2}}, - {2981, {wxStyledTextCtrl, markerDeleteAll, 1}}, - {2982, {wxStyledTextCtrl, markerGet, 1}}, - {2983, {wxStyledTextCtrl, markerNext, 2}}, - {2984, {wxStyledTextCtrl, markerPrevious, 2}}, - {2985, {wxStyledTextCtrl, markerDefineBitmap, 2}}, - {2986, {wxStyledTextCtrl, markerAddSet, 2}}, - {2987, {wxStyledTextCtrl, markerSetAlpha, 2}}, - {2988, {wxStyledTextCtrl, setMarginType, 2}}, - {2989, {wxStyledTextCtrl, getMarginType, 1}}, - {2990, {wxStyledTextCtrl, setMarginWidth, 2}}, - {2991, {wxStyledTextCtrl, getMarginWidth, 1}}, - {2992, {wxStyledTextCtrl, setMarginMask, 2}}, - {2993, {wxStyledTextCtrl, getMarginMask, 1}}, - {2994, {wxStyledTextCtrl, setMarginSensitive, 2}}, - {2995, {wxStyledTextCtrl, getMarginSensitive, 1}}, - {2996, {wxStyledTextCtrl, styleClearAll, 0}}, - {2997, {wxStyledTextCtrl, styleSetForeground, 2}}, - {2998, {wxStyledTextCtrl, styleSetBackground, 2}}, - {2999, {wxStyledTextCtrl, styleSetBold, 2}}, - {3000, {wxStyledTextCtrl, styleSetItalic, 2}}, - {3001, {wxStyledTextCtrl, styleSetSize, 2}}, - {3002, {wxStyledTextCtrl, styleSetFaceName, 2}}, - {3003, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, - {3004, {wxStyledTextCtrl, styleResetDefault, 0}}, - {3005, {wxStyledTextCtrl, styleSetUnderline, 2}}, - {3006, {wxStyledTextCtrl, styleSetCase, 2}}, - {3007, {wxStyledTextCtrl, styleSetHotSpot, 2}}, - {3008, {wxStyledTextCtrl, setSelForeground, 2}}, - {3009, {wxStyledTextCtrl, setSelBackground, 2}}, - {3010, {wxStyledTextCtrl, getSelAlpha, 0}}, - {3011, {wxStyledTextCtrl, setSelAlpha, 1}}, - {3012, {wxStyledTextCtrl, setCaretForeground, 1}}, - {3013, {wxStyledTextCtrl, cmdKeyAssign, 3}}, - {3014, {wxStyledTextCtrl, cmdKeyClear, 2}}, - {3015, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, - {3016, {wxStyledTextCtrl, setStyleBytes, 2}}, - {3017, {wxStyledTextCtrl, styleSetVisible, 2}}, - {3018, {wxStyledTextCtrl, getCaretPeriod, 0}}, - {3019, {wxStyledTextCtrl, setCaretPeriod, 1}}, - {3020, {wxStyledTextCtrl, setWordChars, 1}}, - {3021, {wxStyledTextCtrl, beginUndoAction, 0}}, - {3022, {wxStyledTextCtrl, endUndoAction, 0}}, - {3023, {wxStyledTextCtrl, indicatorSetStyle, 2}}, - {3024, {wxStyledTextCtrl, indicatorGetStyle, 1}}, - {3025, {wxStyledTextCtrl, indicatorSetForeground, 2}}, - {3026, {wxStyledTextCtrl, indicatorGetForeground, 1}}, - {3027, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, - {3028, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, - {3029, {wxStyledTextCtrl, getStyleBits, 0}}, - {3030, {wxStyledTextCtrl, setLineState, 2}}, - {3031, {wxStyledTextCtrl, getLineState, 1}}, - {3032, {wxStyledTextCtrl, getMaxLineState, 0}}, - {3033, {wxStyledTextCtrl, getCaretLineVisible, 0}}, - {3034, {wxStyledTextCtrl, setCaretLineVisible, 1}}, - {3035, {wxStyledTextCtrl, getCaretLineBackground, 0}}, - {3036, {wxStyledTextCtrl, setCaretLineBackground, 1}}, - {3037, {wxStyledTextCtrl, autoCompShow, 2}}, - {3038, {wxStyledTextCtrl, autoCompCancel, 0}}, - {3039, {wxStyledTextCtrl, autoCompActive, 0}}, - {3040, {wxStyledTextCtrl, autoCompPosStart, 0}}, - {3041, {wxStyledTextCtrl, autoCompComplete, 0}}, - {3042, {wxStyledTextCtrl, autoCompStops, 1}}, - {3043, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, - {3044, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, - {3045, {wxStyledTextCtrl, autoCompSelect, 1}}, - {3046, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, - {3047, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, - {3048, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, - {3049, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, - {3050, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, - {3051, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, - {3052, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, - {3053, {wxStyledTextCtrl, userListShow, 2}}, - {3054, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, - {3055, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, - {3056, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, - {3057, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, - {3058, {wxStyledTextCtrl, registerImage, 2}}, - {3059, {wxStyledTextCtrl, clearRegisteredImages, 0}}, - {3060, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, - {3061, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, - {3062, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, - {3063, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, - {3064, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, - {3065, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, - {3066, {wxStyledTextCtrl, setIndent, 1}}, - {3067, {wxStyledTextCtrl, getIndent, 0}}, - {3068, {wxStyledTextCtrl, setUseTabs, 1}}, - {3069, {wxStyledTextCtrl, getUseTabs, 0}}, - {3070, {wxStyledTextCtrl, setLineIndentation, 2}}, - {3071, {wxStyledTextCtrl, getLineIndentation, 1}}, - {3072, {wxStyledTextCtrl, getLineIndentPosition, 1}}, - {3073, {wxStyledTextCtrl, getColumn, 1}}, - {3074, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, - {3075, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, - {3076, {wxStyledTextCtrl, setIndentationGuides, 1}}, - {3077, {wxStyledTextCtrl, getIndentationGuides, 0}}, - {3078, {wxStyledTextCtrl, setHighlightGuide, 1}}, - {3079, {wxStyledTextCtrl, getHighlightGuide, 0}}, - {3080, {wxStyledTextCtrl, getLineEndPosition, 1}}, - {3081, {wxStyledTextCtrl, getCodePage, 0}}, - {3082, {wxStyledTextCtrl, getCaretForeground, 0}}, - {3083, {wxStyledTextCtrl, getReadOnly, 0}}, - {3084, {wxStyledTextCtrl, setCurrentPos, 1}}, - {3085, {wxStyledTextCtrl, setSelectionStart, 1}}, - {3086, {wxStyledTextCtrl, getSelectionStart, 0}}, - {3087, {wxStyledTextCtrl, setSelectionEnd, 1}}, - {3088, {wxStyledTextCtrl, getSelectionEnd, 0}}, - {3089, {wxStyledTextCtrl, setPrintMagnification, 1}}, - {3090, {wxStyledTextCtrl, getPrintMagnification, 0}}, - {3091, {wxStyledTextCtrl, setPrintColourMode, 1}}, - {3092, {wxStyledTextCtrl, getPrintColourMode, 0}}, - {3093, {wxStyledTextCtrl, findText, 4}}, - {3094, {wxStyledTextCtrl, formatRange, 7}}, - {3095, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, - {3096, {wxStyledTextCtrl, getLine, 1}}, - {3097, {wxStyledTextCtrl, getLineCount, 0}}, - {3098, {wxStyledTextCtrl, setMarginLeft, 1}}, - {3099, {wxStyledTextCtrl, getMarginLeft, 0}}, - {3100, {wxStyledTextCtrl, setMarginRight, 1}}, - {3101, {wxStyledTextCtrl, getMarginRight, 0}}, - {3102, {wxStyledTextCtrl, getModify, 0}}, - {3103, {wxStyledTextCtrl, setSelection, 2}}, - {3104, {wxStyledTextCtrl, getSelectedText, 0}}, - {3105, {wxStyledTextCtrl, getTextRange, 2}}, - {3106, {wxStyledTextCtrl, hideSelection, 1}}, - {3107, {wxStyledTextCtrl, lineFromPosition, 1}}, - {3108, {wxStyledTextCtrl, positionFromLine, 1}}, - {3109, {wxStyledTextCtrl, lineScroll, 2}}, - {3110, {wxStyledTextCtrl, ensureCaretVisible, 0}}, - {3111, {wxStyledTextCtrl, replaceSelection, 1}}, - {3112, {wxStyledTextCtrl, setReadOnly, 1}}, - {3113, {wxStyledTextCtrl, canPaste, 0}}, - {3114, {wxStyledTextCtrl, canUndo, 0}}, - {3115, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, - {3116, {wxStyledTextCtrl, undo, 0}}, - {3117, {wxStyledTextCtrl, cut, 0}}, - {3118, {wxStyledTextCtrl, copy, 0}}, - {3119, {wxStyledTextCtrl, paste, 0}}, - {3120, {wxStyledTextCtrl, clear, 0}}, - {3121, {wxStyledTextCtrl, setText, 1}}, - {3122, {wxStyledTextCtrl, getText, 0}}, - {3123, {wxStyledTextCtrl, getTextLength, 0}}, - {3124, {wxStyledTextCtrl, getOvertype, 0}}, - {3125, {wxStyledTextCtrl, setCaretWidth, 1}}, - {3126, {wxStyledTextCtrl, getCaretWidth, 0}}, - {3127, {wxStyledTextCtrl, setTargetStart, 1}}, - {3128, {wxStyledTextCtrl, getTargetStart, 0}}, - {3129, {wxStyledTextCtrl, setTargetEnd, 1}}, - {3130, {wxStyledTextCtrl, getTargetEnd, 0}}, - {3131, {wxStyledTextCtrl, replaceTarget, 1}}, - {3132, {wxStyledTextCtrl, searchInTarget, 1}}, - {3133, {wxStyledTextCtrl, setSearchFlags, 1}}, - {3134, {wxStyledTextCtrl, getSearchFlags, 0}}, - {3135, {wxStyledTextCtrl, callTipShow, 2}}, - {3136, {wxStyledTextCtrl, callTipCancel, 0}}, - {3137, {wxStyledTextCtrl, callTipActive, 0}}, - {3138, {wxStyledTextCtrl, callTipPosAtStart, 0}}, - {3139, {wxStyledTextCtrl, callTipSetHighlight, 2}}, - {3140, {wxStyledTextCtrl, callTipSetBackground, 1}}, - {3141, {wxStyledTextCtrl, callTipSetForeground, 1}}, - {3142, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, - {3143, {wxStyledTextCtrl, callTipUseStyle, 1}}, - {3144, {wxStyledTextCtrl, visibleFromDocLine, 1}}, - {3145, {wxStyledTextCtrl, docLineFromVisible, 1}}, - {3146, {wxStyledTextCtrl, wrapCount, 1}}, - {3147, {wxStyledTextCtrl, setFoldLevel, 2}}, - {3148, {wxStyledTextCtrl, getFoldLevel, 1}}, - {3149, {wxStyledTextCtrl, getLastChild, 2}}, - {3150, {wxStyledTextCtrl, getFoldParent, 1}}, - {3151, {wxStyledTextCtrl, showLines, 2}}, - {3152, {wxStyledTextCtrl, hideLines, 2}}, - {3153, {wxStyledTextCtrl, getLineVisible, 1}}, - {3154, {wxStyledTextCtrl, setFoldExpanded, 2}}, - {3155, {wxStyledTextCtrl, getFoldExpanded, 1}}, - {3156, {wxStyledTextCtrl, toggleFold, 1}}, - {3157, {wxStyledTextCtrl, ensureVisible, 1}}, - {3158, {wxStyledTextCtrl, setFoldFlags, 1}}, - {3159, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, - {3160, {wxStyledTextCtrl, setTabIndents, 1}}, - {3161, {wxStyledTextCtrl, getTabIndents, 0}}, - {3162, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, - {3163, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, - {3164, {wxStyledTextCtrl, setMouseDwellTime, 1}}, - {3165, {wxStyledTextCtrl, getMouseDwellTime, 0}}, - {3166, {wxStyledTextCtrl, wordStartPosition, 2}}, - {3167, {wxStyledTextCtrl, wordEndPosition, 2}}, - {3168, {wxStyledTextCtrl, setWrapMode, 1}}, - {3169, {wxStyledTextCtrl, getWrapMode, 0}}, - {3170, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, - {3171, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, - {3172, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, - {3173, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, - {3174, {wxStyledTextCtrl, setWrapStartIndent, 1}}, - {3175, {wxStyledTextCtrl, getWrapStartIndent, 0}}, - {3176, {wxStyledTextCtrl, setLayoutCache, 1}}, - {3177, {wxStyledTextCtrl, getLayoutCache, 0}}, - {3178, {wxStyledTextCtrl, setScrollWidth, 1}}, - {3179, {wxStyledTextCtrl, getScrollWidth, 0}}, - {3180, {wxStyledTextCtrl, textWidth, 2}}, - {3181, {wxStyledTextCtrl, getEndAtLastLine, 0}}, - {3182, {wxStyledTextCtrl, textHeight, 1}}, - {3183, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, - {3184, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, - {3185, {wxStyledTextCtrl, appendText, 1}}, - {3186, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, - {3187, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, - {3188, {wxStyledTextCtrl, targetFromSelection, 0}}, - {3189, {wxStyledTextCtrl, linesJoin, 0}}, - {3190, {wxStyledTextCtrl, linesSplit, 1}}, - {3191, {wxStyledTextCtrl, setFoldMarginColour, 2}}, - {3192, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, - {3193, {wxStyledTextCtrl, lineDown, 0}}, - {3194, {wxStyledTextCtrl, lineDownExtend, 0}}, - {3195, {wxStyledTextCtrl, lineUp, 0}}, - {3196, {wxStyledTextCtrl, lineUpExtend, 0}}, - {3197, {wxStyledTextCtrl, charLeft, 0}}, - {3198, {wxStyledTextCtrl, charLeftExtend, 0}}, - {3199, {wxStyledTextCtrl, charRight, 0}}, - {3200, {wxStyledTextCtrl, charRightExtend, 0}}, - {3201, {wxStyledTextCtrl, wordLeft, 0}}, - {3202, {wxStyledTextCtrl, wordLeftExtend, 0}}, - {3203, {wxStyledTextCtrl, wordRight, 0}}, - {3204, {wxStyledTextCtrl, wordRightExtend, 0}}, - {3205, {wxStyledTextCtrl, home, 0}}, - {3206, {wxStyledTextCtrl, homeExtend, 0}}, - {3207, {wxStyledTextCtrl, lineEnd, 0}}, - {3208, {wxStyledTextCtrl, lineEndExtend, 0}}, - {3209, {wxStyledTextCtrl, documentStart, 0}}, - {3210, {wxStyledTextCtrl, documentStartExtend, 0}}, - {3211, {wxStyledTextCtrl, documentEnd, 0}}, - {3212, {wxStyledTextCtrl, documentEndExtend, 0}}, - {3213, {wxStyledTextCtrl, pageUp, 0}}, - {3214, {wxStyledTextCtrl, pageUpExtend, 0}}, - {3215, {wxStyledTextCtrl, pageDown, 0}}, - {3216, {wxStyledTextCtrl, pageDownExtend, 0}}, - {3217, {wxStyledTextCtrl, editToggleOvertype, 0}}, - {3218, {wxStyledTextCtrl, cancel, 0}}, - {3219, {wxStyledTextCtrl, deleteBack, 0}}, - {3220, {wxStyledTextCtrl, tab, 0}}, - {3221, {wxStyledTextCtrl, backTab, 0}}, - {3222, {wxStyledTextCtrl, newLine, 0}}, - {3223, {wxStyledTextCtrl, formFeed, 0}}, - {3224, {wxStyledTextCtrl, vCHome, 0}}, - {3225, {wxStyledTextCtrl, vCHomeExtend, 0}}, - {3226, {wxStyledTextCtrl, zoomIn, 0}}, - {3227, {wxStyledTextCtrl, zoomOut, 0}}, - {3228, {wxStyledTextCtrl, delWordLeft, 0}}, - {3229, {wxStyledTextCtrl, delWordRight, 0}}, - {3230, {wxStyledTextCtrl, lineCut, 0}}, - {3231, {wxStyledTextCtrl, lineDelete, 0}}, - {3232, {wxStyledTextCtrl, lineTranspose, 0}}, - {3233, {wxStyledTextCtrl, lineDuplicate, 0}}, - {3234, {wxStyledTextCtrl, lowerCase, 0}}, - {3235, {wxStyledTextCtrl, upperCase, 0}}, - {3236, {wxStyledTextCtrl, lineScrollDown, 0}}, - {3237, {wxStyledTextCtrl, lineScrollUp, 0}}, - {3238, {wxStyledTextCtrl, deleteBackNotLine, 0}}, - {3239, {wxStyledTextCtrl, homeDisplay, 0}}, - {3240, {wxStyledTextCtrl, homeDisplayExtend, 0}}, - {3241, {wxStyledTextCtrl, lineEndDisplay, 0}}, - {3242, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, - {3243, {wxStyledTextCtrl, homeWrapExtend, 0}}, - {3244, {wxStyledTextCtrl, lineEndWrap, 0}}, - {3245, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, - {3246, {wxStyledTextCtrl, vCHomeWrap, 0}}, - {3247, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, - {3248, {wxStyledTextCtrl, lineCopy, 0}}, - {3249, {wxStyledTextCtrl, moveCaretInsideView, 0}}, - {3250, {wxStyledTextCtrl, lineLength, 1}}, - {3251, {wxStyledTextCtrl, braceHighlight, 2}}, - {3252, {wxStyledTextCtrl, braceBadLight, 1}}, - {3253, {wxStyledTextCtrl, braceMatch, 1}}, - {3254, {wxStyledTextCtrl, getViewEOL, 0}}, - {3255, {wxStyledTextCtrl, setViewEOL, 1}}, - {3256, {wxStyledTextCtrl, setModEventMask, 1}}, - {3257, {wxStyledTextCtrl, getEdgeColumn, 0}}, - {3258, {wxStyledTextCtrl, setEdgeColumn, 1}}, - {3259, {wxStyledTextCtrl, getEdgeMode, 0}}, - {3260, {wxStyledTextCtrl, getEdgeColour, 0}}, - {3261, {wxStyledTextCtrl, setEdgeColour, 1}}, - {3262, {wxStyledTextCtrl, searchAnchor, 0}}, - {3263, {wxStyledTextCtrl, searchNext, 2}}, - {3264, {wxStyledTextCtrl, searchPrev, 2}}, - {3265, {wxStyledTextCtrl, linesOnScreen, 0}}, - {3266, {wxStyledTextCtrl, usePopUp, 1}}, - {3267, {wxStyledTextCtrl, selectionIsRectangle, 0}}, - {3268, {wxStyledTextCtrl, setZoom, 1}}, - {3269, {wxStyledTextCtrl, getZoom, 0}}, - {3270, {wxStyledTextCtrl, getModEventMask, 0}}, - {3271, {wxStyledTextCtrl, setSTCFocus, 1}}, - {3272, {wxStyledTextCtrl, getSTCFocus, 0}}, - {3273, {wxStyledTextCtrl, setStatus, 1}}, - {3274, {wxStyledTextCtrl, getStatus, 0}}, - {3275, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, - {3276, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, - {3277, {wxStyledTextCtrl, setSTCCursor, 1}}, - {3278, {wxStyledTextCtrl, getSTCCursor, 0}}, - {3279, {wxStyledTextCtrl, setControlCharSymbol, 1}}, - {3280, {wxStyledTextCtrl, getControlCharSymbol, 0}}, - {3281, {wxStyledTextCtrl, wordPartLeft, 0}}, - {3282, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, - {3283, {wxStyledTextCtrl, wordPartRight, 0}}, - {3284, {wxStyledTextCtrl, wordPartRightExtend, 0}}, - {3285, {wxStyledTextCtrl, setVisiblePolicy, 2}}, - {3286, {wxStyledTextCtrl, delLineLeft, 0}}, - {3287, {wxStyledTextCtrl, delLineRight, 0}}, - {3288, {wxStyledTextCtrl, getXOffset, 0}}, - {3289, {wxStyledTextCtrl, chooseCaretX, 0}}, - {3290, {wxStyledTextCtrl, setXCaretPolicy, 2}}, - {3291, {wxStyledTextCtrl, setYCaretPolicy, 2}}, - {3292, {wxStyledTextCtrl, getPrintWrapMode, 0}}, - {3293, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, - {3294, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, - {3295, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, - {3296, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, - {3297, {wxStyledTextCtrl, paraDownExtend, 0}}, - {3298, {wxStyledTextCtrl, paraUp, 0}}, - {3299, {wxStyledTextCtrl, paraUpExtend, 0}}, - {3300, {wxStyledTextCtrl, positionBefore, 1}}, - {3301, {wxStyledTextCtrl, positionAfter, 1}}, - {3302, {wxStyledTextCtrl, copyRange, 2}}, - {3303, {wxStyledTextCtrl, copyText, 2}}, - {3304, {wxStyledTextCtrl, setSelectionMode, 1}}, - {3305, {wxStyledTextCtrl, getSelectionMode, 0}}, - {3306, {wxStyledTextCtrl, lineDownRectExtend, 0}}, - {3307, {wxStyledTextCtrl, lineUpRectExtend, 0}}, - {3308, {wxStyledTextCtrl, charLeftRectExtend, 0}}, - {3309, {wxStyledTextCtrl, charRightRectExtend, 0}}, - {3310, {wxStyledTextCtrl, homeRectExtend, 0}}, - {3311, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, - {3312, {wxStyledTextCtrl, lineEndRectExtend, 0}}, - {3313, {wxStyledTextCtrl, pageUpRectExtend, 0}}, - {3314, {wxStyledTextCtrl, pageDownRectExtend, 0}}, - {3315, {wxStyledTextCtrl, stutteredPageUp, 0}}, - {3316, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, - {3317, {wxStyledTextCtrl, stutteredPageDown, 0}}, - {3318, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, - {3319, {wxStyledTextCtrl, wordLeftEnd, 0}}, - {3320, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, - {3321, {wxStyledTextCtrl, wordRightEnd, 0}}, - {3322, {wxStyledTextCtrl, wordRightEndExtend, 0}}, - {3323, {wxStyledTextCtrl, setWhitespaceChars, 1}}, - {3324, {wxStyledTextCtrl, setCharsDefault, 0}}, - {3325, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, - {3326, {wxStyledTextCtrl, allocate, 1}}, - {3327, {wxStyledTextCtrl, findColumn, 2}}, - {3328, {wxStyledTextCtrl, getCaretSticky, 0}}, - {3329, {wxStyledTextCtrl, setCaretSticky, 1}}, - {3330, {wxStyledTextCtrl, toggleCaretSticky, 0}}, - {3331, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, - {3332, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, - {3333, {wxStyledTextCtrl, selectionDuplicate, 0}}, - {3334, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, - {3335, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, - {3336, {wxStyledTextCtrl, startRecord, 0}}, - {3337, {wxStyledTextCtrl, stopRecord, 0}}, - {3338, {wxStyledTextCtrl, setLexer, 1}}, - {3339, {wxStyledTextCtrl, getLexer, 0}}, - {3340, {wxStyledTextCtrl, colourise, 2}}, - {3341, {wxStyledTextCtrl, setProperty, 2}}, - {3342, {wxStyledTextCtrl, setKeyWords, 2}}, - {3343, {wxStyledTextCtrl, setLexerLanguage, 1}}, - {3344, {wxStyledTextCtrl, getProperty, 1}}, - {3345, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, - {3346, {wxStyledTextCtrl, getCurrentLine, 0}}, - {3347, {wxStyledTextCtrl, styleSetSpec, 2}}, - {3348, {wxStyledTextCtrl, styleSetFont, 2}}, - {3349, {wxStyledTextCtrl, styleSetFontAttr, 7}}, - {3350, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, - {3351, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, - {3352, {wxStyledTextCtrl, cmdKeyExecute, 1}}, - {3353, {wxStyledTextCtrl, setMargins, 2}}, - {3354, {wxStyledTextCtrl, getSelection, 2}}, - {3355, {wxStyledTextCtrl, pointFromPosition, 1}}, - {3356, {wxStyledTextCtrl, scrollToLine, 1}}, - {3357, {wxStyledTextCtrl, scrollToColumn, 1}}, - {3358, {wxStyledTextCtrl, sendMsg, 2}}, - {3359, {wxStyledTextCtrl, setVScrollBar, 1}}, - {3360, {wxStyledTextCtrl, setHScrollBar, 1}}, - {3361, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, - {3362, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, - {3363, {wxStyledTextCtrl, saveFile, 1}}, - {3364, {wxStyledTextCtrl, loadFile, 1}}, - {3365, {wxStyledTextCtrl, doDragOver, 3}}, - {3366, {wxStyledTextCtrl, doDropText, 3}}, - {3367, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, - {3368, {wxStyledTextCtrl, addTextRaw, 1}}, - {3369, {wxStyledTextCtrl, insertTextRaw, 2}}, - {3370, {wxStyledTextCtrl, getCurLineRaw, 1}}, - {3371, {wxStyledTextCtrl, getLineRaw, 1}}, - {3372, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, - {3373, {wxStyledTextCtrl, getTextRangeRaw, 2}}, - {3374, {wxStyledTextCtrl, setTextRaw, 1}}, - {3375, {wxStyledTextCtrl, getTextRaw, 0}}, - {3376, {wxStyledTextCtrl, appendTextRaw, 1}}, - {3377, {wxArtProvider, getBitmap, 2}}, - {3378, {wxArtProvider, getIcon, 2}}, - {3379, {wxTreeEvent, getKeyCode, 0}}, - {3380, {wxTreeEvent, getItem, 0}}, - {3381, {wxTreeEvent, getKeyEvent, 0}}, - {3382, {wxTreeEvent, getLabel, 0}}, - {3383, {wxTreeEvent, getOldItem, 0}}, - {3384, {wxTreeEvent, getPoint, 0}}, - {3385, {wxTreeEvent, isEditCancelled, 0}}, - {3386, {wxTreeEvent, setToolTip, 1}}, - {3387, {wxNotebookEvent, getOldSelection, 0}}, - {3388, {wxNotebookEvent, getSelection, 0}}, - {3389, {wxNotebookEvent, setOldSelection, 1}}, - {3390, {wxNotebookEvent, setSelection, 1}}, - {3391, {wxFileDataObject, new, 0}}, - {3392, {wxFileDataObject, addFile, 1}}, - {3393, {wxFileDataObject, getFilenames, 0}}, - {3394, {wxFileDataObject, 'Destroy', undefined}}, - {3395, {wxTextDataObject, new, 1}}, - {3396, {wxTextDataObject, getTextLength, 0}}, - {3397, {wxTextDataObject, getText, 0}}, - {3398, {wxTextDataObject, setText, 1}}, - {3399, {wxTextDataObject, 'Destroy', undefined}}, - {3400, {wxBitmapDataObject, new_1_1, 1}}, - {3401, {wxBitmapDataObject, new_1_0, 1}}, - {3402, {wxBitmapDataObject, getBitmap, 0}}, - {3403, {wxBitmapDataObject, setBitmap, 1}}, - {3404, {wxBitmapDataObject, 'Destroy', undefined}}, - {3406, {wxClipboard, new, 0}}, - {3407, {wxClipboard, destruct, 0}}, - {3408, {wxClipboard, addData, 1}}, - {3409, {wxClipboard, clear, 0}}, - {3410, {wxClipboard, close, 0}}, - {3411, {wxClipboard, flush, 0}}, - {3412, {wxClipboard, getData, 1}}, - {3413, {wxClipboard, isOpened, 0}}, - {3414, {wxClipboard, open, 0}}, - {3415, {wxClipboard, setData, 1}}, - {3417, {wxClipboard, usePrimarySelection, 1}}, - {3418, {wxClipboard, isSupported, 1}}, - {3419, {wxClipboard, get, 0}}, - {3420, {wxSpinEvent, getPosition, 0}}, - {3421, {wxSpinEvent, setPosition, 1}}, - {3422, {wxSplitterWindow, new_0, 0}}, - {3423, {wxSplitterWindow, new_2, 2}}, - {3424, {wxSplitterWindow, destruct, 0}}, - {3425, {wxSplitterWindow, create, 2}}, - {3426, {wxSplitterWindow, getMinimumPaneSize, 0}}, - {3427, {wxSplitterWindow, getSashGravity, 0}}, - {3428, {wxSplitterWindow, getSashPosition, 0}}, - {3429, {wxSplitterWindow, getSplitMode, 0}}, - {3430, {wxSplitterWindow, getWindow1, 0}}, - {3431, {wxSplitterWindow, getWindow2, 0}}, - {3432, {wxSplitterWindow, initialize, 1}}, - {3433, {wxSplitterWindow, isSplit, 0}}, - {3434, {wxSplitterWindow, replaceWindow, 2}}, - {3435, {wxSplitterWindow, setSashGravity, 1}}, - {3436, {wxSplitterWindow, setSashPosition, 2}}, - {3437, {wxSplitterWindow, setSashSize, 1}}, - {3438, {wxSplitterWindow, setMinimumPaneSize, 1}}, - {3439, {wxSplitterWindow, setSplitMode, 1}}, - {3440, {wxSplitterWindow, splitHorizontally, 3}}, - {3441, {wxSplitterWindow, splitVertically, 3}}, - {3442, {wxSplitterWindow, unsplit, 1}}, - {3443, {wxSplitterWindow, updateSize, 0}}, - {3444, {wxSplitterEvent, getSashPosition, 0}}, - {3445, {wxSplitterEvent, getX, 0}}, - {3446, {wxSplitterEvent, getY, 0}}, - {3447, {wxSplitterEvent, getWindowBeingRemoved, 0}}, - {3448, {wxSplitterEvent, setSashPosition, 1}}, - {3449, {wxHtmlWindow, new_0, 0}}, - {3450, {wxHtmlWindow, new_2, 2}}, - {3451, {wxHtmlWindow, appendToPage, 1}}, - {3452, {wxHtmlWindow, getOpenedAnchor, 0}}, - {3453, {wxHtmlWindow, getOpenedPage, 0}}, - {3454, {wxHtmlWindow, getOpenedPageTitle, 0}}, - {3455, {wxHtmlWindow, getRelatedFrame, 0}}, - {3456, {wxHtmlWindow, historyBack, 0}}, - {3457, {wxHtmlWindow, historyCanBack, 0}}, - {3458, {wxHtmlWindow, historyCanForward, 0}}, - {3459, {wxHtmlWindow, historyClear, 0}}, - {3460, {wxHtmlWindow, historyForward, 0}}, - {3461, {wxHtmlWindow, loadFile, 1}}, - {3462, {wxHtmlWindow, loadPage, 1}}, - {3463, {wxHtmlWindow, selectAll, 0}}, - {3464, {wxHtmlWindow, selectionToText, 0}}, - {3465, {wxHtmlWindow, selectLine, 1}}, - {3466, {wxHtmlWindow, selectWord, 1}}, - {3467, {wxHtmlWindow, setBorders, 1}}, - {3468, {wxHtmlWindow, setFonts, 3}}, - {3469, {wxHtmlWindow, setPage, 1}}, - {3470, {wxHtmlWindow, setRelatedFrame, 2}}, - {3471, {wxHtmlWindow, setRelatedStatusBar, 1}}, - {3472, {wxHtmlWindow, toText, 0}}, - {3473, {wxHtmlWindow, 'Destroy', undefined}}, - {3474, {wxHtmlLinkEvent, getLinkInfo, 0}}, - {3475, {wxAuiNotebookEvent, setSelection, 1}}, - {3476, {wxAuiNotebookEvent, getSelection, 0}}, - {3477, {wxAuiNotebookEvent, setOldSelection, 1}}, - {3478, {wxAuiNotebookEvent, getOldSelection, 0}}, - {3479, {wxAuiNotebookEvent, setDragSource, 1}}, - {3480, {wxAuiNotebookEvent, getDragSource, 0}}, - {3481, {wxAuiManagerEvent, setManager, 1}}, - {3482, {wxAuiManagerEvent, getManager, 0}}, - {3483, {wxAuiManagerEvent, setPane, 1}}, - {3484, {wxAuiManagerEvent, getPane, 0}}, - {3485, {wxAuiManagerEvent, setButton, 1}}, - {3486, {wxAuiManagerEvent, getButton, 0}}, - {3487, {wxAuiManagerEvent, setDC, 1}}, - {3488, {wxAuiManagerEvent, getDC, 0}}, - {3489, {wxAuiManagerEvent, veto, 1}}, - {3490, {wxAuiManagerEvent, getVeto, 0}}, - {3491, {wxAuiManagerEvent, setCanVeto, 1}}, - {3492, {wxAuiManagerEvent, canVeto, 0}}, - {3493, {wxLogNull, new, 0}}, - {3494, {wxLogNull, 'Destroy', undefined}}, + {2010, {wxTreeCtrl, editLabel, 1}}, + {2011, {wxTreeCtrl, ensureVisible, 1}}, + {2012, {wxTreeCtrl, expand, 1}}, + {2013, {wxTreeCtrl, getBoundingRect, 3}}, + {2015, {wxTreeCtrl, getChildrenCount, 2}}, + {2016, {wxTreeCtrl, getCount, 0}}, + {2017, {wxTreeCtrl, getEditControl, 0}}, + {2018, {wxTreeCtrl, getFirstChild, 2}}, + {2019, {wxTreeCtrl, getNextChild, 2}}, + {2020, {wxTreeCtrl, getFirstVisibleItem, 0}}, + {2021, {wxTreeCtrl, getImageList, 0}}, + {2022, {wxTreeCtrl, getIndent, 0}}, + {2023, {wxTreeCtrl, getItemBackgroundColour, 1}}, + {2024, {wxTreeCtrl, getItemData, 1}}, + {2025, {wxTreeCtrl, getItemFont, 1}}, + {2026, {wxTreeCtrl, getItemImage_1, 1}}, + {2027, {wxTreeCtrl, getItemImage_2, 2}}, + {2028, {wxTreeCtrl, getItemText, 1}}, + {2029, {wxTreeCtrl, getItemTextColour, 1}}, + {2030, {wxTreeCtrl, getLastChild, 1}}, + {2031, {wxTreeCtrl, getNextSibling, 1}}, + {2032, {wxTreeCtrl, getNextVisible, 1}}, + {2033, {wxTreeCtrl, getItemParent, 1}}, + {2034, {wxTreeCtrl, getPrevSibling, 1}}, + {2035, {wxTreeCtrl, getPrevVisible, 1}}, + {2036, {wxTreeCtrl, getRootItem, 0}}, + {2037, {wxTreeCtrl, getSelection, 0}}, + {2038, {wxTreeCtrl, getSelections, 1}}, + {2039, {wxTreeCtrl, getStateImageList, 0}}, + {2040, {wxTreeCtrl, hitTest, 1}}, + {2042, {wxTreeCtrl, insertItem, 4}}, + {2043, {wxTreeCtrl, isBold, 1}}, + {2044, {wxTreeCtrl, isExpanded, 1}}, + {2045, {wxTreeCtrl, isSelected, 1}}, + {2046, {wxTreeCtrl, isVisible, 1}}, + {2047, {wxTreeCtrl, itemHasChildren, 1}}, + {2048, {wxTreeCtrl, prependItem, 3}}, + {2049, {wxTreeCtrl, scrollTo, 1}}, + {2050, {wxTreeCtrl, selectItem_1, 1}}, + {2051, {wxTreeCtrl, selectItem_2, 2}}, + {2052, {wxTreeCtrl, setIndent, 1}}, + {2053, {wxTreeCtrl, setImageList, 1}}, + {2054, {wxTreeCtrl, setItemBackgroundColour, 2}}, + {2055, {wxTreeCtrl, setItemBold, 2}}, + {2056, {wxTreeCtrl, setItemData, 2}}, + {2057, {wxTreeCtrl, setItemDropHighlight, 2}}, + {2058, {wxTreeCtrl, setItemFont, 2}}, + {2059, {wxTreeCtrl, setItemHasChildren, 2}}, + {2060, {wxTreeCtrl, setItemImage_2, 2}}, + {2061, {wxTreeCtrl, setItemImage_3, 3}}, + {2062, {wxTreeCtrl, setItemText, 2}}, + {2063, {wxTreeCtrl, setItemTextColour, 2}}, + {2064, {wxTreeCtrl, setStateImageList, 1}}, + {2065, {wxTreeCtrl, setWindowStyle, 1}}, + {2066, {wxTreeCtrl, sortChildren, 1}}, + {2067, {wxTreeCtrl, toggle, 1}}, + {2068, {wxTreeCtrl, toggleItemSelection, 1}}, + {2069, {wxTreeCtrl, unselect, 0}}, + {2070, {wxTreeCtrl, unselectAll, 0}}, + {2071, {wxTreeCtrl, unselectItem, 1}}, + {2072, {wxScrollBar, new_0, 0}}, + {2073, {wxScrollBar, new_3, 3}}, + {2074, {wxScrollBar, destruct, 0}}, + {2075, {wxScrollBar, create, 3}}, + {2076, {wxScrollBar, getRange, 0}}, + {2077, {wxScrollBar, getPageSize, 0}}, + {2078, {wxScrollBar, getThumbPosition, 0}}, + {2079, {wxScrollBar, getThumbSize, 0}}, + {2080, {wxScrollBar, setThumbPosition, 1}}, + {2081, {wxScrollBar, setScrollbar, 5}}, + {2083, {wxSpinButton, new_2, 2}}, + {2084, {wxSpinButton, new_0, 0}}, + {2085, {wxSpinButton, create, 2}}, + {2086, {wxSpinButton, getMax, 0}}, + {2087, {wxSpinButton, getMin, 0}}, + {2088, {wxSpinButton, getValue, 0}}, + {2089, {wxSpinButton, setRange, 2}}, + {2090, {wxSpinButton, setValue, 1}}, + {2091, {wxSpinButton, 'Destroy', undefined}}, + {2092, {wxSpinCtrl, new_0, 0}}, + {2093, {wxSpinCtrl, new_2, 2}}, + {2095, {wxSpinCtrl, create, 2}}, + {2098, {wxSpinCtrl, setValue_1_1, 1}}, + {2099, {wxSpinCtrl, setValue_1_0, 1}}, + {2101, {wxSpinCtrl, getValue, 0}}, + {2103, {wxSpinCtrl, setRange, 2}}, + {2104, {wxSpinCtrl, setSelection, 2}}, + {2106, {wxSpinCtrl, getMin, 0}}, + {2108, {wxSpinCtrl, getMax, 0}}, + {2109, {wxSpinCtrl, 'Destroy', undefined}}, + {2110, {wxStaticText, new_0, 0}}, + {2111, {wxStaticText, new_4, 4}}, + {2112, {wxStaticText, create, 4}}, + {2113, {wxStaticText, getLabel, 0}}, + {2114, {wxStaticText, setLabel, 1}}, + {2115, {wxStaticText, wrap, 1}}, + {2116, {wxStaticText, 'Destroy', undefined}}, + {2117, {wxStaticBitmap, new_0, 0}}, + {2118, {wxStaticBitmap, new_4, 4}}, + {2119, {wxStaticBitmap, create, 4}}, + {2120, {wxStaticBitmap, getBitmap, 0}}, + {2121, {wxStaticBitmap, setBitmap, 1}}, + {2122, {wxStaticBitmap, 'Destroy', undefined}}, + {2123, {wxRadioBox, new, 7}}, + {2125, {wxRadioBox, destruct, 0}}, + {2126, {wxRadioBox, create, 7}}, + {2127, {wxRadioBox, enable_2, 2}}, + {2128, {wxRadioBox, enable_1, 1}}, + {2129, {wxRadioBox, getSelection, 0}}, + {2130, {wxRadioBox, getString, 1}}, + {2131, {wxRadioBox, setSelection, 1}}, + {2132, {wxRadioBox, show_2, 2}}, + {2133, {wxRadioBox, show_1, 1}}, + {2134, {wxRadioBox, getColumnCount, 0}}, + {2135, {wxRadioBox, getItemHelpText, 1}}, + {2136, {wxRadioBox, getItemToolTip, 1}}, + {2138, {wxRadioBox, getItemFromPoint, 1}}, + {2139, {wxRadioBox, getRowCount, 0}}, + {2140, {wxRadioBox, isItemEnabled, 1}}, + {2141, {wxRadioBox, isItemShown, 1}}, + {2142, {wxRadioBox, setItemHelpText, 2}}, + {2143, {wxRadioBox, setItemToolTip, 2}}, + {2144, {wxRadioButton, new_0, 0}}, + {2145, {wxRadioButton, new_4, 4}}, + {2146, {wxRadioButton, create, 4}}, + {2147, {wxRadioButton, getValue, 0}}, + {2148, {wxRadioButton, setValue, 1}}, + {2149, {wxRadioButton, 'Destroy', undefined}}, + {2151, {wxSlider, new_6, 6}}, + {2152, {wxSlider, new_0, 0}}, + {2153, {wxSlider, create, 6}}, + {2154, {wxSlider, getLineSize, 0}}, + {2155, {wxSlider, getMax, 0}}, + {2156, {wxSlider, getMin, 0}}, + {2157, {wxSlider, getPageSize, 0}}, + {2158, {wxSlider, getThumbLength, 0}}, + {2159, {wxSlider, getValue, 0}}, + {2160, {wxSlider, setLineSize, 1}}, + {2161, {wxSlider, setPageSize, 1}}, + {2162, {wxSlider, setRange, 2}}, + {2163, {wxSlider, setThumbLength, 1}}, + {2164, {wxSlider, setValue, 1}}, + {2165, {wxSlider, 'Destroy', undefined}}, + {2167, {wxDialog, new_4, 4}}, + {2168, {wxDialog, new_0, 0}}, + {2170, {wxDialog, destruct, 0}}, + {2171, {wxDialog, create, 4}}, + {2172, {wxDialog, createButtonSizer, 1}}, + {2173, {wxDialog, createStdDialogButtonSizer, 1}}, + {2174, {wxDialog, endModal, 1}}, + {2175, {wxDialog, getAffirmativeId, 0}}, + {2176, {wxDialog, getReturnCode, 0}}, + {2177, {wxDialog, isModal, 0}}, + {2178, {wxDialog, setAffirmativeId, 1}}, + {2179, {wxDialog, setReturnCode, 1}}, + {2180, {wxDialog, show, 1}}, + {2181, {wxDialog, showModal, 0}}, + {2182, {wxColourDialog, new_0, 0}}, + {2183, {wxColourDialog, new_2, 2}}, + {2184, {wxColourDialog, destruct, 0}}, + {2185, {wxColourDialog, create, 2}}, + {2186, {wxColourDialog, getColourData, 0}}, + {2187, {wxColourData, new_0, 0}}, + {2188, {wxColourData, new_1, 1}}, + {2189, {wxColourData, destruct, 0}}, + {2190, {wxColourData, getChooseFull, 0}}, + {2191, {wxColourData, getColour, 0}}, + {2193, {wxColourData, getCustomColour, 1}}, + {2194, {wxColourData, setChooseFull, 1}}, + {2195, {wxColourData, setColour, 1}}, + {2196, {wxColourData, setCustomColour, 2}}, + {2197, {wxPalette, new_0, 0}}, + {2198, {wxPalette, new_4, 4}}, + {2200, {wxPalette, destruct, 0}}, + {2201, {wxPalette, create, 4}}, + {2202, {wxPalette, getColoursCount, 0}}, + {2203, {wxPalette, getPixel, 3}}, + {2204, {wxPalette, getRGB, 4}}, + {2205, {wxPalette, isOk, 0}}, + {2209, {wxDirDialog, new, 2}}, + {2210, {wxDirDialog, destruct, 0}}, + {2211, {wxDirDialog, getPath, 0}}, + {2212, {wxDirDialog, getMessage, 0}}, + {2213, {wxDirDialog, setMessage, 1}}, + {2214, {wxDirDialog, setPath, 1}}, + {2218, {wxFileDialog, new, 2}}, + {2219, {wxFileDialog, destruct, 0}}, + {2220, {wxFileDialog, getDirectory, 0}}, + {2221, {wxFileDialog, getFilename, 0}}, + {2222, {wxFileDialog, getFilenames, 1}}, + {2223, {wxFileDialog, getFilterIndex, 0}}, + {2224, {wxFileDialog, getMessage, 0}}, + {2225, {wxFileDialog, getPath, 0}}, + {2226, {wxFileDialog, getPaths, 1}}, + {2227, {wxFileDialog, getWildcard, 0}}, + {2228, {wxFileDialog, setDirectory, 1}}, + {2229, {wxFileDialog, setFilename, 1}}, + {2230, {wxFileDialog, setFilterIndex, 1}}, + {2231, {wxFileDialog, setMessage, 1}}, + {2232, {wxFileDialog, setPath, 1}}, + {2233, {wxFileDialog, setWildcard, 1}}, + {2234, {wxPickerBase, setInternalMargin, 1}}, + {2235, {wxPickerBase, getInternalMargin, 0}}, + {2236, {wxPickerBase, setTextCtrlProportion, 1}}, + {2237, {wxPickerBase, setPickerCtrlProportion, 1}}, + {2238, {wxPickerBase, getTextCtrlProportion, 0}}, + {2239, {wxPickerBase, getPickerCtrlProportion, 0}}, + {2240, {wxPickerBase, hasTextCtrl, 0}}, + {2241, {wxPickerBase, getTextCtrl, 0}}, + {2242, {wxPickerBase, isTextCtrlGrowable, 0}}, + {2243, {wxPickerBase, setPickerCtrlGrowable, 1}}, + {2244, {wxPickerBase, setTextCtrlGrowable, 1}}, + {2245, {wxPickerBase, isPickerCtrlGrowable, 0}}, + {2246, {wxFilePickerCtrl, new_0, 0}}, + {2247, {wxFilePickerCtrl, new_3, 3}}, + {2248, {wxFilePickerCtrl, create, 3}}, + {2249, {wxFilePickerCtrl, getPath, 0}}, + {2250, {wxFilePickerCtrl, setPath, 1}}, + {2251, {wxFilePickerCtrl, 'Destroy', undefined}}, + {2252, {wxDirPickerCtrl, new_0, 0}}, + {2253, {wxDirPickerCtrl, new_3, 3}}, + {2254, {wxDirPickerCtrl, create, 3}}, + {2255, {wxDirPickerCtrl, getPath, 0}}, + {2256, {wxDirPickerCtrl, setPath, 1}}, + {2257, {wxDirPickerCtrl, 'Destroy', undefined}}, + {2258, {wxColourPickerCtrl, new_0, 0}}, + {2259, {wxColourPickerCtrl, new_3, 3}}, + {2260, {wxColourPickerCtrl, create, 3}}, + {2261, {wxColourPickerCtrl, getColour, 0}}, + {2262, {wxColourPickerCtrl, setColour_1_1, 1}}, + {2263, {wxColourPickerCtrl, setColour_1_0, 1}}, + {2264, {wxColourPickerCtrl, 'Destroy', undefined}}, + {2265, {wxDatePickerCtrl, new_0, 0}}, + {2266, {wxDatePickerCtrl, new_3, 3}}, + {2267, {wxDatePickerCtrl, getRange, 2}}, + {2268, {wxDatePickerCtrl, getValue, 0}}, + {2269, {wxDatePickerCtrl, setRange, 2}}, + {2270, {wxDatePickerCtrl, setValue, 1}}, + {2271, {wxDatePickerCtrl, 'Destroy', undefined}}, + {2272, {wxFontPickerCtrl, new_0, 0}}, + {2273, {wxFontPickerCtrl, new_3, 3}}, + {2274, {wxFontPickerCtrl, create, 3}}, + {2275, {wxFontPickerCtrl, getSelectedFont, 0}}, + {2276, {wxFontPickerCtrl, setSelectedFont, 1}}, + {2277, {wxFontPickerCtrl, getMaxPointSize, 0}}, + {2278, {wxFontPickerCtrl, setMaxPointSize, 1}}, + {2279, {wxFontPickerCtrl, 'Destroy', undefined}}, + {2282, {wxFindReplaceDialog, new_0, 0}}, + {2283, {wxFindReplaceDialog, new_4, 4}}, + {2284, {wxFindReplaceDialog, destruct, 0}}, + {2285, {wxFindReplaceDialog, create, 4}}, + {2286, {wxFindReplaceDialog, getData, 0}}, + {2287, {wxFindReplaceData, new_0, 0}}, + {2288, {wxFindReplaceData, new_1, 1}}, + {2289, {wxFindReplaceData, getFindString, 0}}, + {2290, {wxFindReplaceData, getReplaceString, 0}}, + {2291, {wxFindReplaceData, getFlags, 0}}, + {2292, {wxFindReplaceData, setFlags, 1}}, + {2293, {wxFindReplaceData, setFindString, 1}}, + {2294, {wxFindReplaceData, setReplaceString, 1}}, + {2295, {wxFindReplaceData, 'Destroy', undefined}}, + {2296, {wxMultiChoiceDialog, new_0, 0}}, + {2298, {wxMultiChoiceDialog, new_5, 5}}, + {2299, {wxMultiChoiceDialog, getSelections, 0}}, + {2300, {wxMultiChoiceDialog, setSelections, 1}}, + {2301, {wxMultiChoiceDialog, 'Destroy', undefined}}, + {2302, {wxSingleChoiceDialog, new_0, 0}}, + {2304, {wxSingleChoiceDialog, new_5, 5}}, + {2305, {wxSingleChoiceDialog, getSelection, 0}}, + {2306, {wxSingleChoiceDialog, getStringSelection, 0}}, + {2307, {wxSingleChoiceDialog, setSelection, 1}}, + {2308, {wxSingleChoiceDialog, 'Destroy', undefined}}, + {2309, {wxTextEntryDialog, new, 3}}, + {2310, {wxTextEntryDialog, getValue, 0}}, + {2311, {wxTextEntryDialog, setValue, 1}}, + {2312, {wxTextEntryDialog, 'Destroy', undefined}}, + {2313, {wxPasswordEntryDialog, new, 3}}, + {2314, {wxPasswordEntryDialog, 'Destroy', undefined}}, + {2315, {wxFontData, new_0, 0}}, + {2316, {wxFontData, new_1, 1}}, + {2317, {wxFontData, destruct, 0}}, + {2318, {wxFontData, enableEffects, 1}}, + {2319, {wxFontData, getAllowSymbols, 0}}, + {2320, {wxFontData, getColour, 0}}, + {2321, {wxFontData, getChosenFont, 0}}, + {2322, {wxFontData, getEnableEffects, 0}}, + {2323, {wxFontData, getInitialFont, 0}}, + {2324, {wxFontData, getShowHelp, 0}}, + {2325, {wxFontData, setAllowSymbols, 1}}, + {2326, {wxFontData, setChosenFont, 1}}, + {2327, {wxFontData, setColour, 1}}, + {2328, {wxFontData, setInitialFont, 1}}, + {2329, {wxFontData, setRange, 2}}, + {2330, {wxFontData, setShowHelp, 1}}, + {2334, {wxFontDialog, new_0, 0}}, + {2336, {wxFontDialog, new_2, 2}}, + {2338, {wxFontDialog, create, 2}}, + {2339, {wxFontDialog, getFontData, 0}}, + {2341, {wxFontDialog, 'Destroy', undefined}}, + {2342, {wxProgressDialog, new, 3}}, + {2343, {wxProgressDialog, destruct, 0}}, + {2344, {wxProgressDialog, resume, 0}}, + {2345, {wxProgressDialog, update_2, 2}}, + {2346, {wxProgressDialog, update_0, 0}}, + {2347, {wxMessageDialog, new, 3}}, + {2348, {wxMessageDialog, destruct, 0}}, + {2349, {wxPageSetupDialog, new, 2}}, + {2350, {wxPageSetupDialog, destruct, 0}}, + {2351, {wxPageSetupDialog, getPageSetupData, 0}}, + {2352, {wxPageSetupDialog, showModal, 0}}, + {2353, {wxPageSetupDialogData, new_0, 0}}, + {2354, {wxPageSetupDialogData, new_1_0, 1}}, + {2355, {wxPageSetupDialogData, new_1_1, 1}}, + {2356, {wxPageSetupDialogData, destruct, 0}}, + {2357, {wxPageSetupDialogData, enableHelp, 1}}, + {2358, {wxPageSetupDialogData, enableMargins, 1}}, + {2359, {wxPageSetupDialogData, enableOrientation, 1}}, + {2360, {wxPageSetupDialogData, enablePaper, 1}}, + {2361, {wxPageSetupDialogData, enablePrinter, 1}}, + {2362, {wxPageSetupDialogData, getDefaultMinMargins, 0}}, + {2363, {wxPageSetupDialogData, getEnableMargins, 0}}, + {2364, {wxPageSetupDialogData, getEnableOrientation, 0}}, + {2365, {wxPageSetupDialogData, getEnablePaper, 0}}, + {2366, {wxPageSetupDialogData, getEnablePrinter, 0}}, + {2367, {wxPageSetupDialogData, getEnableHelp, 0}}, + {2368, {wxPageSetupDialogData, getDefaultInfo, 0}}, + {2369, {wxPageSetupDialogData, getMarginTopLeft, 0}}, + {2370, {wxPageSetupDialogData, getMarginBottomRight, 0}}, + {2371, {wxPageSetupDialogData, getMinMarginTopLeft, 0}}, + {2372, {wxPageSetupDialogData, getMinMarginBottomRight, 0}}, + {2373, {wxPageSetupDialogData, getPaperId, 0}}, + {2374, {wxPageSetupDialogData, getPaperSize, 0}}, + {2376, {wxPageSetupDialogData, getPrintData, 0}}, + {2377, {wxPageSetupDialogData, isOk, 0}}, + {2378, {wxPageSetupDialogData, setDefaultInfo, 1}}, + {2379, {wxPageSetupDialogData, setDefaultMinMargins, 1}}, + {2380, {wxPageSetupDialogData, setMarginTopLeft, 1}}, + {2381, {wxPageSetupDialogData, setMarginBottomRight, 1}}, + {2382, {wxPageSetupDialogData, setMinMarginTopLeft, 1}}, + {2383, {wxPageSetupDialogData, setMinMarginBottomRight, 1}}, + {2384, {wxPageSetupDialogData, setPaperId, 1}}, + {2385, {wxPageSetupDialogData, setPaperSize_1_1, 1}}, + {2386, {wxPageSetupDialogData, setPaperSize_1_0, 1}}, + {2387, {wxPageSetupDialogData, setPrintData, 1}}, + {2388, {wxPrintDialog, new_2_0, 2}}, + {2389, {wxPrintDialog, new_2_1, 2}}, + {2390, {wxPrintDialog, destruct, 0}}, + {2391, {wxPrintDialog, getPrintDialogData, 0}}, + {2392, {wxPrintDialog, getPrintDC, 0}}, + {2393, {wxPrintDialogData, new_0, 0}}, + {2394, {wxPrintDialogData, new_1_1, 1}}, + {2395, {wxPrintDialogData, new_1_0, 1}}, + {2396, {wxPrintDialogData, destruct, 0}}, + {2397, {wxPrintDialogData, enableHelp, 1}}, + {2398, {wxPrintDialogData, enablePageNumbers, 1}}, + {2399, {wxPrintDialogData, enablePrintToFile, 1}}, + {2400, {wxPrintDialogData, enableSelection, 1}}, + {2401, {wxPrintDialogData, getAllPages, 0}}, + {2402, {wxPrintDialogData, getCollate, 0}}, + {2403, {wxPrintDialogData, getFromPage, 0}}, + {2404, {wxPrintDialogData, getMaxPage, 0}}, + {2405, {wxPrintDialogData, getMinPage, 0}}, + {2406, {wxPrintDialogData, getNoCopies, 0}}, + {2407, {wxPrintDialogData, getPrintData, 0}}, + {2408, {wxPrintDialogData, getPrintToFile, 0}}, + {2409, {wxPrintDialogData, getSelection, 0}}, + {2410, {wxPrintDialogData, getToPage, 0}}, + {2411, {wxPrintDialogData, isOk, 0}}, + {2412, {wxPrintDialogData, setCollate, 1}}, + {2413, {wxPrintDialogData, setFromPage, 1}}, + {2414, {wxPrintDialogData, setMaxPage, 1}}, + {2415, {wxPrintDialogData, setMinPage, 1}}, + {2416, {wxPrintDialogData, setNoCopies, 1}}, + {2417, {wxPrintDialogData, setPrintData, 1}}, + {2418, {wxPrintDialogData, setPrintToFile, 1}}, + {2419, {wxPrintDialogData, setSelection, 1}}, + {2420, {wxPrintDialogData, setToPage, 1}}, + {2421, {wxPrintData, new_0, 0}}, + {2422, {wxPrintData, new_1, 1}}, + {2423, {wxPrintData, destruct, 0}}, + {2424, {wxPrintData, getCollate, 0}}, + {2425, {wxPrintData, getBin, 0}}, + {2426, {wxPrintData, getColour, 0}}, + {2427, {wxPrintData, getDuplex, 0}}, + {2428, {wxPrintData, getNoCopies, 0}}, + {2429, {wxPrintData, getOrientation, 0}}, + {2430, {wxPrintData, getPaperId, 0}}, + {2431, {wxPrintData, getPrinterName, 0}}, + {2432, {wxPrintData, getQuality, 0}}, + {2433, {wxPrintData, isOk, 0}}, + {2434, {wxPrintData, setBin, 1}}, + {2435, {wxPrintData, setCollate, 1}}, + {2436, {wxPrintData, setColour, 1}}, + {2437, {wxPrintData, setDuplex, 1}}, + {2438, {wxPrintData, setNoCopies, 1}}, + {2439, {wxPrintData, setOrientation, 1}}, + {2440, {wxPrintData, setPaperId, 1}}, + {2441, {wxPrintData, setPrinterName, 1}}, + {2442, {wxPrintData, setQuality, 1}}, + {2445, {wxPrintPreview, new_2, 2}}, + {2446, {wxPrintPreview, new_3, 3}}, + {2448, {wxPrintPreview, destruct, 0}}, + {2449, {wxPrintPreview, getCanvas, 0}}, + {2450, {wxPrintPreview, getCurrentPage, 0}}, + {2451, {wxPrintPreview, getFrame, 0}}, + {2452, {wxPrintPreview, getMaxPage, 0}}, + {2453, {wxPrintPreview, getMinPage, 0}}, + {2454, {wxPrintPreview, getPrintout, 0}}, + {2455, {wxPrintPreview, getPrintoutForPrinting, 0}}, + {2456, {wxPrintPreview, isOk, 0}}, + {2457, {wxPrintPreview, paintPage, 2}}, + {2458, {wxPrintPreview, print, 1}}, + {2459, {wxPrintPreview, renderPage, 1}}, + {2460, {wxPrintPreview, setCanvas, 1}}, + {2461, {wxPrintPreview, setCurrentPage, 1}}, + {2462, {wxPrintPreview, setFrame, 1}}, + {2463, {wxPrintPreview, setPrintout, 1}}, + {2464, {wxPrintPreview, setZoom, 1}}, + {2465, {wxPreviewFrame, new, 3}}, + {2466, {wxPreviewFrame, destruct, 0}}, + {2467, {wxPreviewFrame, createControlBar, 0}}, + {2468, {wxPreviewFrame, createCanvas, 0}}, + {2469, {wxPreviewFrame, initialize, 0}}, + {2470, {wxPreviewFrame, onCloseWindow, 1}}, + {2471, {wxPreviewControlBar, new, 4}}, + {2472, {wxPreviewControlBar, destruct, 0}}, + {2473, {wxPreviewControlBar, createButtons, 0}}, + {2474, {wxPreviewControlBar, getPrintPreview, 0}}, + {2475, {wxPreviewControlBar, getZoomControl, 0}}, + {2476, {wxPreviewControlBar, setZoomControl, 1}}, + {2478, {wxPrinter, new, 1}}, + {2479, {wxPrinter, createAbortWindow, 2}}, + {2480, {wxPrinter, getAbort, 0}}, + {2481, {wxPrinter, getLastError, 0}}, + {2482, {wxPrinter, getPrintDialogData, 0}}, + {2483, {wxPrinter, print, 3}}, + {2484, {wxPrinter, printDialog, 1}}, + {2485, {wxPrinter, reportError, 3}}, + {2486, {wxPrinter, setup, 1}}, + {2487, {wxPrinter, 'Destroy', undefined}}, + {2488, {wxXmlResource, new_1, 1}}, + {2489, {wxXmlResource, new_2, 2}}, + {2490, {wxXmlResource, destruct, 0}}, + {2491, {wxXmlResource, attachUnknownControl, 3}}, + {2492, {wxXmlResource, clearHandlers, 0}}, + {2493, {wxXmlResource, compareVersion, 4}}, + {2494, {wxXmlResource, get, 0}}, + {2495, {wxXmlResource, getFlags, 0}}, + {2496, {wxXmlResource, getVersion, 0}}, + {2497, {wxXmlResource, getXRCID, 2}}, + {2498, {wxXmlResource, initAllHandlers, 0}}, + {2499, {wxXmlResource, load, 1}}, + {2500, {wxXmlResource, loadBitmap, 1}}, + {2501, {wxXmlResource, loadDialog_2, 2}}, + {2502, {wxXmlResource, loadDialog_3, 3}}, + {2503, {wxXmlResource, loadFrame_2, 2}}, + {2504, {wxXmlResource, loadFrame_3, 3}}, + {2505, {wxXmlResource, loadIcon, 1}}, + {2506, {wxXmlResource, loadMenu, 1}}, + {2507, {wxXmlResource, loadMenuBar_2, 2}}, + {2508, {wxXmlResource, loadMenuBar_1, 1}}, + {2509, {wxXmlResource, loadPanel_2, 2}}, + {2510, {wxXmlResource, loadPanel_3, 3}}, + {2511, {wxXmlResource, loadToolBar, 2}}, + {2512, {wxXmlResource, set, 1}}, + {2513, {wxXmlResource, setFlags, 1}}, + {2514, {wxXmlResource, unload, 1}}, + {2515, {wxXmlResource, xrcctrl, 3}}, + {2516, {wxHtmlEasyPrinting, new, 1}}, + {2517, {wxHtmlEasyPrinting, destruct, 0}}, + {2518, {wxHtmlEasyPrinting, getPrintData, 0}}, + {2519, {wxHtmlEasyPrinting, getPageSetupData, 0}}, + {2520, {wxHtmlEasyPrinting, previewFile, 1}}, + {2521, {wxHtmlEasyPrinting, previewText, 2}}, + {2522, {wxHtmlEasyPrinting, printFile, 1}}, + {2523, {wxHtmlEasyPrinting, printText, 2}}, + {2524, {wxHtmlEasyPrinting, pageSetup, 0}}, + {2525, {wxHtmlEasyPrinting, setFonts, 3}}, + {2526, {wxHtmlEasyPrinting, setHeader, 2}}, + {2527, {wxHtmlEasyPrinting, setFooter, 2}}, + {2529, {wxGLCanvas, new_2, 2}}, + {2530, {wxGLCanvas, new_3_1, 3}}, + {2531, {wxGLCanvas, new_3_0, 3}}, + {2532, {wxGLCanvas, getContext, 0}}, + {2534, {wxGLCanvas, setCurrent, 0}}, + {2535, {wxGLCanvas, swapBuffers, 0}}, + {2536, {wxGLCanvas, 'Destroy', undefined}}, + {2537, {wxAuiManager, new, 1}}, + {2538, {wxAuiManager, destruct, 0}}, + {2539, {wxAuiManager, addPane_2_1, 2}}, + {2540, {wxAuiManager, addPane_3, 3}}, + {2541, {wxAuiManager, addPane_2_0, 2}}, + {2542, {wxAuiManager, detachPane, 1}}, + {2543, {wxAuiManager, getAllPanes, 0}}, + {2544, {wxAuiManager, getArtProvider, 0}}, + {2545, {wxAuiManager, getDockSizeConstraint, 2}}, + {2546, {wxAuiManager, getFlags, 0}}, + {2547, {wxAuiManager, getManagedWindow, 0}}, + {2548, {wxAuiManager, getManager, 1}}, + {2549, {wxAuiManager, getPane_1_1, 1}}, + {2550, {wxAuiManager, getPane_1_0, 1}}, + {2551, {wxAuiManager, hideHint, 0}}, + {2552, {wxAuiManager, insertPane, 3}}, + {2553, {wxAuiManager, loadPaneInfo, 2}}, + {2554, {wxAuiManager, loadPerspective, 2}}, + {2555, {wxAuiManager, savePaneInfo, 1}}, + {2556, {wxAuiManager, savePerspective, 0}}, + {2557, {wxAuiManager, setArtProvider, 1}}, + {2558, {wxAuiManager, setDockSizeConstraint, 2}}, + {2559, {wxAuiManager, setFlags, 1}}, + {2560, {wxAuiManager, setManagedWindow, 1}}, + {2561, {wxAuiManager, showHint, 1}}, + {2562, {wxAuiManager, unInit, 0}}, + {2563, {wxAuiManager, update, 0}}, + {2564, {wxAuiPaneInfo, new_0, 0}}, + {2565, {wxAuiPaneInfo, new_1, 1}}, + {2566, {wxAuiPaneInfo, destruct, 0}}, + {2567, {wxAuiPaneInfo, bestSize_1, 1}}, + {2568, {wxAuiPaneInfo, bestSize_2, 2}}, + {2569, {wxAuiPaneInfo, bottom, 0}}, + {2570, {wxAuiPaneInfo, bottomDockable, 1}}, + {2571, {wxAuiPaneInfo, caption, 1}}, + {2572, {wxAuiPaneInfo, captionVisible, 1}}, + {2573, {wxAuiPaneInfo, centre, 0}}, + {2574, {wxAuiPaneInfo, centrePane, 0}}, + {2575, {wxAuiPaneInfo, closeButton, 1}}, + {2576, {wxAuiPaneInfo, defaultPane, 0}}, + {2577, {wxAuiPaneInfo, destroyOnClose, 1}}, + {2578, {wxAuiPaneInfo, direction, 1}}, + {2579, {wxAuiPaneInfo, dock, 0}}, + {2580, {wxAuiPaneInfo, dockable, 1}}, + {2581, {wxAuiPaneInfo, fixed, 0}}, + {2582, {wxAuiPaneInfo, float, 0}}, + {2583, {wxAuiPaneInfo, floatable, 1}}, + {2584, {wxAuiPaneInfo, floatingPosition_1, 1}}, + {2585, {wxAuiPaneInfo, floatingPosition_2, 2}}, + {2586, {wxAuiPaneInfo, floatingSize_1, 1}}, + {2587, {wxAuiPaneInfo, floatingSize_2, 2}}, + {2588, {wxAuiPaneInfo, gripper, 1}}, + {2589, {wxAuiPaneInfo, gripperTop, 1}}, + {2590, {wxAuiPaneInfo, hasBorder, 0}}, + {2591, {wxAuiPaneInfo, hasCaption, 0}}, + {2592, {wxAuiPaneInfo, hasCloseButton, 0}}, + {2593, {wxAuiPaneInfo, hasFlag, 1}}, + {2594, {wxAuiPaneInfo, hasGripper, 0}}, + {2595, {wxAuiPaneInfo, hasGripperTop, 0}}, + {2596, {wxAuiPaneInfo, hasMaximizeButton, 0}}, + {2597, {wxAuiPaneInfo, hasMinimizeButton, 0}}, + {2598, {wxAuiPaneInfo, hasPinButton, 0}}, + {2599, {wxAuiPaneInfo, hide, 0}}, + {2600, {wxAuiPaneInfo, isBottomDockable, 0}}, + {2601, {wxAuiPaneInfo, isDocked, 0}}, + {2602, {wxAuiPaneInfo, isFixed, 0}}, + {2603, {wxAuiPaneInfo, isFloatable, 0}}, + {2604, {wxAuiPaneInfo, isFloating, 0}}, + {2605, {wxAuiPaneInfo, isLeftDockable, 0}}, + {2606, {wxAuiPaneInfo, isMovable, 0}}, + {2607, {wxAuiPaneInfo, isOk, 0}}, + {2608, {wxAuiPaneInfo, isResizable, 0}}, + {2609, {wxAuiPaneInfo, isRightDockable, 0}}, + {2610, {wxAuiPaneInfo, isShown, 0}}, + {2611, {wxAuiPaneInfo, isToolbar, 0}}, + {2612, {wxAuiPaneInfo, isTopDockable, 0}}, + {2613, {wxAuiPaneInfo, layer, 1}}, + {2614, {wxAuiPaneInfo, left, 0}}, + {2615, {wxAuiPaneInfo, leftDockable, 1}}, + {2616, {wxAuiPaneInfo, maxSize_1, 1}}, + {2617, {wxAuiPaneInfo, maxSize_2, 2}}, + {2618, {wxAuiPaneInfo, maximizeButton, 1}}, + {2619, {wxAuiPaneInfo, minSize_1, 1}}, + {2620, {wxAuiPaneInfo, minSize_2, 2}}, + {2621, {wxAuiPaneInfo, minimizeButton, 1}}, + {2622, {wxAuiPaneInfo, movable, 1}}, + {2623, {wxAuiPaneInfo, name, 1}}, + {2624, {wxAuiPaneInfo, paneBorder, 1}}, + {2625, {wxAuiPaneInfo, pinButton, 1}}, + {2626, {wxAuiPaneInfo, position, 1}}, + {2627, {wxAuiPaneInfo, resizable, 1}}, + {2628, {wxAuiPaneInfo, right, 0}}, + {2629, {wxAuiPaneInfo, rightDockable, 1}}, + {2630, {wxAuiPaneInfo, row, 1}}, + {2631, {wxAuiPaneInfo, safeSet, 1}}, + {2632, {wxAuiPaneInfo, setFlag, 2}}, + {2633, {wxAuiPaneInfo, show, 1}}, + {2634, {wxAuiPaneInfo, toolbarPane, 0}}, + {2635, {wxAuiPaneInfo, top, 0}}, + {2636, {wxAuiPaneInfo, topDockable, 1}}, + {2637, {wxAuiPaneInfo, window, 1}}, + {2638, {wxAuiNotebook, new_0, 0}}, + {2639, {wxAuiNotebook, new_2, 2}}, + {2640, {wxAuiNotebook, addPage, 3}}, + {2641, {wxAuiNotebook, create, 2}}, + {2642, {wxAuiNotebook, deletePage, 1}}, + {2643, {wxAuiNotebook, getArtProvider, 0}}, + {2644, {wxAuiNotebook, getPage, 1}}, + {2645, {wxAuiNotebook, getPageBitmap, 1}}, + {2646, {wxAuiNotebook, getPageCount, 0}}, + {2647, {wxAuiNotebook, getPageIndex, 1}}, + {2648, {wxAuiNotebook, getPageText, 1}}, + {2649, {wxAuiNotebook, getSelection, 0}}, + {2650, {wxAuiNotebook, insertPage, 4}}, + {2651, {wxAuiNotebook, removePage, 1}}, + {2652, {wxAuiNotebook, setArtProvider, 1}}, + {2653, {wxAuiNotebook, setFont, 1}}, + {2654, {wxAuiNotebook, setPageBitmap, 2}}, + {2655, {wxAuiNotebook, setPageText, 2}}, + {2656, {wxAuiNotebook, setSelection, 1}}, + {2657, {wxAuiNotebook, setTabCtrlHeight, 1}}, + {2658, {wxAuiNotebook, setUniformBitmapSize, 1}}, + {2659, {wxAuiNotebook, 'Destroy', undefined}}, + {2660, {wxMDIParentFrame, new_0, 0}}, + {2661, {wxMDIParentFrame, new_4, 4}}, + {2662, {wxMDIParentFrame, destruct, 0}}, + {2663, {wxMDIParentFrame, activateNext, 0}}, + {2664, {wxMDIParentFrame, activatePrevious, 0}}, + {2665, {wxMDIParentFrame, arrangeIcons, 0}}, + {2666, {wxMDIParentFrame, cascade, 0}}, + {2667, {wxMDIParentFrame, create, 4}}, + {2668, {wxMDIParentFrame, getActiveChild, 0}}, + {2669, {wxMDIParentFrame, getClientWindow, 0}}, + {2670, {wxMDIParentFrame, tile, 1}}, + {2671, {wxMDIChildFrame, new_0, 0}}, + {2672, {wxMDIChildFrame, new_4, 4}}, + {2673, {wxMDIChildFrame, destruct, 0}}, + {2674, {wxMDIChildFrame, activate, 0}}, + {2675, {wxMDIChildFrame, create, 4}}, + {2676, {wxMDIChildFrame, maximize, 1}}, + {2677, {wxMDIChildFrame, restore, 0}}, + {2678, {wxMDIClientWindow, new_0, 0}}, + {2679, {wxMDIClientWindow, new_2, 2}}, + {2680, {wxMDIClientWindow, destruct, 0}}, + {2681, {wxMDIClientWindow, createClient, 2}}, + {2682, {wxLayoutAlgorithm, new, 0}}, + {2683, {wxLayoutAlgorithm, layoutFrame, 2}}, + {2684, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, + {2685, {wxLayoutAlgorithm, layoutWindow, 2}}, + {2686, {wxLayoutAlgorithm, 'Destroy', undefined}}, + {2687, {wxEvent, getId, 0}}, + {2688, {wxEvent, getSkipped, 0}}, + {2689, {wxEvent, getTimestamp, 0}}, + {2690, {wxEvent, isCommandEvent, 0}}, + {2691, {wxEvent, resumePropagation, 1}}, + {2692, {wxEvent, shouldPropagate, 0}}, + {2693, {wxEvent, skip, 1}}, + {2694, {wxEvent, stopPropagation, 0}}, + {2695, {wxCommandEvent, getClientData, 0}}, + {2696, {wxCommandEvent, getExtraLong, 0}}, + {2697, {wxCommandEvent, getInt, 0}}, + {2698, {wxCommandEvent, getSelection, 0}}, + {2699, {wxCommandEvent, getString, 0}}, + {2700, {wxCommandEvent, isChecked, 0}}, + {2701, {wxCommandEvent, isSelection, 0}}, + {2702, {wxCommandEvent, setInt, 1}}, + {2703, {wxCommandEvent, setString, 1}}, + {2704, {wxScrollEvent, getOrientation, 0}}, + {2705, {wxScrollEvent, getPosition, 0}}, + {2706, {wxScrollWinEvent, getOrientation, 0}}, + {2707, {wxScrollWinEvent, getPosition, 0}}, + {2708, {wxMouseEvent, altDown, 0}}, + {2709, {wxMouseEvent, button, 1}}, + {2710, {wxMouseEvent, buttonDClick, 1}}, + {2711, {wxMouseEvent, buttonDown, 1}}, + {2712, {wxMouseEvent, buttonUp, 1}}, + {2713, {wxMouseEvent, cmdDown, 0}}, + {2714, {wxMouseEvent, controlDown, 0}}, + {2715, {wxMouseEvent, dragging, 0}}, + {2716, {wxMouseEvent, entering, 0}}, + {2717, {wxMouseEvent, getButton, 0}}, + {2720, {wxMouseEvent, getPosition, 0}}, + {2721, {wxMouseEvent, getLogicalPosition, 1}}, + {2722, {wxMouseEvent, getLinesPerAction, 0}}, + {2723, {wxMouseEvent, getWheelRotation, 0}}, + {2724, {wxMouseEvent, getWheelDelta, 0}}, + {2725, {wxMouseEvent, getX, 0}}, + {2726, {wxMouseEvent, getY, 0}}, + {2727, {wxMouseEvent, isButton, 0}}, + {2728, {wxMouseEvent, isPageScroll, 0}}, + {2729, {wxMouseEvent, leaving, 0}}, + {2730, {wxMouseEvent, leftDClick, 0}}, + {2731, {wxMouseEvent, leftDown, 0}}, + {2732, {wxMouseEvent, leftIsDown, 0}}, + {2733, {wxMouseEvent, leftUp, 0}}, + {2734, {wxMouseEvent, metaDown, 0}}, + {2735, {wxMouseEvent, middleDClick, 0}}, + {2736, {wxMouseEvent, middleDown, 0}}, + {2737, {wxMouseEvent, middleIsDown, 0}}, + {2738, {wxMouseEvent, middleUp, 0}}, + {2739, {wxMouseEvent, moving, 0}}, + {2740, {wxMouseEvent, rightDClick, 0}}, + {2741, {wxMouseEvent, rightDown, 0}}, + {2742, {wxMouseEvent, rightIsDown, 0}}, + {2743, {wxMouseEvent, rightUp, 0}}, + {2744, {wxMouseEvent, shiftDown, 0}}, + {2745, {wxSetCursorEvent, getCursor, 0}}, + {2746, {wxSetCursorEvent, getX, 0}}, + {2747, {wxSetCursorEvent, getY, 0}}, + {2748, {wxSetCursorEvent, hasCursor, 0}}, + {2749, {wxSetCursorEvent, setCursor, 1}}, + {2750, {wxKeyEvent, altDown, 0}}, + {2751, {wxKeyEvent, cmdDown, 0}}, + {2752, {wxKeyEvent, controlDown, 0}}, + {2753, {wxKeyEvent, getKeyCode, 0}}, + {2754, {wxKeyEvent, getModifiers, 0}}, + {2757, {wxKeyEvent, getPosition, 0}}, + {2758, {wxKeyEvent, getRawKeyCode, 0}}, + {2759, {wxKeyEvent, getRawKeyFlags, 0}}, + {2760, {wxKeyEvent, getUnicodeKey, 0}}, + {2761, {wxKeyEvent, getX, 0}}, + {2762, {wxKeyEvent, getY, 0}}, + {2763, {wxKeyEvent, hasModifiers, 0}}, + {2764, {wxKeyEvent, metaDown, 0}}, + {2765, {wxKeyEvent, shiftDown, 0}}, + {2766, {wxSizeEvent, getSize, 0}}, + {2767, {wxMoveEvent, getPosition, 0}}, + {2768, {wxEraseEvent, getDC, 0}}, + {2769, {wxFocusEvent, getWindow, 0}}, + {2770, {wxChildFocusEvent, getWindow, 0}}, + {2771, {wxMenuEvent, getMenu, 0}}, + {2772, {wxMenuEvent, getMenuId, 0}}, + {2773, {wxMenuEvent, isPopup, 0}}, + {2774, {wxCloseEvent, canVeto, 0}}, + {2775, {wxCloseEvent, getLoggingOff, 0}}, + {2776, {wxCloseEvent, setCanVeto, 1}}, + {2777, {wxCloseEvent, setLoggingOff, 1}}, + {2778, {wxCloseEvent, veto, 1}}, + {2779, {wxShowEvent, setShow, 1}}, + {2780, {wxShowEvent, getShow, 0}}, + {2781, {wxIconizeEvent, iconized, 0}}, + {2782, {wxJoystickEvent, buttonDown, 1}}, + {2783, {wxJoystickEvent, buttonIsDown, 1}}, + {2784, {wxJoystickEvent, buttonUp, 1}}, + {2785, {wxJoystickEvent, getButtonChange, 0}}, + {2786, {wxJoystickEvent, getButtonState, 0}}, + {2787, {wxJoystickEvent, getJoystick, 0}}, + {2788, {wxJoystickEvent, getPosition, 0}}, + {2789, {wxJoystickEvent, getZPosition, 0}}, + {2790, {wxJoystickEvent, isButton, 0}}, + {2791, {wxJoystickEvent, isMove, 0}}, + {2792, {wxJoystickEvent, isZMove, 0}}, + {2793, {wxUpdateUIEvent, canUpdate, 1}}, + {2794, {wxUpdateUIEvent, check, 1}}, + {2795, {wxUpdateUIEvent, enable, 1}}, + {2796, {wxUpdateUIEvent, show, 1}}, + {2797, {wxUpdateUIEvent, getChecked, 0}}, + {2798, {wxUpdateUIEvent, getEnabled, 0}}, + {2799, {wxUpdateUIEvent, getShown, 0}}, + {2800, {wxUpdateUIEvent, getSetChecked, 0}}, + {2801, {wxUpdateUIEvent, getSetEnabled, 0}}, + {2802, {wxUpdateUIEvent, getSetShown, 0}}, + {2803, {wxUpdateUIEvent, getSetText, 0}}, + {2804, {wxUpdateUIEvent, getText, 0}}, + {2805, {wxUpdateUIEvent, getMode, 0}}, + {2806, {wxUpdateUIEvent, getUpdateInterval, 0}}, + {2807, {wxUpdateUIEvent, resetUpdateTime, 0}}, + {2808, {wxUpdateUIEvent, setMode, 1}}, + {2809, {wxUpdateUIEvent, setText, 1}}, + {2810, {wxUpdateUIEvent, setUpdateInterval, 1}}, + {2811, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, + {2812, {wxPaletteChangedEvent, setChangedWindow, 1}}, + {2813, {wxPaletteChangedEvent, getChangedWindow, 0}}, + {2814, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, + {2815, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, + {2816, {wxNavigationKeyEvent, getDirection, 0}}, + {2817, {wxNavigationKeyEvent, setDirection, 1}}, + {2818, {wxNavigationKeyEvent, isWindowChange, 0}}, + {2819, {wxNavigationKeyEvent, setWindowChange, 1}}, + {2820, {wxNavigationKeyEvent, isFromTab, 0}}, + {2821, {wxNavigationKeyEvent, setFromTab, 1}}, + {2822, {wxNavigationKeyEvent, getCurrentFocus, 0}}, + {2823, {wxNavigationKeyEvent, setCurrentFocus, 1}}, + {2824, {wxHelpEvent, getOrigin, 0}}, + {2825, {wxHelpEvent, getPosition, 0}}, + {2826, {wxHelpEvent, setOrigin, 1}}, + {2827, {wxHelpEvent, setPosition, 1}}, + {2828, {wxContextMenuEvent, getPosition, 0}}, + {2829, {wxContextMenuEvent, setPosition, 1}}, + {2830, {wxIdleEvent, canSend, 1}}, + {2831, {wxIdleEvent, getMode, 0}}, + {2832, {wxIdleEvent, requestMore, 1}}, + {2833, {wxIdleEvent, moreRequested, 0}}, + {2834, {wxIdleEvent, setMode, 1}}, + {2835, {wxGridEvent, altDown, 0}}, + {2836, {wxGridEvent, controlDown, 0}}, + {2837, {wxGridEvent, getCol, 0}}, + {2838, {wxGridEvent, getPosition, 0}}, + {2839, {wxGridEvent, getRow, 0}}, + {2840, {wxGridEvent, metaDown, 0}}, + {2841, {wxGridEvent, selecting, 0}}, + {2842, {wxGridEvent, shiftDown, 0}}, + {2843, {wxNotifyEvent, allow, 0}}, + {2844, {wxNotifyEvent, isAllowed, 0}}, + {2845, {wxNotifyEvent, veto, 0}}, + {2846, {wxSashEvent, getEdge, 0}}, + {2847, {wxSashEvent, getDragRect, 0}}, + {2848, {wxSashEvent, getDragStatus, 0}}, + {2849, {wxListEvent, getCacheFrom, 0}}, + {2850, {wxListEvent, getCacheTo, 0}}, + {2851, {wxListEvent, getKeyCode, 0}}, + {2852, {wxListEvent, getIndex, 0}}, + {2853, {wxListEvent, getColumn, 0}}, + {2854, {wxListEvent, getPoint, 0}}, + {2855, {wxListEvent, getLabel, 0}}, + {2856, {wxListEvent, getText, 0}}, + {2857, {wxListEvent, getImage, 0}}, + {2858, {wxListEvent, getData, 0}}, + {2859, {wxListEvent, getMask, 0}}, + {2860, {wxListEvent, getItem, 0}}, + {2861, {wxListEvent, isEditCancelled, 0}}, + {2862, {wxDateEvent, getDate, 0}}, + {2863, {wxCalendarEvent, getWeekDay, 0}}, + {2864, {wxFileDirPickerEvent, getPath, 0}}, + {2865, {wxColourPickerEvent, getColour, 0}}, + {2866, {wxFontPickerEvent, getFont, 0}}, + {2867, {wxStyledTextEvent, getPosition, 0}}, + {2868, {wxStyledTextEvent, getKey, 0}}, + {2869, {wxStyledTextEvent, getModifiers, 0}}, + {2870, {wxStyledTextEvent, getModificationType, 0}}, + {2871, {wxStyledTextEvent, getText, 0}}, + {2872, {wxStyledTextEvent, getLength, 0}}, + {2873, {wxStyledTextEvent, getLinesAdded, 0}}, + {2874, {wxStyledTextEvent, getLine, 0}}, + {2875, {wxStyledTextEvent, getFoldLevelNow, 0}}, + {2876, {wxStyledTextEvent, getFoldLevelPrev, 0}}, + {2877, {wxStyledTextEvent, getMargin, 0}}, + {2878, {wxStyledTextEvent, getMessage, 0}}, + {2879, {wxStyledTextEvent, getWParam, 0}}, + {2880, {wxStyledTextEvent, getLParam, 0}}, + {2881, {wxStyledTextEvent, getListType, 0}}, + {2882, {wxStyledTextEvent, getX, 0}}, + {2883, {wxStyledTextEvent, getY, 0}}, + {2884, {wxStyledTextEvent, getDragText, 0}}, + {2885, {wxStyledTextEvent, getDragAllowMove, 0}}, + {2886, {wxStyledTextEvent, getDragResult, 0}}, + {2887, {wxStyledTextEvent, getShift, 0}}, + {2888, {wxStyledTextEvent, getControl, 0}}, + {2889, {wxStyledTextEvent, getAlt, 0}}, + {2890, {utils, getKeyState, 1}}, + {2891, {utils, getMousePosition, 2}}, + {2892, {utils, getMouseState, 0}}, + {2893, {utils, setDetectableAutoRepeat, 1}}, + {2894, {utils, bell, 0}}, + {2895, {utils, findMenuItemId, 3}}, + {2896, {utils, genericFindWindowAtPoint, 1}}, + {2897, {utils, findWindowAtPoint, 1}}, + {2898, {utils, beginBusyCursor, 1}}, + {2899, {utils, endBusyCursor, 0}}, + {2900, {utils, isBusy, 0}}, + {2901, {utils, shutdown, 1}}, + {2902, {utils, shell, 1}}, + {2903, {utils, launchDefaultBrowser, 2}}, + {2904, {utils, getEmailAddress, 0}}, + {2905, {utils, getUserId, 0}}, + {2906, {utils, getHomeDir, 0}}, + {2907, {utils, newId, 0}}, + {2908, {utils, registerId, 1}}, + {2909, {utils, getCurrentId, 0}}, + {2910, {utils, getOsDescription, 0}}, + {2911, {utils, isPlatformLittleEndian, 0}}, + {2912, {utils, isPlatform64Bit, 0}}, + {2913, {wxPrintout, new, 1}}, + {2914, {wxPrintout, destruct, 0}}, + {2915, {wxPrintout, getDC, 0}}, + {2916, {wxPrintout, getPageSizeMM, 2}}, + {2917, {wxPrintout, getPageSizePixels, 2}}, + {2918, {wxPrintout, getPaperRectPixels, 0}}, + {2919, {wxPrintout, getPPIPrinter, 2}}, + {2920, {wxPrintout, getPPIScreen, 2}}, + {2921, {wxPrintout, getTitle, 0}}, + {2922, {wxPrintout, isPreview, 0}}, + {2923, {wxPrintout, fitThisSizeToPaper, 1}}, + {2924, {wxPrintout, fitThisSizeToPage, 1}}, + {2925, {wxPrintout, fitThisSizeToPageMargins, 2}}, + {2926, {wxPrintout, mapScreenSizeToPaper, 0}}, + {2927, {wxPrintout, mapScreenSizeToPage, 0}}, + {2928, {wxPrintout, mapScreenSizeToPageMargins, 1}}, + {2929, {wxPrintout, mapScreenSizeToDevice, 0}}, + {2930, {wxPrintout, getLogicalPaperRect, 0}}, + {2931, {wxPrintout, getLogicalPageRect, 0}}, + {2932, {wxPrintout, getLogicalPageMarginsRect, 1}}, + {2933, {wxPrintout, setLogicalOrigin, 2}}, + {2934, {wxPrintout, offsetLogicalOrigin, 2}}, + {2935, {wxStyledTextCtrl, new_2, 2}}, + {2936, {wxStyledTextCtrl, new_0, 0}}, + {2937, {wxStyledTextCtrl, destruct, 0}}, + {2938, {wxStyledTextCtrl, create, 2}}, + {2939, {wxStyledTextCtrl, addText, 1}}, + {2940, {wxStyledTextCtrl, addStyledText, 1}}, + {2941, {wxStyledTextCtrl, insertText, 2}}, + {2942, {wxStyledTextCtrl, clearAll, 0}}, + {2943, {wxStyledTextCtrl, clearDocumentStyle, 0}}, + {2944, {wxStyledTextCtrl, getLength, 0}}, + {2945, {wxStyledTextCtrl, getCharAt, 1}}, + {2946, {wxStyledTextCtrl, getCurrentPos, 0}}, + {2947, {wxStyledTextCtrl, getAnchor, 0}}, + {2948, {wxStyledTextCtrl, getStyleAt, 1}}, + {2949, {wxStyledTextCtrl, redo, 0}}, + {2950, {wxStyledTextCtrl, setUndoCollection, 1}}, + {2951, {wxStyledTextCtrl, selectAll, 0}}, + {2952, {wxStyledTextCtrl, setSavePoint, 0}}, + {2953, {wxStyledTextCtrl, getStyledText, 2}}, + {2954, {wxStyledTextCtrl, canRedo, 0}}, + {2955, {wxStyledTextCtrl, markerLineFromHandle, 1}}, + {2956, {wxStyledTextCtrl, markerDeleteHandle, 1}}, + {2957, {wxStyledTextCtrl, getUndoCollection, 0}}, + {2958, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, + {2959, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, + {2960, {wxStyledTextCtrl, positionFromPoint, 1}}, + {2961, {wxStyledTextCtrl, positionFromPointClose, 2}}, + {2962, {wxStyledTextCtrl, gotoLine, 1}}, + {2963, {wxStyledTextCtrl, gotoPos, 1}}, + {2964, {wxStyledTextCtrl, setAnchor, 1}}, + {2965, {wxStyledTextCtrl, getCurLine, 1}}, + {2966, {wxStyledTextCtrl, getEndStyled, 0}}, + {2967, {wxStyledTextCtrl, convertEOLs, 1}}, + {2968, {wxStyledTextCtrl, getEOLMode, 0}}, + {2969, {wxStyledTextCtrl, setEOLMode, 1}}, + {2970, {wxStyledTextCtrl, startStyling, 2}}, + {2971, {wxStyledTextCtrl, setStyling, 2}}, + {2972, {wxStyledTextCtrl, getBufferedDraw, 0}}, + {2973, {wxStyledTextCtrl, setBufferedDraw, 1}}, + {2974, {wxStyledTextCtrl, setTabWidth, 1}}, + {2975, {wxStyledTextCtrl, getTabWidth, 0}}, + {2976, {wxStyledTextCtrl, setCodePage, 1}}, + {2977, {wxStyledTextCtrl, markerDefine, 3}}, + {2978, {wxStyledTextCtrl, markerSetForeground, 2}}, + {2979, {wxStyledTextCtrl, markerSetBackground, 2}}, + {2980, {wxStyledTextCtrl, markerAdd, 2}}, + {2981, {wxStyledTextCtrl, markerDelete, 2}}, + {2982, {wxStyledTextCtrl, markerDeleteAll, 1}}, + {2983, {wxStyledTextCtrl, markerGet, 1}}, + {2984, {wxStyledTextCtrl, markerNext, 2}}, + {2985, {wxStyledTextCtrl, markerPrevious, 2}}, + {2986, {wxStyledTextCtrl, markerDefineBitmap, 2}}, + {2987, {wxStyledTextCtrl, markerAddSet, 2}}, + {2988, {wxStyledTextCtrl, markerSetAlpha, 2}}, + {2989, {wxStyledTextCtrl, setMarginType, 2}}, + {2990, {wxStyledTextCtrl, getMarginType, 1}}, + {2991, {wxStyledTextCtrl, setMarginWidth, 2}}, + {2992, {wxStyledTextCtrl, getMarginWidth, 1}}, + {2993, {wxStyledTextCtrl, setMarginMask, 2}}, + {2994, {wxStyledTextCtrl, getMarginMask, 1}}, + {2995, {wxStyledTextCtrl, setMarginSensitive, 2}}, + {2996, {wxStyledTextCtrl, getMarginSensitive, 1}}, + {2997, {wxStyledTextCtrl, styleClearAll, 0}}, + {2998, {wxStyledTextCtrl, styleSetForeground, 2}}, + {2999, {wxStyledTextCtrl, styleSetBackground, 2}}, + {3000, {wxStyledTextCtrl, styleSetBold, 2}}, + {3001, {wxStyledTextCtrl, styleSetItalic, 2}}, + {3002, {wxStyledTextCtrl, styleSetSize, 2}}, + {3003, {wxStyledTextCtrl, styleSetFaceName, 2}}, + {3004, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, + {3005, {wxStyledTextCtrl, styleResetDefault, 0}}, + {3006, {wxStyledTextCtrl, styleSetUnderline, 2}}, + {3007, {wxStyledTextCtrl, styleSetCase, 2}}, + {3008, {wxStyledTextCtrl, styleSetHotSpot, 2}}, + {3009, {wxStyledTextCtrl, setSelForeground, 2}}, + {3010, {wxStyledTextCtrl, setSelBackground, 2}}, + {3011, {wxStyledTextCtrl, getSelAlpha, 0}}, + {3012, {wxStyledTextCtrl, setSelAlpha, 1}}, + {3013, {wxStyledTextCtrl, setCaretForeground, 1}}, + {3014, {wxStyledTextCtrl, cmdKeyAssign, 3}}, + {3015, {wxStyledTextCtrl, cmdKeyClear, 2}}, + {3016, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, + {3017, {wxStyledTextCtrl, setStyleBytes, 2}}, + {3018, {wxStyledTextCtrl, styleSetVisible, 2}}, + {3019, {wxStyledTextCtrl, getCaretPeriod, 0}}, + {3020, {wxStyledTextCtrl, setCaretPeriod, 1}}, + {3021, {wxStyledTextCtrl, setWordChars, 1}}, + {3022, {wxStyledTextCtrl, beginUndoAction, 0}}, + {3023, {wxStyledTextCtrl, endUndoAction, 0}}, + {3024, {wxStyledTextCtrl, indicatorSetStyle, 2}}, + {3025, {wxStyledTextCtrl, indicatorGetStyle, 1}}, + {3026, {wxStyledTextCtrl, indicatorSetForeground, 2}}, + {3027, {wxStyledTextCtrl, indicatorGetForeground, 1}}, + {3028, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, + {3029, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, + {3030, {wxStyledTextCtrl, getStyleBits, 0}}, + {3031, {wxStyledTextCtrl, setLineState, 2}}, + {3032, {wxStyledTextCtrl, getLineState, 1}}, + {3033, {wxStyledTextCtrl, getMaxLineState, 0}}, + {3034, {wxStyledTextCtrl, getCaretLineVisible, 0}}, + {3035, {wxStyledTextCtrl, setCaretLineVisible, 1}}, + {3036, {wxStyledTextCtrl, getCaretLineBackground, 0}}, + {3037, {wxStyledTextCtrl, setCaretLineBackground, 1}}, + {3038, {wxStyledTextCtrl, autoCompShow, 2}}, + {3039, {wxStyledTextCtrl, autoCompCancel, 0}}, + {3040, {wxStyledTextCtrl, autoCompActive, 0}}, + {3041, {wxStyledTextCtrl, autoCompPosStart, 0}}, + {3042, {wxStyledTextCtrl, autoCompComplete, 0}}, + {3043, {wxStyledTextCtrl, autoCompStops, 1}}, + {3044, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, + {3045, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, + {3046, {wxStyledTextCtrl, autoCompSelect, 1}}, + {3047, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, + {3048, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, + {3049, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, + {3050, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, + {3051, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, + {3052, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, + {3053, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, + {3054, {wxStyledTextCtrl, userListShow, 2}}, + {3055, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, + {3056, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, + {3057, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, + {3058, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, + {3059, {wxStyledTextCtrl, registerImage, 2}}, + {3060, {wxStyledTextCtrl, clearRegisteredImages, 0}}, + {3061, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, + {3062, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, + {3063, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, + {3064, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, + {3065, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, + {3066, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, + {3067, {wxStyledTextCtrl, setIndent, 1}}, + {3068, {wxStyledTextCtrl, getIndent, 0}}, + {3069, {wxStyledTextCtrl, setUseTabs, 1}}, + {3070, {wxStyledTextCtrl, getUseTabs, 0}}, + {3071, {wxStyledTextCtrl, setLineIndentation, 2}}, + {3072, {wxStyledTextCtrl, getLineIndentation, 1}}, + {3073, {wxStyledTextCtrl, getLineIndentPosition, 1}}, + {3074, {wxStyledTextCtrl, getColumn, 1}}, + {3075, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, + {3076, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, + {3077, {wxStyledTextCtrl, setIndentationGuides, 1}}, + {3078, {wxStyledTextCtrl, getIndentationGuides, 0}}, + {3079, {wxStyledTextCtrl, setHighlightGuide, 1}}, + {3080, {wxStyledTextCtrl, getHighlightGuide, 0}}, + {3081, {wxStyledTextCtrl, getLineEndPosition, 1}}, + {3082, {wxStyledTextCtrl, getCodePage, 0}}, + {3083, {wxStyledTextCtrl, getCaretForeground, 0}}, + {3084, {wxStyledTextCtrl, getReadOnly, 0}}, + {3085, {wxStyledTextCtrl, setCurrentPos, 1}}, + {3086, {wxStyledTextCtrl, setSelectionStart, 1}}, + {3087, {wxStyledTextCtrl, getSelectionStart, 0}}, + {3088, {wxStyledTextCtrl, setSelectionEnd, 1}}, + {3089, {wxStyledTextCtrl, getSelectionEnd, 0}}, + {3090, {wxStyledTextCtrl, setPrintMagnification, 1}}, + {3091, {wxStyledTextCtrl, getPrintMagnification, 0}}, + {3092, {wxStyledTextCtrl, setPrintColourMode, 1}}, + {3093, {wxStyledTextCtrl, getPrintColourMode, 0}}, + {3094, {wxStyledTextCtrl, findText, 4}}, + {3095, {wxStyledTextCtrl, formatRange, 7}}, + {3096, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, + {3097, {wxStyledTextCtrl, getLine, 1}}, + {3098, {wxStyledTextCtrl, getLineCount, 0}}, + {3099, {wxStyledTextCtrl, setMarginLeft, 1}}, + {3100, {wxStyledTextCtrl, getMarginLeft, 0}}, + {3101, {wxStyledTextCtrl, setMarginRight, 1}}, + {3102, {wxStyledTextCtrl, getMarginRight, 0}}, + {3103, {wxStyledTextCtrl, getModify, 0}}, + {3104, {wxStyledTextCtrl, setSelection, 2}}, + {3105, {wxStyledTextCtrl, getSelectedText, 0}}, + {3106, {wxStyledTextCtrl, getTextRange, 2}}, + {3107, {wxStyledTextCtrl, hideSelection, 1}}, + {3108, {wxStyledTextCtrl, lineFromPosition, 1}}, + {3109, {wxStyledTextCtrl, positionFromLine, 1}}, + {3110, {wxStyledTextCtrl, lineScroll, 2}}, + {3111, {wxStyledTextCtrl, ensureCaretVisible, 0}}, + {3112, {wxStyledTextCtrl, replaceSelection, 1}}, + {3113, {wxStyledTextCtrl, setReadOnly, 1}}, + {3114, {wxStyledTextCtrl, canPaste, 0}}, + {3115, {wxStyledTextCtrl, canUndo, 0}}, + {3116, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, + {3117, {wxStyledTextCtrl, undo, 0}}, + {3118, {wxStyledTextCtrl, cut, 0}}, + {3119, {wxStyledTextCtrl, copy, 0}}, + {3120, {wxStyledTextCtrl, paste, 0}}, + {3121, {wxStyledTextCtrl, clear, 0}}, + {3122, {wxStyledTextCtrl, setText, 1}}, + {3123, {wxStyledTextCtrl, getText, 0}}, + {3124, {wxStyledTextCtrl, getTextLength, 0}}, + {3125, {wxStyledTextCtrl, getOvertype, 0}}, + {3126, {wxStyledTextCtrl, setCaretWidth, 1}}, + {3127, {wxStyledTextCtrl, getCaretWidth, 0}}, + {3128, {wxStyledTextCtrl, setTargetStart, 1}}, + {3129, {wxStyledTextCtrl, getTargetStart, 0}}, + {3130, {wxStyledTextCtrl, setTargetEnd, 1}}, + {3131, {wxStyledTextCtrl, getTargetEnd, 0}}, + {3132, {wxStyledTextCtrl, replaceTarget, 1}}, + {3133, {wxStyledTextCtrl, searchInTarget, 1}}, + {3134, {wxStyledTextCtrl, setSearchFlags, 1}}, + {3135, {wxStyledTextCtrl, getSearchFlags, 0}}, + {3136, {wxStyledTextCtrl, callTipShow, 2}}, + {3137, {wxStyledTextCtrl, callTipCancel, 0}}, + {3138, {wxStyledTextCtrl, callTipActive, 0}}, + {3139, {wxStyledTextCtrl, callTipPosAtStart, 0}}, + {3140, {wxStyledTextCtrl, callTipSetHighlight, 2}}, + {3141, {wxStyledTextCtrl, callTipSetBackground, 1}}, + {3142, {wxStyledTextCtrl, callTipSetForeground, 1}}, + {3143, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, + {3144, {wxStyledTextCtrl, callTipUseStyle, 1}}, + {3145, {wxStyledTextCtrl, visibleFromDocLine, 1}}, + {3146, {wxStyledTextCtrl, docLineFromVisible, 1}}, + {3147, {wxStyledTextCtrl, wrapCount, 1}}, + {3148, {wxStyledTextCtrl, setFoldLevel, 2}}, + {3149, {wxStyledTextCtrl, getFoldLevel, 1}}, + {3150, {wxStyledTextCtrl, getLastChild, 2}}, + {3151, {wxStyledTextCtrl, getFoldParent, 1}}, + {3152, {wxStyledTextCtrl, showLines, 2}}, + {3153, {wxStyledTextCtrl, hideLines, 2}}, + {3154, {wxStyledTextCtrl, getLineVisible, 1}}, + {3155, {wxStyledTextCtrl, setFoldExpanded, 2}}, + {3156, {wxStyledTextCtrl, getFoldExpanded, 1}}, + {3157, {wxStyledTextCtrl, toggleFold, 1}}, + {3158, {wxStyledTextCtrl, ensureVisible, 1}}, + {3159, {wxStyledTextCtrl, setFoldFlags, 1}}, + {3160, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, + {3161, {wxStyledTextCtrl, setTabIndents, 1}}, + {3162, {wxStyledTextCtrl, getTabIndents, 0}}, + {3163, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, + {3164, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, + {3165, {wxStyledTextCtrl, setMouseDwellTime, 1}}, + {3166, {wxStyledTextCtrl, getMouseDwellTime, 0}}, + {3167, {wxStyledTextCtrl, wordStartPosition, 2}}, + {3168, {wxStyledTextCtrl, wordEndPosition, 2}}, + {3169, {wxStyledTextCtrl, setWrapMode, 1}}, + {3170, {wxStyledTextCtrl, getWrapMode, 0}}, + {3171, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, + {3172, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, + {3173, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, + {3174, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, + {3175, {wxStyledTextCtrl, setWrapStartIndent, 1}}, + {3176, {wxStyledTextCtrl, getWrapStartIndent, 0}}, + {3177, {wxStyledTextCtrl, setLayoutCache, 1}}, + {3178, {wxStyledTextCtrl, getLayoutCache, 0}}, + {3179, {wxStyledTextCtrl, setScrollWidth, 1}}, + {3180, {wxStyledTextCtrl, getScrollWidth, 0}}, + {3181, {wxStyledTextCtrl, textWidth, 2}}, + {3182, {wxStyledTextCtrl, getEndAtLastLine, 0}}, + {3183, {wxStyledTextCtrl, textHeight, 1}}, + {3184, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, + {3185, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, + {3186, {wxStyledTextCtrl, appendText, 1}}, + {3187, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, + {3188, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, + {3189, {wxStyledTextCtrl, targetFromSelection, 0}}, + {3190, {wxStyledTextCtrl, linesJoin, 0}}, + {3191, {wxStyledTextCtrl, linesSplit, 1}}, + {3192, {wxStyledTextCtrl, setFoldMarginColour, 2}}, + {3193, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, + {3194, {wxStyledTextCtrl, lineDown, 0}}, + {3195, {wxStyledTextCtrl, lineDownExtend, 0}}, + {3196, {wxStyledTextCtrl, lineUp, 0}}, + {3197, {wxStyledTextCtrl, lineUpExtend, 0}}, + {3198, {wxStyledTextCtrl, charLeft, 0}}, + {3199, {wxStyledTextCtrl, charLeftExtend, 0}}, + {3200, {wxStyledTextCtrl, charRight, 0}}, + {3201, {wxStyledTextCtrl, charRightExtend, 0}}, + {3202, {wxStyledTextCtrl, wordLeft, 0}}, + {3203, {wxStyledTextCtrl, wordLeftExtend, 0}}, + {3204, {wxStyledTextCtrl, wordRight, 0}}, + {3205, {wxStyledTextCtrl, wordRightExtend, 0}}, + {3206, {wxStyledTextCtrl, home, 0}}, + {3207, {wxStyledTextCtrl, homeExtend, 0}}, + {3208, {wxStyledTextCtrl, lineEnd, 0}}, + {3209, {wxStyledTextCtrl, lineEndExtend, 0}}, + {3210, {wxStyledTextCtrl, documentStart, 0}}, + {3211, {wxStyledTextCtrl, documentStartExtend, 0}}, + {3212, {wxStyledTextCtrl, documentEnd, 0}}, + {3213, {wxStyledTextCtrl, documentEndExtend, 0}}, + {3214, {wxStyledTextCtrl, pageUp, 0}}, + {3215, {wxStyledTextCtrl, pageUpExtend, 0}}, + {3216, {wxStyledTextCtrl, pageDown, 0}}, + {3217, {wxStyledTextCtrl, pageDownExtend, 0}}, + {3218, {wxStyledTextCtrl, editToggleOvertype, 0}}, + {3219, {wxStyledTextCtrl, cancel, 0}}, + {3220, {wxStyledTextCtrl, deleteBack, 0}}, + {3221, {wxStyledTextCtrl, tab, 0}}, + {3222, {wxStyledTextCtrl, backTab, 0}}, + {3223, {wxStyledTextCtrl, newLine, 0}}, + {3224, {wxStyledTextCtrl, formFeed, 0}}, + {3225, {wxStyledTextCtrl, vCHome, 0}}, + {3226, {wxStyledTextCtrl, vCHomeExtend, 0}}, + {3227, {wxStyledTextCtrl, zoomIn, 0}}, + {3228, {wxStyledTextCtrl, zoomOut, 0}}, + {3229, {wxStyledTextCtrl, delWordLeft, 0}}, + {3230, {wxStyledTextCtrl, delWordRight, 0}}, + {3231, {wxStyledTextCtrl, lineCut, 0}}, + {3232, {wxStyledTextCtrl, lineDelete, 0}}, + {3233, {wxStyledTextCtrl, lineTranspose, 0}}, + {3234, {wxStyledTextCtrl, lineDuplicate, 0}}, + {3235, {wxStyledTextCtrl, lowerCase, 0}}, + {3236, {wxStyledTextCtrl, upperCase, 0}}, + {3237, {wxStyledTextCtrl, lineScrollDown, 0}}, + {3238, {wxStyledTextCtrl, lineScrollUp, 0}}, + {3239, {wxStyledTextCtrl, deleteBackNotLine, 0}}, + {3240, {wxStyledTextCtrl, homeDisplay, 0}}, + {3241, {wxStyledTextCtrl, homeDisplayExtend, 0}}, + {3242, {wxStyledTextCtrl, lineEndDisplay, 0}}, + {3243, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, + {3244, {wxStyledTextCtrl, homeWrapExtend, 0}}, + {3245, {wxStyledTextCtrl, lineEndWrap, 0}}, + {3246, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, + {3247, {wxStyledTextCtrl, vCHomeWrap, 0}}, + {3248, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, + {3249, {wxStyledTextCtrl, lineCopy, 0}}, + {3250, {wxStyledTextCtrl, moveCaretInsideView, 0}}, + {3251, {wxStyledTextCtrl, lineLength, 1}}, + {3252, {wxStyledTextCtrl, braceHighlight, 2}}, + {3253, {wxStyledTextCtrl, braceBadLight, 1}}, + {3254, {wxStyledTextCtrl, braceMatch, 1}}, + {3255, {wxStyledTextCtrl, getViewEOL, 0}}, + {3256, {wxStyledTextCtrl, setViewEOL, 1}}, + {3257, {wxStyledTextCtrl, setModEventMask, 1}}, + {3258, {wxStyledTextCtrl, getEdgeColumn, 0}}, + {3259, {wxStyledTextCtrl, setEdgeColumn, 1}}, + {3260, {wxStyledTextCtrl, getEdgeMode, 0}}, + {3261, {wxStyledTextCtrl, getEdgeColour, 0}}, + {3262, {wxStyledTextCtrl, setEdgeColour, 1}}, + {3263, {wxStyledTextCtrl, searchAnchor, 0}}, + {3264, {wxStyledTextCtrl, searchNext, 2}}, + {3265, {wxStyledTextCtrl, searchPrev, 2}}, + {3266, {wxStyledTextCtrl, linesOnScreen, 0}}, + {3267, {wxStyledTextCtrl, usePopUp, 1}}, + {3268, {wxStyledTextCtrl, selectionIsRectangle, 0}}, + {3269, {wxStyledTextCtrl, setZoom, 1}}, + {3270, {wxStyledTextCtrl, getZoom, 0}}, + {3271, {wxStyledTextCtrl, getModEventMask, 0}}, + {3272, {wxStyledTextCtrl, setSTCFocus, 1}}, + {3273, {wxStyledTextCtrl, getSTCFocus, 0}}, + {3274, {wxStyledTextCtrl, setStatus, 1}}, + {3275, {wxStyledTextCtrl, getStatus, 0}}, + {3276, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, + {3277, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, + {3278, {wxStyledTextCtrl, setSTCCursor, 1}}, + {3279, {wxStyledTextCtrl, getSTCCursor, 0}}, + {3280, {wxStyledTextCtrl, setControlCharSymbol, 1}}, + {3281, {wxStyledTextCtrl, getControlCharSymbol, 0}}, + {3282, {wxStyledTextCtrl, wordPartLeft, 0}}, + {3283, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, + {3284, {wxStyledTextCtrl, wordPartRight, 0}}, + {3285, {wxStyledTextCtrl, wordPartRightExtend, 0}}, + {3286, {wxStyledTextCtrl, setVisiblePolicy, 2}}, + {3287, {wxStyledTextCtrl, delLineLeft, 0}}, + {3288, {wxStyledTextCtrl, delLineRight, 0}}, + {3289, {wxStyledTextCtrl, getXOffset, 0}}, + {3290, {wxStyledTextCtrl, chooseCaretX, 0}}, + {3291, {wxStyledTextCtrl, setXCaretPolicy, 2}}, + {3292, {wxStyledTextCtrl, setYCaretPolicy, 2}}, + {3293, {wxStyledTextCtrl, getPrintWrapMode, 0}}, + {3294, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, + {3295, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, + {3296, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, + {3297, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, + {3298, {wxStyledTextCtrl, paraDownExtend, 0}}, + {3299, {wxStyledTextCtrl, paraUp, 0}}, + {3300, {wxStyledTextCtrl, paraUpExtend, 0}}, + {3301, {wxStyledTextCtrl, positionBefore, 1}}, + {3302, {wxStyledTextCtrl, positionAfter, 1}}, + {3303, {wxStyledTextCtrl, copyRange, 2}}, + {3304, {wxStyledTextCtrl, copyText, 2}}, + {3305, {wxStyledTextCtrl, setSelectionMode, 1}}, + {3306, {wxStyledTextCtrl, getSelectionMode, 0}}, + {3307, {wxStyledTextCtrl, lineDownRectExtend, 0}}, + {3308, {wxStyledTextCtrl, lineUpRectExtend, 0}}, + {3309, {wxStyledTextCtrl, charLeftRectExtend, 0}}, + {3310, {wxStyledTextCtrl, charRightRectExtend, 0}}, + {3311, {wxStyledTextCtrl, homeRectExtend, 0}}, + {3312, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, + {3313, {wxStyledTextCtrl, lineEndRectExtend, 0}}, + {3314, {wxStyledTextCtrl, pageUpRectExtend, 0}}, + {3315, {wxStyledTextCtrl, pageDownRectExtend, 0}}, + {3316, {wxStyledTextCtrl, stutteredPageUp, 0}}, + {3317, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, + {3318, {wxStyledTextCtrl, stutteredPageDown, 0}}, + {3319, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, + {3320, {wxStyledTextCtrl, wordLeftEnd, 0}}, + {3321, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, + {3322, {wxStyledTextCtrl, wordRightEnd, 0}}, + {3323, {wxStyledTextCtrl, wordRightEndExtend, 0}}, + {3324, {wxStyledTextCtrl, setWhitespaceChars, 1}}, + {3325, {wxStyledTextCtrl, setCharsDefault, 0}}, + {3326, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, + {3327, {wxStyledTextCtrl, allocate, 1}}, + {3328, {wxStyledTextCtrl, findColumn, 2}}, + {3329, {wxStyledTextCtrl, getCaretSticky, 0}}, + {3330, {wxStyledTextCtrl, setCaretSticky, 1}}, + {3331, {wxStyledTextCtrl, toggleCaretSticky, 0}}, + {3332, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, + {3333, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, + {3334, {wxStyledTextCtrl, selectionDuplicate, 0}}, + {3335, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, + {3336, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, + {3337, {wxStyledTextCtrl, startRecord, 0}}, + {3338, {wxStyledTextCtrl, stopRecord, 0}}, + {3339, {wxStyledTextCtrl, setLexer, 1}}, + {3340, {wxStyledTextCtrl, getLexer, 0}}, + {3341, {wxStyledTextCtrl, colourise, 2}}, + {3342, {wxStyledTextCtrl, setProperty, 2}}, + {3343, {wxStyledTextCtrl, setKeyWords, 2}}, + {3344, {wxStyledTextCtrl, setLexerLanguage, 1}}, + {3345, {wxStyledTextCtrl, getProperty, 1}}, + {3346, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, + {3347, {wxStyledTextCtrl, getCurrentLine, 0}}, + {3348, {wxStyledTextCtrl, styleSetSpec, 2}}, + {3349, {wxStyledTextCtrl, styleSetFont, 2}}, + {3350, {wxStyledTextCtrl, styleSetFontAttr, 7}}, + {3351, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, + {3352, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, + {3353, {wxStyledTextCtrl, cmdKeyExecute, 1}}, + {3354, {wxStyledTextCtrl, setMargins, 2}}, + {3355, {wxStyledTextCtrl, getSelection, 2}}, + {3356, {wxStyledTextCtrl, pointFromPosition, 1}}, + {3357, {wxStyledTextCtrl, scrollToLine, 1}}, + {3358, {wxStyledTextCtrl, scrollToColumn, 1}}, + {3359, {wxStyledTextCtrl, sendMsg, 2}}, + {3360, {wxStyledTextCtrl, setVScrollBar, 1}}, + {3361, {wxStyledTextCtrl, setHScrollBar, 1}}, + {3362, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, + {3363, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, + {3364, {wxStyledTextCtrl, saveFile, 1}}, + {3365, {wxStyledTextCtrl, loadFile, 1}}, + {3366, {wxStyledTextCtrl, doDragOver, 3}}, + {3367, {wxStyledTextCtrl, doDropText, 3}}, + {3368, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, + {3369, {wxStyledTextCtrl, addTextRaw, 1}}, + {3370, {wxStyledTextCtrl, insertTextRaw, 2}}, + {3371, {wxStyledTextCtrl, getCurLineRaw, 1}}, + {3372, {wxStyledTextCtrl, getLineRaw, 1}}, + {3373, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, + {3374, {wxStyledTextCtrl, getTextRangeRaw, 2}}, + {3375, {wxStyledTextCtrl, setTextRaw, 1}}, + {3376, {wxStyledTextCtrl, getTextRaw, 0}}, + {3377, {wxStyledTextCtrl, appendTextRaw, 1}}, + {3378, {wxArtProvider, getBitmap, 2}}, + {3379, {wxArtProvider, getIcon, 2}}, + {3380, {wxTreeEvent, getKeyCode, 0}}, + {3381, {wxTreeEvent, getItem, 0}}, + {3382, {wxTreeEvent, getKeyEvent, 0}}, + {3383, {wxTreeEvent, getLabel, 0}}, + {3384, {wxTreeEvent, getOldItem, 0}}, + {3385, {wxTreeEvent, getPoint, 0}}, + {3386, {wxTreeEvent, isEditCancelled, 0}}, + {3387, {wxTreeEvent, setToolTip, 1}}, + {3388, {wxNotebookEvent, getOldSelection, 0}}, + {3389, {wxNotebookEvent, getSelection, 0}}, + {3390, {wxNotebookEvent, setOldSelection, 1}}, + {3391, {wxNotebookEvent, setSelection, 1}}, + {3392, {wxFileDataObject, new, 0}}, + {3393, {wxFileDataObject, addFile, 1}}, + {3394, {wxFileDataObject, getFilenames, 0}}, + {3395, {wxFileDataObject, 'Destroy', undefined}}, + {3396, {wxTextDataObject, new, 1}}, + {3397, {wxTextDataObject, getTextLength, 0}}, + {3398, {wxTextDataObject, getText, 0}}, + {3399, {wxTextDataObject, setText, 1}}, + {3400, {wxTextDataObject, 'Destroy', undefined}}, + {3401, {wxBitmapDataObject, new_1_1, 1}}, + {3402, {wxBitmapDataObject, new_1_0, 1}}, + {3403, {wxBitmapDataObject, getBitmap, 0}}, + {3404, {wxBitmapDataObject, setBitmap, 1}}, + {3405, {wxBitmapDataObject, 'Destroy', undefined}}, + {3407, {wxClipboard, new, 0}}, + {3408, {wxClipboard, destruct, 0}}, + {3409, {wxClipboard, addData, 1}}, + {3410, {wxClipboard, clear, 0}}, + {3411, {wxClipboard, close, 0}}, + {3412, {wxClipboard, flush, 0}}, + {3413, {wxClipboard, getData, 1}}, + {3414, {wxClipboard, isOpened, 0}}, + {3415, {wxClipboard, open, 0}}, + {3416, {wxClipboard, setData, 1}}, + {3418, {wxClipboard, usePrimarySelection, 1}}, + {3419, {wxClipboard, isSupported, 1}}, + {3420, {wxClipboard, get, 0}}, + {3421, {wxSpinEvent, getPosition, 0}}, + {3422, {wxSpinEvent, setPosition, 1}}, + {3423, {wxSplitterWindow, new_0, 0}}, + {3424, {wxSplitterWindow, new_2, 2}}, + {3425, {wxSplitterWindow, destruct, 0}}, + {3426, {wxSplitterWindow, create, 2}}, + {3427, {wxSplitterWindow, getMinimumPaneSize, 0}}, + {3428, {wxSplitterWindow, getSashGravity, 0}}, + {3429, {wxSplitterWindow, getSashPosition, 0}}, + {3430, {wxSplitterWindow, getSplitMode, 0}}, + {3431, {wxSplitterWindow, getWindow1, 0}}, + {3432, {wxSplitterWindow, getWindow2, 0}}, + {3433, {wxSplitterWindow, initialize, 1}}, + {3434, {wxSplitterWindow, isSplit, 0}}, + {3435, {wxSplitterWindow, replaceWindow, 2}}, + {3436, {wxSplitterWindow, setSashGravity, 1}}, + {3437, {wxSplitterWindow, setSashPosition, 2}}, + {3438, {wxSplitterWindow, setSashSize, 1}}, + {3439, {wxSplitterWindow, setMinimumPaneSize, 1}}, + {3440, {wxSplitterWindow, setSplitMode, 1}}, + {3441, {wxSplitterWindow, splitHorizontally, 3}}, + {3442, {wxSplitterWindow, splitVertically, 3}}, + {3443, {wxSplitterWindow, unsplit, 1}}, + {3444, {wxSplitterWindow, updateSize, 0}}, + {3445, {wxSplitterEvent, getSashPosition, 0}}, + {3446, {wxSplitterEvent, getX, 0}}, + {3447, {wxSplitterEvent, getY, 0}}, + {3448, {wxSplitterEvent, getWindowBeingRemoved, 0}}, + {3449, {wxSplitterEvent, setSashPosition, 1}}, + {3450, {wxHtmlWindow, new_0, 0}}, + {3451, {wxHtmlWindow, new_2, 2}}, + {3452, {wxHtmlWindow, appendToPage, 1}}, + {3453, {wxHtmlWindow, getOpenedAnchor, 0}}, + {3454, {wxHtmlWindow, getOpenedPage, 0}}, + {3455, {wxHtmlWindow, getOpenedPageTitle, 0}}, + {3456, {wxHtmlWindow, getRelatedFrame, 0}}, + {3457, {wxHtmlWindow, historyBack, 0}}, + {3458, {wxHtmlWindow, historyCanBack, 0}}, + {3459, {wxHtmlWindow, historyCanForward, 0}}, + {3460, {wxHtmlWindow, historyClear, 0}}, + {3461, {wxHtmlWindow, historyForward, 0}}, + {3462, {wxHtmlWindow, loadFile, 1}}, + {3463, {wxHtmlWindow, loadPage, 1}}, + {3464, {wxHtmlWindow, selectAll, 0}}, + {3465, {wxHtmlWindow, selectionToText, 0}}, + {3466, {wxHtmlWindow, selectLine, 1}}, + {3467, {wxHtmlWindow, selectWord, 1}}, + {3468, {wxHtmlWindow, setBorders, 1}}, + {3469, {wxHtmlWindow, setFonts, 3}}, + {3470, {wxHtmlWindow, setPage, 1}}, + {3471, {wxHtmlWindow, setRelatedFrame, 2}}, + {3472, {wxHtmlWindow, setRelatedStatusBar, 1}}, + {3473, {wxHtmlWindow, toText, 0}}, + {3474, {wxHtmlWindow, 'Destroy', undefined}}, + {3475, {wxHtmlLinkEvent, getLinkInfo, 0}}, + {3476, {wxSystemSettings, getColour, 1}}, + {3477, {wxSystemSettings, getFont, 1}}, + {3478, {wxSystemSettings, getMetric, 2}}, + {3479, {wxSystemSettings, getScreenType, 0}}, + {3480, {wxAuiNotebookEvent, setSelection, 1}}, + {3481, {wxAuiNotebookEvent, getSelection, 0}}, + {3482, {wxAuiNotebookEvent, setOldSelection, 1}}, + {3483, {wxAuiNotebookEvent, getOldSelection, 0}}, + {3484, {wxAuiNotebookEvent, setDragSource, 1}}, + {3485, {wxAuiNotebookEvent, getDragSource, 0}}, + {3486, {wxAuiManagerEvent, setManager, 1}}, + {3487, {wxAuiManagerEvent, getManager, 0}}, + {3488, {wxAuiManagerEvent, setPane, 1}}, + {3489, {wxAuiManagerEvent, getPane, 0}}, + {3490, {wxAuiManagerEvent, setButton, 1}}, + {3491, {wxAuiManagerEvent, getButton, 0}}, + {3492, {wxAuiManagerEvent, setDC, 1}}, + {3493, {wxAuiManagerEvent, getDC, 0}}, + {3494, {wxAuiManagerEvent, veto, 1}}, + {3495, {wxAuiManagerEvent, getVeto, 0}}, + {3496, {wxAuiManagerEvent, setCanVeto, 1}}, + {3497, {wxAuiManagerEvent, canVeto, 0}}, + {3498, {wxLogNull, new, 0}}, + {3499, {wxLogNull, 'Destroy', undefined}}, {-1, {mod, func, -1}} ]. diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl index 7b5ca229c8..cf672644c6 100644 --- a/lib/wx/src/gen/wxe_funcs.hrl +++ b/lib/wx/src/gen/wxe_funcs.hrl @@ -1834,1442 +1834,1447 @@ -define(wxTreeCtrl_Delete, 2007). -define(wxTreeCtrl_DeleteAllItems, 2008). -define(wxTreeCtrl_DeleteChildren, 2009). --define(wxTreeCtrl_EnsureVisible, 2010). --define(wxTreeCtrl_Expand, 2011). --define(wxTreeCtrl_GetBoundingRect, 2012). --define(wxTreeCtrl_GetChildrenCount, 2014). --define(wxTreeCtrl_GetCount, 2015). --define(wxTreeCtrl_GetEditControl, 2016). --define(wxTreeCtrl_GetFirstChild, 2017). --define(wxTreeCtrl_GetNextChild, 2018). --define(wxTreeCtrl_GetFirstVisibleItem, 2019). --define(wxTreeCtrl_GetImageList, 2020). --define(wxTreeCtrl_GetIndent, 2021). --define(wxTreeCtrl_GetItemBackgroundColour, 2022). --define(wxTreeCtrl_GetItemData, 2023). --define(wxTreeCtrl_GetItemFont, 2024). --define(wxTreeCtrl_GetItemImage_1, 2025). --define(wxTreeCtrl_GetItemImage_2, 2026). --define(wxTreeCtrl_GetItemText, 2027). --define(wxTreeCtrl_GetItemTextColour, 2028). --define(wxTreeCtrl_GetLastChild, 2029). --define(wxTreeCtrl_GetNextSibling, 2030). --define(wxTreeCtrl_GetNextVisible, 2031). --define(wxTreeCtrl_GetItemParent, 2032). --define(wxTreeCtrl_GetPrevSibling, 2033). --define(wxTreeCtrl_GetPrevVisible, 2034). --define(wxTreeCtrl_GetRootItem, 2035). --define(wxTreeCtrl_GetSelection, 2036). --define(wxTreeCtrl_GetSelections, 2037). --define(wxTreeCtrl_GetStateImageList, 2038). --define(wxTreeCtrl_HitTest, 2039). --define(wxTreeCtrl_InsertItem, 2041). --define(wxTreeCtrl_IsBold, 2042). --define(wxTreeCtrl_IsExpanded, 2043). --define(wxTreeCtrl_IsSelected, 2044). --define(wxTreeCtrl_IsVisible, 2045). --define(wxTreeCtrl_ItemHasChildren, 2046). --define(wxTreeCtrl_PrependItem, 2047). --define(wxTreeCtrl_ScrollTo, 2048). --define(wxTreeCtrl_SelectItem_1, 2049). --define(wxTreeCtrl_SelectItem_2, 2050). --define(wxTreeCtrl_SetIndent, 2051). --define(wxTreeCtrl_SetImageList, 2052). --define(wxTreeCtrl_SetItemBackgroundColour, 2053). --define(wxTreeCtrl_SetItemBold, 2054). --define(wxTreeCtrl_SetItemData, 2055). --define(wxTreeCtrl_SetItemDropHighlight, 2056). --define(wxTreeCtrl_SetItemFont, 2057). --define(wxTreeCtrl_SetItemHasChildren, 2058). --define(wxTreeCtrl_SetItemImage_2, 2059). --define(wxTreeCtrl_SetItemImage_3, 2060). --define(wxTreeCtrl_SetItemText, 2061). --define(wxTreeCtrl_SetItemTextColour, 2062). --define(wxTreeCtrl_SetStateImageList, 2063). --define(wxTreeCtrl_SetWindowStyle, 2064). --define(wxTreeCtrl_SortChildren, 2065). --define(wxTreeCtrl_Toggle, 2066). --define(wxTreeCtrl_ToggleItemSelection, 2067). --define(wxTreeCtrl_Unselect, 2068). --define(wxTreeCtrl_UnselectAll, 2069). --define(wxTreeCtrl_UnselectItem, 2070). --define(wxScrollBar_new_0, 2071). --define(wxScrollBar_new_3, 2072). --define(wxScrollBar_destruct, 2073). --define(wxScrollBar_Create, 2074). --define(wxScrollBar_GetRange, 2075). --define(wxScrollBar_GetPageSize, 2076). --define(wxScrollBar_GetThumbPosition, 2077). --define(wxScrollBar_GetThumbSize, 2078). --define(wxScrollBar_SetThumbPosition, 2079). --define(wxScrollBar_SetScrollbar, 2080). --define(wxSpinButton_new_2, 2082). --define(wxSpinButton_new_0, 2083). --define(wxSpinButton_Create, 2084). --define(wxSpinButton_GetMax, 2085). --define(wxSpinButton_GetMin, 2086). --define(wxSpinButton_GetValue, 2087). --define(wxSpinButton_SetRange, 2088). --define(wxSpinButton_SetValue, 2089). --define(wxSpinButton_destroy, 2090). --define(wxSpinCtrl_new_0, 2091). --define(wxSpinCtrl_new_2, 2092). --define(wxSpinCtrl_Create, 2094). --define(wxSpinCtrl_SetValue_1_1, 2097). --define(wxSpinCtrl_SetValue_1_0, 2098). --define(wxSpinCtrl_GetValue, 2100). --define(wxSpinCtrl_SetRange, 2102). --define(wxSpinCtrl_SetSelection, 2103). --define(wxSpinCtrl_GetMin, 2105). --define(wxSpinCtrl_GetMax, 2107). --define(wxSpinCtrl_destroy, 2108). --define(wxStaticText_new_0, 2109). --define(wxStaticText_new_4, 2110). --define(wxStaticText_Create, 2111). --define(wxStaticText_GetLabel, 2112). --define(wxStaticText_SetLabel, 2113). --define(wxStaticText_Wrap, 2114). --define(wxStaticText_destroy, 2115). --define(wxStaticBitmap_new_0, 2116). --define(wxStaticBitmap_new_4, 2117). --define(wxStaticBitmap_Create, 2118). --define(wxStaticBitmap_GetBitmap, 2119). --define(wxStaticBitmap_SetBitmap, 2120). --define(wxStaticBitmap_destroy, 2121). --define(wxRadioBox_new, 2122). --define(wxRadioBox_destruct, 2124). --define(wxRadioBox_Create, 2125). --define(wxRadioBox_Enable_2, 2126). --define(wxRadioBox_Enable_1, 2127). --define(wxRadioBox_GetSelection, 2128). --define(wxRadioBox_GetString, 2129). --define(wxRadioBox_SetSelection, 2130). --define(wxRadioBox_Show_2, 2131). --define(wxRadioBox_Show_1, 2132). --define(wxRadioBox_GetColumnCount, 2133). --define(wxRadioBox_GetItemHelpText, 2134). --define(wxRadioBox_GetItemToolTip, 2135). --define(wxRadioBox_GetItemFromPoint, 2137). --define(wxRadioBox_GetRowCount, 2138). --define(wxRadioBox_IsItemEnabled, 2139). --define(wxRadioBox_IsItemShown, 2140). --define(wxRadioBox_SetItemHelpText, 2141). --define(wxRadioBox_SetItemToolTip, 2142). --define(wxRadioButton_new_0, 2143). --define(wxRadioButton_new_4, 2144). --define(wxRadioButton_Create, 2145). --define(wxRadioButton_GetValue, 2146). --define(wxRadioButton_SetValue, 2147). --define(wxRadioButton_destroy, 2148). --define(wxSlider_new_6, 2150). --define(wxSlider_new_0, 2151). --define(wxSlider_Create, 2152). --define(wxSlider_GetLineSize, 2153). --define(wxSlider_GetMax, 2154). --define(wxSlider_GetMin, 2155). --define(wxSlider_GetPageSize, 2156). --define(wxSlider_GetThumbLength, 2157). --define(wxSlider_GetValue, 2158). --define(wxSlider_SetLineSize, 2159). --define(wxSlider_SetPageSize, 2160). --define(wxSlider_SetRange, 2161). --define(wxSlider_SetThumbLength, 2162). --define(wxSlider_SetValue, 2163). --define(wxSlider_destroy, 2164). --define(wxDialog_new_4, 2166). --define(wxDialog_new_0, 2167). --define(wxDialog_destruct, 2169). --define(wxDialog_Create, 2170). --define(wxDialog_CreateButtonSizer, 2171). --define(wxDialog_CreateStdDialogButtonSizer, 2172). --define(wxDialog_EndModal, 2173). --define(wxDialog_GetAffirmativeId, 2174). --define(wxDialog_GetReturnCode, 2175). --define(wxDialog_IsModal, 2176). --define(wxDialog_SetAffirmativeId, 2177). --define(wxDialog_SetReturnCode, 2178). --define(wxDialog_Show, 2179). --define(wxDialog_ShowModal, 2180). --define(wxColourDialog_new_0, 2181). --define(wxColourDialog_new_2, 2182). --define(wxColourDialog_destruct, 2183). --define(wxColourDialog_Create, 2184). --define(wxColourDialog_GetColourData, 2185). --define(wxColourData_new_0, 2186). --define(wxColourData_new_1, 2187). --define(wxColourData_destruct, 2188). --define(wxColourData_GetChooseFull, 2189). --define(wxColourData_GetColour, 2190). --define(wxColourData_GetCustomColour, 2192). --define(wxColourData_SetChooseFull, 2193). --define(wxColourData_SetColour, 2194). --define(wxColourData_SetCustomColour, 2195). --define(wxPalette_new_0, 2196). --define(wxPalette_new_4, 2197). --define(wxPalette_destruct, 2199). --define(wxPalette_Create, 2200). --define(wxPalette_GetColoursCount, 2201). --define(wxPalette_GetPixel, 2202). --define(wxPalette_GetRGB, 2203). --define(wxPalette_IsOk, 2204). --define(wxDirDialog_new, 2208). --define(wxDirDialog_destruct, 2209). --define(wxDirDialog_GetPath, 2210). --define(wxDirDialog_GetMessage, 2211). --define(wxDirDialog_SetMessage, 2212). --define(wxDirDialog_SetPath, 2213). --define(wxFileDialog_new, 2217). --define(wxFileDialog_destruct, 2218). --define(wxFileDialog_GetDirectory, 2219). --define(wxFileDialog_GetFilename, 2220). --define(wxFileDialog_GetFilenames, 2221). --define(wxFileDialog_GetFilterIndex, 2222). --define(wxFileDialog_GetMessage, 2223). --define(wxFileDialog_GetPath, 2224). --define(wxFileDialog_GetPaths, 2225). --define(wxFileDialog_GetWildcard, 2226). --define(wxFileDialog_SetDirectory, 2227). --define(wxFileDialog_SetFilename, 2228). --define(wxFileDialog_SetFilterIndex, 2229). --define(wxFileDialog_SetMessage, 2230). --define(wxFileDialog_SetPath, 2231). --define(wxFileDialog_SetWildcard, 2232). --define(wxPickerBase_SetInternalMargin, 2233). --define(wxPickerBase_GetInternalMargin, 2234). --define(wxPickerBase_SetTextCtrlProportion, 2235). --define(wxPickerBase_SetPickerCtrlProportion, 2236). --define(wxPickerBase_GetTextCtrlProportion, 2237). --define(wxPickerBase_GetPickerCtrlProportion, 2238). --define(wxPickerBase_HasTextCtrl, 2239). --define(wxPickerBase_GetTextCtrl, 2240). --define(wxPickerBase_IsTextCtrlGrowable, 2241). --define(wxPickerBase_SetPickerCtrlGrowable, 2242). --define(wxPickerBase_SetTextCtrlGrowable, 2243). --define(wxPickerBase_IsPickerCtrlGrowable, 2244). --define(wxFilePickerCtrl_new_0, 2245). --define(wxFilePickerCtrl_new_3, 2246). --define(wxFilePickerCtrl_Create, 2247). --define(wxFilePickerCtrl_GetPath, 2248). --define(wxFilePickerCtrl_SetPath, 2249). --define(wxFilePickerCtrl_destroy, 2250). --define(wxDirPickerCtrl_new_0, 2251). --define(wxDirPickerCtrl_new_3, 2252). --define(wxDirPickerCtrl_Create, 2253). --define(wxDirPickerCtrl_GetPath, 2254). --define(wxDirPickerCtrl_SetPath, 2255). --define(wxDirPickerCtrl_destroy, 2256). --define(wxColourPickerCtrl_new_0, 2257). --define(wxColourPickerCtrl_new_3, 2258). --define(wxColourPickerCtrl_Create, 2259). --define(wxColourPickerCtrl_GetColour, 2260). --define(wxColourPickerCtrl_SetColour_1_1, 2261). --define(wxColourPickerCtrl_SetColour_1_0, 2262). --define(wxColourPickerCtrl_destroy, 2263). --define(wxDatePickerCtrl_new_0, 2264). --define(wxDatePickerCtrl_new_3, 2265). --define(wxDatePickerCtrl_GetRange, 2266). --define(wxDatePickerCtrl_GetValue, 2267). --define(wxDatePickerCtrl_SetRange, 2268). --define(wxDatePickerCtrl_SetValue, 2269). --define(wxDatePickerCtrl_destroy, 2270). --define(wxFontPickerCtrl_new_0, 2271). --define(wxFontPickerCtrl_new_3, 2272). --define(wxFontPickerCtrl_Create, 2273). --define(wxFontPickerCtrl_GetSelectedFont, 2274). --define(wxFontPickerCtrl_SetSelectedFont, 2275). --define(wxFontPickerCtrl_GetMaxPointSize, 2276). --define(wxFontPickerCtrl_SetMaxPointSize, 2277). --define(wxFontPickerCtrl_destroy, 2278). --define(wxFindReplaceDialog_new_0, 2281). --define(wxFindReplaceDialog_new_4, 2282). --define(wxFindReplaceDialog_destruct, 2283). --define(wxFindReplaceDialog_Create, 2284). --define(wxFindReplaceDialog_GetData, 2285). --define(wxFindReplaceData_new_0, 2286). --define(wxFindReplaceData_new_1, 2287). --define(wxFindReplaceData_GetFindString, 2288). --define(wxFindReplaceData_GetReplaceString, 2289). --define(wxFindReplaceData_GetFlags, 2290). --define(wxFindReplaceData_SetFlags, 2291). --define(wxFindReplaceData_SetFindString, 2292). --define(wxFindReplaceData_SetReplaceString, 2293). --define(wxFindReplaceData_destroy, 2294). --define(wxMultiChoiceDialog_new_0, 2295). --define(wxMultiChoiceDialog_new_5, 2297). --define(wxMultiChoiceDialog_GetSelections, 2298). --define(wxMultiChoiceDialog_SetSelections, 2299). --define(wxMultiChoiceDialog_destroy, 2300). --define(wxSingleChoiceDialog_new_0, 2301). --define(wxSingleChoiceDialog_new_5, 2303). --define(wxSingleChoiceDialog_GetSelection, 2304). --define(wxSingleChoiceDialog_GetStringSelection, 2305). --define(wxSingleChoiceDialog_SetSelection, 2306). --define(wxSingleChoiceDialog_destroy, 2307). --define(wxTextEntryDialog_new, 2308). --define(wxTextEntryDialog_GetValue, 2309). --define(wxTextEntryDialog_SetValue, 2310). --define(wxTextEntryDialog_destroy, 2311). --define(wxPasswordEntryDialog_new, 2312). --define(wxPasswordEntryDialog_destroy, 2313). --define(wxFontData_new_0, 2314). --define(wxFontData_new_1, 2315). --define(wxFontData_destruct, 2316). --define(wxFontData_EnableEffects, 2317). --define(wxFontData_GetAllowSymbols, 2318). --define(wxFontData_GetColour, 2319). --define(wxFontData_GetChosenFont, 2320). --define(wxFontData_GetEnableEffects, 2321). --define(wxFontData_GetInitialFont, 2322). --define(wxFontData_GetShowHelp, 2323). --define(wxFontData_SetAllowSymbols, 2324). --define(wxFontData_SetChosenFont, 2325). --define(wxFontData_SetColour, 2326). --define(wxFontData_SetInitialFont, 2327). --define(wxFontData_SetRange, 2328). --define(wxFontData_SetShowHelp, 2329). --define(wxFontDialog_new_0, 2333). --define(wxFontDialog_new_2, 2335). --define(wxFontDialog_Create, 2337). --define(wxFontDialog_GetFontData, 2338). --define(wxFontDialog_destroy, 2340). --define(wxProgressDialog_new, 2341). --define(wxProgressDialog_destruct, 2342). --define(wxProgressDialog_Resume, 2343). --define(wxProgressDialog_Update_2, 2344). --define(wxProgressDialog_Update_0, 2345). --define(wxMessageDialog_new, 2346). --define(wxMessageDialog_destruct, 2347). --define(wxPageSetupDialog_new, 2348). --define(wxPageSetupDialog_destruct, 2349). --define(wxPageSetupDialog_GetPageSetupData, 2350). --define(wxPageSetupDialog_ShowModal, 2351). --define(wxPageSetupDialogData_new_0, 2352). --define(wxPageSetupDialogData_new_1_0, 2353). --define(wxPageSetupDialogData_new_1_1, 2354). --define(wxPageSetupDialogData_destruct, 2355). --define(wxPageSetupDialogData_EnableHelp, 2356). --define(wxPageSetupDialogData_EnableMargins, 2357). --define(wxPageSetupDialogData_EnableOrientation, 2358). --define(wxPageSetupDialogData_EnablePaper, 2359). --define(wxPageSetupDialogData_EnablePrinter, 2360). --define(wxPageSetupDialogData_GetDefaultMinMargins, 2361). --define(wxPageSetupDialogData_GetEnableMargins, 2362). --define(wxPageSetupDialogData_GetEnableOrientation, 2363). --define(wxPageSetupDialogData_GetEnablePaper, 2364). --define(wxPageSetupDialogData_GetEnablePrinter, 2365). --define(wxPageSetupDialogData_GetEnableHelp, 2366). --define(wxPageSetupDialogData_GetDefaultInfo, 2367). --define(wxPageSetupDialogData_GetMarginTopLeft, 2368). --define(wxPageSetupDialogData_GetMarginBottomRight, 2369). --define(wxPageSetupDialogData_GetMinMarginTopLeft, 2370). --define(wxPageSetupDialogData_GetMinMarginBottomRight, 2371). --define(wxPageSetupDialogData_GetPaperId, 2372). --define(wxPageSetupDialogData_GetPaperSize, 2373). --define(wxPageSetupDialogData_GetPrintData, 2375). --define(wxPageSetupDialogData_IsOk, 2376). --define(wxPageSetupDialogData_SetDefaultInfo, 2377). --define(wxPageSetupDialogData_SetDefaultMinMargins, 2378). --define(wxPageSetupDialogData_SetMarginTopLeft, 2379). --define(wxPageSetupDialogData_SetMarginBottomRight, 2380). --define(wxPageSetupDialogData_SetMinMarginTopLeft, 2381). --define(wxPageSetupDialogData_SetMinMarginBottomRight, 2382). --define(wxPageSetupDialogData_SetPaperId, 2383). --define(wxPageSetupDialogData_SetPaperSize_1_1, 2384). --define(wxPageSetupDialogData_SetPaperSize_1_0, 2385). --define(wxPageSetupDialogData_SetPrintData, 2386). --define(wxPrintDialog_new_2_0, 2387). --define(wxPrintDialog_new_2_1, 2388). --define(wxPrintDialog_destruct, 2389). --define(wxPrintDialog_GetPrintDialogData, 2390). --define(wxPrintDialog_GetPrintDC, 2391). --define(wxPrintDialogData_new_0, 2392). --define(wxPrintDialogData_new_1_1, 2393). --define(wxPrintDialogData_new_1_0, 2394). --define(wxPrintDialogData_destruct, 2395). --define(wxPrintDialogData_EnableHelp, 2396). --define(wxPrintDialogData_EnablePageNumbers, 2397). --define(wxPrintDialogData_EnablePrintToFile, 2398). --define(wxPrintDialogData_EnableSelection, 2399). --define(wxPrintDialogData_GetAllPages, 2400). --define(wxPrintDialogData_GetCollate, 2401). --define(wxPrintDialogData_GetFromPage, 2402). --define(wxPrintDialogData_GetMaxPage, 2403). --define(wxPrintDialogData_GetMinPage, 2404). --define(wxPrintDialogData_GetNoCopies, 2405). --define(wxPrintDialogData_GetPrintData, 2406). --define(wxPrintDialogData_GetPrintToFile, 2407). --define(wxPrintDialogData_GetSelection, 2408). --define(wxPrintDialogData_GetToPage, 2409). --define(wxPrintDialogData_IsOk, 2410). --define(wxPrintDialogData_SetCollate, 2411). --define(wxPrintDialogData_SetFromPage, 2412). --define(wxPrintDialogData_SetMaxPage, 2413). --define(wxPrintDialogData_SetMinPage, 2414). --define(wxPrintDialogData_SetNoCopies, 2415). --define(wxPrintDialogData_SetPrintData, 2416). --define(wxPrintDialogData_SetPrintToFile, 2417). --define(wxPrintDialogData_SetSelection, 2418). --define(wxPrintDialogData_SetToPage, 2419). --define(wxPrintData_new_0, 2420). --define(wxPrintData_new_1, 2421). --define(wxPrintData_destruct, 2422). --define(wxPrintData_GetCollate, 2423). --define(wxPrintData_GetBin, 2424). --define(wxPrintData_GetColour, 2425). --define(wxPrintData_GetDuplex, 2426). --define(wxPrintData_GetNoCopies, 2427). --define(wxPrintData_GetOrientation, 2428). --define(wxPrintData_GetPaperId, 2429). --define(wxPrintData_GetPrinterName, 2430). --define(wxPrintData_GetQuality, 2431). --define(wxPrintData_IsOk, 2432). --define(wxPrintData_SetBin, 2433). --define(wxPrintData_SetCollate, 2434). --define(wxPrintData_SetColour, 2435). --define(wxPrintData_SetDuplex, 2436). --define(wxPrintData_SetNoCopies, 2437). --define(wxPrintData_SetOrientation, 2438). --define(wxPrintData_SetPaperId, 2439). --define(wxPrintData_SetPrinterName, 2440). --define(wxPrintData_SetQuality, 2441). --define(wxPrintPreview_new_2, 2444). --define(wxPrintPreview_new_3, 2445). --define(wxPrintPreview_destruct, 2447). --define(wxPrintPreview_GetCanvas, 2448). --define(wxPrintPreview_GetCurrentPage, 2449). --define(wxPrintPreview_GetFrame, 2450). --define(wxPrintPreview_GetMaxPage, 2451). --define(wxPrintPreview_GetMinPage, 2452). --define(wxPrintPreview_GetPrintout, 2453). --define(wxPrintPreview_GetPrintoutForPrinting, 2454). --define(wxPrintPreview_IsOk, 2455). --define(wxPrintPreview_PaintPage, 2456). --define(wxPrintPreview_Print, 2457). --define(wxPrintPreview_RenderPage, 2458). --define(wxPrintPreview_SetCanvas, 2459). --define(wxPrintPreview_SetCurrentPage, 2460). --define(wxPrintPreview_SetFrame, 2461). --define(wxPrintPreview_SetPrintout, 2462). --define(wxPrintPreview_SetZoom, 2463). --define(wxPreviewFrame_new, 2464). --define(wxPreviewFrame_destruct, 2465). --define(wxPreviewFrame_CreateControlBar, 2466). --define(wxPreviewFrame_CreateCanvas, 2467). --define(wxPreviewFrame_Initialize, 2468). --define(wxPreviewFrame_OnCloseWindow, 2469). --define(wxPreviewControlBar_new, 2470). --define(wxPreviewControlBar_destruct, 2471). --define(wxPreviewControlBar_CreateButtons, 2472). --define(wxPreviewControlBar_GetPrintPreview, 2473). --define(wxPreviewControlBar_GetZoomControl, 2474). --define(wxPreviewControlBar_SetZoomControl, 2475). --define(wxPrinter_new, 2477). --define(wxPrinter_CreateAbortWindow, 2478). --define(wxPrinter_GetAbort, 2479). --define(wxPrinter_GetLastError, 2480). --define(wxPrinter_GetPrintDialogData, 2481). --define(wxPrinter_Print, 2482). --define(wxPrinter_PrintDialog, 2483). --define(wxPrinter_ReportError, 2484). --define(wxPrinter_Setup, 2485). --define(wxPrinter_destroy, 2486). --define(wxXmlResource_new_1, 2487). --define(wxXmlResource_new_2, 2488). --define(wxXmlResource_destruct, 2489). --define(wxXmlResource_AttachUnknownControl, 2490). --define(wxXmlResource_ClearHandlers, 2491). --define(wxXmlResource_CompareVersion, 2492). --define(wxXmlResource_Get, 2493). --define(wxXmlResource_GetFlags, 2494). --define(wxXmlResource_GetVersion, 2495). --define(wxXmlResource_GetXRCID, 2496). --define(wxXmlResource_InitAllHandlers, 2497). --define(wxXmlResource_Load, 2498). --define(wxXmlResource_LoadBitmap, 2499). --define(wxXmlResource_LoadDialog_2, 2500). --define(wxXmlResource_LoadDialog_3, 2501). --define(wxXmlResource_LoadFrame_2, 2502). --define(wxXmlResource_LoadFrame_3, 2503). --define(wxXmlResource_LoadIcon, 2504). --define(wxXmlResource_LoadMenu, 2505). --define(wxXmlResource_LoadMenuBar_2, 2506). --define(wxXmlResource_LoadMenuBar_1, 2507). --define(wxXmlResource_LoadPanel_2, 2508). --define(wxXmlResource_LoadPanel_3, 2509). --define(wxXmlResource_LoadToolBar, 2510). --define(wxXmlResource_Set, 2511). --define(wxXmlResource_SetFlags, 2512). --define(wxXmlResource_Unload, 2513). --define(wxXmlResource_xrcctrl, 2514). --define(wxHtmlEasyPrinting_new, 2515). --define(wxHtmlEasyPrinting_destruct, 2516). --define(wxHtmlEasyPrinting_GetPrintData, 2517). --define(wxHtmlEasyPrinting_GetPageSetupData, 2518). --define(wxHtmlEasyPrinting_PreviewFile, 2519). --define(wxHtmlEasyPrinting_PreviewText, 2520). --define(wxHtmlEasyPrinting_PrintFile, 2521). --define(wxHtmlEasyPrinting_PrintText, 2522). --define(wxHtmlEasyPrinting_PageSetup, 2523). --define(wxHtmlEasyPrinting_SetFonts, 2524). --define(wxHtmlEasyPrinting_SetHeader, 2525). --define(wxHtmlEasyPrinting_SetFooter, 2526). --define(wxGLCanvas_new_2, 2528). --define(wxGLCanvas_new_3_1, 2529). --define(wxGLCanvas_new_3_0, 2530). --define(wxGLCanvas_GetContext, 2531). --define(wxGLCanvas_SetCurrent, 2533). --define(wxGLCanvas_SwapBuffers, 2534). --define(wxGLCanvas_destroy, 2535). --define(wxAuiManager_new, 2536). --define(wxAuiManager_destruct, 2537). --define(wxAuiManager_AddPane_2_1, 2538). --define(wxAuiManager_AddPane_3, 2539). --define(wxAuiManager_AddPane_2_0, 2540). --define(wxAuiManager_DetachPane, 2541). --define(wxAuiManager_GetAllPanes, 2542). --define(wxAuiManager_GetArtProvider, 2543). --define(wxAuiManager_GetDockSizeConstraint, 2544). --define(wxAuiManager_GetFlags, 2545). --define(wxAuiManager_GetManagedWindow, 2546). --define(wxAuiManager_GetManager, 2547). --define(wxAuiManager_GetPane_1_1, 2548). --define(wxAuiManager_GetPane_1_0, 2549). --define(wxAuiManager_HideHint, 2550). --define(wxAuiManager_InsertPane, 2551). --define(wxAuiManager_LoadPaneInfo, 2552). --define(wxAuiManager_LoadPerspective, 2553). --define(wxAuiManager_SavePaneInfo, 2554). --define(wxAuiManager_SavePerspective, 2555). --define(wxAuiManager_SetArtProvider, 2556). --define(wxAuiManager_SetDockSizeConstraint, 2557). --define(wxAuiManager_SetFlags, 2558). --define(wxAuiManager_SetManagedWindow, 2559). --define(wxAuiManager_ShowHint, 2560). --define(wxAuiManager_UnInit, 2561). --define(wxAuiManager_Update, 2562). --define(wxAuiPaneInfo_new_0, 2563). --define(wxAuiPaneInfo_new_1, 2564). --define(wxAuiPaneInfo_destruct, 2565). --define(wxAuiPaneInfo_BestSize_1, 2566). --define(wxAuiPaneInfo_BestSize_2, 2567). --define(wxAuiPaneInfo_Bottom, 2568). --define(wxAuiPaneInfo_BottomDockable, 2569). --define(wxAuiPaneInfo_Caption, 2570). --define(wxAuiPaneInfo_CaptionVisible, 2571). --define(wxAuiPaneInfo_Centre, 2572). --define(wxAuiPaneInfo_CentrePane, 2573). --define(wxAuiPaneInfo_CloseButton, 2574). --define(wxAuiPaneInfo_DefaultPane, 2575). --define(wxAuiPaneInfo_DestroyOnClose, 2576). --define(wxAuiPaneInfo_Direction, 2577). --define(wxAuiPaneInfo_Dock, 2578). --define(wxAuiPaneInfo_Dockable, 2579). --define(wxAuiPaneInfo_Fixed, 2580). --define(wxAuiPaneInfo_Float, 2581). --define(wxAuiPaneInfo_Floatable, 2582). --define(wxAuiPaneInfo_FloatingPosition_1, 2583). --define(wxAuiPaneInfo_FloatingPosition_2, 2584). --define(wxAuiPaneInfo_FloatingSize_1, 2585). --define(wxAuiPaneInfo_FloatingSize_2, 2586). --define(wxAuiPaneInfo_Gripper, 2587). --define(wxAuiPaneInfo_GripperTop, 2588). --define(wxAuiPaneInfo_HasBorder, 2589). --define(wxAuiPaneInfo_HasCaption, 2590). --define(wxAuiPaneInfo_HasCloseButton, 2591). --define(wxAuiPaneInfo_HasFlag, 2592). --define(wxAuiPaneInfo_HasGripper, 2593). --define(wxAuiPaneInfo_HasGripperTop, 2594). --define(wxAuiPaneInfo_HasMaximizeButton, 2595). --define(wxAuiPaneInfo_HasMinimizeButton, 2596). --define(wxAuiPaneInfo_HasPinButton, 2597). --define(wxAuiPaneInfo_Hide, 2598). --define(wxAuiPaneInfo_IsBottomDockable, 2599). --define(wxAuiPaneInfo_IsDocked, 2600). --define(wxAuiPaneInfo_IsFixed, 2601). --define(wxAuiPaneInfo_IsFloatable, 2602). --define(wxAuiPaneInfo_IsFloating, 2603). --define(wxAuiPaneInfo_IsLeftDockable, 2604). --define(wxAuiPaneInfo_IsMovable, 2605). --define(wxAuiPaneInfo_IsOk, 2606). --define(wxAuiPaneInfo_IsResizable, 2607). --define(wxAuiPaneInfo_IsRightDockable, 2608). --define(wxAuiPaneInfo_IsShown, 2609). --define(wxAuiPaneInfo_IsToolbar, 2610). --define(wxAuiPaneInfo_IsTopDockable, 2611). --define(wxAuiPaneInfo_Layer, 2612). --define(wxAuiPaneInfo_Left, 2613). --define(wxAuiPaneInfo_LeftDockable, 2614). --define(wxAuiPaneInfo_MaxSize_1, 2615). --define(wxAuiPaneInfo_MaxSize_2, 2616). --define(wxAuiPaneInfo_MaximizeButton, 2617). --define(wxAuiPaneInfo_MinSize_1, 2618). --define(wxAuiPaneInfo_MinSize_2, 2619). --define(wxAuiPaneInfo_MinimizeButton, 2620). --define(wxAuiPaneInfo_Movable, 2621). --define(wxAuiPaneInfo_Name, 2622). --define(wxAuiPaneInfo_PaneBorder, 2623). --define(wxAuiPaneInfo_PinButton, 2624). --define(wxAuiPaneInfo_Position, 2625). --define(wxAuiPaneInfo_Resizable, 2626). --define(wxAuiPaneInfo_Right, 2627). --define(wxAuiPaneInfo_RightDockable, 2628). --define(wxAuiPaneInfo_Row, 2629). --define(wxAuiPaneInfo_SafeSet, 2630). --define(wxAuiPaneInfo_SetFlag, 2631). --define(wxAuiPaneInfo_Show, 2632). --define(wxAuiPaneInfo_ToolbarPane, 2633). --define(wxAuiPaneInfo_Top, 2634). --define(wxAuiPaneInfo_TopDockable, 2635). --define(wxAuiPaneInfo_Window, 2636). --define(wxAuiNotebook_new_0, 2637). --define(wxAuiNotebook_new_2, 2638). --define(wxAuiNotebook_AddPage, 2639). --define(wxAuiNotebook_Create, 2640). --define(wxAuiNotebook_DeletePage, 2641). --define(wxAuiNotebook_GetArtProvider, 2642). --define(wxAuiNotebook_GetPage, 2643). --define(wxAuiNotebook_GetPageBitmap, 2644). --define(wxAuiNotebook_GetPageCount, 2645). --define(wxAuiNotebook_GetPageIndex, 2646). --define(wxAuiNotebook_GetPageText, 2647). --define(wxAuiNotebook_GetSelection, 2648). --define(wxAuiNotebook_InsertPage, 2649). --define(wxAuiNotebook_RemovePage, 2650). --define(wxAuiNotebook_SetArtProvider, 2651). --define(wxAuiNotebook_SetFont, 2652). --define(wxAuiNotebook_SetPageBitmap, 2653). --define(wxAuiNotebook_SetPageText, 2654). --define(wxAuiNotebook_SetSelection, 2655). --define(wxAuiNotebook_SetTabCtrlHeight, 2656). --define(wxAuiNotebook_SetUniformBitmapSize, 2657). --define(wxAuiNotebook_destroy, 2658). --define(wxMDIParentFrame_new_0, 2659). --define(wxMDIParentFrame_new_4, 2660). --define(wxMDIParentFrame_destruct, 2661). --define(wxMDIParentFrame_ActivateNext, 2662). --define(wxMDIParentFrame_ActivatePrevious, 2663). --define(wxMDIParentFrame_ArrangeIcons, 2664). --define(wxMDIParentFrame_Cascade, 2665). --define(wxMDIParentFrame_Create, 2666). --define(wxMDIParentFrame_GetActiveChild, 2667). --define(wxMDIParentFrame_GetClientWindow, 2668). --define(wxMDIParentFrame_Tile, 2669). --define(wxMDIChildFrame_new_0, 2670). --define(wxMDIChildFrame_new_4, 2671). --define(wxMDIChildFrame_destruct, 2672). --define(wxMDIChildFrame_Activate, 2673). --define(wxMDIChildFrame_Create, 2674). --define(wxMDIChildFrame_Maximize, 2675). --define(wxMDIChildFrame_Restore, 2676). --define(wxMDIClientWindow_new_0, 2677). --define(wxMDIClientWindow_new_2, 2678). --define(wxMDIClientWindow_destruct, 2679). --define(wxMDIClientWindow_CreateClient, 2680). --define(wxLayoutAlgorithm_new, 2681). --define(wxLayoutAlgorithm_LayoutFrame, 2682). --define(wxLayoutAlgorithm_LayoutMDIFrame, 2683). --define(wxLayoutAlgorithm_LayoutWindow, 2684). --define(wxLayoutAlgorithm_destroy, 2685). --define(wxEvent_GetId, 2686). --define(wxEvent_GetSkipped, 2687). --define(wxEvent_GetTimestamp, 2688). --define(wxEvent_IsCommandEvent, 2689). --define(wxEvent_ResumePropagation, 2690). --define(wxEvent_ShouldPropagate, 2691). --define(wxEvent_Skip, 2692). --define(wxEvent_StopPropagation, 2693). --define(wxCommandEvent_getClientData, 2694). --define(wxCommandEvent_GetExtraLong, 2695). --define(wxCommandEvent_GetInt, 2696). --define(wxCommandEvent_GetSelection, 2697). --define(wxCommandEvent_GetString, 2698). --define(wxCommandEvent_IsChecked, 2699). --define(wxCommandEvent_IsSelection, 2700). --define(wxCommandEvent_SetInt, 2701). --define(wxCommandEvent_SetString, 2702). --define(wxScrollEvent_GetOrientation, 2703). --define(wxScrollEvent_GetPosition, 2704). --define(wxScrollWinEvent_GetOrientation, 2705). --define(wxScrollWinEvent_GetPosition, 2706). --define(wxMouseEvent_AltDown, 2707). --define(wxMouseEvent_Button, 2708). --define(wxMouseEvent_ButtonDClick, 2709). --define(wxMouseEvent_ButtonDown, 2710). --define(wxMouseEvent_ButtonUp, 2711). --define(wxMouseEvent_CmdDown, 2712). --define(wxMouseEvent_ControlDown, 2713). --define(wxMouseEvent_Dragging, 2714). --define(wxMouseEvent_Entering, 2715). --define(wxMouseEvent_GetButton, 2716). --define(wxMouseEvent_GetPosition, 2719). --define(wxMouseEvent_GetLogicalPosition, 2720). --define(wxMouseEvent_GetLinesPerAction, 2721). --define(wxMouseEvent_GetWheelRotation, 2722). --define(wxMouseEvent_GetWheelDelta, 2723). --define(wxMouseEvent_GetX, 2724). --define(wxMouseEvent_GetY, 2725). --define(wxMouseEvent_IsButton, 2726). --define(wxMouseEvent_IsPageScroll, 2727). --define(wxMouseEvent_Leaving, 2728). --define(wxMouseEvent_LeftDClick, 2729). --define(wxMouseEvent_LeftDown, 2730). --define(wxMouseEvent_LeftIsDown, 2731). --define(wxMouseEvent_LeftUp, 2732). --define(wxMouseEvent_MetaDown, 2733). --define(wxMouseEvent_MiddleDClick, 2734). --define(wxMouseEvent_MiddleDown, 2735). --define(wxMouseEvent_MiddleIsDown, 2736). --define(wxMouseEvent_MiddleUp, 2737). --define(wxMouseEvent_Moving, 2738). --define(wxMouseEvent_RightDClick, 2739). --define(wxMouseEvent_RightDown, 2740). --define(wxMouseEvent_RightIsDown, 2741). --define(wxMouseEvent_RightUp, 2742). --define(wxMouseEvent_ShiftDown, 2743). --define(wxSetCursorEvent_GetCursor, 2744). --define(wxSetCursorEvent_GetX, 2745). --define(wxSetCursorEvent_GetY, 2746). --define(wxSetCursorEvent_HasCursor, 2747). --define(wxSetCursorEvent_SetCursor, 2748). --define(wxKeyEvent_AltDown, 2749). --define(wxKeyEvent_CmdDown, 2750). --define(wxKeyEvent_ControlDown, 2751). --define(wxKeyEvent_GetKeyCode, 2752). --define(wxKeyEvent_GetModifiers, 2753). --define(wxKeyEvent_GetPosition, 2756). --define(wxKeyEvent_GetRawKeyCode, 2757). --define(wxKeyEvent_GetRawKeyFlags, 2758). --define(wxKeyEvent_GetUnicodeKey, 2759). --define(wxKeyEvent_GetX, 2760). --define(wxKeyEvent_GetY, 2761). --define(wxKeyEvent_HasModifiers, 2762). --define(wxKeyEvent_MetaDown, 2763). --define(wxKeyEvent_ShiftDown, 2764). --define(wxSizeEvent_GetSize, 2765). --define(wxMoveEvent_GetPosition, 2766). --define(wxEraseEvent_GetDC, 2767). --define(wxFocusEvent_GetWindow, 2768). --define(wxChildFocusEvent_GetWindow, 2769). --define(wxMenuEvent_GetMenu, 2770). --define(wxMenuEvent_GetMenuId, 2771). --define(wxMenuEvent_IsPopup, 2772). --define(wxCloseEvent_CanVeto, 2773). --define(wxCloseEvent_GetLoggingOff, 2774). --define(wxCloseEvent_SetCanVeto, 2775). --define(wxCloseEvent_SetLoggingOff, 2776). --define(wxCloseEvent_Veto, 2777). --define(wxShowEvent_SetShow, 2778). --define(wxShowEvent_GetShow, 2779). --define(wxIconizeEvent_Iconized, 2780). --define(wxJoystickEvent_ButtonDown, 2781). --define(wxJoystickEvent_ButtonIsDown, 2782). --define(wxJoystickEvent_ButtonUp, 2783). --define(wxJoystickEvent_GetButtonChange, 2784). --define(wxJoystickEvent_GetButtonState, 2785). --define(wxJoystickEvent_GetJoystick, 2786). --define(wxJoystickEvent_GetPosition, 2787). --define(wxJoystickEvent_GetZPosition, 2788). --define(wxJoystickEvent_IsButton, 2789). --define(wxJoystickEvent_IsMove, 2790). --define(wxJoystickEvent_IsZMove, 2791). --define(wxUpdateUIEvent_CanUpdate, 2792). --define(wxUpdateUIEvent_Check, 2793). --define(wxUpdateUIEvent_Enable, 2794). --define(wxUpdateUIEvent_Show, 2795). --define(wxUpdateUIEvent_GetChecked, 2796). --define(wxUpdateUIEvent_GetEnabled, 2797). --define(wxUpdateUIEvent_GetShown, 2798). --define(wxUpdateUIEvent_GetSetChecked, 2799). --define(wxUpdateUIEvent_GetSetEnabled, 2800). --define(wxUpdateUIEvent_GetSetShown, 2801). --define(wxUpdateUIEvent_GetSetText, 2802). --define(wxUpdateUIEvent_GetText, 2803). --define(wxUpdateUIEvent_GetMode, 2804). --define(wxUpdateUIEvent_GetUpdateInterval, 2805). --define(wxUpdateUIEvent_ResetUpdateTime, 2806). --define(wxUpdateUIEvent_SetMode, 2807). --define(wxUpdateUIEvent_SetText, 2808). --define(wxUpdateUIEvent_SetUpdateInterval, 2809). --define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2810). --define(wxPaletteChangedEvent_SetChangedWindow, 2811). --define(wxPaletteChangedEvent_GetChangedWindow, 2812). --define(wxQueryNewPaletteEvent_SetPaletteRealized, 2813). --define(wxQueryNewPaletteEvent_GetPaletteRealized, 2814). --define(wxNavigationKeyEvent_GetDirection, 2815). --define(wxNavigationKeyEvent_SetDirection, 2816). --define(wxNavigationKeyEvent_IsWindowChange, 2817). --define(wxNavigationKeyEvent_SetWindowChange, 2818). --define(wxNavigationKeyEvent_IsFromTab, 2819). --define(wxNavigationKeyEvent_SetFromTab, 2820). --define(wxNavigationKeyEvent_GetCurrentFocus, 2821). --define(wxNavigationKeyEvent_SetCurrentFocus, 2822). --define(wxHelpEvent_GetOrigin, 2823). --define(wxHelpEvent_GetPosition, 2824). --define(wxHelpEvent_SetOrigin, 2825). --define(wxHelpEvent_SetPosition, 2826). --define(wxContextMenuEvent_GetPosition, 2827). --define(wxContextMenuEvent_SetPosition, 2828). --define(wxIdleEvent_CanSend, 2829). --define(wxIdleEvent_GetMode, 2830). --define(wxIdleEvent_RequestMore, 2831). --define(wxIdleEvent_MoreRequested, 2832). --define(wxIdleEvent_SetMode, 2833). --define(wxGridEvent_AltDown, 2834). --define(wxGridEvent_ControlDown, 2835). --define(wxGridEvent_GetCol, 2836). --define(wxGridEvent_GetPosition, 2837). --define(wxGridEvent_GetRow, 2838). --define(wxGridEvent_MetaDown, 2839). --define(wxGridEvent_Selecting, 2840). --define(wxGridEvent_ShiftDown, 2841). --define(wxNotifyEvent_Allow, 2842). --define(wxNotifyEvent_IsAllowed, 2843). --define(wxNotifyEvent_Veto, 2844). --define(wxSashEvent_GetEdge, 2845). --define(wxSashEvent_GetDragRect, 2846). --define(wxSashEvent_GetDragStatus, 2847). --define(wxListEvent_GetCacheFrom, 2848). --define(wxListEvent_GetCacheTo, 2849). --define(wxListEvent_GetKeyCode, 2850). --define(wxListEvent_GetIndex, 2851). --define(wxListEvent_GetColumn, 2852). --define(wxListEvent_GetPoint, 2853). --define(wxListEvent_GetLabel, 2854). --define(wxListEvent_GetText, 2855). --define(wxListEvent_GetImage, 2856). --define(wxListEvent_GetData, 2857). --define(wxListEvent_GetMask, 2858). --define(wxListEvent_GetItem, 2859). --define(wxListEvent_IsEditCancelled, 2860). --define(wxDateEvent_GetDate, 2861). --define(wxCalendarEvent_GetWeekDay, 2862). --define(wxFileDirPickerEvent_GetPath, 2863). --define(wxColourPickerEvent_GetColour, 2864). --define(wxFontPickerEvent_GetFont, 2865). --define(wxStyledTextEvent_GetPosition, 2866). --define(wxStyledTextEvent_GetKey, 2867). --define(wxStyledTextEvent_GetModifiers, 2868). --define(wxStyledTextEvent_GetModificationType, 2869). --define(wxStyledTextEvent_GetText, 2870). --define(wxStyledTextEvent_GetLength, 2871). --define(wxStyledTextEvent_GetLinesAdded, 2872). --define(wxStyledTextEvent_GetLine, 2873). --define(wxStyledTextEvent_GetFoldLevelNow, 2874). --define(wxStyledTextEvent_GetFoldLevelPrev, 2875). --define(wxStyledTextEvent_GetMargin, 2876). --define(wxStyledTextEvent_GetMessage, 2877). --define(wxStyledTextEvent_GetWParam, 2878). --define(wxStyledTextEvent_GetLParam, 2879). --define(wxStyledTextEvent_GetListType, 2880). --define(wxStyledTextEvent_GetX, 2881). --define(wxStyledTextEvent_GetY, 2882). --define(wxStyledTextEvent_GetDragText, 2883). --define(wxStyledTextEvent_GetDragAllowMove, 2884). --define(wxStyledTextEvent_GetDragResult, 2885). --define(wxStyledTextEvent_GetShift, 2886). --define(wxStyledTextEvent_GetControl, 2887). --define(wxStyledTextEvent_GetAlt, 2888). --define(utils_wxGetKeyState, 2889). --define(utils_wxGetMousePosition, 2890). --define(utils_wxGetMouseState, 2891). --define(utils_wxSetDetectableAutoRepeat, 2892). --define(utils_wxBell, 2893). --define(utils_wxFindMenuItemId, 2894). --define(utils_wxGenericFindWindowAtPoint, 2895). --define(utils_wxFindWindowAtPoint, 2896). --define(utils_wxBeginBusyCursor, 2897). --define(utils_wxEndBusyCursor, 2898). --define(utils_wxIsBusy, 2899). --define(utils_wxShutdown, 2900). --define(utils_wxShell, 2901). --define(utils_wxLaunchDefaultBrowser, 2902). --define(utils_wxGetEmailAddress, 2903). --define(utils_wxGetUserId, 2904). --define(utils_wxGetHomeDir, 2905). --define(utils_wxNewId, 2906). --define(utils_wxRegisterId, 2907). --define(utils_wxGetCurrentId, 2908). --define(utils_wxGetOsDescription, 2909). --define(utils_wxIsPlatformLittleEndian, 2910). --define(utils_wxIsPlatform64Bit, 2911). --define(wxPrintout_new, 2912). --define(wxPrintout_destruct, 2913). --define(wxPrintout_GetDC, 2914). --define(wxPrintout_GetPageSizeMM, 2915). --define(wxPrintout_GetPageSizePixels, 2916). --define(wxPrintout_GetPaperRectPixels, 2917). --define(wxPrintout_GetPPIPrinter, 2918). --define(wxPrintout_GetPPIScreen, 2919). --define(wxPrintout_GetTitle, 2920). --define(wxPrintout_IsPreview, 2921). --define(wxPrintout_FitThisSizeToPaper, 2922). --define(wxPrintout_FitThisSizeToPage, 2923). --define(wxPrintout_FitThisSizeToPageMargins, 2924). --define(wxPrintout_MapScreenSizeToPaper, 2925). --define(wxPrintout_MapScreenSizeToPage, 2926). --define(wxPrintout_MapScreenSizeToPageMargins, 2927). --define(wxPrintout_MapScreenSizeToDevice, 2928). --define(wxPrintout_GetLogicalPaperRect, 2929). --define(wxPrintout_GetLogicalPageRect, 2930). --define(wxPrintout_GetLogicalPageMarginsRect, 2931). --define(wxPrintout_SetLogicalOrigin, 2932). --define(wxPrintout_OffsetLogicalOrigin, 2933). --define(wxStyledTextCtrl_new_2, 2934). --define(wxStyledTextCtrl_new_0, 2935). --define(wxStyledTextCtrl_destruct, 2936). --define(wxStyledTextCtrl_Create, 2937). --define(wxStyledTextCtrl_AddText, 2938). --define(wxStyledTextCtrl_AddStyledText, 2939). --define(wxStyledTextCtrl_InsertText, 2940). --define(wxStyledTextCtrl_ClearAll, 2941). --define(wxStyledTextCtrl_ClearDocumentStyle, 2942). --define(wxStyledTextCtrl_GetLength, 2943). --define(wxStyledTextCtrl_GetCharAt, 2944). --define(wxStyledTextCtrl_GetCurrentPos, 2945). --define(wxStyledTextCtrl_GetAnchor, 2946). --define(wxStyledTextCtrl_GetStyleAt, 2947). --define(wxStyledTextCtrl_Redo, 2948). --define(wxStyledTextCtrl_SetUndoCollection, 2949). --define(wxStyledTextCtrl_SelectAll, 2950). --define(wxStyledTextCtrl_SetSavePoint, 2951). --define(wxStyledTextCtrl_GetStyledText, 2952). --define(wxStyledTextCtrl_CanRedo, 2953). --define(wxStyledTextCtrl_MarkerLineFromHandle, 2954). --define(wxStyledTextCtrl_MarkerDeleteHandle, 2955). --define(wxStyledTextCtrl_GetUndoCollection, 2956). --define(wxStyledTextCtrl_GetViewWhiteSpace, 2957). --define(wxStyledTextCtrl_SetViewWhiteSpace, 2958). --define(wxStyledTextCtrl_PositionFromPoint, 2959). --define(wxStyledTextCtrl_PositionFromPointClose, 2960). --define(wxStyledTextCtrl_GotoLine, 2961). --define(wxStyledTextCtrl_GotoPos, 2962). --define(wxStyledTextCtrl_SetAnchor, 2963). --define(wxStyledTextCtrl_GetCurLine, 2964). --define(wxStyledTextCtrl_GetEndStyled, 2965). --define(wxStyledTextCtrl_ConvertEOLs, 2966). --define(wxStyledTextCtrl_GetEOLMode, 2967). --define(wxStyledTextCtrl_SetEOLMode, 2968). --define(wxStyledTextCtrl_StartStyling, 2969). --define(wxStyledTextCtrl_SetStyling, 2970). --define(wxStyledTextCtrl_GetBufferedDraw, 2971). --define(wxStyledTextCtrl_SetBufferedDraw, 2972). --define(wxStyledTextCtrl_SetTabWidth, 2973). --define(wxStyledTextCtrl_GetTabWidth, 2974). --define(wxStyledTextCtrl_SetCodePage, 2975). --define(wxStyledTextCtrl_MarkerDefine, 2976). --define(wxStyledTextCtrl_MarkerSetForeground, 2977). --define(wxStyledTextCtrl_MarkerSetBackground, 2978). --define(wxStyledTextCtrl_MarkerAdd, 2979). --define(wxStyledTextCtrl_MarkerDelete, 2980). --define(wxStyledTextCtrl_MarkerDeleteAll, 2981). --define(wxStyledTextCtrl_MarkerGet, 2982). --define(wxStyledTextCtrl_MarkerNext, 2983). --define(wxStyledTextCtrl_MarkerPrevious, 2984). --define(wxStyledTextCtrl_MarkerDefineBitmap, 2985). --define(wxStyledTextCtrl_MarkerAddSet, 2986). --define(wxStyledTextCtrl_MarkerSetAlpha, 2987). --define(wxStyledTextCtrl_SetMarginType, 2988). --define(wxStyledTextCtrl_GetMarginType, 2989). --define(wxStyledTextCtrl_SetMarginWidth, 2990). --define(wxStyledTextCtrl_GetMarginWidth, 2991). --define(wxStyledTextCtrl_SetMarginMask, 2992). --define(wxStyledTextCtrl_GetMarginMask, 2993). --define(wxStyledTextCtrl_SetMarginSensitive, 2994). --define(wxStyledTextCtrl_GetMarginSensitive, 2995). --define(wxStyledTextCtrl_StyleClearAll, 2996). --define(wxStyledTextCtrl_StyleSetForeground, 2997). --define(wxStyledTextCtrl_StyleSetBackground, 2998). --define(wxStyledTextCtrl_StyleSetBold, 2999). --define(wxStyledTextCtrl_StyleSetItalic, 3000). --define(wxStyledTextCtrl_StyleSetSize, 3001). --define(wxStyledTextCtrl_StyleSetFaceName, 3002). --define(wxStyledTextCtrl_StyleSetEOLFilled, 3003). --define(wxStyledTextCtrl_StyleResetDefault, 3004). --define(wxStyledTextCtrl_StyleSetUnderline, 3005). --define(wxStyledTextCtrl_StyleSetCase, 3006). --define(wxStyledTextCtrl_StyleSetHotSpot, 3007). --define(wxStyledTextCtrl_SetSelForeground, 3008). --define(wxStyledTextCtrl_SetSelBackground, 3009). --define(wxStyledTextCtrl_GetSelAlpha, 3010). --define(wxStyledTextCtrl_SetSelAlpha, 3011). --define(wxStyledTextCtrl_SetCaretForeground, 3012). --define(wxStyledTextCtrl_CmdKeyAssign, 3013). --define(wxStyledTextCtrl_CmdKeyClear, 3014). --define(wxStyledTextCtrl_CmdKeyClearAll, 3015). --define(wxStyledTextCtrl_SetStyleBytes, 3016). --define(wxStyledTextCtrl_StyleSetVisible, 3017). --define(wxStyledTextCtrl_GetCaretPeriod, 3018). --define(wxStyledTextCtrl_SetCaretPeriod, 3019). --define(wxStyledTextCtrl_SetWordChars, 3020). --define(wxStyledTextCtrl_BeginUndoAction, 3021). --define(wxStyledTextCtrl_EndUndoAction, 3022). --define(wxStyledTextCtrl_IndicatorSetStyle, 3023). --define(wxStyledTextCtrl_IndicatorGetStyle, 3024). --define(wxStyledTextCtrl_IndicatorSetForeground, 3025). --define(wxStyledTextCtrl_IndicatorGetForeground, 3026). --define(wxStyledTextCtrl_SetWhitespaceForeground, 3027). --define(wxStyledTextCtrl_SetWhitespaceBackground, 3028). --define(wxStyledTextCtrl_GetStyleBits, 3029). --define(wxStyledTextCtrl_SetLineState, 3030). --define(wxStyledTextCtrl_GetLineState, 3031). --define(wxStyledTextCtrl_GetMaxLineState, 3032). --define(wxStyledTextCtrl_GetCaretLineVisible, 3033). --define(wxStyledTextCtrl_SetCaretLineVisible, 3034). --define(wxStyledTextCtrl_GetCaretLineBackground, 3035). --define(wxStyledTextCtrl_SetCaretLineBackground, 3036). --define(wxStyledTextCtrl_AutoCompShow, 3037). --define(wxStyledTextCtrl_AutoCompCancel, 3038). --define(wxStyledTextCtrl_AutoCompActive, 3039). --define(wxStyledTextCtrl_AutoCompPosStart, 3040). --define(wxStyledTextCtrl_AutoCompComplete, 3041). --define(wxStyledTextCtrl_AutoCompStops, 3042). --define(wxStyledTextCtrl_AutoCompSetSeparator, 3043). --define(wxStyledTextCtrl_AutoCompGetSeparator, 3044). --define(wxStyledTextCtrl_AutoCompSelect, 3045). --define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3046). --define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3047). --define(wxStyledTextCtrl_AutoCompSetFillUps, 3048). --define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3049). --define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3050). --define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3051). --define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3052). --define(wxStyledTextCtrl_UserListShow, 3053). --define(wxStyledTextCtrl_AutoCompSetAutoHide, 3054). --define(wxStyledTextCtrl_AutoCompGetAutoHide, 3055). --define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3056). --define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3057). --define(wxStyledTextCtrl_RegisterImage, 3058). --define(wxStyledTextCtrl_ClearRegisteredImages, 3059). --define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3060). --define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3061). --define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3062). --define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3063). --define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3064). --define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3065). --define(wxStyledTextCtrl_SetIndent, 3066). --define(wxStyledTextCtrl_GetIndent, 3067). --define(wxStyledTextCtrl_SetUseTabs, 3068). --define(wxStyledTextCtrl_GetUseTabs, 3069). --define(wxStyledTextCtrl_SetLineIndentation, 3070). --define(wxStyledTextCtrl_GetLineIndentation, 3071). --define(wxStyledTextCtrl_GetLineIndentPosition, 3072). --define(wxStyledTextCtrl_GetColumn, 3073). --define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3074). --define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3075). --define(wxStyledTextCtrl_SetIndentationGuides, 3076). --define(wxStyledTextCtrl_GetIndentationGuides, 3077). --define(wxStyledTextCtrl_SetHighlightGuide, 3078). --define(wxStyledTextCtrl_GetHighlightGuide, 3079). --define(wxStyledTextCtrl_GetLineEndPosition, 3080). --define(wxStyledTextCtrl_GetCodePage, 3081). --define(wxStyledTextCtrl_GetCaretForeground, 3082). --define(wxStyledTextCtrl_GetReadOnly, 3083). --define(wxStyledTextCtrl_SetCurrentPos, 3084). --define(wxStyledTextCtrl_SetSelectionStart, 3085). --define(wxStyledTextCtrl_GetSelectionStart, 3086). --define(wxStyledTextCtrl_SetSelectionEnd, 3087). --define(wxStyledTextCtrl_GetSelectionEnd, 3088). --define(wxStyledTextCtrl_SetPrintMagnification, 3089). --define(wxStyledTextCtrl_GetPrintMagnification, 3090). --define(wxStyledTextCtrl_SetPrintColourMode, 3091). --define(wxStyledTextCtrl_GetPrintColourMode, 3092). --define(wxStyledTextCtrl_FindText, 3093). --define(wxStyledTextCtrl_FormatRange, 3094). --define(wxStyledTextCtrl_GetFirstVisibleLine, 3095). --define(wxStyledTextCtrl_GetLine, 3096). --define(wxStyledTextCtrl_GetLineCount, 3097). --define(wxStyledTextCtrl_SetMarginLeft, 3098). --define(wxStyledTextCtrl_GetMarginLeft, 3099). --define(wxStyledTextCtrl_SetMarginRight, 3100). --define(wxStyledTextCtrl_GetMarginRight, 3101). --define(wxStyledTextCtrl_GetModify, 3102). --define(wxStyledTextCtrl_SetSelection, 3103). --define(wxStyledTextCtrl_GetSelectedText, 3104). --define(wxStyledTextCtrl_GetTextRange, 3105). --define(wxStyledTextCtrl_HideSelection, 3106). --define(wxStyledTextCtrl_LineFromPosition, 3107). --define(wxStyledTextCtrl_PositionFromLine, 3108). --define(wxStyledTextCtrl_LineScroll, 3109). --define(wxStyledTextCtrl_EnsureCaretVisible, 3110). --define(wxStyledTextCtrl_ReplaceSelection, 3111). --define(wxStyledTextCtrl_SetReadOnly, 3112). --define(wxStyledTextCtrl_CanPaste, 3113). --define(wxStyledTextCtrl_CanUndo, 3114). --define(wxStyledTextCtrl_EmptyUndoBuffer, 3115). --define(wxStyledTextCtrl_Undo, 3116). --define(wxStyledTextCtrl_Cut, 3117). --define(wxStyledTextCtrl_Copy, 3118). --define(wxStyledTextCtrl_Paste, 3119). --define(wxStyledTextCtrl_Clear, 3120). --define(wxStyledTextCtrl_SetText, 3121). --define(wxStyledTextCtrl_GetText, 3122). --define(wxStyledTextCtrl_GetTextLength, 3123). --define(wxStyledTextCtrl_GetOvertype, 3124). --define(wxStyledTextCtrl_SetCaretWidth, 3125). --define(wxStyledTextCtrl_GetCaretWidth, 3126). --define(wxStyledTextCtrl_SetTargetStart, 3127). --define(wxStyledTextCtrl_GetTargetStart, 3128). --define(wxStyledTextCtrl_SetTargetEnd, 3129). --define(wxStyledTextCtrl_GetTargetEnd, 3130). --define(wxStyledTextCtrl_ReplaceTarget, 3131). --define(wxStyledTextCtrl_SearchInTarget, 3132). --define(wxStyledTextCtrl_SetSearchFlags, 3133). --define(wxStyledTextCtrl_GetSearchFlags, 3134). --define(wxStyledTextCtrl_CallTipShow, 3135). --define(wxStyledTextCtrl_CallTipCancel, 3136). --define(wxStyledTextCtrl_CallTipActive, 3137). --define(wxStyledTextCtrl_CallTipPosAtStart, 3138). --define(wxStyledTextCtrl_CallTipSetHighlight, 3139). --define(wxStyledTextCtrl_CallTipSetBackground, 3140). --define(wxStyledTextCtrl_CallTipSetForeground, 3141). --define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3142). --define(wxStyledTextCtrl_CallTipUseStyle, 3143). --define(wxStyledTextCtrl_VisibleFromDocLine, 3144). --define(wxStyledTextCtrl_DocLineFromVisible, 3145). --define(wxStyledTextCtrl_WrapCount, 3146). --define(wxStyledTextCtrl_SetFoldLevel, 3147). --define(wxStyledTextCtrl_GetFoldLevel, 3148). --define(wxStyledTextCtrl_GetLastChild, 3149). --define(wxStyledTextCtrl_GetFoldParent, 3150). --define(wxStyledTextCtrl_ShowLines, 3151). --define(wxStyledTextCtrl_HideLines, 3152). --define(wxStyledTextCtrl_GetLineVisible, 3153). --define(wxStyledTextCtrl_SetFoldExpanded, 3154). --define(wxStyledTextCtrl_GetFoldExpanded, 3155). --define(wxStyledTextCtrl_ToggleFold, 3156). --define(wxStyledTextCtrl_EnsureVisible, 3157). --define(wxStyledTextCtrl_SetFoldFlags, 3158). --define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3159). --define(wxStyledTextCtrl_SetTabIndents, 3160). --define(wxStyledTextCtrl_GetTabIndents, 3161). --define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3162). --define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3163). --define(wxStyledTextCtrl_SetMouseDwellTime, 3164). --define(wxStyledTextCtrl_GetMouseDwellTime, 3165). --define(wxStyledTextCtrl_WordStartPosition, 3166). --define(wxStyledTextCtrl_WordEndPosition, 3167). --define(wxStyledTextCtrl_SetWrapMode, 3168). --define(wxStyledTextCtrl_GetWrapMode, 3169). --define(wxStyledTextCtrl_SetWrapVisualFlags, 3170). --define(wxStyledTextCtrl_GetWrapVisualFlags, 3171). --define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3172). --define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3173). --define(wxStyledTextCtrl_SetWrapStartIndent, 3174). --define(wxStyledTextCtrl_GetWrapStartIndent, 3175). --define(wxStyledTextCtrl_SetLayoutCache, 3176). --define(wxStyledTextCtrl_GetLayoutCache, 3177). --define(wxStyledTextCtrl_SetScrollWidth, 3178). --define(wxStyledTextCtrl_GetScrollWidth, 3179). --define(wxStyledTextCtrl_TextWidth, 3180). --define(wxStyledTextCtrl_GetEndAtLastLine, 3181). --define(wxStyledTextCtrl_TextHeight, 3182). --define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3183). --define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3184). --define(wxStyledTextCtrl_AppendText, 3185). --define(wxStyledTextCtrl_GetTwoPhaseDraw, 3186). --define(wxStyledTextCtrl_SetTwoPhaseDraw, 3187). --define(wxStyledTextCtrl_TargetFromSelection, 3188). --define(wxStyledTextCtrl_LinesJoin, 3189). --define(wxStyledTextCtrl_LinesSplit, 3190). --define(wxStyledTextCtrl_SetFoldMarginColour, 3191). --define(wxStyledTextCtrl_SetFoldMarginHiColour, 3192). --define(wxStyledTextCtrl_LineDown, 3193). --define(wxStyledTextCtrl_LineDownExtend, 3194). --define(wxStyledTextCtrl_LineUp, 3195). --define(wxStyledTextCtrl_LineUpExtend, 3196). --define(wxStyledTextCtrl_CharLeft, 3197). --define(wxStyledTextCtrl_CharLeftExtend, 3198). --define(wxStyledTextCtrl_CharRight, 3199). --define(wxStyledTextCtrl_CharRightExtend, 3200). --define(wxStyledTextCtrl_WordLeft, 3201). --define(wxStyledTextCtrl_WordLeftExtend, 3202). --define(wxStyledTextCtrl_WordRight, 3203). --define(wxStyledTextCtrl_WordRightExtend, 3204). --define(wxStyledTextCtrl_Home, 3205). --define(wxStyledTextCtrl_HomeExtend, 3206). --define(wxStyledTextCtrl_LineEnd, 3207). --define(wxStyledTextCtrl_LineEndExtend, 3208). --define(wxStyledTextCtrl_DocumentStart, 3209). --define(wxStyledTextCtrl_DocumentStartExtend, 3210). --define(wxStyledTextCtrl_DocumentEnd, 3211). --define(wxStyledTextCtrl_DocumentEndExtend, 3212). --define(wxStyledTextCtrl_PageUp, 3213). --define(wxStyledTextCtrl_PageUpExtend, 3214). --define(wxStyledTextCtrl_PageDown, 3215). --define(wxStyledTextCtrl_PageDownExtend, 3216). --define(wxStyledTextCtrl_EditToggleOvertype, 3217). --define(wxStyledTextCtrl_Cancel, 3218). --define(wxStyledTextCtrl_DeleteBack, 3219). --define(wxStyledTextCtrl_Tab, 3220). --define(wxStyledTextCtrl_BackTab, 3221). --define(wxStyledTextCtrl_NewLine, 3222). --define(wxStyledTextCtrl_FormFeed, 3223). --define(wxStyledTextCtrl_VCHome, 3224). --define(wxStyledTextCtrl_VCHomeExtend, 3225). --define(wxStyledTextCtrl_ZoomIn, 3226). --define(wxStyledTextCtrl_ZoomOut, 3227). --define(wxStyledTextCtrl_DelWordLeft, 3228). --define(wxStyledTextCtrl_DelWordRight, 3229). --define(wxStyledTextCtrl_LineCut, 3230). --define(wxStyledTextCtrl_LineDelete, 3231). --define(wxStyledTextCtrl_LineTranspose, 3232). --define(wxStyledTextCtrl_LineDuplicate, 3233). --define(wxStyledTextCtrl_LowerCase, 3234). --define(wxStyledTextCtrl_UpperCase, 3235). --define(wxStyledTextCtrl_LineScrollDown, 3236). --define(wxStyledTextCtrl_LineScrollUp, 3237). --define(wxStyledTextCtrl_DeleteBackNotLine, 3238). --define(wxStyledTextCtrl_HomeDisplay, 3239). --define(wxStyledTextCtrl_HomeDisplayExtend, 3240). --define(wxStyledTextCtrl_LineEndDisplay, 3241). --define(wxStyledTextCtrl_LineEndDisplayExtend, 3242). --define(wxStyledTextCtrl_HomeWrapExtend, 3243). --define(wxStyledTextCtrl_LineEndWrap, 3244). --define(wxStyledTextCtrl_LineEndWrapExtend, 3245). --define(wxStyledTextCtrl_VCHomeWrap, 3246). --define(wxStyledTextCtrl_VCHomeWrapExtend, 3247). --define(wxStyledTextCtrl_LineCopy, 3248). --define(wxStyledTextCtrl_MoveCaretInsideView, 3249). --define(wxStyledTextCtrl_LineLength, 3250). --define(wxStyledTextCtrl_BraceHighlight, 3251). --define(wxStyledTextCtrl_BraceBadLight, 3252). --define(wxStyledTextCtrl_BraceMatch, 3253). --define(wxStyledTextCtrl_GetViewEOL, 3254). --define(wxStyledTextCtrl_SetViewEOL, 3255). --define(wxStyledTextCtrl_SetModEventMask, 3256). --define(wxStyledTextCtrl_GetEdgeColumn, 3257). --define(wxStyledTextCtrl_SetEdgeColumn, 3258). --define(wxStyledTextCtrl_GetEdgeMode, 3259). --define(wxStyledTextCtrl_GetEdgeColour, 3260). --define(wxStyledTextCtrl_SetEdgeColour, 3261). --define(wxStyledTextCtrl_SearchAnchor, 3262). --define(wxStyledTextCtrl_SearchNext, 3263). --define(wxStyledTextCtrl_SearchPrev, 3264). --define(wxStyledTextCtrl_LinesOnScreen, 3265). --define(wxStyledTextCtrl_UsePopUp, 3266). --define(wxStyledTextCtrl_SelectionIsRectangle, 3267). --define(wxStyledTextCtrl_SetZoom, 3268). --define(wxStyledTextCtrl_GetZoom, 3269). --define(wxStyledTextCtrl_GetModEventMask, 3270). --define(wxStyledTextCtrl_SetSTCFocus, 3271). --define(wxStyledTextCtrl_GetSTCFocus, 3272). --define(wxStyledTextCtrl_SetStatus, 3273). --define(wxStyledTextCtrl_GetStatus, 3274). --define(wxStyledTextCtrl_SetMouseDownCaptures, 3275). --define(wxStyledTextCtrl_GetMouseDownCaptures, 3276). --define(wxStyledTextCtrl_SetSTCCursor, 3277). --define(wxStyledTextCtrl_GetSTCCursor, 3278). --define(wxStyledTextCtrl_SetControlCharSymbol, 3279). --define(wxStyledTextCtrl_GetControlCharSymbol, 3280). --define(wxStyledTextCtrl_WordPartLeft, 3281). --define(wxStyledTextCtrl_WordPartLeftExtend, 3282). --define(wxStyledTextCtrl_WordPartRight, 3283). --define(wxStyledTextCtrl_WordPartRightExtend, 3284). --define(wxStyledTextCtrl_SetVisiblePolicy, 3285). --define(wxStyledTextCtrl_DelLineLeft, 3286). --define(wxStyledTextCtrl_DelLineRight, 3287). --define(wxStyledTextCtrl_GetXOffset, 3288). --define(wxStyledTextCtrl_ChooseCaretX, 3289). --define(wxStyledTextCtrl_SetXCaretPolicy, 3290). --define(wxStyledTextCtrl_SetYCaretPolicy, 3291). --define(wxStyledTextCtrl_GetPrintWrapMode, 3292). --define(wxStyledTextCtrl_SetHotspotActiveForeground, 3293). --define(wxStyledTextCtrl_SetHotspotActiveBackground, 3294). --define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3295). --define(wxStyledTextCtrl_SetHotspotSingleLine, 3296). --define(wxStyledTextCtrl_ParaDownExtend, 3297). --define(wxStyledTextCtrl_ParaUp, 3298). --define(wxStyledTextCtrl_ParaUpExtend, 3299). --define(wxStyledTextCtrl_PositionBefore, 3300). --define(wxStyledTextCtrl_PositionAfter, 3301). --define(wxStyledTextCtrl_CopyRange, 3302). --define(wxStyledTextCtrl_CopyText, 3303). --define(wxStyledTextCtrl_SetSelectionMode, 3304). --define(wxStyledTextCtrl_GetSelectionMode, 3305). --define(wxStyledTextCtrl_LineDownRectExtend, 3306). --define(wxStyledTextCtrl_LineUpRectExtend, 3307). --define(wxStyledTextCtrl_CharLeftRectExtend, 3308). --define(wxStyledTextCtrl_CharRightRectExtend, 3309). --define(wxStyledTextCtrl_HomeRectExtend, 3310). --define(wxStyledTextCtrl_VCHomeRectExtend, 3311). --define(wxStyledTextCtrl_LineEndRectExtend, 3312). --define(wxStyledTextCtrl_PageUpRectExtend, 3313). --define(wxStyledTextCtrl_PageDownRectExtend, 3314). --define(wxStyledTextCtrl_StutteredPageUp, 3315). --define(wxStyledTextCtrl_StutteredPageUpExtend, 3316). --define(wxStyledTextCtrl_StutteredPageDown, 3317). --define(wxStyledTextCtrl_StutteredPageDownExtend, 3318). --define(wxStyledTextCtrl_WordLeftEnd, 3319). --define(wxStyledTextCtrl_WordLeftEndExtend, 3320). --define(wxStyledTextCtrl_WordRightEnd, 3321). --define(wxStyledTextCtrl_WordRightEndExtend, 3322). --define(wxStyledTextCtrl_SetWhitespaceChars, 3323). --define(wxStyledTextCtrl_SetCharsDefault, 3324). --define(wxStyledTextCtrl_AutoCompGetCurrent, 3325). --define(wxStyledTextCtrl_Allocate, 3326). --define(wxStyledTextCtrl_FindColumn, 3327). --define(wxStyledTextCtrl_GetCaretSticky, 3328). --define(wxStyledTextCtrl_SetCaretSticky, 3329). --define(wxStyledTextCtrl_ToggleCaretSticky, 3330). --define(wxStyledTextCtrl_SetPasteConvertEndings, 3331). --define(wxStyledTextCtrl_GetPasteConvertEndings, 3332). --define(wxStyledTextCtrl_SelectionDuplicate, 3333). --define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3334). --define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3335). --define(wxStyledTextCtrl_StartRecord, 3336). --define(wxStyledTextCtrl_StopRecord, 3337). --define(wxStyledTextCtrl_SetLexer, 3338). --define(wxStyledTextCtrl_GetLexer, 3339). --define(wxStyledTextCtrl_Colourise, 3340). --define(wxStyledTextCtrl_SetProperty, 3341). --define(wxStyledTextCtrl_SetKeyWords, 3342). --define(wxStyledTextCtrl_SetLexerLanguage, 3343). --define(wxStyledTextCtrl_GetProperty, 3344). --define(wxStyledTextCtrl_GetStyleBitsNeeded, 3345). --define(wxStyledTextCtrl_GetCurrentLine, 3346). --define(wxStyledTextCtrl_StyleSetSpec, 3347). --define(wxStyledTextCtrl_StyleSetFont, 3348). --define(wxStyledTextCtrl_StyleSetFontAttr, 3349). --define(wxStyledTextCtrl_StyleSetCharacterSet, 3350). --define(wxStyledTextCtrl_StyleSetFontEncoding, 3351). --define(wxStyledTextCtrl_CmdKeyExecute, 3352). --define(wxStyledTextCtrl_SetMargins, 3353). --define(wxStyledTextCtrl_GetSelection, 3354). --define(wxStyledTextCtrl_PointFromPosition, 3355). --define(wxStyledTextCtrl_ScrollToLine, 3356). --define(wxStyledTextCtrl_ScrollToColumn, 3357). --define(wxStyledTextCtrl_SendMsg, 3358). --define(wxStyledTextCtrl_SetVScrollBar, 3359). --define(wxStyledTextCtrl_SetHScrollBar, 3360). --define(wxStyledTextCtrl_GetLastKeydownProcessed, 3361). --define(wxStyledTextCtrl_SetLastKeydownProcessed, 3362). --define(wxStyledTextCtrl_SaveFile, 3363). --define(wxStyledTextCtrl_LoadFile, 3364). --define(wxStyledTextCtrl_DoDragOver, 3365). --define(wxStyledTextCtrl_DoDropText, 3366). --define(wxStyledTextCtrl_GetUseAntiAliasing, 3367). --define(wxStyledTextCtrl_AddTextRaw, 3368). --define(wxStyledTextCtrl_InsertTextRaw, 3369). --define(wxStyledTextCtrl_GetCurLineRaw, 3370). --define(wxStyledTextCtrl_GetLineRaw, 3371). --define(wxStyledTextCtrl_GetSelectedTextRaw, 3372). --define(wxStyledTextCtrl_GetTextRangeRaw, 3373). --define(wxStyledTextCtrl_SetTextRaw, 3374). --define(wxStyledTextCtrl_GetTextRaw, 3375). --define(wxStyledTextCtrl_AppendTextRaw, 3376). --define(wxArtProvider_GetBitmap, 3377). --define(wxArtProvider_GetIcon, 3378). --define(wxTreeEvent_GetKeyCode, 3379). --define(wxTreeEvent_GetItem, 3380). --define(wxTreeEvent_GetKeyEvent, 3381). --define(wxTreeEvent_GetLabel, 3382). --define(wxTreeEvent_GetOldItem, 3383). --define(wxTreeEvent_GetPoint, 3384). --define(wxTreeEvent_IsEditCancelled, 3385). --define(wxTreeEvent_SetToolTip, 3386). --define(wxNotebookEvent_GetOldSelection, 3387). --define(wxNotebookEvent_GetSelection, 3388). --define(wxNotebookEvent_SetOldSelection, 3389). --define(wxNotebookEvent_SetSelection, 3390). --define(wxFileDataObject_new, 3391). --define(wxFileDataObject_AddFile, 3392). --define(wxFileDataObject_GetFilenames, 3393). --define(wxFileDataObject_destroy, 3394). --define(wxTextDataObject_new, 3395). --define(wxTextDataObject_GetTextLength, 3396). --define(wxTextDataObject_GetText, 3397). --define(wxTextDataObject_SetText, 3398). --define(wxTextDataObject_destroy, 3399). --define(wxBitmapDataObject_new_1_1, 3400). --define(wxBitmapDataObject_new_1_0, 3401). --define(wxBitmapDataObject_GetBitmap, 3402). --define(wxBitmapDataObject_SetBitmap, 3403). --define(wxBitmapDataObject_destroy, 3404). --define(wxClipboard_new, 3406). --define(wxClipboard_destruct, 3407). --define(wxClipboard_AddData, 3408). --define(wxClipboard_Clear, 3409). --define(wxClipboard_Close, 3410). --define(wxClipboard_Flush, 3411). --define(wxClipboard_GetData, 3412). --define(wxClipboard_IsOpened, 3413). --define(wxClipboard_Open, 3414). --define(wxClipboard_SetData, 3415). --define(wxClipboard_UsePrimarySelection, 3417). --define(wxClipboard_IsSupported, 3418). --define(wxClipboard_Get, 3419). --define(wxSpinEvent_GetPosition, 3420). --define(wxSpinEvent_SetPosition, 3421). --define(wxSplitterWindow_new_0, 3422). --define(wxSplitterWindow_new_2, 3423). --define(wxSplitterWindow_destruct, 3424). --define(wxSplitterWindow_Create, 3425). --define(wxSplitterWindow_GetMinimumPaneSize, 3426). --define(wxSplitterWindow_GetSashGravity, 3427). --define(wxSplitterWindow_GetSashPosition, 3428). --define(wxSplitterWindow_GetSplitMode, 3429). --define(wxSplitterWindow_GetWindow1, 3430). --define(wxSplitterWindow_GetWindow2, 3431). --define(wxSplitterWindow_Initialize, 3432). --define(wxSplitterWindow_IsSplit, 3433). --define(wxSplitterWindow_ReplaceWindow, 3434). --define(wxSplitterWindow_SetSashGravity, 3435). --define(wxSplitterWindow_SetSashPosition, 3436). --define(wxSplitterWindow_SetSashSize, 3437). --define(wxSplitterWindow_SetMinimumPaneSize, 3438). --define(wxSplitterWindow_SetSplitMode, 3439). --define(wxSplitterWindow_SplitHorizontally, 3440). --define(wxSplitterWindow_SplitVertically, 3441). --define(wxSplitterWindow_Unsplit, 3442). --define(wxSplitterWindow_UpdateSize, 3443). --define(wxSplitterEvent_GetSashPosition, 3444). --define(wxSplitterEvent_GetX, 3445). --define(wxSplitterEvent_GetY, 3446). --define(wxSplitterEvent_GetWindowBeingRemoved, 3447). --define(wxSplitterEvent_SetSashPosition, 3448). --define(wxHtmlWindow_new_0, 3449). --define(wxHtmlWindow_new_2, 3450). --define(wxHtmlWindow_AppendToPage, 3451). --define(wxHtmlWindow_GetOpenedAnchor, 3452). --define(wxHtmlWindow_GetOpenedPage, 3453). --define(wxHtmlWindow_GetOpenedPageTitle, 3454). --define(wxHtmlWindow_GetRelatedFrame, 3455). --define(wxHtmlWindow_HistoryBack, 3456). --define(wxHtmlWindow_HistoryCanBack, 3457). --define(wxHtmlWindow_HistoryCanForward, 3458). --define(wxHtmlWindow_HistoryClear, 3459). --define(wxHtmlWindow_HistoryForward, 3460). --define(wxHtmlWindow_LoadFile, 3461). --define(wxHtmlWindow_LoadPage, 3462). --define(wxHtmlWindow_SelectAll, 3463). --define(wxHtmlWindow_SelectionToText, 3464). --define(wxHtmlWindow_SelectLine, 3465). --define(wxHtmlWindow_SelectWord, 3466). --define(wxHtmlWindow_SetBorders, 3467). --define(wxHtmlWindow_SetFonts, 3468). --define(wxHtmlWindow_SetPage, 3469). --define(wxHtmlWindow_SetRelatedFrame, 3470). --define(wxHtmlWindow_SetRelatedStatusBar, 3471). --define(wxHtmlWindow_ToText, 3472). --define(wxHtmlWindow_destroy, 3473). --define(wxHtmlLinkEvent_GetLinkInfo, 3474). --define(wxAuiNotebookEvent_SetSelection, 3475). --define(wxAuiNotebookEvent_GetSelection, 3476). --define(wxAuiNotebookEvent_SetOldSelection, 3477). --define(wxAuiNotebookEvent_GetOldSelection, 3478). --define(wxAuiNotebookEvent_SetDragSource, 3479). --define(wxAuiNotebookEvent_GetDragSource, 3480). --define(wxAuiManagerEvent_SetManager, 3481). --define(wxAuiManagerEvent_GetManager, 3482). --define(wxAuiManagerEvent_SetPane, 3483). --define(wxAuiManagerEvent_GetPane, 3484). --define(wxAuiManagerEvent_SetButton, 3485). --define(wxAuiManagerEvent_GetButton, 3486). --define(wxAuiManagerEvent_SetDC, 3487). --define(wxAuiManagerEvent_GetDC, 3488). --define(wxAuiManagerEvent_Veto, 3489). --define(wxAuiManagerEvent_GetVeto, 3490). --define(wxAuiManagerEvent_SetCanVeto, 3491). --define(wxAuiManagerEvent_CanVeto, 3492). --define(wxLogNull_new, 3493). --define(wxLogNull_destroy, 3494). +-define(wxTreeCtrl_EditLabel, 2010). +-define(wxTreeCtrl_EnsureVisible, 2011). +-define(wxTreeCtrl_Expand, 2012). +-define(wxTreeCtrl_GetBoundingRect, 2013). +-define(wxTreeCtrl_GetChildrenCount, 2015). +-define(wxTreeCtrl_GetCount, 2016). +-define(wxTreeCtrl_GetEditControl, 2017). +-define(wxTreeCtrl_GetFirstChild, 2018). +-define(wxTreeCtrl_GetNextChild, 2019). +-define(wxTreeCtrl_GetFirstVisibleItem, 2020). +-define(wxTreeCtrl_GetImageList, 2021). +-define(wxTreeCtrl_GetIndent, 2022). +-define(wxTreeCtrl_GetItemBackgroundColour, 2023). +-define(wxTreeCtrl_GetItemData, 2024). +-define(wxTreeCtrl_GetItemFont, 2025). +-define(wxTreeCtrl_GetItemImage_1, 2026). +-define(wxTreeCtrl_GetItemImage_2, 2027). +-define(wxTreeCtrl_GetItemText, 2028). +-define(wxTreeCtrl_GetItemTextColour, 2029). +-define(wxTreeCtrl_GetLastChild, 2030). +-define(wxTreeCtrl_GetNextSibling, 2031). +-define(wxTreeCtrl_GetNextVisible, 2032). +-define(wxTreeCtrl_GetItemParent, 2033). +-define(wxTreeCtrl_GetPrevSibling, 2034). +-define(wxTreeCtrl_GetPrevVisible, 2035). +-define(wxTreeCtrl_GetRootItem, 2036). +-define(wxTreeCtrl_GetSelection, 2037). +-define(wxTreeCtrl_GetSelections, 2038). +-define(wxTreeCtrl_GetStateImageList, 2039). +-define(wxTreeCtrl_HitTest, 2040). +-define(wxTreeCtrl_InsertItem, 2042). +-define(wxTreeCtrl_IsBold, 2043). +-define(wxTreeCtrl_IsExpanded, 2044). +-define(wxTreeCtrl_IsSelected, 2045). +-define(wxTreeCtrl_IsVisible, 2046). +-define(wxTreeCtrl_ItemHasChildren, 2047). +-define(wxTreeCtrl_PrependItem, 2048). +-define(wxTreeCtrl_ScrollTo, 2049). +-define(wxTreeCtrl_SelectItem_1, 2050). +-define(wxTreeCtrl_SelectItem_2, 2051). +-define(wxTreeCtrl_SetIndent, 2052). +-define(wxTreeCtrl_SetImageList, 2053). +-define(wxTreeCtrl_SetItemBackgroundColour, 2054). +-define(wxTreeCtrl_SetItemBold, 2055). +-define(wxTreeCtrl_SetItemData, 2056). +-define(wxTreeCtrl_SetItemDropHighlight, 2057). +-define(wxTreeCtrl_SetItemFont, 2058). +-define(wxTreeCtrl_SetItemHasChildren, 2059). +-define(wxTreeCtrl_SetItemImage_2, 2060). +-define(wxTreeCtrl_SetItemImage_3, 2061). +-define(wxTreeCtrl_SetItemText, 2062). +-define(wxTreeCtrl_SetItemTextColour, 2063). +-define(wxTreeCtrl_SetStateImageList, 2064). +-define(wxTreeCtrl_SetWindowStyle, 2065). +-define(wxTreeCtrl_SortChildren, 2066). +-define(wxTreeCtrl_Toggle, 2067). +-define(wxTreeCtrl_ToggleItemSelection, 2068). +-define(wxTreeCtrl_Unselect, 2069). +-define(wxTreeCtrl_UnselectAll, 2070). +-define(wxTreeCtrl_UnselectItem, 2071). +-define(wxScrollBar_new_0, 2072). +-define(wxScrollBar_new_3, 2073). +-define(wxScrollBar_destruct, 2074). +-define(wxScrollBar_Create, 2075). +-define(wxScrollBar_GetRange, 2076). +-define(wxScrollBar_GetPageSize, 2077). +-define(wxScrollBar_GetThumbPosition, 2078). +-define(wxScrollBar_GetThumbSize, 2079). +-define(wxScrollBar_SetThumbPosition, 2080). +-define(wxScrollBar_SetScrollbar, 2081). +-define(wxSpinButton_new_2, 2083). +-define(wxSpinButton_new_0, 2084). +-define(wxSpinButton_Create, 2085). +-define(wxSpinButton_GetMax, 2086). +-define(wxSpinButton_GetMin, 2087). +-define(wxSpinButton_GetValue, 2088). +-define(wxSpinButton_SetRange, 2089). +-define(wxSpinButton_SetValue, 2090). +-define(wxSpinButton_destroy, 2091). +-define(wxSpinCtrl_new_0, 2092). +-define(wxSpinCtrl_new_2, 2093). +-define(wxSpinCtrl_Create, 2095). +-define(wxSpinCtrl_SetValue_1_1, 2098). +-define(wxSpinCtrl_SetValue_1_0, 2099). +-define(wxSpinCtrl_GetValue, 2101). +-define(wxSpinCtrl_SetRange, 2103). +-define(wxSpinCtrl_SetSelection, 2104). +-define(wxSpinCtrl_GetMin, 2106). +-define(wxSpinCtrl_GetMax, 2108). +-define(wxSpinCtrl_destroy, 2109). +-define(wxStaticText_new_0, 2110). +-define(wxStaticText_new_4, 2111). +-define(wxStaticText_Create, 2112). +-define(wxStaticText_GetLabel, 2113). +-define(wxStaticText_SetLabel, 2114). +-define(wxStaticText_Wrap, 2115). +-define(wxStaticText_destroy, 2116). +-define(wxStaticBitmap_new_0, 2117). +-define(wxStaticBitmap_new_4, 2118). +-define(wxStaticBitmap_Create, 2119). +-define(wxStaticBitmap_GetBitmap, 2120). +-define(wxStaticBitmap_SetBitmap, 2121). +-define(wxStaticBitmap_destroy, 2122). +-define(wxRadioBox_new, 2123). +-define(wxRadioBox_destruct, 2125). +-define(wxRadioBox_Create, 2126). +-define(wxRadioBox_Enable_2, 2127). +-define(wxRadioBox_Enable_1, 2128). +-define(wxRadioBox_GetSelection, 2129). +-define(wxRadioBox_GetString, 2130). +-define(wxRadioBox_SetSelection, 2131). +-define(wxRadioBox_Show_2, 2132). +-define(wxRadioBox_Show_1, 2133). +-define(wxRadioBox_GetColumnCount, 2134). +-define(wxRadioBox_GetItemHelpText, 2135). +-define(wxRadioBox_GetItemToolTip, 2136). +-define(wxRadioBox_GetItemFromPoint, 2138). +-define(wxRadioBox_GetRowCount, 2139). +-define(wxRadioBox_IsItemEnabled, 2140). +-define(wxRadioBox_IsItemShown, 2141). +-define(wxRadioBox_SetItemHelpText, 2142). +-define(wxRadioBox_SetItemToolTip, 2143). +-define(wxRadioButton_new_0, 2144). +-define(wxRadioButton_new_4, 2145). +-define(wxRadioButton_Create, 2146). +-define(wxRadioButton_GetValue, 2147). +-define(wxRadioButton_SetValue, 2148). +-define(wxRadioButton_destroy, 2149). +-define(wxSlider_new_6, 2151). +-define(wxSlider_new_0, 2152). +-define(wxSlider_Create, 2153). +-define(wxSlider_GetLineSize, 2154). +-define(wxSlider_GetMax, 2155). +-define(wxSlider_GetMin, 2156). +-define(wxSlider_GetPageSize, 2157). +-define(wxSlider_GetThumbLength, 2158). +-define(wxSlider_GetValue, 2159). +-define(wxSlider_SetLineSize, 2160). +-define(wxSlider_SetPageSize, 2161). +-define(wxSlider_SetRange, 2162). +-define(wxSlider_SetThumbLength, 2163). +-define(wxSlider_SetValue, 2164). +-define(wxSlider_destroy, 2165). +-define(wxDialog_new_4, 2167). +-define(wxDialog_new_0, 2168). +-define(wxDialog_destruct, 2170). +-define(wxDialog_Create, 2171). +-define(wxDialog_CreateButtonSizer, 2172). +-define(wxDialog_CreateStdDialogButtonSizer, 2173). +-define(wxDialog_EndModal, 2174). +-define(wxDialog_GetAffirmativeId, 2175). +-define(wxDialog_GetReturnCode, 2176). +-define(wxDialog_IsModal, 2177). +-define(wxDialog_SetAffirmativeId, 2178). +-define(wxDialog_SetReturnCode, 2179). +-define(wxDialog_Show, 2180). +-define(wxDialog_ShowModal, 2181). +-define(wxColourDialog_new_0, 2182). +-define(wxColourDialog_new_2, 2183). +-define(wxColourDialog_destruct, 2184). +-define(wxColourDialog_Create, 2185). +-define(wxColourDialog_GetColourData, 2186). +-define(wxColourData_new_0, 2187). +-define(wxColourData_new_1, 2188). +-define(wxColourData_destruct, 2189). +-define(wxColourData_GetChooseFull, 2190). +-define(wxColourData_GetColour, 2191). +-define(wxColourData_GetCustomColour, 2193). +-define(wxColourData_SetChooseFull, 2194). +-define(wxColourData_SetColour, 2195). +-define(wxColourData_SetCustomColour, 2196). +-define(wxPalette_new_0, 2197). +-define(wxPalette_new_4, 2198). +-define(wxPalette_destruct, 2200). +-define(wxPalette_Create, 2201). +-define(wxPalette_GetColoursCount, 2202). +-define(wxPalette_GetPixel, 2203). +-define(wxPalette_GetRGB, 2204). +-define(wxPalette_IsOk, 2205). +-define(wxDirDialog_new, 2209). +-define(wxDirDialog_destruct, 2210). +-define(wxDirDialog_GetPath, 2211). +-define(wxDirDialog_GetMessage, 2212). +-define(wxDirDialog_SetMessage, 2213). +-define(wxDirDialog_SetPath, 2214). +-define(wxFileDialog_new, 2218). +-define(wxFileDialog_destruct, 2219). +-define(wxFileDialog_GetDirectory, 2220). +-define(wxFileDialog_GetFilename, 2221). +-define(wxFileDialog_GetFilenames, 2222). +-define(wxFileDialog_GetFilterIndex, 2223). +-define(wxFileDialog_GetMessage, 2224). +-define(wxFileDialog_GetPath, 2225). +-define(wxFileDialog_GetPaths, 2226). +-define(wxFileDialog_GetWildcard, 2227). +-define(wxFileDialog_SetDirectory, 2228). +-define(wxFileDialog_SetFilename, 2229). +-define(wxFileDialog_SetFilterIndex, 2230). +-define(wxFileDialog_SetMessage, 2231). +-define(wxFileDialog_SetPath, 2232). +-define(wxFileDialog_SetWildcard, 2233). +-define(wxPickerBase_SetInternalMargin, 2234). +-define(wxPickerBase_GetInternalMargin, 2235). +-define(wxPickerBase_SetTextCtrlProportion, 2236). +-define(wxPickerBase_SetPickerCtrlProportion, 2237). +-define(wxPickerBase_GetTextCtrlProportion, 2238). +-define(wxPickerBase_GetPickerCtrlProportion, 2239). +-define(wxPickerBase_HasTextCtrl, 2240). +-define(wxPickerBase_GetTextCtrl, 2241). +-define(wxPickerBase_IsTextCtrlGrowable, 2242). +-define(wxPickerBase_SetPickerCtrlGrowable, 2243). +-define(wxPickerBase_SetTextCtrlGrowable, 2244). +-define(wxPickerBase_IsPickerCtrlGrowable, 2245). +-define(wxFilePickerCtrl_new_0, 2246). +-define(wxFilePickerCtrl_new_3, 2247). +-define(wxFilePickerCtrl_Create, 2248). +-define(wxFilePickerCtrl_GetPath, 2249). +-define(wxFilePickerCtrl_SetPath, 2250). +-define(wxFilePickerCtrl_destroy, 2251). +-define(wxDirPickerCtrl_new_0, 2252). +-define(wxDirPickerCtrl_new_3, 2253). +-define(wxDirPickerCtrl_Create, 2254). +-define(wxDirPickerCtrl_GetPath, 2255). +-define(wxDirPickerCtrl_SetPath, 2256). +-define(wxDirPickerCtrl_destroy, 2257). +-define(wxColourPickerCtrl_new_0, 2258). +-define(wxColourPickerCtrl_new_3, 2259). +-define(wxColourPickerCtrl_Create, 2260). +-define(wxColourPickerCtrl_GetColour, 2261). +-define(wxColourPickerCtrl_SetColour_1_1, 2262). +-define(wxColourPickerCtrl_SetColour_1_0, 2263). +-define(wxColourPickerCtrl_destroy, 2264). +-define(wxDatePickerCtrl_new_0, 2265). +-define(wxDatePickerCtrl_new_3, 2266). +-define(wxDatePickerCtrl_GetRange, 2267). +-define(wxDatePickerCtrl_GetValue, 2268). +-define(wxDatePickerCtrl_SetRange, 2269). +-define(wxDatePickerCtrl_SetValue, 2270). +-define(wxDatePickerCtrl_destroy, 2271). +-define(wxFontPickerCtrl_new_0, 2272). +-define(wxFontPickerCtrl_new_3, 2273). +-define(wxFontPickerCtrl_Create, 2274). +-define(wxFontPickerCtrl_GetSelectedFont, 2275). +-define(wxFontPickerCtrl_SetSelectedFont, 2276). +-define(wxFontPickerCtrl_GetMaxPointSize, 2277). +-define(wxFontPickerCtrl_SetMaxPointSize, 2278). +-define(wxFontPickerCtrl_destroy, 2279). +-define(wxFindReplaceDialog_new_0, 2282). +-define(wxFindReplaceDialog_new_4, 2283). +-define(wxFindReplaceDialog_destruct, 2284). +-define(wxFindReplaceDialog_Create, 2285). +-define(wxFindReplaceDialog_GetData, 2286). +-define(wxFindReplaceData_new_0, 2287). +-define(wxFindReplaceData_new_1, 2288). +-define(wxFindReplaceData_GetFindString, 2289). +-define(wxFindReplaceData_GetReplaceString, 2290). +-define(wxFindReplaceData_GetFlags, 2291). +-define(wxFindReplaceData_SetFlags, 2292). +-define(wxFindReplaceData_SetFindString, 2293). +-define(wxFindReplaceData_SetReplaceString, 2294). +-define(wxFindReplaceData_destroy, 2295). +-define(wxMultiChoiceDialog_new_0, 2296). +-define(wxMultiChoiceDialog_new_5, 2298). +-define(wxMultiChoiceDialog_GetSelections, 2299). +-define(wxMultiChoiceDialog_SetSelections, 2300). +-define(wxMultiChoiceDialog_destroy, 2301). +-define(wxSingleChoiceDialog_new_0, 2302). +-define(wxSingleChoiceDialog_new_5, 2304). +-define(wxSingleChoiceDialog_GetSelection, 2305). +-define(wxSingleChoiceDialog_GetStringSelection, 2306). +-define(wxSingleChoiceDialog_SetSelection, 2307). +-define(wxSingleChoiceDialog_destroy, 2308). +-define(wxTextEntryDialog_new, 2309). +-define(wxTextEntryDialog_GetValue, 2310). +-define(wxTextEntryDialog_SetValue, 2311). +-define(wxTextEntryDialog_destroy, 2312). +-define(wxPasswordEntryDialog_new, 2313). +-define(wxPasswordEntryDialog_destroy, 2314). +-define(wxFontData_new_0, 2315). +-define(wxFontData_new_1, 2316). +-define(wxFontData_destruct, 2317). +-define(wxFontData_EnableEffects, 2318). +-define(wxFontData_GetAllowSymbols, 2319). +-define(wxFontData_GetColour, 2320). +-define(wxFontData_GetChosenFont, 2321). +-define(wxFontData_GetEnableEffects, 2322). +-define(wxFontData_GetInitialFont, 2323). +-define(wxFontData_GetShowHelp, 2324). +-define(wxFontData_SetAllowSymbols, 2325). +-define(wxFontData_SetChosenFont, 2326). +-define(wxFontData_SetColour, 2327). +-define(wxFontData_SetInitialFont, 2328). +-define(wxFontData_SetRange, 2329). +-define(wxFontData_SetShowHelp, 2330). +-define(wxFontDialog_new_0, 2334). +-define(wxFontDialog_new_2, 2336). +-define(wxFontDialog_Create, 2338). +-define(wxFontDialog_GetFontData, 2339). +-define(wxFontDialog_destroy, 2341). +-define(wxProgressDialog_new, 2342). +-define(wxProgressDialog_destruct, 2343). +-define(wxProgressDialog_Resume, 2344). +-define(wxProgressDialog_Update_2, 2345). +-define(wxProgressDialog_Update_0, 2346). +-define(wxMessageDialog_new, 2347). +-define(wxMessageDialog_destruct, 2348). +-define(wxPageSetupDialog_new, 2349). +-define(wxPageSetupDialog_destruct, 2350). +-define(wxPageSetupDialog_GetPageSetupData, 2351). +-define(wxPageSetupDialog_ShowModal, 2352). +-define(wxPageSetupDialogData_new_0, 2353). +-define(wxPageSetupDialogData_new_1_0, 2354). +-define(wxPageSetupDialogData_new_1_1, 2355). +-define(wxPageSetupDialogData_destruct, 2356). +-define(wxPageSetupDialogData_EnableHelp, 2357). +-define(wxPageSetupDialogData_EnableMargins, 2358). +-define(wxPageSetupDialogData_EnableOrientation, 2359). +-define(wxPageSetupDialogData_EnablePaper, 2360). +-define(wxPageSetupDialogData_EnablePrinter, 2361). +-define(wxPageSetupDialogData_GetDefaultMinMargins, 2362). +-define(wxPageSetupDialogData_GetEnableMargins, 2363). +-define(wxPageSetupDialogData_GetEnableOrientation, 2364). +-define(wxPageSetupDialogData_GetEnablePaper, 2365). +-define(wxPageSetupDialogData_GetEnablePrinter, 2366). +-define(wxPageSetupDialogData_GetEnableHelp, 2367). +-define(wxPageSetupDialogData_GetDefaultInfo, 2368). +-define(wxPageSetupDialogData_GetMarginTopLeft, 2369). +-define(wxPageSetupDialogData_GetMarginBottomRight, 2370). +-define(wxPageSetupDialogData_GetMinMarginTopLeft, 2371). +-define(wxPageSetupDialogData_GetMinMarginBottomRight, 2372). +-define(wxPageSetupDialogData_GetPaperId, 2373). +-define(wxPageSetupDialogData_GetPaperSize, 2374). +-define(wxPageSetupDialogData_GetPrintData, 2376). +-define(wxPageSetupDialogData_IsOk, 2377). +-define(wxPageSetupDialogData_SetDefaultInfo, 2378). +-define(wxPageSetupDialogData_SetDefaultMinMargins, 2379). +-define(wxPageSetupDialogData_SetMarginTopLeft, 2380). +-define(wxPageSetupDialogData_SetMarginBottomRight, 2381). +-define(wxPageSetupDialogData_SetMinMarginTopLeft, 2382). +-define(wxPageSetupDialogData_SetMinMarginBottomRight, 2383). +-define(wxPageSetupDialogData_SetPaperId, 2384). +-define(wxPageSetupDialogData_SetPaperSize_1_1, 2385). +-define(wxPageSetupDialogData_SetPaperSize_1_0, 2386). +-define(wxPageSetupDialogData_SetPrintData, 2387). +-define(wxPrintDialog_new_2_0, 2388). +-define(wxPrintDialog_new_2_1, 2389). +-define(wxPrintDialog_destruct, 2390). +-define(wxPrintDialog_GetPrintDialogData, 2391). +-define(wxPrintDialog_GetPrintDC, 2392). +-define(wxPrintDialogData_new_0, 2393). +-define(wxPrintDialogData_new_1_1, 2394). +-define(wxPrintDialogData_new_1_0, 2395). +-define(wxPrintDialogData_destruct, 2396). +-define(wxPrintDialogData_EnableHelp, 2397). +-define(wxPrintDialogData_EnablePageNumbers, 2398). +-define(wxPrintDialogData_EnablePrintToFile, 2399). +-define(wxPrintDialogData_EnableSelection, 2400). +-define(wxPrintDialogData_GetAllPages, 2401). +-define(wxPrintDialogData_GetCollate, 2402). +-define(wxPrintDialogData_GetFromPage, 2403). +-define(wxPrintDialogData_GetMaxPage, 2404). +-define(wxPrintDialogData_GetMinPage, 2405). +-define(wxPrintDialogData_GetNoCopies, 2406). +-define(wxPrintDialogData_GetPrintData, 2407). +-define(wxPrintDialogData_GetPrintToFile, 2408). +-define(wxPrintDialogData_GetSelection, 2409). +-define(wxPrintDialogData_GetToPage, 2410). +-define(wxPrintDialogData_IsOk, 2411). +-define(wxPrintDialogData_SetCollate, 2412). +-define(wxPrintDialogData_SetFromPage, 2413). +-define(wxPrintDialogData_SetMaxPage, 2414). +-define(wxPrintDialogData_SetMinPage, 2415). +-define(wxPrintDialogData_SetNoCopies, 2416). +-define(wxPrintDialogData_SetPrintData, 2417). +-define(wxPrintDialogData_SetPrintToFile, 2418). +-define(wxPrintDialogData_SetSelection, 2419). +-define(wxPrintDialogData_SetToPage, 2420). +-define(wxPrintData_new_0, 2421). +-define(wxPrintData_new_1, 2422). +-define(wxPrintData_destruct, 2423). +-define(wxPrintData_GetCollate, 2424). +-define(wxPrintData_GetBin, 2425). +-define(wxPrintData_GetColour, 2426). +-define(wxPrintData_GetDuplex, 2427). +-define(wxPrintData_GetNoCopies, 2428). +-define(wxPrintData_GetOrientation, 2429). +-define(wxPrintData_GetPaperId, 2430). +-define(wxPrintData_GetPrinterName, 2431). +-define(wxPrintData_GetQuality, 2432). +-define(wxPrintData_IsOk, 2433). +-define(wxPrintData_SetBin, 2434). +-define(wxPrintData_SetCollate, 2435). +-define(wxPrintData_SetColour, 2436). +-define(wxPrintData_SetDuplex, 2437). +-define(wxPrintData_SetNoCopies, 2438). +-define(wxPrintData_SetOrientation, 2439). +-define(wxPrintData_SetPaperId, 2440). +-define(wxPrintData_SetPrinterName, 2441). +-define(wxPrintData_SetQuality, 2442). +-define(wxPrintPreview_new_2, 2445). +-define(wxPrintPreview_new_3, 2446). +-define(wxPrintPreview_destruct, 2448). +-define(wxPrintPreview_GetCanvas, 2449). +-define(wxPrintPreview_GetCurrentPage, 2450). +-define(wxPrintPreview_GetFrame, 2451). +-define(wxPrintPreview_GetMaxPage, 2452). +-define(wxPrintPreview_GetMinPage, 2453). +-define(wxPrintPreview_GetPrintout, 2454). +-define(wxPrintPreview_GetPrintoutForPrinting, 2455). +-define(wxPrintPreview_IsOk, 2456). +-define(wxPrintPreview_PaintPage, 2457). +-define(wxPrintPreview_Print, 2458). +-define(wxPrintPreview_RenderPage, 2459). +-define(wxPrintPreview_SetCanvas, 2460). +-define(wxPrintPreview_SetCurrentPage, 2461). +-define(wxPrintPreview_SetFrame, 2462). +-define(wxPrintPreview_SetPrintout, 2463). +-define(wxPrintPreview_SetZoom, 2464). +-define(wxPreviewFrame_new, 2465). +-define(wxPreviewFrame_destruct, 2466). +-define(wxPreviewFrame_CreateControlBar, 2467). +-define(wxPreviewFrame_CreateCanvas, 2468). +-define(wxPreviewFrame_Initialize, 2469). +-define(wxPreviewFrame_OnCloseWindow, 2470). +-define(wxPreviewControlBar_new, 2471). +-define(wxPreviewControlBar_destruct, 2472). +-define(wxPreviewControlBar_CreateButtons, 2473). +-define(wxPreviewControlBar_GetPrintPreview, 2474). +-define(wxPreviewControlBar_GetZoomControl, 2475). +-define(wxPreviewControlBar_SetZoomControl, 2476). +-define(wxPrinter_new, 2478). +-define(wxPrinter_CreateAbortWindow, 2479). +-define(wxPrinter_GetAbort, 2480). +-define(wxPrinter_GetLastError, 2481). +-define(wxPrinter_GetPrintDialogData, 2482). +-define(wxPrinter_Print, 2483). +-define(wxPrinter_PrintDialog, 2484). +-define(wxPrinter_ReportError, 2485). +-define(wxPrinter_Setup, 2486). +-define(wxPrinter_destroy, 2487). +-define(wxXmlResource_new_1, 2488). +-define(wxXmlResource_new_2, 2489). +-define(wxXmlResource_destruct, 2490). +-define(wxXmlResource_AttachUnknownControl, 2491). +-define(wxXmlResource_ClearHandlers, 2492). +-define(wxXmlResource_CompareVersion, 2493). +-define(wxXmlResource_Get, 2494). +-define(wxXmlResource_GetFlags, 2495). +-define(wxXmlResource_GetVersion, 2496). +-define(wxXmlResource_GetXRCID, 2497). +-define(wxXmlResource_InitAllHandlers, 2498). +-define(wxXmlResource_Load, 2499). +-define(wxXmlResource_LoadBitmap, 2500). +-define(wxXmlResource_LoadDialog_2, 2501). +-define(wxXmlResource_LoadDialog_3, 2502). +-define(wxXmlResource_LoadFrame_2, 2503). +-define(wxXmlResource_LoadFrame_3, 2504). +-define(wxXmlResource_LoadIcon, 2505). +-define(wxXmlResource_LoadMenu, 2506). +-define(wxXmlResource_LoadMenuBar_2, 2507). +-define(wxXmlResource_LoadMenuBar_1, 2508). +-define(wxXmlResource_LoadPanel_2, 2509). +-define(wxXmlResource_LoadPanel_3, 2510). +-define(wxXmlResource_LoadToolBar, 2511). +-define(wxXmlResource_Set, 2512). +-define(wxXmlResource_SetFlags, 2513). +-define(wxXmlResource_Unload, 2514). +-define(wxXmlResource_xrcctrl, 2515). +-define(wxHtmlEasyPrinting_new, 2516). +-define(wxHtmlEasyPrinting_destruct, 2517). +-define(wxHtmlEasyPrinting_GetPrintData, 2518). +-define(wxHtmlEasyPrinting_GetPageSetupData, 2519). +-define(wxHtmlEasyPrinting_PreviewFile, 2520). +-define(wxHtmlEasyPrinting_PreviewText, 2521). +-define(wxHtmlEasyPrinting_PrintFile, 2522). +-define(wxHtmlEasyPrinting_PrintText, 2523). +-define(wxHtmlEasyPrinting_PageSetup, 2524). +-define(wxHtmlEasyPrinting_SetFonts, 2525). +-define(wxHtmlEasyPrinting_SetHeader, 2526). +-define(wxHtmlEasyPrinting_SetFooter, 2527). +-define(wxGLCanvas_new_2, 2529). +-define(wxGLCanvas_new_3_1, 2530). +-define(wxGLCanvas_new_3_0, 2531). +-define(wxGLCanvas_GetContext, 2532). +-define(wxGLCanvas_SetCurrent, 2534). +-define(wxGLCanvas_SwapBuffers, 2535). +-define(wxGLCanvas_destroy, 2536). +-define(wxAuiManager_new, 2537). +-define(wxAuiManager_destruct, 2538). +-define(wxAuiManager_AddPane_2_1, 2539). +-define(wxAuiManager_AddPane_3, 2540). +-define(wxAuiManager_AddPane_2_0, 2541). +-define(wxAuiManager_DetachPane, 2542). +-define(wxAuiManager_GetAllPanes, 2543). +-define(wxAuiManager_GetArtProvider, 2544). +-define(wxAuiManager_GetDockSizeConstraint, 2545). +-define(wxAuiManager_GetFlags, 2546). +-define(wxAuiManager_GetManagedWindow, 2547). +-define(wxAuiManager_GetManager, 2548). +-define(wxAuiManager_GetPane_1_1, 2549). +-define(wxAuiManager_GetPane_1_0, 2550). +-define(wxAuiManager_HideHint, 2551). +-define(wxAuiManager_InsertPane, 2552). +-define(wxAuiManager_LoadPaneInfo, 2553). +-define(wxAuiManager_LoadPerspective, 2554). +-define(wxAuiManager_SavePaneInfo, 2555). +-define(wxAuiManager_SavePerspective, 2556). +-define(wxAuiManager_SetArtProvider, 2557). +-define(wxAuiManager_SetDockSizeConstraint, 2558). +-define(wxAuiManager_SetFlags, 2559). +-define(wxAuiManager_SetManagedWindow, 2560). +-define(wxAuiManager_ShowHint, 2561). +-define(wxAuiManager_UnInit, 2562). +-define(wxAuiManager_Update, 2563). +-define(wxAuiPaneInfo_new_0, 2564). +-define(wxAuiPaneInfo_new_1, 2565). +-define(wxAuiPaneInfo_destruct, 2566). +-define(wxAuiPaneInfo_BestSize_1, 2567). +-define(wxAuiPaneInfo_BestSize_2, 2568). +-define(wxAuiPaneInfo_Bottom, 2569). +-define(wxAuiPaneInfo_BottomDockable, 2570). +-define(wxAuiPaneInfo_Caption, 2571). +-define(wxAuiPaneInfo_CaptionVisible, 2572). +-define(wxAuiPaneInfo_Centre, 2573). +-define(wxAuiPaneInfo_CentrePane, 2574). +-define(wxAuiPaneInfo_CloseButton, 2575). +-define(wxAuiPaneInfo_DefaultPane, 2576). +-define(wxAuiPaneInfo_DestroyOnClose, 2577). +-define(wxAuiPaneInfo_Direction, 2578). +-define(wxAuiPaneInfo_Dock, 2579). +-define(wxAuiPaneInfo_Dockable, 2580). +-define(wxAuiPaneInfo_Fixed, 2581). +-define(wxAuiPaneInfo_Float, 2582). +-define(wxAuiPaneInfo_Floatable, 2583). +-define(wxAuiPaneInfo_FloatingPosition_1, 2584). +-define(wxAuiPaneInfo_FloatingPosition_2, 2585). +-define(wxAuiPaneInfo_FloatingSize_1, 2586). +-define(wxAuiPaneInfo_FloatingSize_2, 2587). +-define(wxAuiPaneInfo_Gripper, 2588). +-define(wxAuiPaneInfo_GripperTop, 2589). +-define(wxAuiPaneInfo_HasBorder, 2590). +-define(wxAuiPaneInfo_HasCaption, 2591). +-define(wxAuiPaneInfo_HasCloseButton, 2592). +-define(wxAuiPaneInfo_HasFlag, 2593). +-define(wxAuiPaneInfo_HasGripper, 2594). +-define(wxAuiPaneInfo_HasGripperTop, 2595). +-define(wxAuiPaneInfo_HasMaximizeButton, 2596). +-define(wxAuiPaneInfo_HasMinimizeButton, 2597). +-define(wxAuiPaneInfo_HasPinButton, 2598). +-define(wxAuiPaneInfo_Hide, 2599). +-define(wxAuiPaneInfo_IsBottomDockable, 2600). +-define(wxAuiPaneInfo_IsDocked, 2601). +-define(wxAuiPaneInfo_IsFixed, 2602). +-define(wxAuiPaneInfo_IsFloatable, 2603). +-define(wxAuiPaneInfo_IsFloating, 2604). +-define(wxAuiPaneInfo_IsLeftDockable, 2605). +-define(wxAuiPaneInfo_IsMovable, 2606). +-define(wxAuiPaneInfo_IsOk, 2607). +-define(wxAuiPaneInfo_IsResizable, 2608). +-define(wxAuiPaneInfo_IsRightDockable, 2609). +-define(wxAuiPaneInfo_IsShown, 2610). +-define(wxAuiPaneInfo_IsToolbar, 2611). +-define(wxAuiPaneInfo_IsTopDockable, 2612). +-define(wxAuiPaneInfo_Layer, 2613). +-define(wxAuiPaneInfo_Left, 2614). +-define(wxAuiPaneInfo_LeftDockable, 2615). +-define(wxAuiPaneInfo_MaxSize_1, 2616). +-define(wxAuiPaneInfo_MaxSize_2, 2617). +-define(wxAuiPaneInfo_MaximizeButton, 2618). +-define(wxAuiPaneInfo_MinSize_1, 2619). +-define(wxAuiPaneInfo_MinSize_2, 2620). +-define(wxAuiPaneInfo_MinimizeButton, 2621). +-define(wxAuiPaneInfo_Movable, 2622). +-define(wxAuiPaneInfo_Name, 2623). +-define(wxAuiPaneInfo_PaneBorder, 2624). +-define(wxAuiPaneInfo_PinButton, 2625). +-define(wxAuiPaneInfo_Position, 2626). +-define(wxAuiPaneInfo_Resizable, 2627). +-define(wxAuiPaneInfo_Right, 2628). +-define(wxAuiPaneInfo_RightDockable, 2629). +-define(wxAuiPaneInfo_Row, 2630). +-define(wxAuiPaneInfo_SafeSet, 2631). +-define(wxAuiPaneInfo_SetFlag, 2632). +-define(wxAuiPaneInfo_Show, 2633). +-define(wxAuiPaneInfo_ToolbarPane, 2634). +-define(wxAuiPaneInfo_Top, 2635). +-define(wxAuiPaneInfo_TopDockable, 2636). +-define(wxAuiPaneInfo_Window, 2637). +-define(wxAuiNotebook_new_0, 2638). +-define(wxAuiNotebook_new_2, 2639). +-define(wxAuiNotebook_AddPage, 2640). +-define(wxAuiNotebook_Create, 2641). +-define(wxAuiNotebook_DeletePage, 2642). +-define(wxAuiNotebook_GetArtProvider, 2643). +-define(wxAuiNotebook_GetPage, 2644). +-define(wxAuiNotebook_GetPageBitmap, 2645). +-define(wxAuiNotebook_GetPageCount, 2646). +-define(wxAuiNotebook_GetPageIndex, 2647). +-define(wxAuiNotebook_GetPageText, 2648). +-define(wxAuiNotebook_GetSelection, 2649). +-define(wxAuiNotebook_InsertPage, 2650). +-define(wxAuiNotebook_RemovePage, 2651). +-define(wxAuiNotebook_SetArtProvider, 2652). +-define(wxAuiNotebook_SetFont, 2653). +-define(wxAuiNotebook_SetPageBitmap, 2654). +-define(wxAuiNotebook_SetPageText, 2655). +-define(wxAuiNotebook_SetSelection, 2656). +-define(wxAuiNotebook_SetTabCtrlHeight, 2657). +-define(wxAuiNotebook_SetUniformBitmapSize, 2658). +-define(wxAuiNotebook_destroy, 2659). +-define(wxMDIParentFrame_new_0, 2660). +-define(wxMDIParentFrame_new_4, 2661). +-define(wxMDIParentFrame_destruct, 2662). +-define(wxMDIParentFrame_ActivateNext, 2663). +-define(wxMDIParentFrame_ActivatePrevious, 2664). +-define(wxMDIParentFrame_ArrangeIcons, 2665). +-define(wxMDIParentFrame_Cascade, 2666). +-define(wxMDIParentFrame_Create, 2667). +-define(wxMDIParentFrame_GetActiveChild, 2668). +-define(wxMDIParentFrame_GetClientWindow, 2669). +-define(wxMDIParentFrame_Tile, 2670). +-define(wxMDIChildFrame_new_0, 2671). +-define(wxMDIChildFrame_new_4, 2672). +-define(wxMDIChildFrame_destruct, 2673). +-define(wxMDIChildFrame_Activate, 2674). +-define(wxMDIChildFrame_Create, 2675). +-define(wxMDIChildFrame_Maximize, 2676). +-define(wxMDIChildFrame_Restore, 2677). +-define(wxMDIClientWindow_new_0, 2678). +-define(wxMDIClientWindow_new_2, 2679). +-define(wxMDIClientWindow_destruct, 2680). +-define(wxMDIClientWindow_CreateClient, 2681). +-define(wxLayoutAlgorithm_new, 2682). +-define(wxLayoutAlgorithm_LayoutFrame, 2683). +-define(wxLayoutAlgorithm_LayoutMDIFrame, 2684). +-define(wxLayoutAlgorithm_LayoutWindow, 2685). +-define(wxLayoutAlgorithm_destroy, 2686). +-define(wxEvent_GetId, 2687). +-define(wxEvent_GetSkipped, 2688). +-define(wxEvent_GetTimestamp, 2689). +-define(wxEvent_IsCommandEvent, 2690). +-define(wxEvent_ResumePropagation, 2691). +-define(wxEvent_ShouldPropagate, 2692). +-define(wxEvent_Skip, 2693). +-define(wxEvent_StopPropagation, 2694). +-define(wxCommandEvent_getClientData, 2695). +-define(wxCommandEvent_GetExtraLong, 2696). +-define(wxCommandEvent_GetInt, 2697). +-define(wxCommandEvent_GetSelection, 2698). +-define(wxCommandEvent_GetString, 2699). +-define(wxCommandEvent_IsChecked, 2700). +-define(wxCommandEvent_IsSelection, 2701). +-define(wxCommandEvent_SetInt, 2702). +-define(wxCommandEvent_SetString, 2703). +-define(wxScrollEvent_GetOrientation, 2704). +-define(wxScrollEvent_GetPosition, 2705). +-define(wxScrollWinEvent_GetOrientation, 2706). +-define(wxScrollWinEvent_GetPosition, 2707). +-define(wxMouseEvent_AltDown, 2708). +-define(wxMouseEvent_Button, 2709). +-define(wxMouseEvent_ButtonDClick, 2710). +-define(wxMouseEvent_ButtonDown, 2711). +-define(wxMouseEvent_ButtonUp, 2712). +-define(wxMouseEvent_CmdDown, 2713). +-define(wxMouseEvent_ControlDown, 2714). +-define(wxMouseEvent_Dragging, 2715). +-define(wxMouseEvent_Entering, 2716). +-define(wxMouseEvent_GetButton, 2717). +-define(wxMouseEvent_GetPosition, 2720). +-define(wxMouseEvent_GetLogicalPosition, 2721). +-define(wxMouseEvent_GetLinesPerAction, 2722). +-define(wxMouseEvent_GetWheelRotation, 2723). +-define(wxMouseEvent_GetWheelDelta, 2724). +-define(wxMouseEvent_GetX, 2725). +-define(wxMouseEvent_GetY, 2726). +-define(wxMouseEvent_IsButton, 2727). +-define(wxMouseEvent_IsPageScroll, 2728). +-define(wxMouseEvent_Leaving, 2729). +-define(wxMouseEvent_LeftDClick, 2730). +-define(wxMouseEvent_LeftDown, 2731). +-define(wxMouseEvent_LeftIsDown, 2732). +-define(wxMouseEvent_LeftUp, 2733). +-define(wxMouseEvent_MetaDown, 2734). +-define(wxMouseEvent_MiddleDClick, 2735). +-define(wxMouseEvent_MiddleDown, 2736). +-define(wxMouseEvent_MiddleIsDown, 2737). +-define(wxMouseEvent_MiddleUp, 2738). +-define(wxMouseEvent_Moving, 2739). +-define(wxMouseEvent_RightDClick, 2740). +-define(wxMouseEvent_RightDown, 2741). +-define(wxMouseEvent_RightIsDown, 2742). +-define(wxMouseEvent_RightUp, 2743). +-define(wxMouseEvent_ShiftDown, 2744). +-define(wxSetCursorEvent_GetCursor, 2745). +-define(wxSetCursorEvent_GetX, 2746). +-define(wxSetCursorEvent_GetY, 2747). +-define(wxSetCursorEvent_HasCursor, 2748). +-define(wxSetCursorEvent_SetCursor, 2749). +-define(wxKeyEvent_AltDown, 2750). +-define(wxKeyEvent_CmdDown, 2751). +-define(wxKeyEvent_ControlDown, 2752). +-define(wxKeyEvent_GetKeyCode, 2753). +-define(wxKeyEvent_GetModifiers, 2754). +-define(wxKeyEvent_GetPosition, 2757). +-define(wxKeyEvent_GetRawKeyCode, 2758). +-define(wxKeyEvent_GetRawKeyFlags, 2759). +-define(wxKeyEvent_GetUnicodeKey, 2760). +-define(wxKeyEvent_GetX, 2761). +-define(wxKeyEvent_GetY, 2762). +-define(wxKeyEvent_HasModifiers, 2763). +-define(wxKeyEvent_MetaDown, 2764). +-define(wxKeyEvent_ShiftDown, 2765). +-define(wxSizeEvent_GetSize, 2766). +-define(wxMoveEvent_GetPosition, 2767). +-define(wxEraseEvent_GetDC, 2768). +-define(wxFocusEvent_GetWindow, 2769). +-define(wxChildFocusEvent_GetWindow, 2770). +-define(wxMenuEvent_GetMenu, 2771). +-define(wxMenuEvent_GetMenuId, 2772). +-define(wxMenuEvent_IsPopup, 2773). +-define(wxCloseEvent_CanVeto, 2774). +-define(wxCloseEvent_GetLoggingOff, 2775). +-define(wxCloseEvent_SetCanVeto, 2776). +-define(wxCloseEvent_SetLoggingOff, 2777). +-define(wxCloseEvent_Veto, 2778). +-define(wxShowEvent_SetShow, 2779). +-define(wxShowEvent_GetShow, 2780). +-define(wxIconizeEvent_Iconized, 2781). +-define(wxJoystickEvent_ButtonDown, 2782). +-define(wxJoystickEvent_ButtonIsDown, 2783). +-define(wxJoystickEvent_ButtonUp, 2784). +-define(wxJoystickEvent_GetButtonChange, 2785). +-define(wxJoystickEvent_GetButtonState, 2786). +-define(wxJoystickEvent_GetJoystick, 2787). +-define(wxJoystickEvent_GetPosition, 2788). +-define(wxJoystickEvent_GetZPosition, 2789). +-define(wxJoystickEvent_IsButton, 2790). +-define(wxJoystickEvent_IsMove, 2791). +-define(wxJoystickEvent_IsZMove, 2792). +-define(wxUpdateUIEvent_CanUpdate, 2793). +-define(wxUpdateUIEvent_Check, 2794). +-define(wxUpdateUIEvent_Enable, 2795). +-define(wxUpdateUIEvent_Show, 2796). +-define(wxUpdateUIEvent_GetChecked, 2797). +-define(wxUpdateUIEvent_GetEnabled, 2798). +-define(wxUpdateUIEvent_GetShown, 2799). +-define(wxUpdateUIEvent_GetSetChecked, 2800). +-define(wxUpdateUIEvent_GetSetEnabled, 2801). +-define(wxUpdateUIEvent_GetSetShown, 2802). +-define(wxUpdateUIEvent_GetSetText, 2803). +-define(wxUpdateUIEvent_GetText, 2804). +-define(wxUpdateUIEvent_GetMode, 2805). +-define(wxUpdateUIEvent_GetUpdateInterval, 2806). +-define(wxUpdateUIEvent_ResetUpdateTime, 2807). +-define(wxUpdateUIEvent_SetMode, 2808). +-define(wxUpdateUIEvent_SetText, 2809). +-define(wxUpdateUIEvent_SetUpdateInterval, 2810). +-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2811). +-define(wxPaletteChangedEvent_SetChangedWindow, 2812). +-define(wxPaletteChangedEvent_GetChangedWindow, 2813). +-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2814). +-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2815). +-define(wxNavigationKeyEvent_GetDirection, 2816). +-define(wxNavigationKeyEvent_SetDirection, 2817). +-define(wxNavigationKeyEvent_IsWindowChange, 2818). +-define(wxNavigationKeyEvent_SetWindowChange, 2819). +-define(wxNavigationKeyEvent_IsFromTab, 2820). +-define(wxNavigationKeyEvent_SetFromTab, 2821). +-define(wxNavigationKeyEvent_GetCurrentFocus, 2822). +-define(wxNavigationKeyEvent_SetCurrentFocus, 2823). +-define(wxHelpEvent_GetOrigin, 2824). +-define(wxHelpEvent_GetPosition, 2825). +-define(wxHelpEvent_SetOrigin, 2826). +-define(wxHelpEvent_SetPosition, 2827). +-define(wxContextMenuEvent_GetPosition, 2828). +-define(wxContextMenuEvent_SetPosition, 2829). +-define(wxIdleEvent_CanSend, 2830). +-define(wxIdleEvent_GetMode, 2831). +-define(wxIdleEvent_RequestMore, 2832). +-define(wxIdleEvent_MoreRequested, 2833). +-define(wxIdleEvent_SetMode, 2834). +-define(wxGridEvent_AltDown, 2835). +-define(wxGridEvent_ControlDown, 2836). +-define(wxGridEvent_GetCol, 2837). +-define(wxGridEvent_GetPosition, 2838). +-define(wxGridEvent_GetRow, 2839). +-define(wxGridEvent_MetaDown, 2840). +-define(wxGridEvent_Selecting, 2841). +-define(wxGridEvent_ShiftDown, 2842). +-define(wxNotifyEvent_Allow, 2843). +-define(wxNotifyEvent_IsAllowed, 2844). +-define(wxNotifyEvent_Veto, 2845). +-define(wxSashEvent_GetEdge, 2846). +-define(wxSashEvent_GetDragRect, 2847). +-define(wxSashEvent_GetDragStatus, 2848). +-define(wxListEvent_GetCacheFrom, 2849). +-define(wxListEvent_GetCacheTo, 2850). +-define(wxListEvent_GetKeyCode, 2851). +-define(wxListEvent_GetIndex, 2852). +-define(wxListEvent_GetColumn, 2853). +-define(wxListEvent_GetPoint, 2854). +-define(wxListEvent_GetLabel, 2855). +-define(wxListEvent_GetText, 2856). +-define(wxListEvent_GetImage, 2857). +-define(wxListEvent_GetData, 2858). +-define(wxListEvent_GetMask, 2859). +-define(wxListEvent_GetItem, 2860). +-define(wxListEvent_IsEditCancelled, 2861). +-define(wxDateEvent_GetDate, 2862). +-define(wxCalendarEvent_GetWeekDay, 2863). +-define(wxFileDirPickerEvent_GetPath, 2864). +-define(wxColourPickerEvent_GetColour, 2865). +-define(wxFontPickerEvent_GetFont, 2866). +-define(wxStyledTextEvent_GetPosition, 2867). +-define(wxStyledTextEvent_GetKey, 2868). +-define(wxStyledTextEvent_GetModifiers, 2869). +-define(wxStyledTextEvent_GetModificationType, 2870). +-define(wxStyledTextEvent_GetText, 2871). +-define(wxStyledTextEvent_GetLength, 2872). +-define(wxStyledTextEvent_GetLinesAdded, 2873). +-define(wxStyledTextEvent_GetLine, 2874). +-define(wxStyledTextEvent_GetFoldLevelNow, 2875). +-define(wxStyledTextEvent_GetFoldLevelPrev, 2876). +-define(wxStyledTextEvent_GetMargin, 2877). +-define(wxStyledTextEvent_GetMessage, 2878). +-define(wxStyledTextEvent_GetWParam, 2879). +-define(wxStyledTextEvent_GetLParam, 2880). +-define(wxStyledTextEvent_GetListType, 2881). +-define(wxStyledTextEvent_GetX, 2882). +-define(wxStyledTextEvent_GetY, 2883). +-define(wxStyledTextEvent_GetDragText, 2884). +-define(wxStyledTextEvent_GetDragAllowMove, 2885). +-define(wxStyledTextEvent_GetDragResult, 2886). +-define(wxStyledTextEvent_GetShift, 2887). +-define(wxStyledTextEvent_GetControl, 2888). +-define(wxStyledTextEvent_GetAlt, 2889). +-define(utils_wxGetKeyState, 2890). +-define(utils_wxGetMousePosition, 2891). +-define(utils_wxGetMouseState, 2892). +-define(utils_wxSetDetectableAutoRepeat, 2893). +-define(utils_wxBell, 2894). +-define(utils_wxFindMenuItemId, 2895). +-define(utils_wxGenericFindWindowAtPoint, 2896). +-define(utils_wxFindWindowAtPoint, 2897). +-define(utils_wxBeginBusyCursor, 2898). +-define(utils_wxEndBusyCursor, 2899). +-define(utils_wxIsBusy, 2900). +-define(utils_wxShutdown, 2901). +-define(utils_wxShell, 2902). +-define(utils_wxLaunchDefaultBrowser, 2903). +-define(utils_wxGetEmailAddress, 2904). +-define(utils_wxGetUserId, 2905). +-define(utils_wxGetHomeDir, 2906). +-define(utils_wxNewId, 2907). +-define(utils_wxRegisterId, 2908). +-define(utils_wxGetCurrentId, 2909). +-define(utils_wxGetOsDescription, 2910). +-define(utils_wxIsPlatformLittleEndian, 2911). +-define(utils_wxIsPlatform64Bit, 2912). +-define(wxPrintout_new, 2913). +-define(wxPrintout_destruct, 2914). +-define(wxPrintout_GetDC, 2915). +-define(wxPrintout_GetPageSizeMM, 2916). +-define(wxPrintout_GetPageSizePixels, 2917). +-define(wxPrintout_GetPaperRectPixels, 2918). +-define(wxPrintout_GetPPIPrinter, 2919). +-define(wxPrintout_GetPPIScreen, 2920). +-define(wxPrintout_GetTitle, 2921). +-define(wxPrintout_IsPreview, 2922). +-define(wxPrintout_FitThisSizeToPaper, 2923). +-define(wxPrintout_FitThisSizeToPage, 2924). +-define(wxPrintout_FitThisSizeToPageMargins, 2925). +-define(wxPrintout_MapScreenSizeToPaper, 2926). +-define(wxPrintout_MapScreenSizeToPage, 2927). +-define(wxPrintout_MapScreenSizeToPageMargins, 2928). +-define(wxPrintout_MapScreenSizeToDevice, 2929). +-define(wxPrintout_GetLogicalPaperRect, 2930). +-define(wxPrintout_GetLogicalPageRect, 2931). +-define(wxPrintout_GetLogicalPageMarginsRect, 2932). +-define(wxPrintout_SetLogicalOrigin, 2933). +-define(wxPrintout_OffsetLogicalOrigin, 2934). +-define(wxStyledTextCtrl_new_2, 2935). +-define(wxStyledTextCtrl_new_0, 2936). +-define(wxStyledTextCtrl_destruct, 2937). +-define(wxStyledTextCtrl_Create, 2938). +-define(wxStyledTextCtrl_AddText, 2939). +-define(wxStyledTextCtrl_AddStyledText, 2940). +-define(wxStyledTextCtrl_InsertText, 2941). +-define(wxStyledTextCtrl_ClearAll, 2942). +-define(wxStyledTextCtrl_ClearDocumentStyle, 2943). +-define(wxStyledTextCtrl_GetLength, 2944). +-define(wxStyledTextCtrl_GetCharAt, 2945). +-define(wxStyledTextCtrl_GetCurrentPos, 2946). +-define(wxStyledTextCtrl_GetAnchor, 2947). +-define(wxStyledTextCtrl_GetStyleAt, 2948). +-define(wxStyledTextCtrl_Redo, 2949). +-define(wxStyledTextCtrl_SetUndoCollection, 2950). +-define(wxStyledTextCtrl_SelectAll, 2951). +-define(wxStyledTextCtrl_SetSavePoint, 2952). +-define(wxStyledTextCtrl_GetStyledText, 2953). +-define(wxStyledTextCtrl_CanRedo, 2954). +-define(wxStyledTextCtrl_MarkerLineFromHandle, 2955). +-define(wxStyledTextCtrl_MarkerDeleteHandle, 2956). +-define(wxStyledTextCtrl_GetUndoCollection, 2957). +-define(wxStyledTextCtrl_GetViewWhiteSpace, 2958). +-define(wxStyledTextCtrl_SetViewWhiteSpace, 2959). +-define(wxStyledTextCtrl_PositionFromPoint, 2960). +-define(wxStyledTextCtrl_PositionFromPointClose, 2961). +-define(wxStyledTextCtrl_GotoLine, 2962). +-define(wxStyledTextCtrl_GotoPos, 2963). +-define(wxStyledTextCtrl_SetAnchor, 2964). +-define(wxStyledTextCtrl_GetCurLine, 2965). +-define(wxStyledTextCtrl_GetEndStyled, 2966). +-define(wxStyledTextCtrl_ConvertEOLs, 2967). +-define(wxStyledTextCtrl_GetEOLMode, 2968). +-define(wxStyledTextCtrl_SetEOLMode, 2969). +-define(wxStyledTextCtrl_StartStyling, 2970). +-define(wxStyledTextCtrl_SetStyling, 2971). +-define(wxStyledTextCtrl_GetBufferedDraw, 2972). +-define(wxStyledTextCtrl_SetBufferedDraw, 2973). +-define(wxStyledTextCtrl_SetTabWidth, 2974). +-define(wxStyledTextCtrl_GetTabWidth, 2975). +-define(wxStyledTextCtrl_SetCodePage, 2976). +-define(wxStyledTextCtrl_MarkerDefine, 2977). +-define(wxStyledTextCtrl_MarkerSetForeground, 2978). +-define(wxStyledTextCtrl_MarkerSetBackground, 2979). +-define(wxStyledTextCtrl_MarkerAdd, 2980). +-define(wxStyledTextCtrl_MarkerDelete, 2981). +-define(wxStyledTextCtrl_MarkerDeleteAll, 2982). +-define(wxStyledTextCtrl_MarkerGet, 2983). +-define(wxStyledTextCtrl_MarkerNext, 2984). +-define(wxStyledTextCtrl_MarkerPrevious, 2985). +-define(wxStyledTextCtrl_MarkerDefineBitmap, 2986). +-define(wxStyledTextCtrl_MarkerAddSet, 2987). +-define(wxStyledTextCtrl_MarkerSetAlpha, 2988). +-define(wxStyledTextCtrl_SetMarginType, 2989). +-define(wxStyledTextCtrl_GetMarginType, 2990). +-define(wxStyledTextCtrl_SetMarginWidth, 2991). +-define(wxStyledTextCtrl_GetMarginWidth, 2992). +-define(wxStyledTextCtrl_SetMarginMask, 2993). +-define(wxStyledTextCtrl_GetMarginMask, 2994). +-define(wxStyledTextCtrl_SetMarginSensitive, 2995). +-define(wxStyledTextCtrl_GetMarginSensitive, 2996). +-define(wxStyledTextCtrl_StyleClearAll, 2997). +-define(wxStyledTextCtrl_StyleSetForeground, 2998). +-define(wxStyledTextCtrl_StyleSetBackground, 2999). +-define(wxStyledTextCtrl_StyleSetBold, 3000). +-define(wxStyledTextCtrl_StyleSetItalic, 3001). +-define(wxStyledTextCtrl_StyleSetSize, 3002). +-define(wxStyledTextCtrl_StyleSetFaceName, 3003). +-define(wxStyledTextCtrl_StyleSetEOLFilled, 3004). +-define(wxStyledTextCtrl_StyleResetDefault, 3005). +-define(wxStyledTextCtrl_StyleSetUnderline, 3006). +-define(wxStyledTextCtrl_StyleSetCase, 3007). +-define(wxStyledTextCtrl_StyleSetHotSpot, 3008). +-define(wxStyledTextCtrl_SetSelForeground, 3009). +-define(wxStyledTextCtrl_SetSelBackground, 3010). +-define(wxStyledTextCtrl_GetSelAlpha, 3011). +-define(wxStyledTextCtrl_SetSelAlpha, 3012). +-define(wxStyledTextCtrl_SetCaretForeground, 3013). +-define(wxStyledTextCtrl_CmdKeyAssign, 3014). +-define(wxStyledTextCtrl_CmdKeyClear, 3015). +-define(wxStyledTextCtrl_CmdKeyClearAll, 3016). +-define(wxStyledTextCtrl_SetStyleBytes, 3017). +-define(wxStyledTextCtrl_StyleSetVisible, 3018). +-define(wxStyledTextCtrl_GetCaretPeriod, 3019). +-define(wxStyledTextCtrl_SetCaretPeriod, 3020). +-define(wxStyledTextCtrl_SetWordChars, 3021). +-define(wxStyledTextCtrl_BeginUndoAction, 3022). +-define(wxStyledTextCtrl_EndUndoAction, 3023). +-define(wxStyledTextCtrl_IndicatorSetStyle, 3024). +-define(wxStyledTextCtrl_IndicatorGetStyle, 3025). +-define(wxStyledTextCtrl_IndicatorSetForeground, 3026). +-define(wxStyledTextCtrl_IndicatorGetForeground, 3027). +-define(wxStyledTextCtrl_SetWhitespaceForeground, 3028). +-define(wxStyledTextCtrl_SetWhitespaceBackground, 3029). +-define(wxStyledTextCtrl_GetStyleBits, 3030). +-define(wxStyledTextCtrl_SetLineState, 3031). +-define(wxStyledTextCtrl_GetLineState, 3032). +-define(wxStyledTextCtrl_GetMaxLineState, 3033). +-define(wxStyledTextCtrl_GetCaretLineVisible, 3034). +-define(wxStyledTextCtrl_SetCaretLineVisible, 3035). +-define(wxStyledTextCtrl_GetCaretLineBackground, 3036). +-define(wxStyledTextCtrl_SetCaretLineBackground, 3037). +-define(wxStyledTextCtrl_AutoCompShow, 3038). +-define(wxStyledTextCtrl_AutoCompCancel, 3039). +-define(wxStyledTextCtrl_AutoCompActive, 3040). +-define(wxStyledTextCtrl_AutoCompPosStart, 3041). +-define(wxStyledTextCtrl_AutoCompComplete, 3042). +-define(wxStyledTextCtrl_AutoCompStops, 3043). +-define(wxStyledTextCtrl_AutoCompSetSeparator, 3044). +-define(wxStyledTextCtrl_AutoCompGetSeparator, 3045). +-define(wxStyledTextCtrl_AutoCompSelect, 3046). +-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3047). +-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3048). +-define(wxStyledTextCtrl_AutoCompSetFillUps, 3049). +-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3050). +-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3051). +-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3052). +-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3053). +-define(wxStyledTextCtrl_UserListShow, 3054). +-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3055). +-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3056). +-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3057). +-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3058). +-define(wxStyledTextCtrl_RegisterImage, 3059). +-define(wxStyledTextCtrl_ClearRegisteredImages, 3060). +-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3061). +-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3062). +-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3063). +-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3064). +-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3065). +-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3066). +-define(wxStyledTextCtrl_SetIndent, 3067). +-define(wxStyledTextCtrl_GetIndent, 3068). +-define(wxStyledTextCtrl_SetUseTabs, 3069). +-define(wxStyledTextCtrl_GetUseTabs, 3070). +-define(wxStyledTextCtrl_SetLineIndentation, 3071). +-define(wxStyledTextCtrl_GetLineIndentation, 3072). +-define(wxStyledTextCtrl_GetLineIndentPosition, 3073). +-define(wxStyledTextCtrl_GetColumn, 3074). +-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3075). +-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3076). +-define(wxStyledTextCtrl_SetIndentationGuides, 3077). +-define(wxStyledTextCtrl_GetIndentationGuides, 3078). +-define(wxStyledTextCtrl_SetHighlightGuide, 3079). +-define(wxStyledTextCtrl_GetHighlightGuide, 3080). +-define(wxStyledTextCtrl_GetLineEndPosition, 3081). +-define(wxStyledTextCtrl_GetCodePage, 3082). +-define(wxStyledTextCtrl_GetCaretForeground, 3083). +-define(wxStyledTextCtrl_GetReadOnly, 3084). +-define(wxStyledTextCtrl_SetCurrentPos, 3085). +-define(wxStyledTextCtrl_SetSelectionStart, 3086). +-define(wxStyledTextCtrl_GetSelectionStart, 3087). +-define(wxStyledTextCtrl_SetSelectionEnd, 3088). +-define(wxStyledTextCtrl_GetSelectionEnd, 3089). +-define(wxStyledTextCtrl_SetPrintMagnification, 3090). +-define(wxStyledTextCtrl_GetPrintMagnification, 3091). +-define(wxStyledTextCtrl_SetPrintColourMode, 3092). +-define(wxStyledTextCtrl_GetPrintColourMode, 3093). +-define(wxStyledTextCtrl_FindText, 3094). +-define(wxStyledTextCtrl_FormatRange, 3095). +-define(wxStyledTextCtrl_GetFirstVisibleLine, 3096). +-define(wxStyledTextCtrl_GetLine, 3097). +-define(wxStyledTextCtrl_GetLineCount, 3098). +-define(wxStyledTextCtrl_SetMarginLeft, 3099). +-define(wxStyledTextCtrl_GetMarginLeft, 3100). +-define(wxStyledTextCtrl_SetMarginRight, 3101). +-define(wxStyledTextCtrl_GetMarginRight, 3102). +-define(wxStyledTextCtrl_GetModify, 3103). +-define(wxStyledTextCtrl_SetSelection, 3104). +-define(wxStyledTextCtrl_GetSelectedText, 3105). +-define(wxStyledTextCtrl_GetTextRange, 3106). +-define(wxStyledTextCtrl_HideSelection, 3107). +-define(wxStyledTextCtrl_LineFromPosition, 3108). +-define(wxStyledTextCtrl_PositionFromLine, 3109). +-define(wxStyledTextCtrl_LineScroll, 3110). +-define(wxStyledTextCtrl_EnsureCaretVisible, 3111). +-define(wxStyledTextCtrl_ReplaceSelection, 3112). +-define(wxStyledTextCtrl_SetReadOnly, 3113). +-define(wxStyledTextCtrl_CanPaste, 3114). +-define(wxStyledTextCtrl_CanUndo, 3115). +-define(wxStyledTextCtrl_EmptyUndoBuffer, 3116). +-define(wxStyledTextCtrl_Undo, 3117). +-define(wxStyledTextCtrl_Cut, 3118). +-define(wxStyledTextCtrl_Copy, 3119). +-define(wxStyledTextCtrl_Paste, 3120). +-define(wxStyledTextCtrl_Clear, 3121). +-define(wxStyledTextCtrl_SetText, 3122). +-define(wxStyledTextCtrl_GetText, 3123). +-define(wxStyledTextCtrl_GetTextLength, 3124). +-define(wxStyledTextCtrl_GetOvertype, 3125). +-define(wxStyledTextCtrl_SetCaretWidth, 3126). +-define(wxStyledTextCtrl_GetCaretWidth, 3127). +-define(wxStyledTextCtrl_SetTargetStart, 3128). +-define(wxStyledTextCtrl_GetTargetStart, 3129). +-define(wxStyledTextCtrl_SetTargetEnd, 3130). +-define(wxStyledTextCtrl_GetTargetEnd, 3131). +-define(wxStyledTextCtrl_ReplaceTarget, 3132). +-define(wxStyledTextCtrl_SearchInTarget, 3133). +-define(wxStyledTextCtrl_SetSearchFlags, 3134). +-define(wxStyledTextCtrl_GetSearchFlags, 3135). +-define(wxStyledTextCtrl_CallTipShow, 3136). +-define(wxStyledTextCtrl_CallTipCancel, 3137). +-define(wxStyledTextCtrl_CallTipActive, 3138). +-define(wxStyledTextCtrl_CallTipPosAtStart, 3139). +-define(wxStyledTextCtrl_CallTipSetHighlight, 3140). +-define(wxStyledTextCtrl_CallTipSetBackground, 3141). +-define(wxStyledTextCtrl_CallTipSetForeground, 3142). +-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3143). +-define(wxStyledTextCtrl_CallTipUseStyle, 3144). +-define(wxStyledTextCtrl_VisibleFromDocLine, 3145). +-define(wxStyledTextCtrl_DocLineFromVisible, 3146). +-define(wxStyledTextCtrl_WrapCount, 3147). +-define(wxStyledTextCtrl_SetFoldLevel, 3148). +-define(wxStyledTextCtrl_GetFoldLevel, 3149). +-define(wxStyledTextCtrl_GetLastChild, 3150). +-define(wxStyledTextCtrl_GetFoldParent, 3151). +-define(wxStyledTextCtrl_ShowLines, 3152). +-define(wxStyledTextCtrl_HideLines, 3153). +-define(wxStyledTextCtrl_GetLineVisible, 3154). +-define(wxStyledTextCtrl_SetFoldExpanded, 3155). +-define(wxStyledTextCtrl_GetFoldExpanded, 3156). +-define(wxStyledTextCtrl_ToggleFold, 3157). +-define(wxStyledTextCtrl_EnsureVisible, 3158). +-define(wxStyledTextCtrl_SetFoldFlags, 3159). +-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3160). +-define(wxStyledTextCtrl_SetTabIndents, 3161). +-define(wxStyledTextCtrl_GetTabIndents, 3162). +-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3163). +-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3164). +-define(wxStyledTextCtrl_SetMouseDwellTime, 3165). +-define(wxStyledTextCtrl_GetMouseDwellTime, 3166). +-define(wxStyledTextCtrl_WordStartPosition, 3167). +-define(wxStyledTextCtrl_WordEndPosition, 3168). +-define(wxStyledTextCtrl_SetWrapMode, 3169). +-define(wxStyledTextCtrl_GetWrapMode, 3170). +-define(wxStyledTextCtrl_SetWrapVisualFlags, 3171). +-define(wxStyledTextCtrl_GetWrapVisualFlags, 3172). +-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3173). +-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3174). +-define(wxStyledTextCtrl_SetWrapStartIndent, 3175). +-define(wxStyledTextCtrl_GetWrapStartIndent, 3176). +-define(wxStyledTextCtrl_SetLayoutCache, 3177). +-define(wxStyledTextCtrl_GetLayoutCache, 3178). +-define(wxStyledTextCtrl_SetScrollWidth, 3179). +-define(wxStyledTextCtrl_GetScrollWidth, 3180). +-define(wxStyledTextCtrl_TextWidth, 3181). +-define(wxStyledTextCtrl_GetEndAtLastLine, 3182). +-define(wxStyledTextCtrl_TextHeight, 3183). +-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3184). +-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3185). +-define(wxStyledTextCtrl_AppendText, 3186). +-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3187). +-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3188). +-define(wxStyledTextCtrl_TargetFromSelection, 3189). +-define(wxStyledTextCtrl_LinesJoin, 3190). +-define(wxStyledTextCtrl_LinesSplit, 3191). +-define(wxStyledTextCtrl_SetFoldMarginColour, 3192). +-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3193). +-define(wxStyledTextCtrl_LineDown, 3194). +-define(wxStyledTextCtrl_LineDownExtend, 3195). +-define(wxStyledTextCtrl_LineUp, 3196). +-define(wxStyledTextCtrl_LineUpExtend, 3197). +-define(wxStyledTextCtrl_CharLeft, 3198). +-define(wxStyledTextCtrl_CharLeftExtend, 3199). +-define(wxStyledTextCtrl_CharRight, 3200). +-define(wxStyledTextCtrl_CharRightExtend, 3201). +-define(wxStyledTextCtrl_WordLeft, 3202). +-define(wxStyledTextCtrl_WordLeftExtend, 3203). +-define(wxStyledTextCtrl_WordRight, 3204). +-define(wxStyledTextCtrl_WordRightExtend, 3205). +-define(wxStyledTextCtrl_Home, 3206). +-define(wxStyledTextCtrl_HomeExtend, 3207). +-define(wxStyledTextCtrl_LineEnd, 3208). +-define(wxStyledTextCtrl_LineEndExtend, 3209). +-define(wxStyledTextCtrl_DocumentStart, 3210). +-define(wxStyledTextCtrl_DocumentStartExtend, 3211). +-define(wxStyledTextCtrl_DocumentEnd, 3212). +-define(wxStyledTextCtrl_DocumentEndExtend, 3213). +-define(wxStyledTextCtrl_PageUp, 3214). +-define(wxStyledTextCtrl_PageUpExtend, 3215). +-define(wxStyledTextCtrl_PageDown, 3216). +-define(wxStyledTextCtrl_PageDownExtend, 3217). +-define(wxStyledTextCtrl_EditToggleOvertype, 3218). +-define(wxStyledTextCtrl_Cancel, 3219). +-define(wxStyledTextCtrl_DeleteBack, 3220). +-define(wxStyledTextCtrl_Tab, 3221). +-define(wxStyledTextCtrl_BackTab, 3222). +-define(wxStyledTextCtrl_NewLine, 3223). +-define(wxStyledTextCtrl_FormFeed, 3224). +-define(wxStyledTextCtrl_VCHome, 3225). +-define(wxStyledTextCtrl_VCHomeExtend, 3226). +-define(wxStyledTextCtrl_ZoomIn, 3227). +-define(wxStyledTextCtrl_ZoomOut, 3228). +-define(wxStyledTextCtrl_DelWordLeft, 3229). +-define(wxStyledTextCtrl_DelWordRight, 3230). +-define(wxStyledTextCtrl_LineCut, 3231). +-define(wxStyledTextCtrl_LineDelete, 3232). +-define(wxStyledTextCtrl_LineTranspose, 3233). +-define(wxStyledTextCtrl_LineDuplicate, 3234). +-define(wxStyledTextCtrl_LowerCase, 3235). +-define(wxStyledTextCtrl_UpperCase, 3236). +-define(wxStyledTextCtrl_LineScrollDown, 3237). +-define(wxStyledTextCtrl_LineScrollUp, 3238). +-define(wxStyledTextCtrl_DeleteBackNotLine, 3239). +-define(wxStyledTextCtrl_HomeDisplay, 3240). +-define(wxStyledTextCtrl_HomeDisplayExtend, 3241). +-define(wxStyledTextCtrl_LineEndDisplay, 3242). +-define(wxStyledTextCtrl_LineEndDisplayExtend, 3243). +-define(wxStyledTextCtrl_HomeWrapExtend, 3244). +-define(wxStyledTextCtrl_LineEndWrap, 3245). +-define(wxStyledTextCtrl_LineEndWrapExtend, 3246). +-define(wxStyledTextCtrl_VCHomeWrap, 3247). +-define(wxStyledTextCtrl_VCHomeWrapExtend, 3248). +-define(wxStyledTextCtrl_LineCopy, 3249). +-define(wxStyledTextCtrl_MoveCaretInsideView, 3250). +-define(wxStyledTextCtrl_LineLength, 3251). +-define(wxStyledTextCtrl_BraceHighlight, 3252). +-define(wxStyledTextCtrl_BraceBadLight, 3253). +-define(wxStyledTextCtrl_BraceMatch, 3254). +-define(wxStyledTextCtrl_GetViewEOL, 3255). +-define(wxStyledTextCtrl_SetViewEOL, 3256). +-define(wxStyledTextCtrl_SetModEventMask, 3257). +-define(wxStyledTextCtrl_GetEdgeColumn, 3258). +-define(wxStyledTextCtrl_SetEdgeColumn, 3259). +-define(wxStyledTextCtrl_GetEdgeMode, 3260). +-define(wxStyledTextCtrl_GetEdgeColour, 3261). +-define(wxStyledTextCtrl_SetEdgeColour, 3262). +-define(wxStyledTextCtrl_SearchAnchor, 3263). +-define(wxStyledTextCtrl_SearchNext, 3264). +-define(wxStyledTextCtrl_SearchPrev, 3265). +-define(wxStyledTextCtrl_LinesOnScreen, 3266). +-define(wxStyledTextCtrl_UsePopUp, 3267). +-define(wxStyledTextCtrl_SelectionIsRectangle, 3268). +-define(wxStyledTextCtrl_SetZoom, 3269). +-define(wxStyledTextCtrl_GetZoom, 3270). +-define(wxStyledTextCtrl_GetModEventMask, 3271). +-define(wxStyledTextCtrl_SetSTCFocus, 3272). +-define(wxStyledTextCtrl_GetSTCFocus, 3273). +-define(wxStyledTextCtrl_SetStatus, 3274). +-define(wxStyledTextCtrl_GetStatus, 3275). +-define(wxStyledTextCtrl_SetMouseDownCaptures, 3276). +-define(wxStyledTextCtrl_GetMouseDownCaptures, 3277). +-define(wxStyledTextCtrl_SetSTCCursor, 3278). +-define(wxStyledTextCtrl_GetSTCCursor, 3279). +-define(wxStyledTextCtrl_SetControlCharSymbol, 3280). +-define(wxStyledTextCtrl_GetControlCharSymbol, 3281). +-define(wxStyledTextCtrl_WordPartLeft, 3282). +-define(wxStyledTextCtrl_WordPartLeftExtend, 3283). +-define(wxStyledTextCtrl_WordPartRight, 3284). +-define(wxStyledTextCtrl_WordPartRightExtend, 3285). +-define(wxStyledTextCtrl_SetVisiblePolicy, 3286). +-define(wxStyledTextCtrl_DelLineLeft, 3287). +-define(wxStyledTextCtrl_DelLineRight, 3288). +-define(wxStyledTextCtrl_GetXOffset, 3289). +-define(wxStyledTextCtrl_ChooseCaretX, 3290). +-define(wxStyledTextCtrl_SetXCaretPolicy, 3291). +-define(wxStyledTextCtrl_SetYCaretPolicy, 3292). +-define(wxStyledTextCtrl_GetPrintWrapMode, 3293). +-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3294). +-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3295). +-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3296). +-define(wxStyledTextCtrl_SetHotspotSingleLine, 3297). +-define(wxStyledTextCtrl_ParaDownExtend, 3298). +-define(wxStyledTextCtrl_ParaUp, 3299). +-define(wxStyledTextCtrl_ParaUpExtend, 3300). +-define(wxStyledTextCtrl_PositionBefore, 3301). +-define(wxStyledTextCtrl_PositionAfter, 3302). +-define(wxStyledTextCtrl_CopyRange, 3303). +-define(wxStyledTextCtrl_CopyText, 3304). +-define(wxStyledTextCtrl_SetSelectionMode, 3305). +-define(wxStyledTextCtrl_GetSelectionMode, 3306). +-define(wxStyledTextCtrl_LineDownRectExtend, 3307). +-define(wxStyledTextCtrl_LineUpRectExtend, 3308). +-define(wxStyledTextCtrl_CharLeftRectExtend, 3309). +-define(wxStyledTextCtrl_CharRightRectExtend, 3310). +-define(wxStyledTextCtrl_HomeRectExtend, 3311). +-define(wxStyledTextCtrl_VCHomeRectExtend, 3312). +-define(wxStyledTextCtrl_LineEndRectExtend, 3313). +-define(wxStyledTextCtrl_PageUpRectExtend, 3314). +-define(wxStyledTextCtrl_PageDownRectExtend, 3315). +-define(wxStyledTextCtrl_StutteredPageUp, 3316). +-define(wxStyledTextCtrl_StutteredPageUpExtend, 3317). +-define(wxStyledTextCtrl_StutteredPageDown, 3318). +-define(wxStyledTextCtrl_StutteredPageDownExtend, 3319). +-define(wxStyledTextCtrl_WordLeftEnd, 3320). +-define(wxStyledTextCtrl_WordLeftEndExtend, 3321). +-define(wxStyledTextCtrl_WordRightEnd, 3322). +-define(wxStyledTextCtrl_WordRightEndExtend, 3323). +-define(wxStyledTextCtrl_SetWhitespaceChars, 3324). +-define(wxStyledTextCtrl_SetCharsDefault, 3325). +-define(wxStyledTextCtrl_AutoCompGetCurrent, 3326). +-define(wxStyledTextCtrl_Allocate, 3327). +-define(wxStyledTextCtrl_FindColumn, 3328). +-define(wxStyledTextCtrl_GetCaretSticky, 3329). +-define(wxStyledTextCtrl_SetCaretSticky, 3330). +-define(wxStyledTextCtrl_ToggleCaretSticky, 3331). +-define(wxStyledTextCtrl_SetPasteConvertEndings, 3332). +-define(wxStyledTextCtrl_GetPasteConvertEndings, 3333). +-define(wxStyledTextCtrl_SelectionDuplicate, 3334). +-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3335). +-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3336). +-define(wxStyledTextCtrl_StartRecord, 3337). +-define(wxStyledTextCtrl_StopRecord, 3338). +-define(wxStyledTextCtrl_SetLexer, 3339). +-define(wxStyledTextCtrl_GetLexer, 3340). +-define(wxStyledTextCtrl_Colourise, 3341). +-define(wxStyledTextCtrl_SetProperty, 3342). +-define(wxStyledTextCtrl_SetKeyWords, 3343). +-define(wxStyledTextCtrl_SetLexerLanguage, 3344). +-define(wxStyledTextCtrl_GetProperty, 3345). +-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3346). +-define(wxStyledTextCtrl_GetCurrentLine, 3347). +-define(wxStyledTextCtrl_StyleSetSpec, 3348). +-define(wxStyledTextCtrl_StyleSetFont, 3349). +-define(wxStyledTextCtrl_StyleSetFontAttr, 3350). +-define(wxStyledTextCtrl_StyleSetCharacterSet, 3351). +-define(wxStyledTextCtrl_StyleSetFontEncoding, 3352). +-define(wxStyledTextCtrl_CmdKeyExecute, 3353). +-define(wxStyledTextCtrl_SetMargins, 3354). +-define(wxStyledTextCtrl_GetSelection, 3355). +-define(wxStyledTextCtrl_PointFromPosition, 3356). +-define(wxStyledTextCtrl_ScrollToLine, 3357). +-define(wxStyledTextCtrl_ScrollToColumn, 3358). +-define(wxStyledTextCtrl_SendMsg, 3359). +-define(wxStyledTextCtrl_SetVScrollBar, 3360). +-define(wxStyledTextCtrl_SetHScrollBar, 3361). +-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3362). +-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3363). +-define(wxStyledTextCtrl_SaveFile, 3364). +-define(wxStyledTextCtrl_LoadFile, 3365). +-define(wxStyledTextCtrl_DoDragOver, 3366). +-define(wxStyledTextCtrl_DoDropText, 3367). +-define(wxStyledTextCtrl_GetUseAntiAliasing, 3368). +-define(wxStyledTextCtrl_AddTextRaw, 3369). +-define(wxStyledTextCtrl_InsertTextRaw, 3370). +-define(wxStyledTextCtrl_GetCurLineRaw, 3371). +-define(wxStyledTextCtrl_GetLineRaw, 3372). +-define(wxStyledTextCtrl_GetSelectedTextRaw, 3373). +-define(wxStyledTextCtrl_GetTextRangeRaw, 3374). +-define(wxStyledTextCtrl_SetTextRaw, 3375). +-define(wxStyledTextCtrl_GetTextRaw, 3376). +-define(wxStyledTextCtrl_AppendTextRaw, 3377). +-define(wxArtProvider_GetBitmap, 3378). +-define(wxArtProvider_GetIcon, 3379). +-define(wxTreeEvent_GetKeyCode, 3380). +-define(wxTreeEvent_GetItem, 3381). +-define(wxTreeEvent_GetKeyEvent, 3382). +-define(wxTreeEvent_GetLabel, 3383). +-define(wxTreeEvent_GetOldItem, 3384). +-define(wxTreeEvent_GetPoint, 3385). +-define(wxTreeEvent_IsEditCancelled, 3386). +-define(wxTreeEvent_SetToolTip, 3387). +-define(wxNotebookEvent_GetOldSelection, 3388). +-define(wxNotebookEvent_GetSelection, 3389). +-define(wxNotebookEvent_SetOldSelection, 3390). +-define(wxNotebookEvent_SetSelection, 3391). +-define(wxFileDataObject_new, 3392). +-define(wxFileDataObject_AddFile, 3393). +-define(wxFileDataObject_GetFilenames, 3394). +-define(wxFileDataObject_destroy, 3395). +-define(wxTextDataObject_new, 3396). +-define(wxTextDataObject_GetTextLength, 3397). +-define(wxTextDataObject_GetText, 3398). +-define(wxTextDataObject_SetText, 3399). +-define(wxTextDataObject_destroy, 3400). +-define(wxBitmapDataObject_new_1_1, 3401). +-define(wxBitmapDataObject_new_1_0, 3402). +-define(wxBitmapDataObject_GetBitmap, 3403). +-define(wxBitmapDataObject_SetBitmap, 3404). +-define(wxBitmapDataObject_destroy, 3405). +-define(wxClipboard_new, 3407). +-define(wxClipboard_destruct, 3408). +-define(wxClipboard_AddData, 3409). +-define(wxClipboard_Clear, 3410). +-define(wxClipboard_Close, 3411). +-define(wxClipboard_Flush, 3412). +-define(wxClipboard_GetData, 3413). +-define(wxClipboard_IsOpened, 3414). +-define(wxClipboard_Open, 3415). +-define(wxClipboard_SetData, 3416). +-define(wxClipboard_UsePrimarySelection, 3418). +-define(wxClipboard_IsSupported, 3419). +-define(wxClipboard_Get, 3420). +-define(wxSpinEvent_GetPosition, 3421). +-define(wxSpinEvent_SetPosition, 3422). +-define(wxSplitterWindow_new_0, 3423). +-define(wxSplitterWindow_new_2, 3424). +-define(wxSplitterWindow_destruct, 3425). +-define(wxSplitterWindow_Create, 3426). +-define(wxSplitterWindow_GetMinimumPaneSize, 3427). +-define(wxSplitterWindow_GetSashGravity, 3428). +-define(wxSplitterWindow_GetSashPosition, 3429). +-define(wxSplitterWindow_GetSplitMode, 3430). +-define(wxSplitterWindow_GetWindow1, 3431). +-define(wxSplitterWindow_GetWindow2, 3432). +-define(wxSplitterWindow_Initialize, 3433). +-define(wxSplitterWindow_IsSplit, 3434). +-define(wxSplitterWindow_ReplaceWindow, 3435). +-define(wxSplitterWindow_SetSashGravity, 3436). +-define(wxSplitterWindow_SetSashPosition, 3437). +-define(wxSplitterWindow_SetSashSize, 3438). +-define(wxSplitterWindow_SetMinimumPaneSize, 3439). +-define(wxSplitterWindow_SetSplitMode, 3440). +-define(wxSplitterWindow_SplitHorizontally, 3441). +-define(wxSplitterWindow_SplitVertically, 3442). +-define(wxSplitterWindow_Unsplit, 3443). +-define(wxSplitterWindow_UpdateSize, 3444). +-define(wxSplitterEvent_GetSashPosition, 3445). +-define(wxSplitterEvent_GetX, 3446). +-define(wxSplitterEvent_GetY, 3447). +-define(wxSplitterEvent_GetWindowBeingRemoved, 3448). +-define(wxSplitterEvent_SetSashPosition, 3449). +-define(wxHtmlWindow_new_0, 3450). +-define(wxHtmlWindow_new_2, 3451). +-define(wxHtmlWindow_AppendToPage, 3452). +-define(wxHtmlWindow_GetOpenedAnchor, 3453). +-define(wxHtmlWindow_GetOpenedPage, 3454). +-define(wxHtmlWindow_GetOpenedPageTitle, 3455). +-define(wxHtmlWindow_GetRelatedFrame, 3456). +-define(wxHtmlWindow_HistoryBack, 3457). +-define(wxHtmlWindow_HistoryCanBack, 3458). +-define(wxHtmlWindow_HistoryCanForward, 3459). +-define(wxHtmlWindow_HistoryClear, 3460). +-define(wxHtmlWindow_HistoryForward, 3461). +-define(wxHtmlWindow_LoadFile, 3462). +-define(wxHtmlWindow_LoadPage, 3463). +-define(wxHtmlWindow_SelectAll, 3464). +-define(wxHtmlWindow_SelectionToText, 3465). +-define(wxHtmlWindow_SelectLine, 3466). +-define(wxHtmlWindow_SelectWord, 3467). +-define(wxHtmlWindow_SetBorders, 3468). +-define(wxHtmlWindow_SetFonts, 3469). +-define(wxHtmlWindow_SetPage, 3470). +-define(wxHtmlWindow_SetRelatedFrame, 3471). +-define(wxHtmlWindow_SetRelatedStatusBar, 3472). +-define(wxHtmlWindow_ToText, 3473). +-define(wxHtmlWindow_destroy, 3474). +-define(wxHtmlLinkEvent_GetLinkInfo, 3475). +-define(wxSystemSettings_GetColour, 3476). +-define(wxSystemSettings_GetFont, 3477). +-define(wxSystemSettings_GetMetric, 3478). +-define(wxSystemSettings_GetScreenType, 3479). +-define(wxAuiNotebookEvent_SetSelection, 3480). +-define(wxAuiNotebookEvent_GetSelection, 3481). +-define(wxAuiNotebookEvent_SetOldSelection, 3482). +-define(wxAuiNotebookEvent_GetOldSelection, 3483). +-define(wxAuiNotebookEvent_SetDragSource, 3484). +-define(wxAuiNotebookEvent_GetDragSource, 3485). +-define(wxAuiManagerEvent_SetManager, 3486). +-define(wxAuiManagerEvent_GetManager, 3487). +-define(wxAuiManagerEvent_SetPane, 3488). +-define(wxAuiManagerEvent_GetPane, 3489). +-define(wxAuiManagerEvent_SetButton, 3490). +-define(wxAuiManagerEvent_GetButton, 3491). +-define(wxAuiManagerEvent_SetDC, 3492). +-define(wxAuiManagerEvent_GetDC, 3493). +-define(wxAuiManagerEvent_Veto, 3494). +-define(wxAuiManagerEvent_GetVeto, 3495). +-define(wxAuiManagerEvent_SetCanVeto, 3496). +-define(wxAuiManagerEvent_CanVeto, 3497). +-define(wxLogNull_new, 3498). +-define(wxLogNull_destroy, 3499). diff --git a/lib/wx/test/Makefile b/lib/wx/test/Makefile index 71b79aa272..dfec4bb695 100644 --- a/lib/wx/test/Makefile +++ b/lib/wx/test/Makefile @@ -63,7 +63,7 @@ release_spec: release_tests_spec: opt $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) wx.spec wx_test_lib.hrl $(ErlSrc) $(ErlTargets) $(RELSYSDIR) - $(INSTALL_PROGRAM) wxt $(RELSYSDIR) + $(INSTALL_SCRIPT) wxt $(RELSYSDIR) release_docs_spec: diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl index 76df6e4a23..6f43247d74 100644 --- a/lib/wx/test/wx_class_SUITE.erl +++ b/lib/wx/test/wx_class_SUITE.erl @@ -137,6 +137,9 @@ treeCtrl(Config) -> wxFrame:connect(Tree, command_tree_item_expanded), wxFrame:connect(Tree, command_tree_item_collapsed), wxFrame:connect(Frame, close_window), + + wxTreeCtrl:editLabel(Tree, Root), + wx_test_lib:wx_destroy(Frame,Config). diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk index 4ed22d2256..c3ad3920a4 100644 --- a/lib/wx/vsn.mk +++ b/lib/wx/vsn.mk @@ -1,9 +1 @@ WX_VSN = 0.98.6 - -TICKETS = OTP-8656 - -TICKETS_0.98.5 = OTP-8330 OTP-8461 OTP-8408 OTP-8455 OTP-8462 -TICKETS_0.98.4 = OTP-8243 OTP-8250 OTP-8292 -TICKETS_0.98.3 = OTP-8138 OTP-8126 OTP-8083 -TICKETS_0.98.2 = OTP-7943 -TICKETS_0.98.1 = OTP-7875
\ No newline at end of file diff --git a/lib/xmerl/src/xmerl_dtd.erl b/lib/xmerl/src/xmerl_dtd.erl deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/xmerl/src/xmerl_dtd.erl +++ /dev/null diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl index 4e5cc59d8f..e2e6f95c4a 100644 --- a/lib/xmerl/src/xmerl_scan.erl +++ b/lib/xmerl/src/xmerl_scan.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2003-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2003-2010. 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% %% @@ -2602,8 +2602,7 @@ scan_reference("#x" ++ T, S0) -> %% [66] CharRef ?bump_col(1), if hd(T) /= $; -> - {[Ch], T2, S2} = scan_char_ref_hex(T, S, 0), - {to_char_set(S2#xmerl_scanner.encoding,Ch),T2,S2}; + scan_char_ref_hex(T, S, 0); true -> ?fatal(invalid_char_ref, S) end; @@ -3452,14 +3451,14 @@ scan_entity_value("%" ++ T, S0, Delim, Acc, PEName,Namespace,PENesting) -> %% {system,URI} or {public,URI} %% Included in literal. {ExpRef,Sx}=fetch_not_parse(Tuple,S1), - {EntV,_,_S2} = - scan_entity_value(ExpRef, Sx, no_delim,[], + {EntV, _, S5} = + scan_entity_value(ExpRef, Sx, no_delim,[], PERefName,parameter,[]), %% should do an update Write(parameter_entity) %% so next expand_pe_reference is faster - {EntV,_S2}; + {string_to_char_set(S5#xmerl_scanner.encoding, EntV), S5}; ExpRef -> - {ExpRef,S1} + {string_to_char_set(S1#xmerl_scanner.encoding, ExpRef) ,S1} end, %% single or duoble qoutes are not treated as delimeters %% in passages "included in literal" @@ -4020,12 +4019,12 @@ utf8_2_ucs([A|Rest]) when A < 16#80 -> utf8_2_ucs([A|Rest]) -> {{error,{bad_character,A}},Rest}. -to_char_set("iso-10646-utf-1",Ch) -> - [Ch]; -to_char_set(UTF8,Ch) when UTF8 =:= "utf-8"; UTF8 =:= undefined -> - ucs_2_utf8(Ch); -to_char_set(_,Ch) -> - [Ch]. +%% to_char_set("iso-10646-utf-1",Ch) -> +%% [Ch]; +%% to_char_set(UTF8,Ch) when UTF8 =:= "utf-8"; UTF8 =:= undefined -> +%% ucs_2_utf8(Ch); +%% to_char_set(_,Ch) -> +%% [Ch]. ucs_2_utf8(Ch) when Ch < 128 -> %% 0vvvvvvv diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk index aee7546c3c..03d16ad6fe 100644 --- a/lib/xmerl/vsn.mk +++ b/lib/xmerl/vsn.mk @@ -1,130 +1 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2003-2010. 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% -# - XMERL_VSN = 1.2.5 - - -TICKETS = \ - OTP-8537 \ - OTP-8599 - -TICKETS_1.2.5 = \ - OTP-8537 - -TICKETS_1.2.4 = \ - OTP-8343 - -TICKETS_1.2.3 = \ - OTP-8251 \ - OTP-8252 \ - OTP-8253 - -TICKETS_1.2.2 = \ - OTP-8213 \ - OTP-8214 - -TICKETS_1.2.1 = \ - OTP-8084 \ - OTP-8153 \ - OTP-8156 - -TICKETS_1.2 = \ - OTP-6635 - -TICKETS_1.1.12 = \ - OTP-7847 - -TICKETS_1.1.11 = \ - OTP-7736 - -TICKETS_1.1.10 = \ - OTP-6053 \ - OTP-6873 \ - OTP-7430 \ - OTP-7473 \ - OTP-7496 - -TICKETS_1.1.9 = \ - OTP-5998 \ - OTP-6947 \ - OTP-7288 - -TICKETS_1.1.8 = \ - OTP-7211 \ - OTP-7214 - -TICKETS_1.1.7 = \ - OTP-7190 - -TICKETS_1.1.6 = \ - OTP-6773 \ - OTP-6777 \ - OTP-6877 \ - OTP-6910 - -TICKETS_1.1.5 = \ - OTP-6720 \ - OTP-6739 \ - OTP-6752 - -TICKETS_1.1.4 = \ - OTP-6679 - -TICKETS_1.1.3 = \ - OTP-6599 - -TICKETS_1.1.2 = \ - OTP-6507 \ - OTP-6460 - -TICKETS_1.1.1 = \ - OTP-6402 - -TICKETS_1.1 = \ - OTP-6043 \ - OTP-6099 \ - OTP-6401 - -TICKETS_1.0.5 = \ - - -TICKETS_1.0.4 = \ - OTP-5599 \ - OTP-5718 \ - OTP-5734 \ - OTP-5895 \ - OTP-5902 \ - OTP-5905 - -TICKETS_1.0.3 = \ - OTP-5587 - -TICKETS_1.0.2 = \ - OTP-5498 \ - OTP-5500 \ - OTP-5531 - -TICKETS_1.0.1 = \ - OTP-5268 \ - OTP-5301 \ - OTP-5407 - -TICKETS_1.0 = \ - OTP-5174 \ - |