diff options
Diffstat (limited to 'lib')
471 files changed, 13552 insertions, 17529 deletions
diff --git a/lib/Makefile b/lib/Makefile index 34c2fe9a9e..863b9abac6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -35,8 +35,8 @@ ALL_ERLANG_APPLICATIONS = xmerl edoc erl_docgen snmp otp_mibs erl_interface \ ic mnesia crypto orber os_mon syntax_tools \ public_key ssl observer odbc diameter \ cosTransactions cosEvent cosTime cosNotification \ - cosProperty cosFileTransfer cosEventDomain et megaco webtool \ - eunit ssh typer percept eldap dialyzer hipe ose + cosProperty cosFileTransfer cosEventDomain et megaco \ + eunit ssh typer percept eldap dialyzer hipe ifdef BUILD_ALL ERLANG_APPLICATIONS += $(ALL_ERLANG_APPLICATIONS) diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile index 2b72e1a214..e0d4f09a70 100644 --- a/lib/asn1/c_src/Makefile +++ b/lib/asn1/c_src/Makefile @@ -97,12 +97,7 @@ endif _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) -ifneq ($(findstring ose,$(TARGET)),ose) opt: $(NIF_SHARED_OBJ_FILE) -else -# Do not build dynamic files on OSE -opt: -endif debug: opt @@ -140,9 +135,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" -ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) "$(RELSYSDIR)/priv/lib" -endif $(INSTALL_DIR) "$(RELSYSDIR)/c_src" $(INSTALL_DATA) *.c "$(RELSYSDIR)/c_src" diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index 6db8d19b5a..bd85f22462 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,26 @@ <p>This document describes the changes made to the Compiler application.</p> +<section><title>Compiler 6.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix <c>get_map_elements</c> register corruption</p> + <p> + Instruction <c>get_map_elements</c> might destroy target + registers when the fail-label is taken. Only seen for + patterns with two, and only two, target registers. + Specifically if we copy one register and then jump.</p> + <p> + Own Id: OTP-12967</p> + </item> + </list> + </section> + +</section> + <section><title>Compiler 6.0</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index 299b2892fc..f75beaba20 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -50,6 +50,7 @@ MODULES = \ beam_asm \ beam_block \ beam_bool \ + beam_bs \ beam_bsm \ beam_clean \ beam_dead \ @@ -62,6 +63,7 @@ MODULES = \ beam_opcodes \ beam_peep \ beam_receive \ + beam_reorder \ beam_split \ beam_trim \ beam_type \ diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 0321b1c07b..10dbaf462c 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -23,14 +23,13 @@ -module(beam_block). -export([module/2]). --import(lists, [mapfoldl/3,reverse/1,reverse/2,foldl/3,member/2]). --define(MAXREG, 1024). +-import(lists, [reverse/1,reverse/2,foldl/3,member/2]). -module({Mod,Exp,Attr,Fs0,Lc0}, _Opt) -> - {Fs,Lc} = mapfoldl(fun function/2, Lc0, Fs0), +module({Mod,Exp,Attr,Fs0,Lc}, _Opt) -> + Fs = [function(F) || F <- Fs0], {ok,{Mod,Exp,Attr,Fs,Lc}}. -function({function,Name,Arity,CLabel,Is0}, Lc0) -> +function({function,Name,Arity,CLabel,Is0}) -> try %% Collect basic blocks and optimize them. Is1 = blockify(Is0), @@ -40,11 +39,8 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) -> Is5 = opt_blocks(Is4), Is6 = beam_utils:delete_live_annos(Is5), - %% Optimize bit syntax. - {Is,Lc} = bsm_opt(Is6, Lc0), - %% Done. - {{function,Name,Arity,CLabel,Is},Lc} + {function,Name,Arity,CLabel,Is6} catch Class:Error -> Stack = erlang:get_stacktrace(), @@ -62,56 +58,15 @@ blockify(Is) -> blockify([{loop_rec,{f,Fail},{x,0}},{loop_rec_end,_Lbl},{label,Fail}|Is], Acc) -> %% Useless instruction sequence. blockify(Is, Acc); -blockify([{test,is_atom,{f,Fail},[Reg]}=I| - [{select,select_val,Reg,{f,Fail}, - [{atom,false},{f,_}=BrFalse, - {atom,true}=AtomTrue,{f,_}=BrTrue]}|Is]=Is0], - [{block,Bl}|_]=Acc) -> - case is_last_bool(Bl, Reg) of - false -> - blockify(Is0, [I|Acc]); - true -> - %% The last instruction is a boolean operator/guard BIF that can't fail. - %% We can convert the three-way branch to a two-way branch (eliminating - %% the reference to the failure label). - blockify(Is, [{jump,BrTrue}, - {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc]) - end; -blockify([{test,is_atom,{f,Fail},[Reg]}=I| - [{select,select_val,Reg,{f,Fail}, - [{atom,true}=AtomTrue,{f,_}=BrTrue, - {atom,false},{f,_}=BrFalse]}|Is]=Is0], - [{block,Bl}|_]=Acc) -> - case is_last_bool(Bl, Reg) of - false -> - blockify(Is0, [I|Acc]); - true -> - blockify(Is, [{jump,BrTrue}, - {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc]) - end; blockify([I|Is0]=IsAll, Acc) -> - case is_bs_put(I) of - true -> - {BsPuts0,Is} = collect_bs_puts(IsAll), - BsPuts = opt_bs_puts(BsPuts0), - blockify(Is, reverse(BsPuts, Acc)); - false -> - case collect(I) of - error -> blockify(Is0, [I|Acc]); - Instr when is_tuple(Instr) -> - {Block,Is} = collect_block(IsAll), - blockify(Is, [{block,Block}|Acc]) - end + case collect(I) of + error -> blockify(Is0, [I|Acc]); + Instr when is_tuple(Instr) -> + {Block,Is} = collect_block(IsAll), + blockify(Is, [{block,Block}|Acc]) end; blockify([], Acc) -> reverse(Acc). -is_last_bool([{set,[Reg],As,{bif,N,_}}], Reg) -> - Ar = length(As), - erl_internal:new_type_test(N, Ar) orelse erl_internal:comp_op(N, Ar) - orelse erl_internal:bool_op(N, Ar); -is_last_bool([_|Is], Reg) -> is_last_bool(Is, Reg); -is_last_bool([], _) -> false. - collect_block(Is) -> collect_block(Is, []). @@ -149,7 +104,10 @@ collect({put_map,F,Op,S,D,R,{list,Puts}}) -> collect({get_map_elements,F,S,{list,Gets}}) -> {Ss,Ds} = beam_utils:split_even(Gets), {set,Ds,[S|Ss],{get_map_elements,F}}; -collect({'catch',R,L}) -> {set,[R],[],{'catch',L}}; +collect({'catch'=Op,R,L}) -> + {set,[R],[],{try_catch,Op,L}}; +collect({'try'=Op,R,L}) -> + {set,[R],[],{try_catch,Op,L}}; collect(fclearerror) -> {set,[],[],fclearerror}; collect({fcheckerror,{f,0}}) -> {set,[],[],fcheckerror}; collect({fmove,S,D}) -> {set,[D],[S],fmove}; @@ -183,7 +141,9 @@ opt_blocks([I|Is]) -> opt_blocks([]) -> []. opt_block(Is0) -> - Is = find_fixpoint(fun opt/1, Is0), + Is = find_fixpoint(fun(Is) -> + opt_tuple_element(opt(Is)) + end, Is0), opt_alloc(Is). find_fixpoint(OptFun, Is0) -> @@ -279,76 +239,151 @@ opt_moves([X0,Y0], Is0) -> not_possible -> {[X,Y0],Is2}; {X,_} -> {[X,Y0],Is2}; {Y,Is} -> {[X,Y],Is} - end; -opt_moves(Ds, Is) -> - %% multiple destinations -> pass through - {Ds,Is}. - + end. %% opt_move(Dest, [Instruction]) -> {UpdatedDest,[Instruction]} | not_possible %% If there is a {move,Dest,FinalDest} instruction %% in the instruction stream, remove the move instruction %% and let FinalDest be the destination. -%% -%% For this optimization to be safe, we must be sure that -%% Dest will not be referenced in any other by other instructions -%% in the rest of the instruction stream. Not even the indirect -%% reference by an instruction that may allocate (such as -%% test_heap/2 or a GC Bif) is allowed. opt_move(Dest, Is) -> - opt_move_1(Dest, Is, ?MAXREG, []). - -opt_move_1(R, [{set,_,_,{alloc,Live,_}}|_]=Is, SafeRegs, Acc) when Live < SafeRegs -> - %% Downgrade number of safe regs and rescan the instruction, as it most probably - %% is a gc_bif instruction. - opt_move_1(R, Is, Live, Acc); -opt_move_1(R, [{set,[{x,X}=D],[R],move}|Is], SafeRegs, Acc) -> - case X < SafeRegs andalso beam_utils:is_killed_block(R, Is) of - true -> opt_move_2(D, Acc, Is); - false -> not_possible + opt_move_1(Dest, Is, []). + +opt_move_1(R, [{set,[D],[R],move}|Is0], Acc) -> + %% Provided that the source register is killed by instructions + %% that follow, the optimization is safe. + case eliminate_use_of_from_reg(Is0, R, D, []) of + {yes,Is} -> opt_move_rev(D, Acc, Is); + no -> not_possible end; -opt_move_1(R, [{set,[D],[R],move}|Is], _SafeRegs, Acc) -> - case beam_utils:is_killed_block(R, Is) of - true -> opt_move_2(D, Acc, Is); - false -> not_possible +opt_move_1({x,_}, [{set,_,_,{alloc,_,_}}|_], _) -> + %% The optimization is not possible. If the X register is not + %% killed by allocation, the optimization would not be safe. + %% If the X register is killed, it means that there cannot + %% follow a 'move' instruction with this X register as the + %% source. + not_possible; +opt_move_1(R, [{set,_,_,_}=I|Is], Acc) -> + %% If the source register is either killed or used by this + %% instruction, the optimimization is not possible. + case is_killed_or_used(R, I) of + true -> not_possible; + false -> opt_move_1(R, Is, [I|Acc]) end; -opt_move_1(R, [I|Is], SafeRegs, Acc) -> - case is_transparent(R, I) of - false -> not_possible; - true -> opt_move_1(R, Is, SafeRegs, [I|Acc]) - end. +opt_move_1(_, _, _) -> + not_possible. + +%% opt_tuple_element([Instruction]) -> [Instruction] +%% If possible, move get_tuple_element instructions forward +%% in the instruction stream to a move instruction, eliminating +%% the move instruction. Example: +%% +%% get_tuple_element Tuple Pos Dst1 +%% ... +%% move Dst1 Dst2 +%% +%% This code may be possible to rewrite to: +%% +%% %%(Moved get_tuple_element instruction) +%% ... +%% get_tuple_element Tuple Pos Dst2 +%% -%% Reverse the instructions, while checking that there are no instructions that -%% would interfere with using the new destination register chosen. +opt_tuple_element([{set,[D],[S],{get_tuple_element,_}}=I|Is0]) -> + case opt_tuple_element_1(Is0, I, {S,D}, []) of + no -> + [I|opt_tuple_element(Is0)]; + {yes,Is} -> + opt_tuple_element(Is) + end; +opt_tuple_element([I|Is]) -> + [I|opt_tuple_element(Is)]; +opt_tuple_element([]) -> []. + +opt_tuple_element_1([{set,_,_,{alloc,_,_}}|_], _, _, _) -> + no; +opt_tuple_element_1([{set,_,_,{try_catch,_,_}}|_], _, _, _) -> + no; +opt_tuple_element_1([{set,[D],[S],move}|Is0], I0, {_,S}, Acc) -> + case eliminate_use_of_from_reg(Is0, S, D, []) of + no -> + no; + {yes,Is} -> + {set,[S],Ss,Op} = I0, + I = {set,[D],Ss,Op}, + {yes,reverse(Acc, [I|Is])} + end; +opt_tuple_element_1([{set,Ds,Ss,_}=I|Is], MovedI, {S,D}=Regs, Acc) -> + case member(S, Ds) orelse member(D, Ss) of + true -> + no; + false -> + opt_tuple_element_1(Is, MovedI, Regs, [I|Acc]) + end; +opt_tuple_element_1(_, _, _, _) -> no. + +%% Reverse the instructions, while checking that there are no +%% instructions that would interfere with using the new destination +%% register (D). -opt_move_2(D, [I|Is], Acc) -> - case is_transparent(D, I) of - false -> not_possible; - true -> opt_move_2(D, Is, [I|Acc]) +opt_move_rev(D, [I|Is], Acc) -> + case is_killed_or_used(D, I) of + true -> not_possible; + false -> opt_move_rev(D, Is, [I|Acc]) + end; +opt_move_rev(D, [], Acc) -> {D,Acc}. + +%% is_killed_or_used(Register, {set,_,_,_}) -> bool() +%% Test whether the register is used by the instruction. + +is_killed_or_used(R, {set,Ss,Ds,_}) -> + member(R, Ds) orelse member(R, Ss). + +%% eliminate_use_of_from_reg([Instruction], FromRegister, ToRegister, Acc) -> +%% {yes,Is} | no +%% Eliminate any use of FromRegister in the instruction sequence +%% by replacing uses of FromRegister with ToRegister. If FromRegister +%% is referenced by an allocation instruction, return 'no' to indicate +%% that FromRegister is still used and that the optimization is not +%% possible. + +eliminate_use_of_from_reg([{set,_,_,{alloc,Live,_}}|_]=Is0, {x,X}, _, Acc) -> + if + X < Live -> + no; + true -> + {yes,reverse(Acc, Is0)} end; -opt_move_2(D, [], Acc) -> {D,Acc}. - -%% is_transparent(Register, Instruction) -> true | false -%% Returns true if Instruction does not in any way references Register -%% (even indirectly by an allocation instruction). -%% Returns false if Instruction does reference Register, or we are -%% not sure. - -is_transparent({x,X}, {set,_,_,{alloc,Live,_}}) when X < Live -> - false; -is_transparent(R, {set,Ds,Ss,_Op}) -> - case member(R, Ds) of - true -> false; - false -> not member(R, Ss) +eliminate_use_of_from_reg([{set,Ds,Ss0,Op}=I0|Is], From, To, Acc) -> + I = case member(From, Ss0) of + true -> + Ss = [case S of + From -> To; + _ -> S + end || S <- Ss0], + {set,Ds,Ss,Op}; + false -> + I0 + end, + case member(From, Ds) of + true -> + {yes,reverse(Acc, [I|Is])}; + false -> + eliminate_use_of_from_reg(Is, From, To, [I|Acc]) end; -is_transparent(_, _) -> false. +eliminate_use_of_from_reg([I]=Is, From, _To, Acc) -> + case beam_utils:is_killed_block(From, [I]) of + true -> + {yes,reverse(Acc, Is)}; + false -> + no + end. %% opt_alloc(Instructions) -> Instructions' %% Optimises all allocate instructions. opt_alloc([{set,[],[],{alloc,R,{_,Ns,Nh,[]}}}|Is]) -> - [{set,[],[],opt_alloc(Is, Ns, Nh, R)}|opt(Is)]; + [{set,[],[],opt_alloc(Is, Ns, Nh, R)}|Is]; opt_alloc([I|Is]) -> [I|opt_alloc(Is)]; opt_alloc([]) -> []. @@ -414,234 +449,3 @@ x_dead([], Regs) -> Regs. x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N)); x_live([_|Rs], Regs) -> x_live(Rs, Regs); x_live([], Regs) -> Regs. - -%%% -%%% Evaluation of constant bit fields. -%%% - -is_bs_put({bs_put,_,{bs_put_integer,_,_},_}) -> true; -is_bs_put({bs_put,_,{bs_put_float,_,_},_}) -> true; -is_bs_put(_) -> false. - -collect_bs_puts(Is) -> - collect_bs_puts_1(Is, []). - -collect_bs_puts_1([I|Is]=Is0, Acc) -> - case is_bs_put(I) of - false -> {reverse(Acc),Is0}; - true -> collect_bs_puts_1(Is, [I|Acc]) - end. - -opt_bs_puts(Is) -> - opt_bs_1(Is, []). - -opt_bs_1([{bs_put,Fail, - {bs_put_float,1,Flags0},[{integer,Sz},Src]}=I0|Is], Acc) -> - try eval_put_float(Src, Sz, Flags0) of - <<Int:Sz>> -> - Flags = force_big(Flags0), - I = {bs_put,Fail,{bs_put_integer,1,Flags}, - [{integer,Sz},{integer,Int}]}, - opt_bs_1([I|Is], Acc) - catch - error:_ -> - opt_bs_1(Is, [I0|Acc]) - end; -opt_bs_1([{bs_put,_,{bs_put_integer,1,_},[{integer,8},{integer,_}]}|_]=IsAll, - Acc0) -> - {Is,Acc} = bs_collect_string(IsAll, Acc0), - opt_bs_1(Is, Acc); -opt_bs_1([{bs_put,Fail,{bs_put_integer,1,F},[{integer,Sz},{integer,N}]}=I|Is0], - Acc) when Sz > 8 -> - case field_endian(F) of - big -> - %% We can do this optimization for any field size without risk - %% for code explosion. - case bs_split_int(N, Sz, Fail, Is0) of - no_split -> opt_bs_1(Is0, [I|Acc]); - Is -> opt_bs_1(Is, Acc) - end; - little when Sz < 128 -> - %% We only try to optimize relatively small fields, to avoid - %% an explosion in code size. - <<Int:Sz>> = <<N:Sz/little>>, - Flags = force_big(F), - Is = [{bs_put,Fail,{bs_put_integer,1,Flags}, - [{integer,Sz},{integer,Int}]}|Is0], - opt_bs_1(Is, Acc); - _ -> %native or too wide little field - opt_bs_1(Is0, [I|Acc]) - end; -opt_bs_1([{bs_put,Fail,{Op,U,F},[{integer,Sz},Src]}|Is], Acc) when U > 1 -> - opt_bs_1([{bs_put,Fail,{Op,1,F},[{integer,U*Sz},Src]}|Is], Acc); -opt_bs_1([I|Is], Acc) -> - opt_bs_1(Is, [I|Acc]); -opt_bs_1([], Acc) -> reverse(Acc). - -eval_put_float(Src, Sz, Flags) when Sz =< 256 -> %Only evaluate if Sz is reasonable. - Val = value(Src), - case field_endian(Flags) of - little -> <<Val:Sz/little-float-unit:1>>; - big -> <<Val:Sz/big-float-unit:1>> - %% native intentionally not handled here - we can't optimize it. - end. - -value({integer,I}) -> I; -value({float,F}) -> F. - -bs_collect_string(Is, [{bs_put,_,{bs_put_string,Len,{string,Str}},[]}|Acc]) -> - bs_coll_str_1(Is, Len, reverse(Str), Acc); -bs_collect_string(Is, Acc) -> - bs_coll_str_1(Is, 0, [], Acc). - -bs_coll_str_1([{bs_put,_,{bs_put_integer,U,_},[{integer,Sz},{integer,V}]}|Is], - Len, StrAcc, IsAcc) when U*Sz =:= 8 -> - Byte = V band 16#FF, - bs_coll_str_1(Is, Len+1, [Byte|StrAcc], IsAcc); -bs_coll_str_1(Is, Len, StrAcc, IsAcc) -> - {Is,[{bs_put,{f,0},{bs_put_string,Len,{string,reverse(StrAcc)}},[]}|IsAcc]}. - -field_endian({field_flags,F}) -> field_endian_1(F). - -field_endian_1([big=E|_]) -> E; -field_endian_1([little=E|_]) -> E; -field_endian_1([native=E|_]) -> E; -field_endian_1([_|Fs]) -> field_endian_1(Fs). - -force_big({field_flags,F}) -> - {field_flags,force_big_1(F)}. - -force_big_1([big|_]=Fs) -> Fs; -force_big_1([little|Fs]) -> [big|Fs]; -force_big_1([F|Fs]) -> [F|force_big_1(Fs)]. - -bs_split_int(0, Sz, _, _) when Sz > 64 -> - %% We don't want to split in this case because the - %% string will consist of only zeroes. - no_split; -bs_split_int(-1, Sz, _, _) when Sz > 64 -> - %% We don't want to split in this case because the - %% string will consist of only 255 bytes. - no_split; -bs_split_int(N, Sz, Fail, Acc) -> - FirstByteSz = case Sz rem 8 of - 0 -> 8; - Rem -> Rem - end, - bs_split_int_1(N, FirstByteSz, Sz, Fail, Acc). - -bs_split_int_1(-1, _, Sz, Fail, Acc) when Sz > 64 -> - I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, - [{integer,Sz},{integer,-1}]}, - [I|Acc]; -bs_split_int_1(0, _, Sz, Fail, Acc) when Sz > 64 -> - I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, - [{integer,Sz},{integer,0}]}, - [I|Acc]; -bs_split_int_1(N, ByteSz, Sz, Fail, Acc) when Sz > 0 -> - Mask = (1 bsl ByteSz) - 1, - I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, - [{integer,ByteSz},{integer,N band Mask}]}, - bs_split_int_1(N bsr ByteSz, 8, Sz-ByteSz, Fail, [I|Acc]); -bs_split_int_1(_, _, _, _, Acc) -> Acc. - - -%%% -%%% Optimization of new bit syntax matching: get rid -%%% of redundant bs_restore2/2 instructions across select_val -%%% instructions, as well as a few other simple peep-hole optimizations. -%%% - -bsm_opt(Is0, Lc0) -> - {Is1,D0,Lc} = bsm_scan(Is0, [], Lc0, []), - Is2 = case D0 of - [] -> - Is1; - _ -> - D = gb_trees:from_orddict(orddict:from_list(D0)), - bsm_reroute(Is1, D, none, []) - end, - Is = beam_clean:bs_clean_saves(Is2), - {bsm_opt_2(Is, []),Lc}. - -bsm_scan([{label,L}=Lbl,{bs_restore2,_,Save}=R|Is], D0, Lc, Acc0) -> - D = [{{L,Save},Lc}|D0], - Acc = [{label,Lc},R,Lbl|Acc0], - bsm_scan(Is, D, Lc+1, Acc); -bsm_scan([I|Is], D, Lc, Acc) -> - bsm_scan(Is, D, Lc, [I|Acc]); -bsm_scan([], D, Lc, Acc) -> - {reverse(Acc),D,Lc}. - -bsm_reroute([{bs_save2,Reg,Save}=I|Is], D, _, Acc) -> - bsm_reroute(Is, D, {Reg,Save}, [I|Acc]); -bsm_reroute([{bs_restore2,Reg,Save}=I|Is], D, _, Acc) -> - bsm_reroute(Is, D, {Reg,Save}, [I|Acc]); -bsm_reroute([{label,_}=I|Is], D, S, Acc) -> - bsm_reroute(Is, D, S, [I|Acc]); -bsm_reroute([{select,select_val,Reg,F0,Lbls0}|Is], D, {_,Save}=S, Acc0) -> - [F|Lbls] = bsm_subst_labels([F0|Lbls0], Save, D), - Acc = [{select,select_val,Reg,F,Lbls}|Acc0], - bsm_reroute(Is, D, S, Acc); -bsm_reroute([{test,TestOp,F0,TestArgs}=I|Is], D, {_,Save}=S, Acc0) -> - F = bsm_subst_label(F0, Save, D), - Acc = [{test,TestOp,F,TestArgs}|Acc0], - case bsm_not_bs_test(I) of - true -> - %% The test instruction will not update the bit offset for the - %% binary being matched. Therefore the save position can be kept. - bsm_reroute(Is, D, S, Acc); - false -> - %% The test instruction might update the bit offset. Kill our - %% remembered Save position. - bsm_reroute(Is, D, none, Acc) - end; -bsm_reroute([{test,TestOp,F0,Live,TestArgs,Dst}|Is], D, {_,Save}, Acc0) -> - F = bsm_subst_label(F0, Save, D), - Acc = [{test,TestOp,F,Live,TestArgs,Dst}|Acc0], - %% The test instruction will update the bit offset. Kill our - %% remembered Save position. - bsm_reroute(Is, D, none, Acc); -bsm_reroute([{block,[{set,[],[],{alloc,_,_}}]}=Bl, - {bs_context_to_binary,_}=I|Is], D, S, Acc) -> - %% To help further bit syntax optimizations. - bsm_reroute([I,Bl|Is], D, S, Acc); -bsm_reroute([I|Is], D, _, Acc) -> - bsm_reroute(Is, D, none, [I|Acc]); -bsm_reroute([], _, _, Acc) -> reverse(Acc). - -bsm_opt_2([{test,bs_test_tail2,F,[Ctx,Bits]}|Is], - [{test,bs_skip_bits2,F,[Ctx,{integer,I},Unit,_Flags]}|Acc]) -> - bsm_opt_2(Is, [{test,bs_test_tail2,F,[Ctx,Bits+I*Unit]}|Acc]); -bsm_opt_2([{test,bs_skip_bits2,F,[Ctx,{integer,I1},Unit1,_]}|Is], - [{test,bs_skip_bits2,F,[Ctx,{integer,I2},Unit2,Flags]}|Acc]) -> - bsm_opt_2(Is, [{test,bs_skip_bits2,F, - [Ctx,{integer,I1*Unit1+I2*Unit2},1,Flags]}|Acc]); -bsm_opt_2([I|Is], Acc) -> - bsm_opt_2(Is, [I|Acc]); -bsm_opt_2([], Acc) -> reverse(Acc). - -%% bsm_not_bs_test({test,Name,_,Operands}) -> true|false. -%% Test whether is the test is a "safe", i.e. does not move the -%% bit offset for a binary. -%% -%% 'true' means that the test is safe, 'false' that we don't know or -%% that the test moves the offset (e.g. bs_get_integer2). - -bsm_not_bs_test({test,bs_test_tail2,_,[_,_]}) -> true; -bsm_not_bs_test(Test) -> beam_utils:is_pure_test(Test). - -bsm_subst_labels(Fs, Save, D) -> - bsm_subst_labels_1(Fs, Save, D, []). - -bsm_subst_labels_1([F|Fs], Save, D, Acc) -> - bsm_subst_labels_1(Fs, Save, D, [bsm_subst_label(F, Save, D)|Acc]); -bsm_subst_labels_1([], _, _, Acc) -> - reverse(Acc). - -bsm_subst_label({f,Lbl0}=F, Save, D) -> - case gb_trees:lookup({Lbl0,Save}, D) of - {value,Lbl} -> {f,Lbl}; - none -> F - end; -bsm_subst_label(Other, _, _) -> Other. diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl index 14b6381230..c9e103eae9 100644 --- a/lib/compiler/src/beam_bool.erl +++ b/lib/compiler/src/beam_bool.erl @@ -25,8 +25,6 @@ -import(lists, [reverse/1,reverse/2,foldl/3,mapfoldl/3,map/2]). --define(MAXREG, 1024). - -record(st, {next, %Next label number. ll %Live regs at labels. diff --git a/lib/compiler/src/beam_bs.erl b/lib/compiler/src/beam_bs.erl new file mode 100644 index 0000000000..55fa7ce10c --- /dev/null +++ b/lib/compiler/src/beam_bs.erl @@ -0,0 +1,278 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +%% Purpose : Partitions assembly instructions into basic blocks and +%% optimizes them. + +-module(beam_bs). + +-export([module/2]). +-import(lists, [mapfoldl/3,reverse/1]). + +module({Mod,Exp,Attr,Fs0,Lc0}, _Opt) -> + {Fs,Lc} = mapfoldl(fun function/2, Lc0, Fs0), + {ok,{Mod,Exp,Attr,Fs,Lc}}. + +function({function,Name,Arity,CLabel,Is0}, Lc0) -> + try + Is1 = bs_put_opt(Is0), + {Is,Lc} = bsm_opt(Is1, Lc0), + {{function,Name,Arity,CLabel,Is},Lc} + catch + Class:Error -> + Stack = erlang:get_stacktrace(), + io:fwrite("Function: ~w/~w\n", [Name,Arity]), + erlang:raise(Class, Error, Stack) + end. + +%%% +%%% Evaluation of constant bit fields. +%%% + +bs_put_opt([{bs_put,_,_,_}=I|Is0]) -> + {BsPuts0,Is} = collect_bs_puts(Is0, [I]), + BsPuts = opt_bs_puts(BsPuts0), + BsPuts ++ bs_put_opt(Is); +bs_put_opt([I|Is]) -> + [I|bs_put_opt(Is)]; +bs_put_opt([]) -> []. + +collect_bs_puts([{bs_put,_,_,_}=I|Is], Acc) -> + collect_bs_puts(Is, [I|Acc]); +collect_bs_puts([_|_]=Is, Acc) -> + {reverse(Acc),Is}. + +opt_bs_puts(Is) -> + opt_bs_1(Is, []). + +opt_bs_1([{bs_put,Fail, + {bs_put_float,1,Flags0},[{integer,Sz},Src]}=I0|Is], Acc) -> + try eval_put_float(Src, Sz, Flags0) of + <<Int:Sz>> -> + Flags = force_big(Flags0), + I = {bs_put,Fail,{bs_put_integer,1,Flags}, + [{integer,Sz},{integer,Int}]}, + opt_bs_1([I|Is], Acc) + catch + error:_ -> + opt_bs_1(Is, [I0|Acc]) + end; +opt_bs_1([{bs_put,_,{bs_put_integer,1,_},[{integer,8},{integer,_}]}|_]=IsAll, + Acc0) -> + {Is,Acc} = bs_collect_string(IsAll, Acc0), + opt_bs_1(Is, Acc); +opt_bs_1([{bs_put,Fail,{bs_put_integer,1,F},[{integer,Sz},{integer,N}]}=I|Is0], + Acc) when Sz > 8 -> + case field_endian(F) of + big -> + %% We can do this optimization for any field size without + %% risk for code explosion. + case bs_split_int(N, Sz, Fail, Is0) of + no_split -> opt_bs_1(Is0, [I|Acc]); + Is -> opt_bs_1(Is, Acc) + end; + little when Sz < 128 -> + %% We only try to optimize relatively small fields, to + %% avoid an explosion in code size. + <<Int:Sz>> = <<N:Sz/little>>, + Flags = force_big(F), + Is = [{bs_put,Fail,{bs_put_integer,1,Flags}, + [{integer,Sz},{integer,Int}]}|Is0], + opt_bs_1(Is, Acc); + _ -> %native or too wide little field + opt_bs_1(Is0, [I|Acc]) + end; +opt_bs_1([{bs_put,Fail,{Op,U,F},[{integer,Sz},Src]}|Is], Acc) when U > 1 -> + opt_bs_1([{bs_put,Fail,{Op,1,F},[{integer,U*Sz},Src]}|Is], Acc); +opt_bs_1([I|Is], Acc) -> + opt_bs_1(Is, [I|Acc]); +opt_bs_1([], Acc) -> reverse(Acc). + +eval_put_float(Src, Sz, Flags) when Sz =< 256 -> + %%Only evaluate if Sz is reasonable. + Val = value(Src), + case field_endian(Flags) of + little -> <<Val:Sz/little-float-unit:1>>; + big -> <<Val:Sz/big-float-unit:1>> + %% native intentionally not handled here - we can't optimize + %% it. + end. + +value({integer,I}) -> I; +value({float,F}) -> F. + +bs_collect_string(Is, [{bs_put,_,{bs_put_string,Len,{string,Str}},[]}|Acc]) -> + bs_coll_str_1(Is, Len, reverse(Str), Acc); +bs_collect_string(Is, Acc) -> + bs_coll_str_1(Is, 0, [], Acc). + +bs_coll_str_1([{bs_put,_,{bs_put_integer,U,_},[{integer,Sz},{integer,V}]}|Is], + Len, StrAcc, IsAcc) when U*Sz =:= 8 -> + Byte = V band 16#FF, + bs_coll_str_1(Is, Len+1, [Byte|StrAcc], IsAcc); +bs_coll_str_1(Is, Len, StrAcc, IsAcc) -> + {Is,[{bs_put,{f,0},{bs_put_string,Len,{string,reverse(StrAcc)}},[]}|IsAcc]}. + +field_endian({field_flags,F}) -> field_endian_1(F). + +field_endian_1([big=E|_]) -> E; +field_endian_1([little=E|_]) -> E; +field_endian_1([native=E|_]) -> E; +field_endian_1([_|Fs]) -> field_endian_1(Fs). + +force_big({field_flags,F}) -> + {field_flags,force_big_1(F)}. + +force_big_1([big|_]=Fs) -> Fs; +force_big_1([little|Fs]) -> [big|Fs]; +force_big_1([F|Fs]) -> [F|force_big_1(Fs)]. + +bs_split_int(0, Sz, _, _) when Sz > 64 -> + %% We don't want to split in this case because the + %% string will consist of only zeroes. + no_split; +bs_split_int(-1, Sz, _, _) when Sz > 64 -> + %% We don't want to split in this case because the + %% string will consist of only 255 bytes. + no_split; +bs_split_int(N, Sz, Fail, Acc) -> + FirstByteSz = case Sz rem 8 of + 0 -> 8; + Rem -> Rem + end, + bs_split_int_1(N, FirstByteSz, Sz, Fail, Acc). + +bs_split_int_1(-1, _, Sz, Fail, Acc) when Sz > 64 -> + I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, + [{integer,Sz},{integer,-1}]}, + [I|Acc]; +bs_split_int_1(0, _, Sz, Fail, Acc) when Sz > 64 -> + I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, + [{integer,Sz},{integer,0}]}, + [I|Acc]; +bs_split_int_1(N, ByteSz, Sz, Fail, Acc) when Sz > 0 -> + Mask = (1 bsl ByteSz) - 1, + I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, + [{integer,ByteSz},{integer,N band Mask}]}, + bs_split_int_1(N bsr ByteSz, 8, Sz-ByteSz, Fail, [I|Acc]); +bs_split_int_1(_, _, _, _, Acc) -> Acc. + +%%% +%%% Optimization of bit syntax matching: get rid +%%% of redundant bs_restore2/2 instructions across select_val +%%% instructions, as well as a few other simple peep-hole +%%% optimizations. +%%% + +bsm_opt(Is0, Lc0) -> + {Is1,D0,Lc} = bsm_scan(Is0, [], Lc0, []), + Is2 = case D0 of + [] -> + %% No bit syntax matching in this function. + Is1; + [_|_] -> + %% Optimize the bit syntax matching. + D = gb_trees:from_orddict(orddict:from_list(D0)), + bsm_reroute(Is1, D, none, []) + end, + Is = beam_clean:bs_clean_saves(Is2), + {bsm_opt_2(Is, []),Lc}. + +bsm_scan([{label,L}=Lbl,{bs_restore2,_,Save}=R|Is], D0, Lc, Acc0) -> + D = [{{L,Save},Lc}|D0], + Acc = [{label,Lc},R,Lbl|Acc0], + bsm_scan(Is, D, Lc+1, Acc); +bsm_scan([I|Is], D, Lc, Acc) -> + bsm_scan(Is, D, Lc, [I|Acc]); +bsm_scan([], D, Lc, Acc) -> + {reverse(Acc),D,Lc}. + +bsm_reroute([{bs_save2,Reg,Save}=I|Is], D, _, Acc) -> + bsm_reroute(Is, D, {Reg,Save}, [I|Acc]); +bsm_reroute([{bs_restore2,Reg,Save}=I|Is], D, _, Acc) -> + bsm_reroute(Is, D, {Reg,Save}, [I|Acc]); +bsm_reroute([{label,_}=I|Is], D, S, Acc) -> + bsm_reroute(Is, D, S, [I|Acc]); +bsm_reroute([{select,select_val,Reg,F0,Lbls0}|Is], D, {_,Save}=S, Acc0) -> + [F|Lbls] = bsm_subst_labels([F0|Lbls0], Save, D), + Acc = [{select,select_val,Reg,F,Lbls}|Acc0], + bsm_reroute(Is, D, S, Acc); +bsm_reroute([{test,TestOp,F0,TestArgs}=I|Is], D, {_,Save}=S, Acc0) -> + F = bsm_subst_label(F0, Save, D), + Acc = [{test,TestOp,F,TestArgs}|Acc0], + case bsm_not_bs_test(I) of + true -> + %% The test instruction will not update the bit offset for + %% the binary being matched. Therefore the save position + %% can be kept. + bsm_reroute(Is, D, S, Acc); + false -> + %% The test instruction might update the bit offset. Kill + %% our remembered Save position. + bsm_reroute(Is, D, none, Acc) + end; +bsm_reroute([{test,TestOp,F0,Live,TestArgs,Dst}|Is], D, {_,Save}, Acc0) -> + F = bsm_subst_label(F0, Save, D), + Acc = [{test,TestOp,F,Live,TestArgs,Dst}|Acc0], + %% The test instruction will update the bit offset. Kill our + %% remembered Save position. + bsm_reroute(Is, D, none, Acc); +bsm_reroute([{block,[{set,[],[],{alloc,_,_}}]}=Bl, + {bs_context_to_binary,_}=I|Is], D, S, Acc) -> + %% To help further bit syntax optimizations. + bsm_reroute([I,Bl|Is], D, S, Acc); +bsm_reroute([I|Is], D, _, Acc) -> + bsm_reroute(Is, D, none, [I|Acc]); +bsm_reroute([], _, _, Acc) -> reverse(Acc). + +bsm_opt_2([{test,bs_test_tail2,F,[Ctx,Bits]}|Is], + [{test,bs_skip_bits2,F,[Ctx,{integer,I},Unit,_Flags]}|Acc]) -> + bsm_opt_2(Is, [{test,bs_test_tail2,F,[Ctx,Bits+I*Unit]}|Acc]); +bsm_opt_2([{test,bs_skip_bits2,F,[Ctx,{integer,I1},Unit1,_]}|Is], + [{test,bs_skip_bits2,F,[Ctx,{integer,I2},Unit2,Flags]}|Acc]) -> + bsm_opt_2(Is, [{test,bs_skip_bits2,F, + [Ctx,{integer,I1*Unit1+I2*Unit2},1,Flags]}|Acc]); +bsm_opt_2([I|Is], Acc) -> + bsm_opt_2(Is, [I|Acc]); +bsm_opt_2([], Acc) -> reverse(Acc). + +%% bsm_not_bs_test({test,Name,_,Operands}) -> true|false. +%% Test whether is the test is a "safe", i.e. does not move the +%% bit offset for a binary. +%% +%% 'true' means that the test is safe, 'false' that we don't know or +%% that the test moves the offset (e.g. bs_get_integer2). + +bsm_not_bs_test({test,bs_test_tail2,_,[_,_]}) -> true; +bsm_not_bs_test(Test) -> beam_utils:is_pure_test(Test). + +bsm_subst_labels(Fs, Save, D) -> + bsm_subst_labels_1(Fs, Save, D, []). + +bsm_subst_labels_1([F|Fs], Save, D, Acc) -> + bsm_subst_labels_1(Fs, Save, D, [bsm_subst_label(F, Save, D)|Acc]); +bsm_subst_labels_1([], _, _, Acc) -> + reverse(Acc). + +bsm_subst_label({f,Lbl0}=F, Save, D) -> + case gb_trees:lookup({Lbl0,Save}, D) of + {value,Lbl} -> {f,Lbl}; + none -> F + end; +bsm_subst_label(Other, _, _) -> Other. diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl index 919ee3ee7d..d9108c383d 100644 --- a/lib/compiler/src/beam_clean.erl +++ b/lib/compiler/src/beam_clean.erl @@ -141,7 +141,7 @@ renumber_labels([{bif,is_record,{f,_}, renumber_labels(Is, Acc, St); renumber_labels([{test,is_record,{f,_}=Fail, [Term,{atom,Tag}=TagAtom,{integer,Arity}]}|Is0], Acc, St) -> - Tmp = {x,1023}, + Tmp = {x,1022}, Is = case is_record_tuple(Term, Tag, Arity) of yes -> Is0; @@ -190,17 +190,11 @@ replace([{test,Test,{f,Lbl},Ops}|Is], Acc, D) -> replace([{test,Test,{f,Lbl},Live,Ops,Dst}|Is], Acc, D) -> replace(Is, [{test,Test,{f,label(Lbl, D)},Live,Ops,Dst}|Acc], D); replace([{select,I,R,{f,Fail0},Vls0}|Is], Acc, D) -> - Vls1 = map(fun ({f,L}) -> {f,label(L, D)}; - (Other) -> Other end, Vls0), + Vls = map(fun ({f,L}) -> {f,label(L, D)}; + (Other) -> Other + end, Vls0), Fail = label(Fail0, D), - case redundant_values(Vls1, Fail, []) of - [] -> - %% Oops, no choices left. The loader will not accept that. - %% Convert to a plain jump. - replace(Is, [{jump,{f,Fail}}|Acc], D); - Vls -> - replace(Is, [{select,I,R,{f,Fail},Vls}|Acc], D) - end; + replace(Is, [{select,I,R,{f,Fail},Vls}|Acc], D); replace([{'try',R,{f,Lbl}}|Is], Acc, D) -> replace(Is, [{'try',R,{f,label(Lbl, D)}}|Acc], D); replace([{'catch',R,{f,Lbl}}|Is], Acc, D) -> @@ -241,12 +235,6 @@ label(Old, D) -> {value,Val} -> Val; none -> throw({error,{undefined_label,Old}}) end. - -redundant_values([_,{f,Fail}|Vls], Fail, Acc) -> - redundant_values(Vls, Fail, Acc); -redundant_values([Val,Lbl|Vls], Fail, Acc) -> - redundant_values(Vls, Fail, [Lbl,Val|Acc]); -redundant_values([], _, Acc) -> reverse(Acc). %%% %%% Final fixup of bs_start_match2/5,bs_save2/bs_restore2 instructions for diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index ead88b57e9..11129c39bc 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -239,11 +239,26 @@ backward([{test,is_eq_exact,Fail,[Dst,{integer,Arity}]}=I| backward([{label,Lbl}=L|Is], D, Acc) -> backward(Is, beam_utils:index_label(Lbl, Acc, D), [L|Acc]); backward([{select,select_val,Reg,{f,Fail0},List0}|Is], D, Acc) -> - List = shortcut_select_list(List0, Reg, D, []), + List1 = shortcut_select_list(List0, Reg, D, []), Fail1 = shortcut_label(Fail0, D), Fail = shortcut_bs_test(Fail1, Is, D), - Sel = {select,select_val,Reg,{f,Fail},List}, - backward(Is, D, [Sel|Acc]); + List = prune_redundant(List1, Fail), + case List of + [] -> + Jump = {jump,{f,Fail}}, + backward([Jump|Is], D, Acc); + [V,F] -> + Test = {test,is_eq_exact,{f,Fail},[Reg,V]}, + Jump = {jump,F}, + backward([Jump,Test|Is], D, Acc); + [{atom,B1},F,{atom,B2},F] when B1 =:= not B2 -> + Test = {test,is_boolean,{f,Fail},[Reg]}, + Jump = {jump,F}, + backward([Jump,Test|Is], D, Acc); + [_|_] -> + Sel = {select,select_val,Reg,{f,Fail},List}, + backward(Is, D, [Sel|Acc]) + end; backward([{jump,{f,To0}},{move,Src,Reg}=Move|Is], D, Acc) -> To = shortcut_select_label(To0, Reg, Src, D), Jump = {jump,{f,To}}, @@ -257,14 +272,17 @@ backward([{jump,{f,To}}=J|[{bif,Op,_,Ops,Reg}|Is]=Is0], D, Acc) -> catch throw:not_possible -> backward(Is0, D, [J|Acc]) end; -backward([{test,bs_start_match2,F,_,[R,_],Ctxt}=I|Is], D, +backward([{test,bs_start_match2,F,Live,[R,_]=Args,Ctxt}|Is], D, [{test,bs_match_string,F,[Ctxt,Bs]}, {test,bs_test_tail2,F,[Ctxt,0]}|Acc0]=Acc) -> + {f,To0} = F, + To = shortcut_bs_start_match(To0, R, D), case beam_utils:is_killed(Ctxt, Acc0, D) of true -> - Eq = {test,is_eq_exact,F,[R,{literal,Bs}]}, + Eq = {test,is_eq_exact,{f,To},[R,{literal,Bs}]}, backward(Is, D, [Eq|Acc0]); false -> + I = {test,bs_start_match2,{f,To},Live,Args,Ctxt}, backward(Is, D, [I|Acc]) end; backward([{test,bs_start_match2,{f,To0},Live,[Src|_]=Info,Dst}|Is], D, Acc) -> @@ -295,7 +313,28 @@ backward([{test,Op,{f,To0},Ops0}|Is], D, Acc) -> is_eq_exact -> combine_eqs(To, Ops0, D, Acc); _ -> {test,Op,{f,To},Ops0} end, - backward(Is, D, [I|Acc]); + case {I,Acc} of + {{test,is_atom,Fail,Ops0},[{test,is_boolean,Fail,Ops0}|_]} -> + %% An is_atom test before an is_boolean test (with the + %% same failure label) is redundant. + backward(Is, D, Acc); + {{test,is_atom,Fail,[R]}, + [{test,is_eq_exact,Fail,[R,{atom,_}]}|_]} -> + %% An is_atom test before a comparison with an atom (with + %% the same failure label) is redundant. + backward(Is, D, Acc); + {{test,is_integer,Fail,[R]}, + [{test,is_eq_exact,Fail,[R,{integer,_}]}|_]} -> + %% An is_integer test before a comparison with an integer + %% (with the same failure label) is redundant. + backward(Is, D, Acc); + {{test,_,_,_},_} -> + %% Still a test instruction. Done. + backward(Is, D, [I|Acc]); + {_,_} -> + %% Rewritten to a select_val. Rescan. + backward([I|Is], D, Acc) + end; backward([{test,Op,{f,To0},Live,Ops0,Dst}|Is], D, Acc) -> To1 = shortcut_bs_test(To0, Is, D), To2 = shortcut_label(To1, D), @@ -348,6 +387,12 @@ shortcut_label(To0, D) -> shortcut_select_label(To, Reg, Lit, D) -> shortcut_rel_op(To, is_ne_exact, [Reg,Lit], D). +prune_redundant([_,{f,Fail}|T], Fail) -> + prune_redundant(T, Fail); +prune_redundant([V,F|T], Fail) -> + [V,F|prune_redundant(T, Fail)]; +prune_redundant([], _) -> []. + %% Replace a comparison operator with a test instruction and a jump. %% For example, if we have this code: %% diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl index 5e58e0f6ac..3b6eb19fe8 100644 --- a/lib/compiler/src/beam_jump.erl +++ b/lib/compiler/src/beam_jump.erl @@ -495,7 +495,7 @@ is_label_used_in_block({set,_,_,Info}, Lbl) -> {alloc,_,{gc_bif,_,{f,F}}} -> F =:= Lbl; {alloc,_,{put_map,_,{f,F}}} -> F =:= Lbl; {get_map_elements,{f,F}} -> F =:= Lbl; - {'catch',{f,F}} -> F =:= Lbl; + {try_catch,_,{f,F}} -> F =:= Lbl; {alloc,_,_} -> false; {put_tuple,_} -> false; {get_tuple_element,_} -> false; diff --git a/lib/compiler/src/beam_peep.erl b/lib/compiler/src/beam_peep.erl index 17fd2e502a..0c1abfe6a0 100644 --- a/lib/compiler/src/beam_peep.erl +++ b/lib/compiler/src/beam_peep.erl @@ -65,18 +65,6 @@ function({function,Name,Arity,CLabel,Is0}) -> %% InEncoding =:= latin1, OutEncoding =:= unicode; %% InEncoding =:= latin1, OutEncoding =:= utf8 -> %% -%% (2) A select_val/4 instruction that only verifies that -%% its argument is either 'true' or 'false' can be -%% be replaced with an is_boolean/2 instruction. That is: -%% -%% select_val Reg Fail [ true Next false Next ] -%% Next: ... -%% -%% can be rewritten to -%% -%% is_boolean Fail Reg -%% Next: ... -%% peep(Is) -> peep(Is, gb_sets:empty(), []). @@ -95,12 +83,16 @@ peep([{gc_bif,_,_,_,_,Dst}=I|Is], SeenTests0, Acc) -> %% Kill all remembered tests that depend on the destination register. SeenTests = kill_seen(Dst, SeenTests0), peep(Is, SeenTests, [I|Acc]); -peep([{test,is_boolean,{f,Fail},Ops}|_]=Is, SeenTests, - [{test,is_atom,{f,Fail},Ops}|Acc]) -> - %% The previous is_atom/2 test (with the same failure label) is redundant. - %% (If is_boolean(Src) is true, is_atom(Src) is also true, so it is - %% OK to still remember that we have seen is_atom/1.) - peep(Is, SeenTests, Acc); +peep([{select,Op,R,F,Vls0}|Is], _, Acc) -> + case prune_redundant_values(Vls0, F) of + [] -> + %% No values left. Must convert to plain jump. + I = {jump,F}, + peep(Is, gb_sets:empty(), [I|Acc]); + [_|_]=Vls -> + I = {select,Op,R,F,Vls}, + peep(Is, gb_sets:empty(), [I|Acc]) + end; peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) -> case beam_utils:is_pure_test(I) of false -> @@ -121,16 +113,6 @@ peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) -> peep(Is, SeenTests, [I|Acc]) end end; -peep([{select,select_val,Src,Fail, - [{atom,false},{f,L},{atom,true},{f,L}]}| - [{label,L}|_]=Is], SeenTests, Acc) -> - I = {test,is_boolean,Fail,[Src]}, - peep([I|Is], SeenTests, Acc); -peep([{select,select_val,Src,Fail, - [{atom,true},{f,L},{atom,false},{f,L}]}| - [{label,L}|_]=Is], SeenTests, Acc) -> - I = {test,is_boolean,Fail,[Src]}, - peep([I|Is], SeenTests, Acc); peep([I|Is], _, Acc) -> %% An unknown instruction. Throw away all information we %% have collected about test instructions. @@ -155,3 +137,9 @@ kill_seen_1([{_,Ops}=Test|T], Dst) -> false -> [Test|kill_seen_1(T, Dst)] end; kill_seen_1([], _) -> []. + +prune_redundant_values([_Val,F|Vls], F) -> + prune_redundant_values(Vls, F); +prune_redundant_values([Val,Lbl|Vls], F) -> + [Val,Lbl|prune_redundant_values(Vls, F)]; +prune_redundant_values([], _) -> []. diff --git a/lib/compiler/src/beam_reorder.erl b/lib/compiler/src/beam_reorder.erl new file mode 100644 index 0000000000..41586a7bf2 --- /dev/null +++ b/lib/compiler/src/beam_reorder.erl @@ -0,0 +1,139 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(beam_reorder). + +-export([module/2]). +-import(lists, [member/2,reverse/1]). + +module({Mod,Exp,Attr,Fs0,Lc}, _Opt) -> + Fs = [function(F) || F <- Fs0], + {ok,{Mod,Exp,Attr,Fs,Lc}}. + +function({function,Name,Arity,CLabel,Is0}) -> + try + Is = reorder(Is0), + {function,Name,Arity,CLabel,Is} + catch + Class:Error -> + Stack = erlang:get_stacktrace(), + io:fwrite("Function: ~w/~w\n", [Name,Arity]), + erlang:raise(Class, Error, Stack) + end. + +%% reorder(Instructions0) -> Instructions +%% Reorder instructions before the beam_block pass, because reordering +%% will be more cumbersome when the blocks are in place. +%% +%% Execution of get_tuple_element instructions can be delayed until +%% they are actually needed. Consider the sequence: +%% +%% get_tuple_element Tuple Pos Dst +%% test Test Fail Operands +%% +%% If Dst is killed at label Fail (and not referenced in Operands), +%% we can can swap the instructions: +%% +%% test Test Fail Operands +%% get_tuple_element Tuple Pos Dst +%% +%% That can be beneficial in two ways: Firstly, if the branch is taken +%% we have avoided execution of the get_tuple_element instruction. +%% Secondly, even if the branch is not taken, subsequent optimization +%% (opt_blocks/1) may be able to change Dst to the final destination +%% register and eliminate a 'move' instruction. + +reorder(Is) -> + D = beam_utils:index_labels(Is), + reorder_1(Is, D, []). + +reorder_1([{Op,_,_}=TryCatch|[I|Is]=Is0], D, Acc) + when Op =:= 'catch'; Op =:= 'try' -> + %% Don't allow 'try' or 'catch' instructions to split blocks if + %% it can be avoided. + case is_safe(I) of + false -> + reorder_1(Is0, D, [TryCatch|Acc]); + true -> + reorder_1([TryCatch|Is], D, [I|Acc]) + end; +reorder_1([{label,L}=I|_], D, Acc) -> + Is = beam_utils:code_at(L, D), + reorder_1(Is, D, [I|Acc]); +reorder_1([{test,is_nonempty_list,_,_}=I|Is], D, Acc) -> + %% The run-time system may combine the is_nonempty_list test with + %% the following get_list instruction. + reorder_1(Is, D, [I|Acc]); +reorder_1([{test,_,_,_}=I, + {select,_,_,_,_}=S|Is], D, Acc) -> + %% There is nothing to gain by inserting a get_tuple_element + %% instruction between the test instruction and the select + %% instruction. + reorder_1(Is, D, [S,I|Acc]); +reorder_1([{test,_,{f,L},Ss}=I|Is0], D0, + [{get_tuple_element,_,_,El}=G|Acc0]=Acc) -> + case member(El, Ss) of + true -> + reorder_1(Is0, D0, [I|Acc]); + false -> + case beam_utils:is_killed_at(El, L, D0) of + true -> + Is = [I,G|Is0], + reorder_1(Is, D0, Acc0); + false -> + case beam_utils:is_killed(El, Is0, D0) of + true -> + Code0 = beam_utils:code_at(L, D0), + Code = [G|Code0], + D = beam_utils:index_label(L, Code, D0), + Is = [I|Is0], + reorder_1(Is, D, Acc0); + false -> + reorder_1(Is0, D0, [I|Acc]) + end + end + end; +reorder_1([{allocate_zero,N,Live}=I0|Is], D, + [{get_tuple_element,{x,Tup},_,{x,Dst}}=G|Acc]=Acc0) -> + case Tup < Dst andalso Dst+1 =:= Live of + true -> + %% Move allocation instruction upwards past + %% get_tuple_element instructions to create more + %% opportunities for moving get_tuple_element + %% instructions. + I = {allocate_zero,N,Dst}, + reorder_1([I,G|Is], D, Acc); + false -> + reorder_1(Is, D, [I0|Acc0]) + end; +reorder_1([I|Is], D, Acc) -> + reorder_1(Is, D, [I|Acc]); +reorder_1([], _, Acc) -> reverse(Acc). + +%% is_safe(Instruction) -> true|false +%% Test whether an instruction is safe (cannot cause an exception). + +is_safe({kill,_}) -> true; +is_safe({move,_,_}) -> true; +is_safe({put,_}) -> true; +is_safe({put_list,_,_,_}) -> true; +is_safe({put_tuple,_,_}) -> true; +is_safe({test_heap,_,_}) -> true; +is_safe(_) -> false. diff --git a/lib/compiler/src/beam_split.erl b/lib/compiler/src/beam_split.erl index 3be9311080..bb1c0e23a9 100644 --- a/lib/compiler/src/beam_split.erl +++ b/lib/compiler/src/beam_split.erl @@ -57,8 +57,8 @@ split_block([{set,[D],[S|Puts],{alloc,R,{put_map,Op,{f,Lbl}=Fail}}}|Is], split_block([{set,Ds,[S|Ss],{get_map_elements,Fail}}|Is], Bl, Acc) -> Gets = beam_utils:join_even(Ss,Ds), split_block(Is, [], [{get_map_elements,Fail,S,{list,Gets}}|make_block(Bl, Acc)]); -split_block([{set,[R],[],{'catch',L}}|Is], Bl, Acc) -> - split_block(Is, [], [{'catch',R,L}|make_block(Bl, Acc)]); +split_block([{set,[R],[],{try_catch,Op,L}}|Is], Bl, Acc) -> + split_block(Is, [], [{Op,R,L}|make_block(Bl, Acc)]); split_block([{set,[],[],{line,_}=Line}|Is], Bl, Acc) -> split_block(Is, [], [Line|make_block(Bl, Acc)]); split_block([I|Is], Bl, Acc) -> diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl index 5298589f83..4b45c28623 100644 --- a/lib/compiler/src/beam_type.erl +++ b/lib/compiler/src/beam_type.erl @@ -23,7 +23,8 @@ -export([module/2]). --import(lists, [foldl/3,reverse/1,filter/2]). +-import(lists, [filter/2,foldl/3,keyfind/3,member/2, + reverse/1,reverse/2,sort/1]). module({Mod,Exp,Attr,Fs0,Lc}, _Opts) -> Fs = [function(F) || F <- Fs0], @@ -92,8 +93,19 @@ simplify_basic_1([{set,[D],[TupleReg],{get_tuple_element,0}}=I|Is0], Ts0, Acc) - Ts = update(I, Ts0), simplify_basic_1(Is0, Ts, [I|Acc]) end; -simplify_basic_1([{set,_,_,{'catch',_}}=I|Is], _Ts, Acc) -> +simplify_basic_1([{set,_,_,{try_catch,_,_}}=I|Is], _Ts, Acc) -> simplify_basic_1(Is, tdb_new(), [I|Acc]); +simplify_basic_1([{test,is_atom,_,[R]}=I|Is], Ts, Acc) -> + case tdb_find(R, Ts) of + boolean -> simplify_basic_1(Is, Ts, Acc); + _ -> simplify_basic_1(Is, Ts, [I|Acc]) + end; +simplify_basic_1([{test,is_integer,_,[R]}=I|Is], Ts, Acc) -> + case tdb_find(R, Ts) of + integer -> simplify_basic_1(Is, Ts, Acc); + {integer,_} -> simplify_basic_1(Is, Ts, Acc); + _ -> simplify_basic_1(Is, Ts, [I|Acc]) + end; simplify_basic_1([{test,is_tuple,_,[R]}=I|Is], Ts, Acc) -> case tdb_find(R, Ts) of {tuple,_,_} -> simplify_basic_1(Is, Ts, Acc); @@ -137,6 +149,16 @@ simplify_basic_1([{test,is_record,_,[R,{atom,_}=Tag,{integer,Arity}]}=I|Is], Ts0 Ts = update(I, Ts0), simplify_basic_1(Is, Ts, [I|Acc]) end; +simplify_basic_1([{select,select_val,Reg,_,_}=I0|Is], Ts, Acc) -> + I = case tdb_find(Reg, Ts) of + {integer,Range} -> + simplify_select_val_int(I0, Range); + boolean -> + simplify_select_val_bool(I0); + _ -> + I0 + end, + simplify_basic_1(Is, tdb_new(), [I|Acc]); simplify_basic_1([I|Is], Ts0, Acc) -> Ts = update(I, Ts0), simplify_basic_1(Is, Ts, [I|Acc]); @@ -144,6 +166,32 @@ simplify_basic_1([], Ts, Acc) -> Is = reverse(Acc), {Is,Ts}. +simplify_select_val_int({select,select_val,R,_,L0}=I, {Min,Max}) -> + Vs = sort([V || {integer,V} <- L0]), + case eq_ranges(Vs, Min, Max) of + false -> I; + true -> simplify_select_val_1(L0, {integer,Max}, R, []) + end. + +simplify_select_val_bool({select,select_val,R,_,L}=I) -> + Vs = sort([V || {atom,V} <- L]), + case Vs of + [false,true] -> + simplify_select_val_1(L, {atom,false}, R, []); + _ -> + I + end. + +simplify_select_val_1([Val,F|T], Val, R, Acc) -> + L = reverse(Acc, T), + {select,select_val,R,F,L}; +simplify_select_val_1([V,F|T], Val, R, Acc) -> + simplify_select_val_1(T, Val, R, [F,V|Acc]). + +eq_ranges([H], H, H) -> true; +eq_ranges([H|T], H, Max) -> eq_ranges(T, H+1, Max); +eq_ranges(_, _, _) -> false. + %% simplify_float([Instruction], TypeDatabase) -> %% {[Instruction],TypeDatabase'} | not_possible %% Simplify floating point operations in blocks. @@ -199,7 +247,7 @@ simplify_float_1([{set,[D0],[A0,B0],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0, Ts = tdb_update([{D0,float}], Ts0), simplify_float_1(Is, Ts, Rs, Acc) end; -simplify_float_1([{set,_,_,{'catch',_}}=I|Is]=Is0, _Ts, Rs0, Acc0) -> +simplify_float_1([{set,_,_,{try_catch,_,_}}=I|Is]=Is0, _Ts, Rs0, Acc0) -> Acc = flush_all(Rs0, Is0, Acc0), simplify_float_1(Is, tdb_new(), Rs0, [I|Acc]); simplify_float_1([{set,_,_,{line,_}}=I|Is], Ts, Rs, Acc) -> @@ -311,7 +359,7 @@ flt_need_heap_2({set,_,_,{get_tuple_element,_}}, H, Fl) -> {[],H,Fl}; flt_need_heap_2({set,_,_,get_list}, H, Fl) -> {[],H,Fl}; -flt_need_heap_2({set,_,_,{'catch',_}}, H, Fl) -> +flt_need_heap_2({set,_,_,{try_catch,_,_}}, H, Fl) -> {[],H,Fl}; %% All other instructions should cause the insertion of an allocation %% instruction if needed. @@ -382,6 +430,17 @@ update({set,[D],[{integer,I},Reg],{bif,element,_}}, Ts0) -> tdb_update([{Reg,{tuple,I,[]}},{D,kill}], Ts0); update({set,[D],[_Index,Reg],{bif,element,_}}, Ts0) -> tdb_update([{Reg,{tuple,0,[]}},{D,kill}], Ts0); +update({set,[D],Args,{bif,N,_}}, Ts0) -> + Ar = length(Args), + BoolOp = erl_internal:new_type_test(N, Ar) orelse + erl_internal:comp_op(N, Ar) orelse + erl_internal:bool_op(N, Ar), + case BoolOp of + true -> + tdb_update([{D,boolean}], Ts0); + false -> + tdb_update([{D,kill}], Ts0) + end; update({set,[D],[S],{get_tuple_element,0}}, Ts) -> tdb_update([{D,{tuple_element,S,0}}], Ts); update({set,[D],[S],{alloc,_,{gc_bif,float,{f,0}}}}, Ts0) -> @@ -390,6 +449,13 @@ update({set,[D],[S],{alloc,_,{gc_bif,float,{f,0}}}}, Ts0) -> true -> tdb_update([{D,float}], Ts0); false -> Ts0 end; +update({set,[D],[S1,S2],{alloc,_,{gc_bif,'band',{f,0}}}}, Ts) -> + case keyfind(integer, 1, [S1,S2]) of + {integer,N} -> + update_band(N, D, Ts); + false -> + tdb_update([{D,integer}], Ts) + end; update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts0) -> %% Make sure we reject non-numeric literals. case possibly_numeric(S1) andalso possibly_numeric(S2) of @@ -397,15 +463,17 @@ update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts0) -> false -> Ts0 end; update({set,[D],[S1,S2],{alloc,_,{gc_bif,Op,{f,0}}}}, Ts0) -> - case arith_op(Op) of - no -> - tdb_update([{D,kill}], Ts0); - {yes,_} -> + case op_type(Op) of + integer -> + tdb_update([{D,integer}], Ts0); + {float,_} -> case {tdb_find(S1, Ts0),tdb_find(S2, Ts0)} of {float,_} -> tdb_update([{D,float}], Ts0); {_,float} -> tdb_update([{D,float}], Ts0); {_,_} -> tdb_update([{D,kill}], Ts0) - end + end; + unknown -> + tdb_update([{D,kill}], Ts0) end; update({set,[],_Src,_Op}, Ts0) -> Ts0; update({set,[D],_Src,_Op}, Ts0) -> @@ -437,6 +505,8 @@ update({test,is_record,_Fail,[Src,Tag,{integer,Arity}]}, Ts) -> tdb_update([{Src,{tuple,Arity,[Tag]}}], Ts); update({test,_Test,_Fail,_Other}, Ts) -> Ts; +update({test,bs_get_integer2,_,_,Args,Dst}, Ts) -> + tdb_update([{Dst,get_bs_integer_type(Args)}], Ts); update({call_ext,Ar,{extfunc,math,Math,Ar}}, Ts) -> case is_math_bif(Math, Ar) of true -> tdb_update([{{x,0},float}], Ts); @@ -453,10 +523,43 @@ update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts); update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts); update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts); update({line,_}, Ts) -> Ts; +update({bs_save2,_,_}, Ts) -> Ts; +update({bs_restore2,_,_}, Ts) -> Ts; %% The instruction is unknown. Kill all information. update(_I, _Ts) -> tdb_new(). +update_band(N, Reg, Ts) -> + Type = update_band_1(N, 0), + tdb_update([{Reg,Type}], Ts). + +update_band_1(N, Bits) when Bits < 64 -> + case 1 bsl Bits of + P when P =:= N + 1 -> + {integer,{0,N}}; + P when P > N + 1 -> + integer; + _ -> + update_band_1(N, Bits+1) + end; +update_band_1(_, _) -> + %% Negative or large positive number. Give up. + integer. + +get_bs_integer_type([_,{integer,N},U,{field_flags,Fl}]) + when N*U < 64 -> + NumBits = N*U, + case member(unsigned, Fl) of + true -> + {integer,{0,(1 bsl NumBits)-1}}; + false -> + %% Signed integer. Don't bother. + integer + end; +get_bs_integer_type(_) -> + %% Avoid creating ranges with a huge upper limit. + integer. + is_math_bif(cos, 1) -> true; is_math_bif(cosh, 1) -> true; is_math_bif(sin, 1) -> true; @@ -545,11 +648,22 @@ load_reg(V, Ts, Rs0, Is0) -> {Rs,Is} end. -arith_op('+') -> {yes,fadd}; -arith_op('-') -> {yes,fsub}; -arith_op('*') -> {yes,fmul}; -arith_op('/') -> {yes,fdiv}; -arith_op(_) -> no. +arith_op(Op) -> + case op_type(Op) of + {float,Instr} -> {yes,Instr}; + _ -> no + end. + +op_type('+') -> {float,fadd}; +op_type('-') -> {float,fsub}; +op_type('*') -> {float,fmul}; +%% '/' and 'band' are specially handled. +op_type('bor') -> integer; +op_type('bxor') -> integer; +op_type('bsl') -> integer; +op_type('bsr') -> integer; +op_type('div') -> integer; +op_type(_) -> unknown. flush(Rs, [{set,[_],[],{put_tuple,_}}|_]=Is0, Acc0) -> Acc = flush_all(Rs, Is0, Acc0), @@ -618,7 +732,6 @@ checkerror(Is) -> checkerror_1(Is, Is). checkerror_1([{set,[],[],fcheckerror}|_], OrigIs) -> OrigIs; -checkerror_1([{set,[],[],fclearerror}|_], OrigIs) -> OrigIs; checkerror_1([{set,_,_,{bif,fadd,_}}|_], OrigIs) -> checkerror_2(OrigIs); checkerror_1([{set,_,_,{bif,fsub,_}}|_], OrigIs) -> checkerror_2(OrigIs); checkerror_1([{set,_,_,{bif,fmul,_}}|_], OrigIs) -> checkerror_2(OrigIs); @@ -640,6 +753,9 @@ checkerror_2(OrigIs) -> [{set,[],[],fcheckerror}|OrigIs]. %%% of the first element). %%% %%% 'float' means that the register contains a float. +%%% +%%% 'integer' or {integer,{Min,Max}} that the register contains an +%%% integer. %% tdb_new() -> EmptyDataBase %% Creates a new, empty type database. @@ -729,10 +845,20 @@ merge_type_info({tuple,Sz1,[]}, {tuple,_Sz2,First}=Tuple2) -> merge_type_info({tuple,Sz1,First}, Tuple2); merge_type_info({tuple,_Sz1,First}=Tuple1, {tuple,Sz2,_}) -> merge_type_info(Tuple1, {tuple,Sz2,First}); +merge_type_info(integer, {integer,_}=Int) -> + Int; +merge_type_info({integer,_}=Int, integer) -> + Int; +merge_type_info({integer,{Min1,Max1}}, {integer,{Min2,Max2}}) -> + {integer,{max(Min1, Min2),min(Max1, Max2)}}; merge_type_info(NewType, _) -> verify_type(NewType), NewType. +verify_type(boolean) -> ok; +verify_type(integer) -> ok; +verify_type({integer,{Min,Max}}) + when is_integer(Min), is_integer(Max) -> ok; verify_type(map) -> ok; verify_type(nonempty_list) -> ok; verify_type({tuple,Sz,[]}) when is_integer(Sz) -> ok; diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index fbcd5de1bb..68d6105cfa 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -484,6 +484,15 @@ check_liveness(R, [{get_map_elements,{f,Fail},S,{list,L}}|Is], St0) -> Other end end; +check_liveness(R, [{test_heap,N,Live}|Is], St) -> + I = {block,[{set,[],[],{alloc,Live,{nozero,nostack,N,[]}}}]}, + check_liveness(R, [I|Is], St); +check_liveness(R, [{allocate_zero,N,Live}|Is], St) -> + I = {block,[{set,[],[],{alloc,Live,{zero,N,0,[]}}}]}, + check_liveness(R, [I|Is], St); +check_liveness(R, [{get_list,S,D1,D2}|Is], St) -> + I = {block,[{set,[D1,D2],[S],get_list}]}, + check_liveness(R, [I|Is], St); check_liveness(_R, Is, St) when is_list(Is) -> %% case Is of %% [I|_] -> diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 6004f1974e..cdace42a68 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -31,8 +31,6 @@ -import(lists, [reverse/1,foldl/3,foreach/2,dropwhile/2]). --define(MAXREG, 1024). - %%-define(DEBUG, 1). -ifdef(DEBUG). -define(DBG_FORMAT(F, D), (io:format((F), (D)))). @@ -980,9 +978,9 @@ get_fls(#vst{current=#st{fls=Fls}}) when is_atom(Fls) -> Fls. init_fregs() -> 0. -set_freg({fr,Fr}, #vst{current=#st{f=Fregs0}=St}=Vst) +set_freg({fr,Fr}=Freg, #vst{current=#st{f=Fregs0}=St}=Vst) when is_integer(Fr), 0 =< Fr -> - limit_check(Fr), + check_limit(Freg), Bit = 1 bsl Fr, if Fregs0 band Bit =:= 0 -> @@ -995,9 +993,10 @@ set_freg(Fr, _) -> error({bad_target,Fr}). assert_freg_set({fr,Fr}=Freg, #vst{current=#st{f=Fregs}}) when is_integer(Fr), 0 =< Fr -> if - Fregs band (1 bsl Fr) =/= 0 -> - limit_check(Fr); - true -> error({uninitialized_reg,Freg}) + (Fregs bsr Fr) band 1 =:= 0 -> + error({uninitialized_reg,Freg}); + true -> + ok end; assert_freg_set(Fr, _) -> error({bad_source,Fr}). @@ -1076,16 +1075,16 @@ set_type(Type, {x,_}=Reg, Vst) -> set_type_reg(Type, Reg, Vst); set_type(Type, {y,_}=Reg, Vst) -> set_type_y(Type, Reg, Vst); set_type(_, _, #vst{}=Vst) -> Vst. -set_type_reg(Type, {x,X}, #vst{current=#st{x=Xs}=St}=Vst) +set_type_reg(Type, {x,X}=Reg, #vst{current=#st{x=Xs}=St}=Vst) when is_integer(X), 0 =< X -> - limit_check(X), + check_limit(Reg), Vst#vst{current=St#st{x=gb_trees:enter(X, Type, Xs)}}; set_type_reg(Type, Reg, Vst) -> set_type_y(Type, Reg, Vst). set_type_y(Type, {y,Y}=Reg, #vst{current=#st{y=Ys0}=St}=Vst) when is_integer(Y), 0 =< Y -> - limit_check(Y), + check_limit(Reg), Ys = case gb_trees:lookup(Y, Ys0) of none -> error({invalid_store,Reg,Type}); @@ -1612,9 +1611,15 @@ return_type_math(pow, 2) -> {float,[]}; return_type_math(pi, 0) -> {float,[]}; return_type_math(F, A) when is_atom(F), is_integer(A), A >= 0 -> term. -limit_check(Num) when is_integer(Num), Num >= ?MAXREG -> - error(limit); -limit_check(_) -> ok. +check_limit({x,X}) when is_integer(X), X < 1023 -> + %% Note: x(1023) is reserved for use by the BEAM loader. + ok; +check_limit({y,Y}) when is_integer(Y), Y < 1024 -> + ok; +check_limit({fr,Fr}) when is_integer(Fr), Fr < 1024 -> + ok; +check_limit(_) -> + error(limit). min(A, B) when is_integer(A), is_integer(B), A < B -> A; min(A, B) when is_integer(A), is_integer(B) -> B. diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index e0a29fe9b1..a2a23a2b90 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -671,11 +671,16 @@ asm_passes() -> %% Assembly level optimisations. [{delay, [{pass,beam_a}, + {iff,da,{listing,"a"}}, {unless,no_postopt, - [{pass,beam_block}, + [{unless,no_reorder,{pass,beam_reorder}}, + {iff,dre,{listing,"reorder"}}, + {pass,beam_block}, {iff,dblk,{listing,"block"}}, {unless,no_except,{pass,beam_except}}, {iff,dexcept,{listing,"except"}}, + {unless,no_bs_opt,{pass,beam_bs}}, + {iff,dbs,{listing,"bs"}}, {unless,no_bopt,{pass,beam_bool}}, {iff,dbool,{listing,"bool"}}, {unless,no_topt,{pass,beam_type}}, @@ -703,6 +708,7 @@ asm_passes() -> {iff,no_postopt,[{pass,beam_clean}]}, {pass,beam_z}, + {iff,dz,{listing,"z"}}, {iff,dopt,{listing,"optimize"}}, {iff,'S',{listing,"S"}}, {iff,'to_asm',{done,"S"}}]}, diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src index afb85f4710..a2b2a1d277 100644 --- a/lib/compiler/src/compiler.app.src +++ b/lib/compiler/src/compiler.app.src @@ -25,6 +25,7 @@ beam_asm, beam_block, beam_bool, + beam_bs, beam_bsm, beam_clean, beam_dead, @@ -37,6 +38,7 @@ beam_opcodes, beam_peep, beam_receive, + beam_reorder, beam_split, beam_trim, beam_type, diff --git a/lib/compiler/src/core_lib.erl b/lib/compiler/src/core_lib.erl index 3abb520485..839c736ff2 100644 --- a/lib/compiler/src/core_lib.erl +++ b/lib/compiler/src/core_lib.erl @@ -21,52 +21,16 @@ -module(core_lib). --deprecated({get_anno,1,next_major_release}). --deprecated({set_anno,2,next_major_release}). --deprecated({is_literal,1,next_major_release}). --deprecated({is_literal_list,1,next_major_release}). --deprecated({literal_value,1,next_major_release}). - --export([get_anno/1,set_anno/2]). --export([is_literal/1,is_literal_list/1]). --export([literal_value/1]). -export([make_values/1]). -export([is_var_used/2]). -include("core_parse.hrl"). -%% -%% Generic get/set annotation that should be used only with cerl() structures. -%% --spec get_anno(cerl:cerl()) -> term(). - -get_anno(C) -> cerl:get_ann(C). - --spec set_anno(cerl:cerl(), term()) -> cerl:cerl(). - -set_anno(C, A) -> cerl:set_ann(C, A). - --spec is_literal(cerl:cerl()) -> boolean(). - -is_literal(Cerl) -> - cerl:is_literal(cerl:fold_literal(Cerl)). - --spec is_literal_list([cerl:cerl()]) -> boolean(). - -is_literal_list(Es) -> lists:all(fun is_literal/1, Es). - -%% Return the value of LitExpr. --spec literal_value(cerl:c_literal() | cerl:c_binary() | - cerl:c_map() | cerl:c_cons() | cerl:c_tuple()) -> term(). - -literal_value(Cerl) -> - cerl:concrete(cerl:fold_literal(Cerl)). - %% Make a suitable values structure, expr or values, depending on Expr. -spec make_values([cerl:cerl()] | cerl:cerl()) -> cerl:cerl(). make_values([E]) -> E; -make_values([H|_]=Es) -> #c_values{anno=get_anno(H),es=Es}; +make_values([H|_]=Es) -> #c_values{anno=cerl:get_ann(H),es=Es}; make_values([]) -> #c_values{es=[]}; make_values(E) -> E. diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl index cc54f6e411..7d3513c0ba 100644 --- a/lib/compiler/src/core_lint.erl +++ b/lib/compiler/src/core_lint.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -73,7 +73,7 @@ %% Define the lint state record. -record(lint, {module :: module(), % Current module - func :: fa(), % Current function + func :: fa() | 'undefined', % Current function errors = [] :: [error()], % Errors warnings= [] :: [warning()]}). % Warnings diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab index 8124729b35..3a877f2403 100755 --- a/lib/compiler/src/genop.tab +++ b/lib/compiler/src/genop.tab @@ -45,7 +45,7 @@ BEAM_FORMAT_NUMBER=0 ## Save the next instruction as the return address in the CP register. 4: call/2 -## @spec call_last Arity Label Dellocate +## @spec call_last Arity Label Deallocate ## @doc Deallocate and do a tail recursive call to the function at Label. ## Do not update the CP register. ## Before the call deallocate Deallocate words of stack. @@ -137,7 +137,7 @@ BEAM_FORMAT_NUMBER=0 # Sending & receiving. # ## @spec send -## @doc Send argument in x(0) as a message to the destination process in x(0). +## @doc Send argument in x(1) as a message to the destination process in x(0). ## The message in x(1) ends up as the result of the send in x(0). 20: send/0 @@ -164,12 +164,12 @@ BEAM_FORMAT_NUMBER=0 25: wait/1 ## @spec wait_timeout Lable Time -## @doc Sets up a timeout of Time milllisecons and saves the address of the +## @doc Sets up a timeout of Time milliseconds and saves the address of the ## following instruction as the entry point if the timeout triggers. 26: wait_timeout/2 # -# Arithmethic opcodes. +# Arithmetic opcodes. # 27: -m_plus/4 28: -m_minus/4 @@ -316,7 +316,7 @@ BEAM_FORMAT_NUMBER=0 66: get_tuple_element/3 ## @spec set_tuple_element NewElement Tuple Position -## @doc Update the element at postition Position of the tuple Tuple +## @doc Update the element at position Position of the tuple Tuple ## with the new element NewElement. 67: set_tuple_element/3 diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 27d023d067..0a16776bd4 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -2793,12 +2793,18 @@ extract_type_1(Expr, Sub) -> true -> bool end. +returns_integer('band', [_,_]) -> true; +returns_integer('bnot', [_]) -> true; +returns_integer('bor', [_,_]) -> true; +returns_integer('bxor', [_,_]) -> true; returns_integer(bit_size, [_]) -> true; returns_integer('bsl', [_,_]) -> true; returns_integer('bsr', [_,_]) -> true; returns_integer(byte_size, [_]) -> true; +returns_integer('div', [_,_]) -> true; returns_integer(length, [_]) -> true; returns_integer('rem', [_,_]) -> true; +returns_integer('round', [_]) -> true; returns_integer(size, [_]) -> true; returns_integer(tuple_size, [_]) -> true; returns_integer(trunc, [_]) -> true; diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl index 34c67b16ca..5083995f30 100644 --- a/lib/compiler/src/v3_codegen.erl +++ b/lib/compiler/src/v3_codegen.erl @@ -827,21 +827,24 @@ select_extract_bin([{var,Hd},{var,Tl}], Size0, Unit, Type, Flags, Vf, {bs_save2,CtxReg,{Ctx,Tl}}],Int1} end, {Es,clear_dead(Aft, I, Vdb),St}; -select_extract_bin([{var,Hd}], Size0, Unit, binary, Flags, Vf, +select_extract_bin([{var,Hd}], Size, Unit, binary, Flags, Vf, I, Vdb, Bef, Ctx, Body, St) -> - SizeReg = get_bin_size_reg(Size0, Bef), + %% Match the last segment of a binary. We KNOW that the size + %% must be 'all'. + Size = {atom,all}, %Assertion. {Es,Aft} = case vdb_find(Hd, Vdb) of {_,_,Lhd} when Lhd =< I -> + %% The result will not be used. Furthermore, since we + %% we are at the end of the binary, the position will + %% not be used again; thus, it is safe to do a cheaper + %% test of the unit. CtxReg = fetch_var(Ctx, Bef), - {case SizeReg =:= {atom,all} andalso is_context_unused(Body) of - true when Unit =:= 1 -> + {case Unit of + 1 -> []; - true -> - [{test,bs_test_unit,{f,Vf},[CtxReg,Unit]}]; - false -> - [{test,bs_skip_bits2,{f,Vf}, - [CtxReg,SizeReg,Unit,{field_flags,Flags}]}] + _ -> + [{test,bs_test_unit,{f,Vf},[CtxReg,Unit]}] end,Bef}; {_,_,_} -> case is_context_unused(Body) of @@ -853,7 +856,7 @@ select_extract_bin([{var,Hd}], Size0, Unit, binary, Flags, Vf, Name = bs_get_binary2, Live = max_reg(Bef#sr.reg), {[{test,Name,{f,Vf},Live, - [CtxReg,SizeReg,Unit,{field_flags,Flags}],Rhd}], + [CtxReg,Size,Unit,{field_flags,Flags}],Rhd}], Int1}; true -> %% Since the matching context will not be used again, @@ -868,7 +871,7 @@ select_extract_bin([{var,Hd}], Size0, Unit, binary, Flags, Vf, Name = bs_get_binary2, Live = max_reg(Int1#sr.reg), {[{test,Name,{f,Vf},Live, - [CtxReg,SizeReg,Unit,{field_flags,Flags}],CtxReg}], + [CtxReg,Size,Unit,{field_flags,Flags}],CtxReg}], Int1} end end, diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 0941ad5dd5..7c229210a0 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -469,7 +469,8 @@ unforce_tree([#iset{var=#c_var{name=V},arg=Arg0}|Es], D0) -> unforce_tree(Es, D); unforce_tree([#icall{}=Call], D) -> unforce_tree_subst(Call, D); -unforce_tree([Top], _) -> Top. +unforce_tree([#c_var{name=V}], D) -> + gb_trees:get(V, D). unforce_tree_subst(#icall{module=#c_literal{val=erlang}, name=#c_literal{val='=:='}, diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index 6553d10077..400565100f 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -11,6 +11,8 @@ MODULES= \ beam_validator_SUITE \ beam_disasm_SUITE \ beam_except_SUITE \ + beam_reorder_SUITE \ + beam_type_SUITE \ beam_utils_SUITE \ bs_bincomp_SUITE \ bs_bit_binaries_SUITE \ @@ -43,6 +45,8 @@ NO_OPT= \ andor \ apply \ beam_except \ + beam_reorder \ + beam_type \ beam_utils \ bs_construct \ bs_match \ diff --git a/lib/compiler/test/beam_reorder_SUITE.erl b/lib/compiler/test/beam_reorder_SUITE.erl new file mode 100644 index 0000000000..4b2262f65b --- /dev/null +++ b/lib/compiler/test/beam_reorder_SUITE.erl @@ -0,0 +1,69 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(beam_reorder_SUITE). + +-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, + init_per_group/2,end_per_group/2, + alloc/1]). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + test_lib:recompile(?MODULE), + [{group,p}]. + +groups() -> + [{p,[parallel], + [alloc + ]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +-record(alloc, {version}). + +alloc(_Config) -> + {ok,42} = alloc_a(1, 2, #alloc{version=42}), + {a,b,c} = alloc_b(1, 2, #alloc{version={a,b,c}}), + ok. + +alloc_a(_U1, _U2, R) -> + V = R#alloc.version, + Res = id({ok,V}), + _ = id(0), + Res. + +alloc_b(_U1, _U2, R) -> + V = R#alloc.version, + Res = id(V), + _ = id(0), + Res. + +id(I) -> + I. diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl new file mode 100644 index 0000000000..8d5c0190ed --- /dev/null +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -0,0 +1,98 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(beam_type_SUITE). + +-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, + init_per_group/2,end_per_group/2, + integers/1,coverage/1,booleans/1]). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + test_lib:recompile(?MODULE), + [{group,p}]. + +groups() -> + [{p,[parallel], + [integers, + coverage, + booleans + ]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +integers(_Config) -> + a = do_integers_1(2#11000), + b = do_integers_1(2#11001), + + a = do_integers_2(<<0:1>>), + {'EXIT',{{case_clause,-1},_}} = (catch do_integers_2(<<1:1>>)), + + ok. + +do_integers_1(B0) -> + B = B0 band 1, + case B band 15 of + 0 -> a; + 1 -> b + end. + +do_integers_2(Bin) -> + <<B:1/signed>> = Bin, + case B of + 0 -> a; + 1 -> b + end. + +coverage(_Config) -> + {'EXIT',{badarith,_}} = (catch id(1) bsl 0.5), + {'EXIT',{badarith,_}} = (catch id(2.0) bsl 2), + {'EXIT',{badarith,_}} = (catch a + 0.5), + {'EXIT',{badarith,_}} = (catch 2.0 * b), + + {'EXIT',{badarith,_}} = (catch id(42.0) / (1 bsl 2000)), + + id(id(42) band 387439739874298734983787934283479243879), + id(-1 band id(13)), + + ok. + +booleans(_Config) -> + {'EXIT',{{case_clause,_},_}} = (catch do_booleans(42)), + ok. + +do_booleans(B) -> + case is_integer(B) of + yes -> yes; + no -> no + end. + +id(I) -> + I. diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index 69391b15eb..d6deb4a730 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -107,13 +107,13 @@ xrange(Config) when is_list(Config) -> {{bif,'+',{f,0},[{x,-1},{x,1}],{x,0}},4, {uninitialized_reg,{x,-1}}}}, {{t,sum_2,2}, - {{bif,'+',{f,0},[{x,0},{x,1024}],{x,0}},4, - {uninitialized_reg,{x,1024}}}}, + {{bif,'+',{f,0},[{x,0},{x,1023}],{x,0}},4, + {uninitialized_reg,{x,1023}}}}, {{t,sum_3,2}, {{bif,'+',{f,0},[{x,0},{x,1}],{x,-1}},4, {invalid_store,{x,-1},number}}}, {{t,sum_4,2}, - {{bif,'+',{f,0},[{x,0},{x,1}],{x,1024}},4,limit}}] = Errors, + {{bif,'+',{f,0},[{x,0},{x,1}],{x,1023}},4,limit}}] = Errors, ok. yrange(Config) when is_list(Config) -> diff --git a/lib/compiler/test/beam_validator_SUITE_data/xrange.S b/lib/compiler/test/beam_validator_SUITE_data/xrange.S index c6f20288f7..a76408dde3 100644 --- a/lib/compiler/test/beam_validator_SUITE_data/xrange.S +++ b/lib/compiler/test/beam_validator_SUITE_data/xrange.S @@ -20,7 +20,7 @@ {label,3}. {func_info,{atom,t},{atom,sum_2},2}. {label,4}. - {bif,'+',{f,0},[{x,0},{x,1024}],{x,0}}. + {bif,'+',{f,0},[{x,0},{x,1023}],{x,0}}. {'%live',1}. return. @@ -38,7 +38,7 @@ {label,7}. {func_info,{atom,t},{atom,sum_4},2}. {label,8}. - {bif,'+',{f,0},[{x,0},{x,1}],{x,1024}}. + {bif,'+',{f,0},[{x,0},{x,1}],{x,1023}}. {'%live',1}. return. diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index 6e138b0a43..a19b152bc5 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -36,7 +36,7 @@ match_string/1,zero_width/1,bad_size/1,haystack/1, cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1, no_partition/1,calling_a_binary/1,binary_in_map/1, - match_string_opt/1]). + match_string_opt/1,select_on_integer/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -62,7 +62,7 @@ groups() -> otp_7498,match_string,zero_width,bad_size,haystack, cover_beam_bool,matched_out_size,follow_fail_branch, no_partition,calling_a_binary,binary_in_map, - match_string_opt]}]. + match_string_opt,select_on_integer]}]. init_per_suite(Config) -> @@ -1225,6 +1225,20 @@ match_string_opt(Config) when is_list(Config) -> do_match_string_opt({<<1>>,{v,V}}=T) -> {x,V,T}. +select_on_integer(Config) when is_list(Config) -> + 42 = do_select_on_integer(<<42>>), + <<"abc">> = do_select_on_integer(<<128,"abc">>), + + {'EXIT',_} = (catch do_select_on_integer(<<0:1>>)), + {'EXIT',_} = (catch do_select_on_integer(<<1:1>>)), + {'EXIT',_} = (catch do_select_on_integer(<<0:1,0:15>>)), + ok. + +%% The ASN.1 compiler frequently generates code like this. +do_select_on_integer(<<0:1,I:7>>) -> + I; +do_select_on_integer(<<1:1,_:7,Bin/binary>>) -> + Bin. check(F, R) -> R = F(). diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index df401ccc2b..806cb58bab 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -31,7 +31,9 @@ other_output/1, encrypted_abstr/1, bad_record_use1/1, bad_record_use2/1, strict_record/1, missing_testheap/1, cover/1, env/1, core/1, asm/1, - sys_pre_attributes/1, dialyzer/1]). + sys_pre_attributes/1, dialyzer/1, + warnings/1 + ]). -export([init/3]). @@ -48,7 +50,7 @@ all() -> other_output, encrypted_abstr, {group, bad_record_use}, strict_record, missing_testheap, cover, env, core, asm, - sys_pre_attributes, dialyzer]. + sys_pre_attributes, dialyzer, warnings]. groups() -> [{bad_record_use, [], @@ -328,6 +330,8 @@ do_file_listings(DataDir, PrivDir, [File|Files]) -> do_listing(Simple, TargetDir, dlife, ".life"), do_listing(Simple, TargetDir, dcg, ".codegen"), do_listing(Simple, TargetDir, dblk, ".block"), + do_listing(Simple, TargetDir, dexcept, ".except"), + do_listing(Simple, TargetDir, dbs, ".bs"), do_listing(Simple, TargetDir, dbool, ".bool"), do_listing(Simple, TargetDir, dtype, ".type"), do_listing(Simple, TargetDir, ddead, ".dead"), @@ -895,6 +899,44 @@ dialyzer(Config) -> [{a,b,c}] = M:M(), ok. + +%% Test that warnings contain filenames and line numbers. +warnings(_Config) -> + TestDir = filename:dirname(code:which(?MODULE)), + Files = filelib:wildcard(filename:join(TestDir, "*.erl")), + test_lib:p_run(fun do_warnings/1, Files). + +do_warnings(F) -> + {ok,_,_,Ws} = compile:file(F, [binary,bin_opt_info,return]), + do_warnings_1(Ws, F). + +do_warnings_1([{"no_file",Ws}|_], F) -> + io:format("~s:\nMissing file for warnings: ~p\n", + [F,Ws]), + error; +do_warnings_1([{Name,Ws}|T], F) -> + case filename:extension(Name) of + ".erl" -> + do_warnings_2(Ws, T, F); + _ -> + io:format("~s:\nNo .erl extension\n", [F]), + error + end; +do_warnings_1([], _) -> ok. + +do_warnings_2([{Int,_,_}=W|T], Next, F) -> + if + is_integer(Int) -> + do_warnings_2(T, Next, F); + true -> + io:format("~s:\nMissing line number: ~p\n", + [F,W]), + error + end; +do_warnings_2([], Next, F) -> + do_warnings_1(Next, F). + + %%% %%% Utilities. %%% diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index 8606935504..b88abaf62d 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -192,6 +192,14 @@ silly_coverage(Config) when is_list(Config) -> {label,2}|non_proper_list]}],99}, expect_error(fun() -> beam_a:module(BeamAInput, []) end), + %% beam_reorder + BlockInput = {?MODULE,[{foo,0}],[], + [{function,foo,0,2, + [{label,1}, + {func_info,{atom,?MODULE},{atom,foo},0}, + {label,2}|non_proper_list]}],99}, + expect_error(fun() -> beam_reorder:module(BlockInput, []) end), + %% beam_block BlockInput = {?MODULE,[{foo,0}],[], [{function,foo,0,2, @@ -200,6 +208,10 @@ silly_coverage(Config) when is_list(Config) -> {label,2}|non_proper_list]}],99}, ?line expect_error(fun() -> beam_block:module(BlockInput, []) end), + %% beam_bs + BsInput = BlockInput, + expect_error(fun() -> beam_bs:module(BsInput, []) end), + %% beam_type TypeInput = {?MODULE,[{foo,0}],[], [{function,foo,0,2, diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 69f71ba5dd..357b35e47b 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 6.0 +COMPILER_VSN = 6.0.1 diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 24db75bf91..fbf108c410 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -24,11 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # Macros # -ifneq ($(findstring ose,$(TARGET)),ose) SUB_DIRECTORIES = src c_src doc/src -else -SUB_DIRECTORIES = src doc/src -endif static_lib: SUB_DIRECTORIES = c_src include vsn.mk diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in index e66c0ca916..e7f750b60a 100644 --- a/lib/crypto/c_src/Makefile.in +++ b/lib/crypto/c_src/Makefile.in @@ -127,12 +127,7 @@ ALL_STATIC_CFLAGS = $(DED_STATIC_CFLAGS) $(INCLUDES) _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) -ifneq ($(findstring ose,$(TARGET)),ose) debug opt valgrind: $(NIF_LIB) $(CALLBACK_LIB) -else -# Do not build dynamic files on OSE -debug opt valgrind: -endif static_lib: $(NIF_ARCHIVE) @@ -203,14 +198,12 @@ release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj" $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" $(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj" -ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(CRYPTO_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib" ifeq ($(DYNAMIC_CRYPTO_LIB),yes) $(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib" endif -endif release_docs_spec: diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 9de8dc74c2..e9cac30c9c 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -507,47 +507,6 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*); #define PRINTF_ERR1(FMT,A1) #define PRINTF_ERR2(FMT,A1,A2) -#ifdef __OSE__ - -/* For crypto on OSE we have to initialize the crypto library on each - process that uses it. So since we do not know which scheduler is going - to execute the nif we have to check before each nif call that we have - initialized crypto in that process. */ - -#include "ose.h" -#include "openssl/osessl.h" - -static ErlNifTSDKey crypto_init_key; -static int check_ose_crypto(void); -static int init_ose_crypto(void); - -static int check_ose_crypto() { - int key = (int)enif_tsd_get(crypto_init_key); - if (!key) { - if (!CRYPTO_OSE5_init()) { - PRINTF_ERR0("CRYPTO: Call to CRYPTO_OSE5_init failed"); - return 0; - } - enif_tsd_set(crypto_init_key,1); - } - return 1; -} - -static int init_ose_crypto() { - /* Crypto nif upgrade does not work on OSE so no need to - destroy this key */ - enif_tsd_key_create("crypto_init_key", &crypto_init_key); - return check_ose_crypto(); -} - -#define INIT_OSE_CRYPTO() init_ose_crypto() -#define CHECK_OSE_CRYPTO() check_ose_crypto() -#else -#define INIT_OSE_CRYPTO() 1 -#define CHECK_OSE_CRYPTO() -#endif - - static int verify_lib_version(void) { const unsigned long libv = SSLeay(); @@ -609,9 +568,6 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) ErlNifBinary lib_bin; char lib_buf[1000]; - if (!INIT_OSE_CRYPTO()) - return 0; - if (!verify_lib_version()) return 0; @@ -853,7 +809,6 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -865,7 +820,6 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); MD5_Init((MD5_CTX *) enif_make_new_binary(env, MD5_CTX_LEN, &ret)); return ret; } @@ -874,7 +828,6 @@ static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv MD5_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { @@ -891,7 +844,6 @@ static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary ctx_bin; MD5_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN) { return enif_make_badarg(env); } @@ -904,7 +856,6 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -916,7 +867,6 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret)); return ret; } @@ -925,7 +875,6 @@ static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TER RIPEMD160_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { @@ -942,7 +891,6 @@ static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary ctx_bin; RIPEMD160_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) { return enif_make_badarg(env); } @@ -956,7 +904,6 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -968,7 +915,6 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); SHA1_Init((SHA_CTX *) enif_make_new_binary(env, SHA_CTX_LEN, &ret)); return ret; } @@ -977,7 +923,6 @@ static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv SHA_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -993,7 +938,6 @@ static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary ctx_bin; SHA_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN) { return enif_make_badarg(env); } @@ -1007,7 +951,6 @@ static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA224 ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1023,7 +966,6 @@ static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM {/* () */ #ifdef HAVE_SHA224 ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret)); return ret; #else @@ -1036,7 +978,6 @@ static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA256_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1056,7 +997,6 @@ static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA256_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) { return enif_make_badarg(env); } @@ -1073,7 +1013,6 @@ static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA256 ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1089,7 +1028,6 @@ static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM {/* () */ #ifdef HAVE_SHA256 ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret)); return ret; #else @@ -1102,7 +1040,6 @@ static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA256_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1122,7 +1059,6 @@ static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA256_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) { return enif_make_badarg(env); } @@ -1139,7 +1075,6 @@ static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA384 ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1155,7 +1090,6 @@ static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM {/* () */ #ifdef HAVE_SHA384 ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret)); return ret; #else @@ -1168,7 +1102,6 @@ static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA512_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1188,7 +1121,6 @@ static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA512_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) { return enif_make_badarg(env); } @@ -1205,7 +1137,6 @@ static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA512 ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1233,7 +1164,6 @@ static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA512_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1253,7 +1183,6 @@ static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA512_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) { return enif_make_badarg(env); } @@ -1270,7 +1199,6 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1282,7 +1210,6 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); MD4_Init((MD4_CTX *) enif_make_new_binary(env, MD4_CTX_LEN, &ret)); return ret; } @@ -1291,7 +1218,6 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv MD4_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1307,7 +1233,6 @@ static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary ctx_bin; MD4_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN) { return enif_make_badarg(env); } @@ -1322,7 +1247,6 @@ static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > MD5_LEN) { @@ -1340,7 +1264,6 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA_LEN) { @@ -1360,7 +1283,6 @@ static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) { @@ -1383,7 +1305,6 @@ static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) { @@ -1406,7 +1327,6 @@ static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) { @@ -1430,7 +1350,6 @@ static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) { @@ -1462,7 +1381,6 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ const EVP_MD *md; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (argv[0] == atom_sha) md = EVP_sha1(); #ifdef HAVE_SHA224 @@ -1502,7 +1420,6 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg ErlNifBinary data; struct hmac_context* obj; - CHECK_OSE_CRYPTO(); if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj) || !enif_inspect_iolist_as_binary(env, argv[1], &data)) { @@ -1529,7 +1446,6 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv unsigned int req_len = 0; unsigned int mac_len; - CHECK_OSE_CRYPTO(); if (!enif_get_resource(env,argv[0],hmac_context_rtype, (void**)&obj) || (argc == 2 && !enif_get_uint(env, argv[1], &req_len))) { @@ -1564,7 +1480,6 @@ static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8 @@ -1587,7 +1502,6 @@ static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8 @@ -1607,7 +1521,6 @@ static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ErlNifBinary key, text; DES_key_schedule schedule; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || !enif_inspect_iolist_as_binary(env, argv[1], &text) || text.size != 8) { return enif_make_badarg(env); @@ -1627,7 +1540,6 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8 || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8 @@ -1657,7 +1569,6 @@ static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_N DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8 || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8 @@ -1714,7 +1625,6 @@ static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE int new_ivlen = 0; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !(key.size == 16 || key.size == 24 || key.size == 32) @@ -1744,7 +1654,6 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned int num = 0; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 @@ -1777,7 +1686,6 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N unsigned char * ivec2_buf; unsigned char * ecount2_buf; - CHECK_OSE_CRYPTO(); if (!enif_get_tuple(env, argv[0], &state_arity, &state_term) || state_arity != 4 @@ -1816,7 +1724,6 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char *outp; ERL_NIF_TERM out, out_tag; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 @@ -1866,7 +1773,6 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char *outp; ERL_NIF_TERM out; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 @@ -1937,7 +1843,6 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER unsigned char poly1305_key[32]; poly1305_state poly1305; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32 || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN @@ -1991,7 +1896,6 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER unsigned char mac[POLY1305_TAG_LEN]; poly1305_state poly1305; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32 || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN @@ -2045,7 +1949,6 @@ static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a unsigned char* ret_ptr; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 16 && key_bin.size != 32) @@ -2074,7 +1977,6 @@ static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned bytes; unsigned char* data; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bytes)) { return enif_make_badarg(env); } @@ -2088,7 +1990,6 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI unsigned bytes; unsigned char* data; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bytes)) { return enif_make_badarg(env); } @@ -2106,7 +2007,6 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned char* data; unsigned top_mask, bot_mask; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bytes) || !enif_get_uint(env, argv[1], &top_mask) || !enif_get_uint(env, argv[2], &bot_mask)) { @@ -2130,7 +2030,6 @@ static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NI unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bits) || !enif_get_int(env, argv[1], &top) @@ -2200,7 +2099,6 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_mpint(env, argv[0], &bn_from) || !get_bn_from_mpint(env, argv[1], &bn_rand)) { @@ -2233,7 +2131,6 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg unsigned extra_byte; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_bin(env, argv[0], &bn_base) || !get_bn_from_bin(env, argv[1], &bn_exponent) @@ -2277,7 +2174,6 @@ static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM DSA *dsa; int i; - CHECK_OSE_CRYPTO(); if (argv[0] == atom_sha) { if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { @@ -2446,7 +2342,6 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM struct digest_type_t* digp = NULL; unsigned char* digest = NULL; - CHECK_OSE_CRYPTO(); digp = get_digest_type(type); if (!digp) { @@ -2508,7 +2403,6 @@ static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a unsigned char* ret_ptr; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 16 && key_bin.size != 32) @@ -2569,7 +2463,6 @@ static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE unsigned char* ret_ptr; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 16 && key_bin.size != 32) @@ -2607,7 +2500,6 @@ static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) int i; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env,argv[0], &d1) || !enif_inspect_iolist_as_binary(env,argv[1], &d2) @@ -2629,7 +2521,6 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg RC4_KEY rc4_key; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env,argv[0], &key) || !enif_inspect_iolist_as_binary(env,argv[1], &data)) { @@ -2647,7 +2538,6 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg ErlNifBinary key; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env,argv[0], &key)) { return enif_make_badarg(env); @@ -2664,7 +2554,6 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N RC4_KEY* rc4_key; ERL_NIF_TERM new_state, new_data; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env,argv[0], &state) || state.size != sizeof(RC4_KEY) @@ -2686,7 +2575,6 @@ static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ERL_NIF_TERM ret; unsigned char iv_copy[8]; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16) @@ -2748,7 +2636,6 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar struct digest_type_t *digp; unsigned char* digest; - CHECK_OSE_CRYPTO(); digp = get_digest_type(argv[0]); if (!digp) { @@ -2816,7 +2703,6 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar DSA* dsa; int i; - CHECK_OSE_CRYPTO(); if (argv[0] == atom_sha) { if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { @@ -2903,7 +2789,6 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER int padding, i; RSA* rsa; - CHECK_OSE_CRYPTO(); rsa = RSA_new(); @@ -2953,7 +2838,6 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE int padding, i; RSA* rsa; - CHECK_OSE_CRYPTO(); rsa = RSA_new(); @@ -3001,7 +2885,6 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E unsigned char *p_ptr, *g_ptr; ERL_NIF_TERM ret_p, ret_g; - CHECK_OSE_CRYPTO(); if (!enif_get_int(env, argv[0], &prime_len) || !enif_get_int(env, argv[1], &generator)) { @@ -3030,7 +2913,6 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] int i; ERL_NIF_TERM ret, head, tail; - CHECK_OSE_CRYPTO(); dh_params = DH_new(); @@ -3066,7 +2948,6 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail; int mpint; /* 0 or 4 */ - CHECK_OSE_CRYPTO(); dh_params = DH_new(); @@ -3112,7 +2993,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T ErlNifBinary ret_bin; ERL_NIF_TERM ret, head, tail; - CHECK_OSE_CRYPTO(); dh_params = DH_new(); @@ -3154,7 +3034,6 @@ static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_bin(env, argv[0], &bn_multiplier) || !get_bn_from_bin(env, argv[1], &bn_verifier) @@ -3216,7 +3095,6 @@ static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_bin(env, argv[0], &bn_a) || !get_bn_from_bin(env, argv[1], &bn_u) @@ -3297,7 +3175,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_bin(env, argv[0], &bn_verifier) || !get_bn_from_bin(env, argv[1], &bn_b) @@ -3359,7 +3236,6 @@ static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM int bf_n = 0; /* blowfish ivec pos */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_binary(env, argv[1], &ivec_bin) @@ -3384,7 +3260,6 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned char bf_tkey[8]; /* blowfish ivec */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_binary(env, argv[1], &ivec_bin) @@ -3409,7 +3284,6 @@ static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar BF_KEY bf_key; /* blowfish key 8 */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin) @@ -3431,7 +3305,6 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N int bf_n = 0; /* blowfish ivec pos */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_binary(env, argv[1], &ivec_bin) @@ -3756,7 +3629,6 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM ERL_NIF_TERM priv_key; ERL_NIF_TERM pub_key = atom_undefined; - CHECK_OSE_CRYPTO(); if (!get_ec_key(env, argv[0], argv[1], atom_undefined, &key)) goto badarg; @@ -3799,7 +3671,6 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM struct digest_type_t *digp; unsigned char* digest; - CHECK_OSE_CRYPTO(); digp = get_digest_type(argv[0]); if (!digp) { @@ -3868,7 +3739,6 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER struct digest_type_t* digp = NULL; unsigned char* digest = NULL; - CHECK_OSE_CRYPTO(); digp = get_digest_type(type); if (!digp) { @@ -3933,7 +3803,6 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF EC_POINT *my_ecpoint; EC_KEY *other_ecdh = NULL; - CHECK_OSE_CRYPTO(); if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) return enif_make_badarg(env); @@ -3978,7 +3847,6 @@ out_err: static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary seed_bin; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &seed_bin)) return enif_make_badarg(env); RAND_seed(seed_bin.data,seed_bin.size); diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 385a583883..291a5145e4 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -617,7 +617,7 @@ RAND_seed function from openssl. Only use this if the system you are running on does not have enough "randomness" built in. Normally this is when <seealso marker="#strong_rand_bytes/1"> - stong_rand_bytes/1</seealso> returns <c>low_entropy</c></p> + strong_rand_bytes/1</seealso> returns <c>low_entropy</c></p> </desc> </func> @@ -710,7 +710,7 @@ </type> <desc> <p>Initializes the state for use in streaming AES encryption using Counter mode (CTR). - <c>Key</c> is the AES key and must be either 128, 192, or 256 bts long. <c>IVec</c> is + <c>Key</c> is the AES key and must be either 128, 192, or 256 bits long. <c>IVec</c> is an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and <seealso marker="#stream_decrypt-2">stream_decrypt</seealso>.</p> diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index e2b90eca75..54dd8872eb 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -31,6 +31,22 @@ </header> <p>This document describes the changes made to the Crypto application.</p> +<section><title>Crypto 3.6.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Make <c>crypto:ec_curves/0</c> return empty list if + elliptic curve is not supported at all.</p> + <p> + Own Id: OTP-12944</p> + </item> + </list> + </section> + +</section> + <section><title>Crypto 3.6</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index e84f5e1075..0b955c0965 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -118,10 +118,10 @@ init_per_suite(Config) -> _ -> Config catch error:low_entropy -> - %% Make sure we are on OSE, otherwise we want to crash - {ose,_} = os:type(), + %% We are testing on an OS with low entropy in its random + %% seed. So we have to seed it with a binary to get started. - %% This is NOT how you want to seed this, it is just here + %% This is NOT how you want to do seeding, it is just here %% to make the tests pass. Check your OS manual for how you %% really want to seed. {H,M,L} = erlang:now(), diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index 55b1b3e8c4..c2166a8e75 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 3.6 +CRYPTO_VSN = 3.6.1 diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml index 67cfe20d83..3eaecf86b2 100644 --- a/lib/debugger/doc/src/notes.xml +++ b/lib/debugger/doc/src/notes.xml @@ -33,6 +33,22 @@ <p>This document describes the changes made to the Debugger application.</p> +<section><title>Debugger 4.1.1</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix crash when starting a quick debugging session. Thanks + Alan Duffield.</p> + <p> + Own Id: OTP-12911 Aux Id: seq12906 </p> + </item> + </list> + </section> + +</section> + + <section><title>Debugger 4.1</title> <section><title>Improvements and New Features</title> diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl index 2a8bcd32d8..7746a06fcb 100644 --- a/lib/debugger/src/dbg_iload.erl +++ b/lib/debugger/src/dbg_iload.erl @@ -541,7 +541,7 @@ fun_clauses([]) -> []. new_map(Fs0, Anno, F) -> Line = ln(Anno), Fs1 = map_fields(Fs0, F), - Fs2 = [{ln(A),K,V} || {map_field_assoc,A,K,V} <- Fs1], + Fs2 = [{L,K,V} || {map_field_assoc,L,K,V} <- Fs1], try {value,Line,map_literal(Fs2, #{})} catch diff --git a/lib/debugger/src/dbg_wx_win.erl b/lib/debugger/src/dbg_wx_win.erl index 63f74392b5..1ff8818bbe 100644 --- a/lib/debugger/src/dbg_wx_win.erl +++ b/lib/debugger/src/dbg_wx_win.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -95,10 +95,9 @@ create_menu_item(Menu, [{Name, _N, cascade, Items}|Is], Win, Id0,Connect) -> false -> Acc end end, - Filter = fun(_,_) -> + Filter = fun(Ev,_) -> Enabled = lists:foldl(IsChecked, [], Butts), - Self ! #wx{userData={Name, Enabled}, - event=#wxCommand{type=command_menu_selected}} + Self ! Ev#wx{userData={Name, Enabled}} end, wxMenu:connect(Win, command_menu_selected, [{id,Id0},{lastId, Id-1},{callback,Filter}]), diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk index b6fd4e8e44..e47ed98128 100644 --- a/lib/debugger/vsn.mk +++ b/lib/debugger/vsn.mk @@ -1 +1 @@ -DEBUGGER_VSN = 4.1 +DEBUGGER_VSN = 4.1.1 diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index 93d3b09f07..aa29684697 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -32,6 +32,48 @@ <p>This document describes the changes made to the Dialyzer application.</p> +<section><title>Dialyzer 2.8.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Improve the translation of forms to types. </p> + <p> + Own Id: OTP-12865</p> + </item> + <item> + <p> Fix a bug concerning parameterized opaque types. </p> + <p> + Own Id: OTP-12866</p> + </item> + <item> + <p> Fix a bug concerning parameterized opaque types. </p> + <p> + Own Id: OTP-12940</p> + </item> + <item> + <p> Fix bugs concerning <c>erlang:abs/1</c>. </p> + <p> + Own Id: OTP-12948</p> + </item> + <item> + <p> Fix a bug concerning <c>lists:keydelete/3</c> with + union and opaque types. </p> + <p> + Own Id: OTP-12949</p> + </item> + <item> + <p> + Use new function <c>hipe:erts_checksum</c> to get correct + runtime checksum for cached beam files.</p> + <p> + Own Id: OTP-12964 Aux Id: OTP-12963, OTP-12962 </p> + </item> + </list> + </section> + +</section> + <section><title>Dialyzer 2.8</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -405,22 +447,28 @@ <p> EEP43: New data type - Maps</p> <p> - With Maps you may for instance: <taglist> <item><c>M0 = - #{ a => 1, b => 2}, % create - associations</c></item> <item><c>M1 = M0#{ a := 10 }, % - update values</c></item> <item><c>M2 = M1#{ "hi" => - "hello"}, % add new associations</c></item> <item><c>#{ - "hi" := V1, a := V2, b := V3} = M2. % match keys with - values</c></item> </taglist></p> + With Maps you may for instance:</p> + <taglist> + <tag/> <item><c>M0 = #{ a => 1, b => 2}, % create + associations</c></item> + <tag/><item><c>M1 = M0#{ a := 10 }, % update values</c></item> + <tag/><item><c>M2 = M1#{ "hi" => + "hello"}, % add new associations</c></item> + <tag/><item><c>#{ "hi" := V1, a := V2, b := V3} = M2. + % match keys with values</c></item> + </taglist> <p> For information on how to use Maps please see Map Expressions in the <seealso marker="doc/reference_manual:expressions#map_expressions"> Reference Manual</seealso>.</p> <p> The current implementation is without the following - features: <taglist> <item>No variable keys</item> - <item>No single value access</item> <item>No map - comprehensions</item> </taglist></p> + features:</p> + <taglist> + <tag/><item>No variable keys</item> + <tag/><item>No single value access</item> + <tag/><item>No map comprehensions</item> + </taglist> <p> Note that Maps is <em>experimental</em> during OTP 17.0.</p> <p> @@ -734,19 +782,17 @@ Own Id: OTP-9731</p> </item> <item> - <p> <list> <item><p>No warnings for underspecs with remote types</p></item> <item><p> Fix crash in Typer</p></item> <item><p>Fix Dialyzer's warning for its own code</p></item> <item><p>Fix Dialyzer's warnings in HiPE</p></item> <item><p>Add file/line info in a particular Dialyzer crash</p></item> <item><p>Update - inets test results</p></item> </list></p> + inets test results</p></item> </list> <p> Own Id: OTP-9758</p> </item> <item> - <p> <list> <item><p>Correct callback spec in application module</p></item> <item><p>Refine warning about callback specs with extra ranges</p></item> <item><p>Cleanup @@ -757,7 +803,7 @@ analysis</p></item> <item><p>Fix crash in Dialyzer</p></item> <item><p>Variable substitution was not generalizing any unknown variables.</p></item> - </list></p> + </list> <p> Own Id: OTP-9776</p> </item> diff --git a/lib/dialyzer/src/dialyzer.app.src b/lib/dialyzer/src/dialyzer.app.src index 8ac6dc1367..7794cb46c6 100644 --- a/lib/dialyzer/src/dialyzer.app.src +++ b/lib/dialyzer/src/dialyzer.app.src @@ -44,7 +44,7 @@ dialyzer_timing, dialyzer_worker]}, {registered, []}, - {applications, [compiler, gs, hipe, kernel, stdlib, wx]}, + {applications, [compiler, hipe, kernel, stdlib, wx]}, {env, []}, {runtime_dependencies, ["wx-1.2","syntax_tools-1.6.14","stdlib-2.5", "kernel-3.0","hipe-3.13","erts-7.0", diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl index de236f91ab..601e2e954b 100644 --- a/lib/dialyzer/src/dialyzer.hrl +++ b/lib/dialyzer/src/dialyzer.hrl @@ -2,7 +2,7 @@ %%% %%% %CopyrightBegin% %%% -%%% Copyright Ericsson AB 2006-2014. All Rights Reserved. +%%% Copyright Ericsson AB 2006-2015. All Rights Reserved. %%% %%% Licensed under the Apache License, Version 2.0 (the "License"); %%% you may not use this file except in compliance with the License. @@ -123,10 +123,12 @@ %% Record declarations used by various files %%-------------------------------------------------------------------- --record(analysis, {analysis_pid :: pid(), +-type doc_plt() :: 'undefined' | dialyzer_plt:plt(). + +-record(analysis, {analysis_pid :: pid() | 'undefined', type = succ_typings :: anal_type(), defines = [] :: [dial_define()], - doc_plt :: dialyzer_plt:plt(), + doc_plt :: doc_plt(), files = [] :: [file:filename()], include_dirs = [] :: [file:filename()], start_from = byte_code :: start_from(), @@ -135,7 +137,7 @@ race_detection = false :: boolean(), behaviours_chk = false :: boolean(), timing = false :: boolean() | 'debug', - timing_server :: dialyzer_timing:timing_server(), + timing_server = none :: dialyzer_timing:timing_server(), callgraph_file = "" :: file:filename(), solvers :: [solver()]}). diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl index a1cd2015ca..069c02fa65 100644 --- a/lib/dialyzer/src/dialyzer_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_callgraph.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2014. All Rights Reserved. +%% Copyright Ericsson AB 2006-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -96,15 +96,22 @@ %% whenever applicable. %%----------------------------------------------------------------------------- +%% Types with comment 'race' are due to dialyzer_races.erl. -record(callgraph, {digraph = digraph:new() :: digraph:graph(), - active_digraph :: active_digraph(), - esc :: ets:tid(), - letrec_map :: ets:tid(), + active_digraph :: active_digraph() + | 'undefined', % race + esc :: ets:tid() + | 'undefined', % race + letrec_map :: ets:tid() + | 'undefined', % race name_map :: ets:tid(), rev_name_map :: ets:tid(), - rec_var_map :: ets:tid(), - self_rec :: ets:tid(), - calls :: ets:tid(), + rec_var_map :: ets:tid() + | 'undefined', % race + self_rec :: ets:tid() + | 'undefined', % race + calls :: ets:tid() + | 'undefined', % race race_detection = false :: boolean(), race_data_server = new_race_data_server() :: pid()}). diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index 4116866916..92134b7b81 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -36,7 +36,7 @@ -include_lib("kernel/include/file.hrl"). % needed for #file_info{} -record(cl_state, - {backend_pid :: pid(), + {backend_pid :: pid() | 'undefined', erlang_mode = false :: boolean(), external_calls = [] :: [mfa()], external_types = [] :: [mfa()], diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl index 978ecd3843..03cd9671af 100644 --- a/lib/dialyzer/src/dialyzer_codeserver.erl +++ b/lib/dialyzer/src/dialyzer_codeserver.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2014. All Rights Reserved. +%% Copyright Ericsson AB 2006-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -81,10 +81,10 @@ -record(codeserver, {next_core_label = 0 :: label(), code :: dict_ets(), - exported_types :: set_ets(), % set(mfa()) - records :: dict_ets(), - contracts :: dict_ets(), - callbacks :: dict_ets(), + exported_types :: set_ets() | 'undefined', % set(mfa()) + records :: dict_ets() | 'undefined', + contracts :: dict_ets() | 'undefined', + callbacks :: dict_ets() | 'undefined', fun_meta_info :: dict_ets(), % {mfa(), meta_info()} exports :: 'clean' | set_ets(), % set(mfa()) temp_exported_types :: 'clean' | set_ets(), % set(mfa()) diff --git a/lib/dialyzer/src/dialyzer_coordinator.erl b/lib/dialyzer/src/dialyzer_coordinator.erl index 612f379d32..3290161ca1 100644 --- a/lib/dialyzer/src/dialyzer_coordinator.erl +++ b/lib/dialyzer/src/dialyzer_coordinator.erl @@ -38,7 +38,7 @@ %%% Exports for the compilation workers -export([get_next_label/2]). --export_type([coordinator/0, mode/0, init_data/0, result/0]). +-export_type([coordinator/0, mode/0, init_data/0, result/0, job/0]). %%-------------------------------------------------------------------- @@ -52,10 +52,12 @@ -type scc() :: [mfa_or_funlbl()]. -type mode() :: 'typesig' | 'dataflow' | 'compile' | 'warnings'. --type compile_jobs() :: [file:filename()]. --type typesig_jobs() :: [scc()]. --type dataflow_jobs() :: [module()]. --type warnings_jobs() :: [module()]. +-type compile_job() :: file:filename(). +-type typesig_job() :: scc(). +-type dataflow_job() :: module(). +-type warnings_job() :: module(). + +-type job() :: compile_job() | typesig_job() | dataflow_job() | warnings_job(). -type compile_init_data() :: dialyzer_analysis_callgraph:compile_init_data(). -type typesig_init_data() :: dialyzer_succ_typings:typesig_init_data(). @@ -73,7 +75,6 @@ -type result() :: compile_result() | typesig_result() | dataflow_result() | warnings_result(). --type job() :: scc() | module() | file:filename(). -type job_result() :: dialyzer_analysis_callgraph:one_file_result() | typesig_result() | dataflow_result() | warnings_result(). @@ -90,13 +91,13 @@ %%-------------------------------------------------------------------- --spec parallel_job('compile', compile_jobs(), compile_init_data(), timing()) -> +-spec parallel_job('compile', [compile_job()], compile_init_data(), timing()) -> {compile_result(), integer()}; - ('typesig', typesig_jobs(), typesig_init_data(), timing()) -> + ('typesig', [typesig_job()], typesig_init_data(), timing()) -> typesig_result(); - ('dataflow', dataflow_jobs(), dataflow_init_data(), + ('dataflow', [dataflow_job()], dataflow_init_data(), timing()) -> dataflow_result(); - ('warnings', warnings_jobs(), warnings_init_data(), + ('warnings', [warnings_job()], warnings_init_data(), timing()) -> warnings_result(). parallel_job(Mode, Jobs, InitData, Timing) -> diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index cabc5e9e0d..6e49043551 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -99,19 +99,29 @@ -define(BITS, 128). --record(state, {callgraph :: dialyzer_callgraph:callgraph(), - codeserver :: dialyzer_codeserver:codeserver(), - envs :: env_tab(), - fun_tab :: fun_tab(), - fun_homes :: dict:dict(label(), mfa()), - plt :: dialyzer_plt:plt(), - opaques :: [type()], +%% Types with comment 'race' are due to dialyzer_races.erl. +-record(state, {callgraph :: dialyzer_callgraph:callgraph() + | 'undefined', % race + codeserver :: dialyzer_codeserver:codeserver() + | 'undefined', % race + envs :: env_tab() + | 'undefined', % race + fun_tab :: fun_tab() + | 'undefined', % race + fun_homes :: dict:dict(label(), mfa()) + | 'undefined', % race + plt :: dialyzer_plt:plt() + | 'undefined', % race + opaques :: [type()] + | 'undefined', % race races = dialyzer_races:new() :: dialyzer_races:races(), records = dict:new() :: types(), - tree_map :: dict:dict(label(), cerl:cerl()), + tree_map :: dict:dict(label(), cerl:cerl()) + | 'undefined', % race warning_mode = false :: boolean(), warnings = [] :: [raw_warning()], - work :: {[_], [_], sets:set()}, + work :: {[_], [_], sets:set()} + | 'undefined', % race module :: module(), curr_fun :: curr_fun() }). diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl index ff54a91ce1..9f344d87ff 100644 --- a/lib/dialyzer/src/dialyzer_gui_wx.erl +++ b/lib/dialyzer/src/dialyzer_gui_wx.erl @@ -2,7 +2,7 @@ %%------------------------------------------------------------------------ %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2013. All Rights Reserved. +%% Copyright Ericsson AB 2009-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -52,7 +52,6 @@ add_dir :: wx:wx_object(), add_rec :: wx:wx_object(), chosen_box :: wx:wx_object(), - analysis_pid :: pid(), del_file :: wx:wx_object(), doc_plt :: dialyzer_plt:plt(), clear_chosen :: wx:wx_object(), @@ -72,11 +71,11 @@ stop :: wx:wx_object(), frame :: wx:wx_object(), warnings_box :: wx:wx_object(), - explanation_box :: wx:wx_object(), + explanation_box :: wx:wx_object() | 'undefined', wantedWarnings :: list(), rawWarnings :: list(), - backend_pid :: pid(), - expl_pid :: pid()}). + backend_pid :: pid() | 'undefined', + expl_pid :: pid() | 'undefined'}). %%------------------------------------------------------------------------ diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl index 39de071bde..bb43d1dcb8 100644 --- a/lib/dialyzer/src/dialyzer_races.erl +++ b/lib/dialyzer/src/dialyzer_races.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2014. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -92,27 +92,28 @@ -type race_warn_tag() :: ?WARN_WHEREIS_REGISTER | ?WARN_WHEREIS_UNREGISTER | ?WARN_ETS_LOOKUP_INSERT | ?WARN_MNESIA_DIRTY_READ_WRITE. --record(beg_clause, {arg :: var_to_map1(), - pats :: var_to_map1(), - guard :: cerl:cerl()}). --record(end_clause, {arg :: var_to_map1(), - pats :: var_to_map1(), - guard :: cerl:cerl()}). +-record(beg_clause, {arg :: var_to_map1() | 'undefined', + pats :: var_to_map1() | 'undefined', + guard :: cerl:cerl() | 'undefined'}). +-record(end_clause, {arg :: var_to_map1() | 'undefined', + pats :: var_to_map1() | 'undefined', + guard :: cerl:cerl() | 'undefined'}). -record(end_case, {clauses :: [#end_clause{}]}). --record(curr_fun, {status :: 'in' | 'out', - mfa :: dialyzer_callgraph:mfa_or_funlbl(), - label :: label(), - def_vars :: [core_vars()], - arg_types :: [erl_types:erl_type()], - call_vars :: [core_vars()], - var_map :: dict:dict()}). +-record(curr_fun, {status :: 'in' | 'out' | 'undefined', + mfa :: dialyzer_callgraph:mfa_or_funlbl() + | 'undefined', + label :: label() | 'undefined', + def_vars :: [core_vars()] | 'undefined', + arg_types :: [erl_types:erl_type()] | 'undefined', + call_vars :: [core_vars()] | 'undefined', + var_map :: dict:dict() | 'undefined'}). -record(dep_call, {call_name :: dep_calls(), - args :: args(), + args :: args() | 'undefined', arg_types :: [erl_types:erl_type()], vars :: [core_vars()], state :: dialyzer_dataflow:state(), file_line :: file_line(), - var_map :: dict:dict()}). + var_map :: dict:dict() | 'undefined'}). -record(fun_call, {caller :: dialyzer_callgraph:mfa_or_funlbl(), callee :: dialyzer_callgraph:mfa_or_funlbl(), arg_types :: [erl_types:erl_type()], @@ -121,7 +122,7 @@ arg :: var_to_map1()}). -record(warn_call, {call_name :: warn_calls(), args :: args(), - var_map :: dict:dict()}). + var_map :: dict:dict() | 'undefined'}). -type case_tags() :: 'beg_case' | #beg_clause{} | #end_clause{} | #end_case{}. -type code() :: [#dep_call{} | #fun_call{} | #warn_call{} | @@ -139,8 +140,9 @@ fun_mfa :: dialyzer_callgraph:mfa_or_funlbl(), fun_label :: label()}). --record(races, {curr_fun :: dialyzer_callgraph:mfa_or_funlbl(), - curr_fun_label :: label(), +-record(races, {curr_fun :: dialyzer_callgraph:mfa_or_funlbl() + | 'undefined', + curr_fun_label :: label() | 'undefined', curr_fun_args = 'empty' :: core_args(), new_table = 'no_t' :: table(), race_list = [] :: code(), diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl index 18f02e6742..987da3aecf 100644 --- a/lib/dialyzer/src/dialyzer_succ_typings.erl +++ b/lib/dialyzer/src/dialyzer_succ_typings.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2014. All Rights Reserved. +%% Copyright Ericsson AB 2006-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -134,7 +134,6 @@ get_refined_success_typings(SCCs, #st{callgraph = Callgraph, end end. --type doc_plt() :: 'undefined' | dialyzer_plt:plt(). -spec get_warnings(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(), doc_plt(), dialyzer_codeserver:codeserver(), dialyzer_timing:timing_server(), [solver()], pid()) -> diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 0b8b244cc9..5f0881bbcd 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -68,7 +68,7 @@ -type type_var() :: erl_types:erl_type(). %% actually: {'c','var',_,_} -record(fun_var, {'fun' :: fun((_) -> erl_types:erl_type()), deps :: [dep()], - origin :: integer()}). + origin :: integer() | 'undefined'}). -type constr_op() :: 'eq' | 'sub'. -type fvar_or_type() :: #fun_var{} | erl_types:erl_type(). @@ -83,9 +83,9 @@ -record(constraint_list, {type :: 'conj' | 'disj', list :: [constr()], deps :: [dep()], - masks :: [{dep(),[non_neg_integer()]}] | - {'d',dict:dict(dep(), [non_neg_integer()])}, - id :: {'list', dep()}}). + masks = [] :: [{dep(),[non_neg_integer()]}] | + {'d',dict:dict(dep(), [non_neg_integer()])}, + id :: {'list', dep()} | 'undefined'}). -type constraint_list() :: #constraint_list{}. @@ -104,7 +104,8 @@ -type dict_or_ets() :: {'d', prop_types()} | {'e', ets:tid()}. --record(state, {callgraph :: dialyzer_callgraph:callgraph(), +-record(state, {callgraph :: dialyzer_callgraph:callgraph() + | 'undefined', cs = [] :: [constr()], cmap = {'d', dict:new()} :: dict_or_ets(), fun_map = [] :: typesig_funmap(), @@ -116,7 +117,8 @@ cerl:c_fun()), next_label = 0 :: label(), self_rec :: 'false' | erl_types:erl_type(), - plt :: dialyzer_plt:plt(), + plt :: dialyzer_plt:plt() + | 'undefined', prop_types = {'d', dict:new()} :: dict_or_ets(), records = dict:new() :: types(), scc = [] :: [type_var()], @@ -1746,7 +1748,10 @@ minimize_state(#state{ fun_arities = FunArities, self_rec = SelfRec, prop_types = {e, ETSPropTypes}, - solvers = Solvers + solvers = Solvers, + callgraph = undefined, + plt = undefined, + mfas = [] }. dispose_state(#state{cmap = {e, ETSCMap}, @@ -2884,8 +2889,7 @@ mk_constraint(Lhs, Op, Rhs) -> case t_is_any(Lhs) orelse constraint_opnd_is_any(Rhs) of false -> Deps = find_constraint_deps([Lhs, Rhs]), - C0 = mk_constraint_1(Lhs, Op, Rhs), - C = C0#constraint{deps = Deps}, + C = mk_constraint_1(Lhs, Op, Rhs, Deps), case Deps =:= [] of true -> %% This constraint is constant. Solve it immediately. @@ -2903,8 +2907,7 @@ mk_constraint(Lhs, Op, Rhs) -> end. mk_constraint_any(Op) -> - C = mk_constraint_1(t_any(), Op, t_any()), - C#constraint{deps = []}. + mk_constraint_1(t_any(), Op, t_any(), []). %% the following function is used so that we do not call %% erl_types:t_is_any/1 with a term other than an erl_type() @@ -2952,12 +2955,12 @@ find_constraint_deps([Type|Tail], Acc) -> find_constraint_deps([], Acc) -> lists:flatten(Acc). -mk_constraint_1(Lhs, eq, Rhs) when Lhs < Rhs -> - #constraint{lhs = Lhs, op = eq, rhs = Rhs}; -mk_constraint_1(Lhs, eq, Rhs) -> - #constraint{lhs = Rhs, op = eq, rhs = Lhs}; -mk_constraint_1(Lhs, Op, Rhs) -> - #constraint{lhs = Lhs, op = Op, rhs = Rhs}. +mk_constraint_1(Lhs, eq, Rhs, Deps) when Lhs < Rhs -> + #constraint{lhs = Lhs, op = eq, rhs = Rhs, deps = Deps}; +mk_constraint_1(Lhs, eq, Rhs, Deps) -> + #constraint{lhs = Rhs, op = eq, rhs = Lhs, deps = Deps}; +mk_constraint_1(Lhs, Op, Rhs, Deps) -> + #constraint{lhs = Lhs, op = Op, rhs = Rhs, deps = Deps}. mk_constraints([Lhs|LhsTail], Op, [Rhs|RhsTail]) -> [mk_constraint(Lhs, Op, Rhs) | diff --git a/lib/dialyzer/src/dialyzer_worker.erl b/lib/dialyzer/src/dialyzer_worker.erl index 4be93c75bf..979e3a621d 100644 --- a/lib/dialyzer/src/dialyzer_worker.erl +++ b/lib/dialyzer/src/dialyzer_worker.erl @@ -31,10 +31,11 @@ -type coordinator() :: dialyzer_coordinator:coordinator(). -type init_data() :: dialyzer_coordinator:init_data(). -type result() :: dialyzer_coordinator:result(). +-type job() :: dialyzer_coordinator:job(). -record(state, { mode :: mode(), - job :: mfa_or_funlbl() | file:filename(), + job :: job(), coordinator :: coordinator(), init_data :: init_data(), depends_on = [] :: list() @@ -52,7 +53,7 @@ %%-------------------------------------------------------------------- --spec launch(mode(), [mfa_or_funlbl()], init_data(), coordinator()) -> worker(). +-spec launch(mode(), job(), init_data(), coordinator()) -> worker(). launch(Mode, Job, InitData, Coordinator) -> State = #state{mode = Mode, @@ -174,7 +175,7 @@ collect_warnings(#state{job = Job, init_data = InitData}) -> -type extra() :: label() | 'unused'. --spec sequential(mode(), [mfa_or_funlbl()], init_data(), extra()) -> result(). +-spec sequential(mode(), job(), init_data(), extra()) -> result(). sequential('compile', Job, InitData, Extra) -> case dialyzer_analysis_callgraph:start_compilation(Job, InitData) of diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs b/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs index 33d135048e..38999e8919 100644 --- a/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs @@ -1,5 +1,5 @@ -my_callbacks_wrong.erl:26: The return type #state{parent::'undefined' | pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()} in the specification of callback_init/1 is not a subtype of {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour -my_callbacks_wrong.erl:28: The inferred return type of callback_init/1 (#state{parent::'undefined' | pid(),status::'init',subscribe::[],counter::1}) has nothing in common with {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour -my_callbacks_wrong.erl:30: The return type {'reply',#state{parent::'undefined' | pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()}} in the specification of callback_cast/3 is not a subtype of {'noreply',_}, which is the expected return type for the callback of my_behaviour behaviour +my_callbacks_wrong.erl:26: The return type #state{parent::pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()} in the specification of callback_init/1 is not a subtype of {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour +my_callbacks_wrong.erl:28: The inferred return type of callback_init/1 (#state{parent::pid(),status::'init',subscribe::[],counter::1}) has nothing in common with {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour +my_callbacks_wrong.erl:30: The return type {'reply',#state{parent::pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()}} in the specification of callback_cast/3 is not a subtype of {'noreply',_}, which is the expected return type for the callback of my_behaviour behaviour my_callbacks_wrong.erl:39: The specified type for the 2nd argument of callback_call/3 (atom()) is not a supertype of pid(), which is expected type for this argument in the callback of the my_behaviour behaviour diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/crash b/lib/dialyzer/test/opaque_SUITE_data/results/crash index 69bdc00257..d63389f79c 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/crash +++ b/lib/dialyzer/test/opaque_SUITE_data/results/crash @@ -1,6 +1,6 @@ -crash_1.erl:45: Record construction #targetlist{list::[]} violates the declared type of field list::'undefined' | crash_1:target() -crash_1.erl:48: The call crash_1:get_using_branch2(Branch::maybe_improper_list(),L::'undefined' | crash_1:target()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),maybe_improper_list()) -crash_1.erl:50: The pattern <_Branch, []> can never match the type <maybe_improper_list(),'undefined' | crash_1:target()> -crash_1.erl:52: The pattern <Branch, [H = {'target', _, _} | _T]> can never match the type <maybe_improper_list(),'undefined' | crash_1:target()> -crash_1.erl:54: The pattern <Branch, [{'target', _, _} | T]> can never match the type <maybe_improper_list(),'undefined' | crash_1:target()> +crash_1.erl:45: Record construction #targetlist{list::[]} violates the declared type of field list::crash_1:target() +crash_1.erl:48: The call crash_1:get_using_branch2(Branch::maybe_improper_list(),L::crash_1:target()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),maybe_improper_list()) +crash_1.erl:50: The pattern <_Branch, []> can never match the type <maybe_improper_list(),crash_1:target()> +crash_1.erl:52: The pattern <Branch, [H = {'target', _, _} | _T]> can never match the type <maybe_improper_list(),crash_1:target()> +crash_1.erl:54: The pattern <Branch, [{'target', _, _} | T]> can never match the type <maybe_improper_list(),crash_1:target()> diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/simple b/lib/dialyzer/test/opaque_SUITE_data/results/simple index 1a7a139d6e..5f58f69730 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/simple +++ b/lib/dialyzer/test/opaque_SUITE_data/results/simple @@ -18,7 +18,7 @@ rec_api.erl:104: Matching of pattern {'r2', 10} tagged with a record name violat rec_api.erl:113: The attempt to match a term of type #r3{f1::queue:queue(_)} against the pattern {'r3', 'a'} breaks the opaqueness of queue:queue(_) rec_api.erl:118: Record construction #r3{f1::10} violates the declared type of field f1::queue:queue(_) rec_api.erl:123: The attempt to match a term of type #r3{f1::10} against the pattern {'r3', 10} breaks the opaqueness of queue:queue(_) -rec_api.erl:24: Record construction #r1{f1::10} violates the declared type of field f1::'undefined' | rec_api:a() +rec_api.erl:24: Record construction #r1{f1::10} violates the declared type of field f1::rec_api:a() rec_api.erl:29: Matching of pattern {'r1', 10} tagged with a record name violates the declared type of #r1{f1::10} rec_api.erl:33: The attempt to match a term of type rec_adt:r1() against the pattern {'r1', 'a'} breaks the opaqueness of the term rec_api.erl:35: Invalid type specification for function rec_api:adt_t1/1. The success typing is (#r1{f1::'a'}) -> #r1{f1::'a'} diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia index b73943422a..1dc5a105bf 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia +++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia @@ -35,6 +35,6 @@ mnesia_schema.erl:1258: Guard test FromS::'disc_copies' | 'disc_only_copies' | ' mnesia_schema.erl:1639: The pattern {'false', 'mandatory'} can never match the type {'false','optional'} mnesia_schema.erl:2434: The variable Reason can never match since previous clauses completely covered the type {'error',_} | {'ok',_} mnesia_schema.erl:451: Guard test UseDirAnyway::'false' == 'true' can never succeed -mnesia_text.erl:180: The variable T can never match since previous clauses completely covered the type {'error',{integer(),atom() | tuple(),_}} | {'ok',_} +mnesia_text.erl:180: The variable T can never match since previous clauses completely covered the type {'error',{non_neg_integer(),atom() | tuple(),_}} | {'ok',_} mnesia_tm.erl:1522: Function commit_participant/5 has no local return mnesia_tm.erl:2169: Function system_terminate/4 has no local return diff --git a/lib/dialyzer/test/small_SUITE_data/results/bif1 b/lib/dialyzer/test/small_SUITE_data/results/bif1 new file mode 100644 index 0000000000..289b6f821f --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/bif1 @@ -0,0 +1,3 @@ + +bif1.erl:13: Function string_chars/0 has no local return +bif1.erl:16: The call string:chars(S::65,10,L2::bif1_adt:s()) contains an opaque term as 3rd argument when terms of different types are expected in these positions diff --git a/lib/dialyzer/test/small_SUITE_data/results/fun_arity b/lib/dialyzer/test/small_SUITE_data/results/fun_arity new file mode 100644 index 0000000000..280f5490d0 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/fun_arity @@ -0,0 +1,35 @@ + +fun_arity.erl:100: Fun application will fail since _cor1 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:100: Function 'Mfa_0_ko'/1 has no local return +fun_arity.erl:104: Fun application will fail since _cor1 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:104: Function 'Mfa_1_ko'/1 has no local return +fun_arity.erl:111: Fun application will fail since _cor1 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:111: Function mFa_0_ko/1 has no local return +fun_arity.erl:115: Fun application will fail since _cor1 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:115: Function mFa_1_ko/1 has no local return +fun_arity.erl:122: Fun application will fail since _cor2 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:122: Function 'MFa_0_ko'/2 has no local return +fun_arity.erl:126: Fun application will fail since _cor2 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:126: Function 'MFa_1_ko'/2 has no local return +fun_arity.erl:35: Fun application will fail since _cor0 :: fun(() -> 'ok') is not a function of arity 1 +fun_arity.erl:35: Function f_0_ko/0 has no local return +fun_arity.erl:39: Fun application will fail since _cor0 :: fun((_) -> 'ok') is not a function of arity 0 +fun_arity.erl:39: Function f_1_ko/0 has no local return +fun_arity.erl:48: Fun application will fail since _cor0 :: fun(() -> 'ok') is not a function of arity 1 +fun_arity.erl:48: Function fa_0_ko/0 has no local return +fun_arity.erl:53: Fun application will fail since _cor0 :: fun((_) -> 'ok') is not a function of arity 0 +fun_arity.erl:53: Function fa_1_ko/0 has no local return +fun_arity.erl:63: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:63: Function mfa_0_ko/0 has no local return +fun_arity.erl:68: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:68: Function mfa_1_ko/0 has no local return +fun_arity.erl:76: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:76: Function mfa_ne_0_ko/0 has no local return +fun_arity.erl:78: Function mf_ne/0 will never be called +fun_arity.erl:81: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:81: Function mfa_ne_1_ko/0 has no local return +fun_arity.erl:83: Function mf_ne/1 will never be called +fun_arity.erl:89: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:89: Function mfa_nd_0_ko/0 has no local return +fun_arity.erl:93: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:93: Function mfa_nd_1_ko/0 has no local return diff --git a/lib/dialyzer/test/small_SUITE_data/results/literals b/lib/dialyzer/test/small_SUITE_data/results/literals index 03e161ca71..222d2c0cdb 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/literals +++ b/lib/dialyzer/test/small_SUITE_data/results/literals @@ -1,14 +1,14 @@ literals.erl:11: Function t1/0 has no local return -literals.erl:12: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:12: Record construction #r{id::'a'} violates the declared type of field id::'integer' literals.erl:14: Function t2/0 has no local return -literals.erl:15: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:15: Record construction #r{id::'a'} violates the declared type of field id::'integer' literals.erl:17: Function t3/0 has no local return -literals.erl:18: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' -literals.erl:21: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:18: Record construction #r{id::'a'} violates the declared type of field id::'integer' +literals.erl:21: Record construction #r{id::'a'} violates the declared type of field id::'integer' literals.erl:23: Function m1/1 has no local return -literals.erl:23: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer' | 'undefined'} +literals.erl:23: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer'} literals.erl:26: Function m2/1 has no local return -literals.erl:26: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer' | 'undefined'} +literals.erl:26: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer'} literals.erl:29: Function m3/1 has no local return literals.erl:29: The pattern {{'r', 'a'}} can never match the type any() diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs b/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs index f00c4b10ff..c971935bbf 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs +++ b/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs @@ -1,3 +1,3 @@ record_creation_diffs.erl:10: Function foo/1 has no local return -record_creation_diffs.erl:11: Record construction #bar{some_list::{'this','is','a','tuple'}} violates the declared type of field some_list::'undefined' | [any()] +record_creation_diffs.erl:11: Record construction #bar{some_list::{'this','is','a','tuple'}} violates the declared type of field some_list::[any()] diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_pat b/lib/dialyzer/test/small_SUITE_data/results/record_pat index a46be6c451..8317ea041a 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/record_pat +++ b/lib/dialyzer/test/small_SUITE_data/results/record_pat @@ -1,2 +1,2 @@ -record_pat.erl:14: Matching of pattern {'foo', 'baz'} tagged with a record name violates the declared type of #foo{bar::'undefined' | integer()} +record_pat.erl:14: Matching of pattern {'foo', 'baz'} tagged with a record name violates the declared type of #foo{bar::integer()} diff --git a/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning b/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning index 2e417e1b2a..ea3ac92d96 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning +++ b/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning @@ -1,3 +1,3 @@ relevant_record_warning.erl:22: Function test/1 has no local return -relevant_record_warning.erl:23: Record construction #r{field::<<_:8>>} violates the declared type of field field::'binary' | 'undefined' +relevant_record_warning.erl:23: Record construction #r{field::<<_:8>>} violates the declared type of field field::'binary' diff --git a/lib/dialyzer/test/small_SUITE_data/results/undefined b/lib/dialyzer/test/small_SUITE_data/results/undefined new file mode 100644 index 0000000000..9daa8640d3 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/undefined @@ -0,0 +1,2 @@ + +r.erl:16: Record construction #r{a::{'fi'},b::{'a','b'},c::[],d::'undefined',e::[],f::'undefined'} violates the declared type of field b::[any()] and d::[any()] and f::[any()] diff --git a/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl new file mode 100644 index 0000000000..bc746538d3 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl @@ -0,0 +1,16 @@ +-module(bif1). + +%% Other set of warnings due to removed of functions from +%% erl_bif_types. + +-export([ets_rename/0, string_chars/0]). + +ets_rename() -> + A = ets:new(fipp, []), + true = not is_atom(A), + ets:rename(A, fopp). % No warning + +string_chars() -> + L2 = bif1_adt:opaque_string(), + S = $A, + string:chars(S, 10, L2). % Warning diff --git a/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl new file mode 100644 index 0000000000..01b0bccc68 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl @@ -0,0 +1,12 @@ +-module(bif1_adt). + +-export([opaque_string/0]). + +-export_type([s/0]). + +-opaque s() :: string(). + +-spec opaque_string() -> s(). + +opaque_string() -> + "string". diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl index ab84e94106..9ad4810a5e 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl @@ -36,7 +36,7 @@ %% Start of Abstract Format --type line() :: erl_scan:line(). +-type line() :: erl_anno:line(). -export_type([af_record_index/0, af_record_field/1, af_record_name/0, af_field_name/0, af_function_decl/0]). @@ -332,8 +332,8 @@ %% End of Abstract Format -type error_description() :: term(). --type error_info() :: {erl_scan:line(), module(), error_description()}. --type token() :: {Tag :: atom(), Line :: erl_scan:line()}. +-type error_info() :: {erl_anno:line(), module(), error_description()}. +-type token() :: {Tag :: atom(), Line :: erl_scan:anno()}. %% mkop(Op, Arg) -> {op,Line,Op,Arg}. %% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}. diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl index fc7c5241a8..fe567ff10d 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl @@ -36,7 +36,7 @@ %% Start of Abstract Format --type line() :: erl_scan:line(). +-type line() :: erl_anno:line(). -export_type([af_module/0, af_export/0, af_import/0, af_fa_list/0, af_compile/0, af_file/0, af_record_decl/0, @@ -329,8 +329,8 @@ %% End of Abstract Format -type error_description() :: term(). --type error_info() :: {erl_scan:line(), module(), error_description()}. --type token() :: {Tag :: atom(), Line :: erl_scan:line()}. +-type error_info() :: {erl_anno:line(), module(), error_description()}. +-type token() :: {Tag :: atom(), Line :: erl_anno:line()}. %% mkop(Op, Arg) -> {op,Line,Op,Arg}. %% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}. diff --git a/lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl b/lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl new file mode 100644 index 0000000000..850d2fd331 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl @@ -0,0 +1,127 @@ +%%-------------------------------------------------------------------------- +%% Module which contains calls to funs of different arity. +%%-------------------------------------------------------------------------- +-module(fun_arity). + +-export([f_0_ok/0, f_0_ko/0]). +-export([f_1_ok/0, f_1_ko/0]). + +-export([fa_0_ok/0, fa_0_ko/0]). +-export([fa_1_ok/0, fa_1_ko/0]). + +-export([mfa_0_ok/0, mfa_0_ko/0, mf/0]). +-export([mfa_1_ok/0, mfa_1_ko/0, mf/1]). + +-export([mfa_ne_0_ok/0, mfa_ne_0_ko/0]). +-export([mfa_ne_1_ok/0, mfa_ne_1_ko/0]). + +-export([mfa_nd_0_ok/0, mfa_nd_0_ko/0]). +-export([mfa_nd_1_ok/0, mfa_nd_1_ko/0]). + +-export(['Mfa_0_ok'/1, 'Mfa_0_ko'/1]). +-export(['Mfa_1_ok'/1, 'Mfa_1_ko'/1]). + +-export(['mFa_0_ok'/1, 'mFa_0_ko'/1]). +-export(['mFa_1_ok'/1, 'mFa_1_ko'/1]). + +-export(['MFa_0_ok'/2, 'MFa_0_ko'/2]). +-export(['MFa_1_ok'/2, 'MFa_1_ko'/2]). + +%%-------------------------------------------------------------------------- + +%% Funs like "fun(...) -> ... end". + +f_0_ok() -> (fun_f_0())(). +f_0_ko() -> (fun_f_0())(1). +fun_f_0() -> fun() -> ok end. + +f_1_ok() -> (fun_f_1())(1). +f_1_ko() -> (fun_f_1())(). +fun_f_1() -> fun(_) -> ok end . + +%%-------------------------------------------------------------------------- + +%% Funs like "fun F/A" when F is literal atom and A is literal +%% non-negative integer. + +fa_0_ok() -> (fun_fa_0())(). +fa_0_ko() -> (fun_fa_0())(1). +fun_fa_0() -> fun f/0. +f() -> ok. + +fa_1_ok() -> (fun_fa_1())(1). +fa_1_ko() -> (fun_fa_1())(). +fun_fa_1() -> fun f/1. +f(_) -> ok. + +%%-------------------------------------------------------------------------- + +%% Funs like "fun M:F/A" when M and F are literal atoms, A is literal +%% non-negative integer and function is (defined and) exported. + +mfa_0_ok() -> (fun_mfa_0())(). +mfa_0_ko() -> (fun_mfa_0())(1). +fun_mfa_0() -> fun ?MODULE:mf/0. +mf() -> ok. + +mfa_1_ok() -> (fun_mfa_1())(1). +mfa_1_ko() -> (fun_mfa_1())(). +fun_mfa_1() -> fun ?MODULE:mf/1. +mf(_) -> ok. + +%% Funs like "fun M:F/A" when M and F are literal atoms, A is literal +%% non-negative integer and function is defined but not exported. + +mfa_ne_0_ok() -> (fun_mfa_ne_0())(). +mfa_ne_0_ko() -> (fun_mfa_ne_0())(1). +fun_mfa_ne_0() -> fun ?MODULE:mf_ne/0. +mf_ne() -> ok. + +mfa_ne_1_ok() -> (fun_mfa_ne_1())(1). +mfa_ne_1_ko() -> (fun_mfa_ne_1())(). +fun_mfa_ne_1() -> fun ?MODULE:mf_ne/1. +mf_ne(_) -> ok. + +%% Funs like "fun M:F/A" when M and F are literal atoms, A is literal +%% non-negative integer and function is not defined. + +mfa_nd_0_ok() -> (fun_mfa_nd_0())(). +mfa_nd_0_ko() -> (fun_mfa_nd_0())(1). +fun_mfa_nd_0() -> fun ?MODULE:mf_nd/0. + +mfa_nd_1_ok() -> (fun_mfa_nd_1())(1). +mfa_nd_1_ko() -> (fun_mfa_nd_1())(). +fun_mfa_nd_1() -> fun ?MODULE:mf_nd/1. + +%% Funs like "fun M:F/A" when M is variable, F is literal atoms and A +%% is literal non-negative integer. + +'Mfa_0_ok'(M) -> ('fun_Mfa_0'(M))(). +'Mfa_0_ko'(M) -> ('fun_Mfa_0'(M))(1). +'fun_Mfa_0'(M) -> fun M:f/0. + +'Mfa_1_ok'(M) -> ('fun_Mfa_1'(M))(1). +'Mfa_1_ko'(M) -> ('fun_Mfa_1'(M))(). +'fun_Mfa_1'(M) -> fun M:f/1. + +%% Funs like "fun M:F/A" when M is literal atom, F is variable and A +%% is literal non-negative integer. + +'mFa_0_ok'(F) -> ('fun_mFa_0'(F))(). +'mFa_0_ko'(F) -> ('fun_mFa_0'(F))(1). +'fun_mFa_0'(F) -> fun ?MODULE:F/0. + +'mFa_1_ok'(F) -> ('fun_mFa_1'(F))(1). +'mFa_1_ko'(F) -> ('fun_mFa_1'(F))(). +'fun_mFa_1'(F) -> fun ?MODULE:F/1. + +%% Funs like "fun M:F/A" when M and F are variables and A is literal +%% non-negative integer. + +'MFa_0_ok'(M, F) -> ('fun_MFa_0'(M, F))(). +'MFa_0_ko'(M, F) -> ('fun_MFa_0'(M, F))(1). +'fun_MFa_0'(M, F) -> fun M:F/0. + +'MFa_1_ok'(M, F) -> ('fun_MFa_1'(M, F))(1). +'MFa_1_ko'(M, F) -> ('fun_MFa_1'(M, F))(). +'fun_MFa_1'(M, F) -> fun M:F/1. diff --git a/lib/dialyzer/test/small_SUITE_data/src/trec.erl b/lib/dialyzer/test/small_SUITE_data/src/trec.erl index 06706162c1..516358f7c6 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/trec.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/trec.erl @@ -8,7 +8,7 @@ -module(trec). -export([test/0, mk_foo_exp/2]). --record(foo, {a :: integer(), b :: [atom()]}). +-record(foo, {a :: integer() | 'undefined', b :: [atom()]}). %% %% For these functions we currently get the following warnings: diff --git a/lib/dialyzer/test/small_SUITE_data/undefined.erl b/lib/dialyzer/test/small_SUITE_data/undefined.erl new file mode 100644 index 0000000000..8549f2e161 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/undefined.erl @@ -0,0 +1,29 @@ +-module(undefined). + +-export([t/0]). + +%% As of OTP 19.0 'undefined' is no longer added to fields with a type +%% declaration but without an initializer. The pretty printing of +%% records (erl_types:t_to_string()) is updated to reflect this: if a +%% field is of type 'undefined', it is output if 'undefined' is not in +%% the declared type of the field. (It used to be the case that the +%% singleton type 'undefined' was never output.) +%% +%% One consequence is shown by the example below: the warning about +%% the record construction violating the the declared type shows +%% #r{..., d::'undefined', ...} which is meant to be of help to the +%% user, who could otherwise get confused the first time (s)he gets +%% confronted by the warning. + +-record(r, + { + a = {fi}, + b = {a,b} :: list(), % violation + c = {a,b} :: list(), + d :: list(), % violation + e = [] :: list(), + f = undefined :: list() % violation + }). + +t() -> + #r{c = []}. diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 48e0830109..9480f17f51 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 2.8 +DIALYZER_VSN = 2.8.2 diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml index 47247bc2ff..61b7fd1337 100644 --- a/lib/diameter/doc/src/diameter.xml +++ b/lib/diameter/doc/src/diameter.xml @@ -913,6 +913,49 @@ Options <c>monitor</c> and <c>link</c> are ignored.</p> Defaults to the empty list.</p> </item> +<marker id="strict_mbit"/> +<tag><c>{strict_mbit, boolean()}</c></tag> +<item> +<p> +Whether or not to regard an AVP setting the M-bit as erroneous when +the command grammar in question does not explicitly allow the AVP. +If <c>true</c> then such AVPs are regarded as 5001 errors, +DIAMETER_AVP_UNSUPPORTED. +If <c>false</c> then the M-bit is ignored and policing +it becomes the receiver's responsibility.</p> + +<p> +Defaults to <c>true</c>.</p> + +<warning> +<p> +RFC 6733 is unclear about the semantics of the M-bit. +One the one hand, the CCF specification in section 3.2 documents AVP +in a command grammar as meaning <b>any</b> arbitrary AVP; on the +other hand, 1.3.4 states that AVPs setting the M-bit cannot be added +to an existing command: the modified command must instead be +placed in a new Diameter application.</p> +<p> +The reason for the latter is presumably interoperability: +allowing arbitrary AVPs setting the M-bit in a command makes its +interpretation implementation-dependent, since there's no +guarantee that all implementations will understand the same set of +arbitrary AVPs in the context of a given command. +However, interpreting <c>AVP</c> in a command grammar as <b>any</b> +AVP, regardless of M-bit, renders 1.3.4 meaningless, since the receiver +can simply ignore any AVP it thinks isn't relevant, regardless of the +sender's intent.</p> +<p> +Beware of confusing mandatory in the sense of the M-bit with mandatory +in the sense of the command grammar. +The former is a semantic requirement: that the receiver understand the +semantics of the AVP in the context in question. +The latter is a syntactic requirement: whether or not the AVP must +occur in the message in question.</p> +</warning> + +</item> + <marker id="string_decode"/> <tag><c>{string_decode, boolean()}</c></tag> <item> diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index c5f0d66f10..61bed37682 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -49,6 +49,41 @@ first.</p> <list> <item> <p> + Fix relay encode of nested, Grouped AVPs.</p> + <p> + A fault in OTP-12475 caused encode to fail if the first + AVP in a Grouped AVP was itself Grouped.</p> + <p> + Own Id: OTP-12879 Aux Id: OTP-12475 </p> + </item> + <item> + <p> + Match acceptable peer addresses case insensitively.</p> + <p> + Regular expressions passed in an 'accept' tuple to + diameter_tcp or diameter_sctp inappropriately matched + case.</p> + <p> + Own Id: OTP-12902</p> + </item> + <item> + <p> + Fix diameter_watchdog function clause.</p> + <p> + OTP-12912 introduced an error with accepting transports + setting <c>{restrict_connections, false}</c>, causing + processes to fail when peer connections were terminated.</p> + <p> + Own Id: OTP-12969</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Don't report 5005 (DIAMETER_AVP_MISSING) errors unnecessarily.</p> <p> @@ -60,15 +95,6 @@ first.</p> </item> <item> <p> - Fix relay encode of nested, Grouped AVPs.</p> - <p> - A fault in OTP-12475 caused encode to fail if the first - AVP in a Grouped AVP was itself Grouped.</p> - <p> - Own Id: OTP-12879 Aux Id: OTP-12475 </p> - </item> - <item> - <p> Improve decode performance.</p> <p> The time required to decode a message increased @@ -79,16 +105,6 @@ first.</p> </item> <item> <p> - Match acceptable peer addresses case insensitively.</p> - <p> - Regular expressions passed in an 'accept' tuple to - diameter_tcp or diameter_sctp inappropriately matched - case.</p> - <p> - Own Id: OTP-12902</p> - </item> - <item> - <p> Improve watchdog and statistics performance.</p> <p> Inefficient use of timers contributed to poor performance @@ -97,13 +113,24 @@ first.</p> <p> Own Id: OTP-12912</p> </item> + <item> + <p> + Add service_opt() strict_mbit.</p> + <p> + There are differing opinions on whether or not reception + of an arbitrary AVP setting the M-bit is an error. The + default interpretation is strict: if a command grammar + doesn't explicitly allow an AVP setting the M-bit then + reception of such an AVP is regarded as an error. Setting + <c>{strict_mbit, false}</c> disables this check.</p> + <p> + Own Id: OTP-12947</p> + </item> </list> </section> </section> -<!-- ===================================================================== --> - <section><title>diameter 1.10</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl index 5624ee6626..611ad796a9 100644 --- a/lib/diameter/include/diameter_gen.hrl +++ b/lib/diameter/include/diameter_gen.hrl @@ -31,7 +31,10 @@ %% Key to a value in the process dictionary that determines whether or %% not an unrecognized AVP setting the M-bit should be regarded as an -%% error or not. See is_strict/0. +%% error or not. See is_strict/0. This is only used to relax M-bit +%% interpretation inside Grouped AVPs not setting the M-bit. The +%% service_opt() strict_mbit can be used to disable the check +%% globally. -define(STRICT_KEY, strict). %% Key that says whether or not we should do a best-effort decode @@ -448,7 +451,8 @@ relax(_, _) -> false. is_strict() -> - false /= getr(?STRICT_KEY). + diameter_codec:getopt(strict_mbit) + andalso false /= getr(?STRICT_KEY). %% relax/1 %% diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl index e82c2c168c..de88f6befd 100644 --- a/lib/diameter/src/base/diameter.erl +++ b/lib/diameter/src/base/diameter.erl @@ -312,6 +312,7 @@ call(SvcName, App, Message) -> | {sequence, sequence() | evaluable()} | {share_peers, remotes()} | {string_decode, boolean()} + | {strict_mbit, boolean()} | {incoming_maxlen, message_length()} | {use_shared_peers, remotes()} | {spawn_opt, list()}. diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl index bcdc5b3005..1ea5357924 100644 --- a/lib/diameter/src/base/diameter_codec.erl +++ b/lib/diameter/src/base/diameter_codec.erl @@ -77,9 +77,10 @@ setopts(Opts) when is_list(Opts) -> lists:foreach(fun setopt/1, Opts). -%% Decode stringish types to string()? The default true is for -%% backwards compatibility. -setopt({string_decode = K, false = B}) -> +%% The default string_decode true is for backwards compatibility. +setopt({K, false = B}) + when K == string_decode; + K == strict_mbit -> setopt(K, B); %% Regard anything but the generated RFC 3588 dictionary as modern. @@ -97,7 +98,8 @@ setopt(Key, Value) -> getopt(Key) -> case get({diameter, Key}) of - undefined when Key == string_decode -> + undefined when Key == string_decode; + Key == strict_mbit -> true; undefined when Key == rfc -> 6733; diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl index b7d8345b6c..702f11593a 100644 --- a/lib/diameter/src/base/diameter_config.erl +++ b/lib/diameter/src/base/diameter_config.erl @@ -647,6 +647,7 @@ make_config(SvcName, Opts) -> {?NOMASK, sequence}, {nodes, restrict_connections}, {16#FFFFFF, incoming_maxlen}, + {true, strict_mbit}, {true, string_decode}, {[], spawn_opt}]), @@ -685,12 +686,14 @@ opt(K, false = B) K == use_shared_peers; K == monitor; K == restrict_connections; + K == strict_mbit; K == string_decode -> B; opt(K, true = B) when K == share_peers; K == use_shared_peers; + K == strict_mbit; K == string_decode -> B; diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl index 2b23183d18..fb874013a3 100644 --- a/lib/diameter/src/base/diameter_peer_fsm.erl +++ b/lib/diameter/src/base/diameter_peer_fsm.erl @@ -117,7 +117,7 @@ parent :: pid(), %% watchdog process transport :: pid(), %% transport process dictionary :: module(), %% common dictionary - service :: #diameter_service{}, + service :: #diameter_service{} | undefined, dpr = false :: false | true %% DPR received, DPA sent | {boolean(), uint32(), uint32()}, diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index e47b975768..86781c02bf 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -129,6 +129,7 @@ | {share_peers, diameter:remotes()} %% broadcast to | {use_shared_peers, diameter:remotes()} %% use from | {restrict_connections, diameter:restriction()} + | {strict_mbit, boolean()} | {string_decode, boolean()} | {incoming_maxlen, diameter:message_length()}]}). %% shared_peers reflects the peers broadcast from remote nodes. @@ -136,7 +137,7 @@ %% Record representing an RFC 3539 watchdog process implemented by %% diameter_watchdog. -record(watchdog, - {pid :: match(pid()), + {pid :: match(pid()) | undefined, type :: match(connect | accept), ref :: match(reference()), %% key into diameter_config options :: match([diameter:transport_opt()]),%% from start_transport @@ -698,7 +699,8 @@ service_options(Opts) -> ?RESTRICT)}, {spawn_opt, proplists:get_value(spawn_opt, Opts, [])}, {string_decode, proplists:get_value(string_decode, Opts, true)}, - {incoming_maxlen, proplists:get_value(incoming_maxlen, Opts, 16#FFFFFF)}]. + {incoming_maxlen, proplists:get_value(incoming_maxlen, Opts, 16#FFFFFF)}, + {strict_mbit, proplists:get_value(strict_mbit, Opts, true)}]. %% The order of options is significant since we match against the list. mref(false = No) -> diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl index 692a01e651..9e14860693 100644 --- a/lib/diameter/src/base/diameter_traffic.erl +++ b/lib/diameter/src/base/diameter_traffic.erl @@ -80,6 +80,7 @@ apps :: [#diameter_app{}], sequence :: diameter:sequence(), codec :: [{string_decode, boolean()} + | {strict_mbit, boolean()} | {incoming_maxlen, diameter:message_length()}]}). %% Note that incoming_maxlen is currently handled in diameter_peer_fsm, %% so that any message exceeding the maximum is discarded. Retain the @@ -106,7 +107,8 @@ make_recvdata([SvcName, PeerT, Apps, SvcOpts | _]) -> sequence = Mask, codec = [T || {K,_} = T <- SvcOpts, lists:member(K, [string_decode, - incoming_maxlen])]}. + incoming_maxlen, + strict_mbit])]}. %% --------------------------------------------------------------------------- %% peer_up/1 diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl index 3c0d8f6f6e..ea8b2fdb0e 100644 --- a/lib/diameter/src/base/diameter_watchdog.erl +++ b/lib/diameter/src/base/diameter_watchdog.erl @@ -541,13 +541,13 @@ set_watchdog(#watchdog{tref = undefined} = S) -> %% Timer already set: start at new one only at expiry. set_watchdog(#watchdog{} = S) -> - S#watchdog{tref = diameter_lib:now()}; - -set_watchdog(stop = No) -> - No. + S#watchdog{tref = diameter_lib:now()}. %% set_watchdog/2 +set_watchdog(_, stop = No) -> + No; + set_watchdog(Ms, #watchdog{tw = TwInit} = S) -> S#watchdog{tref = erlang:start_timer(tw(TwInit, Ms), self(), tw)}. diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src index 788ea790fa..b77043d983 100644 --- a/lib/diameter/src/diameter.appup.src +++ b/lib/diameter/src/diameter.appup.src @@ -52,8 +52,10 @@ {load_module, diameter_lib}, {load_module, diameter_peer}, {load_module, diameter_reg}, + {load_module, diameter_traffic}, {load_module, diameter_service}, {load_module, diameter_sync}, + {load_module, diameter}, {load_module, diameter_gen_base_rfc6733}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc3588}, @@ -89,8 +91,10 @@ {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc6733}, + {load_module, diameter}, {load_module, diameter_sync}, {load_module, diameter_service}, + {load_module, diameter_traffic}, {load_module, diameter_reg}, {load_module, diameter_peer}, {load_module, diameter_lib}, diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl index 678dc9b5d6..8a80ce630a 100644 --- a/lib/diameter/src/transport/diameter_sctp.erl +++ b/lib/diameter/src/transport/diameter_sctp.erl @@ -84,16 +84,18 @@ %% Accepting/connecting transport process state. -record(transport, - {parent :: pid(), + {parent :: pid() | undefined, mode :: {accept, pid()} | accept | {connect, {[inet:ip_address()], uint(), list()}} %% {RAs, RP, Errors} | connect, - socket :: gen_sctp:sctp_socket(), + socket :: gen_sctp:sctp_socket() | undefined, assoc_id :: gen_sctp:assoc_id(), %% association identifier - peer :: {[inet:ip_address()], uint()}, %% {RAs, RP} - streams :: {uint(), uint()}, %% {InStream, OutStream} counts + peer :: {[inet:ip_address()], uint()} %% {RAs, RP} + | undefined, + streams :: {uint(), uint()} %% {InStream, OutStream} counts + | undefined, os = 0 :: uint()}). %% next output stream %% Listener process state. @@ -102,7 +104,7 @@ socket :: gen_sctp:sctp_socket(), count = 0 :: uint(), %% attached transport processes pending = {0, queue:new()}, - tref :: reference(), + tref :: reference() | undefined, accept :: [match()]}). %% Field pending implements two queues: the first of transport-to-be %% processes to which an association has been assigned but for which diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl index 005b2442c0..c79d85820b 100644 --- a/lib/diameter/src/transport/diameter_tcp.erl +++ b/lib/diameter/src/transport/diameter_tcp.erl @@ -73,7 +73,7 @@ %% Listener process state. -record(listener, {socket :: inet:socket(), count = 1 :: non_neg_integer(), - tref :: reference()}). + tref :: reference() | undefined}). %% Monitor process state. -record(monitor, diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl index ae47c815c9..df87ddde08 100644 --- a/lib/eldap/src/eldap.erl +++ b/lib/eldap/src/eldap.erl @@ -242,7 +242,7 @@ modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup) %%% Sanity checks ! -bool_p(Bool) when Bool==true;Bool==false -> Bool. +bool_p(Bool) when is_boolean(Bool) -> Bool. optional([]) -> asn1_NOVALUE; optional(Value) -> Value. @@ -1022,10 +1022,13 @@ log(_, _, _, _) -> %%% Misc. routines %%% -------------------------------------------------------------------- -send(To,Msg) -> To ! {self(),Msg}. +send(To,Msg) -> + To ! {self(), Msg}, + ok. + recv(From) -> receive - {From,Msg} -> Msg; + {From, Msg} -> Msg; {'EXIT', From, Reason} -> {error, {internal_error, Reason}} end. diff --git a/lib/erl_docgen/doc/src/erl_docgen_app.xml b/lib/erl_docgen/doc/src/erl_docgen_app.xml index c2c65a0592..58c2a24f4b 100644 --- a/lib/erl_docgen/doc/src/erl_docgen_app.xml +++ b/lib/erl_docgen/doc/src/erl_docgen_app.xml @@ -32,7 +32,7 @@ <description> <p> - The application consists of the following parts + The application consists of the following parts:</p> <taglist> <tag>XSL</tag> <item> @@ -59,7 +59,6 @@ </p> </item> </taglist> - </p> </description> </appref> diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css index 0b531db701..347782eb1e 100644 --- a/lib/erl_docgen/priv/css/otp_doc.css +++ b/lib/erl_docgen/priv/css/otp_doc.css @@ -37,7 +37,7 @@ a:visited { color: blue; text-decoration: none } top: 0; bottom: 0; left: 0; - width: 200px; + width: 300px; overflow:auto; margin: 0; padding: 1px; @@ -45,7 +45,7 @@ a:visited { color: blue; text-decoration: none } } #content { - margin-left: 240px; /* set left value to WidthOfFrameDiv */ + margin-left: 340px; /* set left value to WidthOfFrameDiv */ } .frontpage diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in index 777d709b1e..d6176ec053 100644 --- a/lib/erl_interface/src/Makefile.in +++ b/lib/erl_interface/src/Makefile.in @@ -126,11 +126,7 @@ else WARNFLAGS = @WFLAGS@ endif -ifneq ($(findstring ose,$(TARGET)),ose) CFLAGS = @LIB_CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -else -CFLAGS = @CFLAGS@ $(INCFLAGS) -endif PROG_CFLAGS = @CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -Ilegacy ifeq ($(findstring vxworks,$(TARGET)),vxworks) @@ -210,12 +206,8 @@ MDD_ERLLIB = $(OBJDIR)/$(LIBPRE)erl_interface_mdd$(LIBEXT) # Specify targets to build ########################################################################### -ifneq ($(findstring ose,$(TARGET)),ose) EXE_TARGETS = \ $(ERL_CALL) -else -EXE_TARGETS = -endif ifeq ($(USING_VC),yes) @@ -480,44 +472,6 @@ ERLSOURCES = \ SOURCES = $(EISOURCES) $(ERLSOURCES) -OSE_EISOURCES = \ - $(DECODESRC) \ - $(ENCODESRC) \ - misc/ei_decode_term.c \ - misc/ei_format.c \ - misc/ei_locking.c \ - misc/ei_malloc.c \ - misc/ei_printterm.c \ - misc/ei_pthreads.c \ - misc/ei_trace.c \ - misc/ei_x_encode.c \ - misc/eimd5.c \ - misc/get_type.c \ - misc/show_msg.c \ - misc/ei_compat.c \ - registry/hash_dohash.c \ - registry/hash_foreach.c \ - registry/hash_freetab.c \ - registry/hash_insert.c \ - registry/hash_isprime.c \ - registry/hash_lookup.c \ - registry/hash_newtab.c \ - registry/hash_remove.c \ - registry/hash_resize.c \ - registry/hash_rlookup.c - -OSE_ERLSOURCES = \ - legacy/decode_term.c \ - legacy/encode_term.c \ - legacy/erl_error.c \ - legacy/erl_eterm.c \ - legacy/erl_fix_alloc.c \ - legacy/erl_format.c \ - legacy/erl_malloc.c \ - legacy/erl_marshal.c - -OSE_SOURCES = $(OSE_EISOURCES) $(OSE_ERLSOURCES) - NEVERUSED = \ whereis.c \ ei_send.c \ @@ -532,13 +486,8 @@ ERLCALL = \ # Note that encode/decode_term.c defines ei functions that is # located in the erl_interface library, not ei library. -ifneq ($(findstring ose,$(TARGET)),ose) ST_EIOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) ST_ERLOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o))) -else -ST_EIOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(OSE_EISOURCES:.c=.o))) -ST_ERLOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(OSE_ERLSOURCES:.c=.o))) -endif MT_EIOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) MT_ERLOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o))) MD_EIOBJECTS = $(addprefix $(MD_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) @@ -587,14 +536,6 @@ $(TARGET)/config.h: $(V_at)echo "#define HAVE_SOCKLEN_T 1" >> $@ endif -ifeq ($(findstring ose,$(TARGET)),ose) -$(TARGET)/config.h: - $(gen_verbose) - $(V_at)echo "/* Generated by Makefile */" > $@ - $(V_at)echo "#define HAVE_STRERROR 1" >> $@ - $(V_at)echo "#define HAVE_SOCKLEN_T 1" >> $@ -endif - ########################################################################### # Default rules, normal and threaded ########################################################################### @@ -719,9 +660,6 @@ $(ST_OBJDIR)/erl_start.o: prog/erl_start.c $(V_CC) $(CFLAGS) -c $< -o $@ else -ifeq ($(findstring ose,$(TARGET)),ose) -$(ERL_CALL): -else ifdef THR_DEFS $(ERL_CALL): $(ERLCALL) ../include/ei.h $(MT_EILIB) $(ld_verbose)$(PURIFY) $(CC) $(PROG_CFLAGS) $(THR_DEFS) $(LDFLAGS) -o $@ $(ERLCALL) \ @@ -733,7 +671,6 @@ $(ERL_CALL): $(ERLCALL) ../include/ei.h $(ST_EILIB) endif endif endif -endif ########################################################################### # Fake application targets used to test header files and linking diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc index df716cdeea..2789a05792 100644 --- a/lib/eunit/doc/overview.edoc +++ b/lib/eunit/doc/overview.edoc @@ -885,7 +885,7 @@ the timeout is exceeded, the unfinished tests will be forced to terminate. Note that if a timeout is set around a fixture, it includes the time for setup and cleanup, and if the timeout is triggered, the entire fixture is abruptly terminated (without running the -cleanup).</dd> +cleanup). The default timeout for an individual test is 5 seconds.</dd> <dt>`{inorder, Tests}'</dt> <dd>Runs the specified tests in strict order. Also see `{inparallel, Tests}'. By default, tests are neither marked as `inorder' or diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml index d4ffb30967..3760e396ee 100644 --- a/lib/eunit/doc/src/notes.xml +++ b/lib/eunit/doc/src/notes.xml @@ -33,6 +33,21 @@ </header> <p>This document describes the changes made to the EUnit application.</p> +<section><title>Eunit 2.2.11</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Improve success message when 2 tests have passed</p> + <p> + Own Id: OTP-12952</p> + </item> + </list> + </section> + +</section> + <section><title>Eunit 2.2.10</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl index f3e58a3d1c..1b468551d8 100644 --- a/lib/eunit/src/eunit_surefire.erl +++ b/lib/eunit/src/eunit_surefire.erl @@ -56,7 +56,11 @@ { name :: chars(), description :: chars(), - result :: ok | {failed, tuple()} | {aborted, tuple()} | {skipped, term()}, + result :: ok + | {failed, tuple()} + | {aborted, tuple()} + | {skipped, term()} + | undefined, time :: integer(), output :: binary() }). diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk index 8b489bdc04..079520def2 100644 --- a/lib/eunit/vsn.mk +++ b/lib/eunit/vsn.mk @@ -1 +1 @@ -EUNIT_VSN = 2.2.10 +EUNIT_VSN = 2.2.11 diff --git a/lib/hipe/cerl/cerl_cconv.erl b/lib/hipe/cerl/cerl_cconv.erl index 0fc28be5f3..ac9d01ab0e 100644 --- a/lib/hipe/cerl/cerl_cconv.erl +++ b/lib/hipe/cerl/cerl_cconv.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -710,7 +710,7 @@ ren__new() -> ren__add(Key, Value, Ren) -> dict:store(Key, Value, Ren). -ren__map(Key, Ren) -> +ren__map(Key, Ren) -> case dict:find(Key, Ren) of {ok, Value} -> Value; @@ -722,11 +722,14 @@ ren__map(Key, Ren) -> %% --------------------------------------------------------------------- %% State --record(state, {module :: module(), function :: {atom(), arity()}, - names, refs, defs = []}). +-record(state, {module :: module(), + function :: {atom(), arity()} | 'undefined', + names = sets:new() :: sets:set(), %% XXX: refine + refs = dict:new() :: dict:dict(), %% XXX: refine + defs = []}). s__new(Module) -> - #state{module = Module, names = sets:new(), refs = dict:new()}. + #state{module = Module}. s__add_function_name(Name, S) -> S#state{names = sets:add_element(Name, S#state.names)}. diff --git a/lib/hipe/cerl/cerl_hipeify.erl b/lib/hipe/cerl/cerl_hipeify.erl index 8691e80cac..6611abd204 100644 --- a/lib/hipe/cerl/cerl_hipeify.erl +++ b/lib/hipe/cerl/cerl_hipeify.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2012. All Rights Reserved. +%% Copyright Ericsson AB 2003-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -623,12 +623,12 @@ ren__map(Key, Ren) -> %% --------------------------------------------------------------------- %% State -%% pmatch = 'true' | 'false' | 'no_duplicates' | 'duplicate_all' +-type pmatch() :: 'true' | 'false' | 'no_duplicates' | 'duplicate_all'. --record(state, {module::atom(), - function::{atom(), 0..256}, - pmatch=true, - revisit = false}). +-record(state, {module :: module(), + function :: {atom(), arity()} | 'undefined', + pmatch = true :: pmatch(), + revisit = false :: boolean()}). s__new(Module) -> #state{module = Module}. diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 5387edfb47..622c235638 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -46,7 +46,6 @@ t_bitstr/0, t_boolean/0, t_byte/0, - t_char/0, t_cons/0, t_cons/2, t_cons_hd/1, @@ -87,7 +86,6 @@ t_is_port/2, t_is_maybe_improper_list/2, t_is_reference/2, - t_is_string/1, t_is_subtype/2, t_is_tuple/2, t_list/0, @@ -552,9 +550,6 @@ type(erlang, bit_size, 1, Xs, Opaques) -> type(erlang, byte_size, 1, Xs, Opaques) -> strict(erlang, byte_size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques); -type(erlang, disconnect_node, 1, Xs, Opaques) -> - strict(erlang, disconnect_node, 1, Xs, - fun (_) -> t_sup([t_boolean(), t_atom('ignored')]) end, Opaques); %% Guard bif, needs to be here. %% Also much more expressive than anything you could write in a spec... type(erlang, element, 2, Xs, Opaques) -> @@ -583,16 +578,9 @@ type(erlang, element, 2, Xs, Opaques) -> %% Guard bif, needs to be here. type(erlang, float, 1, Xs, Opaques) -> strict(erlang, float, 1, Xs, fun (_) -> t_float() end, Opaques); -type(erlang, fun_info, 1, Xs, Opaques) -> - strict(erlang, fun_info, 1, Xs, - fun (_) -> t_list(t_tuple([t_atom(), t_any()])) end, Opaques); -type(erlang, get_cookie, 0, _, _Opaques) -> t_atom(); % | t_atom('nocookie') %% Guard bif, needs to be here. type(erlang, hd, 1, Xs, Opaques) -> strict(erlang, hd, 1, Xs, fun ([X]) -> t_cons_hd(X) end, Opaques); -type(erlang, integer_to_list, 2, Xs, Opaques) -> - strict(erlang, integer_to_list, 2, Xs, - fun (_) -> t_string() end, Opaques); type(erlang, info, 1, Xs, _) -> type(erlang, system_info, 1, Xs); % alias %% All type tests are guard BIF's and may be implemented in ways that %% cannot be expressed in a type spec, why they are kept in erl_bif_types. @@ -768,6 +756,18 @@ type(erlang, length, 1, Xs, Opaques) -> %% Guard bif, needs to be here. type(erlang, map_size, 1, Xs, Opaques) -> strict(erlang, map_size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques); +type(erlang, make_fun, 3, Xs, Opaques) -> + strict(erlang, make_fun, 3, Xs, + fun ([_, _, Arity]) -> + case t_number_vals(Arity, Opaques) of + [N] -> + case is_integer(N) andalso 0 =< N andalso N =< 255 of + true -> t_fun(N, t_any()); + false -> t_none() + end; + _Other -> t_fun() + end + end, Opaques); type(erlang, make_tuple, 2, Xs, Opaques) -> strict(erlang, make_tuple, 2, Xs, fun ([Int, _]) -> @@ -784,8 +784,6 @@ type(erlang, make_tuple, 3, Xs, Opaques) -> _Other -> t_tuple() end end, Opaques); -type(erlang, memory, 0, _, _Opaques) -> - t_list(t_tuple([t_atom(), t_non_neg_fixnum()])); type(erlang, nif_error, 1, Xs, Opaques) -> %% this BIF and the next one are stubs for NIFs and never return strict(erlang, nif_error, 1, Xs, fun (_) -> t_any() end, Opaques); @@ -801,8 +799,6 @@ type(erlang, round, 1, Xs, Opaques) -> strict(erlang, round, 1, Xs, fun (_) -> t_integer() end, Opaques); %% Guard bif, needs to be here. type(erlang, self, 0, _, _Opaques) -> t_pid(); -type(erlang, set_cookie, 2, Xs, Opaques) -> - strict(erlang, set_cookie, 2, Xs, fun (_) -> t_atom('true') end, Opaques); type(erlang, setelement, 3, Xs, Opaques) -> strict(erlang, setelement, 3, Xs, fun ([X1, X2, X3]) -> @@ -837,19 +833,7 @@ type(erlang, setelement, 3, Xs, Opaques) -> %% Guard bif, needs to be here. type(erlang, size, 1, Xs, Opaques) -> strict(erlang, size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques); -type(erlang, spawn, 1, Xs, Opaques) -> - strict(erlang, spawn, 1, Xs, fun (_) -> t_pid() end, Opaques); -type(erlang, spawn, 2, Xs, Opaques) -> - strict(erlang, spawn, 2, Xs, fun (_) -> t_pid() end, Opaques); -type(erlang, spawn, 4, Xs, Opaques) -> - strict(erlang, spawn, 4, Xs, fun (_) -> t_pid() end, Opaques); -type(erlang, spawn_link, 1, Xs, _) -> type(erlang, spawn, 1, Xs); % same -type(erlang, spawn_link, 2, Xs, _) -> type(erlang, spawn, 2, Xs); % same -type(erlang, spawn_link, 4, Xs, _) -> type(erlang, spawn, 4, Xs); % same type(erlang, subtract, 2, Xs, _Opaques) -> type(erlang, '--', 2, Xs); % alias -type(erlang, suspend_process, 1, Xs, Opaques) -> - strict(erlang, suspend_process, 1, Xs, - fun (_) -> t_atom('true') end, Opaques); type(erlang, system_info, 1, Xs, Opaques) -> strict(erlang, system_info, 1, Xs, fun ([Type]) -> @@ -914,8 +898,7 @@ type(erlang, system_info, 1, Xs, Opaques) -> t_list(t_pid()); ['os_type'] -> t_tuple([t_sup([t_atom('unix'), - t_atom('win32'), - t_atom('ose')]), + t_atom('win32')]), t_atom()]); ['os_version'] -> t_sup(t_tuple([t_non_neg_fixnum(), @@ -1003,10 +986,6 @@ type(erlang, tuple_to_list, 1, Xs, Opaques) -> end end end, Opaques); -type(erlang, yield, 0, _, _Opaques) -> t_atom('true'); -%%-- ets ---------------------------------------------------------------------- -type(ets, rename, 2, Xs, Opaques) -> - strict(ets, rename, 2, Xs, fun ([_, Name]) -> Name end, Opaques); %%-- hipe_bifs ---------------------------------------------------------------- type(hipe_bifs, add_ref, 2, Xs, Opaques) -> strict(hipe_bifs, add_ref, 2, Xs, fun (_) -> t_nil() end, Opaques); @@ -1666,25 +1645,6 @@ type(lists, zipwith3, 4, Xs, Opaques) -> fun ([F,_As,_Bs,_Cs]) -> t_sup(t_list(t_fun_range(F, Opaques)), t_nil()) end, Opaques); -%%-- string ------------------------------------------------------------------- -type(string, chars, 2, Xs, Opaques) -> % NOTE: added to avoid loss of info - strict(string, chars, 2, Xs, fun (_) -> t_string() end, Opaques); -type(string, chars, 3, Xs, Opaques) -> % NOTE: added to avoid loss of info - strict(string, chars, 3, Xs, - fun ([Char, N, Tail]) -> - case t_is_nil(Tail) of - true -> - type(string, chars, 2, [Char, N]); - false -> - case t_is_string(Tail) of - true -> - t_string(); - false -> - t_sup(t_sup(t_string(), Tail), t_cons(Char, Tail)) - end - end - end, Opaques); - %%----------------------------------------------------------------------------- type(M, F, A, Xs, _O) when is_atom(M), is_atom(F), is_integer(A), 0 =< A, A =< 255 -> @@ -2289,8 +2249,6 @@ arg_types(erlang, bit_size, 1) -> %% Guard bif, needs to be here. arg_types(erlang, byte_size, 1) -> [t_binary()]; -arg_types(erlang, disconnect_node, 1) -> - [t_node()]; arg_types(erlang, halt, 0) -> []; arg_types(erlang, halt, 1) -> @@ -2310,17 +2268,11 @@ arg_types(erlang, element, 2) -> %% Guard bif, needs to be here. arg_types(erlang, float, 1) -> [t_number()]; -arg_types(erlang, fun_info, 1) -> - [t_fun()]; -arg_types(erlang, get_cookie, 0) -> - []; %% Guard bif, needs to be here. arg_types(erlang, hd, 1) -> [t_cons()]; arg_types(erlang, info, 1) -> arg_types(erlang, system_info, 1); % alias -arg_types(erlang, integer_to_list, 2) -> - [t_integer(), t_from_range(2, 36)]; arg_types(erlang, is_atom, 1) -> [t_any()]; arg_types(erlang, is_binary, 1) -> @@ -2361,12 +2313,12 @@ arg_types(erlang, length, 1) -> %% Guard bif, needs to be here. arg_types(erlang, map_size, 1) -> [t_map()]; +arg_types(erlang, make_fun, 3) -> + [t_atom(), t_atom(), t_arity()]; arg_types(erlang, make_tuple, 2) -> [t_non_neg_fixnum(), t_any()]; % the value 0 is OK as first argument arg_types(erlang, make_tuple, 3) -> [t_non_neg_fixnum(), t_any(), t_list(t_tuple([t_pos_integer(), t_any()]))]; -arg_types(erlang, memory, 0) -> - []; arg_types(erlang, nif_error, 1) -> [t_any()]; arg_types(erlang, nif_error, 2) -> @@ -2383,29 +2335,13 @@ arg_types(erlang, round, 1) -> %% Guard bif, needs to be here. arg_types(erlang, self, 0) -> []; -arg_types(erlang, set_cookie, 2) -> - [t_node(), t_atom()]; arg_types(erlang, setelement, 3) -> [t_pos_integer(), t_tuple(), t_any()]; %% Guard bif, needs to be here. arg_types(erlang, size, 1) -> [t_sup(t_tuple(), t_binary())]; -arg_types(erlang, spawn, 1) -> %% TODO: Tuple? - [t_fun()]; -arg_types(erlang, spawn, 2) -> %% TODO: Tuple? - [t_node(), t_fun()]; -arg_types(erlang, spawn, 4) -> %% TODO: Tuple? - [t_node(), t_atom(), t_atom(), t_list()]; -arg_types(erlang, spawn_link, 1) -> - arg_types(erlang, spawn, 1); % same -arg_types(erlang, spawn_link, 2) -> - arg_types(erlang, spawn, 2); % same -arg_types(erlang, spawn_link, 4) -> - arg_types(erlang, spawn, 4); % same arg_types(erlang, subtract, 2) -> arg_types(erlang, '--', 2); -arg_types(erlang, suspend_process, 1) -> - [t_pid()]; arg_types(erlang, system_info, 1) -> [t_sup([t_atom(), % documented t_tuple([t_atom(), t_any()]), % documented @@ -2424,11 +2360,6 @@ arg_types(erlang, tuple_size, 1) -> [t_tuple()]; arg_types(erlang, tuple_to_list, 1) -> [t_tuple()]; -arg_types(erlang, yield, 0) -> - []; -%%------- ets ----------------------------------------------------------------- -arg_types(ets, rename, 2) -> - [t_atom(), t_atom()]; %%------- hipe_bifs ----------------------------------------------------------- arg_types(hipe_bifs, add_ref, 2) -> [t_mfa(), t_tuple([t_mfa(), @@ -2625,13 +2556,6 @@ arg_types(lists, zipwith, 3) -> [t_fun([t_any(), t_any()], t_any()), t_list(), t_list()]; arg_types(lists, zipwith3, 4) -> [t_fun([t_any(), t_any(), t_any()], t_any()), t_list(), t_list(), t_list()]; - -%%------- string -------------------------------------------------------------- -arg_types(string, chars, 2) -> - [t_char(), t_non_neg_integer()]; -arg_types(string, chars, 3) -> - [t_char(), t_non_neg_integer(), t_any()]; -%%----------------------------------------------------------------------------- arg_types(M, F, A) when is_atom(M), is_atom(F), is_integer(A), 0 =< A, A =< 255 -> unknown. % safe approximation for all functions. diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index cd2d2fe207..420d7e2a8f 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -3974,18 +3974,17 @@ record_to_string(Tag, [_|Fields], FieldNames, RecDict) -> FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []), "#" ++ atom_to_string(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}". -record_fields_to_string([F|Fs], [{FName, _Abstr, _DefType}|FDefs], +record_fields_to_string([F|Fs], [{FName, _Abstr, DefType}|FDefs], RecDict, Acc) -> NewAcc = - case t_is_equal(F, t_any()) orelse t_is_any_atom('undefined', F) of + case + t_is_equal(F, t_any()) orelse + (t_is_any_atom('undefined', F) andalso + not t_is_none(t_inf(F, DefType))) + of true -> Acc; false -> StrFV = atom_to_string(FName) ++ "::" ++ t_to_string(F, RecDict), - %% ActualDefType = t_subtract(DefType, t_atom('undefined')), - %% Str = case t_is_any(ActualDefType) of - %% true -> StrFV; - %% false -> StrFV ++ "::" ++ t_to_string(ActualDefType, RecDict) - %% end, [StrFV|Acc] end, record_fields_to_string(Fs, FDefs, RecDict, NewAcc); diff --git a/lib/hipe/doc/src/hipe_app.xml b/lib/hipe/doc/src/hipe_app.xml index 98fec900af..bf4bdbb3b3 100644 --- a/lib/hipe/doc/src/hipe_app.xml +++ b/lib/hipe/doc/src/hipe_app.xml @@ -37,15 +37,14 @@ <description> <p> The normal way to native-compile an Erlang module using HiPE is to include the atom native - in the Erlang compiler options, as in: - <code> - 1> <input>c(my_module, [native]).</input></code> - Options to the HiPE compiler are then passed as follows: - <code> - 1> <input>c(my_module, [native,{hipe,Options}]).</input></code> - For on-line help in the Erlang shell, call <c>hipe:help()</c>. - Details on HiPE compiler options are given by <c>hipe:help_options()</c>. - </p> + in the Erlang compiler options, as in:</p> + <pre> + 1> <input>c(my_module, [native]).</input></pre> + <p>Options to the HiPE compiler are then passed as follows:</p> + <pre> + 1> <input>c(my_module, [native,{hipe,Options}]).</input></pre> + <p>For on-line help in the Erlang shell, call <c>hipe:help()</c>. + Details on HiPE compiler options are given by <c>hipe:help_options()</c>.</p> </description> <section> <title>SEE ALSO</title> diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index 33a18ff7ef..e1aec698e4 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -31,6 +31,50 @@ </header> <p>This document describes the changes made to HiPE.</p> +<section><title>Hipe 3.13</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> Fix bugs concerning <c>erlang:abs/1</c>. </p> + <p> + Own Id: OTP-12948</p> + </item> + <item> + <p> Fix a bug concerning <c>lists:keydelete/3</c> with + union and opaque types. </p> + <p> + Own Id: OTP-12949</p> + </item> + <item> + <p> + A beam file compiled by hipe for an incompatible runtime + system was sometimes not rejected by the loader, which + could lead to vm crash. This fix will also allow the same + hipe compiler to be used by both normal and debug-built + vm.</p> + <p> + Own Id: OTP-12962</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + New function <c>hipe:erts_checksum/0</c> which returns a + value identifying the target runtime system for the + compiler. Used by dialyzer for its beam cache directory.</p> + <p> + Own Id: OTP-12963 Aux Id: OTP-12962, OTP-12964 </p> + </item> + </list> + </section> + +</section> + <section><title>Hipe 3.12</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -275,22 +319,28 @@ <p> EEP43: New data type - Maps</p> <p> - With Maps you may for instance: <taglist> <item><c>M0 = - #{ a => 1, b => 2}, % create - associations</c></item> <item><c>M1 = M0#{ a := 10 }, % - update values</c></item> <item><c>M2 = M1#{ "hi" => - "hello"}, % add new associations</c></item> <item><c>#{ - "hi" := V1, a := V2, b := V3} = M2. % match keys with - values</c></item> </taglist></p> + With Maps you may for instance:</p> + <taglist> + <tag/> <item><c>M0 = #{ a => 1, b => 2}, % create + associations</c></item> + <tag/><item><c>M1 = M0#{ a := 10 }, % update values</c></item> + <tag/><item><c>M2 = M1#{ "hi" => + "hello"}, % add new associations</c></item> + <tag/><item><c>#{ "hi" := V1, a := V2, b := V3} = M2. + % match keys with values</c></item> + </taglist> <p> For information on how to use Maps please see Map Expressions in the <seealso marker="doc/reference_manual:expressions#map_expressions"> Reference Manual</seealso>.</p> <p> The current implementation is without the following - features: <taglist> <item>No variable keys</item> - <item>No single value access</item> <item>No map - comprehensions</item> </taglist></p> + features:</p> + <taglist> + <tag/><item>No variable keys</item> + <tag/><item>No single value access</item> + <tag/><item>No map comprehensions</item> + </taglist> <p> Note that Maps is <em>experimental</em> during OTP 17.0.</p> <p> @@ -558,19 +608,17 @@ <section><title>Fixed Bugs and Malfunctions</title> <list> <item> - <p> <list> <item><p>No warnings for underspecs with remote types</p></item> <item><p> Fix crash in Typer</p></item> <item><p>Fix Dialyzer's warning for its own code</p></item> <item><p>Fix Dialyzer's warnings in HiPE</p></item> <item><p>Add file/line info in a particular Dialyzer crash</p></item> <item><p>Update - inets test results</p></item> </list></p> + inets test results</p></item> </list> <p> Own Id: OTP-9758</p> </item> <item> - <p> <list> <item><p>Correct callback spec in application module</p></item> <item><p>Refine warning about callback specs with extra ranges</p></item> <item><p>Cleanup @@ -581,7 +629,7 @@ analysis</p></item> <item><p>Fix crash in Dialyzer</p></item> <item><p>Variable substitution was not generalizing any unknown variables.</p></item> - </list></p> + </list> <p> Own Id: OTP-9776</p> </item> diff --git a/lib/hipe/flow/cfg.hrl b/lib/hipe/flow/cfg.hrl index f79fff4efe..641ec102db 100644 --- a/lib/hipe/flow/cfg.hrl +++ b/lib/hipe/flow/cfg.hrl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2014. All Rights Reserved. +%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -34,11 +34,13 @@ %% -record(cfg_info, {'fun' :: mfa(), start_label :: cfg_lbl(), + %% TODO: merge is_closure and closure_arity into one field is_closure :: boolean(), - closure_arity :: arity(), + closure_arity = none :: 'none' | arity(), is_leaf :: boolean(), params, % :: list() info = []}). %% this field seems not needed; take out?? +-type cfg_info() :: #cfg_info{}. %% %% Data is a triple with a dict of constants, a list of labels and an integer @@ -49,6 +51,6 @@ %% The following is to be used by other modules %% -record(cfg, {table = gb_trees:empty() :: gb_trees:tree(), - info :: #cfg_info{}, + info :: cfg_info(), data :: cfg_data()}). -type cfg() :: #cfg{}. diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl index 5c7003b0ed..9692eebb10 100644 --- a/lib/hipe/icode/hipe_icode.erl +++ b/lib/hipe/icode/hipe_icode.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -631,59 +631,59 @@ mk_icode(Fun, Params, IsClosure, IsLeaf, Code, VarRange, LabelRange) -> -spec mk_icode(mfa(), [icode_var()], boolean(), boolean(), [icode_instr()], hipe_consttab(), {non_neg_integer(),non_neg_integer()}, - {icode_lbl(),icode_lbl()}) -> #icode{}. + {icode_lbl(),icode_lbl()}) -> icode(). mk_icode(Fun, Params, IsClosure, IsLeaf, Code, Data, VarRange, LabelRange) -> #icode{'fun'=Fun, params=Params, code=Code, data=Data, is_closure=IsClosure, is_leaf=IsLeaf, var_range=VarRange, label_range=LabelRange}. --spec icode_fun(#icode{}) -> mfa(). +-spec icode_fun(icode()) -> mfa(). icode_fun(#icode{'fun' = MFA}) -> MFA. --spec icode_params(#icode{}) -> [icode_var()]. +-spec icode_params(icode()) -> [icode_var()]. icode_params(#icode{params = Params}) -> Params. --spec icode_params_update(#icode{}, [icode_var()]) -> #icode{}. +-spec icode_params_update(icode(), [icode_var()]) -> icode(). icode_params_update(Icode, Params) -> Icode#icode{params = Params}. --spec icode_is_closure(#icode{}) -> boolean(). +-spec icode_is_closure(icode()) -> boolean(). icode_is_closure(#icode{is_closure = Closure}) -> Closure. --spec icode_is_leaf(#icode{}) -> boolean(). +-spec icode_is_leaf(icode()) -> boolean(). icode_is_leaf(#icode{is_leaf = Leaf}) -> Leaf. --spec icode_code(#icode{}) -> icode_instrs(). +-spec icode_code(icode()) -> icode_instrs(). icode_code(#icode{code = Code}) -> Code. --spec icode_code_update(#icode{}, icode_instrs()) -> #icode{}. +-spec icode_code_update(icode(), icode_instrs()) -> icode(). icode_code_update(Icode, NewCode) -> Vmax = highest_var(NewCode), Lmax = highest_label(NewCode), Icode#icode{code = NewCode, var_range = {0,Vmax}, label_range = {0,Lmax}}. --spec icode_data(#icode{}) -> hipe_consttab(). +-spec icode_data(icode()) -> hipe_consttab(). icode_data(#icode{data=Data}) -> Data. -%% %% -spec icode_data_update(#icode{}, hipe_consttab()) -> #icode{}. +%% %% -spec icode_data_update(icode(), hipe_consttab()) -> icode(). %% icode_data_update(Icode, NewData) -> Icode#icode{data=NewData}. --spec icode_var_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}. +-spec icode_var_range(icode()) -> {non_neg_integer(), non_neg_integer()}. icode_var_range(#icode{var_range = VarRange}) -> VarRange. --spec icode_label_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}. +-spec icode_label_range(icode()) -> {non_neg_integer(), non_neg_integer()}. icode_label_range(#icode{label_range = LabelRange}) -> LabelRange. --spec icode_info(#icode{}) -> icode_info(). +-spec icode_info(icode()) -> icode_info(). icode_info(#icode{info = Info}) -> Info. --spec icode_info_update(#icode{}, icode_info()) -> #icode{}. +-spec icode_info_update(icode(), icode_info()) -> icode(). icode_info_update(Icode, Info) -> Icode#icode{info = Info}. --spec icode_closure_arity(#icode{}) -> arity(). +-spec icode_closure_arity(icode()) -> arity(). icode_closure_arity(#icode{closure_arity = Arity}) -> Arity. --spec icode_closure_arity_update(#icode{}, arity()) -> #icode{}. +-spec icode_closure_arity_update(icode(), arity()) -> icode(). icode_closure_arity_update(Icode, Arity) -> Icode#icode{closure_arity = Arity}. @@ -1709,7 +1709,7 @@ mk_new_label() -> %% @doc Removes comments from Icode. %% --spec strip_comments(#icode{}) -> #icode{}. +-spec strip_comments(icode()) -> icode(). strip_comments(ICode) -> icode_code_update(ICode, no_comments(icode_code(ICode))). diff --git a/lib/hipe/icode/hipe_icode.hrl b/lib/hipe/icode/hipe_icode.hrl index 9b24c4914e..3bb7bae019 100644 --- a/lib/hipe/icode/hipe_icode.hrl +++ b/lib/hipe/icode/hipe_icode.hrl @@ -170,8 +170,9 @@ -record(icode, {'fun' :: mfa(), params :: [icode_var()], + %% TODO: merge is_closure and closure_arity into one field is_closure :: boolean(), - closure_arity :: arity(), + closure_arity = none :: 'none' | arity(), is_leaf :: boolean(), code = [] :: icode_instrs(), data :: hipe_consttab(), diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl index 41556ab80f..f03ce2faaa 100644 --- a/lib/hipe/icode/hipe_icode_exceptions.erl +++ b/lib/hipe/icode/hipe_icode_exceptions.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2014. All Rights Reserved. +%% Copyright Ericsson AB 2004-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -85,7 +85,7 @@ %%---------------------------------------------------------------------------- --spec fix_catches(#cfg{}) -> #cfg{}. +-spec fix_catches(cfg()) -> cfg(). fix_catches(CFG) -> {Map, State} = build_mapping(find_catches(init_state(CFG))), @@ -393,10 +393,10 @@ get_renaming(C, Map) -> %%--------------------------------------------------------------------- %% State abstraction --record(state, {cfg :: #cfg{}, +-record(state, {cfg :: cfg(), changed = false :: boolean(), - succ :: #cfg{}, - pred :: #cfg{}, + succ :: cfg(), + pred :: cfg(), start_labels :: [icode_lbl(),...], visited = hipe_icode_cfg:none_visited() :: gb_sets:set(), out = gb_trees:empty() :: gb_trees:tree(), @@ -404,13 +404,8 @@ get_renaming(C, Map) -> }). init_state(CFG) -> - State = #state{cfg = CFG}, - refresh_state_cache(State). - -refresh_state_cache(State) -> - CFG = State#state.cfg, SLs = [hipe_icode_cfg:start_label(CFG)], - State#state{succ = CFG, pred = CFG, start_labels = SLs}. + #state{cfg = CFG, succ = CFG, pred = CFG, start_labels = SLs}. get_cfg(State) -> State#state.cfg. @@ -466,7 +461,8 @@ get_bb_code(L, State) -> set_bb_code(L, Code, State) -> CFG = State#state.cfg, CFG1 = hipe_icode_cfg:bb_add(CFG, L, hipe_bb:mk_bb(Code)), - refresh_state_cache(State#state{cfg = CFG1}). + SLs = [hipe_icode_cfg:start_label(CFG1)], + State#state{cfg = CFG1, succ = CFG1, pred = CFG1, start_labels = SLs}. get_new_catches_in(L, State) -> Ps = get_pred(L, State), diff --git a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl index e350a6ff18..7613024787 100644 --- a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl +++ b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2014. All Rights Reserved. +%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -314,7 +314,7 @@ node_create(Label, Pred, Succ) -> %% tree - the tree of nodes, with labels as keys and node records as values -record(nodes, { - domtree :: hipe_dominators:domTree(), + domtree = none :: 'none' | hipe_dominators:domTree(), labels = none :: 'none' | [icode_lbl()], postorder = none :: 'none' | [icode_lbl()], start_label = none :: 'none' | icode_lbl(), @@ -390,7 +390,7 @@ update_del_red_test_set(Update) -> %%----------------------------------------------------------------------------- %% Main function called from the hipe_main module --spec struct_reuse(#cfg{}) -> #cfg{}. +-spec struct_reuse(cfg()) -> cfg(). struct_reuse(CFG) -> %% debug_init_case_count(?SR_INSTR_TYPE), diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index 1a4bbf179f..0e32da1d36 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -764,7 +764,8 @@ finalize(OrigList, Mod, Exports, WholeModule, Opts) -> finalize_fun(MfaIcodeList, Exports, Opts) -> case proplists:get_value(concurrent_comp, Opts) of FalseVal when (FalseVal =:= undefined) orelse (FalseVal =:= false) -> - [finalize_fun_sequential(MFAIcode, Opts, #comp_servers{}) + NoServers = #comp_servers{pp_server = none, range = none, type = none}, + [finalize_fun_sequential(MFAIcode, Opts, NoServers) || {_MFA, _Icode} = MFAIcode <- MfaIcodeList]; TrueVal when (TrueVal =:= true) orelse (TrueVal =:= debug) -> finalize_fun_concurrent(MfaIcodeList, Exports, Opts) diff --git a/lib/hipe/main/hipe.hrl.src b/lib/hipe/main/hipe.hrl.src index ba27878a84..3be824ac34 100644 --- a/lib/hipe/main/hipe.hrl.src +++ b/lib/hipe/main/hipe.hrl.src @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -299,7 +299,8 @@ %% Records defined in the hipe module used in other parts of the compiler %%---------------------------------------------------------------------------- --record(comp_servers, {pp_server :: pid(), range :: pid(), type :: pid()}). +-type mpid() :: 'none' | pid(). +-record(comp_servers, {pp_server :: mpid(), range :: mpid(), type :: mpid()}). %%---------------------------------------------------------------------------- %% Basic types of the 'hipe' application used in other parts of the system diff --git a/lib/hipe/main/hipe_main.erl b/lib/hipe/main/hipe_main.erl index 5753169961..be5050e155 100644 --- a/lib/hipe/main/hipe_main.erl +++ b/lib/hipe/main/hipe_main.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -55,7 +55,7 @@ %%===================================================================== %% @spec compile_icode(MFA::mfa(), -%% LinearIcode::#icode{}, +%% LinearIcode::icode(), %% CompilerOptions::comp_options(), %% CompServers::#comp_servers()) -> %% {native,Platform,{unprofiled,NativeCode}} | {rtl,RTLCode} @@ -69,7 +69,7 @@ %% generated). The compiler options must have already been expanded %% (cf. `<a href="hipe.html">hipe:expand_options</a>'). </p> --spec compile_icode(mfa(), #icode{}, comp_options(), #comp_servers{}) -> +-spec compile_icode(mfa(), icode(), comp_options(), #comp_servers{}) -> comp_icode_ret(). compile_icode(MFA, LinearIcode, Options, Servers) -> @@ -230,10 +230,12 @@ get_pp_module(icode_liveness) -> hipe_icode_liveness; get_pp_module(rtl_liveness) -> hipe_rtl_liveness. perform_io(no_fun, _) -> ok; -perform_io(Fun,PPServer) when is_pid(PPServer) -> - PPServer ! {print,Fun}; -perform_io(Fun, undefined) -> - Fun(). +perform_io(Fun, PPServer) when is_pid(PPServer) -> + PPServer ! {print, Fun}, + ok; +perform_io(Fun, none) -> + Fun(), + ok. %%-------------------------------------------------------------------- diff --git a/lib/hipe/rtl/hipe_rtl_binary_construct.erl b/lib/hipe/rtl/hipe_rtl_binary_construct.erl index 40bd22aa8e..692bad7d96 100644 --- a/lib/hipe/rtl/hipe_rtl_binary_construct.erl +++ b/lib/hipe/rtl/hipe_rtl_binary_construct.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1192,7 +1192,10 @@ copy_little_word(Base, Offset, NewOffset, Word) -> hipe_rtl:mk_store(Base, TmpOffset, Word, byte), hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(32))]. -copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) -> +copy_offset_int_big(_Base, Offset, NewOffset, 0, _Tmp1) -> + [hipe_rtl:mk_move(NewOffset, Offset)]; +copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) + when is_integer(Size), Size > 0 -> Tmp2 = hipe_rtl:mk_new_reg(), Tmp3 = hipe_rtl:mk_new_reg(), Tmp4 = hipe_rtl:mk_new_reg(), @@ -1203,7 +1206,7 @@ copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) - Tmp9 = hipe_rtl:mk_new_reg(), OldByte = hipe_rtl:mk_new_reg(), TmpOffset = hipe_rtl:mk_new_reg(), - BranchLbl = hipe_rtl:mk_new_label(), + BranchLbl = hipe_rtl:mk_new_label(), BodyLbl = hipe_rtl:mk_new_label(), EndLbl = hipe_rtl:mk_new_label(), NextLbl = hipe_rtl:mk_new_label(), diff --git a/lib/hipe/test/bs_SUITE_data/bs_construct.erl b/lib/hipe/test/bs_SUITE_data/bs_construct.erl index 9cc9ac848c..37a54c1981 100644 --- a/lib/hipe/test/bs_SUITE_data/bs_construct.erl +++ b/lib/hipe/test/bs_SUITE_data/bs_construct.erl @@ -13,6 +13,7 @@ test() -> ok = bs5(), 16#10000008 = bit_size(large_bin(1, 2, 3, 4)), ok = bad_ones(), + ok = zero_width(), ok. %%-------------------------------------------------------------------- @@ -126,3 +127,18 @@ bad_ones() -> Bin123 = <<1,2,3>>, ?FAIL(<<Bin123/float>>), ok. + +%%-------------------------------------------------------------------- +%% Taken from the emulator bs_construct_SUITE - seg faulted till 18.1 + +zero_width() -> + Z = id(0), + Small = id(42), + Big = id(1 bsl 128), % puts stuff on the heap + <<>> = <<Small:Z>>, + <<>> = <<Small:0>>, + <<>> = <<Big:Z>>, + <<>> = <<Big:0>>, + ok. + +id(X) -> X. diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index e507ae933f..3ec9d7ee45 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.12 +HIPE_VSN = 3.13 diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile index a0a3472c4a..cb71fbeb9c 100644 --- a/lib/inets/doc/src/Makefile +++ b/lib/inets/doc/src/Makefile @@ -52,7 +52,6 @@ XML_REF3_FILES = \ http_uri.xml\ httpc.xml\ httpd.xml \ - httpd_conf.xml \ httpd_custom_api.xml \ httpd_socket.xml \ httpd_util.xml \ diff --git a/lib/inets/doc/src/ftp.xml b/lib/inets/doc/src/ftp.xml index f3d4a5c45d..f64bc0e18b 100644 --- a/lib/inets/doc/src/ftp.xml +++ b/lib/inets/doc/src/ftp.xml @@ -30,95 +30,94 @@ <file>ftp.xml</file> </header> <module>ftp</module> - <modulesummary>A File Transfer Protocol client</modulesummary> + <modulesummary>A File Transfer Protocol client.</modulesummary> <description> - <p>The <c>ftp</c> module implements a client for file transfer - according to a subset of the File Transfer Protocol (see <term - id="RFC"></term>959). </p> + <p>This module implements a client for file transfer + according to a subset of the File Transfer Protocol (FTP), see + <url href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</url>.</p> - <p>Starting from inets version 4.4.1 the ftp - client will always try to use passive ftp mode and only resort - to active ftp mode if this fails. There is a start option - <seealso marker="#mode">mode</seealso> where this default behavior - may be changed. </p> + <p>As from <c>Inets</c> 4.4.1, the FTP + client always tries to use passive FTP mode and only resort + to active FTP mode if this fails. This default behavior can be + changed by start option <seealso marker="#mode">mode</seealso>.</p> <marker id="two_start"></marker> - <p>There are two ways to start an ftp client. One is using the - <seealso marker="#service_start">Inets service framework</seealso> - and the other is to start it directy as a standalone process - using the <seealso marker="#open">open</seealso> function. </p> + <p>An FTP client can be started in two ways. One is using the + <seealso marker="#service_start">Inets service framework</seealso>, + the other is to start it directly as a standalone process + using function <seealso marker="#open">open</seealso>.</p> - <p>For a simple example of an ftp session see - <seealso marker="ftp_client">Inets User's Guide.</seealso></p> + <p>For a simple example of an FTP session, see + <seealso marker="ftp_client">Inets User's Guide</seealso>.</p> <p>In addition to the ordinary functions for receiving and sending - files (see <c>recv/2</c>, <c>recv/3</c>, <c>send/2</c> and + files (see <c>recv/2</c>, <c>recv/3</c>, <c>send/2</c>, and <c>send/3</c>) there are functions for receiving remote files as - binaries (see <c>recv_bin/2</c>) and for sending binaries to to be + binaries (see <c>recv_bin/2</c>) and for sending binaries to be stored as remote files (see <c>send_bin/3</c>).</p> - <p>There is also a set of functions for sending and receiving - contiguous parts of a file to be stored in a remote file (for send - see <c>send_chunk_start/2</c>, <c>send_chunk/2</c> and - <c>send_chunk_end/1</c> and for receive see + <p>A set of functions is provvided for sending and receiving + contiguous parts of a file to be stored in a remote file. For send, + see <c>send_chunk_start/2</c>, <c>send_chunk/2</c>, and + <c>send_chunk_end/1</c>. For receive, see <c>recv_chunk_start/2</c> and <c>recv_chunk/</c>).</p> - <p>The particular return values of the functions below depend very + <p>The return values of the following functions depend much on the implementation of the FTP server at the remote - host. In particular the results from <c>ls</c> and <c>nlist</c> + host. In particular, the results from <c>ls</c> and <c>nlist</c> varies. Often real errors are not reported as errors by <c>ls</c>, - even if for instance a file or directory does not + even if, for example, a file or directory does not exist. <c>nlist</c> is usually more strict, but some implementations have the peculiar behaviour of responding with an - error, if the request is a listing of the contents of directory - which exists but is empty.</p> + error if the request is a listing of the contents of a directory + that exists but is empty.</p> <marker id="service_start"></marker> </description> <section> - <title>FTP CLIENT SERVICE START/STOP </title> + <title>FTP CLIENT SERVICE START/STOP</title> <p>The FTP client can be started and stopped dynamically in runtime by - calling the Inets application API + calling the <c>Inets</c> application API <c>inets:start(ftpc, ServiceConfig)</c>, or <c>inets:start(ftpc, ServiceConfig, How)</c>, and <c>inets:stop(ftpc, Pid)</c>. - See <seealso marker="inets">inets(3)</seealso> for more info. </p> - <p>Below follows a description of - the available configuration options.</p> + For details, see <seealso marker="inets">inets(3)</seealso>.</p> + + <p>The available configuration options are as follows:</p> <taglist> <tag>{host, Host}</tag> <item> <marker id="host"></marker> - <p>Host = <c>string() | ip_address()</c> </p> + <p>Host = <c>string() | ip_address()</c></p> </item> <tag>{port, Port}</tag> <item> <marker id="port"></marker> - <p>Port = <c>integer() > 0</c> </p> - <p>Default is 21.</p> + <p>Port = <c>integer() > 0</c></p> + <p>Default is <c>21</c>.</p> </item> <tag>{mode, Mode}</tag> <item> <marker id="mode"></marker> - <p>Mode = <c>active | passive</c> </p> - <p>Default is <c>passive</c>. </p> + <p>Mode = <c>active | passive</c></p> + <p>Default is <c>passive</c>.</p> </item> <tag>{verbose, Verbose}</tag> <item> <marker id="verbose"></marker> <p>Verbose = <c>boolean()</c> </p> - <p>This determines if the FTP communication should be - verbose or not. </p> - <p>Default is <c>false</c>. </p> + <p>Determines if the FTP communication is to be + verbose or not.</p> + <p>Default is <c>false</c>.</p> </item> <tag>{debug, Debug}</tag> @@ -126,93 +125,90 @@ <marker id="debug"></marker> <p>Debug = <c>trace | debug | disable</c> </p> <p>Debugging using the dbg toolkit. </p> - <p>Default is <c>disable</c>. </p> + <p>Default is <c>disable</c>.</p> </item> <tag>{ipfamily, IpFamily}</tag> <item> <marker id="ipfamily"></marker> <p>IpFamily = <c>inet | inet6 | inet6fb4</c> </p> - <p>With <c>inet6fb4</c> the client behaves as before - (it tries to use IPv6 and only if that does not work, it - uses IPv4). </p> - <p>Default is <c>inet</c> (IPv4). </p> + <p>With <c>inet6fb4</c> the client behaves as before, that is, + tries to use IPv6, and only if that does not work it + uses IPv4).</p> + <p>Default is <c>inet</c> (IPv4).</p> </item> <tag>{timeout, Timeout}</tag> <item> <marker id="timeout"></marker> - <p>Timeout = <c>non_neg_integer()</c> </p> - <p>Connection timeout. </p> - <p>Default is 60000 (milliseconds). </p> + <p>Timeout = <c>non_neg_integer()</c></p> + <p>Connection time-out.</p> + <p>Default is <c>60000</c> (milliseconds).</p> </item> <tag>{dtimeout, DTimeout}</tag> <item> <marker id="dtimeout"></marker> <p>DTimeout = <c>non_neg_integer() | infinity</c> </p> - <p>Data Connect timeout. - The time the client will wait for the server to connect to the - data socket. </p> - <p>Default is infinity. </p> + <p>Data connect time-out. + The time the client waits for the server to connect to the + data socket.</p> + <p>Default is <c>infinity</c>. </p> </item> <tag>{progress, Progress}</tag> <item> <marker id="progress"></marker> <p>Progress = <c>ignore | {CBModule, CBFunction, InitProgress}</c></p> - <p>CBModule = <c>atom()</c>, CBFunction = <c>atom()</c> </p> - <p>InitProgress = <c>term()</c> </p> - <p>Default is <c>ignore</c>. </p> + <p><c>CBModule = atom()</c>, <c>CBFunction = atom()</c></p> + <p><c>InitProgress = term()</c></p> + <p>Default is <c>ignore</c>.</p> </item> </taglist> - <p>The progress option is intended to be used by applications that - want to create some type of progress report such as a progress bar in - a GUI. The default value for the progress option is ignore - e.i. the option is not used. When the progress option is - specified the following will happen when ftp:send/[3,4] or - ftp:recv/[3,4] are called.</p> + <p>Option <c>progress</c> is intended to be used by applications that + want to create some type of progress report, such as a progress bar in + a GUI. Default for the progress option is <c>ignore</c>, + that is, the option is not used. When the progress option is + specified, the following happens when <c>ftp:send/[3,4]</c> or + <c>ftp:recv/[3,4]</c> are called:</p> <list type="bulleted"> <item> - <p>Before a file is transfered the following call will - be made to indicate the start of the file transfer and how big + <p>Before a file is transferred, the following call is + made to indicate the start of the file transfer and how large the file is. The return value of the callback function - should be a new value for the UserProgressTerm that will - bu used as input next time the callback function is + is to be a new value for the <c>UserProgressTerm</c> that will + be used as input the next time the callback function is called.</p> - <br></br> <p><c> CBModule:CBFunction(InitProgress, File, {file_size, FileSize}) </c></p> - <br></br> </item> <item> - <p>Every time a chunk of bytes is transfered the - following call will be made:</p> - <br></br> + <p>Every time a chunk of bytes is transferred the + following call is made:</p> <p><c> - CBModule:CBFunction(UserProgressTerm, File, {transfer_size, TransferSize}) </c></p> - <br></br> + CBModule:CBFunction(UserProgressTerm, File, {transfer_size, TransferSize}) + </c></p> </item> <item> - <p>At the end of the file the following call will be - made to indicate the end of the transfer.</p> - <br></br> + <p>At the end of the file the following call is + made to indicate the end of the transfer:</p> <p><c> - CBModule:CBFunction(UserProgressTerm, File, {transfer_size, 0}) </c></p> - <br></br> + CBModule:CBFunction(UserProgressTerm, File, {transfer_size, 0}) + </c></p> </item> </list> - <p>The callback function should be defined as </p> + <p>The callback function is to be defined as follows:</p> <p><c> - CBModule:CBFunction(UserProgressTerm, File, Size) -> UserProgressTerm </c></p> + CBModule:CBFunction(UserProgressTerm, File, Size) -> UserProgressTerm + </c></p> <p><c> CBModule = CBFunction = atom() @@ -227,50 +223,51 @@ </c></p> <p><c> - Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown} </c></p> + Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown} + </c></p> - <p>Alas for remote files it is not possible for ftp to determine the + <p>For remote files, <c>ftp</c> cannot determine the file size in a platform independent way. In this case the size - will be <c>unknown</c> and it is left to the application to find - out the size. </p> + becomes <c>unknown</c> and it is left to the application to + determine the size.</p> <note> <p>The callback is made by a middleman process, hence the - file transfer will not be affected by the code in the progress - callback function. If the callback should crash this will be - detected by the ftp connection process that will print an - info-report and then go one as if the progress option was set - to ignore. </p> + file transfer is not affected by the code in the progress + callback function. If the callback crashes, this is + detected by the FTP connection process, which then prints an + info-report and goes on as if the progress option was set + to <c>ignore</c>.</p> </note> <p>The file transfer type is set to the default of the FTP server - when the session is opened. This is usually ASCCI-mode. + when the session is opened. This is usually ASCCI mode. </p> - <p>The current local working directory (cf. <c>lpwd/1</c>) is set to - the value reported by <c>file:get_cwd/1</c>. the wanted + <p>The current local working directory (compare <c>lpwd/1</c>) is set + to the value reported by <c>file:get_cwd/1</c>, the wanted local directory. </p> <p>The return value <c>Pid</c> is used as a reference to the - newly created ftp client in all other functions, and they should - be called by the process that created the connection. The ftp + newly created FTP client in all other functions, and they are to + be called by the process that created the connection. The FTP client process monitors the process that created it and - will terminate if that process terminates.</p> + terminates if that process terminates.</p> </section> <section> - <title>COMMON DATA TYPES </title> - <p>Here follows type definitions that are used by more than one - function in the FTP client API. </p> - <p><c> pid() - identifier of an ftp connection.</c></p> - <p><c> string() = list of ASCII characters.</c></p> - <p><c> shortage_reason() = etnospc | epnospc</c></p> - <p><c> restriction_reason() = epath | efnamena | elogin | enotbinary - - note not all restrictions may always relevant to all functions - </c></p> - <p><c>common_reason() = econn | eclosed | term() - some kind of - explanation of what went wrong.</c></p> + <title>DATA TYPES</title> + <p>The following type definitions are used by more than one + function in the FTP client API:</p> + <p><c>pid()</c> = identifier of an FTP connection</p> + <p><c>string()</c> = list of ASCII characters</p> + <p><c>shortage_reason()</c> = <c>etnospc | epnospc</c></p> + <p><c>restriction_reason()</c> = <c>epath | efnamena | elogin | enotbinary</c> + - all restrictions are not always relevant to all functions + </p> + <p><c>common_reason()</c> = <c>econn | eclosed | term()</c> + - some explanation of what went wrong</p> <marker id="account"></marker> </section> @@ -278,15 +275,14 @@ <funcs> <func> <name>account(Pid, Account) -> ok | {error, Reason}</name> - <fsummary>Specify which account to use.</fsummary> + <fsummary>Specifies which account to use.</fsummary> <type> <v>Pid = pid()</v> <v>Account = string()</v> <v>Reason = eacct | common_reason()</v> </type> <desc> - <p>If an account is needed for an operation set the account - with this operation.</p> + <p>Sets the account for an operation, if needed.</p> <marker id="append"></marker> <marker id="append2"></marker> @@ -297,7 +293,8 @@ <func> <name>append(Pid, LocalFile) -> </name> <name>append(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name> - <fsummary>Transfer file to remote server, and append it to Remotefile.</fsummary> + <fsummary>Transfers a file to remote server, and appends it to + <c>Remotefile</c>.</fsummary> <type> <v>Pid = pid()</v> <v>LocalFile = RemoteFile = string()</v> @@ -306,9 +303,9 @@ <desc> <p>Transfers the file <c>LocalFile</c> to the remote server. If <c>RemoteFile</c> is specified, the name of the remote file that the - file will be appended to is set to <c>RemoteFile</c>; otherwise - the name is set to <c>LocalFile</c> If the file does not exists the - file will be created.</p> + file is appended to is set to <c>RemoteFile</c>, otherwise + to <c>LocalFile</c>. If the file does not exists, + it is created.</p> <marker id="append_bin"></marker> </desc> @@ -316,17 +313,17 @@ <func> <name>append_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name> - <fsummary>Transfer a binary into a remote file.</fsummary> + <fsummary>Transfers a binary into a remote file.</fsummary> <type> <v>Pid = pid()</v> <v>Bin = binary()()</v> <v>RemoteFile = string()</v> - <v>Reason = restriction_reason()| shortage_reason() | common_reason()</v> + <v>Reason = restriction_reason()| shortage_reason() | common_reason()</v> </type> <desc> - <p>Transfers the binary <c>Bin</c> to the remote server and append - it to the file <c>RemoteFile</c>. If the file does not exists it - will be created.</p> + <p>Transfers the binary <c>Bin</c> to the remote server and appends + it to the file <c>RemoteFile</c>. If the file does not exist, it + is created.</p> <marker id="append_chunk"></marker> </desc> @@ -334,18 +331,18 @@ <func> <name>append_chunk(Pid, Bin) -> ok | {error, Reason}</name> - <fsummary>append a chunk to the remote file.</fsummary> + <fsummary>Appends a chunk to the remote file.</fsummary> <type> <v>Pid = pid()</v> <v>Bin = binary()</v> <v>Reason = echunk | restriction_reason() | common_reason()</v> </type> <desc> - <p>Transfer the chunk <c>Bin</c> to the remote server, which - append it into the file specified in the call to - <c>append_chunk_start/2</c>. </p> - <p>Note that for some errors, e.g. file system full, it is - necessary to to call <c>append_chunk_end</c> to get the + <p>Transfers the chunk <c>Bin</c> to the remote server, which + appends it to the file specified in the call to + <c>append_chunk_start/2</c>.</p> + <p>For some errors, for example, file system full, it is + necessary to call <c>append_chunk_end</c> to get the proper reason.</p> <marker id="append_chunk_start"></marker> @@ -354,16 +351,16 @@ <func> <name>append_chunk_start(Pid, File) -> ok | {error, Reason}</name> - <fsummary>Start transfer of file chunks for appending to File.</fsummary> + <fsummary>Starts transfer of file chunks for appending to <c>File</c>.</fsummary> <type> <v>Pid = pid()</v> <v>File = string()</v> <v>Reason = restriction_reason() | common_reason()</v> </type> <desc> - <p>Start the transfer of chunks for appending to the file - <c>File</c> at the remote server. If the file does not exists - it will be created.</p> + <p>Starts the transfer of chunks for appending to the file + <c>File</c> at the remote server. If the file does not exist, + it is created.</p> <marker id="append_chunk_end"></marker> </desc> @@ -371,7 +368,7 @@ <func> <name>append_chunk_end(Pid) -> ok | {error, Reason}</name> - <fsummary>Stop transfer of chunks for appending.</fsummary> + <fsummary>Stops transfer of chunks for appending.</fsummary> <type> <v>Pid = pid()</v> <v>Reason = echunk | restriction_reason() | shortage_reason() </v> @@ -379,7 +376,7 @@ <desc> <p>Stops transfer of chunks for appending to the remote server. The file at the remote server, specified in the call to - <c>append_chunk_start/2</c> is closed by the server.</p> + <c>append_chunk_start/2</c>, is closed by the server.</p> <marker id="cd"></marker> </desc> @@ -387,7 +384,7 @@ <func> <name>cd(Pid, Dir) -> ok | {error, Reason}</name> - <fsummary>Change remote working directory.</fsummary> + <fsummary>Changes remote working directory.</fsummary> <type> <v>Pid = pid()</v> <v>Dir = string()</v> @@ -403,13 +400,13 @@ <func> <name>close(Pid) -> ok</name> - <fsummary>End the ftp session.</fsummary> + <fsummary>Ends the FTP session.</fsummary> <type> <v>Pid = pid()</v> </type> <desc> - <p>Ends an ftp session, created using the - <seealso marker="#open">open</seealso> function. </p> + <p>Ends an FTP session, created using function + <seealso marker="#open">open</seealso>.</p> <marker id="delete"></marker> </desc> @@ -417,7 +414,7 @@ <func> <name>delete(Pid, File) -> ok | {error, Reason}</name> - <fsummary>Delete a file at the remote server..</fsummary> + <fsummary>Deletes a file at the remote server.</fsummary> <type> <v>Pid = pid()</v> <v>File = string()</v> @@ -432,7 +429,7 @@ <func> <name>formaterror(Tag) -> string()</name> - <fsummary>Return error diagnostics.</fsummary> + <fsummary>Returns error diagnostics.</fsummary> <type> <v>Tag = {error, atom()} | atom()</v> </type> @@ -446,14 +443,14 @@ <func> <name>lcd(Pid, Dir) -> ok | {error, Reason}</name> - <fsummary>Change local working directory.</fsummary> + <fsummary>Changes local working directory.</fsummary> <type> <v>Pid = pid()</v> <v>Dir = string()</v> <v>Reason = restriction_reason()</v> </type> <desc> - <p>Changes the working directory to <c>Dir</c> for the local client. </p> + <p>Changes the working directory to <c>Dir</c> for the local client.</p> <marker id="lpwd"></marker> </desc> @@ -461,7 +458,7 @@ <func> <name>lpwd(Pid) -> {ok, Dir}</name> - <fsummary>Get local current working directory.</fsummary> + <fsummary>Gets local current working directory.</fsummary> <type> <v>Pid = pid()</v> </type> @@ -485,13 +482,13 @@ <v>Reason = restriction_reason() | common_reason()</v> </type> <desc> - <p>Returns a list of files in long format. </p> - <p><c>Pathname</c> can be a directory, a group of files or - even a file. The <c>Pathname</c> string can contain wildcard(s). </p> - <p><c>ls/1</c> implies the user's current remote directory. </p> - <p>The format of <c>Listing</c> is operating system dependent - (on UNIX it is typically produced from the output of the - <c>ls -l</c> shell command).</p> + <p>Returns a list of files in long format.</p> + <p><c>Pathname</c> can be a directory, a group of files, or + a file. The <c>Pathname</c> string can contain wildcards.</p> + <p><c>ls/1</c> implies the current remote directory of the user.</p> + <p>The format of <c>Listing</c> depends on the operating system. + On UNIX, it is typically produced from the output of the + <c>ls -l</c> shell command.</p> <marker id="mkdir"></marker> </desc> @@ -499,7 +496,7 @@ <func> <name>mkdir(Pid, Dir) -> ok | {error, Reason}</name> - <fsummary>Create remote directory.</fsummary> + <fsummary>Creates a remote directory.</fsummary> <type> <v>Pid = pid()</v> <v>Dir = string()</v> @@ -525,15 +522,15 @@ <v>Reason = restriction_reason() | common_reason()</v> </type> <desc> - <p>Returns a list of files in short format. </p> - <p><c>Pathname</c> can be a directory, a group of files or - even a file. The <c>Pathname</c> string can contain wildcard(s). </p> - <p><c>nlist/1</c> implies the user's current remote directory. </p> + <p>Returns a list of files in short format.</p> + <p><c>Pathname</c> can be a directory, a group of files, or + a file. The <c>Pathname</c> string can contain wildcards.</p> + <p><c>nlist/1</c> implies the current remote directory of the user.</p> <p>The format of <c>Listing</c> is a stream of - file names, where each name is separated by <CRLF> or - <NL>. Contrary to the <c>ls</c> function, the purpose of - <c>nlist</c> is to make it possible for a program to - automatically process file name information.</p> + filenames where each filename is separated by <CRLF> or + <NL>. Contrary to function <c>ls</c>, the purpose of + <c>nlist</c> is to enable a program to + process filename information automatically.</p> <marker id="open"></marker> </desc> @@ -542,23 +539,23 @@ <func> <name>open(Host) -> {ok, Pid} | {error, Reason}</name> <name>open(Host, Opts) -> {ok, Pid} | {error, Reason}</name> - <fsummary>Start an standalone ftp client.</fsummary> + <fsummary>Starts a standalone FTP client.</fsummary> <type> <v>Host = string() | ip_address()</v> <v>Opts = options()</v> <v>options() = [option()]</v> <v>option() = start_option() | open_option()</v> <v>start_option() = {verbose, verbose()} | {debug, debug()}</v> - <v>verbose() = boolean() (defaults to false)</v> - <v>debug() = disable | debug | trace (defaults to disable)</v> + <v>verbose() = boolean() (default is false)</v> + <v>debug() = disable | debug | trace (default is disable)</v> <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress()}</v> - <v>ipfamily() = inet | inet6 | inet6fb4 (defaults to inet)</v> - <v>port() = integer() > 0 (defaults to 21)</v> - <v>mode() = active | passive (defaults to passive)</v> + <v>ipfamily() = inet | inet6 | inet6fb4 (default is inet)</v> + <v>port() = integer() > 0 (default is 21)</v> + <v>mode() = active | passive (default is passive)</v> <v>tls_options() = [<seealso marker="ssl:ssl#type-ssloption">ssl:ssloption()</seealso>]</v> - <v>timeout() = integer() > 0 (defaults to 60000 milliseconds)</v> - <v>dtimeout() = integer() > 0 | infinity (defaults to infinity)</v> - <v>pogress() = ignore | {module(), function(), initial_data()} (defaults to ignore)</v> + <v>timeout() = integer() > 0 (default is 60000 milliseconds)</v> + <v>dtimeout() = integer() > 0 | infinity (default is infinity)</v> + <v>pogress() = ignore | {module(), function(), initial_data()} (default is ignore)</v> <v>module() = atom()</v> <v>function() = atom()</v> <v>initial_data() = term()</v> @@ -566,16 +563,20 @@ </type> <desc> - <p>This function is used to start a standalone ftp client process - (without the inets service framework) and - open a session with the FTP server at <c>Host</c>. </p> + <p>Starts a standalone FTP client process + (without the <c>Inets</c> service framework) and + opens a session with the FTP server at <c>Host</c>. </p> - <p>If the option <c>{tls, tls_options()}</c> is present, the ftp session will be transported over tls (ftps, see -<url href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</url>). The list <c>tls_options()</c> may be empty. The function <seealso marker="ssl:ssl#connect/3"><c>ssl:connect/3</c></seealso> is used for securing both the control connection and the data sessions. + <p>If option <c>{tls, tls_options()}</c> is present, the FTP session + is transported over <c>tls</c> (<c>ftps</c>, see + <url href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</url>). + The list <c>tls_options()</c> can be empty. The function + <seealso marker="ssl:ssl#connect/3"><c>ssl:connect/3</c></seealso> + is used for securing both the control connection and the data sessions. </p> - <p>A session opened in this way, is closed using the - <seealso marker="#close">close</seealso> function. </p> + <p>A session opened in this way is closed using function + <seealso marker="#close">close</seealso>.</p> <marker id="pwd"></marker> </desc> @@ -583,22 +584,10 @@ <func> <name>pwd(Pid) -> {ok, Dir} | {error, Reason}</name> - <fsummary>Get remote current working directory.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Reason = restriction_reason() | common_reason() </v> - </type> - <desc> - <p>Returns the current working directory at the remote server. </p> - </desc> - </func> - - <func> - <name>pwd(Pid) -> {ok, Dir} | {error, Reason}</name> - <fsummary>Get remote current working directory.</fsummary> + <fsummary>Gets the remote current working directory.</fsummary> <type> <v>Pid = pid()</v> - <v>Reason = restriction_reason() | common_reason() </v> + <v>Reason = restriction_reason() | common_reason()</v> </type> <desc> <p>Returns the current working directory at the remote server.</p> @@ -612,7 +601,7 @@ <func> <name>recv(Pid, RemoteFile) -> </name> <name>recv(Pid, RemoteFile, LocalFile) -> ok | {error, Reason}</name> - <fsummary>Transfer file from remote server.</fsummary> + <fsummary>Transfers a file from remote server.</fsummary> <type> <v>Pid = pid()</v> <v>RemoteFile = LocalFile = string()</v> @@ -620,14 +609,14 @@ <v>file_write_error_reason() = see file:write/2</v> </type> <desc> - <p>Transfer the file <c>RemoteFile</c> from the remote server - to the the file system of the local client. If + <p>Transfers the file <c>RemoteFile</c> from the remote server + to the file system of the local client. If <c>LocalFile</c> is specified, the local file will be - <c>LocalFile</c>; otherwise it will be + <c>LocalFile</c>, otherwise <c>RemoteFile</c>.</p> - <p>If the file write fails - (e.g. enospc), then the command is aborted and <c>{error, file_write_error_reason()}</c> is returned. The file is - however <em>not</em> removed.</p> + <p>If the file write fails (for example, <c>enospc</c>), the command is + aborted and <c>{error, file_write_error_reason()}</c> is returned. + However, the file is <em>not</em> removed.</p> <marker id="recv_bin"></marker> </desc> @@ -635,7 +624,7 @@ <func> <name>recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, Reason}</name> - <fsummary>Transfer file from remote server as a binary.</fsummary> + <fsummary>Transfers a file from remote server as a binary.</fsummary> <type> <v>Pid = pid()</v> <v>Bin = binary()</v> @@ -652,14 +641,14 @@ <func> <name>recv_chunk_start(Pid, RemoteFile) -> ok | {error, Reason}</name> - <fsummary>Start chunk-reading of the remote file.</fsummary> + <fsummary>Starts chunk-reading of the remote file.</fsummary> <type> <v>Pid = pid()</v> <v>RemoteFile = string()</v> <v>Reason = restriction_reason() | common_reason()</v> </type> <desc> - <p>Start transfer of the file <c>RemoteFile</c> from the + <p>Starts transfer of the file <c>RemoteFile</c> from the remote server.</p> <marker id="recv_chunk"></marker> @@ -668,20 +657,20 @@ <func> <name>recv_chunk(Pid) -> ok | {ok, Bin} | {error, Reason}</name> - <fsummary>Receive a chunk of the remote file.</fsummary> + <fsummary>Receives a chunk of the remote file.</fsummary> <type> <v>Pid = pid()</v> <v>Bin = binary()</v> <v>Reason = restriction_reason() | common_reason()</v> </type> <desc> - <p>Receive a chunk of the remote file (<c>RemoteFile</c> of - <c>recv_chunk_start</c>). The return values has the following + <p>Receives a chunk of the remote file (<c>RemoteFile</c> of + <c>recv_chunk_start</c>). The return values have the following meaning:</p> <list type="bulleted"> - <item><c>ok</c> the transfer is complete.</item> - <item><c>{ok, Bin}</c> just another chunk of the file.</item> - <item><c>{error, Reason}</c> transfer failed.</item> + <item><c>ok</c> = the transfer is complete.</item> + <item><c>{ok, Bin}</c> = just another chunk of the file.</item> + <item><c>{error, Reason}</c> = transfer failed.</item> </list> <marker id="rename"></marker> @@ -690,7 +679,7 @@ <func> <name>rename(Pid, Old, New) -> ok | {error, Reason}</name> - <fsummary>Rename a file at the remote server..</fsummary> + <fsummary>Renames a file at the remote server.</fsummary> <type> <v>Pid = pid()</v> <v>CurrFile = NewFile = string()</v> @@ -705,7 +694,7 @@ <func> <name>rmdir(Pid, Dir) -> ok | {error, Reason}</name> - <fsummary>Remove a remote directory.</fsummary> + <fsummary>Removes a remote directory.</fsummary> <type> <v>Pid = pid()</v> <v>Dir = string()</v> @@ -723,7 +712,7 @@ <func> <name>send(Pid, LocalFile) -></name> <name>send(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name> - <fsummary>Transfer file to remote server.</fsummary> + <fsummary>Transfers a file to the remote server.</fsummary> <type> <v>Pid = pid()</v> <v>LocalFile = RemoteFile = string()</v> @@ -732,7 +721,7 @@ <desc> <p>Transfers the file <c>LocalFile</c> to the remote server. If <c>RemoteFile</c> is specified, the name of the remote file is set - to <c>RemoteFile</c>; otherwise the name is set to <c>LocalFile</c>.</p> + to <c>RemoteFile</c>, otherwise to <c>LocalFile</c>.</p> <marker id="send_bin"></marker> </desc> @@ -740,7 +729,7 @@ <func> <name>send_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name> - <fsummary>Transfer a binary into a remote file.</fsummary> + <fsummary>Transfers a binary into a remote file.</fsummary> <type> <v>Pid = pid()</v> <v>Bin = binary()()</v> @@ -757,17 +746,17 @@ <func> <name>send_chunk(Pid, Bin) -> ok | {error, Reason}</name> - <fsummary>Write a chunk to the remote file.</fsummary> + <fsummary>Writes a chunk to the remote file.</fsummary> <type> <v>Pid = pid()</v> <v>Bin = binary()</v> <v>Reason = echunk | restriction_reason() | common_reason()</v> </type> <desc> - <p>Transfer the chunk <c>Bin</c> to the remote server, which + <p>Transfers the chunk <c>Bin</c> to the remote server, which writes it into the file specified in the call to - <c>send_chunk_start/2</c>. </p> - <p>Note that for some errors, e.g. file system full, it is + <c>send_chunk_start/2</c>.</p> + <p>For some errors, for example, file system full, it is necessary to to call <c>send_chunk_end</c> to get the proper reason.</p> @@ -777,14 +766,14 @@ <func> <name>send_chunk_start(Pid, File) -> ok | {error, Reason}</name> - <fsummary>Start transfer of file chunks.</fsummary> + <fsummary>Starts transfer of file chunks.</fsummary> <type> <v>Pid = pid()</v> <v>File = string()</v> <v>Reason = restriction_reason() | common_reason()</v> </type> <desc> - <p>Start transfer of chunks into the file <c>File</c> at the + <p>Starts transfer of chunks into the file <c>File</c> at the remote server.</p> <marker id="send_chunk_end"></marker> @@ -793,7 +782,7 @@ <func> <name>send_chunk_end(Pid) -> ok | {error, Reason}</name> - <fsummary>Stop transfer of chunks.</fsummary> + <fsummary>Stops transfer of chunks.</fsummary> <type> <v>Pid = pid()</v> <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v> @@ -809,7 +798,7 @@ <func> <name>type(Pid, Type) -> ok | {error, Reason}</name> - <fsummary>Set transfer type to <c>ascii</c>or <c>binary</c>.</fsummary> + <fsummary>Sets transfer type to <c>ascii</c>or <c>binary</c>.</fsummary> <type> <v>Pid = pid()</v> <v>Type = ascii | binary</v> @@ -817,8 +806,8 @@ </type> <desc> <p>Sets the file transfer type to <c>ascii</c> or <c>binary</c>. When - an ftp session is opened, the default transfer type of the - server is used, most often <c>ascii</c>, which is the default + an FTP session is opened, the default transfer type of the + server is used, most often <c>ascii</c>, which is default according to <url href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</url>.</p> <marker id="user3"></marker> </desc> @@ -857,21 +846,22 @@ <func> <name>quote(Pid, Command) -> [FTPLine]</name> - <fsummary>Sends an arbitrary FTP command. </fsummary> + <fsummary>Sends an arbitrary FTP command.</fsummary> <type> <v>Pid = pid()</v> <v>Command = string()</v> - <v>FTPLine = string() - Note the telnet end of line characters, from the ftp protocol definition, CRLF e.g. "\\r\\n" has been removed.</v> - </type> - <desc> - <p>Sends an arbitrary FTP command and returns verbatimly a list - of the lines sent back by the FTP server. This functions is - intended to give an application accesses to FTP commands - that are server specific or that may not be provided by - this FTP client. </p> + <v>FTPLine = string(</v> + </type> + <desc><note><p>The telnet end of line characters, from the FTP + protocol definition, CRLF, for example, "\\r\\n" has been removed.</p></note> + <p>Sends an arbitrary FTP command and returns verbatim a list + of the lines sent back by the FTP server. This function is + intended to give application accesses to FTP commands + that are server-specific or that cannot be provided by + this FTP client.</p> <note> - <p>FTP commands that require a data connection can not be - successfully issued with this function. </p> + <p>FTP commands requiring a data connection cannot be + successfully issued with this function.</p> </note> </desc> </func> @@ -885,30 +875,31 @@ <taglist> <tag><c>echunk</c></tag> <item> - <p>Synchronisation error during chunk sending. - </p> - <p>A call has been made to <c>send_chunk/2</c> or - <c>send_chunk_end/1</c>, before a call to - <c>send_chunk_start/2</c>; or a call has been made to another - transfer function during chunk sending, i.e. before a call - to <c>send_chunk_end/1</c>.</p> + <p>Synchronization error during chunk sending according to one + of the following: + </p><list type="bulleted"> + <item>A call is made to <c>send_chunk/2</c> or <c>send_chunk_end/1</c> + before a call to <c>send_chunk_start/2</c>.</item> + <item>A call has been made to another transfer function during chunk + sending, that is, before a call to <c>send_chunk_end/1</c>.</item> + </list> </item> <tag><c>eclosed</c></tag> <item> - <p>The session has been closed.</p> + <p>The session is closed.</p> </item> <tag><c>econn</c></tag> <item> - <p>Connection to remote server prematurely closed.</p> + <p>Connection to the remote server is prematurely closed.</p> </item> <tag><c>ehost</c></tag> <item> - <p>Host not found, FTP server not found, or connection rejected + <p>Host is not found, FTP server is not found, or connection is rejected by FTP server.</p> </item> <tag><c>elogin</c></tag> <item> - <p>User not logged in.</p> + <p>User is not logged in.</p> </item> <tag><c>enotbinary</c></tag> <item> @@ -925,7 +916,7 @@ </item> <tag><c>euser</c></tag> <item> - <p>User name or password not valid.</p> + <p>Invalid username or password.</p> </item> <tag><c>etnospc</c></tag> <item> @@ -938,14 +929,16 @@ </item> <tag><c>efnamena</c></tag> <item> - <p>File name not allowed [553].</p> + <p>Filename not allowed [553].</p> </item> </taglist> </section> <section> <title>SEE ALSO</title> - <p>file, filename, J. Postel and J. Reynolds: File Transfer Protocol + <p><seealso marker="kernel:file">file(3)</seealso> + <seealso marker="stdlib:filename">filename(3)</seealso> + and J. Postel and J. Reynolds: File Transfer Protocol (<url href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</url>). </p> </section> diff --git a/lib/inets/doc/src/ftp_client.xml b/lib/inets/doc/src/ftp_client.xml index 2f5b8abb5f..89e66db814 100644 --- a/lib/inets/doc/src/ftp_client.xml +++ b/lib/inets/doc/src/ftp_client.xml @@ -34,38 +34,24 @@ </header> <section> - <title>Introduction</title> + <title>Getting Started</title> - <p>Ftp clients are consider to be rather temporary and are - for that reason only started and stopped during - runtime and can not be started at application startup. - Due to the design of FTP client API, letting some - functions return intermediate results, only the process - that started the ftp client will be able to access it in - order to preserve sane semantics. (This could be solved - by changing the API and using the concept of a controlling - process more in line with other OTP applications, but - that is perhaps something for the future.) - If the process that started the ftp session - dies the ftp client process will terminate.</p> + <p>FTP clients are considered to be rather temporary. Thus, + they are only started and stopped during runtime and cannot + be started at application startup. + The FTP client API is designed to allow some functions to + return intermediate results. This implies that only the process + that started the FTP client can access it with + preserved sane semantics. + If the process that started the FTP session + dies, the FTP client process terminates.</p> - <p>The client supports ipv6 as long as the underlying mechanisms - also do so. </p> + <p>The client supports IPv6 as long as the underlying mechanisms + also do so.</p> - </section> - - <section> - <title>Using the FTP Client API</title> - <p>The following is a simple example of an ftp session, where + <p>The following is a simple example of an FTP session, where the user <c>guest</c> with password <c>password</c> logs on to - the remote host <c>erlang.org</c>, and where the file - <c>appl.erl</c> is transferred from the remote to the local - host. When the session is opened, the current directory at - the remote host is <c>/home/guest</c>, and <c>/home/fred</c> - at the local host. Before transferring the file, the current - local directory is changed to <c>/home/eproj/examples</c>, and - the remote directory is set to - <c>/home/guest/appl/examples</c>.</p> + the remote host <c>erlang.org</c>:</p> <code type="erl"><![CDATA[ 1> inets:start(). ok @@ -86,6 +72,14 @@ 9> inets:stop(ftpc, Pid). ok ]]></code> + <p> The file + <c>appl.erl</c> is transferred from the remote to the local + host. When the session is opened, the current directory at + the remote host is <c>/home/guest</c>, and <c>/home/fred</c> + at the local host. Before transferring the file, the current + local directory is changed to <c>/home/eproj/examples</c>, and + the remote directory is set to + <c>/home/guest/appl/examples</c>.</p> </section> </chapter> diff --git a/lib/inets/doc/src/http_client.xml b/lib/inets/doc/src/http_client.xml index 5c42f72cec..f4d7b751ac 100644 --- a/lib/inets/doc/src/http_client.xml +++ b/lib/inets/doc/src/http_client.xml @@ -34,103 +34,91 @@ </header> <section> - <title>Introduction</title> + <title>Configuration</title> - <p>The HTTP client default profile will be started when the inets + <p>The HTTP client default profile is started when the <c>Inets</c> application is started and is then available to all processes on - that erlang node. Other profiles may also be started at + that Erlang node. Other profiles can also be started at application startup, or profiles can be started and stopped - dynamically in runtime. Each client profile will spawn a new - process to handle each request unless there is a possibility to use - a persistent connection with or without pipelining. - The client will add a <c>host</c> header and an empty + dynamically in runtime. Each client profile spawns a new + process to handle each request, unless a persistent connection + can be used with or without pipelining. + The client adds a <c>host</c> header and an empty <c>te</c> header if there are no such headers present in the request.</p> - <p>The client supports ipv6 as long as the underlying mechanisms also do + <p>The client supports IPv6 as long as the underlying mechanisms also do so.</p> - </section> - <section> - <title>Configuration</title> - <p> What to put in the erlang node application configuration file - in order to start a profile at application startup.</p> + <p>The following is to be put in the Erlang node application configuration file + to start a profile at application startup:</p> <pre> - [{inets, [{services, [{httpc, PropertyList}]}]}] - </pre> - <p>For valid properties see + [{inets, [{services, [{httpc, PropertyList}]}]}]</pre> + <p>For valid properties, see <seealso marker="httpc">httpc(3)</seealso>. </p> </section> <section> - <title>Using the HTTP Client API</title> + <title>Getting Started</title> + <p>Start <c>Inets</c>:</p> <code type="erl"> 1 > inets:start(). - ok - </code> - <p> The following calls uses the default client profile. - Use the proxy "www-proxy.mycompany.com:8000", - but not for requests to localhost. This will apply to all subsequent - requests</p> + ok</code> + <p>The following calls use the default client profile. + Use the proxy <c>"www-proxy.mycompany.com:8000"</c>, + except from requests to localhost. This applies to all the + following requests.</p> + <p>Example:</p> <code type="erl"> 2 > httpc:set_options([{proxy, {{"www-proxy.mycompany.com", 8000}, ["localhost"]}}]). - ok - </code> - <p>An ordinary synchronous request. </p> + ok</code> + <p>The following is an ordinary synchronous request:</p> <code type="erl"> 3 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = - 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> + httpc:request(get, {"http://www.erlang.org", []}, [], []).</code> + <p>With all the default values presented, a get request can also be written + as follows:</p> <code type="erl"> 4 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = - httpc:request("http://www.erlang.org"). - </code> - <p>An ordinary asynchronous request. The result will be sent - to the calling process in the form <c>{http, {ReqestId, Result}}</c></p> + httpc:request("http://www.erlang.org").</code> + <p>The following is an ordinary asynchronous request:</p> <code type="erl"> 5 > {ok, RequestId} = - 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> + httpc:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]).</code> + <p>The result is sent to the calling process as + <c>{http, {ReqestId, Result}}</c>.</p> + <p>In this case, the calling process is the shell, so the following + result is received:</p> <code type="erl"> 6 > receive {http, {RequestId, Result}} -> ok after 500 -> error end. - ok - </code> - <p>Send a request with a specified connection header. </p> + ok</code> + <p>This sends a request with a specified connection header:</p> <code type="erl"> 7 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} = httpc:request(get, {"http://www.erlang.org", [{"connection", "close"}]}, - [], []). - </code> + [], []).</code> - <p>Start a HTTP client profile. </p> + <p>Start an HTTP client profile:</p> <code><![CDATA[ 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> + <p>The new profile has no proxy settings, so the connection is refused:</p> <code type="erl"> 9 > httpc:request("http://www.erlang.org", foo). - {error, econnrefused} - </code> + {error, econnrefused}</code> - <p>Stop a HTTP client profile. </p> + <p>Stop the HTTP client profile:</p> <code type="erl"> 10 > inets:stop(httpc, foo). - ok - </code> + ok</code> - <p>Alternatively:</p> + <p>Alternative way to stop the HTTP client profile:</p> <code type="erl"> 10 > inets:stop(httpc, Pid). - ok - </code> + ok</code> </section> </chapter> diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml index 51ed826c7c..4b6d64fc8f 100644 --- a/lib/inets/doc/src/http_server.xml +++ b/lib/inets/doc/src/http_server.xml @@ -22,7 +22,7 @@ </legalnotice> - <title>HTTP server </title> + <title>HTTP server</title> <prepared>Ingela Anderton Andin</prepared> <responsible></responsible> <docno></docno> @@ -36,62 +36,65 @@ </header> <section> - <title>Introduction</title> - + <title>Configuration</title> + <marker id="config"></marker> <p>The HTTP server, also referred to as httpd, handles HTTP requests - as described in RFC 2616 with a few exceptions such as gateway - and proxy functionality. The server supports ipv6 as long as the - underlying mechanisms also do so. </p> - - <p>The server implements numerous features such as SSL (Secure Sockets - Layer), ESI (Erlang Scripting Interface), CGI (Common Gateway - Interface), User Authentication(using Mnesia, dets or plain text - database), Common Logfile Format (with or without disk_log(3) - support), URL Aliasing, Action Mappings, and Directory Listings</p> - - <p>The configuration of the server is provided as an erlang - property list, and for backwards compatibility also a configuration + as described in + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url> + with a few exceptions, such as gateway + and proxy functionality. The server supports IPv6 as long as the + underlying mechanisms also do so.</p> + + <p>The server implements numerous features, such as:</p> + <list type="bulleted"> + <item>Secure Sockets Layer (SSL)</item> + <item>Erlang Scripting Interface (ESI)</item> + <item>Common Gateway Interface (CGI)</item> + <item>User Authentication (using <c>Mnesia</c>, + <c>Dets</c> or plain text database)</item> + <item>Common Logfile Format (with or without disk_log(3) support)</item> + <item>URL Aliasing</item> + <item>Action Mappings</item> + <item>Directory Listings</item> + </list> + + <p>The configuration of the server is provided as an Erlang + property list. For backwards compatibility, a configuration file using apache-style configuration directives is supported.</p> - <p>As of inets version 5.0 the HTTP server is an easy to - start/stop and customize web server that provides the most basic - web server functionality. Depending on your needs there - are also other erlang based web servers that may be of interest - such as Yaws, http://yaws.hyber.org, that for instance has its own - markup support to generate html, and supports certain buzzword - technologies such as SOAP.</p> + <p>As of <c>Inets</c> 5.0 the HTTP server is an easy to + start/stop and customize web server providing the most basic + web server functionality. Depending on your needs, there + are also other Erlang-based web servers that can be of interest + such as <url href=" http://yaws.hyber.org ">Yaws</url>, which, + for example, has its own + markup support to generate HTML and supports certain buzzword + technologies, such as SOAP.</p> - <p>Allmost all server functionality has been implemented using an - especially crafted server API which is described in the Erlang Web - Server API. This API can be used to advantage by all who wish + <p>Almost all server functionality has been implemented using an + especially crafted server API, which is described in the Erlang Web + Server API. This API can be used to enhance the core server functionality, for example with custom logging and authentication.</p> - <marker id="config"></marker> - </section> - - <section> - <title>Configuration</title> - - <p> What to put in the erlang node application configuration file - in order to start a http server at application startup.</p> + <p>The following is to be put in the Erlang node application configuration + file to start an HTTP server at application startup:</p> <code type="erl"> [{inets, [{services, [{httpd, [{proplist_file, "/var/tmp/server_root/conf/8888_props.conf"}]}, {httpd, [{proplist_file, - "/var/tmp/server_root/conf/8080_props.conf"}]}]}]}]. - </code> - - <p>The server is configured using an erlang property list. - For the available properties see - <seealso marker="httpd">httpd(3)</seealso> - For backwards compatibility also apache-like config files - are supported. + "/var/tmp/server_root/conf/8080_props.conf"}]}]}]}].</code> + + <p>The server is configured using an Erlang property list. + For the available properties, see + <seealso marker="httpd">httpd(3)</seealso>. + For backwards compatibility, apache-like configuration files + are also supported. </p> - <p>All possible config properties are as follows </p> + <p>The available configuration properties are as follows:</p> <code type="none"> httpd_service() -> {httpd, httpd()} httpd() -> [httpd_config()] @@ -103,40 +106,43 @@ debug_options() -> {all_functions, modules()} | {exported_functions, modules()} | {disable, modules()} - modules() -> [atom()] - </code> - <p>{proplist_file, file()} File containing an erlang property + modules() -> [atom()]</code> + <p>Here:</p> + <taglist> + <tag><c>{file, file()}</c></tag> + <item><p>If you use an old apace-like configuration file.</p></item> + <tag><c>{proplist_file, file()}</c></tag> + <item><p>File containing an Erlang property list, followed by a full stop, describing the HTTP server - configuration.</p> - <p>{file, file()} If you use an old apace-like configuration file.</p> - <p>{debug, debug()} - Can enable trace on all - functions or only exported functions on chosen modules.</p> - <p>{accept_timeout, integer()} sets the wanted timeout value for - the server to set up a request connection.</p> - - <marker id="using_http_server_api"></marker> + configuration.</p></item> + <tag><c>{debug, debug()}</c></tag> + <item><p>Can enable trace on all functions or only exported functions + on chosen modules.</p></item> + <tag><c>{accept_timeout, integer()}</c></tag> + <item><p>Sets the wanted time-out value for + the server to set up a request connection.</p></item> + </taglist> </section> <section> - <title>Using the HTTP Server API</title> + <title>Getting Started</title> + <marker id="using_http_server_api"></marker> + <p>Start <c>Inets</c>:</p> <code type="none"> 1 > inets:start(). - ok - </code> - <p> Start a HTTP server with minimal - required configuration. Note that if you - specify port 0 an arbitrary available port will be - used and you can use the info function to find out - which port number that was picked. - </p> + ok</code> + <p>Start an HTTP server with minimal required configuration. + If you specify port <c>0</c>, an arbitrary available port is + used, and you can use function <c>info</c> to find which port + number that was picked:</p> <code type="none"> 2 > {ok, Pid} = inets:start(httpd, [{port, 0}, {server_name,"httpd_test"}, {server_root,"/tmp"}, {document_root,"/tmp/htdocs"}, {bind_address, "localhost"}]). - {ok, 0.79.0} - </code> + {ok, 0.79.0} </code> + <p>Call <c>info</c>:</p> <code type="none"> 3 > httpd:info(Pid). [{mime_types,[{"html","text/html"},{"htm","text/html"}]}, @@ -144,336 +150,324 @@ {bind_address, {127,0,0,1}}, {server_root,"/tmp"}, {port,59408}, - {document_root,"/tmp/htdocs"}] - </code> + {document_root,"/tmp/htdocs"}]</code> - <p> Reload the configuration without restarting the server. - Note port and bind_address can not be changed. Clients - trying to access the server during the reload will - get a service temporary unavailable answer. + <p>Reload the configuration without restarting the server: + </p> <code type="none"> 4 > httpd:reload_config([{port, 59408}, {server_name,"httpd_test"}, {server_root,"/tmp/www_test"}, {document_root,"/tmp/www_test/htdocs"}, {bind_address, "localhost"}], non_disturbing). - ok. - </code> + ok.</code> + + <note><p><c>port</c> and <c>bind_address</c> cannot be changed. + Clients trying to access the server during the reload + get a service temporary unavailable answer.</p></note> <code type="none"> 5 > httpd:info(Pid, [server_root, document_root]). - [{server_root,"/tmp/www_test"},{document_root,"/tmp/www_test/htdocs"}] - </code> + [{server_root,"/tmp/www_test"},{document_root,"/tmp/www_test/htdocs"}] </code> <code type="none"> - 6 > ok = inets:stop(httpd, Pid). - </code> + 6 > ok = inets:stop(httpd, Pid).</code> - <p> Alternative:</p> + <p>Alternative:</p> <code type="none"> - 6 > ok = inets:stop(httpd, {{127,0,0,1}, 59408}). - </code> + 6 > ok = inets:stop(httpd, {{127,0,0,1}, 59408}).</code> - <p>Note that bind_address has to be - the ip address reported by the info function and can - not be the hostname that is allowed when inputting bind_address.</p> - - <marker id="htaccess"></marker> + <p>Notice that <c>bind_address</c> must be the IP address reported + by function <c>info</c> and cannot be the hostname that is allowed + when putting in <c>bind_address</c>.</p> </section> <section> - <title>Htaccess - User Configurable Authentication.</title> - <p>If users of the web server needs to manage authentication of - web pages that are local to their user and do not have - server administrative privileges. They can use the - per-directory runtime configurable user-authentication scheme - that Inets calls htaccess. It works the following way: </p> + <title>Htaccess - User Configurable Authentication</title> + <marker id="htaccess"></marker> + <p>Web server users without server administrative privileges + that need to manage authentication of web pages that are local + to their user can use the per-directory runtime configurable + user-authentication scheme <c>htaccess</c>. + It works as follows:</p> <list type="bulleted"> <item>Each directory in the path to the requested asset is - searched for an access-file (default .htaccess), that restricts - the web servers rights to respond to a request. If an access-file - is found the rules in that file is applied to the - request. </item> - <item>The rules in an access-file applies both to files in the same - directories and in subdirectories. If there exists more than one - access-file in the path to an asset, the rules in the - access-file nearest the requested asset will be applied.</item> - <item>To change the rules that restricts the use of - an asset. The user only needs to have write access - to the directory where the asset exists.</item> - <item>All the access-files in the path to a requested asset is read - once per request, this means that the load on the server will - increase when this scheme is used.</item> - <item>If a directory is - limited both by auth directives in the HTTP server configuration - file and by the htaccess files. The user must be allowed to get - access the file by both methods for the request to succeed.</item> + searched for an access file (default is <c>.htaccess</c>), which + restricts the web servers rights to respond to a request. + If an access file is found, the rules in that file is applied to the + request.</item> + <item>The rules in an access file apply to files in the same + directory and in subdirectories. If there exists more than one + access file in the path to an asset, the rules in the + access file nearest the requested asset is applied.</item> + <item>To change the rules that restrict the use of + an asset, the user only needs write access + to the directory where the asset is.</item> + <item>All access files in the path to a requested asset are read + once per request. This means that the load on the server + increases when <c>htaccess</c> is used.</item> + <item>If a directory is limited both by authentication directives + in the HTTP server configuration file and by the <c>htaccess</c> + files, the user must be allowed to get access to the file by both + methods for the request to succeed.</item> </list> <section> <title>Access Files Directives</title> - <p>In every directory under the <c>DocumentRoot</c> or under an - <c>Alias</c> a user can place an access-file. An access-file - is a plain text file that specify the restrictions that - shall be considered before the web server answer to a - request. If there are more than one access-file in the path - to the requested asset, the directives in the access-file in - the directory nearest the asset will be used.</p> - <list type="bulleted"> + <p>In every directory under <c>DocumentRoot</c> or under an + <c>Alias</c> a user can place an access file. An access file + is a plain text file that specifies the restrictions to + consider before the web server answers to a + request. If there are more than one access file in the path + to the requested asset, the directives in the access file in + the directory nearest the asset is used.</p> + <taglist> + <tag><em>"allow"</em></tag> <item> - <p><em>DIRECTIVE: "allow"</em></p> - <p><em>Syntax:</em><c>Allow</c> from subnet subnet|from all <br></br> -<em>Default:</em><c>from all </c> <br></br> -</p> - <p>Same as the directive allow for the server config file. </p> + <p><em>Syntax:</em> <c>Allow</c> from subnet <c>subnet | from all</c></p> + <p><em>Default:</em> <c>from all</c></p> + <p>Same as directive <c>allow</c> for the server configuration file.</p> </item> - <item> - <p><em>DIRECTIVE: "AllowOverRide"</em></p> - <p><em>Syntax:</em><c>AllowOverRide</c> all | none | - Directives <br></br> -<em>Default:</em><c>- None -</c> <br></br> -<c>AllowOverRide</c> Specify which parameters that not - access-files in subdirectories are allowed to alter the value - for. If the parameter is set to none no more - access-files will be parsed. + <tag><em>"AllowOverRide"</em></tag> + <item> + <p><em>Syntax:</em> <c>AllowOverRide</c> <c>all | none | Directives</c></p> + <p><em>Default:</em> <c>none</c></p> + <p><c>AllowOverRide</c> specifies the parameters that + access files in subdirectories are not allowed to alter the value + for. If the parameter is set to <c>none</c>, no further + access files is parsed. </p> - <p>If only one access-file exists setting this parameter to - none can lessen the burden on the server since the server - will stop looking for access-files.</p> + <p>If only one access file exists, setting this parameter to + <c>none</c> can ease the burden on the server as the server + then stops looking for access files.</p> </item> + <tag><em>"AuthGroupfile"</em></tag> <item> - <p><em>DIRECTIVE: "AuthGroupfile"</em></p> - <p><em>Syntax:</em><c>AuthGroupFile</c> Filename <br></br> -<em>Default:</em><c>- None -</c> <br></br> -</p> - <p>AuthGroupFile indicates which file that contains the list - of groups. Filename must contain the absolute path to the - file. The format of the file is one group per row and + <p><em>Syntax:</em> <c>AuthGroupFile</c> Filename</p> + <p><em>Default:</em> <c>none</c></p> + <p><c>AuthGroupFile</c> indicates which file that contains the list + of groups. The filename must contain the absolute path to the + file. The format of the file is one group per row and every row contains the name of the group and the members - of the group separated by a space, for example:</p> + of the group, separated by a space, for example:</p> <pre> -GroupName: Member1 Member2 .... MemberN - </pre> +GroupName: Member1 Member2 .... MemberN</pre> </item> + <tag><em>"AuthName"</em></tag> <item> - <p><em>DIRECTIVE: "AuthName"</em></p> - <p><em>Syntax:</em><c>AuthName</c> auth-domain <br></br> -<em>Default:</em><c>- None -</c> <br></br> -</p> - <p>Same as the directive AuthName for the server config file. </p> + <p><em>Syntax:</em> <c>AuthName</c> auth-domain</p> + <p><em>Default:</em> <c>none</c></p> + <p>Same as directive <c>AuthName</c> for the server + configuration file.</p> </item> + <tag><em>"AuthType"</em></tag> <item> - <p><em>DIRECTIVE: "AuthType"</em></p> - <p><em>Syntax:</em><c>AuthType</c> Basic <br></br> -<em>Default:</em><c>Basic</c> <br></br> -</p> - <p><c>AuthType</c> Specify which authentication scheme that shall - be used. Today only Basic Authenticating using UUEncoding of - the password and user ID is implemented. </p> + <p><em>Syntax:</em> <c>AuthType</c> <c>Basic</c></p> + <p><em>Default:</em> <c>Basic</c></p> + <p><c>AuthType</c> specifies which authentication scheme to + be used. Only Basic Authenticating using UUEncoding of + the password and user ID is implemented.</p> </item> + <tag><em>"AuthUserFile"</em></tag> <item> - <p><em>DIRECTIVE: "AuthUserFile"</em></p> - <p><em>Syntax:</em><c>AuthUserFile</c> Filename <br></br> -<em>Default:</em><c>- None -</c> <br></br> -</p> - <p><c>AuthUserFile</c> indicate which file that contains the list - of users. Filename must contain the absolute path to the - file. The users name and password are not encrypted so do not + <p><em>Syntax:</em> <c>AuthUserFile</c> Filename</p> + <p><em>Default:</em><c>none</c></p> + <p><c>AuthUserFile</c> indicates which file that contains the list + of users. The filename must contain the absolute path to the + file. The username and password are not encrypted so do not place the file with users in a directory that is accessible - via the web server. The format of the file is one user per row - and every row contains User Name and Password separated by a - colon, for example:</p> + through the web server. The format of the file is one user per row. + Every row contains <c>UserName</c> and <c>Password</c> separated + by a colon, for example:</p> <pre> UserName:Password -UserName:Password - </pre> +UserName:Password</pre> </item> + <tag><em>"deny"</em></tag> <item> - <p><em>DIRECTIVE: "deny"</em></p> - <p><em>Syntax:</em><c>deny</c> from subnet subnet|from all <br></br> -<em>Context:</em> Limit</p> - <p>Same as the directive deny for the server config file. </p> + <p><em>Syntax:</em> <c>deny</c> from subnet <c>subnet | from all</c></p> + <p><em>Context:</em> Limit</p> + <p>Same as directive <c>deny</c> for the server configuration file.</p> </item> - <item> - <p><em>DIRECTIVE: "Limit"</em> <br></br> -</p> - <p><em>Syntax:</em><c><![CDATA[<Limit]]></c> RequestMethods<c>></c> <br></br> -<em>Default:</em> - None - <br></br> -</p> - <p><c><![CDATA[<Limit>]]></c> and </Limit> are used to enclose - a group of directives which applies only to requests using - the specified methods. If no request method is specified + <tag><em>"Limit"</em></tag> + <item> + <p><em>Syntax:</em> <c><![CDATA[<Limit]]></c> RequestMethods<c>></c></p> + <p><em>Default:</em> <c>none</c></p> + <p><c><![CDATA[<Limit>]]></c> and <c></Limit></c> are used to enclose + a group of directives applying only to requests using + the specified methods. If no request method is specified, all request methods are verified against the restrictions.</p> + <p>Example:</p> <pre> <Limit POST GET HEAD> order allow deny require group group1 allow from 123.145.244.5 -</Limit> - </pre> +</Limit></pre> </item> - <item> - <p><em>DIRECTIVE: "order"</em> <br></br> -<em>Syntax:</em><c>order</c> allow deny | deny allow <br></br> -<em>Default:</em> allow deny <br></br> -</p> - <p><c>order</c>, defines if the deny or allow control shall - be preformed first.</p> - <p>If the order is set to allow deny, then first the users - network address is controlled to be in the allow subset. If - the users network address is not in the allowed subset he will - be denied to get the asset. If the network-address is in the - allowed subset then a second control will be preformed, that - the users network address is not in the subset of network - addresses that shall be denied as specified by the deny - parameter.</p> - <p>If the order is set to deny allow then only users from networks - specified to be in the allowed subset will succeed to request + <tag><em>"order"</em></tag> + <item> + <p><em>Syntax:</em> <c>order</c> <c>allow deny | deny allow</c></p> + <p><em>Default:</em> <c>allow deny</c></p> + <p><c>order</c> defines if the deny or allow control is to + be performed first.</p> + <p>If the order is set to <c>allow deny</c>, the users + network address is first controlled to be in the allow subset. + If the user network address is not in the allowed subset, the user + is denied to get the asset. If the network address is in the + allowed subset, a second control is performed. That is, + the user network address is not in the subset of network + addresses to be denied as specified by parameter <c>deny</c>.</p> + <p>If the order is set to <c>deny allow</c>, only users from networks + specified to be in the allowed subset succeeds to request assets in the limited area.</p> </item> - <item> - <p><em>DIRECTIVE: "require"</em></p> - <p><em>Syntax:</em><c>require</c> - group group1 group2...|user user1 user2... <br></br> -<em>Default:</em><c>- None -</c> <br></br> -<em>Context:</em> Limit <br></br> -</p> - <p>See the require directive in the documentation of mod_auth(3) - for more information.</p> + <tag><em>"require"</em></tag> + <item> + <p><em>Syntax:</em> <c>require</c> + <c>group group1 group2... | user user1 user2...</c></p> + <p><em>Default:</em> <c>none</c></p> + <p><em>Context:</em> Limit</p> + <p>For more information, see directive <c>require</c> in + <seealso marker="mod_auth">mod_auth(3)</seealso>.</p> </item> - </list> + </taglist> </section> - - <marker id="dynamic_we_pages"></marker> </section> <section> <title>Dynamic Web Pages</title> - <p>The Inets HTTP server provides two ways of creating dynamic web - pages, each with its own advantages and disadvantages. </p> - <p>First there are CGI-scripts that can be written in any programming - language. CGI-scripts are standardized and supported by most - web servers. The drawback with CGI-scripts is that they are resource - intensive because of their design. CGI requires the server to fork a - new OS process for each executable it needs to start. </p> - <p>Second there are ESI-functions that provide a tight and efficient - interface to the execution of Erlang functions, this interface - on the other hand is Inets specific. </p> - + <marker id="dynamic_we_pages"></marker> + <p><c>Inets</c> HTTP server provides two ways of creating dynamic web + pages, each with its own advantages and disadvantages:</p> + <taglist> + <tag><em>CGI scripts</em></tag> + <item><p>Common Gateway Interface (CGI) scripts can be written + in any programming language. CGI scripts are standardized and + supported by most web servers. The drawback with CGI scripts is that + they are resource-intensive because of their design. CGI requires the + server to fork a new OS process for each executable it needs to start. + </p></item> + <tag><em>ESI-functions</em></tag> + <item><p>Erlang Server Interface (ESI) functions provide a tight and efficient + interface to the execution of Erlang functions. This interface, + on the other hand, is <c>Inets</c> specific.</p></item> + </taglist> + <section> - <title>The Common Gateway Interface (CGI) Version 1.1, RFC 3875.</title> - <p>The mod_cgi module makes it possible to execute CGI scripts - in the server. A file that matches the definition of a - ScriptAlias config directive is treated as a CGI script. A CGI + <title>CGI Version 1.1, + <url href="http://www.ietf.org/rfc/rfc3875.txt">RFC 3875</url></title> + <p>The module <c>mod_cgi</c> enables execution of CGI scripts + on the server. A file matching the definition of a + ScriptAlias config directive is treated as a CGI script. A CGI script is executed by the server and its output is returned to - the client. </p> - <p>The CGI Script response comprises a message-header and a - message-body, separated by a blank line. The message-header - contains one or more header fields. The body may be - empty. Example: </p> + the client.</p> + <p>The CGI script response comprises a message header and a + message body, separated by a blank line. The message header + contains one or more header fields. The body can be + empty.</p> + <p>Example:</p> <code>"Content-Type:text/plain\nAccept-Ranges:none\n\nsome very - plain text" </code> + plain text"</code> - <p>The server will interpret the cgi-headers and most of them - will be transformed into HTTP headers and sent back to the - client together with the body.</p> - <p>Support for CGI-1.1 is implemented in accordance with the RFC - 3875. </p> + <p>The server interprets the message headers and most of them + are transformed into HTTP headers and sent back to the + client together with the message-body.</p> + <p>Support for CGI-1.1 is implemented in accordance with + <url href="http://www.ietf.org/rfc/rfc3875.txt">RFC 3875</url>.</p> </section> <section> - <title>Erlang Server Interface (ESI)</title> - <p>The erlang server interface is implemented by the - module mod_esi.</p> + <title>ESI</title> + <p>The Erlang server interface is implemented by + module <c>mod_esi</c>.</p> <section> - <title>ERL Scheme </title> + <title>ERL Scheme</title> <p>The erl scheme is designed to mimic plain CGI, but without - the extra overhead. An URL which calls an Erlang erl function + the extra overhead. An URL that calls an Erlang <c>erl</c> function has the following syntax (regular expression): </p> <code type="none"> -http://your.server.org/***/Module[:/]Function(?QueryString|/PathInfo) - </code> - <p>*** above depends on how the ErlScriptAlias config - directive has been used</p> - <p>The module (Module) referred to must be found in the code - path, and it must define a function (Function) with an arity - of two or three. It is preferable to implement a funtion - with arity three as it permits you to send chunks of the - webpage beeing generated to the client during the generation +http://your.server.org/***/Module[:/]Function(?QueryString|/PathInfo)</code> + <p>*** depends on how the ErlScriptAlias config + directive has been used.</p> + <p>The module <c>Module</c> referred to must be found in the code + path, and it must define a function <c>Function</c> with an arity + of two or three. It is preferable to implement a function + with arity three, as it permits to send chunks of the + web page to the client during the generation phase instead of first generating the whole web page and then sending it to the client. The option to implement a function with arity two is only kept for backwards compatibility reasons. - See <seealso marker="mod_esi">mod_esi(3)</seealso> for - implementation details of the esi callback function.</p> + For implementation details of the ESI callback function, + see <seealso marker="mod_esi">mod_esi(3)</seealso>.</p> </section> <section> - <title>EVAL Scheme </title> + <title>EVAL Scheme</title> <p>The eval scheme is straight-forward and does not mimic the - behavior of plain CGI. An URL which calls an Erlang eval + behavior of plain CGI. An URL that calls an Erlang <c>eval</c> function has the following syntax:</p> <code type="none"> -http://your.server.org/***/Mod:Func(Arg1,...,ArgN) - </code> - <p>*** above depends on how the ErlScriptAlias config - directive has been used</p> - <p>The module (Mod) referred to must be found in the code - path, and data returned by the function (Func) is passed +http://your.server.org/***/Mod:Func(Arg1,...,ArgN)</code> + <p>*** depends on how the ErlScriptAlias config + directive has been used.</p> + <p>The module <c>Mod</c> referred to must be found in the code + path and data returned by the function <c>Func</c> is passed back to the client. Data returned from the - function must furthermore take the form as specified in - the CGI specification. See <seealso marker="mod_esi">mod_esi(3)</seealso> for implementation details of the esi - callback function.</p> + function must take the form as specified in + the CGI specification. For implementation details of the ESI + callback function, + see <seealso marker="mod_esi">mod_esi(3)</seealso>.</p> <note> <p>The eval scheme can seriously threaten the - integrity of the Erlang node housing a Web server, for - example: </p> + integrity of the Erlang node housing a web server, for + example:</p> <code type="none"> -http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[]))) - </code> - <p>which effectively will close down the Erlang node, - therefor, use the erl scheme instead, until this - security breach has been fixed.</p> - <p>Today there are no good way of solving this problem - and therefore Eval Scheme may be removed in future - release of Inets. </p> +http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[])))</code> + <p>This effectively closes down the Erlang node. + Therefore, use the erl scheme instead, until this + security breach is fixed.</p> + <p>Today there are no good ways of solving this problem + and therefore the eval scheme can be removed in future + release of <c>Inets</c>.</p> </note> </section> </section> - - <marker id="logging"></marker> </section> <section> - <title>Logging </title> - <p>There are three types of logs supported. Transfer logs, - security logs and error logs. The de-facto standard Common + <title>Logging</title> + <marker id="logging"></marker> + <p>Three types of logs are supported: transfer logs, + security logs, and error logs. The de-facto standard Common Logfile Format is used for the transfer and security logging. There are numerous statistics programs available to analyze Common Logfile Format. The Common Logfile Format looks as follows: </p> <p><em>remotehost rfc931 authuser [date] "request" status bytes</em></p> + <p>Here:</p> <taglist> <tag><em>remotehost</em></tag> - <item>Remote hostname</item> + <item>Remote hostname.</item> <tag><em>rfc931</em></tag> - <item>The client's remote username (RFC 931).</item> + <item>The client remote username (<url href="http://www.ietf.org/rfc/rfc931.txt">RFC 931</url>).</item> <tag><em>authuser</em></tag> - <item>The username with which the user authenticated himself.</item> + <item>The username used for authentication.</item> <tag><em>[date]</em></tag> - <item>Date and time of the request (RFC 1123).</item> + <item>Date and time of the request (<url href="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</url>).</item> <tag><em>"request"</em></tag> - <item>The request line exactly as it came from the client (RFC 1945).</item> + <item>The request line exactly as it came from the client (<url href="http://www.ietf.org/rfc/rfc1945.txt">RFC 1945</url>).</item> <tag><em>status</em></tag> - <item>The HTTP status code returned to the client (RFC 1945).</item> + <item>The HTTP status code returned to the client (<url href="http://www.ietf.org/rfc/rfc1945.txt">RFC 1945</url>).</item> <tag><em>bytes</em></tag> <item>The content-length of the document transferred. </item> </taglist> <p>Internal server errors are recorded in the error log file. The - format of this file is a more ad hoc format than the logs using + format of this file is a more unplanned format than the logs using Common Logfile Format, but conforms to the following syntax: </p> <p><em>[date]</em> access to <em>path</em> failed for @@ -481,73 +475,79 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[ </section> <section> - <title>The Erlang Web Server API</title> - <p>The process of handling a HTTP request involves several steps + <title>Erlang Web Server API</title> + <p>The process of handling an HTTP request involves several steps, such as:</p> <list type="bulleted"> - <item>Seting up connections, sending and receiving data.</item> - <item>URI to filename translation</item> - <item>Authenication/access checks.</item> - <item>Retriving/generating the response.</item> - <item>Logging</item> + <item>Setting up connections, sending and receiving data.</item> + <item>URI to filename translation.</item> + <item>Authentication/access checks.</item> + <item>Retrieving/generating the response.</item> + <item>Logging.</item> </list> - <p>To provide customization and extensibility of the HTTP servers - request handling most of these steps are handled by one or more - modules that may be replaced or removed at runtime, and of course - new ones can be added. For each request all modules will be - traversed in the order specified by the modules directive in the - server configuration file. Some parts mainly the communication - related steps are considered server core functionality and are - not implemented using the Erlang Web Server API. A description of - functionality implemented by the Erlang Webserver API is described - in the section Inets Webserver Modules.</p> + <p>To provide customization and extensibility of the request + handling of the HTTP servers, most of these steps are handled by + one or more modules. These modules can be replaced or removed at + runtime and new ones can be added. For each request, all modules are + traversed in the order specified by the module directive in the + server configuration file. Some parts, mainly the communication- + related steps, are considered server core functionality and are + not implemented using the Erlang web server API. A description of + functionality implemented by the Erlang webserver API is described + in <seealso marker="#Inets_Web_Server_Modules">Section + Inets Web Server Modules</seealso>.</p> + <p>A module can use data generated by previous modules in the - Erlang Webserver API module sequence or generate data to be used - by consecutive Erlang Web Server API modules. This is made - possible due to an internal list of key-value tuples, also referred to - as interaction data. </p> + Erlang webserver API module sequence or generate data to be used + by consecutive Erlang Web Server API modules. This is + possible owing to an internal list of key-value tuples, referred to + as interaction data.</p> <note> <p>Interaction data enforces module dependencies and - should be avoided if possible. This means the order - of modules in the Modules property is significant.</p> + is to be avoided if possible. This means that the order + of modules in the modules property is significant.</p> </note> <section> <title>API Description</title> - <p>Each module implements server functionality - using the Erlang Web Server API should implement the following + <p>Each module that implements server functionality + using the Erlang web server API is to implement the following call back functions:</p> <list type="bulleted"> - <item>do/1 (mandatory) - the function called when - a request should be handled.</item> - <item>load/2</item> - <item>store/2</item> - <item>remove/1</item> + <item><c>do/1</c> (mandatory) - the function called when + a request is to be handled</item> + <item><c>load/2</c></item> + <item><c>store/2</c></item> + <item><c>remove/1</c></item> </list> <p>The latter functions are needed only when new config - directives are to be introduced. For details see - <seealso marker="httpd">httpd(3)</seealso></p> + directives are to be introduced. For details, see + <seealso marker="httpd">httpd(3)</seealso>.</p> </section> </section> <section> - <title>Inets Web Server Modules</title> <p>The convention is that - all modules implementing some webserver functionality has the - name mod_*. When configuring the web server an appropriate - selection of these modules should be present in the Module - directive. Please note that there are some interaction dependencies - to take into account so the order of the modules can not be - totally random.</p> + <title>Inets Web Server Modules</title> + <marker id="Inets_Web_Server_Modules"></marker> + <p>The convention is that + all modules implementing some web server functionality has the + name <c>mod_*</c>. When configuring the web server, an appropriate + selection of these modules is to be present in the module + directive. Notice that there are some interaction dependencies + to take into account, so the order of the modules cannot be + random.</p> <section> - <title>mod_action - Filetype/Method-Based Script Execution.</title> - <p>Runs CGI scripts whenever a file of a - certain type or HTTP method (See RFC 1945) is requested. + <title>mod_action - Filetype/Method-Based Script Execution</title> + <p>This module runs CGI scripts whenever a file of a + certain type or HTTP method (see + <url href="http://tools.ietf.org/html/rfc1945">RFC 1945</url>RFC 1945) + is requested. </p> <p>Uses the following Erlang Web Server API interaction data: </p> <list type="bulleted"> - <item>real_name - from mod_alias</item> + <item><c>real_name</c> - from <seealso marker="mod_alias">mod_alias</seealso>.</item> </list> <p>Exports the following Erlang Web Server API interaction data, if possible: </p> @@ -559,48 +559,51 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[ <section> <title>mod_alias - URL Aliasing</title> - <p>This module makes it possible to map different parts of the - host file system into the document tree e.i. creates aliases and + <p>The <seealso marker="mod_alias">mod_alias</seealso> + module makes it possible to map different parts of the + host file system into the document tree, that is, creates aliases and redirections.</p> <p>Exports the following Erlang Web Server API interaction data, if possible: </p> <taglist> <tag><c>{real_name, PathData}</c></tag> - <item>PathData is the argument used for API function mod_alias:path/3.</item> + <item><c>PathData</c> is the argument used for API function + <seealso marker="mod_alias:path/3">mod_alias:path/3</seealso>.</item> </taglist> </section> <section> - <title>mod_auth - User Authentication </title> - <p>This module provides for basic user authentication using - textual files, dets databases as well as mnesia databases.</p> + <title>mod_auth - User Authentication</title> + <p>The <seealso marker="mod_auth">mod_auth(3)</seealso> + module provides for basic user authentication using + textual files, <c>Dets</c> databases as well as <c>Mnesia</c> databases.</p> <p>Uses the following Erlang Web Server API interaction data: </p> <list type="bulleted"> - <item>real_name - from mod_alias</item> + <item><c>real_name</c> - from <seealso marker="mod_alias">mod_alias</seealso></item> </list> <p>Exports the following Erlang Web Server API interaction data: </p> <taglist> <tag><c>{remote_user, User}</c></tag> - <item>The user name with which the user has authenticated himself.</item> + <item>The username used for authentication.</item> </taglist> <section> - <title>Mnesia as Authentication Database</title> + <title>Mnesia As Authentication Database</title> - <p> If Mnesia is used as storage method, Mnesia must be - started prio to the HTTP server. The first time Mnesia is - started the schema and the tables must be created before - Mnesia is started. A naive example of a module with two - functions that creates and start mnesia is provided - here. The function shall be used the first - time. first_start/0 creates the schema and the tables. The - second function start/0 shall be used in consecutive - startups. start/0 Starts Mnesia and wait for the tables to + <p>If <c>Mnesia</c> is used as storage method, <c>Mnesia</c> must be + started before the HTTP server. The first time <c>Mnesia</c> is + started, the schema and the tables must be created before + <c>Mnesia</c> is started. A simple example of a module with two + functions that creates and start <c>Mnesia</c> is provided + here. Function <c>first_start/0</c> is to be used the first + time. It creates the schema and the tables. + <c>start/0</c> is to be used in consecutive startups. + <c>start/0</c> starts <c>Mnesia</c> and waits for the tables to be initiated. This function must only be used when the - schema and the tables already is created. </p> + schema and the tables are already created.</p> <code> -module(mnesia_test). @@ -624,28 +627,28 @@ first_start() -> start() -> mnesia:start(), - mnesia:wait_for_tables([httpd_user, httpd_group], 60000). - </code> + mnesia:wait_for_tables([httpd_user, httpd_group], 60000). </code> - <p>To create the Mnesia tables we use two records defined in - mod_auth.hrl so the file must be included. The first - function first_start/0 creates a schema that specify on - which nodes the database shall reside. Then it starts Mnesia - and creates the tables. The first argument is the name of - the tables, the second argument is a list of options how the - table will be created, see Mnesia documentation for more - information. Since the current implementation of the - mod_auth_mnesia saves one row for each user the type must be - bag. When the schema and the tables is created the second - function start/0 shall be used to start Mensia. It starts - Mnesia and wait for the tables to be loaded. Mnesia use the - directory specified as mnesia_dir at startup if specified, - otherwise Mnesia use the current directory. For security - reasons, make sure that the Mnesia tables are stored outside - the document tree of the HTTP server. If it is placed in the - directory which it protects, clients will be able to - download the tables. Only the dets and mnesia storage - methods allow writing of dynamic user data to disk. plain is + <p>To create the <c>Mnesia</c> tables, we use two records defined in + <c>mod_auth.hrl</c>, so that file must be included. <c>first_start/0</c> + creates a schema that specifies on which nodes the database is to reside. + Then it starts <c>Mnesia</c> and creates the tables. The first argument + is the name of the tables, the second argument is a list of options of + how to create the table, see + <seealso marker="mnesia:mnesia"><c>mnesia</c></seealso>, documentation for + more information. As the implementation of the <c>mod_auth_mnesia</c> + saves one row for each user, the type must be <c>bag</c>. + When the schema and the tables are created, function + <seealso marker="mnesia:mnesia#start-0">mnesia:start/0</seealso> + is used to start <c>Mnesia</c> and + waits for the tables to be loaded. <c>Mnesia</c> uses the + directory specified as <c>mnesia_dir</c> at startup if specified, + otherwise <c>Mnesia</c> uses the current directory. For security + reasons, ensure that the <c>Mnesia</c> tables are stored outside + the document tree of the HTTP server. If they are placed in the + directory which it protects, clients can download the tables. + Only the <c>Dets</c> and <c>Mnesia</c> storage + methods allow writing of dynamic user data to disk. <c>plain</c> is a read only method.</p> </section> @@ -653,19 +656,19 @@ start() -> <section> <title>mod_cgi - CGI Scripts</title> - <p>This module handles invoking of CGI scripts</p> + <p>This module handles invoking of CGI scripts.</p> </section> <section> <title>mod_dir - Directories</title> <p>This module generates an HTML directory listing (Apache-style) if a client sends a request for a directory - instead of a file. This module needs to be removed from the + instead of a file. This module must be removed from the Modules config directive if directory listings is unwanted.</p> <p>Uses the following Erlang Web Server API interaction data: </p> <list type="bulleted"> - <item>real_name - from mod_alias</item> + <item><c>real_name</c> - from <seealso marker="mod_alias">mod_alias</seealso></item> </list> <p>Exports the following Erlang Web Server API interaction data: </p> @@ -677,27 +680,27 @@ start() -> </section> <section> - <title>mod_disk_log - Logging Using disk_log.</title> + <title>mod_disk_log - Logging Using Disk_Log.</title> <p>Standard logging using the "Common Logfile Format" and - disk_log(3).</p> + <seealso marker="kernel:disk_log">kernel:disk_log(3)</seealso>.</p> <p>Uses the following Erlang Web Server API interaction data: </p> <list type="bulleted"> - <item>remote_user - from mod_auth</item> + <item><c>remote_user</c> - from <c>mod_auth</c></item> </list> </section> <section> <title>mod_esi - Erlang Server Interface</title> - <p>This module implements - the Erlang Server Interface (ESI) that provides a tight and - efficient interface to the execution of Erlang functions. </p> - <p>Uses the following Erlang Web Server API interaction data: + <p>The <seealso marker="mod_esi">mod_esi(3)</seealso> + module implements the Erlang Server Interface (ESI) providing a + tight and efficient interface to the execution of Erlang functions.</p> + <p>Uses the following Erlang web server API interaction data: </p> <list type="bulleted"> - <item>remote_user - from mod_auth</item> + <item><c>remote_user</c> - from <c>mod_auth</c></item> </list> - <p>Exports the following Erlang Web Server API interaction data: + <p>Exports the following Erlang web server API interaction data: </p> <taglist> <tag><c>{mime_type, MimeType}</c></tag> @@ -709,11 +712,11 @@ start() -> <section> <title>mod_get - Regular GET Requests</title> <p>This module is responsible for handling GET requests to regular - files. GET requests for parts of files is handled by mod_range.</p> - <p>Uses the following Erlang Web Server API interaction data: + files. GET requests for parts of files is handled by <c>mod_range</c>.</p> + <p>Uses the following Erlang web server API interaction data: </p> <list type="bulleted"> - <item>real_name - from mod_alias</item> + <item><c>real_name</c> - from <seealso marker="mod_alias">mod_alias</seealso></item> </list> </section> @@ -725,7 +728,7 @@ start() -> <p>Uses the following Erlang Web Server API interaction data: </p> <list type="bulleted"> - <item>real_name - from mod_alias</item> + <item><c>real_name</c> - from <seealso marker="mod_alias">mod_alias</seealso></item> </list> </section> @@ -736,13 +739,13 @@ start() -> <p>Uses the following Erlang Web Server API interaction data: </p> <list type="bulleted"> - <item>real_name - from mod_alias</item> + <item><c>real_name</c> - from <seealso marker="mod_alias">mod_alias</seealso></item> </list> <p>Exports the following Erlang Web Server API interaction data: </p> <taglist> <tag><c>{remote_user_name, User}</c></tag> - <item>The user name with which the user has authenticated himself.</item> + <item>The username used for authentication.</item> </taglist> </section> @@ -750,84 +753,83 @@ start() -> <title>mod_log - Logging Using Text Files.</title> <p>Standard logging using the "Common Logfile Format" and text files.</p> - <p>Uses the following Erlang Webserver API interaction data: + <p>Uses the following Erlang Web Server API interaction data: </p> <list type="bulleted"> - <item>remote_user - from mod_auth</item> + <item><c>remote_user</c> - from <c>mod_auth</c></item> </list> </section> <section> <title>mod_range - Requests with Range Headers</title> - <p>This module response to requests for one or many ranges of a - file. This is especially useful when downloading large files, - since a broken download may be resumed.</p> - <p>Note that request for multiple parts of a document will report a + <p>This module responses to requests for one or many ranges of a + file. This is especially useful when downloading large files, + as a broken download can be resumed.</p> + <p>Notice that request for multiple parts of a document report a size of zero to the log file.</p> - <p>Uses the following Erlang Webserver API interaction data: + <p>Uses the following Erlang Web Server API interaction data: </p> <list type="bulleted"> - <item>real_name - from mod_alias</item> + <item><c>real_name</c> - from <seealso marker="mod_alias">mod_alias</seealso></item> </list> </section> <section> <title>mod_response_control - Requests with If* Headers</title> - <p>This module controls that the conditions in the requests is - fulfilled. For example a request may specify that the answer - only is of interest if the content is unchanged since last - retrieval. Or if the content is changed the range-request shall - be converted to a request for the whole file instead.</p> <p>If - a client sends more then one of the header fields that restricts - the servers right to respond, the standard does not specify how - this shall be handled. httpd will control each field in the - following order and if one of the fields not match the current - state the request will be rejected with a proper response. - <br></br> + <p>This module controls that the conditions in the requests are + fulfilled. For example, a request can specify that the answer + only is of interest if the content is unchanged since the last + retrieval. If the content is changed, the range request is to + be converted to a request for the whole file instead.</p> + <p>If a client sends more than one of the header fields that + restricts the servers right to respond, the standard does not + specify how this is to be handled. + <seealso marker="httpd">httpd(3)</seealso> controls each + field in the following order and if one of the fields does not + match the current state, the request is rejected with a proper + response:</p> + <p><c>If-modified</c></p> + <p><c>If-Unmodified</c></p> + <p><c>If-Match</c></p> + <p><c>If-Nomatch</c></p> - 1.If-modified <br></br> - - 2.If-Unmodified <br></br> - - 3.If-Match <br></br> - - 4.If-Nomatch <br></br> -</p> - <p>Uses the following Erlang Webserver API interaction data: + <p>Uses the following Erlang Web Server API interaction data: </p> <list type="bulleted"> - <item>real_name - from mod_alias</item> + <item><c>real_name</c> - from <seealso marker="mod_alias">mod_alias</seealso></item> </list> - <p>Exports the following Erlang Webserver API interaction data: + <p>Exports the following Erlang Web Server API interaction data: </p> <taglist> <tag><c>{if_range, send_file}</c></tag> - <item>The conditions for the range request was not fulfilled. + <item>The conditions for the range request are not fulfilled. The response must not be treated as a range request, instead it - must be treated as a ordinary get request. </item> + must be treated as an ordinary get request.</item> </taglist> </section> <section> <title>mod_security - Security Filter</title> - <p>This module serves as a filter for authenticated requests - handled in mod_auth. It provides possibility to restrict users - from access for a specified amount of time if they fail to + <p>The <seealso marker="mod_security">mod_security</seealso> + module serves as a filter for authenticated requests + handled in <seealso marker="mod_auth">mod_auth(3)</seealso>. + It provides a possibility to restrict users from + access for a specified amount of time if they fail to authenticate several times. It logs failed authentication as - well as blocking of users, and it also calls a configurable - call-back module when the events occur. </p> + well as blocking of users, and it calls a configurable + callback module when the events occur.</p> <p>There is also an - API to manually block, unblock and list blocked users or users, - who have been authenticated within a configurable amount of - time.</p> + API to block or unblock users manually. This API can also list + blocked users or users who have been authenticated within a + configurable amount of time.</p> </section> <section> <title>mod_trace - TRACE Request</title> - <p>mod_trace is responsible for handling of TRACE requests. + <p><c>mod_trace</c> is responsible for handling of TRACE requests. Trace is a new request method in HTTP/1.1. The intended use of trace requests is for testing. The body of the trace response is - the request message that the responding Web server or proxy + the request message that the responding web server or proxy received.</p> </section> </section> diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml index 4b59c0c7a2..64e6c7a6cc 100644 --- a/lib/inets/doc/src/http_uri.xml +++ b/lib/inets/doc/src/http_uri.xml @@ -35,67 +35,90 @@ <description> <p>This module provides utility functions for working with URIs, - according to RFC 3986. </p> - + according to + <url href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>.</p> </description> <section> - <title>COMMON DATA TYPES </title> + <title>DATA TYPES</title> <p>Type definitions that are used more than once in this module:</p> - <code type="none"><![CDATA[ -boolean() = true | false -string() = list of ASCII characters - ]]></code> + <p><c>boolean() = true | false</c></p> + <p><c>string()</c> = list of ASCII characters</p> </section> <section> - <title>URI DATA TYPES </title> + <title>URI DATA TYPES</title> <p>Type definitions that are related to URI:</p> - <p>For more information about URI, see RFC 3986. </p> - - <code type="none"><![CDATA[ -uri() = string() - Syntax according to the URI definition in rfc 3986, - e.g.: "http://www.erlang.org/" -user_info() = string() -scheme() = atom() - Example: http, https -host() = string() -port() = pos_integer() -path() = string() - Representing a file path or directory path -query() = string() -fragment() = string() - ]]></code> - + +<taglist> + <tag><c>uri() = string()</c></tag> + <item><p>Syntax according to the URI definition in RFC 3986, + for example, "http://www.erlang.org/"</p></item> + <tag><c>user_info() = string()</c></tag> + <item><p></p></item> + <tag><c>scheme() = atom()</c></tag> + <item><p>Example: http, https</p></item> + <tag><c>host() = string()</c></tag> + <item><p></p></item> + <tag><c>port() = pos_integer()</c></tag> + <item><p></p></item> + <tag><c>path() = string()</c></tag> + <item><p>Represents a file path or directory path</p></item> + <tag><c>query() = string()</c></tag> + <item><p></p></item> + <tag><c>fragment() = string()</c></tag> + <item><p></p></item> + </taglist> + + <p>For more information about URI, see + <url href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>.</p> <marker id="scheme_defaults"></marker> </section> <funcs> <func> - <name>scheme_defaults() -> SchemeDefaults</name> - <fsummary>A list of scheme and their default ports</fsummary> + <name>decode(HexEncodedURI) -> URI</name> + + <fsummary>Decodes a hexadecimal encoded URI.</fsummary> <type> - <v>SchemeDefaults = [{scheme(), default_scheme_port_number()}] </v> - <v>default_scheme_port_number() = pos_integer()</v> + <v>HexEncodedURI = string() - A possibly hexadecimal encoded URI</v> + <v>URI = uri()</v> </type> + <desc> - <p>This function provides a list of the scheme and their default - port numbers currently supported (by default) by this utility. </p> + <p>Decodes a possibly hexadecimal encoded URI.</p> - <marker id="parse"></marker> + </desc> + </func> + <func> + <name>encode(URI) -> HexEncodedURI</name> + + <fsummary>Encodes a hexadecimal encoded URI.</fsummary> + <type> + <v>URI = uri()</v> + <v>HexEncodedURI = string() - Hexadecimal encoded URI</v> + </type> + + <desc> + <p>Encodes a hexadecimal encoded URI.</p> + + <marker id="decode"></marker> </desc> </func> <func> <name>parse(URI) -> {ok, Result} | {error, Reason}</name> <name>parse(URI, Options) -> {ok, Result} | {error, Reason}</name> - <fsummary>Parse an URI</fsummary> + <fsummary>Parses a URI.</fsummary> <type> - <v>URI = uri() </v> - <v>Options = [Option] </v> + <v>URI = uri()</v> + <v>Options = [Option]</v> <v>Option = {ipv6_host_with_brackets, boolean()} | {scheme_defaults, scheme_defaults()} | - {fragment, boolean()}]</v> + {fragment, boolean()} | + {schema_validation_fun, fun()}]</v> <v>Result = {Scheme, UserInfo, Host, Port, Path, Query} | {Scheme, UserInfo, Host, Port, Path, Query, Fragment}</v> <v>UserInfo = user_info()</v> @@ -104,62 +127,59 @@ fragment() = string() <v>Path = path()</v> <v>Query = query()</v> <v>Fragment = fragment()</v> - <v>Reason = term() </v> + <v>Reason = term()</v> </type> <desc> - <p>This function is used to parse an URI. If no scheme defaults - are provided, the value of + <p>Parses a URI. If no scheme defaults + are provided, the value of the <seealso marker="#scheme_defaults">scheme_defaults</seealso> - function will be used. </p> + function is used.</p> - <p>Note that when parsing an URI with an unknown scheme (that is, - a scheme not found in the scheme defaults) a port number must be - provided or else the parsing will fail. </p> + <p>When parsing a URI with an unknown scheme (that is, + a scheme not found in the scheme defaults), a port number must be + provided, otherwise the parsing fails.</p> - <p>If the fragment option is true, the URI fragment will be returned as - part of the parsing result, otherwise it is completely ignored.</p> + <p>If the fragment option is <c>true</c>, the URI fragment is returned as + part of the parsing result, otherwise it is ignored.</p> - <marker id="encode"></marker> - </desc> - </func> + <p>Scheme validation fun is to be defined as follows: - <func> - <name>encode(URI) -> HexEncodedURI</name> - - <fsummary>Hex encode an URI</fsummary> - <type> - <v>URI = uri()</v> - <v>HexEncodedURI = string() - Hex encoded uri</v> - </type> + <code> +fun(SchemeStr :: string()) -> + valid | {error, Reason :: term()}. + </code> - <desc> - <p>Hex encode an URI. </p> + It is called before scheme string gets converted into scheme atom and + thus possible atom leak could be prevented</p> - <marker id="decode"></marker> + <marker id="encode"></marker> </desc> </func> <func> - <name>decode(HexEncodedURI) -> URI</name> - - <fsummary>Decode a hex encoded URI</fsummary> + <name>scheme_defaults() -> SchemeDefaults</name> + <fsummary>A list of the scheme and their default ports.</fsummary> <type> - <v>HexEncodedURI = string() - A possibly hex encoded uri</v> - <v>URI = uri()</v> + <v>SchemeDefaults = [{scheme(), default_scheme_port_number()}] </v> + <v>default_scheme_port_number() = pos_integer()</v> </type> - <desc> - <p>Decode a possibly hex encoded URI. </p> + <p>Provides a list of the scheme and their default + port numbers supported (by default) by this utility.</p> + <marker id="parse"></marker> </desc> </func> + + </funcs> <!-- <section> <title>SEE ALSO</title> - <p>RFC 2616, <seealso marker="inets">inets(3)</seealso>, + <p><url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>, + <seealso marker="inets">inets(3)</seealso>, <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>, <seealso marker="ssl:ssl">ssl(3)</seealso> </p> diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index 05eec9cfd3..31e44f405c 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -31,143 +31,252 @@ </header> <module>httpc</module> - <modulesummary>An HTTP/1.1 client </modulesummary> + <modulesummary>An HTTP/1.1 client</modulesummary> <description> - <p>This module provides the API to a HTTP/1.1 compatible client according - to RFC 2616, caching is currently not supported.</p> + <p>This module provides the API to an HTTP/1.1 compatible client according + to <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>. + Caching is not supported.</p> <note> - <p>When starting the Inets application a manager process for the - default profile will be started. The functions in this API - that do not explicitly use a profile will access the + <p>When starting the <c>Inets</c> application, a manager process for the + default profile is started. The functions in this API + that do not explicitly use a profile accesses the default profile. A profile keeps track of proxy options, - cookies and other options that can be applied to more than one - request. </p> + cookies, and other options that can be applied to more than one + request.</p> - <p>If the scheme https is used the ssl application needs to be - started. When https links needs to go through a proxy the + <p>If the scheme <c>https</c> is used, the <c>SSL</c> application must + be started. When <c>https</c> links need to go through a proxy, the CONNECT method extension to HTTP-1.1 is used to establish a - tunnel and then the connection is upgraded to TLS, - however "TLS upgrade" according to RFC 2817 is not + tunnel and then the connection is upgraded to TLS. + However, "TLS upgrade" according to <url href="http://www.ietf.org/rfc/rfc2817.txt">RFC 2817</url>is not supported.</p> - <p>Also note that pipelining will only be used if the pipeline - timeout is set, otherwise persistent connections without - pipelining will be used e.i. the client always waits for + <p>Pipelining is only used if the pipeline + time-out is set, otherwise persistent connections without + pipelining are used. That is, the client always waits for the previous response before sending the next request.</p> </note> - <p>There are some usage examples in the <seealso - marker="http_client">Inets User's Guide.</seealso></p> + <p>Some examples are provided in the <seealso + marker="http_client">Inets User's Guide</seealso>.</p> </description> <section> - <title>COMMON DATA TYPES </title> + <title>DATA TYPES</title> + <marker id="DATA_TYPES"></marker> <p>Type definitions that are used more than once in this module:</p> - <code type="none"><![CDATA[ -boolean() = true | false -string() = list of ASCII characters -request_id() = ref() -profile() = atom() -path() = string() representing a file path or directory path -ip_address() = See inet(3) -socket_opt() = See the Options used by gen_tcp(3) and - ssl(3) connect(s) - ]]></code> - + <p><c>boolean() = true | false</c></p> + <p><c>string()</c> = list of ASCII characters</p> + <p><c>request_id() = ref()</c></p> + <p><c>profile() = atom()</c></p> + <p><c>path() = string()</c> representing a file path or directory path</p> + <p><c>ip_address()</c> = See the + <seealso marker="kernel:inet">inet(3)</seealso> manual page in <c>Kernel</c>.</p> + <p><c>socket_opt()</c> = See the options used by + <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso> <c>gen_tcp(3)</c> and + <seealso marker="ssl:ssl">ssl(3)</seealso> connect(s)</p> + </section> <section> - <title>HTTP DATA TYPES </title> - <p>Type definitions that are related to HTTP:</p> - <p>For more information about HTTP see rfc 2616</p> - - <code type="none"><![CDATA[ -method() = head | get | put | post | trace | options | delete -request() = {url(), headers()} | - {url(), headers(), content_type(), body()} -url() = string() - Syntax according to the URI definition in rfc 2396, ex: "http://www.erlang.org" -status_line() = {http_version(), status_code(), reason_phrase()} -http_version() = string() ex: "HTTP/1.1" -status_code() = integer() -reason_phrase() = string() -content_type() = string() -headers() = [header()] -header() = {field(), value()} -field() = string() -value() = string() -body() = string() | - binary() | - {fun(accumulator()) -> body_processing_result(), - accumulator()} | - {chunkify, - fun(accumulator()) -> body_processing_result(), - accumulator()} -body_processing_result() = eof | {ok, iolist(), accumulator()} -accumulator() = term() -filename() = string() - ]]></code> + <title>HTTP DATA TYPES</title> + <p>Type definitions related to HTTP:</p> - </section> + <p><c>method() = head | get | put | post | trace | options | delete</c></p> + <taglist> + <tag><c>request()</c></tag> + <item><p>= <c>{url(), headers()}</c></p> + <p>| <c>{url(), headers(), content_type(), body()}</c></p> + </item> + </taglist> + <p><c>url() = string()</c> syntax according to the URI definition in + <url href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</url>, + for example <c>"http://www.erlang.org"</c></p> + <p><c>status_line() = {http_version(), status_code(), reason_phrase()}</c></p> + <p><c>http_version() = string()</c>, for example, <c>"HTTP/1.1"</c></p> + <p><c>status_code() = integer()</c></p> + <p><c>reason_phrase() = string()</c></p> + <p><c>content_type() = string()</c></p> + <p><c>headers() = [header()]</c></p> + <p><c>header() = {field(), value()}</c></p> + <p><c>field() = string()</c></p> + <p><c>value() = string()</c></p> + <taglist> + <tag><c>body()</c></tag> + <item><p>= <c>string() | binary()</c></p> + <p>| <c>{fun(accumulator())</c></p> + <p><c> -> body_processing_result(), accumulator()}</c></p> + <p>| <c>{chunkify, fun(accumulator())</c></p> + <p><c> -> body_processing_result(), accumulator()}</c></p> + </item> + </taglist> + <p><c>body_processing_result() = eof | {ok, iolist(), accumulator()}</c></p> + <p><c>accumulator() = term()</c></p> + <p><c>filename() = string()</c></p> + <p>For more information about HTTP, see + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>.</p> +</section> <section> - <title>SSL DATA TYPES </title> + <title>SSL DATA TYPES</title> <p>See <seealso marker="ssl:ssl">ssl(3)</seealso> for information - about ssl options (<c>ssloptions()</c>). </p> + about <c>SSL</c> options (<c>ssloptions()</c>). </p> </section> <section> - <title>HTTP CLIENT SERVICE START/STOP </title> + <title>HTTP CLIENT SERVICE START/STOP</title> - <p>A HTTP client can be configured to start when starting the inets + <p>An HTTP client can be configured to start when starting the <c>Inets</c> application or started dynamically in runtime by calling the - inets application API <c>inets:start(httpc, ServiceConfig)</c>, or - <c>inets:start(httpc, ServiceConfig, How)</c> - see <seealso marker="inets">inets(3)</seealso>. Below follows a - description of the available configuration options.</p> + <c>Inets</c> application API <c>inets:start(httpc, ServiceConfig)</c> + or <c>inets:start(httpc, ServiceConfig, How)</c>, + see <seealso marker="inets">inets(3)</seealso>. + The configuration options are as follows:</p> <taglist> <tag>{profile, profile()}</tag> - <item>Name of the profile, see - common data types below, this option is mandatory.</item> + <item><p>Name of the profile, see + <seealso marker="#DATA_TYPES">DATA TYPES</seealso>. + This option is mandatory.</p></item> <tag>{data_dir, path()}</tag> - <item>Directory where the profile - may save persistent data, if omitted all cookies will be treated - as session cookies.</item> + <item><p>Directory where the profile + can save persistent data. If omitted, all cookies are treated + as session cookies.</p></item> </taglist> <p>The client can be stopped using <c>inets:stop(httpc, Pid)</c> or <c>inets:stop(httpc, Profile)</c>.</p> - - <marker id="request1"></marker> </section> <funcs> + + <func> + <name>cancel_request(RequestId) -></name> + <name>cancel_request(RequestId, Profile) -> ok</name> + <fsummary>Cancels an asynchronous HTTP request.</fsummary> + <type> + <v>RequestId = request_id() - A unique identifier as returned + by request/4</v> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can be used.</d> + </type> + <desc> + <p>Cancels an asynchronous HTTP request. Notice that this does not guarantee + that the request response is not delivered. Because it is asynchronous, + the request can already have been completed when the cancellation arrives. + </p> + </desc> + </func> + + <func> + <name>cookie_header(Url) -> </name> + <name>cookie_header(Url, Profile | Opts) -> header() | {error, Reason}</name> + <name>cookie_header(Url, Opts, Profile) -> header() | {error, Reason}</name> + <fsummary>Returns the cookie header that would have been sent when + making a request to URL using the profile <c>Profile</c>.</fsummary> + <type> + <v>Url = url()</v> + <v>Opts = [cookie_header_opt()]</v> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c>.</d> + <v>cookie_header_opt() = {ipv6_host_with_brackets, boolean()}</v> + </type> + <desc> + <p>Returns the cookie header that would have been sent + when making a request to <c>Url</c> using profile <c>Profile</c>. + If no profile is specified, the default profile is used.</p> + <p>Option <c>ipv6_host_with_bracket</c> deals with how to + parse IPv6 addresses. For details, + see argument <c>Options</c> of + <seealso marker="#request-4">request/[4,5]</seealso>.</p> + </desc> + </func> + + <func> + <name>get_options(OptionItems) -> {ok, Values} | {error, Reason}</name> + <name>get_options(OptionItems, Profile) -> {ok, Values} | {error, Reason}</name> + <fsummary>Gets the currently used options.</fsummary> + <type> + <v>OptionItems = all | [option_item()]</v> + <v>option_item() = proxy | + https_proxy | + max_sessions | + keep_alive_timeout | + max_keep_alive_length | + pipeline_timeout | + max_pipeline_length | + cookies | + ipfamily | + ip | + port | + socket_opts | + verbose</v> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can used.</d> + <v>Values = [{option_item(), term()}]</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Retrieves the options currently used by the client.</p> + </desc> + </func> + + <func> + <name>info() -> list()</name> + <name>info(Profile) -> list()</name> + <fsummary>Produces a list of miscellaneous information.</fsummary> + <type> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can be used.</d> + </type> + <desc> + <p>Produces a list of miscellaneous information. + Intended for debugging. + If no profile is specified, the default profile is used.</p> + </desc> + </func> + + + <func> + <name>reset_cookies() -> void()</name> + <name>reset_cookies(Profile) -> void()</name> + <fsummary>Resets the cookie database.</fsummary> + <type> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can be used.</d> + </type> + <desc> + <p>Resets (clears) the cookie database for the specified + <c>Profile</c>. If no profile is specified the default profile + is used.</p> + </desc> + </func> + <func> <name>request(Url) -> </name> <name>request(Url, Profile) -> {ok, Result} | {error, Reason}</name> - <fsummary>Sends a get HTTP-request</fsummary> + <fsummary>Sends a get HTTP request.</fsummary> <type> - <v>Url = url() </v> + <v>Url = url()</v> <v>Result = {status_line(), headers(), Body} | - {status_code(), Body} | request_id() </v> + {status_code(), Body} | request_id()</v> <v>Body = string() | binary()</v> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> - <v>Reason = term() </v> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can be used.</d> + <v>Reason = term()</v> </type> <desc> <p>Equivalent to <c>httpc:request(get, {Url, []}, [], [])</c>.</p> - - <marker id="request2"></marker> </desc> </func> <func> - <name>request(Method, Request, HTTPOptions, Options) -> </name> + <name>request(Method, Request, HTTPOptions, Options) -></name> <name>request(Method, Request, HTTPOptions, Options, Profile) -> {ok, Result} | {ok, saved_to_file} | {error, Reason}</name> - <fsummary>Sends a HTTP-request</fsummary> + <fsummary>Sends an HTTP request.</fsummary> <type> - <v>Method = method() </v> + <v>Method = method()</v> <v>Request = request()</v> <v>HTTPOptions = http_options()</v> <v>http_options() = [http_option()]</v> @@ -191,215 +300,200 @@ filename() = string() {socket_opts, socket_opts()} | {receiver, receiver()}, {ipv6_host_with_brackets, boolean()}}</v> - <v>stream_to() = none | self | {self, once} | filename() </v> + <v>stream_to() = none | self | {self, once} | filename()</v> <v>socket_opts() = [socket_opt()]</v> - <v>receiver() = pid() | function()/1 | {Module, Function, Args} </v> - <v>Module = atom() </v> - <v>Function = atom() </v> - <v>Args = list() </v> - <v>body_format() = string | binary </v> + <v>receiver() = pid() | function()/1 | {Module, Function, Args}</v> + <v>Module = atom()</v> + <v>Function = atom()</v> + <v>Args = list()</v> + <v>body_format() = string | binary</v> <v>Result = {status_line(), headers(), Body} | - {status_code(), Body} | request_id() </v> + {status_code(), Body} | request_id()</v> <v>Body = string() | binary()</v> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can be used.</d> <v>Reason = {connect_failed, term()} | - {send_failed, term()} | term() </v> + {send_failed, term()} | term()</v> </type> <desc> - <p>Sends a HTTP-request. The function can be both synchronous - and asynchronous. In the later case the function will return - <c>{ok, RequestId}</c> and later on the information will be delivered - to the <c>receiver</c> depending on that value. </p> + <p>Sends an HTTP request. The function can be both synchronous + and asynchronous. In the latter case, the function returns + <c>{ok, RequestId}</c> and then the information is delivered + to the <c>receiver</c> depending on that value.</p> - <p>Http option (<c>http_option()</c>) details: </p> + <p>HTTP option (<c>http_option()</c>) details:</p> <marker id="request2_http_options"></marker> <taglist> <tag><c><![CDATA[timeout]]></c></tag> <item> - <p>Timeout time for the request. </p> - <p>The clock starts ticking as soon as the request has been - sent. </p> - <p>Time is in milliseconds. </p> - <p>Defaults to <c>infinity</c>. </p> + <p>Time-out time for the request.</p> + <p>The clock starts ticking when the request is sent.</p> + <p>Time is in milliseconds.</p> + <p>Default is <c>infinity</c>.</p> </item> <tag><c><![CDATA[connect_timeout]]></c></tag> <item> - <p>Connection timeout time, used during the initial request, - when the client is <em>connecting</em> to the server. </p> - <p>Time is in milliseconds. </p> - <p>Defaults to the value of the <c>timeout</c> option. </p> + <p>Connection time-out time, used during the initial request, + when the client is <em>connecting</em> to the server.</p> + <p>Time is in milliseconds.</p> + <p>Default is the value of option <c>timeout</c>.</p> </item> <tag><c><![CDATA[ssl]]></c></tag> <item> - <p>This is the default ssl config option, currently defaults to - <c>essl</c>, see below. </p> - <p>Defaults to <c>[]</c>. </p> - </item> - - <tag><c><![CDATA[essl]]></c></tag> - <item> - <p>If using the Erlang based implementation of SSL, - these SSL-specific options are used. </p> - <p>Defaults to <c>[]</c>. </p> + <p>This is the <c>SSL/TLS</c> connectin configuration option.</p> + <p>Defaults to <c>[]</c>. See <seealso marker="ssl:ssl">ssl:connect/[2, 3,4]</seealso> for availble options.</p> </item> <tag><c><![CDATA[autoredirect]]></c></tag> <item> - <p>Should the client automatically retrieve the information - from the new URI and return that as the result instead - of a 30X-result code. </p> - <p>Note that for some 30X-result codes automatic redirect - is not allowed. In these cases the 30X-result will always - be returned. </p> - <p>Defaults to <c>true</c>. </p> + <p>The client automatically retrieves the information + from the new URI and returns that as the result, instead + of a 30X-result code.</p> + <p>For some 30X-result codes, automatic redirect + is not allowed. In these cases the 30X-result is always + returned.</p> + <p>Default is <c>true</c>.</p> </item> <tag><c><![CDATA[proxy_auth]]></c></tag> <item> - <p>A proxy-authorization header using the provided user name and - password will be added to the request. </p> + <p>A proxy-authorization header using the provided username and + password is added to the request.</p> </item> <tag><c><![CDATA[version]]></c></tag> <item> <p>Can be used to make the client act as an <c>HTTP/1.0</c> or <c>HTTP/0.9</c> client. By default this is an <c>HTTP/1.1</c> - client. When using <c>HTTP/1.0</c> persistent connections will - not be used. </p> - <p>Defaults to the string <c>"HTTP/1.1"</c>. </p> + client. When using <c>HTTP/1.0</c> persistent connections are + not used.</p> + <p>Default is the string <c>"HTTP/1.1"</c>.</p> </item> <tag><c><![CDATA[relaxed]]></c></tag> <item> - <p>If set to <c>true</c> workarounds for known server deviations - from the HTTP-standard are enabled. </p> - <p>Defaults to <c>false</c>. </p> + <p>If set to <c>true</c>, workarounds for known server deviations + from the HTTP-standard are enabled.</p> + <p>Default is <c>false</c>.</p> </item> <tag><c><![CDATA[url_encode]]></c></tag> <item> - <p>Will apply Percent-encoding, also known as URL encoding on the + <p>Applies Percent-encoding, also known as URL encoding on the URL.</p> - <p>Defaults to <c>false</c>. </p> + <p>Default is <c>false</c>.</p> </item> </taglist> - <p>Option (<c>option()</c>) details: </p> + <p>Option (<c>option()</c>) details:</p> <taglist> <tag><c><![CDATA[sync]]></c></tag> <item> - <p>Shall the request be synchronous or asynchronous. </p> - <p>Defaults to <c>true</c>. </p> + <p>Option for the request to be synchronous or asynchronous.</p> + <p>Default is <c>true</c>.</p> </item> <tag><c><![CDATA[stream]]></c></tag> <item> <p>Streams the body of a 200 or 206 response to the calling process or to a file. When streaming to the calling process - using the option <c>self</c> the following stream messages - will be sent to that process: <c>{http, {RequestId, + using option <c>self</c>, the following stream messages + are sent to that process: <c>{http, {RequestId, stream_start, Headers}}, {http, {RequestId, stream, - BinBodyPart}}, {http, {RequestId, stream_end, Headers}}</c>. When - streaming to the calling processes using the option - <c>{self, once}</c> the first message will have an additional - element e.i. <c>{http, {RequestId, stream_start, Headers, Pid}}</c>, - this is the process id that should be used as an argument to + BinBodyPart}}, and {http, {RequestId, stream_end, Headers}}</c>.</p> + <p>When streaming to the calling processes using option + <c>{self, once}</c>, the first message has an extra + element, that is, <c>{http, {RequestId, stream_start, Headers, Pid}}</c>. + This is the process id to be used as an argument to <c>http:stream_next/1</c> to trigger the next message to be sent to - the calling process. </p> - <p>Note that it is possible that chunked encoding will add + the calling process.</p> + <p>Notice that chunked encoding can add headers so that there are more headers in the <c>stream_end</c> - message than in the <c>stream_start</c>. - When streaming to a file and the request is asynchronous the - message <c>{http, {RequestId, saved_to_file}}</c> will be sent. </p> - <p>Defaults to <c>none</c>. </p> + message than in <c>stream_start</c>. + When streaming to a file and the request is asynchronous, the + message <c>{http, {RequestId, saved_to_file}}</c> is sent.</p> + <p>Default is <c>none</c>.</p> </item> <tag><c><![CDATA[body_format]]></c></tag> <item> - <p>Defines if the body shall be delivered as a string or as a + <p>Defines if the body is to be delivered as a string or binary. This option is only valid for the synchronous - request. </p> - <p>Defaults to <c>string</c>. </p> + request.</p> + <p>Default is <c>string</c>.</p> </item> <tag><c><![CDATA[full_result]]></c></tag> <item> - <p>Should a "full result" be returned to the caller (that is, - the body, the headers and the entire status-line) or not - (the body and the status code). </p> - <p>Defaults to <c>true</c>. </p> + <p>Defines if a "full result" is to be returned to the caller (that is, + the body, the headers, and the entire status line) or not + (the body and the status code).</p> + <p>Default is <c>true</c>.</p> </item> <tag><c><![CDATA[headers_as_is]]></c></tag> <item> - <p>Shall the headers provided by the user be made - lower case or be regarded as case sensitive. </p> - <p>Note that the http standard requires them to be - case insenstive. This feature should only be used if there is + <p>Defines if the headers provided by the user are to be made + lower case or to be regarded as case sensitive.</p> + <p>The HTTP standard requires them to be + case insensitive. Use this feature only if there is no other way to communicate with the server or for testing - purpose. Also note that when this option is used no headers - will be automatically added, all necessary headers have to be - provided by the user. </p> - <p>Defaults to <c>false</c>. </p> + purpose. When this option is used, no headers + are automatically added. All necessary headers must be + provided by the user.</p> + <p>Default is <c>false</c>.</p> </item> <tag><c><![CDATA[socket_opts]]></c></tag> <item> <p>Socket options to be used for this and subsequent - request(s). </p> - <p>Overrides any value set by the - <seealso marker="#set_options">set_options</seealso> - function. </p> - <p>Note that the validity of the options are <em>not</em> - checked in any way. </p> - <p>Note that this may change the socket behaviour - (see <seealso marker="kernel:inet#setopts/2">inet:setopts/2</seealso>) - for an already existing one, and therefore an already connected - request handler. </p> - <p>By default the socket options set by the - <seealso marker="#set_options">set_options/1,2</seealso> - function are used when establishing a connection. </p> + requests.</p> + <p>Overrides any value set by function + <seealso marker="#set_options-1">set_options</seealso>.</p> + <p>The validity of the options is <em>not</em> checked by + the HTTP client they are assumed to be correct and passed + on to ssl application and inet driver, which may reject + them if they are not correct. Note that the current + implementation assumes the requests to the same host, port + combination will use the same socket options. + </p> + + <p>By default the socket options set by function + <seealso marker="#set_options-1">set_options/[1,2]</seealso> + are used when establishing a connection.</p> </item> <tag><c><![CDATA[receiver]]></c></tag> <item> - <p>Defines how the client will deliver the result of an - asynchronous request (<c>sync</c> has the value - <c>false</c>). </p> + <p>Defines how the client delivers the result of an + asynchronous request (<c>sync</c> has the value + <c>false</c>).</p> <taglist> <tag><c><![CDATA[pid()]]></c></tag> <item> - <p>Message(s) will be sent to this process in the format: </p> -<pre> -{http, ReplyInfo} -</pre> + <p>Messages are sent to this process in the format + <c>{http, ReplyInfo}</c>.</p> </item> <tag><c><![CDATA[function/1]]></c></tag> <item> - <p>Information will be delivered to the receiver via calls - to the provided fun: </p> -<pre> -Receiver(ReplyInfo) -</pre> + <p>Information is delivered to the receiver through calls + to the provided fun <c>Receiver(ReplyInfo)</c>.</p> </item> <tag><c><![CDATA[{Module, Function, Args}]]></c></tag> <item> - <p>Information will be delivered to the receiver via calls - to the callback function: </p> -<pre> -apply(Module, Function, [ReplyInfo | Args]) -</pre> + <p>Information is delivered to the receiver through calls + to the callback function + <c>apply(Module, Function, [ReplyInfo | Args])</c>.</p> </item> - </taglist> - <p>In all of the above cases, <c>ReplyInfo</c> has the following - structure: </p> + <p>In all of these cases, <c>ReplyInfo</c> has the following + structure:</p> <pre> {RequestId, saved_to_file} @@ -407,11 +501,10 @@ apply(Module, Function, [ReplyInfo | Args]) {RequestId, Result} {RequestId, stream_start, Headers} {RequestId, stream_start, Headers, HandlerPid} -{RequestId, stream, BinBodyPart} -{RequestId, stream_end, Headers} -</pre> +{RequestId, stream, BinBodyPart} +{RequestId, stream_end, Headers}</pre> - <p>Defaults to the <c>pid()</c> of the process calling the request + <p>Default is the <c>pid</c> of the process calling the request function (<c>self()</c>). </p> <marker id="ipv6_host_with_brackets"></marker> @@ -419,276 +512,178 @@ apply(Module, Function, [ReplyInfo | Args]) <tag><c><![CDATA[ipv6_host_with_brackets]]></c></tag> <item> - <p>When parsing the Host-Port part of an URI with a IPv6 address - with brackets, shall we retain those brackets (<c>true</c>) or - strip them (<c>false</c>). </p> - <p>Defaults to <c>false</c>. </p> + <p>Defines when parsing the Host-Port part of an URI with an IPv6 address + with brackets, if those brackets are to be retained (<c>true</c>) + or stripped (<c>false</c>).</p> + <p>Default is <c>false</c>.</p> </item> </taglist> - - <marker id="cancel_request"></marker> - </desc> - </func> - - <func> - <name>cancel_request(RequestId) -> </name> - <name>cancel_request(RequestId, Profile) -> ok</name> - <fsummary>Cancels an asynchronous HTTP-request.</fsummary> - <type> - <v>RequestId = request_id() - A unique identifier as returned - by request/4</v> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> - </type> - <desc> - <p>Cancels an asynchronous HTTP-request. Note this does not guarantee - that the request response will not be delivered, as it is asynchronous the - the request may already have been completed when the cancellation arrives. - </p> - - <marker id="set_options"></marker> </desc> </func> + <func> <name>set_options(Options) -> </name> <name>set_options(Options, Profile) -> ok | {error, Reason}</name> <fsummary>Sets options to be used for subsequent requests.</fsummary> <type> <v>Options = [Option]</v> - <v>Option = {proxy, {Proxy, NoProxy}} | - {https_proxy, {Proxy, NoProxy}} | - {max_sessions, MaxSessions} | - {max_keep_alive_length, MaxKeepAlive} | - {keep_alive_timeout, KeepAliveTimeout} | - {max_pipeline_length, MaxPipeline} | - {pipeline_timeout, PipelineTimeout} | - {cookies, CookieMode} | - {ipfamily, IpFamily} | - {ip, IpAddress} | - {port, Port} | - {socket_opts, socket_opts()} | - {verbose, VerboseMode} </v> - + <v>Option = {proxy, {Proxy, NoProxy}}</v> + <v>| {https_proxy, {Proxy, NoProxy}}</v> + <v>| {max_sessions, MaxSessions}</v> + <v>| {max_keep_alive_length, MaxKeepAlive}</v> + <v>| {keep_alive_timeout, KeepAliveTimeout}</v> + <v>| {max_pipeline_length, MaxPipeline}</v> + <v>| {pipeline_timeout, PipelineTimeout}</v> + <v>| {cookies, CookieMode}</v> + <v>| {ipfamily, IpFamily}</v> + <v>| {ip, IpAddress}</v> + <v>| {port, Port}</v> + <v>| {socket_opts, socket_opts()}</v> + <v>| {verbose, VerboseMode}</v> <v>Proxy = {Hostname, Port}</v> - <v>Hostname = string() </v> - <d>ex: "localhost" or "foo.bar.se"</d> + <v>Hostname = string()</v> + <d>Example: "localhost" or "foo.bar.se"</d> <v>Port = integer()</v> - <d>ex: 8080 </d> + <d>Example: 8080</d> <v>NoProxy = [NoProxyDesc]</v> <v>NoProxyDesc = DomainDesc | HostName | IPDesc</v> <v>DomainDesc = "*.Domain"</v> - <d>ex: "*.ericsson.se"</d> + <d>Example: "*.ericsson.se"</d> <v>IpDesc = string()</v> - <d>ex: "134.138" or "[FEDC:BA98" (all IP-addresses starting with 134.138 or FEDC:BA98), "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP-address).</d> - - <d>proxy defaults to {undefined, []} e.i. no proxy is configured and https_proxy defaults to - the value of proxy.</d> - - <v>MaxSessions = integer() </v> - <d>Default is <c>2</c>. - Maximum number of persistent connections to a host.</d> - <v>MaxKeepAlive = integer() </v> - <d>Default is <c>5</c>. - Maximum number of outstanding requests on the same connection to - a host.</d> - <v>KeepAliveTimeout = integer() </v> - <d>Default is <c>120000</c> (= 2 min). - If a persistent connection is idle longer than the + <d>Example: "134.138" or "[FEDC:BA98" + (all IP addresses starting with 134.138 or FEDC:BA98), + "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP address).</d> + <d><c>proxy</c> defaults to <c>{undefined, []}</c>, + that is, no proxy is configured and + <c>https_proxy</c> defaults to the value of <c>proxy</c>.</d> + <v>MaxSessions = integer()</v> + <d>Maximum number of persistent connections to a host. + Default is <c>2</c>.</d> + <v>MaxKeepAlive = integer()</v> + <d>Maximum number of outstanding requests on the same connection to + a host. Default is <c>5</c>.</d> + <v>KeepAliveTimeout = integer()</v> + <d>If a persistent connection is idle longer than the <c>keep_alive_timeout</c> in milliseconds, - the client will close the connection. - The server may also have such a time out but you should - not count on it!</d> - <v>MaxPipeline = integer() </v> - <d>Default is <c>2</c>. - Maximum number of outstanding requests on a pipelined connection - to a host.</d> - <v>PipelineTimeout = integer() </v> - <d>Default is <c>0</c>, - which will result in pipelining not being used. - If a persistent connection is idle longer than the + the client closes the connection. + The server can also have such a time-out but do not take that for granted. + Default is <c>120000</c> (= 2 min).</d> + <v>MaxPipeline = integer()</v> + <d>Maximum number of outstanding requests on a pipelined connection + to a host. Default is <c>2</c>.</d> + <v>PipelineTimeout = integer()</v> + <d>If a persistent connection is idle longer than the <c>pipeline_timeout</c> in milliseconds, - the client will close the connection. </d> - <v>CookieMode = enabled | disabled | verify </v> - <d>Default is <c>disabled</c>. - If Cookies are enabled all valid cookies will automatically be - saved in the client manager's cookie database. - If the option <c>verify</c> is used the function <c>store_cookies/2</c> - has to be called for the cookies to be saved.</d> - <v>IpFamily = inet | inet6 | inet6fb4 </v> - <d>By default <c>inet</c>. - When it is set to <c>inet6fb4</c> you can use both ipv4 and ipv6. - It first tries <c>inet6</c> and if that does not works falls back to <c>inet</c>. - The option is here to provide a workaround for buggy ipv6 stacks to ensure that - ipv4 will always work.</d> - <v>IpAddress = ip_address() </v> - <d>If the host has several network interfaces, this option specifies which one to use. - See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d> - <v>Port = integer() </v> - <d>Specify which local port number to use. - See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d> + the client closes the connection. Default is <c>0</c>, + which results in pipelining not being used.</d> + <v>CookieMode = enabled | disabled | verify</v> + <d>If cookies are enabled, all valid cookies are automatically + saved in the cookie database of the client manager. + If option <c>verify</c> is used, function <c>store_cookies/2</c> + has to be called for the cookies to be saved. + Default is <c>disabled</c>.</d> + <v>IpFamily = inet | inet6 </v> + <d>Default is <c>inet</c>.</d> + <v>IpAddress = ip_address()</v> + <d>If the host has several network interfaces, this option specifies + which one to use. + See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> + for details.</d> + <v>Port = integer()</v> + <d>Local port number to use. + See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> + for details.</d> <v>socket_opts() = [socket_opt()]</v> <d>The options are appended to the socket options used by the - client. </d> + client.</d> <d>These are the default values when a new request handler is started (for the initial connect). They are passed directly - to the underlying transport (gen_tcp or ssl) <em>without</em> - verification! </d> - <v>VerboseMode = false | verbose | debug | trace </v> + to the underlying transport (<c>gen_tcp</c> or <c>SSL</c>) + <em>without</em> verification.</d> + <v>VerboseMode = false | verbose | debug | trace</v> <d>Default is <c>false</c>. This option is used to switch on (or off) - different levels of erlang trace on the client. + different levels of Erlang trace on the client. It is a debug feature.</d> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can be used.</d> </type> <desc> <p>Sets options to be used for subsequent requests.</p> <note> - <p>If possible the client will keep its connections - alive and use persistent connections - with or without pipeline depending on configuration + <p>If possible, the client keeps its connections + alive and uses persistent connections + with or without pipeline depending on configuration and current circumstances. The HTTP/1.1 specification does not - provide a guideline for how many requests would be - ideal to be sent on a persistent connection, - this very much depends on the - application. Note that a very long queue of requests may cause a - user perceived delay as earlier requests may take a long time - to complete. The HTTP/1.1 specification does suggest a - limit of 2 persistent connections per server, which is the - default value of the <c>max_sessions</c> option. </p> + provide a guideline for how many requests that are + ideal to be sent on a persistent connection. + This depends much on the application.</p> + <p>A long queue of requests can cause a + user-perceived delay, as earlier requests can take a long time + to complete. The HTTP/1.1 specification suggests a + limit of two persistent connections per server, which is the + default value of option <c>max_sessions</c>.</p> </note> <marker id="get_options"></marker> </desc> </func> - - <func> - <name>get_options(OptionItems) -> {ok, Values} | {error, Reason}</name> - <name>get_options(OptionItems, Profile) -> {ok, Values} | {error, Reason}</name> - <fsummary>Gets the currently used options.</fsummary> - <type> - <v>OptionItems = all | [option_item()]</v> - <v>option_item() = proxy | - https_proxy - max_sessions | - keep_alive_timeout | - max_keep_alive_length | - pipeline_timeout | - max_pipeline_length | - cookies | - ipfamily | - ip | - port | - socket_opts | - verbose</v> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> - <v>Values = [{option_item(), term()}]</v> - <v>Reason = term() </v> - </type> - <desc> - <p>Retrieves the options currently used by the client.</p> - - <marker id="stream_next"></marker> - </desc> - </func> - - <func> - <name>stream_next(Pid) -> ok</name> - <fsummary> Triggers the next message to be streamed, e.i. - same behavior as active once for sockets. - </fsummary> - <type> - <v>Pid = pid() - as received in the stream_start message</v> - </type> - <desc> - <p>Triggers the next message to be streamed, e.i. - same behavior as active once for sockets. </p> - - <marker id="verify_cookies"></marker> - <marker id="store_cookies"></marker> - </desc> - </func> - + <func> <name>store_cookies(SetCookieHeaders, Url) -> </name> <name>store_cookies(SetCookieHeaders, Url, Profile) -> ok | {error, Reason}</name> - <fsummary>Saves the cookies defined in SetCookieHeaders in the client profile's cookie database.</fsummary> + <fsummary>Saves the cookies defined in <c>SetCookieHeaders</c> in the + client profile cookie database.</fsummary> <type> <v>SetCookieHeaders = headers() - where field = "set-cookie"</v> <v>Url = url()</v> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> - </type> - <desc> - <p>Saves the cookies defined in SetCookieHeaders - in the client profile's cookie database. You need to - call this function if you have set the option <c>cookies</c> - to <c>verify</c>. - If no profile is specified the default profile will be used. </p> - - <marker id="cookie_header"></marker> - </desc> - </func> - - <func> - <name>cookie_header(Url) -> </name> - <name>cookie_header(Url, Profile | Opts) -> header() | {error, Reason}</name> - <name>cookie_header(Url, Opts, Profile) -> header() | {error, Reason}</name> - <fsummary>Returns the cookie header that would be sent when - making a request to Url using the profile <c>Profile</c>.</fsummary> - <type> - <v>Url = url()</v> - <v>Opts = [cookie_header_opt()]</v> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> - <v>cookie_header_opt() = {ipv6_host_with_brackets, boolean()}</v> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can be used.</d> </type> <desc> - <p>Returns the cookie header that would be sent - when making a request to <c>Url</c> using the profile <c>Profile</c>. - If no profile is specified the default profile will be used. </p> - <p>The option <c>ipv6_host_with_bracket</c> deals with how to - parse IPv6 addresses. - See the <c>Options</c> argument of the - <seealso marker="#request2">request/4,5</seealso> for more info. </p> - - <marker id="reset_cookies"></marker> + <p>Saves the cookies defined in <c>SetCookieHeaders</c> + in the client profile cookie database. + Call this function if option <c>cookies</c> is set to <c>verify</c>. + If no profile is specified, the default profile is used.</p> </desc> </func> - <func> - <name>reset_cookies() -> void()</name> - <name>reset_cookies(Profile) -> void()</name> - <fsummary>Reset the cookie database.</fsummary> + <name>stream_next(Pid) -> ok</name> + <fsummary>Triggers the next message to be streamed, that is, + the same behavior as active one for sockets. + </fsummary> <type> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> + <v>Pid = pid()</v> + <d>As received in the <c>stream_start message</c></d> </type> <desc> - <p>Resets (clears) the cookie database for the specified - <c>Profile</c>. If no profile is specified the default profile - will be used. </p> + <p>Triggers the next message to be streamed, that is, + the same behavior as active ones for sockets.</p> - <marker id="which_cookies"></marker> + <marker id="verify_cookies"></marker> + <marker id="store_cookies"></marker> </desc> </func> - - + <func> <name>which_cookies() -> cookies()</name> <name>which_cookies(Profile) -> cookies()</name> - <fsummary>Dumps out the entire cookie database.</fsummary> + <fsummary>Dumps the entire cookie database.</fsummary> <type> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can be used.</d> <v>cookies() = [cookie_stores()]</v> <v>cookie_stores() = {cookies, cookies()} | {session_cookies, cookies()}</v> <v>cookies() = [cookie()]</v> <v>cookie() = term()</v> </type> <desc> - <p>This function produces a list of the entire cookie database. - It is intended for debugging/testing purposes. - If no profile is specified the default profile will be used. </p> - - <marker id="which_sessions"></marker> + <p>Produces a list of the entire cookie database. + Intended for debugging/testing purposes. + If no profile is specified, the default profile is used.</p> </desc> </func> @@ -697,41 +692,29 @@ apply(Module, Function, [ReplyInfo | Args]) <name>which_sessions(Profile) -> session_info()</name> <fsummary>Produces a slightly processed dump of the sessions database.</fsummary> <type> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> + <v>Profile = profile() | pid()</v> + <d>When started <c>stand_alone</c> only the pid can be used.</d> <v>session_info() = {GoodSessions, BadSessions, NonSessions}</v> <v>GoodSessions = session()</v> <v>BadSessions = tuple()</v> <v>NonSessions = term()</v> </type> <desc> - <p>This function produces a slightly processed dump of the session + <p>Produces a slightly processed dump of the session database. It is intended for debugging. - If no profile is specified the default profile will be used. </p> - - <marker id="info"></marker> + If no profile is specified, the default profile is used.</p> </desc> </func> - <func> - <name>info() -> list()</name> - <name>info(Profile) -> list()</name> - <fsummary>Produces a list of miscelleneous info</fsummary> - <type> - <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> - </type> - <desc> - <p>This function produces a list of miscelleneous info. - It is intended for debugging. - If no profile is specified the default profile will be used. </p> - </desc> - </func> + </funcs> <section> <title>SEE ALSO</title> - <p>RFC 2616, <seealso marker="inets">inets(3)</seealso>, - <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>, - <seealso marker="ssl:ssl">ssl(3)</seealso> + <p><url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>, + <seealso marker="inets">inets(3)</seealso>, + <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>, + <seealso marker="ssl:ssl">ssl(3)</seealso> </p> </section> diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml index 7ea9b9318f..2a4aea41c2 100644 --- a/lib/inets/doc/src/httpd.xml +++ b/lib/inets/doc/src/httpd.xml @@ -31,191 +31,191 @@ </header> <module>httpd</module> <modulesummary>An implementation of an HTTP - 1.1 compliant Web server, as defined in RFC 2616. + 1.1 compliant web server, as defined in <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url> </modulesummary> <description> - <p>Documents the HTTP server start options, some administrative - functions and also specifies the Erlang Web server callback - API</p> + <p>This module provides the HTTP server start options, some administrative + functions, and specifies the Erlang web server callback + API.</p> </description> <section> - <title>COMMON DATA TYPES </title> + <title>DATA TYPES</title> <p>Type definitions that are used more than once in this module:</p> - <p><c>boolean() = true | false </c></p> - <p><c>string() = list of ASCII characters</c></p> - <p><c>path() = string() - representing a file or directory path.</c></p> - <p><c> ip_address() = {N1,N2,N3,N4} % IPv4 + <p><c>boolean() = true | false</c></p> + <p><c>string()</c> = list of ASCII characters</p> + <p><c>path() = string()</c> representing a file or a directory path</p> + <p><c> ip_address() = {N1,N2,N3,N4} % IPv4 | {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6</c></p> - <p><c>hostname() = string() - representing a host ex "foo.bar.com"</c></p> + <p><c>hostname() = string()</c> representing a host, for example, + "foo.bar.com"</p> <p><c>property() = atom()</c></p> </section> <section> - <title>ERLANG HTTP SERVER SERVICE START/STOP </title> - <p>A web server can be configured to start when starting the inets - application or started dynamically in runtime by calling the - Inets application API <c>inets:start(httpd, ServiceConfig)</c>, or + <title>ERLANG HTTP SERVER SERVICE START/STOP</title> + <p>A web server can be configured to start when starting the <c>Inets</c> + application, or dynamically in runtime by calling the + <c>Inets</c> application API <c>inets:start(httpd, ServiceConfig)</c> or <c>inets:start(httpd, ServiceConfig, How)</c>, - see <seealso marker="inets">inets(3)</seealso> Below follows a - description of the available configuration options, also called - properties.</p> + see <seealso marker="inets">inets(3)</seealso>. + The configuration options, also called + properties, are as follows:</p> <marker id="props_file"></marker> - <p><em>File properties</em></p> + <p><em>File Properties</em></p> <p>When the web server is started - at application start time the properties should be fetched from a - configuration file that could consist of a regular erlang property - list, e.i. <c>[{Option, Value}] </c> where <c> Option = property() + at application start time, the properties are to be fetched from a + configuration file that can consist of a regular Erlang property + list, that is, <c>[{Option, Value}]</c>, where <c> Option = property() </c> and <c>Value = term()</c>, followed by a full stop, or for - backwards compatibility an Apache like configuration file. If the - web server is started dynamically at runtime you may still specify - a file but you could also just specify the complete property + backwards compatibility, an Apache-like configuration file. If the + web server is started dynamically at runtime, + a file can still be specified but also the complete property list.</p> <taglist> <marker id="prop_proplist_file"></marker> <tag>{proplist_file, path()}</tag> <item> - <p>If this property is defined inets will expect to find - all other properties defined in this file. Note that the + <p>If this property is defined, <c>Inets</c> expects to find + all other properties defined in this file. The file must include all properties listed under mandatory - properties. </p> + properties.</p> </item> <marker id="prop_file"></marker> <tag>{file, path()}</tag> <item> - <p>If this property is defined inets will expect to find all - other properties defined in this file, that uses Apache like - syntax. Note that the file must include all properties listed - under mandatory properties. The Apache like syntax is the property, + <p>If this property is defined, <c>Inets</c> expects to find all + other properties defined in this file, which uses Apache-like + syntax. The file must include all properties listed + under mandatory properties. The Apache-like syntax is the property, written as one word where each new word begins with a capital, - followed by a white-space followed by the value followed by a - new line. Ex: </p> - + followed by a white-space, followed by the value, followed by a + new line.</p> + <p>Example:</p> <code> -{server_root, "/urs/local/www"} -> ServerRoot /usr/local/www - </code> +{server_root, "/urs/local/www"} -> ServerRoot /usr/local/www</code> - <p>With a few exceptions, that are documented + <p>A few exceptions are documented for each property that behaves differently, - and the special case {directory, {path(), PropertyList}} and - {security_directory, {Dir, PropertyList}} that are represented + and the special cases <c>{directory, {path(), PropertyList}}</c> + and <c>{security_directory, {Dir, PropertyList}}</c>, are represented as:</p> <pre> <![CDATA[ <Directory Dir> <Properties handled as described above> </Directory> - ]]> - </pre> + ]]></pre> </item> </taglist> <note> - <p>The properties proplist_file and file are mutually exclusive.</p> + <p>The properties <c>proplist_file</c> and <c>file</c> are mutually exclusive. Also newer properties may not be supported as Apache-like options, this is a legacy feature.</p> </note> <marker id="props_mand"></marker> - <p><em>Mandatory properties</em></p> + <p><em>Mandatory Properties</em></p> <taglist> <marker id="prop_port"></marker> <tag>{port, integer()} </tag> <item> - <p>The port that the HTTP server shall listen on. + <p>The port that the HTTP server listen to. If zero is specified as port, an arbitrary available port - will be picked and you can use the httpd:info/2 function to find - out which port was picked. </p> + is picked and function <c>httpd:info/2</c> can be used to + determine which port was picked.</p> </item> <marker id="prop_server_name"></marker> - <tag>{server_name, string()} </tag> + <tag>{server_name, string()}</tag> <item> - <p>The name of your server, normally a fully qualified domain name. </p> + <p>The name of your server, normally a fully qualified domain name.</p> </item> <marker id="prop_server_root"></marker> - <tag>{server_root, path()} </tag> + <tag>{server_root, path()}</tag> <item> - <p>Defines the server's home directory where log files etc can - be stored. Relative paths specified in other properties refer - to this directory. </p> + <p>Defines the home directory of the server, where log files, and so on, + can be stored. Relative paths specified in other properties refer + to this directory.</p> </item> <marker id="prop_doc_root"></marker> <tag>{document_root, path()}</tag> <item> - Defines the top directory for the documents that - are available on the HTTP server. + <p>Defines the top directory for the documents that + are available on the HTTP server.</p> </item> </taglist> <marker id="props_comm"></marker> - <p><em>Communication properties</em> </p> + <p><em>Communication Properties</em></p> <taglist> <marker id="prop_bind_address"></marker> - <tag>{bind_address, ip_address() | hostname() | any} </tag> + <tag>{bind_address, ip_address() | hostname() | any}</tag> <item> - <p>Defaults to <c>any</c>. Note that <c>any</c> is denoted <em>*</em> - in the apache like configuration file. </p> + <p>Default is <c>any</c>. <c>any</c> is denoted <em>*</em> + in the Apache-like configuration file.</p> </item> <marker id="profile"></marker> <tag>{profile, atom()}</tag> <item> - <p>Used together with <seealso marker="prop_bind_address"><c>bind_address</c></seealso> - and <seealso marker="prop_port"><c>port</c></seealso> to uniquely identify + <p>Used together with <seealso marker="#prop_bind_address"><c>bind_address</c></seealso> + and <seealso marker="#prop_port"><c>port</c></seealso> to uniquely identify a HTTP server. This can be useful in a virtualized environment, where there can be more that one server that has the same bind_address and port. If this property is not explicitly set, it is assumed that the - <seealso marker="prop_bind_address"><c>bind_address</c></seealso> and - <seealso marker="prop_port"><c>port</c></seealso>uniquely identifies the HTTP server. + <seealso marker="#prop_bind_address"><c>bind_address</c></seealso> and + <seealso marker="#prop_port"><c>port</c></seealso>uniquely identifies the HTTP server. </p> </item> <marker id="prop_socket_type"></marker> <tag>{socket_type, ip_comm | {essl, Config::proplist()}}</tag> <item> - <p> For ssl configuration options see <seealso marker="ssl:ssl#listen-2">ssl:listen/2</seealso> </p> - <p>Defaults to <c>ip_comm</c>. </p> + <p>For <c>SSL</c> configuration options, see + <seealso marker="ssl:ssl#listen-2">ssl:listen/2</seealso>.</p> + <p>Default is <c>ip_comm</c>.</p> </item> <marker id="prop_ipfamily"></marker> <tag>{ipfamily, inet | inet6 | inet6fb4}</tag> <item> - <p>Defaults to <c>inet6fb4. </c> </p> - <p>Note that this option is only used when the option - <c>socket_type</c> has the value <c>ip_comm</c>. </p> + <p>This option is only used when option + <c>socket_type</c> has value <c>ip_comm</c>.</p> + <p>Default is <c>inet6fb4</c>.</p> </item> <marker id="prop_minimum_bytes_per_second"></marker> <tag>{minimum_bytes_per_second, integer()}</tag> <item> - <p>If given, sets a minimum bytes per second value for connections.</p> - <p>If the value is not reached, the socket will close for that connection.</p> - <p>The option is good for reducing the risk of "slow dos" attacks.</p> + <p>If given, sets a minimum of bytes per second value for connections.</p> + <p>If the value is unreached, the socket closes for that connection.</p> + <p>The option is good for reducing the risk of "slow DoS" attacks.</p> </item> </taglist> <marker id="props_api_modules"></marker> - <p><em>Erlang Web server API modules</em> </p> + <p><em>Erlang Web Server API Modules</em> </p> <taglist> <marker id="prop_modules"></marker> <tag>{modules, [atom()]} </tag> <item> - <p>Defines which modules the HTTP server will use to handle - requests. Defaults to: <c>[mod_alias, mod_auth, mod_esi, + <p>Defines which modules the HTTP server uses when handling + requests. Default is <c>[mod_alias, mod_auth, mod_esi, mod_actions, mod_cgi, mod_dir, mod_get, mod_head, mod_log, - mod_disk_log] </c> - Note that some mod-modules are dependent on - others, so the order can not be entirely arbitrary. See the - <seealso marker="http_server"> Inets Web server Modules in the - Users guide</seealso> for more information. </p> + mod_disk_log]</c>. + Notice that some <c>mod</c>-modules are dependent on + others, so the order cannot be entirely arbitrary. See the + <seealso marker="http_server">Inets Web Server Modules</seealso> in the + User's Guide for details.</p> </item> </taglist> @@ -227,412 +227,413 @@ <tag>{customize, atom()}</tag> <item> <p>A callback module to customize the inets HTTP servers behaviour - see <seealso marker="http_custom_api"> httpd_custom_api</seealso> </p> + see <seealso marker="httpd_custom_api"> httpd_custom_api</seealso> </p> </item> <marker id="prop_disable_chunked_encoding"></marker> <tag>{disable_chunked_transfer_encoding_send, boolean()}</tag> <item> - <p>This property allows you to disable chunked - transfer-encoding when sending a response to a HTTP/1.1 - client, by default this is false. </p> + <p>Allows you to disable chunked + transfer-encoding when sending a response to an HTTP/1.1 + client. Default is <c>false</c>.</p> </item> <marker id="prop_keep_alive"></marker> <tag>{keep_alive, boolean()}</tag> <item> - <p>Instructs the server whether or not to use persistent + <p>Instructs the server whether to use persistent connections when the client claims to be HTTP/1.1 - compliant, default is true. </p> + compliant. Default is <c>true</c>.</p> </item> <marker id="prop_keep_alive_timeout"></marker> <tag>{keep_alive_timeout, integer()}</tag> <item> - <p>The number of seconds the server will wait for a + <p>The number of seconds the server waits for a subsequent request from the client before closing the - connection. Default is 150. </p> + connection. Default is <c>150</c>.</p> </item> <marker id="prop_max_body_size"></marker> <tag>{max_body_size, integer()}</tag> <item> - <p>Limits the size of the message body of HTTP request. - By the default there is no limit. </p> + <p>Limits the size of the message body of an HTTP request. + Default is no limit.</p> </item> <marker id="prop_max_clients"></marker> <tag>{max_clients, integer()}</tag> <item> <p>Limits the number of simultaneous requests that can be - supported. Defaults to 150. </p> + supported. Default is <c>150</c>.</p> </item> <marker id="prop_max_header_size"></marker> <tag>{max_header_size, integer()}</tag> <item> - <p>Limits the size of the message header of HTTP request. - Defaults to 10240. </p> + <p>Limits the size of the message header of an HTTP request. + Default is <c>10240</c>.</p> </item> <marker id="prop_max_content_length"></marker> <tag>{max_content_length, integer()}</tag> <item> - <p>Maximum Content-Length in an incoming request, in bytes. Requests - with content larger than this are answered with Status 413. - Defaults to 100000000 (100 MB). + <p>Maximum content-length in an incoming request, in bytes. Requests + with content larger than this are answered with status 413. + Default is <c>100000000</c> (100 MB). </p> </item> <marker id="prop_max_uri"></marker> <tag>{max_uri_size, integer()}</tag> <item> - <p>Limits the size of the HTTP request URI. By - default there is no limit. </p> + <p>Limits the size of the HTTP request URI. + Default is no limit.</p> </item> <marker id="prop_max_keep_alive_req"></marker> <tag>{max_keep_alive_request, integer()}</tag> <item> - <p>The number of request that a client can do on one + <p>The number of requests that a client can do on one connection. When the server has responded to the number of - requests defined by max_keep_alive_requests the server close the - connection. The server will close it even if there are queued - request. Defaults to no limit. </p> + requests defined by <c>max_keep_alive_requests</c>, the server + closes the connection. The server closes it even if there are + queued request. Default is no limit.</p> </item> </taglist> <marker id="props_admin"></marker> - <p><em>Administrative properties</em></p> + <p><em>Administrative Properties</em></p> <taglist> <marker id="prop_mime_types"></marker> <tag>{mime_types, [{MimeType, Extension}] | path()}</tag> <item> - <p>Where MimeType = string() and Extension = string(). + <p><c>MimeType = string()</c> and <c>Extension = string()</c>. Files delivered to the client are MIME typed according to RFC 1590. File suffixes are mapped to MIME types before file delivery. The mapping between file suffixes and MIME types can be specified - as an Apache like file as well as directly in the property list. Such - a file may look like:</p> + as an Apache-like file or directly in the property list. Such + a file can look like the follwoing:</p> <pre> # MIME type Extension text/html html htm -text/plain asc txt - </pre> +text/plain asc txt</pre> - <p>Defaults to [{"html","text/html"},{"htm","text/html"}]</p> + <p>Default is [{"html","text/html"},{"htm","text/html"}].</p> </item> <marker id="prop_mime_type"></marker> <tag>{mime_type, string()}</tag> <item> - <p>When the server is asked to provide a document type which - cannot be determined by the MIME Type Settings, the server will - use this default type. </p> + <p>When the server is asked to provide a document type that + cannot be determined by the MIME Type Settings, the server + uses this default type.</p> </item> <marker id="prop_server_admin"></marker> <tag>{server_admin, string()}</tag> <item> - <p>ServerAdmin defines the email-address of the server - administrator, to be included in any error messages returned by - the server. </p> + <p>Defines the email-address of the server + administrator to be included in any error messages returned by + the server.</p> </item> <marker id="prop_server_tokens"></marker> <tag>{server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}</tag> <item> - <p>ServerTokens defines how the value of the server header - should look. </p> - <p>Example: Assuming the version of inets is 5.8.1, - here is what the server header string could look like for - the different values of server-tokens: </p> - <pre> -none "" % A Server: header will not be generated -prod "inets" -major "inets/5" -minor "inets/5.8" -minimal "inets/5.8.1" -os "inets/5.8.1 (unix)" -full "inets/5.8.1 (unix/linux) OTP/R15B" -{private, "foo/bar"} "foo/bar" - </pre> - <p>By default, the value is as before, which is <c>minimal</c>. </p> + <p>Defines the look of the value of the server header.</p> + <p>Example: Assuming the version of <c>Inets</c> is 5.8.1, + the server header string can look as follows for + the different values of server-tokens:</p> + <taglist> + <tag><c>none</c></tag> + <item><p>"" % A Server: header will not be generated</p></item> + <tag><c>prod</c></tag> + <item><p>"inets"</p></item> + <tag><c>major</c></tag> + <item><p>"inets/5"</p></item> + <tag><c>minor</c></tag> + <item><p>"inets/5.8"</p></item> + <tag><c>minimal</c></tag> + <item><p>"inets/5.8.1"</p></item> + <tag><c>os</c></tag> + <item><p>"inets/5.8.1 (unix)"</p></item> + <tag><c>full</c></tag> + <item><p>"inets/5.8.1 (unix/linux) OTP/R15B"</p></item> + <tag><c>{private, "foo/bar"}</c></tag> + <item><p>"foo/bar"</p></item> + </taglist> + <p>By default, the value is as before, that is, <c>minimal</c>.</p> </item> <marker id="prop_log_format"></marker> <tag>{log_format, common | combined}</tag> <item> - <p>Defines if access logs should be written according to the common - log format or to the extended common log format. - The <c>common</c> format is one line that looks like this: - <c>remotehost rfc931 authuser [date] "request" status bytes</c></p> - - <pre> -remotehost - Remote -rfc931 - The client's remote username (RFC 931). -authuser - The username with which the user authenticated - himself. -[date] - Date and time of the request (RFC 1123). -"request" - The request line exactly as it came from the client - (RFC 1945). -status - The HTTP status code returned to the client - (RFC 1945). -bytes - The content-length of the document transferred. - </pre> - - <p>The <c>combined</c> format is on line that look like this: + <p>Defines if access logs are to be written according to the <c>common</c> + log format or the extended common log format. + The <c>common</c> format is one line looking like this: + <c>remotehost rfc931 authuser [date] "request" status bytes</c>.</p> + <p>Here:</p> + <taglist> + <tag><c>remotehost</c></tag> + <item>Remote.</item> + <tag><c>rfc931</c></tag> + <item>The remote username of the client (<url href="http://www.ietf.org/rfc/rfc931.txt">RFC 931</url>).</item> + <tag><c>authuser</c></tag> + <item>The username used for authentication.</item> + <tag><c>[date]</c></tag> + <item>Date and time of the request (<url href="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</url>).</item> + <tag><c>"request"</c></tag> + <item>The request line as it came from the client (<url href="http://www.ietf.org/rfc/rfc1945.txt">RFC 1945</url>).</item> + <tag><c>status</c></tag> + <item>The HTTP status code returned to the client (<url href="http://www.ietf.org/rfc/rfc1945.txt">RFC 1945</url>).</item> + <tag><c>bytes</c></tag> + <item>The content-length of the document transferred.</item> + </taglist> + + <p>The <c>combined</c> format is one line looking like this: <c>remotehost rfc931 authuser [date] "request" status bytes "referer" "user_agent" </c></p> + <p>In addition to the earlier:</p> + <taglist> + <tag><c>"referer"</c></tag> + <item>The URL the client was on before + requesting the URL (if it could not be determined, + a minus sign is placed in this field).</item> + <tag><c>"user_agent"</c></tag> + <item>The software the client claims to be using (if it + could not be determined, a minus sign is placed in + this field).</item> + </taglist> - <pre> -"referer" - The url the client was on before - requesting your url. (If it could not be determined - a minus sign will be placed in this field) -"user_agent" - The software the client claims to be using. (If it - could not be determined a minus sign will be placed in - this field) - </pre> - - <p>This affects the access logs written by mod_log and mod_disk_log. - </p> - + <p>This affects the access logs written by <c>mod_log</c> and + <c>mod_disk_log</c>. + </p> </item> <marker id="prop_elog_format"></marker> <tag>{error_log_format, pretty | compact}</tag> <item> - <p>Defaults to pretty. If the error log is meant to be read - directly by a human <c>pretty</c> will be the best - option. <c>pretty</c> has the format corresponding to: - </p> + <p>Default is <c>pretty</c>. If the error log is meant to be read + directly by a human, <c>pretty</c> is the best option.</p> + <p><c>pretty</c> has a format corresponding to:</p> - <code>io:format("[~s] ~s, reason: ~n ~p ~n~n", [Date, Msg, Reason]). - </code> + <code>io:format("[~s] ~s, reason: ~n ~p ~n~n", [Date, Msg, Reason]).</code> - <p><c>compact</c> has the format corresponding to:</p> + <p><c>compact</c> has a format corresponding to:</p> - <code>io:format("[~s] ~s, reason: ~w ~n", [Date, Msg, Reason]). - </code> + <code>io:format("[~s] ~s, reason: ~w ~n", [Date, Msg, Reason]).</code> - <p>This affects the error logs written by mod_log and mod_disk_log. + <p>This affects the error logs written by <c>mod_log</c> and + <c>mod_disk_log</c>. </p> </item> </taglist> <marker id="props_alias"></marker> - <p><em>URL aliasing properties - requires mod_alias</em></p> + <p><em>URL Aliasing Properties - Requires mod_alias</em></p> <taglist> <marker id="prop_alias"></marker> <tag>{alias, {Alias, RealName}}</tag> <item> - <p>Where Alias = string() and RealName = string(). - The Alias property allows documents to be stored in the local file - system instead of the document_root location. URLs with a path that - begins with url-path is mapped to local files that begins with + <p><c>Alias = string()</c> and <c>RealName = string()</c>. + <c>alias</c> allows documents to be stored in the local file + system instead of the <c>document_root</c> location. URLs with a path + beginning with url-path is mapped to local files beginning with directory-filename, for example: <code>{alias, {"/image", "/ftp/pub/image"}}</code> - and an access to http://your.server.org/image/foo.gif would refer to - the file /ftp/pub/image/foo.gif. </p> + Access to http://your.server.org/image/foo.gif would refer to + the file /ftp/pub/image/foo.gif.</p> </item> <marker id="prop_re_write"></marker> <tag>{re_write, {Re, Replacement}}</tag> <item> - <p>Where Re = string() and Replacement = string(). - The ReWrite property allows documents to be stored in the local file - system instead of the document_root location. URLs are rewritten - by re:replace/3 to produce a path in the local filesystem. - For example: + <p><c>Re = string()</c> and <c>Replacement = string()</c>. + <c>re_write</c> allows documents to be stored in the local file + system instead of the <c>document_root</c> location. URLs are rewritten + by <c>re:replace/3</c> to produce a path in the local file-system, + for example: <code>{re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}}</code> - and an access to http://your.server.org/~bob/foo.gif would refer to + Access to http://your.server.org/~bob/foo.gif would refer to the file /home/bob/public/foo.gif. - In an Apache like configuration file the Re is separated - from Replacement with one single space, and as expected - backslashes do not need to be backslash escaped so the + In an Apache-like configuration file, <c>Re</c> is separated + from <c>Replacement</c> with one single space, and as expected + backslashes do not need to be backslash escaped, the same example would become: <code>ReWrite ^/[~]([^/]+)(.*)$ /home/\1/public\2</code> - Beware of trailing space in Replacement that will be used. - If you must have a space in Re use e.g the character encoding - <code>\040</code> see <seealso marker="stdlib:re">re(3)</seealso>. </p> + Beware of trailing space in <c>Replacement</c> to be used. + If you must have a space in <c>Re</c>, use, for example, the character + encoding <c>\040</c>, see + <seealso marker="stdlib:re">re(3)</seealso>.</p> </item> <marker id="prop_dir_idx"></marker> <tag>{directory_index, [string()]}</tag> <item> - <p>DirectoryIndex specifies a list of resources to look for - if a client requests a directory using a / at the end of the - directory name. file depicts the name of a file in the - directory. Several files may be given, in which case the server - will return the first it finds, for example: + <p><c>directory_index</c> specifies a list of resources to look for + if a client requests a directory using a <c>/</c> at the end of the + directory name. <c>file</c> depicts the name of a file in the + directory. Several files can be given, in which case the server + returns the first it finds, for example: <code>{directory_index, ["index.hml", "welcome.html"]}</code> - and access to http://your.server.org/docs/ would return + Access to http://your.server.org/docs/ would return http://your.server.org/docs/index.html or - http://your.server.org/docs/welcome.html if index.html do not - exist. </p> + http://your.server.org/docs/welcome.html if index.html does not + exist.</p> </item> </taglist> <marker id="props_cgi"></marker> - <p><em>CGI properties - requires mod_cgi</em></p> + <p><em>CGI Properties - Requires mod_cgi</em></p> <taglist> <marker id="prop_script_alias"></marker> <tag>{script_alias, {Alias, RealName}}</tag> <item> - <p>Where Alias = string() and RealName = string(). - Has the same behavior as the Alias property, except that - it also marks the target directory as containing CGI + <p><c>Alias = string()</c> and <c>RealName = string()</c>. + Have the same behavior as property <c>alias</c>, except that + they also mark the target directory as containing CGI scripts. URLs with a path beginning with url-path are mapped to scripts beginning with directory-filename, for example: <code>{script_alias, {"/cgi-bin/", "/web/cgi-bin/"}}</code> - and an access to http://your.server.org/cgi-bin/foo would cause - the server to run the script /web/cgi-bin/foo. </p> + Access to http://your.server.org/cgi-bin/foo would cause + the server to run the script /web/cgi-bin/foo.</p> </item> <marker id="prop_script_re_write"></marker> <tag>{script_re_write, {Re, Replacement}}</tag> <item> - <p>Where Re = string() and Replacement = string(). - Has the same behavior as the ReWrite property, except that - it also marks the target directory as containing CGI + <p><c>Re = string()</c> and <c>Replacement = string()</c>. + Have the same behavior as property <c>re_write</c>, except that + they also mark the target directory as containing CGI scripts. URLs with a path beginning with url-path are mapped to scripts beginning with directory-filename, for example: <code>{script_re_write, {"^/cgi-bin/(\\d+)/", "/web/\\1/cgi-bin/"}}</code> - and an access to http://your.server.org/cgi-bin/17/foo would cause - the server to run the script /web/17/cgi-bin/foo. </p> + Access to http://your.server.org/cgi-bin/17/foo would cause + the server to run the script /web/17/cgi-bin/foo.</p> </item> <marker id="prop_script_nocache"></marker> <tag>{script_nocache, boolean()}</tag> <item> - <p>If ScriptNoCache is set to true the HTTP server will by - default add the header fields necessary to prevent proxies from - caching the page. Generally this is something you want. Defaults - to false. </p> + <p>If <c>script_nocache</c> is set to <c>true</c>, the HTTP server by + default adds the header fields necessary to prevent proxies from + caching the page. Generally this is preferred. + Default to <c>false</c>.</p> </item> <marker id="prop_script_timeout"></marker> <tag>{script_timeout, integer()}</tag> <item> - <p>The time in seconds the web server will wait between each - chunk of data from the script. If the CGI-script not delivers - any data before the timeout the connection to the client will be - closed. Defaults to 15. </p> + <p>The time in seconds the web server waits between each + chunk of data from the script. If the CGI script does not deliver + any data before the timeout, the connection to the client is + closed. Default is <c>15</c>.</p> </item> <marker id="prop_action"></marker> <tag>{action, {MimeType, CgiScript}} - requires mod_action</tag> <item> - <p>Where MimeType = string() and CgiScript = string(). - Action adds an action, which will activate a cgi-script - whenever a file of a certain mime-type is requested. It + <p><c>MimeType = string()</c> and <c>CgiScript = string()</c>. + <c>action</c> adds an action activating a CGI script + whenever a file of a certain MIME type is requested. It propagates the URL and file path of the requested document using the standard CGI PATH_INFO and PATH_TRANSLATED environment - variables. + variables.</p> + <p>Example:</p> <code>{action, {"text/plain", "/cgi-bin/log_and_deliver_text"}}</code> - </p> </item> <marker id="prop_script"></marker> <tag>{script, {Method, CgiScript}} - requires mod_action</tag> <item> - <p>Where Method = string() and CgiScript = string(). - Script adds an action, which will activate a cgi-script + <p><c>Method = string()</c> and <c>CgiScript = string()</c>. + <c>script</c> adds an action activating a CGI script whenever a file is requested using a certain HTTP method. The - method is either GET or POST as defined in RFC 1945. It + method is either GET or POST, as defined in <url href="http://www.ietf.org/rfc/rfc1945.txt">RFC 1945</url>. It propagates the URL and file path of the requested document using the standard CGI PATH_INFO and PATH_TRANSLATED environment - variables. + variables.</p> + <p>Example:</p> <code>{script, {"PUT", "/cgi-bin/put"}}</code> - </p> </item> </taglist> <marker id="props_esi"></marker> - <p><em>ESI properties - requires mod_esi</em></p> + <p><em>ESI Properties - Requires mod_esi</em></p> <taglist> <marker id="prop_esi_alias"></marker> <tag>{erl_script_alias, {URLPath, [AllowedModule]}}</tag> <item> - <p>Where URLPath = string() and AllowedModule = atom(). - erl_script_alias marks all URLs matching url-path as erl + <p><c>URLPath = string()</c> and <c>AllowedModule = atom()</c>. + <c>erl_script_alias</c> marks all URLs matching url-path as erl scheme scripts. A matching URL is mapped into a specific module - and function. For example: + and function, for example: - <code>{erl_script_alias, {"/cgi-bin/example", [httpd_example]}} - </code> + <code>{erl_script_alias, {"/cgi-bin/example", [httpd_example]}}</code> - and a request to + A request to http://your.server.org/cgi-bin/example/httpd_example:yahoo - would refer to httpd_example:yahoo/3 or, if that did not exist, + would refer to httpd_example:yahoo/3 or, if that does not exist, httpd_example:yahoo/2 and http://your.server.org/cgi-bin/example/other:yahoo would - not be allowed to execute. </p> + not be allowed to execute.</p> </item> <marker id="prop_esi_nocache"></marker> <tag>{erl_script_nocache, boolean()}</tag> <item> - <p>If erl_script_nocache is set to true the server will add - http header fields that prevents proxies from caching the - page. This is generally a good idea for dynamic content, since - the content often vary between each request. - Defaults to false. </p> + <p>If <c>erl_script_nocache</c> is set to <c>true</c>, the server adds + HTTP header fields preventing proxies from caching the + page. This is generally a good idea for dynamic content, as + the content often varies between each request. + Default is <c>false</c>.</p> </item> <marker id="prop_esi_timeout"></marker> <tag>{erl_script_timeout, integer()}</tag> <item> - <p>If erl_script_timeout sets the time in seconds the server will - wait between each chunk of data to be delivered through - mod_esi:deliver/2. Defaults to 15. This is only relevant - for scripts that uses the erl scheme. </p> + <p>If <c>erl_script_timeout</c> sets the time in seconds the server + waits between each chunk of data to be delivered through + <c>mod_esi:deliver/2</c>. Default is <c>15</c>. This is only relevant + for scripts that use the erl scheme.</p> </item> <marker id="prop_esi_timeout"></marker> <tag>{eval_script_alias, {URLPath, [AllowedModule]}}</tag> <item> - <p>Where URLPath = string() and AllowedModule = atom(). - Same as erl_script_alias but for scripts - using the eval scheme. Note that this is only supported - for backwards compatibility. The eval scheme is deprecated. </p> + <p><c>URLPath = string()</c> and <c>AllowedModule = atom()</c>. + Same as <c>erl_script_alias</c> but for scripts + using the eval scheme. This is only supported + for backwards compatibility. The eval scheme is deprecated.</p> </item> </taglist> <marker id="props_log"></marker> - <p><em>Log properties - requires mod_log</em></p> + <p><em>Log Properties - Requires mod_log</em></p> <taglist> <marker id="prop_elog"></marker> <tag>{error_log, path()}</tag> <item> <p>Defines the filename of the error log file to be used to log - server errors. If the filename does not begin with a slash (/) - it is assumed to be relative to the server_root. </p> + server errors. If the filename does not begin with a slash (/), + it is assumed to be relative to the <c>server_root</c>.</p> </item> <marker id="prop_slog"></marker> @@ -640,7 +641,7 @@ bytes <item> <p>Defines the filename of the access log file to be used to log security events. If the filename does not begin with a slash - (/) it is assumed to be relative to the server_root. </p> + (/), it is assumed to be relative to the <c>server_root</c>.</p> </item> <marker id="prop_tlog"></marker> @@ -648,270 +649,270 @@ bytes <item> <p>Defines the filename of the access log file to be used to log incoming requests. If the filename does not begin with a - slash (/) it is assumed to be relative to the server_root. </p> + slash (/), it is assumed to be relative to the <c>server_root</c>.</p> </item> </taglist> <marker id="props_dlog"></marker> - <p><em>Disk Log properties - requires mod_disk_log</em></p> + <p><em>Disk Log Properties - Requires mod_disk_log</em></p> <taglist> <marker id="prop_dlog_format"></marker> <tag>{disk_log_format, internal | external}</tag> <item> - <p>Defines the file-format of the log files see disk_log for - more information. If the internal file-format is used, the - logfile will be repaired after a crash. When a log file is - repaired data might get lost. When the external file-format is - used httpd will not start if the log file is broken. Defaults to - external. </p> + <p>Defines the file format of the log files. See <c>disk_log</c> for + details. If the internal file format is used, the + log file is repaired after a crash. When a log file is + repaired, data can disappear. When the external file format is + used, <c>httpd</c> does not start if the log file is broken. Default is + <c>external</c>.</p> </item> <marker id="prop_edlog"></marker> <tag>{error_disk_log, path()}</tag> <item> - <p>Defines the filename of the (disk_log(3)) error log file + <p>Defines the filename of the (<c>disk_log(3)</c>) error log file to be used to log server errors. If the filename does not begin - with a slash (/) it is assumed to be relative to the server_root. </p> + with a slash (/), it is assumed to be relative to the <c>server_root</c>.</p> </item> <marker id="prop_edlog_size"></marker> <tag>{error_disk_log_size, {MaxBytes, MaxFiles}}</tag> <item> - <p>Where MaxBytes = integer() and MaxFiles = integer(). - Defines the properties of the (disk_log(3)) error log - file. The disk_log(3) error log file is of type wrap log and - max-bytes will be written to each file and max-files will be - used before the first file is truncated and reused. </p> + <p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>. + Defines the properties of the (<c>disk_log(3)</c>) error log + file. This file is of type wrap log and + max bytes is written to each file and max files is + used before the first file is truncated and reused.</p> </item> <marker id="prop_sdlog"></marker> <tag>{security_disk_log, path()}</tag> <item> - <p>Defines the filename of the (disk_log(3)) access log file - which logs incoming security events i.e authenticated - requests. If the filename does not begin with a slash (/) it - is assumed to be relative to the server_root. </p> + <p>Defines the filename of the (<c>disk_log(3)</c>) access log file + logging incoming security events, that is, authenticated + requests. If the filename does not begin with a slash (/), it + is assumed to be relative to the <c>server_root</c>.</p> </item> <marker id="prop_sdlog_size"></marker> <tag>{security_disk_log_size, {MaxBytes, MaxFiles}}</tag> <item> - <p>Where MaxBytes = integer() and MaxFiles = integer(). - Defines the properties of the disk_log(3) access log - file. The disk_log(3) access log file is of type wrap log and - max-bytes will be written to each file and max-files will be - used before the first file is truncated and reused. </p> + <p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>. + Defines the properties of the <c>disk_log(3)</c> access log + file. This file is of type wrap log and + max bytes is written to each file and max files is + used before the first file is truncated and reused.</p> </item> <marker id="prop_tdlog"></marker> <tag>{transfer_disk_log, path()}</tag> <item> - <p>Defines the filename of the (disk_log(3)) access log file - which logs incoming requests. If the filename does not begin - with a slash (/) it is assumed to be relative to the - server_root. </p> + <p>Defines the filename of the (<c>disk_log(3)</c>) access log file + logging incoming requests. If the filename does not begin + with a slash (/), it is assumed to be relative to the + <c>server_root</c>.</p> </item> <marker id="prop_tdlog_size"></marker> <tag>{transfer_disk_log_size, {MaxBytes, MaxFiles}}</tag> <item> - <p>Where MaxBytes = integer() and MaxFiles = integer(). - Defines the properties of the disk_log(3) access log - file. The disk_log(3) access log file is of type wrap log and - max-bytes will be written to each file and max-files will be - used before the first file is truncated and reused. </p> + <p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>. + Defines the properties of the <c>disk_log(3)</c> access log + file. This file is of type wrap log and + max bytes is written to each file and max files is + used before the first file is truncated and reused.</p> </item> </taglist> <marker id="props_auth"></marker> - <p><em>Authentication properties - requires mod_auth</em></p> + <p><em>Authentication Properties - Requires mod_auth</em></p> <marker id="prop_dri"></marker> <p><em>{directory, {path(), [{property(), term()}]}}</em></p> <marker id="props_dir"></marker> - <p>Here follows the valid properties for directories </p> + <p>The properties for directories are as follows:</p> <taglist> <marker id="prop_allow_from"></marker> - <tag>{allow_from, all | [RegxpHostString]}</tag> + <tag>{allow_from, all | [RegxpHostString]}</tag> <item> - <p>Defines a set of hosts which should be granted access to a - given directory. - - For example: + <p>Defines a set of hosts to be granted access to a + given directory, for example: <code>{allow_from, ["123.34.56.11", "150.100.23"]}</code> - The host 123.34.56.11 and all machines on the 150.100.23 - subnet are allowed access. </p> + The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c> + subnet are allowed access.</p> </item> <marker id="prop_deny_from"></marker> - <tag>{deny_from, all | [RegxpHostString]}</tag> + <tag>{deny_from, all | [RegxpHostString]}</tag> <item> <p>Defines a set of hosts - which should be denied access to a given directory. - For example: + to be denied access to a given directory, for example: <code>{deny_from, ["123.34.56.11", "150.100.23"]}</code> - The host 123.34.56.11 and all machines on the 150.100.23 - subnet are not allowed access. </p> + The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c> + subnet are not allowed access.</p> </item> <marker id="prop_auth_type"></marker> - <tag>{auth_type, plain | dets | mnesia}</tag> + <tag>{auth_type, plain | dets | mnesia}</tag> <item> <p>Sets the type of authentication database that is used for the - directory.The key difference between the different methods is - that dynamic data can be saved when Mnesia and Dets is used. - This property is called AuthDbType in the Apache like - configuration files. </p> + directory. The key difference between the different methods is + that dynamic data can be saved when <c>Mnesia</c> and <c>Dets</c> + are used. + This property is called <c>AuthDbType</c> in the Apache-like + configuration files.</p> </item> <marker id="prop_auth_user_file"></marker> <tag>{auth_user_file, path()}</tag> <item> - <p>Sets the name of a file which contains the list of users and - passwords for user authentication. filename can be either + <p>Sets the name of a file containing the list of users and + passwords for user authentication. The filename can be either absolute or relative to the <c>server_root</c>. If using the - plain storage method, this file is a plain text file, where - each line contains a user name followed by a colon, followed - by the non-encrypted password. If user names are duplicated, - the behavior is undefined. For example: + plain storage method, this file is a plain text file where + each line contains a username followed by a colon, followed + by the non-encrypted password. If usernames are duplicated, + the behavior is undefined.</p> + <p>Example:</p> <code> ragnar:s7Xxv7 edward:wwjau8 </code> - If using the dets storage method, the user database is - maintained by dets and should not be edited by hand. Use the - API functions in mod_auth module to create / edit the user - database. This directive is ignored if using the mnesia - storage method. For security reasons, make sure that the - <c>auth_user_file</c> is stored outside the document tree of the Web - server. If it is placed in the directory which it protects, - clients will be able to download it. </p> + <p>If the <c>Dets</c> storage method is used, the user database is + maintained by <c>Dets</c> and must not be edited by hand. Use the + API functions in module <c>mod_auth</c> to create/edit the user + database. This directive is ignored if the <c>Mnesia</c> + storage method is used. For security reasons, ensure that + <c>auth_user_file</c> is stored outside the document tree of the web + server. If it is placed in the directory that it protects, + clients can download it.</p> </item> <marker id="prop_auth_group_file"></marker> <tag>{auth_group_file, path()}</tag> <item> - <p>Sets the name of a file which contains the list of user - groups for user authentication. Filename can be either - absolute or relative to the <c>server_root</c>. If you use the plain - storage method, the group file is a plain text file, where + <p>Sets the name of a file containing the list of user + groups for user authentication. The filename can be either + absolute or relative to the <c>server_root</c>. If the plain + storage method is used, the group file is a plain text file, where each line contains a group name followed by a colon, followed - by the member user names separated by spaces. For example: + by the members usernames separated by spaces.</p> + <p>Example:</p> <code>group1: bob joe ante</code> - If using the dets storage method, the group database is - maintained by dets and should not be edited by hand. Use the - API for mod_auth module to create / edit the group database. - This directive is ignored if using the mnesia storage method. - For security reasons, make sure that the <c>auth_group_file</c> is - stored outside the document tree of the Web server. If it is - placed in the directory which it protects, clients will be - able to download it. </p> + <p>If the <c>Dets</c> storage method is used, the group database is + maintained by <c>Dets</c> and must not be edited by hand. Use the + API for module <c>mod_auth</c> to create/edit the group database. + This directive is ignored if the <c>Mnesia</c> storage method is used. + For security reasons, ensure that the <c>auth_group_file</c> is + stored outside the document tree of the web server. If it is + placed in the directory that it protects, clients + can download it.</p> </item> <marker id="prop_auth_name"></marker> <tag>{auth_name, string()}</tag> <item> <p>Sets the name of the authorization realm (auth-domain) for - a directory. This string informs the client about which user - name and password to use. </p> + a directory. This string informs the client about which + username and password to use.</p> </item> <marker id="prop_auth_access_passwd"></marker> <tag>{auth_access_password, string()}</tag> <item> - <p>If set to other than "NoPassword" the password is required - for all API calls. If the password is set to "DummyPassword" the + <p>If set to other than "NoPassword", the password is required + for all API calls. If the password is set to "DummyPassword", the password must be changed before any other API calls. To secure - the authenticating data the password must be changed after the - web server is started since it otherwise is written in clear - text in the configuration file. </p> + the authenticating data, the password must be changed after the + web server is started. Otherwise it is written in clear + text in the configuration file.</p> </item> <marker id="prop_req_user"></marker> <tag>{require_user, [string()]}</tag> <item> - <p>Defines users which should be granted access to a given - directory using a secret password. </p> + <p>Defines users to grant access to a given + directory using a secret password.</p> </item> <marker id="prop_req_grp"></marker> <tag>{require_group, [string()]}</tag> <item> - <p>Defines users which should be granted access to a given - directory using a secret password. </p> + <p>Defines users to grant access to a given + directory using a secret password.</p> </item> </taglist> <marker id="props_htaccess"></marker> - <p><em>Htaccess authentication properties - requires mod_htaccess</em></p> + <p><em>Htaccess Authentication Properties - Requires mod_htaccess</em></p> <taglist> <marker id="prop_access_files"></marker> <tag>{access_files, [path()]}</tag> <item> - <p>Specify which filenames that are used for - access-files. When a request comes every directory in the path - to the requested asset will be searched after files with the - names specified by this parameter. If such a file is found the - file will be parsed and the restrictions specified in it will - be applied to the request. </p> + <p>Specifies the filenames that are used for + access files. When a request comes, every directory in the path + to the requested asset are searched after files with the + names specified by this parameter. If such a file is found, the + file is parsed and the restrictions specified in it are + applied to the request.</p> </item> </taglist> <marker id="props_sec"></marker> - <p><em>Security properties - requires mod_security </em></p> + <p><em>Security Properties - Requires mod_security</em></p> <marker id="prop_sec_dir"></marker> <p><em>{security_directory, {path(), [{property(), term()}]}}</em></p> <marker id="props_sdir"></marker> - <p>Here follows the valid properties for security directories</p> + <p>The properties for the security directories are as follows:</p> <taglist> <marker id="prop_data_file"></marker> <tag>{data_file, path()}</tag> <item> - <p>Name of the security data file. The filename can either - absolute or relative to the server_root. This file is used to - store persistent data for the mod_security module. </p> + <p>Name of the security data file. The filename can either be + absolute or relative to the <c>server_root</c>. This file is used to + store persistent data for module <c>mod_security</c>.</p> </item> <marker id="prop_max_retries"></marker> <tag>{max_retries, integer()}</tag> <item> - <p>Specifies the maximum number of tries to authenticate a - user has before the user is blocked out. If a user - successfully authenticates when the user has been blocked, the - user will receive a 403 (Forbidden) response from the - server. If the user makes a failed attempt while blocked the - server will return 401 (Unauthorized), for security + <p>Specifies the maximum number of attempts to authenticate a + user before the user is blocked out. If a user + successfully authenticates while blocked, the + user receives a 403 (Forbidden) response from the + server. If the user makes a failed attempt while blocked, the + server returns 401 (Unauthorized), for security reasons. - Defaults to 3 may also be set to infinity. </p> + Default is <c>3</c>. Can be set to infinity.</p> </item> <marker id="prop_block_time"></marker> <tag>{block_time, integer()}</tag> <item> <p>Specifies the number of minutes a user is blocked. After - this amount of time, he automatically regains access. - Defaults to 60. </p> + this timehas passed, the user automatically regains access. + Default is <c>60</c>.</p> </item> <marker id="prop_fail_exp_time"></marker> <tag>{fail_expire_time, integer()}</tag> <item> <p>Specifies the number of minutes a failed user authentication - is remembered. If a user authenticates after this amount of - time, his previous failed authentications are + is remembered. If a user authenticates after this + time has passed, the previous failed authentications are forgotten. - Defaults to 30. </p> + Default is <c>30</c>.</p> </item> <marker id="prop_auth_timeout"></marker> @@ -919,43 +920,43 @@ bytes <item> Specifies the number of seconds a successful user authentication is remembered. After this time has passed, the - authentication will no longer be reported. Defaults to 30. + authentication is no longer reported. Default is <c>30</c>. </item> </taglist> </section> <funcs> <func> - <marker id="info1"></marker> <name>info(Pid) -></name> <name>info(Pid, Properties) -> [{Option, Value}]</name> - <fsummary>Fetches information about the HTTP server</fsummary> + <fsummary>Fetches information about the HTTP server.</fsummary> <type> <v>Properties = [property()]</v> - <v>Option = property()</v> + <v>Option = property()</v> <v>Value = term()</v> </type> <desc> <p>Fetches information about the HTTP server. When called - with only the pid all properties are fetched, when called - with a list of specific properties they are fetched. - Available properties are the same as the server's start options. + with only the pid, all properties are fetched. When called + with a list of specific properties, they are fetched. + The available properties are the same as the start options + of the server. </p> - <note><p>Pid is the pid returned from inets:start/[2,3]. - Can also be retrieved form inets:services/0, inets:services_info/0 - see <seealso marker="inets">inets(3)</seealso> + <note><p>Pid is the pid returned from <c>inets:start/[2,3]</c>. + Can also be retrieved form <c>inets:services/0</c> and + <c>inets:services_info/0</c>, + see <seealso marker="inets">inets(3)</seealso>. </p></note> </desc> </func> <func> - <marker id="info2"></marker> <name>info(Address, Port) -> </name> <name>info(Address, Port, Profile) -> </name> <name>info(Address, Port, Profile, Properties) -> [{Option, Value}] </name> <name>info(Address, Port, Properties) -> [{Option, Value}] </name> - <fsummary>Fetches information about the HTTP server</fsummary> + <fsummary>Fetches information about the HTTP server.</fsummary> <type> <v>Address = ip_address()</v> <v>Port = integer()</v> @@ -966,20 +967,19 @@ bytes </type> <desc> <p>Fetches information about the HTTP server. When called with - only the Address, Port and Profile, if relevant, all properties are fetched. - When called with a list of specific properties they are fetched. - Available properties are the same as the server's start - options. + only <c>Address</c> and <c>Port</c>, all properties are + fetched. When called with a list of specific properties, they + are fetched. The available properties are the same as the + start options of the server. </p> - <note><p> Address has to be the ip-address and can not be + <note><p>The address must be the IP address and cannot be the hostname. </p></note> </desc> </func> <func> - <marker id="reload_config"></marker> <name>reload_config(Config, Mode) -> ok | {error, Reason}</name> <fsummary>Reloads the HTTP server configuration without restarting the server.</fsummary> @@ -991,24 +991,26 @@ bytes </type> <desc> <p>Reloads the HTTP server configuration without restarting the - server. Incoming requests will be answered with a temporary - down message during the time the it takes to reload.</p> + server. Incoming requests are answered with a temporary + down message during the reload time.</p> - <note><p>Available properties are the same as the server's - start options, although the properties bind_address and - port can not be changed.</p></note> + <note><p>Available properties are the same as the + start options of the server, but the properties + <c>bind_address</c> and <c>port</c> + cannot be changed.</p></note> - <p>If mode is disturbing, the server is blocked forcefully and - all ongoing requests are terminated and the reload will - start immediately. If mode is non-disturbing, no new - connections are accepted, but the ongoing requests are + <p>If mode is disturbing, the server is blocked forcefully, + all ongoing requests terminates, and the reload + starts immediately. If mode is non-disturbing, no new + connections are accepted, but ongoing requests are allowed to complete before the reload is done.</p> </desc> </func> </funcs> <section> - <title>ERLANG WEB SERVER API DATA TYPES </title> + <title>ERLANG WEB SERVER API DATA TYPES</title> + <p>The Erlang web server API data types are as follows:</p> <code type="none"> ModData = #mod{} @@ -1025,73 +1027,75 @@ bytes parsed_header = [], entity_body, connection - }). - </code> + }).</code> - <p>To acess the record in your callback-module use </p> - <code> -include_lib("inets/include/httpd.hrl"). </code> + <p>To acess the record in your callback-module use:</p> + <code> -include_lib("inets/include/httpd.hrl").</code> - <p>The fields of the <c>mod</c> record has the following meaning: + <p>The fields of record <c>mod</c> have the following meaning: </p> <taglist> <tag><c>data</c></tag> - <item>Type <c>[{InteractionKey,InteractionValue}]</c> is used to + <item><p>Type <c>[{InteractionKey,InteractionValue}]</c> is used to propagate data between modules. Depicted - <c>interaction_data()</c> in function type declarations. + <c>interaction_data()</c> in function type declarations.</p> </item> <tag><c>socket_type</c></tag> - <item><c>socket_type()</c>, - Indicates whether it is an ip socket or a ssl socket. + <item><p><c>socket_type()</c> + indicates whether it is an IP socket or an <c>ssl</c> socket.</p> </item> <tag><c>socket</c></tag> - <item>The actual socket in <c>ip_comm</c> or <c>ssl</c> format - depending on the <c>socket_type</c>. + <item><p>The socket, in format <c>ip_comm</c> or <c>ssl</c>, + depending on <c>socket_type</c>.</p> </item> <tag><c>config_db</c></tag> - <item>The config file directives stored as key-value tuples in - an ETS-table. Depicted <c>config_db()</c> in function type - declarations. + <item><p>The config file directives stored as key-value tuples in + an ETS table. Depicted <c>config_db()</c> in function type + declarations.</p> </item> <tag><c>method</c></tag> - <item>Type <c>"GET" | "POST" | "HEAD" | "TRACE"</c>, that is the - HTTP method. + <item><p>Type <c>"GET" | "POST" | "HEAD" | "TRACE"</c>, that is, the + HTTP method.</p> </item> <tag><c>absolute_uri</c></tag> - <item>If the request is a HTTP/1.1 - request the URI might be in the absolute URI format. In that - case httpd will save the absolute URI in this field. An Example - of an absolute URI could - be<c>"http://ServerName:Part/cgi-bin/find.pl?person=jocke"</c></item> + <item><p>If the request is an HTTP/1.1 + request, the URI can be in the absolute URI format. In that + case, <c>httpd</c> saves the absolute URI in this field. An Example + of an absolute URI is + <c>"http://ServerName:Part/cgi-bin/find.pl?person=jocke"</c></p></item> <tag><c>request_uri</c></tag> - <item>The <c>Request-URI</c> as defined - in RFC 1945, for example <c>"/cgi-bin/find.pl?person=jocke"</c></item> + <item><p>The <c>Request-URI</c> as defined + in <url href="http://www.ietf.org/rfc/rfc1945.txt">RFC 1945</url>, for example, <c>"/cgi-bin/find.pl?person=jocke"</c>.</p> + </item> <tag><c>http_version</c></tag> - <item>The <c>HTTP</c> version of the - request, that is "HTTP/0.9", "HTTP/1.0", or "HTTP/1.1". + <item><p>The <c>HTTP</c> version of the + request, that is, "HTTP/0.9", "HTTP/1.0", or "HTTP/1.1".</p> </item> <tag><c>request_line</c></tag> - <item>The <c>Request-Line</c> as - defined in RFC 1945, for example <c>"GET /cgi-bin/find.pl?person=jocke HTTP/1.0"</c>. + <item><p>The <c>Request-Line</c> as + defined in<url href="http://www.ietf.org/rfc/rfc1945.txt">RFC 1945</url>, for example, + <c>"GET /cgi-bin/find.pl?person=jocke HTTP/1.0"</c>.</p> </item> <tag><c>parsed_header</c></tag> - <item>Type <c>[{HeaderKey,HeaderValue}]</c>, + <item>Type <c>[{HeaderKey,HeaderValue}]</c>. <c>parsed_header</c> contains all HTTP header fields from the - HTTP-request stored in a list as key-value tuples. See RFC 2616 - for a listing of all header fields. For example the date field - would be stored as: <c>{"date","Wed, 15 Oct 1997 14:35:17 GMT"} </c>. - RFC 2616 defines that HTTP is a case insensitive protocol and - the header fields may be in lower case or upper case. Httpd will - ensure that all header field names are in lower case. + HTTP request stored in a list as key-value tuples. See + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url> + for a listing of all header fields. For example, the date field + is stored as <c>{"date","Wed, 15 Oct 1997 14:35:17 GMT"}</c>. + RFC 2616 defines that HTTP is a case-insensitive protocol and + the header fields can be in lower case or upper case. <c>httpd</c> + ensures that all header field names are in lower case. </item> <tag><c>entity_body</c></tag> - <item>The <c>Entity-Body</c> as defined - in RFC 2616, for example data sent from a CGI-script using the - POST method. + <item><p>The <c>entity-Body</c> as defined + in <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>, for example, data sent from a CGI script using the + POST method.</p> </item> <tag><c>connection</c></tag> - <item><c>true | false</c> If set to true the connection to the - client is a persistent connection and will not be closed when - the request is served.</item> + <item><p><c>true | false</c>. If set to <c>true</c>, the connection to the + client is a persistent connection and is not closed when + the request is served.</p></item> </taglist> </section> @@ -1100,56 +1104,63 @@ bytes </section> <funcs> <func> - <marker id="module_do"></marker> <name>Module:do(ModData)-> {proceed, OldData} | {proceed, NewData} | {break, NewData} | done</name> - <fsummary>Called for each request to the Web server.</fsummary> + <fsummary>Called for each request to the web server.</fsummary> <type> <v>OldData = list()</v> - <v>NewData = [{response,{StatusCode,Body}}] | [{response,{response,Head,Body}}] | [{response,{already_sent,Statuscode,Size}}] </v> + <v>NewData = [{response,{StatusCode,Body}}]</v> + <v>| [{response,{response,Head,Body}}]</v> + <v>| [{response,{already_sent,Statuscode,Size}}]</v> <v>StatusCode = integer()</v> <v>Body = io_list() | nobody | {Fun, Arg}</v> <v>Head = [HeaderOption]</v> <v>HeaderOption = {Option, Value} | {code, StatusCode}</v> - <v>Option = accept_ranges | allow | cache_control | content_MD5 | content_encoding | content_language | content_length | content_location | content_range | content_type | date | etag | expires | last_modified | location | pragma | retry_after | server | trailer | transfer_encoding</v> + <v>Option = accept_ranges | allow</v> + <v>| cache_control | content_MD5</v> + <v>| content_encoding | content_language</v> + <v>| content_length | content_location</v> + <v>| content_range | content_type | date</v> + <v>| etag | expires | last_modified</v> + <v>| location | pragma | retry_after</v> + <v>| server | trailer | transfer_encoding</v> <v>Value = string()</v> <v>Fun = fun( Arg ) -> sent| close | Body </v> <v>Arg = [term()]</v> </type> <desc> - <p>When a valid request reaches httpd it calls <c>do/1</c> in - each module defined by the Modules configuration - option. The function may generate data for other modules - or a response that can be sent back to the client.</p> - <p>The field <c>data</c> in ModData is a list. This list will be + <p>When a valid request reaches <c>httpd</c>, it calls <c>do/1</c> in + each module, defined by the configuration + option of <c>Module</c>. The function can generate data for other + modules or a response that can be sent back to the client.</p> + <p>The field <c>data</c> in <c>ModData</c> is a list. This list is the list returned from the last call to <c>do/1</c>.</p> - <p><c>Body</c> is the body of the http-response that will be - sent back to the client an appropriate header will be - appended to the message. <c>StatusCode</c> will be the - status code of the response see RFC2616 for the appropriate - values.</p> + <p><c>Body</c> is the body of the HTTP response that is + sent back to the client. An appropriate header is + appended to the message. <c>StatusCode</c> is the + status code of the response, see + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url> + for the appropriate values.</p> <p><c>Head</c> is a key value list of HTTP header fields. The - server will construct a HTTP header from this data. See RFC - 2616 for the appropriate value for each header field. If the - client is a HTTP/1.0 client then the server will filter the - list so that only HTTP/1.0 header fields will be sent back - to the client.</p> + server constructs an HTTP header from this data. See <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url> for the appropriate value for each header field. If the + client is an HTTP/1.0 client, the server filters the + list so that only HTTP/1.0 header fields are sent back + to the client.</p> <p>If <c>Body</c> is returned and equal to <c>{Fun,Arg}</c>, - the Web server will try <c>apply/2</c> on <c>Fun</c> with - <c>Arg</c> as argument and expect that the fun either - returns a list <c>(Body)</c> that is a HTTP-repsonse or the - atom sent if the HTTP-response is sent back to the - client. If close is returned from the fun something has gone - wrong and the server will signal this to the client by + the web server tries <c>apply/2</c> on <c>Fun</c> with + <c>Arg</c> as argument. The web server expects that the fun either + returns a list <c>(Body)</c> that is an HTTP repsonse, or the + atom <c>sent</c> if the HTTP response is sent back to the + client. If <c>close</c> is returned from the fun, something has gone + wrong and the server signals this to the client by closing the connection.</p> </desc> </func> <func> - <marker id="module_load"></marker> - <name>Module:load(Line, AccIn)-> eof | ok | {ok, AccOut} | {ok, AccOut, {Option, Value}} | {ok, AccOut, [{Option, Value}]} | {error, Reason} </name> - <fsummary>Load is used to convert a line in a Apache like config - file to a <c>{Option, Value}</c> tuple.</fsummary> + <name>Module:load(Line, AccIn)-> eof | ok | {ok, AccOut} | {ok, AccOut, {Option, Value}} | {ok, AccOut, [{Option, Value}]} | {error, Reason}</name> + <fsummary>Converts a line in an Apache-like config + file to an <c>{Option, Value}</c> tuple.</fsummary> <type> <v>Line = string()</v> <v>AccIn = [{Option, Value}]</v> @@ -1159,55 +1170,53 @@ bytes <v>Reason = term()</v> </type> <desc> - <p>Load is used to convert a line in a Apache like - configuration file to a <c>{Option, Value}</c> tuple. Some - more complex configuration options such as <c>directory</c> - and <c>security_directory</c> will create an - accumulator.This function does only need clauses for the + <p>Converts a line in an Apache-like + configuration file to an <c>{Option, Value}</c> tuple. Some + more complex configuration options, such as <c>directory</c> + and <c>security_directory</c>, create an + accumulator. This function only needs clauses for the options implemented by this particular callback module. </p> </desc> </func> - + <func> - <marker id="module_store"></marker> - <name>Module:store({Option, Value}, Config)-> {ok, {Option, NewValue}} | {error, Reason} </name> - <fsummary></fsummary> + <name>Module:remove(ConfigDB) -> ok | {error, Reason} </name> + <fsummary>Callback function that is called when the web server is closed.</fsummary> + <type> + <v>ConfigDB = ets_table()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>When <c>httpd</c> is shut down, it tries to execute + <c>remove/1</c> in each Erlang web server callback module. The + programmer can use this function to clean up resources + created in the store function.</p> + </desc> + </func> + + <func> + <name>Module:store({Option, Value}, Config)-> {ok, {Option, NewValue}} | {error, Reason}</name> + <fsummary>Checks the validity of the configuration options.</fsummary> <type> <v>Line = string()</v> <v>Option = property()</v> <v>Config = [{Option, Value}]</v> - <v>Value = term() </v> + <v>Value = term()</v> <v>Reason = term()</v> </type> <desc> - <p>This function is used to check the validity of the + <p>Checks the validity of the configuration options before saving them in the internal - database. This function may also have a side effect - e.i. setup necessary extra resources implied by the + database. This function can also have a side effect, + that is, setup of necessary extra resources implied by the configuration option. It can also resolve possible dependencies among configuration options by changing the value of the option. - This function does only need clauses for the options + This function only needs clauses for the options implemented by this particular callback module.</p> </desc> </func> - - <func> - <marker id="module_remove"></marker> - <name>Module:remove(ConfigDB) -> ok | {error, Reason} </name> - <fsummary>Callback function that is called when the Web server is closed.</fsummary> - <type> - <v>ConfigDB = ets_table()</v> - <v>Reason = term()</v> - </type> - <desc> - <p>When httpd is shutdown it will try to execute - <c>remove/1</c> in each Erlang web server callback module. The - programmer may use this function to clean up resources - that may have been created in the store function.</p> - </desc> - </func> </funcs> <section> @@ -1215,9 +1224,8 @@ bytes </section> <funcs> <func> - <marker id="parse_query"></marker> - <name>parse_query(QueryString) -> [{Key,Value}]</name> - <fsummary>Parse incoming data to <c>erl </c>and <c>eval </c>scripts.</fsummary> + <name>parse_query(QueryString) -> [{Key,Value}]</name> + <fsummary>Parses incoming data to <c>erl</c> and <c>eval</c> scripts.</fsummary> <type> <v>QueryString = string()</v> <v>Key = string()</v> @@ -1225,8 +1233,9 @@ bytes </type> <desc> <p><c>parse_query/1</c> parses incoming data to <c>erl</c> and - <c>eval</c> scripts (See <seealso marker="mod_esi">mod_esi(3)</seealso>) as defined in the standard - URL format, that is '+' becomes 'space' and decoding of + <c>eval</c> scripts (see <seealso marker="mod_esi">mod_esi(3)</seealso>) + as defined in the standard + URL format, that is, '+' becomes 'space' and decoding of hexadecimal characters (<c>%xx</c>).</p> </desc> </func> @@ -1234,8 +1243,9 @@ bytes <section> <title>SEE ALSO</title> - <p>RFC 2616, <seealso marker="inets">inets(3)</seealso>, - <seealso marker="ssl:ssl">ssl(3)</seealso> + <p><url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>, + <seealso marker="inets">inets(3)</seealso>, + <seealso marker="ssl:ssl">ssl(3)</seealso> </p> </section> diff --git a/lib/inets/doc/src/httpd_conf.xml b/lib/inets/doc/src/httpd_conf.xml deleted file mode 100644 index 54a5885eb4..0000000000 --- a/lib/inets/doc/src/httpd_conf.xml +++ /dev/null @@ -1,163 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE erlref SYSTEM "erlref.dtd"> - -<erlref> - <header> - <copyright> - <year>1997</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>httpd_conf</title> - <prepared>Joakim Grebenö</prepared> - <docno></docno> - <date>1997-10-14</date> - <rev>2.2</rev> - <file>httpd_conf.sgml</file> - </header> - <module>httpd_conf</module> - <modulesummary>Configuration utility functions to be used by the Erlang - Web server API programmer.</modulesummary> - <description> - <p>This module provides the Erlang Webserver API programmer with - utility functions for adding run-time configuration directives.</p> - - <marker id="check_enum"></marker> - </description> - - <funcs> - <func> - <name>check_enum(EnumString, ValidEnumStrings) -> Result</name> - <fsummary>Check if string is a valid enumeration.</fsummary> - <type> - <v>EnumString = string()</v> - <v>ValidEnumStrings = [string()]</v> - <v>Result = {ok,atom()} | {error,not_valid}</v> - </type> - <desc> - <marker id="check_enum"></marker> - <p><c>check_enum/2</c> checks if <c>EnumString</c> is a valid - enumeration of <c>ValidEnumStrings</c> in which case it is - returned as an atom.</p> - - <marker id="clean"></marker> - </desc> - </func> - - <func> - <name>clean(String) -> Stripped</name> - <fsummary>Remove leading and/or trailing white spaces.</fsummary> - <type> - <v>String = Stripped = string()</v> - </type> - <desc> - <marker id="clean"></marker> - <p><c>clean/1</c> removes leading and/or trailing white spaces - from <c>String</c>.</p> - - <marker id="custom_clean"></marker> - </desc> - </func> - - <func> - <name>custom_clean(String,Before,After) -> Stripped</name> - <fsummary>Remove leading and/or trailing white spaces and custom characters.</fsummary> - <type> - <v>Before = After = regexp()</v> - <v>String = Stripped = string()</v> - </type> - <desc> - <marker id="custom_clean"></marker> - <p><c>custom_clean/3</c> removes leading and/or trailing white - spaces and custom characters from <c>String</c>. <c>Before</c> - and <c>After</c> are regular expressions, as defined in - <c>regexp(3)</c>, describing the custom characters.</p> - - <marker id="is_directory"></marker> - </desc> - </func> - - <func> - <name>is_directory(FilePath) -> Result</name> - <fsummary>Check if a file path is a directory.</fsummary> - <type> - <v>FilePath = string()</v> - <v>Result = {ok,Directory} | {error,Reason}</v> - <v>Directory = string()</v> - <v>Reason = string() | enoent | eacces | enotdir | FileInfo</v> - <v>FileInfo = File info record</v> - </type> - <desc> - <marker id="is_directory"></marker> - <p><c>is_directory/1</c> checks if <c>FilePath</c> is a - directory in which case it is returned. Please read - <c>file(3)</c> for a description of <c>enoent</c>, - <c>eacces</c> and <c>enotdir</c>. The definition of - the file info record can be found by including <c>file.hrl</c> - from the kernel application, see file(3).</p> - - <marker id="is_file"></marker> - </desc> - </func> - - <func> - <name>is_file(FilePath) -> Result</name> - <fsummary>Check if a file path is a regular file.</fsummary> - <type> - <v>FilePath = string()</v> - <v>Result = {ok,File} | {error,Reason}</v> - <v>File = string()</v> - <v>Reason = string() | enoent | eacces | enotdir | FileInfo</v> - <v>FileInfo = File info record</v> - </type> - <desc> - <marker id="is_file"></marker> - <p><c>is_file/1</c> checks if <c>FilePath</c> is a regular - file in which case it is returned. Read <c>file(3)</c> for a - description of <c>enoent</c>, <c>eacces</c> and - <c>enotdir</c>. The definition of the file info record can be - found by including <c>file.hrl</c> from the kernel application, - see file(3).</p> - - <marker id="make_integer"></marker> - </desc> - </func> - - <func> - <name>make_integer(String) -> Result</name> - <fsummary>Return an integer representation of a string.</fsummary> - <type> - <v>String = string()</v> - <v>Result = {ok,integer()} | {error,nomatch}</v> - </type> - <desc> - <marker id="make_integer"></marker> - <p><c>make_integer/1</c> returns an integer representation of - <c>String</c>.</p> - </desc> - </func> - </funcs> - - <section> - <marker id="see_also"></marker> - <title>SEE ALSO</title> - <p><seealso marker="httpd">httpd(3)</seealso></p> - </section> - -</erlref> - - diff --git a/lib/inets/doc/src/httpd_custom_api.xml b/lib/inets/doc/src/httpd_custom_api.xml index 5840641b37..d2e5441895 100644 --- a/lib/inets/doc/src/httpd_custom_api.xml +++ b/lib/inets/doc/src/httpd_custom_api.xml @@ -29,10 +29,24 @@ <modulesummary>Behaviour with optional callbacks to customize the inets HTTP server.</modulesummary> <description> <p> The module implementing this behaviour shall be supplied to to the servers - configuration with the option <seealso marker="httpd:prop_customize"> customize</seealso></p> + configuration with the option <seealso marker="httpd#prop_customize"> customize</seealso></p> </description> <funcs> + <func> + <name>response_default_headers() -> [Header] </name> + <fsummary>Provide default headers for the HTTP servers responses.</fsummary> + <type> + <v>Header = {HeaderName :: string(), HeaderValue::string()}</v> + <d>string:to_lower/1 will be performed on the HeaderName</d> + </type> + <desc> + <p>Provide default headers for the HTTP servers responses. Note that this + option may override built-in defaults. + </p> + </desc> + </func> + <func> <name>response_header({HeaderName, HeaderValue}) -> {true, Header} | false </name> <fsummary>Filter and possible alter HTTP response headers.</fsummary> diff --git a/lib/inets/doc/src/httpd_socket.xml b/lib/inets/doc/src/httpd_socket.xml index c0368c2b39..f71dac90b2 100644 --- a/lib/inets/doc/src/httpd_socket.xml +++ b/lib/inets/doc/src/httpd_socket.xml @@ -31,12 +31,12 @@ </header> <module>httpd_socket</module> <modulesummary>Communication utility functions to be used by the Erlang - Web server API programmer.</modulesummary> + web server API programmer.</modulesummary> <description> - <p>This module provides the Erlang Web server API module programmer + <p>This module provides the Erlang web server API module programmer with utility functions for generic sockets communication. The appropriate communication mechanism is transparently used, that - is <c>ip_comm</c> or <c>ssl</c>.</p> + is, <c>ip_comm</c> or <c>ssl</c>.</p> <marker id="deliver"></marker> </description> @@ -44,7 +44,7 @@ <funcs> <func> <name>deliver(SocketType, Socket, Data) -> Result</name> - <fsummary>Send binary data over socket.</fsummary> + <fsummary>Sends binary data over socket.</fsummary> <type> <v>SocketType = socket_type()</v> <v>Socket = socket()</v> @@ -53,10 +53,10 @@ </type> <desc> <marker id="deliver"></marker> - <p><c>deliver/3</c> sends the <c>Binary</c> over the - <c>Socket</c> using the specified <c>SocketType</c>. Socket - and SocketType should be the socket and the socket_type form - the mod record as defined in httpd.hrl</p> + <p><c>deliver/3</c> sends <c>Data</c> over + <c>Socket</c> using the specified <c>SocketType</c>. <c>Socket</c> + and <c>SocketType</c> is to be the socket and the <c>socket_type</c> + form the <c>mod</c> record as defined in <c>httpd.hrl</c></p> <marker id="peername"></marker> </desc> @@ -64,7 +64,7 @@ <func> <name>peername(SocketType,Socket) -> {Port,IPAddress}</name> - <fsummary>Return the port and IP-address of the remote socket.</fsummary> + <fsummary>Returns the port and IP address of the remote socket.</fsummary> <type> <v>SocketType = socket_type()</v> <v>Socket = socket()</v> @@ -73,8 +73,8 @@ </type> <desc> <marker id="peername"></marker> - <p><c>peername/3</c> returns the <c>Port</c> and - <c>IPAddress</c> of the remote <c>Socket</c>. </p> + <p><c>peername/2</c> returns the <c>Port</c> and + <c>IPAddress</c> of the remote <c>Socket</c>.</p> <marker id="resolve"></marker> </desc> @@ -82,7 +82,7 @@ <func> <name>resolve() -> HostName</name> - <fsummary>Return the official name of the current host.</fsummary> + <fsummary>Returns the official name of the current host.</fsummary> <type> <v>HostName = string()</v> </type> diff --git a/lib/inets/doc/src/httpd_util.xml b/lib/inets/doc/src/httpd_util.xml index a48e141368..0f498ba2fc 100644 --- a/lib/inets/doc/src/httpd_util.xml +++ b/lib/inets/doc/src/httpd_util.xml @@ -30,9 +30,10 @@ <file>httpd_util.sgml</file> </header> <module>httpd_util</module> - <modulesummary>Miscellaneous utility functions to be used when implementing Erlang Web server API modules.</modulesummary> + <modulesummary>Miscellaneous utility functions to be used when implementing + Erlang web server API modules.</modulesummary> <description> - <p>This module provides the Erlang Web Server API module + <p>This module provides the Erlang web server API module programmer with miscellaneous utility functions.</p> <marker id="convert_request_date"></marker> @@ -41,7 +42,7 @@ <funcs> <func> <name>convert_request_date(DateString) -> ErlDate|bad_date</name> - <fsummary>Convert The the date to the Erlang date format.</fsummary> + <fsummary>Converts the date to the Erlang date format.</fsummary> <type> <v>DateString = string()</v> <v>ErlDate = {{Year,Month,Date},{Hour,Min,Sec}}</v> @@ -49,10 +50,9 @@ </type> <desc> <p><c>convert_request_date/1</c> converts <c>DateString</c> to - the Erlang date format. DateString must be in one of the three - date formats that is defined in the RFC 2616.</p> - - <marker id="create_etag"></marker> + the Erlang date format. <c>DateString</c> must be in one of the + three date formats defined in + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>.</p> </desc> </func> @@ -64,128 +64,84 @@ <v>Etag = string()</v> </type> <desc> - <p><c>create_etag/1</c> calculates the Etag for a file, from its - size and time for last modification. fileinfo is a record defined - in <c>kernel/include/file.hrl</c></p> - - <marker id="decode_hex"></marker> + <p><c>create_etag/1</c> calculates the Etag for a file from its + size and time for last modification. <c>FileInfo</c> is a record defined + in <c>kernel/include/file.hrl</c>.</p> </desc> </func> - - <func> - <name>decode_hex(HexValue) -> DecValue</name> - <fsummary>Convert a hex value into its decimal equivalent.</fsummary> - <type> - <v>HexValue = DecValue = string()</v> - </type> - <desc> - <p>Converts the hexadecimal value <c>HexValue</c> into its - decimal equivalent (<c>DecValue</c>).</p> - - <marker id="day"></marker> - </desc> - </func> - + <func> <name>day(NthDayOfWeek) -> DayOfWeek</name> - <fsummary>Convert the day of the week (integer [1-7]) to an abbreviated string.</fsummary> + <fsummary>Converts the day of the week + (integer [1-7]) to an abbreviated string.</fsummary> <type> <v>NthDayOfWeek = 1-7</v> <v>DayOfWeek = string()</v> </type> <desc> - <marker id="day"></marker> <p><c>day/1</c> converts the day of the week - (<c>NthDayOfWeek</c>) as an integer (1-7) to an abbreviated - string, that is: </p> + (<c>NthDayOfWeek</c>) from an integer (1-7) to an abbreviated + string, that is:</p> <p>1 = "Mon", 2 = "Tue", ..., 7 = "Sat".</p> - - <marker id="flatlength"></marker> </desc> </func> <func> - <name>flatlength(NestedList) -> Size</name> - <fsummary>Compute the size of a possibly nested list.</fsummary> + <name>decode_hex(HexValue) -> DecValue</name> + <fsummary>Converts a hexadecimal value into its decimal equivalent.</fsummary> <type> - <v>NestedList = list()</v> - <v>Size = integer()</v> + <v>HexValue = DecValue = string()</v> </type> <desc> - <marker id="flatlength"></marker> - <p><c>flatlength/1</c> computes the size of the possibly nested - list <c>NestedList</c>. Which may contain binaries.</p> - - <marker id="hexlist_to_integer"></marker> + <p>Converts the hexadecimal value <c>HexValue</c> into its + decimal equivalent (<c>DecValue</c>).</p> </desc> </func> - -<!-- + <func> - <name>header(StatusCode,PersistentConn)</name> - <name>header(StatusCode,Date)</name> - <name>header(StatusCode,MimeType,Date)</name> - <name>header(StatusCode,MimeType,PersistentConn,Date) -> HTTPHeader</name> - <fsummary>Generate a HTTP 1.1 header.</fsummary> + <name>flatlength(NestedList) -> Size</name> + <fsummary>Computes the size of a possibly nested list.</fsummary> <type> - <v>StatusCode = integer()</v> - <v>Date = rfc1123_date()</v> - <v>MimeType = string()</v> - <v>PersistentConn = true | false</v> + <v>NestedList = list()</v> + <v>Size = integer()</v> </type> <desc> - <marker id="header"></marker> - <p><c>header</c> returns a HTTP 1.1 header string. The - <c>StatusCode</c> is one of the status codes defined in RFC - 2616 and the <c>Date</c> string is RFC 1123 - compliant. (See <seealso marker="#rfc1123_date">rfc1123_date/0</seealso>). - </p> - <p>Note that the two version of <c>header/n</c> that does not - has a <c>PersistentConn</c> argument is there only for - backward compatibility, and must not be used in new Erlang - Webserver API modules. that will support persistent - connections.</p> - - <marker id="hexlist_to_integer"></marker> + <p><c>flatlength/1</c> computes the size of the possibly nested + list <c>NestedList</c>, which can contain binaries.</p> </desc> </func> ---> <func> <name>hexlist_to_integer(HexString) -> Number</name> - <fsummary>Convert a hexadecimal string to an integer.</fsummary> + <fsummary>Converts a hexadecimal string to an integer.</fsummary> <type> <v>Number = integer()</v> <v>HexString = string()</v> </type> <desc> - <p><c>hexlist_to_integer</c> Convert the Hexadecimal value of - HexString to an integer.</p> - - <marker id="integer_to_hexlist"></marker> + <p><c>hexlist_to_integer</c> converts the hexadecimal value of + <c>HexString</c> to an integer.</p> </desc> </func> <func> <name>integer_to_hexlist(Number) -> HexString</name> - <fsummary>Convert an integer to a hexadecimal string.</fsummary> + <fsummary>Converts an integer to a hexadecimal string.</fsummary> <type> <v>Number = integer()</v> <v>HexString = string()</v> </type> <desc> - <marker id="integer_to_hexlist"></marker> - <p><c>integer_to_hexlist/1</c> Returns a string that represents - the Number in a Hexadecimal form.</p> - - <marker id="lookup"></marker> + <p><c>integer_to_hexlist/1</c> returns a string representing + <c>Number</c> in a hexadecimal form.</p> </desc> </func> <func> <name>lookup(ETSTable,Key) -> Result</name> <name>lookup(ETSTable,Key,Undefined) -> Result</name> - <fsummary>Extract the first value associated with a key in an ETS table.</fsummary> + <fsummary>Extracts the first value associated with a <c>Key</c> + in an ETS table.</fsummary> <type> <v>ETSTable = ets_table()</v> <v>Key = term()</v> @@ -195,20 +151,18 @@ <desc> <p><c>lookup</c> extracts <c>{Key,Value}</c> tuples from <c>ETSTable</c> and returns the <c>Value</c> associated - with <c>Key</c>. If <c>ETSTable</c> is of type <c>bag</c> + with <c>Key</c>. If <c>ETSTable</c> is of type <c>bag</c>, only the first <c>Value</c> associated with <c>Key</c> is returned. <c>lookup/2</c> returns <c>undefined</c> and <c>lookup/3</c> returns <c>Undefined</c> if no <c>Value</c> is found.</p> - - <marker id="lookup_mime"></marker> </desc> </func> <func> <name>lookup_mime(ConfigDB,Suffix)</name> <name>lookup_mime(ConfigDB,Suffix,Undefined) -> MimeType</name> - <fsummary>Return the mime type associated with a specific file suffix. </fsummary> + <fsummary>Returns the MIME type associated with a specific file suffix.</fsummary> <type> <v>ConfigDB = ets_table()</v> <v>Suffix = string()</v> @@ -216,20 +170,19 @@ <v>Undefined = term()</v> </type> <desc> - <marker id="lookup_mime"></marker> - <p><c>lookup_mime</c> returns the mime type associated with a - specific file suffix as specified in the <c>mime.types</c> - file (located in the - <path unix="$SERVER_ROOT/conf/mime.types" windows="%SERVER_ROOT%\conf\mime.types">config directory</path>).</p> - - <marker id="lookup_mime_default"></marker> + <p><c>lookup_mime</c> returns the MIME type associated with a + specific file suffix as specified in the file <c>mime.types</c> + (located in the + <path unix="$SERVER_ROOT/conf/mime.types" windows="%SERVER_ROOT%\conf\mime.types"> + config directory</path>).</p> </desc> </func> <func> <name>lookup_mime_default(ConfigDB,Suffix)</name> <name>lookup_mime_default(ConfigDB,Suffix,Undefined) -> MimeType</name> - <fsummary>Return the mime type associated with a specific file suffix or the value of the DefaultType.</fsummary> + <fsummary>Returns the MIME type associated with a specific file suffix + or the value of the DefaultType.</fsummary> <type> <v>ConfigDB = ets_table()</v> <v>Suffix = string()</v> @@ -237,22 +190,19 @@ <v>Undefined = term()</v> </type> <desc> - <marker id="lookup_mime_default"></marker> - <p><c>lookup_mime_default</c> returns the mime type associated + <p><c>lookup_mime_default</c> returns the MIME type associated with a specific file suffix as specified in the <c>mime.types</c> file (located in the - <path unix="$SERVER_ROOT/conf/mime.types" windows="%SERVER_ROOT%\conf\mime.types">config directory</path>). - If no appropriate association can be found - the value of DefaultType is + <path unix="$SERVER_ROOT/conf/mime.types" windows="%SERVER_ROOT%\conf\mime.types"> + config directory</path>). + If no appropriate association is found, the value of <c>DefaultType</c> is returned.</p> - - <marker id="message"></marker> </desc> </func> <func> <name>message(StatusCode,PhraseArgs,ConfigDB) -> Message</name> - <fsummary>Return an informative HTTP 1.1 status string in HTML.</fsummary> + <fsummary>Returns an informative HTTP 1.1 status string in HTML.</fsummary> <type> <v>StatusCode = 301 | 400 | 403 | 404 | 500 | 501 | 504</v> <v>PhraseArgs = term()</v> @@ -260,53 +210,48 @@ <v>Message = string()</v> </type> <desc> - <marker id="message"></marker> <p><c>message/3</c> returns an informative HTTP 1.1 status string in HTML. Each <c>StatusCode</c> requires a specific <c>PhraseArgs</c>: </p> <taglist> <tag><c>301</c></tag> - <item><c>string()</c>: A URL pointing at the new document - position.</item> + <item><p><c>string()</c>: A URL pointing at the new document + position.</p></item> <tag><c>400 | 401 | 500</c></tag> - <item><c>none</c> (No <c>PhraseArgs</c>)</item> + <item><p><c>none</c> (no <c>PhraseArgs</c>).</p></item> <tag><c>403 | 404</c></tag> - <item><c>string()</c>: A <c>Request-URI</c> as described in - RFC 2616.</item> + <item><p><c>string()</c>: A <c>Request-URI</c> as described in + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>.</p> + </item> <tag><c>501</c></tag> - <item><c>{Method,RequestURI,HTTPVersion}</c>: The HTTP - <c>Method</c>, <c>Request-URI</c> and <c>HTTP-Version</c> - as defined in RFC 2616.</item> + <item><p><c>{Method,RequestURI,HTTPVersion}</c>: The HTTP + <c>Method</c>, <c>Request-URI</c>, and <c>HTTP-Version</c> + as defined in RFC 2616.</p></item> <tag><c>504</c></tag> - <item><c>string()</c>: A string describing why the service - was unavailable.</item> + <item><p><c>string()</c>: A string describing why the service + was unavailable.</p></item> </taglist> - - <marker id="month"></marker> </desc> </func> <func> <name>month(NthMonth) -> Month</name> - <fsummary>Convert the month as an integer (1-12) to an abbreviated string.</fsummary> + <fsummary>Converts the month as an integer (1-12) to an abbreviated string.</fsummary> <type> <v>NthMonth = 1-12</v> <v>Month = string()</v> </type> <desc> - <marker id="month"></marker> <p><c>month/1</c> converts the month <c>NthMonth</c> as an integer (1-12) to an abbreviated string, that is: </p> <p>1 = "Jan", 2 = "Feb", ..., 12 = "Dec".</p> - - <marker id="multi_lookup"></marker> </desc> </func> <func> <name>multi_lookup(ETSTable,Key) -> Result</name> - <fsummary>Extract the values associated with a key in a ETS table.</fsummary> + <fsummary>Extracts the values associated with a key in an ETS table.</fsummary> <type> <v>ETSTable = ets_table()</v> <v>Key = term()</v> @@ -314,49 +259,44 @@ </type> <desc> <p><c>multi_lookup</c> extracts all <c>{Key,Value}</c> tuples - from an <c>ETSTable</c> and returns <em>all</em><c>Values</c> associated with the <c>Key</c> in a list.</p> - - <marker id="reason phrase"></marker> + from an <c>ETSTable</c> and returns <em>all</em> <c>Values</c> + associated with <c>Key</c> in a list.</p> </desc> </func> <func> <name>reason_phrase(StatusCode) -> Description</name> - <fsummary>Return the description of an HTTP 1.1 status code.</fsummary> + <fsummary>Returns the description of an HTTP 1.1 status code.</fsummary> <type> - <v>StatusCode = 100| 200 | 201 | 202 | 204 | 205 | 206 | 300 | 301 | 302 | 303 | 304 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 410 411 | 412 | 413 | 414 415 | 416 | 417 | 500 | 501 | 502 | 503 | 504 | 505</v> + <v>StatusCode = 100| 200 | 201 | 202 | 204 | 205 | 206 | 300 | 301 | 302 | 303 | 304 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 410 411 | 412 | 413 | 414 415 | 416 | 417 | 500 | 501 | 502 | 503 | 504 | 505</v> <v>Description = string()</v> </type> <desc> - <p><c>reason_phrase</c> returns the <c>Description</c> of an - HTTP 1.1 <c>StatusCode</c>, for example 200 is "OK" and 201 - is "Created". Read RFC 2616 for further information.</p> - - <marker id="rfc1123_date"></marker> + <p><c>reason_phrase</c> returns <c>Description</c> of an + HTTP 1.1 <c>StatusCode</c>, for example, 200 is "OK" and 201 + is "Created". For more information, see + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>.</p> </desc> </func> <func> <name>rfc1123_date() -> RFC1123Date</name> <name>rfc1123_date({{YYYY,MM,DD},{Hour,Min,Sec}}) -> RFC1123Date</name> - <fsummary>Return the current date in RFC 1123 format.</fsummary> + <fsummary>Returns the current date in RFC 1123 format.</fsummary> <type> <v>YYYY = MM = DD = Hour = Min = Sec = integer()</v> <v>RFC1123Date = string()</v> </type> <desc> - <marker id="rfc1123_date"></marker> <p><c>rfc1123_date/0</c> returns the current date in RFC 1123 format. <c>rfc_date/1</c> converts the date in the Erlang format to the RFC 1123 date format.</p> - - <marker id="split"></marker> </desc> </func> <func> <name>split(String,RegExp,N) -> SplitRes</name> - <fsummary>Split a string in N chunks using a regular expression.</fsummary> + <fsummary>Splits a string in N chunks using a regular expression.</fsummary> <type> <v>String = RegExp = string()</v> <v>SplitRes = {ok, FieldList} | {error, errordesc()}</v> @@ -364,96 +304,86 @@ <v>N = integer</v> </type> <desc> - <marker id="split"></marker> - <p><c>split/3</c> splits the <c>String</c> in <c>N</c> chunks - using the <c>RegExp</c>. <c>split/3</c> is is equivalent to - <c>regexp:split/2</c> with one exception, that is <c>N</c> - defines the number of maximum number of fields in the + <p><c>split/3</c> splits <c>String</c> in <c>N</c> chunks + using <c>RegExp</c>. <c>split/3</c> is equivalent to + <c>regexp:split/2</c> with the exception that <c>N</c> + defines the maximum number of fields in <c>FieldList</c>.</p> - - <marker id="split_script_path"></marker> </desc> </func> <func> <name>split_script_path(RequestLine) -> Splitted</name> - <fsummary>Split a <c>RequestLine</c>in a file reference to an executable and a<c>QueryString</c>or a <c>PathInfo</c>string.</fsummary> + <fsummary>Splits a <c>RequestLine</c> in a file reference to an executable, + and a <c>QueryString</c> or a <c>PathInfo</c>string.</fsummary> <type> <v>RequestLine = string()</v> <v>Splitted = not_a_script | {Path, PathInfo, QueryString}</v> <v>Path = QueryString = PathInfo = string()</v> </type> <desc> - <marker id="split_script_path"></marker> <p><c>split_script_path/1</c> is equivalent to <c>split_path/1</c> with one exception. If the longest - possible path is not a regular, accessible and executable - file <c>not_a_script</c> is returned.</p> - - <marker id="split_path"></marker> + possible path is not a regular, accessible, and executable + file, then <c>not_a_script</c> is returned.</p> </desc> </func> <func> <name>split_path(RequestLine) -> {Path,QueryStringOrPathInfo}</name> - <fsummary>Split a <c>RequestLine</c>in a file reference and a <c>QueryString</c>or a<c>PathInfo</c>string.</fsummary> + <fsummary>Splits a <c>RequestLine</c> in a file reference, and a + <c>QueryString</c> or a <c>PathInfo</c> string.</fsummary> <type> <v>RequestLine = Path = QueryStringOrPathInfo = string()</v> </type> <desc> - <marker id="split_path"></marker> - <p><c>split_path/1</c> splits the <c>RequestLine</c> in a file - reference (<c>Path</c>) and a <c>QueryString</c> or a - <c>PathInfo</c> string as specified in RFC 2616. A - <c>QueryString</c> is isolated from the <c>Path</c> with a + <p><c>split_path/1</c> splits <c>RequestLine</c> in a file + reference (<c>Path</c>), and a <c>QueryString</c> or a + <c>PathInfo</c> string as specified in + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>. + A <c>QueryString</c> is isolated from <c>Path</c> with a question mark (<c>?</c>) and <c>PathInfo</c> with a slash (/). In the case of a <c>QueryString</c>, everything before - the <c>?</c> is a <c>Path</c> and everything after a - <c>QueryString</c>. In the case of a <c>PathInfo</c> the + <c>?</c> is a <c>Path</c> and everything after <c>?</c> is a + <c>QueryString</c>. In the case of a <c>PathInfo</c>, <c>RequestLine</c> is scanned from left-to-right on the hunt for longest possible <c>Path</c> being a file or a directory. Everything after the longest possible <c>Path</c>, isolated with a <c>/</c>, is regarded as <c>PathInfo</c>. The resulting <c>Path</c> is decoded using <c>decode_hex/1</c> before delivery.</p> - - <marker id="strip"></marker> </desc> </func> <func> <name>strip(String) -> Stripped</name> - <fsummary>Returns String where the leading and trailing space and tabs has been removed.</fsummary> + <fsummary>Returns <c>String</c> where the leading and trailing space + tabs are removed.</fsummary> <type> <v>String = Stripped = string()</v> </type> <desc> - <marker id="strip"></marker> <p><c>strip/1</c> removes any leading or trailing linear white - space from the string. Linear white space should be read as + space from the string. Linear white space is to be read as horizontal tab or space.</p> - - <marker id="suffix"></marker> </desc> </func> <func> <name>suffix(FileName) -> Suffix</name> - <fsummary>Extract the file suffix from a given filename.</fsummary> + <fsummary>Extracts the file suffix from a given filename.</fsummary> <type> <v>FileName = Suffix = string()</v> </type> <desc> - <marker id="suffix"></marker> <p><c>suffix/1</c> is equivalent to - <c>filename:extension/1</c> with one exception, that is - <c>Suffix</c> is returned without a leading dot (<c>.</c>). </p> + <c>filename:extension/1</c> with the exception that + <c>Suffix</c> is returned without a leading dot (<c>.</c>).</p> </desc> </func> </funcs> <section> - <marker id="see_also"></marker> <title>SEE ALSO</title> <p><seealso marker="httpd">httpd(3)</seealso></p> </section> diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml index f96ff5f8fb..5d071c9a48 100644 --- a/lib/inets/doc/src/inets.xml +++ b/lib/inets/doc/src/inets.xml @@ -30,21 +30,21 @@ <rev></rev> </header> <module>inets</module> - <modulesummary>The inets services API</modulesummary> + <modulesummary>The Inets services API.</modulesummary> <description> <p>This module provides the most basic API to the - clients and servers, that are part of the Inets application, - such as start and stop. </p> + clients and servers that are part of the <c>Inets</c> application, + such as start and stop.</p> <marker id="common_data_types"></marker> </description> <section> - <title>COMMON DATA TYPES </title> + <title>DATA TYPES</title> <p>Type definitions that are used more than once in - this module: </p> - <p><c> service() = ftpc | tftp | httpc | httpd</c></p> - <p><c> property() = atom() </c></p> + this module:</p> + <p><c>service() = ftpc | tftp | httpc | httpd</c></p> + <p><c>property() = atom()</c></p> <marker id="functions"></marker> <marker id="services"></marker> </section> @@ -52,7 +52,7 @@ <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> @@ -60,7 +60,7 @@ <desc> <p>Returns a list of currently running services.</p> <note> - <p>Services started as <c>stand_alone</c> will not be listed.</p> + <p>Services started as <c>stand_alone</c> are not listed.</p> </note> <marker id="services_info"></marker> @@ -70,8 +70,8 @@ <func> <name>services_info() -> [{Service, Pid, Info}]</name> <fsummary>Returns a list of currently running services where - each service is described by a [{Option, Value}] - list. </fsummary> + each service is described by an <c>[{Option, Value}]</c> + list.</fsummary> <type> <v>Service = service()</v> <v>Pid = pid()</v> @@ -81,11 +81,10 @@ </type> <desc> <p>Returns a list of currently running services where each - service is described by a [{Option, Value}] list. The - information given in the list is specific for each service - and it is probable that each service will have its own info - function that gives you even more details about the - service.</p> + service is described by an <c>[{Option, Value}]</c> list. The + information in the list is specific for each service + and each service has probably its own info + function that gives more details about the service.</p> <marker id="service_names"></marker> </desc> @@ -107,59 +106,48 @@ <func> <name>start() -> </name> <name>start(Type) -> ok | {error, Reason}</name> - <fsummary>Starts the Inets application. </fsummary> + <fsummary>Starts the <c>Inets</c> application.</fsummary> <type> <v>Type = permanent | transient | temporary</v> </type> <desc> - <p>Starts the Inets application. Default type - is temporary. See also - <seealso marker="kernel:application">application(3)</seealso>. </p> + <p>Starts the <c>Inets</c> application. Default type + is <c>temporary</c>. See also + <seealso marker="kernel:application">application(3)</seealso>.</p> <marker id="stop"></marker> </desc> </func> <func> - <name>stop() -> ok </name> - <fsummary>Stops the inets application.</fsummary> - <desc> - <p>Stops the inets application. See also - <seealso marker="kernel:application">application(3)</seealso>. </p> - - <marker id="start2"></marker> - </desc> - </func> - - <func> <name>start(Service, ServiceConfig) -> {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> + <fsummary>Dynamically starts an <c>Inets</c> + service after the <c>Inets</c> application has been started.</fsummary> <type> <v>Service = service()</v> <v>ServiceConfig = [{Option, Value}]</v> <v>Option = property()</v> <v>Value = term()</v> - <v>How = inets | stand_alone - default is inets</v> + <v>How = inets | stand_alone - default is inets.</v> </type> <desc> - <p>Dynamically starts an inets service after the inets - application has been started. </p> + <p>Dynamically starts an <c>Inets</c> service after the <c>Inets</c> + application has been started.</p> <note> - <p>Dynamically started services will not be handled by - application takeover and failover behavior when inets is - run as a distributed application. Nor will they be - automatically restarted when the inets application is - restarted, but as long as the inets application is up and - running they will be supervised and may be soft code - upgraded. Services started as <c>stand_alone</c>, - e.i. the service is not started as part of the inets - application, will lose all OTP application benefits such - as soft upgrade. The "stand_alone-service" will be linked to - the process that started it. In most cases some of the - supervision functionality will still be in place and in - some sense the calling process has now become the top + <p>Dynamically started services are not handled by + application takeover and failover behavior when <c>Inets</c> is + run as a distributed application. Nor are they + automatically restarted when the <c>Inets</c> application is + restarted. As long as the <c>Inets</c> application is operational, + they are supervised and can be soft code upgraded.</p> + <p>A service started as <c>stand_alone</c>, that is, the service + is not started as part of the <c>Inets</c> application, + lose all OTP application benefits, such as soft upgrade. + The <c>stand_alone</c>-service is linked to + the process that started it. Usually some + supervision functionality is still in place and in + some sense the calling process becomes the top supervisor.</p> </note> @@ -167,19 +155,30 @@ </desc> </func> + <func> + <name>stop() -> ok </name> + <fsummary>Stops the <c>Inets</c> application.</fsummary> + <desc> + <p>Stops the <c>Inets</c> application. See also + <seealso marker="kernel:application">application(3)</seealso>.</p> + + <marker id="start2"></marker> + </desc> + </func> + <func> <name>stop(Service, Reference) -> ok | {error, Reason} </name> - <fsummary>Stops a started service of the inets application or takes - down a "stand_alone-service" gracefully.</fsummary> + <fsummary>Stops a started service of the <c>Inets</c> application or takes + down a <c>stand_alone </c>service gracefully.</fsummary> <type> <v>Service = service() | stand_alone</v> - <v>Reference = pid() | term() - service specified reference</v> + <v>Reference = pid() | term() - service-specified reference</v> <v>Reason = term()</v> </type> <desc> - <p>Stops a started service of the inets application or takes - down a "stand_alone-service" gracefully. When the - <c>stand_alone</c> option is used in start, + <p>Stops a started service of the <c>Inets</c> application or takes + down a <c>stand_alone</c>-service gracefully. When option + <c>stand_alone</c> is used in start, only the pid is a valid argument to stop.</p> <marker id="see_also"></marker> diff --git a/lib/inets/doc/src/inets_services.xml b/lib/inets/doc/src/inets_services.xml index f78485cb64..d100216ebb 100644 --- a/lib/inets/doc/src/inets_services.xml +++ b/lib/inets/doc/src/inets_services.xml @@ -22,7 +22,7 @@ </legalnotice> - <title>Introduction</title> + <title>Inets</title> <prepared>Ingela Anderton Andin</prepared> <responsible></responsible> <docno></docno> @@ -34,45 +34,26 @@ </header> <section> - <title>Purpose</title> - <p>Inets is a container for Internet clients and - servers. Currently, an <term id="HTTP"></term>client and server, a - TFPT client and server, and a FTP client has been incorporated - into Inets. The HTTP server and client is HTTP 1.1 compliant as - defined in <term id="RFC"></term>2616.</p> - </section> - - <section> - <title>Prerequisites</title> - <p>It is assumed that the reader is familiar with the Erlang - programming language, concepts of OTP and has a basic - understanding of the HTTP, TFTP and FTP protocols.</p> - </section> - - <section> - <title>The Service Concept</title> - <p>Each client and server in inets is viewed as service. Services - may be configured to be started at application startup or - started dynamically in runtime. If you want to run inets as an - distributed application that should handle application failover - and takeover, services should be configured to be started at - application startup. When starting the inets application - the inets top supervisor will start a number of subsupervisors - and worker processes for handling the different services - provided. When starting services dynamically new children will - be added to the supervision tree, unless the service is started - with the stand alone option, in which case the service is linked - to the calling process and all OTP application features such as - soft upgrade are lost.</p> - <p>Services that should be configured for startup at application - startup time should be put into the erlang node configuration file - on the form: </p> + <title>Service Concept</title> + <p>Each client and server in <c>Inets</c> is viewed as a service. + Services can be configured to be started at application startup or + dynamically in runtime. To run <c>Inets</c> as a distributed + application that handles application failover and takeover, + configure the services to be started at application startup. + When starting the <c>Inets</c> application, the <c>Inets</c> + top supervisor starts a number of subsupervisors and worker + processes for handling the provided services. + When starting services dynamically, new children are added to the + supervision tree, unless the service is started with the standalone + option. In this case the service is linked to the calling process + and all OTP application features, such as soft upgrade, are lost.</p> + <p>Services to be configured for startup at application startup are to + be put into the Erlang node configuration file + on the following form:</p> <pre> - [{inets, [{services, ListofConfiguredServices}]}]. - </pre> - <p>For details of exactly what to put in the list of configured - services see the documentation for the services that should be - configured.</p> + [{inets, [{services, ListofConfiguredServices}]}].</pre> + <p>For details of what to put in the list of configured services, + see the documentation for the services to be configured.</p> </section> </chapter> diff --git a/lib/inets/doc/src/introduction.xml b/lib/inets/doc/src/introduction.xml new file mode 100644 index 0000000000..491835f852 --- /dev/null +++ b/lib/inets/doc/src/introduction.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>1997</year><year>2013</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + </legalnotice> + + <title>Introduction</title> + <prepared>Ingela Anderton Andin</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>2004-09-28</date> + <rev>A</rev> + <file>introduction.xml</file> + </header> + + <section> + <title>Purpose</title> + <p><c>Inets</c> is a container for Internet clients and servers + including the following:</p> + <list type="bulleted"> + <item>An FTP client</item> + <item>A TFTP client and server</item> + <item>An <term id="HTTP"></term> client and server</item> + </list> + <p>The HTTP client and server are HTTP 1.1 compliant as + defined in + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>.</p> + </section> + + <section> + <title>Prerequisites</title> + <p>It is assumed that the reader is familiar with the Erlang + programming language, concepts of OTP, and has a basic + understanding of the FTP, TFTP, and HTTP protocols.</p> + </section> +</chapter> + + diff --git a/lib/inets/doc/src/mod_alias.xml b/lib/inets/doc/src/mod_alias.xml index d073b5c5b8..87c950cc6b 100644 --- a/lib/inets/doc/src/mod_alias.xml +++ b/lib/inets/doc/src/mod_alias.xml @@ -32,8 +32,8 @@ <module>mod_alias</module> <modulesummary>URL aliasing.</modulesummary> <description> - <p>Erlang Webserver Server internal API for handling of things - such as interaction data exported by the mod_alias module.</p> + <p>Erlang web server internal API for handling of, for example, + interaction data exported by module <c>mod_alias</c>.</p> <marker id="default_index"></marker> </description> @@ -41,7 +41,7 @@ <funcs> <func> <name>default_index(ConfigDB, Path) -> NewPath</name> - <fsummary>Return a new path with the default resource or file appended.</fsummary> + <fsummary>Returns a new path with the default resource or file appended.</fsummary> <type> <v>ConfigDB = config_db()</v> <v>Path = NewPath = string()</v> @@ -50,14 +50,14 @@ <marker id="default_index"></marker> <p>If <c>Path</c> is a directory, <c>default_index/2</c>, it starts searching for resources or files that are specified in the config - directive DirectoryIndex. + directive <c>DirectoryIndex</c>. If an appropriate resource or file is found, it is appended to the end of <c>Path</c> and then returned. <c>Path</c> is - returned unaltered, if no appropriate - file is found, or if <c>Path</c> is not a directory. + returned unaltered if no appropriate + file is found or if <c>Path</c> is not a directory. <c>config_db()</c> is the server config file in ETS table format as described in - <seealso marker="http_server">Inets Users Guide.</seealso>.</p> + <seealso marker="http_server">Inets User's Guide</seealso>.</p> <marker id="path"></marker> </desc> @@ -65,7 +65,7 @@ <func> <name>path(PathData, ConfigDB, RequestURI) -> Path</name> - <fsummary>Return the actual file path to a URL.</fsummary> + <fsummary>Returns the file path to a URL.</fsummary> <type> <v>PathData = interaction_data()</v> <v>ConfigDB = config_db()</v> @@ -73,15 +73,16 @@ </type> <desc> <marker id="path"></marker> - <p><c>path/3</c> returns the actual file <c>Path</c> in the - <c>RequestURI</c> (See RFC 1945). If the interaction data - <c>{real_name,{Path,AfterPath}}</c> has been exported by - mod_alias; + <p><c>path/3</c> returns the file <c>Path</c> in the + <c>RequestURI</c> (see + <url href="http://www.rfc-base.org/rfc-1945.html">RFC 1945</url>). + If the interaction data <c>{real_name,{Path,AfterPath}}</c> + has been exported by <c>mod_alias</c>, <c>Path</c> is returned. If no interaction data has been - exported, ServerRoot is used to + exported, <c>ServerRoot</c> is used to generate a file <c>Path</c>. <c>config_db()</c> and <c>interaction_data()</c> are as defined in - <seealso marker="http_server">Inets Users Guide</seealso>.</p> + <seealso marker="http_server">Inets User's Guide</seealso>.</p> <marker id="real_name"></marker> </desc> @@ -89,7 +90,7 @@ <func> <name>real_name(ConfigDB, RequestURI, Aliases) -> Ret</name> - <fsummary>Expand a request uri using Alias config directives.</fsummary> + <fsummary>Expands a request URI using <c>Aliases</c> config directives.</fsummary> <type> <v>ConfigDB = config_db()</v> <v>RequestURI = string()</v> @@ -101,18 +102,18 @@ <marker id="real_name"></marker> <p><c>real_name/3</c> traverses <c>Aliases</c>, typically extracted from <c>ConfigDB</c>, and matches each - <c>FakeName</c> with <c>RequestURI</c>. If a match is found + <c>FakeName</c> with <c>RequestURI</c>. If a match is found, <c>FakeName</c> is replaced with <c>RealName</c> in the - match. The resulting path is split into two parts, that - is <c>ShortPath</c> and <c>AfterPath</c> as defined in - <seealso marker="httpd_util#split_path">httpd_util:split_path/1</seealso>. - <c>Path</c> is generated from <c>ShortPath</c>, that is + match. The resulting path is split into two parts, + <c>ShortPath</c> and <c>AfterPath</c>, as defined in + <seealso marker="httpd_util#split_path-1">httpd_util:split_path/1</seealso>. + <c>Path</c> is generated from <c>ShortPath</c>, that is, the result from <seealso marker="#default_index">default_index/2</seealso> with <c>ShortPath</c> as an argument. <c>config_db()</c> is the server config file in ETS table format as described in - <seealso marker="http_server">Inets User Guide.</seealso>. </p> + <seealso marker="http_server">Inets User's Guide</seealso>.</p> <marker id="real_script_name"></marker> </desc> @@ -120,7 +121,8 @@ <func> <name>real_script_name(ConfigDB, RequestURI, ScriptAliases) -> Ret</name> - <fsummary>Expand a request uri using ScriptAlias config directives.</fsummary> + <fsummary>Expands a request URI using <c>ScriptAliases</c> + config directives.</fsummary> <type> <v>ConfigDB = config_db()</v> <v>RequestURI = string()</v> @@ -132,14 +134,16 @@ <marker id="real_script_name"></marker> <p><c>real_script_name/3</c> traverses <c>ScriptAliases</c>, typically extracted from <c>ConfigDB</c>, and matches each - <c>FakeName</c> with <c>RequestURI</c>. If a match is found + <c>FakeName</c> with <c>RequestURI</c>. If a match is found, <c>FakeName</c> is replaced with <c>RealName</c> in the - match. If the resulting match is not an executable script - <c>not_a_script</c> is returned. If it is a script the - resulting script path is in two parts, that is - <c>ShortPath</c> and <c>AfterPath</c> as defined in <seealso marker="httpd_util#split_script_path">httpd_util:split_script_path/1</seealso>. + match. If the resulting match is not an executable script, + <c>not_a_script</c> is returned. If it is a script, the + resulting script path is in two parts, + <c>ShortPath</c> and <c>AfterPath</c>, as defined in + <seealso marker="httpd_util#split_script_path-1">httpd_util:split_script_path/1</seealso>. <c>config_db()</c> is the server config file in ETS table - format as described in <seealso marker="http_server">Inets Users Guide.</seealso>.</p> + format as described in + <seealso marker="http_server">Inets User's Guide</seealso>.</p> </desc> </func> </funcs> diff --git a/lib/inets/doc/src/mod_auth.xml b/lib/inets/doc/src/mod_auth.xml index fda945cf73..2da2be37ed 100644 --- a/lib/inets/doc/src/mod_auth.xml +++ b/lib/inets/doc/src/mod_auth.xml @@ -30,299 +30,267 @@ <file>mod_auth.sgml</file> </header> <module>mod_auth</module> - <modulesummary>User authentication using text files, dets or mnesia database.</modulesummary> + <modulesummary>User authentication using text files, Dets, or Mnesia database.</modulesummary> <description> <p>This module provides for basic user authentication using - textual files, dets databases as well as mnesia databases. </p> - - <marker id="add_user"></marker> + textual files, <c>Dets</c> databases, or <c>Mnesia</c> databases.</p> </description> <funcs> + <func> + <name>add_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name> + <name>add_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name> + <name>add_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason}</name> + <fsummary>Adds a user to a group.</fsummary> + <type> + <v>GroupName = string()</v> + <v>UserName = string()</v> + <v>Options = [Option]</v> + <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> + <v>AuthPassword = string()</v> + <v>Reason = term()</v> + </type> + <desc> + <p><c>add_group_member/3, add_group_member/4</c>, and + <c>add_group_member/5</c> each + adds a user to a group. If the group does not exist, it + is created and the user is added to the group. Upon successful + operation, this function returns <c>true</c>. + When <c>add_group_members/3</c> + is called, options <c>Port</c> and <c>Dir</c> are mandatory.</p> + </desc> + </func> + <func> - <name>add_user(UserName, Options) -> true| {error, Reason}</name> + <name>add_user(UserName, Options) -> true| {error, Reason}</name> <name>add_user(UserName, Password, UserData, Port, Dir) -> true | {error, Reason}</name> <name>add_user(UserName, Password, UserData, Address, Port, Dir) -> true | {error, Reason}</name> - <fsummary>Add a user to the user database.</fsummary> + <fsummary>Adds a user to the user database.</fsummary> <type> - <v>UserName = string()</v> - <v>Options = [Option]</v> - <v>Option = {password,Password} | {userData,UserData} | {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> - <v>Password = string()</v> - <v>UserData = term()</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> + <v>UserName = string()</v> + <v>Options = [Option]</v> + <v>Option = {password,Password} | {userData,UserData} | {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> + <v>Password = string()</v> + <v>UserData = term()</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> <v>AuthPassword =string()</v> - <v>Reason = term()</v> + <v>Reason = term()</v> </type> <desc> - <marker id="user_api"></marker> - <marker id="add_user"></marker> - <p><c>add_user/2, add_user/5</c> and <c>add_user/6</c> adds a - user to the user - database. If the operation is successful, this function returns - <c>true</c>. If an error occurs, <c>{error,Reason}</c> is returned. - When <c>add_user/2</c> is called the Password, - UserData Port and Dir options is mandatory.</p> - - <marker id="delete_user"></marker> + <p><c>add_user/2, add_user/5</c>, and <c>add_user/6</c> each adds a + user to the user database. If the operation is successful, + this function returns <c>true</c>. If an error occurs, + <c>{error,Reason}</c> is returned. + When <c>add_user/2</c> is called, options <c>Password</c>, + <c>UserData</c>, <c>Port</c>, and <c>Dir</c> are mandatory.</p> </desc> </func> - <func> - <name>delete_user(UserName,Options) -> true | {error, Reason}</name> - <name>delete_user(UserName, Port, Dir) -> true | {error, Reason}</name> - <name>delete_user(UserName, Address, Port, Dir) -> true | {error, Reason}</name> - <fsummary>Delete a user from the user database.</fsummary> + <func> + <name>delete_group(GroupName, Options) -> true | {error,Reason} <name>delete_group(GroupName, Port, Dir) -> true | {error, Reason}</name> + <name>delete_group(GroupName, Address, Port, Dir) -> true | {error, Reason}</name> + <fsummary>Deletes a group.</fsummary> <type> - <v>UserName = string()</v> - <v>Options = [Option]</v> - <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> + <v>Options = [Option]</v> + <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> + <v>GroupName = string()</v> <v>AuthPassword = string()</v> - <v>Reason = term()</v> + <v>Reason = term()</v> </type> <desc> - <marker id="delete_user"></marker> - <p><c>delete_user/2, delete_user/3</c> and <c>delete_user/4</c> - deletes a user from the user database. - If the operation is successful, this function returns <c>true</c>. - If an error occurs, <c>{error,Reason}</c> is returned. - When <c>delete_user/2</c> is called the Port and Dir options - are mandatory.</p> - - <marker id="get_user"></marker> + <p><c>delete_group/2, delete_group/3</c>, and <c>delete_group/4</c> + each deletes the group specified and returns <c>true</c>. + If there is an error, <c>{error, Reason}</c> is returned. + When <c>delete_group/2</c> is called, option + <c>Port</c> and <c>Dir</c> are mandatory.</p> </desc> </func> - <func> - <name>get_user(UserName,Options) -> {ok, #httpd_user} |{error, Reason}</name> - <name>get_user(UserName, Port, Dir) -> {ok, #httpd_user} | {error, Reason}</name> - <name>get_user(UserName, Address, Port, Dir) -> {ok, #httpd_user} | {error, Reason}</name> - <fsummary>Returns a user from the user database.</fsummary> + <func> + <name>delete_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name> + <name>delete_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name> + <name>delete_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason}</name> + <fsummary>Removes a user from a group.</fsummary> <type> - <v>UserName = string()</v> - <v>Options = [Option]</v> - <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> + <v>GroupName = string()</v> + <v>UserName = string()</v> + <v>Options = [Option]</v> + <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> <v>AuthPassword = string()</v> - <v>Reason = term()</v> + <v>Reason = term()</v> </type> <desc> - <marker id="get_user"></marker> - <p><c>get_user/2, get_user/3</c> and <c>get_user/4</c> returns a - <c>httpd_user</c> record containing the userdata for a - specific user. If the user cannot be found, <c>{error, Reason}</c> - is returned. When <c>get_user/2</c> is called the Port and Dir - options are mandatory.</p> - - <marker id="list_users"></marker> + <p><c>delete_group_member/3, delete_group_member/4</c>, and + <c>delete_group_member/5</c> each deletes a user from a group. + If the group or the user does not exist, + this function returns an error, otherwise <c>true</c>. + When <c>delete_group_member/3</c> is called, the options <c>Port</c> + and <c>Dir</c> are mandatory.</p> </desc> </func> - + <func> - <name>list_users(Options) -> {ok, Users} | {error, Reason}</name> - <name>list_users(Port, Dir) -> {ok, Users} | {error, Reason}</name> - <name>list_users(Address, Port, Dir) -> {ok, Users} | {error, Reason}</name> - <fsummary>List users in the user database.</fsummary> + <name>delete_user(UserName,Options) -> true | {error, Reason}</name> + <name>delete_user(UserName, Port, Dir) -> true | {error, Reason}</name> + <name>delete_user(UserName, Address, Port, Dir) -> true | {error, Reason}</name> + <fsummary>Deletes a user from the user database.</fsummary> <type> - <v>Options = [Option]</v> - <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> - <v>Users = list()</v> + <v>UserName = string()</v> + <v>Options = [Option]</v> + <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> <v>AuthPassword = string()</v> - <v>Reason = atom()</v> + <v>Reason = term()</v> </type> <desc> - <marker id="list_users"></marker> - <p><c>list_users/1, list_users/2</c> and <c>list_users/3</c> - returns a list - of users in the user database for a specific <c>Port/Dir</c>. - When <c>list_users/1</c> is called the Port and Dir - options are mandatory.</p> - - <marker id="add_group_member"></marker> + <p><c>delete_user/2, delete_user/3</c>, and <c>delete_user/4</c> + each deletes a user from the user database. + If the operation is successful, this function returns <c>true</c>. + If an error occurs, <c>{error,Reason}</c> is returned. + When <c>delete_user/2</c> is called, options <c>Port</c> and <c>Dir</c> + are mandatory.</p> </desc> </func> <func> - <name>add_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name> - <name>add_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name> - <name>add_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason}</name> - <fsummary>Add a user to a group.</fsummary> + <name>get_user(UserName,Options) -> {ok, #httpd_user} |{error, Reason}</name> + <name>get_user(UserName, Port, Dir) -> {ok, #httpd_user} | {error, Reason}</name> + <name>get_user(UserName, Address, Port, Dir) -> {ok, #httpd_user} | {error, Reason}</name> + <fsummary>Returns a user from the user database.</fsummary> <type> - <v>GroupName = string()</v> - <v>UserName = string()</v> - <v>Options = [Option]</v> - <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> + <v>UserName = string()</v> + <v>Options = [Option]</v> + <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> <v>AuthPassword = string()</v> - <v>Reason = term()</v> + <v>Reason = term()</v> </type> <desc> - <marker id="add_group_member"></marker> - <p><c>add_group_member/3, add_group_member/4</c> and - <c>add_group_member/5</c> - adds a user to a group. If the group does not exist, it - is created and the user is added to the group. Upon successful - operation, this function returns <c>true</c>. - When <c>add_group_members/3</c> - is called the Port and Dir options are mandatory.</p> - - <marker id="delete_group_member"></marker> + <p><c>get_user/2, get_user/3</c>, and <c>get_user/4</c> each + returns an <c>httpd_user</c> record containing the userdata for a + specific user. If the user cannot be found, <c>{error, Reason}</c> + is returned. When <c>get_user/2</c> is called, options <c>Port</c> and <c>Dir</c> + are mandatory.</p> </desc> </func> - <func> - <name>delete_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name> - <name>delete_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name> - <name>delete_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason}</name> - <fsummary>Remove a user from a group.</fsummary> + <func> + <name>list_groups(Options) -> {ok, Groups} | {error, Reason}</name> + <name>list_groups(Port, Dir) -> {ok, Groups} | {error, Reason}</name> + <name>list_groups(Address, Port, Dir) -> {ok, Groups} | {error, Reason}</name> + <fsummary>Lists all the groups.</fsummary> <type> - <v>GroupName = string()</v> - <v>UserName = string()</v> - <v>Options = [Option]</v> - <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> + <v>Options = [Option]</v> + <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> + <v>Groups = list()</v> <v>AuthPassword = string()</v> - <v>Reason = term()</v> + <v>Reason = term()</v> </type> <desc> - <marker id="delete_group_member"></marker> - <p><c>delete_group_member/3, delete_group_member/4</c> and - <c>delete_group_member/5</c> deletes a user from a group. - If the group or the user does not exist, - this function returns an error, otherwise it returns <c>true</c>. - When <c>delete_group_member/3</c> is called the Port and Dir options - are mandatory.</p> - - <marker id="list_group_members"></marker> + <p><c>list_groups/1, list_groups/2</c>, and <c>list_groups/3</c> + each lists all the groups available. + If there is an error, <c>{error, Reason}</c> is returned. + When <c>list_groups/1</c> is called, options <c>Port</c> + and <c>Dir</c> are mandatory.</p> </desc> </func> - + <func> <name>list_group_members(GroupName, Options) -> {ok, Users} | {error, Reason}</name> <name>list_group_members(GroupName, Port, Dir) -> {ok, Users} | {error, Reason}</name> <name>list_group_members(GroupName, Address, Port, Dir) -> {ok, Users} | {error, Reason}</name> - <fsummary>List the members of a group.</fsummary> + <fsummary>Lists the members of a group.</fsummary> <type> - <v>GroupName = string()</v> - <v>Options = [Option]</v> - <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> - <v>Users = list()</v> + <v>GroupName = string()</v> + <v>Options = [Option]</v> + <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> + <v>Users = list()</v> <v>AuthPassword = string()</v> - <v>Reason = term()</v> + <v>Reason = term()</v> </type> <desc> - <marker id="list_group_members"></marker> - <p><c>list_group_members/2, list_group_members/3</c> and - <c>list_group_members/4</c> + <p><c>list_group_members/2, list_group_members/3</c>, and + <c>list_group_members/4</c> each lists the members of a specified group. If the group does not exist or there is an error, <c>{error, Reason}</c> is returned. - When <c>list_group_members/2</c> is called the Port and Dir options - are mandatory.</p> - - <marker id="list_groups"></marker> + When <c>list_group_members/2</c> is called, options <c>Port</c> + and <c>Dir</c> are mandatory.</p> </desc> </func> - <func> - <name>list_groups(Options) -> {ok, Groups} | {error, Reason}</name> - <name>list_groups(Port, Dir) -> {ok, Groups} | {error, Reason}</name> - <name>list_groups(Address, Port, Dir) -> {ok, Groups} | {error, Reason}</name> - <fsummary>List all the groups.</fsummary> + <func> + <name>list_users(Options) -> {ok, Users} | {error, Reason}</name> + <name>list_users(Port, Dir) -> {ok, Users} | {error, Reason}</name> + <name>list_users(Address, Port, Dir) -> {ok, Users} | {error, Reason}</name> + <fsummary>Lists users in the user database.</fsummary> <type> - <v>Options = [Option]</v> - <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> - <v>Groups = list()</v> + <v>Options = [Option]</v> + <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> + <v>Users = list()</v> <v>AuthPassword = string()</v> - <v>Reason = term()</v> + <v>Reason = atom()</v> </type> <desc> - <marker id="list_groups"></marker> - <p><c>list_groups/1, list_groups/2</c> and <c>list_groups/3</c> - lists all the groups available. - If there is an error, <c>{error, Reason}</c> is returned. - When <c>list_groups/1</c> is called the Port and Dir options + <p><c>list_users/1, list_users/2</c>, and <c>list_users/3</c> + each returns a list + of users in the user database for a specific <c>Port/Dir</c>. + When <c>list_users/1</c> is called, options <c>Port</c> and <c>Dir</c> are mandatory.</p> - - <marker id="delete_group"></marker> </desc> </func> - - <func> - <name>delete_group(GroupName, Options) -> true | {error,Reason} <name>delete_group(GroupName, Port, Dir) -> true | {error, Reason}</name> - <name>delete_group(GroupName, Address, Port, Dir) -> true | {error, Reason}</name> - <fsummary>Deletes a group</fsummary> - <type> - <v>Options = [Option]</v> - <v>Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword}</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> - <v>GroupName = string()</v> - <v>AuthPassword = string()</v> - <v>Reason = term()</v> - </type> - <desc> - <marker id="delete_group"></marker> - <p><c>delete_group/2, delete_group/3</c> and <c>delete_group/4</c> - deletes the group specified and returns <c>true</c>. - If there is an error, <c>{error, Reason}</c> is returned. - When <c>delete_group/2</c> is called the - Port and Dir options are mandatory.</p> - - <marker id="update_password"></marker> - </desc> - </func> - + <func> <name>update_password(Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason}</name> <name>update_password(Address,Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason}</name> - <fsummary>Change the AuthAcessPassword</fsummary> + <fsummary>Changes <c>AuthAcessPassword</c>.</fsummary> <type> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> - <v>GroupName = string()</v> - <v>OldPassword = string()</v> - <v>NewPassword = string()</v> - <v>Reason = term()</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> + <v>GroupName = string()</v> + <v>OldPassword = string()</v> + <v>NewPassword = string()</v> + <v>Reason = term()</v> </type> <desc> - <marker id="update_password"></marker> - <p><c>update_password/5</c> and <c>update_password/6</c> - Updates the AuthAccessPassword for the specified directory. - If NewPassword is equal to "NoPassword" no password is requires to + <p><c>update_password/5</c> and <c>update_password/6</c> each + updates <c>AuthAccessPassword</c> for the specified directory. + If <c>NewPassword</c> is equal to "NoPassword", no password is required to change authorisation data. - If NewPassword is equal to "DummyPassword" no changes can be done + If <c>NewPassword</c> is equal to "DummyPassword", no changes can be done without changing the password first.</p> </desc> </func> </funcs> <section> - <marker id="see_also"></marker> <title>SEE ALSO</title> <p><seealso marker="httpd">httpd(3)</seealso>, - <seealso marker="mod_alias">mod_alias(3)</seealso>,</p> + <seealso marker="mod_alias">mod_alias(3)</seealso></p> </section> </erlref> diff --git a/lib/inets/doc/src/mod_esi.xml b/lib/inets/doc/src/mod_esi.xml index 8044f46242..66c59a0c60 100644 --- a/lib/inets/doc/src/mod_esi.xml +++ b/lib/inets/doc/src/mod_esi.xml @@ -30,11 +30,11 @@ <file>mod_esi.sgml</file> </header> <module>mod_esi</module> - <modulesummary>Erlang Server Interface </modulesummary> + <modulesummary>Erlang Server Interface</modulesummary> <description> <p>This module defines the Erlang Server Interface (ESI) API. - It is a more efficient way of writing erlang scripts - for your Inets web server than writing them as common CGI scripts.</p> + It is a more efficient way of writing Erlang scripts + for your <c>Inets</c> web server than writing them as common CGI scripts.</p> <marker id="deliver"></marker> </description> @@ -42,7 +42,7 @@ <funcs> <func> <name>deliver(SessionID, Data) -> ok | {error, Reason}</name> - <fsummary>Sends Data back to client.</fsummary> + <fsummary>Sends <c>Data</c> back to client.</fsummary> <type> <v>SessionID = term()</v> <v>Data = string() | io_list() | binary()</v> @@ -53,16 +53,16 @@ <p>This function is <em>only</em> intended to be used from functions called by the Erl Scheme interface to deliver parts of the content to the user.</p> - <p>Sends data from a Erl Scheme script back to the client.</p> + <p>Sends data from an Erl Scheme script back to the client.</p> <note> - <p>Note that if any HTTP-header fields should be added by the - script they must be in the first call to deliver/2 and the - data in the call must be a string. Calls after the headers - are complete may contain binary data to reduce copying - overhead. Do not assume anything about the data type of - SessionID, the SessionID must be the value given as input to - the esi call back function that you implemented.</p> + <p>If any HTTP header fields are added by the + script, they must be in the first call to <c>deliver/2</c>, + and the data in the call must be a string. Calls after the headers + are complete can contain binary data to reduce copying + overhead. Do not assume anything about the data type of + <c>SessionID</c>. <c>SessionID</c> must be the value given + as input to the ESI callback function that you implemented.</p> </note> </desc> </func> @@ -74,54 +74,55 @@ <funcs> <func> <name>Module:Function(SessionID, Env, Input)-> _ </name> - <fsummary>Creates a dynamic web page and returns it chunk by chunk to the server process by calling mod_esi:deliver/2.</fsummary> + <fsummary>Creates a dynamic web page and returns it chunk by chunk + to the server process by calling <c>mod_esi:deliver/2</c>.</fsummary> <type> <v>SessionID = term()</v> - <v>Env = [EnvironmentDirectives] ++ ParsedHeader</v> + <v>Env = [EnvironmentDirectives] ++ ParsedHeader</v> <v>EnvironmentDirectives = {Key,Value}</v> <v>Key = query_string | content_length | server_software | gateway_interface | server_protocol | server_port | request_method | remote_addr | script_name</v> <v>Input = string()</v> </type> <desc> - <p>The <c>Module</c> must be found in the code path and export - <c>Function</c> with an arity of three. An erlScriptAlias must - also be set up in the configuration file for the Web server.</p> - <p>If the HTTP request is a 'post' request and a body is sent - then content_length will be the length of the posted - data. If 'get' is used query_string will be the data after - <em>?</em> in the url.</p> - <p>ParsedHeader is the HTTP request as a key value tuple - list. The keys in parsed header will be the in lower case.</p> - <p>SessionID is a identifier - the server uses when <c>deliver/2</c> is called; do not + <p><c>Module</c> must be found in the code path and export + <c>Function</c> with an arity of three. An <c>erlScriptAlias</c> must + also be set up in the configuration file for the web server.</p> + <p>If the HTTP request is a 'post' request and a body is sent, + <c>content_length</c> is the length of the posted + data. If 'get' is used, <c>query_string</c> is the data after + <em>?</em> in the URL.</p> + <p><c>ParsedHeader</c> is the HTTP request as a key-value tuple + list. The keys in <c>ParsedHeader</c> are in lower case.</p> + <p><c>SessionID</c> is an identifier + the server uses when <c>deliver/2</c> is called. Do not assume anything about the datatype.</p> - <p>Use this callback function to dynamically generate dynamic web - content. When a part of the page is generated send the - data back to the client through <c>deliver/2</c>. Note + <p>Use this callback function to generate dynamic web + content dynamically. When a part of the page is generated, send the + data back to the client through <c>deliver/2</c>. Notice that the first chunk of data sent to the client must at least contain all HTTP header fields that the response will generate. If the first chunk does not contain the - <em>End of HTTP header</em>, that is <c>"\r\n\r\n",</c> - the server will - assume that no HTTP header fields will be generated.</p> + <em>end of HTTP header</em>, that is, <c>"\r\n\r\n",</c> + the server assumes that no HTTP header fields will be generated.</p> </desc> </func> <func> <name>Module:Function(Env, Input)-> Response </name> - <fsummary>Creates a dynamic web page and return it as a list. This functions is deprecated and only kept for backwards compatibility.</fsummary> + <fsummary>Creates a dynamic web page and returns it as a list. + This function is deprecated and is only kept for backwards compatibility.</fsummary> <type> - <v>Env = [EnvironmentDirectives] ++ ParsedHeader</v> + <v>Env = [EnvironmentDirectives] ++ ParsedHeader</v> <v>EnvironmentDirectives = {Key,Value}</v> <v>Key = query_string | content_length | server_software | gateway_interface | server_protocol | server_port | request_method | remote_addr | script_name.</v> <v>Input = string()</v> <v>Response = string()</v> </type> <desc> - <p>This callback format consumes a lot of memory since the + <p>This callback format consumes much memory, as the whole response must be generated before it is sent to the - user. This function is deprecated and only kept for backwards + user. This function is deprecated and is only kept for backwards compatibility. - For new development Module:Function/3 should be used.</p> + For new development, use <c>Module:Function/3</c>.</p> </desc> </func> </funcs> diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml index 467c68d364..9dc32b971b 100644 --- a/lib/inets/doc/src/mod_security.xml +++ b/lib/inets/doc/src/mod_security.xml @@ -35,24 +35,45 @@ <p>Security Audit and Trailing Functionality</p> </description> <funcs> + + <func> + <name>block_user(User, Port, Dir, Seconds) -> true | {error, Reason}</name> + <name>block_user(User, Address, Port, Dir, Seconds) -> true | {error, Reason}</name> + <fsummary>Blocks a user from access to a directory for a certain amount of time.</fsummary> + <type> + <v>User = string()</v> + <v>Port = integer()</v> + <v>Address = {A,B,C,D} | string() | undefined</v> + <v>Dir = string()</v> + <v>Seconds = integer() | infinity</v> + <v>Reason = no_such_directory</v> + </type> + <desc> + <p><c>block_user/4</c> and <c>block_user/5</c> each blocks the user + <c>User</c> from directory <c>Dir</c> for a specified + amount of time.</p> + </desc> + </func> + <func> <name>list_auth_users(Port) -> Users | []</name> <name>list_auth_users(Address, Port) -> Users | []</name> <name>list_auth_users(Port, Dir) -> Users | []</name> <name>list_auth_users(Address, Port, Dir) -> Users | []</name> - <fsummary>List users that have authenticated within the SecurityAuthTimeout time for a given address (if specified), port number and directory (if specified).</fsummary> + <fsummary>Lists users that have authenticated within the <c>SecurityAuthTimeout</c> + time for a given address (if specified), port number, and directory + (if specified).</fsummary> <type> - <v>Port = integer()</v> + <v>Port = integer()</v> <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> - <v>Users = list() = [string()]</v> + <v>Dir = string()</v> + <v>Users = list() = [string()]</v> </type> <desc> - <marker id="list_auth_users"></marker> - <p><c>list_auth_users/1</c>, <c>list_auth_users/2</c> and - <c>list_auth_users/3</c> returns a list of users that are + <p><c>list_auth_users/1</c>, <c>list_auth_users/2</c>, and + <c>list_auth_users/3</c> each returns a list of users that are currently authenticated. Authentications are stored for - SecurityAuthTimeout seconds, and are then discarded.</p> + <c>SecurityAuthTimeout</c> seconds, and then discarded.</p> </desc> </func> <func> @@ -60,96 +81,83 @@ <name>list_blocked_users(Address, Port) -> Users | []</name> <name>list_blocked_users(Port, Dir) -> Users | []</name> <name>list_blocked_users(Address, Port, Dir) -> Users | []</name> - <fsummary>List users that are currently blocked from access to a specified port number, for a given address (if specified).</fsummary> + <fsummary>Lists users that are currently blocked from access to a + specified port number, for a given address (if specified).</fsummary> <type> - <v>Port = integer()</v> + <v>Port = integer()</v> <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> - <v>Users = list() = [string()]</v> + <v>Dir = string()</v> + <v>Users = list() = [string()]</v> </type> <desc> - <marker id="list_blocked_users"></marker> - <p><c>list_blocked_users/1</c>, <c>list_blocked_users/2</c> and - <c>list_blocked_users/3</c> returns a list of users that are + <p><c>list_blocked_users/1</c>, <c>list_blocked_users/2</c>, and + <c>list_blocked_users/3</c> each returns a list of users that are currently blocked from access.</p> </desc> </func> + <func> - <name>block_user(User, Port, Dir, Seconds) -> true | {error, Reason}</name> - <name>block_user(User, Address, Port, Dir, Seconds) -> true | {error, Reason}</name> - <fsummary>Block user from access to a directory for a certain amount of time.</fsummary> - <type> - <v>User = string()</v> - <v>Port = integer()</v> - <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> - <v>Seconds = integer() | infinity</v> - <v>Reason = no_such_directory</v> - </type> - <desc> - <marker id="block_user"></marker> - <p><c>block_user/4</c> and <c>block_user/5</c> blocks the user - <c>User</c> from the directory <c>Dir</c> for a specified - amount of time.</p> - </desc> - </func> - <func> - <name>unblock_user(User, Port) -> true | {error, Reason}</name> + <name>unblock_user(User, Port) -> true | {error, Reason}</name> <name>unblock_user(User, Address, Port) -> true | {error, Reason}</name> - <name>unblock_user(User, Port, Dir) -> true | {error, Reason}</name> + <name>unblock_user(User, Port, Dir) -> true | {error, Reason}</name> <name>unblock_user(User, Address, Port, Dir) -> true | {error, Reason}</name> - <fsummary>Remove a blocked user from the block list</fsummary> + <fsummary>Removes a blocked user from the block list.</fsummary> <type> - <v>User = string()</v> - <v>Port = integer()</v> + <v>User = string()</v> + <v>Port = integer()</v> <v>Address = {A,B,C,D} | string() | undefined</v> - <v>Dir = string()</v> + <v>Dir = string()</v> <v>Reason = term()</v> </type> <desc> - <marker id="unblock_user"></marker> - <p><c>unblock_user/2</c>, <c>unblock_user/3</c> and - <c>unblock_user/4</c> removes the user <c>User</c> from - the list of blocked users for the Port (and Dir) specified.</p> + <p><c>unblock_user/2</c>, <c>unblock_user/3</c>, and + <c>unblock_user/4</c> each removes the user <c>User</c> from + the list of blocked users for <c>Port</c> (and <c>Dir</c>).</p> </desc> </func> </funcs> <section> <marker id="callback_module"></marker> - <title>The SecurityCallbackModule</title> - <p>The SecurityCallbackModule is a user written module that can receive - events from the mod_security Erlang Webserver API module. - This module only exports the function(s), - <seealso marker="#callback_module_event">event/4,5</seealso>, - which are described below. + <title>SecurityCallbackModule</title> + <p>The <c>SecurityCallbackModule</c> is a user-written module that can receive + events from the <c>mod_security</c> Erlang web server API module. + This module only exports the functions event/[4,5] + which are described here. </p> </section> <funcs> <func> - <name>event(What, Port, Dir, Data) -> ignored</name> - <name>event(What, Address, Port, Dir, Data) -> ignored</name> - <fsummary>This function is called whenever an event occurs in mod_security</fsummary> + <name>Module:event(What, Port, Dir, Data) -> ignored</name> + <name>Module:event(What, Address, Port, Dir, Data) -> ignored</name> + <fsummary>Called whenever an event occurs in <c>mod_security</c>.</fsummary> <type> - <v>What = atom()</v> - <v>Port = integer()</v> + <v>What = atom()</v> + <v>Port = integer()</v> <v>Address = {A,B,C,D} | string() <v>Dir = string()</v> - <v>Data = [Info]</v> - <v>Info = {Name, Value}</v> + <v>Data = [Info]</v> + <v>Info = {Name, Value}</v> </type> <desc> <marker id="callback_module_event"></marker> - <p><c>event/4</c> or <c>event/4</c> is called whenever an event - occurs in the mod_security Erlang Webserver API module (<c>event/4</c> is - called if Address is undefined and <c>event/5</c> otherwise). - The <c>What</c> argument specifies the type of event that has - occurred, and should be one of the following reasons; - <c>auth_fail</c> (a failed user authentication), - <c>user_block</c> (a user is being blocked from access) or - <c>user_unblock</c> (a user is being removed from the block list).</p> + <p><c>event/4</c> or <c>event/5</c> is called whenever an event + occurs in the <c>mod_security</c> Erlang web server API module. + (<c>event/4</c> is called if <c>Address</c> is undefined, + otherwise <c>event/5</c>. + Argument <c>What</c> specifies the type of event that has + occurred and is one of the following reasons: + </p> + <taglist> + <tag><c>auth_fail</c></tag> + <item><p>A failed user authentication.</p></item> + <tag><c>user_block</c></tag> + <item><p>A user is being blocked from access.</p></item> + <tag><c>user_unblock</c></tag> + <item><p>A user is being removed from the block list.</p></item> + </taglist> <note> - <p>Note that the <c>user_unblock</c> event is not triggered when + <p>The event <c>user_unblock</c> is not triggered when a user is removed from the block list explicitly using the <c>unblock_user</c> function.</p> </note> diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index d1bfa28013..ef11fdc10c 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,95 @@ <file>notes.xml</file> </header> - <section><title>Inets 6.0</title> + <section><title>Inets 6.0.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Avoid crash in mod_auth_server and mod_security_server + due to using an atom instead of a string when creating a + name.</p> + <p> + Own Id: OTP-13022</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add function response_default_headers/0 to httpd + customize API, to allow user to specify default values + for HTTP response headers.</p> + <p> + Own Id: OTP-13013</p> + </item> + </list> + </section> + +</section> + +<section><title>Inets 6.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix broken socket feature, that is on Linux systems a + socket may be opened before starting Erlang and then + passed to Erlang's httpd daemon. This is useful as the + wrap program can open a privileged port and Erlang does + not have to be run as root.</p> + <p> + Own Id: OTP-12875 Aux Id: seq12878 </p> + </item> + <item> + <p> + Fix broken socket feature, that is on Linux systems a + socket may be opened before starting Erlang and then + passed to Erlangs tftp daemon. This is useful as the wrap + program can open a privileged port and Erlang does not + have to be run as root.</p> + <p> + Own Id: OTP-12898 Aux Id: seq12900 </p> + </item> + <item> + <p> + httpc_handler should react properly to cancel requests + even when the request to be canceled was already finished + but httpc_manager did not get notified about that yet.</p> + <p> + Own Id: OTP-12922</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Added format_status function to httpd process to avoid + sensitive information to be printed in supervisor logs.</p> + <p> + Own Id: OTP-12976</p> + </item> + <item> + <p> + Return meaningful error reason disregarding whether a + http proxy is used or not.</p> + <p> + Own Id: OTP-12984</p> + </item> + </list> + </section> + +</section> + +<section><title>Inets 6.0</title> <section><title>Fixed Bugs and Malfunctions</title> <list> @@ -765,9 +853,9 @@ <p>Better handling of errorI(s) during update of the session database. </p> <p>Also added and updated some debugging functions - <seealso marker="httpc#which_sessions">which_sessions/10,1</seealso> + <seealso marker="httpc#which_sessions-0">which_sessions/[0,1]</seealso> and - <seealso marker="httpc#info">info/0</seealso>. </p> + <seealso marker="httpc#info-0">info/0</seealso>. </p> <p>Own Id: OTP-10093</p> <p>Aux Id: Seq 12062</p> </item> @@ -861,7 +949,7 @@ <item> <p>[httpc] Add function for retrieving current options, - <seealso marker="httpc#get_options">get_options/1,2</seealso>. </p> + <seealso marker="httpc#get_options-1">get_options/[1,2]</seealso>. </p> <p>Own Id: OTP-9979</p> </item> @@ -1038,15 +1126,11 @@ <section> <title>Incompatibilities</title> -<!-- - <p>-</p> ---> - <list> <item> <p>[httpc] Deprecated interface module <c>http</c> has been removed. It has (long) been replaced by http client interface module - <seealso marker="httpc#">httpc</seealso>. </p> + <seealso marker="httpc">httpc</seealso>. </p> <p>Own Id: OTP-9359</p> </item> @@ -1234,15 +1318,13 @@ <section><title>Inets 5.6</title> <section><title>Improvements and New Features</title> -<!-- - <p>-</p> ---> + <list> <item> <p>[httpc] Add support for upload body streaming (PUT and POST).</p> <p>For more info, see the definition of the <c>Body</c> argument of the - <seealso marker="httpc#request2">request/4,5</seealso> + <seealso marker="httpc#request-4">request/[4,5]</seealso> function. </p> <p>Filipe David Manana</p> <p>Own Id: OTP-9094</p> @@ -1255,7 +1337,7 @@ <item> <p>[httpd] - <seealso marker="mod_esi#deliver">mod_esi:deliver/2</seealso> + <seealso marker="mod_esi#deliver-2">mod_esi:deliver/2</seealso> made to accept binary data. </p> <p>Bernard Duggan</p> <p>Own Id: OTP-9123</p> @@ -1283,7 +1365,7 @@ for using file descriptors has been improved. It is now possible to add the file descriptor to the config (option fd) when calling the - <seealso marker="inets#start2">inets:start(httpd, ...)</seealso> + <seealso marker="inets#start-2">inets:start(httpd, ...)</seealso> function. </p> <p>Attila Rajmund Nohl</p> <p>Own Id: OTP-9202</p> @@ -1297,7 +1379,7 @@ <p>See the httpd <seealso marker="httpd#props_comm">socket_type</seealso> communication property or the httpc - <seealso marker="httpc#request2">request/4,5</seealso> function + <seealso marker="httpc#request-4">request/[4,5]</seealso> function for more info. </p> <p>Own Id: OTP-9230</p> <p>*** POTENTIAL INCOMPATIBILITY ***</p> @@ -1497,7 +1579,7 @@ <p>[httpc|httpd] - Now allow the use of the "new" ssl, by using the <c>essl</c> tag instead. </p> <p>See the <c>http_option</c> option in the - <seealso marker="httpc#request2">request/4,5</seealso> or + <seealso marker="httpc#request-4">request/[4,5]</seealso> or the <seealso marker="httpd#props_comm">socket-type</seealso> section of the Communication properties chapter for more info, </p> <p>Own Id: OTP-7907</p> @@ -1729,8 +1811,8 @@ <p>[httpc] - Allow users to pass socket options to the transport module when making requests. </p> <p>See the <c>socket_opts</c> option in the - <seealso marker="httpc#request2">request/4</seealso> or - <seealso marker="httpc#set_options">set_options/1,2</seealso> + <seealso marker="httpc#request-4">request/4</seealso> or + <seealso marker="httpc#set_options-1">set_options/[1,2]</seealso> for more info, </p> <p>Own Id: OTP-8352</p> </item> @@ -1771,7 +1853,7 @@ deliver an async reply to more receivers then the calling process. </p> <p>See the - <seealso marker="httpc#request2">receiver</seealso> + <seealso marker="httpc#request-2">receiver</seealso> option for more info, </p> <p>Own Id: OTP-8106</p> </item> @@ -2040,7 +2122,7 @@ request, when the client connects to the server. Default value is that of the <c>timeout</c> option. </p> <p>See the - <seealso marker="httpc#request2">request/4,5</seealso> + <seealso marker="httpc#request-4">request/[4,5]</seealso> function for more info. </p> <p>Own Id: OTP-7298</p> <!-- <p>Aux Id: seq11086</p> --> @@ -2147,7 +2229,7 @@ the client connects to the server. </p> <p>As a side-effect of this, the option <c>ipv6</c> has been removed and replaced by the <c>ipfamily</c> option. </p> - <p>See <seealso marker="httpc#set_options">http:set_options/1,2</seealso> + <p>See <seealso marker="httpc#set_options-1">http:set_options/[1,2]</seealso> for more info. </p> <p>*** POTENTIAL INCOMPATIBILITY ***</p> <p>Own Id: OTP-8004</p> diff --git a/lib/inets/doc/src/part.xml b/lib/inets/doc/src/part.xml index 1640ff507c..3b817eecf2 100644 --- a/lib/inets/doc/src/part.xml +++ b/lib/inets/doc/src/part.xml @@ -30,10 +30,18 @@ <file>part.sgml</file> </header> <description> - <p>The <em>Inets Application </em> provides a set of Internet - related services. Currently supported are a HTTP client, a HTTP - server a FTP client and a TFTP client and server.</p> + <p>The <c>Inets</c> application provides a set of + Internet-related services as follows:</p> + <list type="bulleted"> + <item>An FTP client</item> + <item>A TFTP client and server</item> + <item>An <term id="HTTP"></term> client and server</item> + </list> + <p>The HTTP client and server are HTTP 1.1 compliant as + defined in + <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>.</p> </description> + <xi:include href="introduction.xml"/> <xi:include href="inets_services.xml"/> <xi:include href="ftp_client.xml"/> <xi:include href="http_client.xml"/> diff --git a/lib/inets/doc/src/ref_man.xml b/lib/inets/doc/src/ref_man.xml index bcebcc0fd4..27021ea09a 100644 --- a/lib/inets/doc/src/ref_man.xml +++ b/lib/inets/doc/src/ref_man.xml @@ -30,16 +30,15 @@ <file>ref_man.xml</file> </header> <description> - <p>Inets is a container for Internet clients and - servers. Currently a FTP client, a HTTP client and server, and - a tftp client and server has been incorporated in Inets.</p> + <p><c>Inets</c> is a container for Internet clients and + servers. An FTP client, an HTTP client and server, and + a TFTP client and server are incorporated in <c>Inets</c>.</p> </description> <xi:include href="inets.xml"/> <xi:include href="ftp.xml"/> <xi:include href="tftp.xml"/> <xi:include href="httpc.xml"/> <xi:include href="httpd.xml"/> - <xi:include href="httpd_conf.xml"/> <xi:include href="httpd_custom_api.xml"/> <xi:include href="httpd_socket.xml"/> <xi:include href="httpd_util.xml"/> diff --git a/lib/inets/doc/src/tftp.xml b/lib/inets/doc/src/tftp.xml index e70712fd1e..00d9d53376 100644 --- a/lib/inets/doc/src/tftp.xml +++ b/lib/inets/doc/src/tftp.xml @@ -29,173 +29,170 @@ <rev></rev> </header> <module>tftp</module> - <modulesummary>Trivial FTP</modulesummary> + <modulesummary>Trivial FTP.</modulesummary> <description> <p>This is a complete implementation of the following IETF standards:</p> <list type="bulleted"> - <item>RFC 1350, The TFTP Protocol (revision 2).</item> - <item>RFC 2347, TFTP Option Extension.</item> - <item>RFC 2348, TFTP Blocksize Option.</item> - <item>RFC 2349, TFTP Timeout Interval and Transfer Size Options.</item> + <item>RFC 1350, The TFTP Protocol (revision 2)</item> + <item>RFC 2347, TFTP Option Extension</item> + <item>RFC 2348, TFTP Blocksize Option</item> + <item>RFC 2349, TFTP Timeout Interval and Transfer Size Options</item> </list> - <p>The only feature that not is implemented in this release is + <p>The only feature that not is implemented is the "netascii" transfer mode.</p> <p>The <seealso marker="#start/1">start/1</seealso> function starts - a daemon process which listens for UDP packets on a port. When it - receives a request for read or write it spawns a temporary server - process which handles the actual transfer of the file.</p> - <p>On the client side - the <seealso marker="#read_file/3">read_file/3</seealso> + a daemon process listening for UDP packets on a port. When it + receives a request for read or write, it spawns a temporary server + process handling the transfer.</p> + <p>On the client side, + function <seealso marker="#read_file/3">read_file/3</seealso> and <seealso marker="#write_file/3">write_file/3</seealso> - functions spawns a temporary client process which establishes - contact with a TFTP daemon and performs the actual transfer of - the file.</p> - <p><c>tftp</c> uses a callback module to handle the actual file + spawn a temporary client process establishing + contact with a TFTP daemon and perform the file transfer.</p> + <p><c>tftp</c> uses a callback module to handle the file transfer. Two such callback modules are provided, <c>tftp_binary</c> and <c>tftp_file</c>. See <seealso marker="#read_file/3">read_file/3</seealso> and - <seealso marker="#write_file/3">write_file/3</seealso> for - more information about these. The user can also implement own - callback modules, see <seealso marker="#tftp_callback">CALLBACK FUNCTIONS</seealso> below. A callback module provided by - the user is registered using the <c>callback</c> option, see - <seealso marker="#options">DATA TYPES</seealso> below.</p> + <seealso marker="#write_file/3">write_file/3</seealso> for details. + You can also implement your own callback modules, see + <seealso marker="#tftp_callback">CALLBACK FUNCTIONS</seealso>. + A callback module provided by + the user is registered using option <c>callback</c>, see + <seealso marker="#options">DATA TYPES</seealso>.</p> </description> <section> - <title>TFTP SERVER SERVICE START/STOP </title> + <title>TFTP SERVER SERVICE START/STOP</title> <p>A TFTP server can be configured to start statically when starting - the Inets application. Alternatively it can be started dynamically - (when Inets already is started) by calling the Inets application API - <c>inets:start(tftpd, ServiceConfig)</c>, or + the <c>Inets</c> application. Alternatively, it can be started dynamically + (when <c>Inets</c> is already started) by calling the <c>Inets</c> application + API <c>inets:start(tftpd, ServiceConfig)</c> or <c>inets:start(tftpd, ServiceConfig, How)</c>, see <seealso marker="inets">inets(3)</seealso> for details. - The <c>ServiceConfig</c> for TFTP is described below in - the <seealso marker="#options">COMMON DATA TYPES</seealso> + The <c>ServiceConfig</c> for TFTP is described in + the <seealso marker="#options">DATA TYPES</seealso> section.</p> <p>The TFTP server can be stopped using <c>inets:stop(tftpd, Pid)</c>, see <seealso marker="inets">inets(3)</seealso> for details.</p> <p>The TPFT client is of such a temporary nature that it is not - handled as a service in the Inets service framework.</p> + handled as a service in the <c>Inets</c> service framework.</p> </section> <section> <marker id="options"></marker> - <title>COMMON DATA TYPES</title> - <pre> - ServiceConfig = Options - Options = [option()] - option() -- see below - </pre> + <title>DATA TYPES</title> + <p><c>ServiceConfig = Options</c></p> + <p><c>Options = [option()]</c></p> <p>Most of the options are common for both the client and the server - side, but some of them differs a little. Here are the available - options:</p> + side, but some of them differs a little. + The available <c>option()</c>s are as follows:</p> <taglist> <tag><c>{debug, Level}</c></tag> <item> <p><c>Level = none | error | warning | brief | normal | verbose | all</c></p> - <p>Controls the level of debug printouts. The default is - <c>none</c>.</p> + <p>Controls the level of debug printouts. + Default is <c>none</c>.</p> </item> <tag><c>{host, Host}</c></tag> <item> - <p><c>Host = hostname()</c> see - <seealso marker="kernel:inet">inet(3)</seealso></p> + <p><c>Host = hostname()</c>, see + <seealso marker="kernel:inet">inet(3)</seealso>.</p> <p>The name or IP address of the host where the TFTP daemon resides. This option is only used by the client.</p> </item> <tag><c>{port, Port}</c></tag> <item> <p><c>Port = int()</c></p> - <p>The TFTP port where the daemon listens. It defaults to - the standardized number 69. On the server side it may - sometimes make sense to set it to 0, which means that - the daemon just will pick a free port (which one is - returned by the <c>info/1</c> function).</p> - <p>If a socket has somehow already has been connected, the - {udp, [{fd, integer()}]} option can be used to pass the - open file descriptor to gen_udp. This can be automated - a bit by using a command line argument stating the + <p>The TFTP port where the daemon listens. Defaults is + the standardized number 69. On the server side, it can + sometimes make sense to set it to 0, meaning that + the daemon just picks a free port (which one is + returned by function <c>info/1</c>).</p> + <p>If a socket is connected already, option + <c>{udp, [{fd, integer()}]}</c> can be used to pass the + open file descriptor to <c>gen_udp</c>. This can be automated + by using a command-line argument stating the prebound file descriptor number. For example, if the - Port is 69 and the file descriptor 22 has been opened by - setuid_socket_wrap. Then the command line argument - "-tftpd_69 22" will trigger the prebound file + port is 69 and file descriptor 22 is opened by + <c>setuid_socket_wrap</c>, the command-line argument + "-tftpd_69 22" triggers the prebound file descriptor 22 to be used instead of opening port 69. - The UDP option {udp, [{fd, 22}]} automatically be added. - See init:get_argument/ about command line arguments and - gen_udp:open/2 about UDP options.</p> + The UDP option <c>{udp, [{fd, 22}]}</c> is automatically added. + See <c>init:get_argument/</c> about command-line arguments and + <c>gen_udp:open/2</c> about UDP options.</p> </item> <tag><c>{port_policy, Policy}</c></tag> <item> - <p><c>Policy = random | Port | {range, MinPort, MaxPort}</c> <br></br> -<c>Port = MinPort = MaxPort = int()</c></p> - <p>Policy for the selection of the temporary port which is used - by the server/client during the file transfer. It defaults to - <c>random</c> which is the standardized policy. With this - policy a randomized free port used. A single port or a range - of ports can be useful if the protocol should pass through a + <p><c>Policy = random | Port | {range, MinPort, MaxPort}</c></p> + <p><c>Port = MinPort = MaxPort = int()</c></p> + <p>Policy for the selection of the temporary port that is used + by the server/client during the file transfer. Default is + <c>random</c>, which is the standardized policy. With this + policy a randomized free port is used. A single port or a range + of ports can be useful if the protocol passes through a firewall.</p> </item> <tag><c>{udp, Options}</c></tag> <item> - <p><c>Options = [Opt]</c> see - <seealso marker="kernel:gen_udp#open/1">gen_udp:open/2</seealso></p> + <p><c>Options = [Opt]</c>, see + <seealso marker="kernel:gen_udp#open/1">gen_udp:open/2</seealso>.</p> </item> <tag><c>{use_tsize, Bool}</c></tag> <item> <p><c>Bool = bool()</c></p> - <p>Flag for automated usage of the <c>tsize</c> option. With - this set to true, the <c>write_file/3</c> client will - determine the filesize and send it to the server as + <p>Flag for automated use of option <c>tsize</c>. With + this set to <c>true</c>, the <c>write_file/3</c> client + determines the filesize and sends it to the server as the standardized <c>tsize</c> option. A <c>read_file/3</c> - client will just acquire filesize from the server by sending + client acquires only a filesize from the server by sending a zero <c>tsize</c>.</p> </item> <tag><c>{max_tsize, MaxTsize}</c></tag> <item> <p><c>MaxTsize = int() | infinity</c></p> <p>Threshold for the maximal filesize in bytes. The transfer - will be aborted if the limit is exceeded. It defaults to - <c>infinity</c>.</p> + is aborted if the limit is exceeded. + Default is <c>infinity</c>.</p> </item> <tag><c>{max_conn, MaxConn}</c></tag> <item> <p><c>MaxConn = int() | infinity</c></p> <p>Threshold for the maximal number of active connections. - The daemon will reject the setup of new connections if - the limit is exceeded. It defaults to <c>infinity</c>.</p> + The daemon rejects the setup of new connections if + the limit is exceeded. Default is <c>infinity</c>.</p> </item> <tag><c>{TftpKey, TftpVal}</c></tag> <item> <p><c>TftpKey = string()</c> <br></br> <c>TftpVal = string()</c></p> - <p>The name and value of a TFTP option.</p> + <p>Name and value of a TFTP option.</p> </item> <tag><c>{reject, Feature}</c></tag> <item> <p><c>Feature = Mode | TftpKey</c> <br></br> <c> Mode = read | write</c> <br></br> <c> TftpKey = string()</c></p> - <p>Control which features that should be rejected. This is - mostly useful for the server as it may restrict usage of - certain TFTP options or read/write access.</p> + <p>Controls which features to reject. This is + mostly useful for the server as it can restrict the use + of certain TFTP options or read/write access.</p> </item> <tag><c>{callback, {RegExp, Module, State}}</c></tag> <item> <p><c>RegExp = string()</c> <br></br> <c>Module = atom()</c> <br></br> -<c>State = term()</c></p> +<c>State = term()</c></p> <p>Registration of a callback module. When a file is to be - transferred, its local filename will be matched to the regular + transferred, its local filename is matched to the regular expressions of the registered callbacks. The first matching - callback will be used the during the transfer. See + callback is used during the transfer. See <seealso marker="#read_file/3">read_file/3</seealso> and <seealso marker="#write_file/3">write_file/3</seealso>. </p> - <p>The callback module must implement the <c>tftp</c> behavior, + <p>The callback module must implement the <c>tftp</c> behavior, see <seealso marker="#tftp_callback">CALLBACK FUNCTIONS</seealso>.</p> </item> @@ -203,9 +200,9 @@ <item> <p><c>Module = module()()</c></p> - <p>Callback module for customized logging of error, warning and - info messages. >The callback module must implement the - <c>tftp_logger</c> behavior, + <p>Callback module for customized logging of errors, warnings, and + info messages. The callback module must implement the + <c>tftp_logger</c> behavior, see <seealso marker="#tftp_logger">LOGGER FUNCTIONS</seealso>. The default module is <c>tftp_logger</c>.</p> </item> @@ -215,8 +212,8 @@ <p><c>MaxRetries = int()</c></p> <p>Threshold for the maximal number of retries. By default - the server/client will try to resend a message up to - <c>5</c> times when the timeout expires.</p> + the server/client tries to resend a message up to + five times when the time-out expires.</p> </item> </taglist> @@ -224,98 +221,67 @@ </section> <funcs> + <marker id="change_config_daemons"></marker> <func> - <name>start(Options) -> {ok, Pid} | {error, Reason}</name> - <fsummary>Start a daemon process</fsummary> + <name>change_config(daemons, Options) -> [{Pid, Result}]</name> + <fsummary>Changes configuration for all daemons. + </fsummary> <type> <v>Options = [option()]</v> <v>Pid = pid()</v> + <v>Result = ok | {error, Reason}</v> <v>Reason = term()</v> </type> <desc> - <p>Starts a daemon process which listens for udp packets on a - port. When it receives a request for read or write it spawns - a temporary server process which handles the actual transfer - of the (virtual) file.</p> + <p>Changes configuration for all TFTP daemon processes. </p> - <marker id="read_file"></marker> + <marker id="change_config_servers"></marker> </desc> </func> <func> - <name>read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name> - <fsummary>Read a (virtual) file from a TFTP server</fsummary> + <name>change_config(servers, Options) -> [{Pid, Result}]</name> + <fsummary>Changes configuration for all servers. + </fsummary> <type> - <v>RemoteFilename = string()</v> - <v>LocalFilename = binary | string()</v> <v>Options = [option()]</v> - <v>LastCallbackState = term()</v> + <v>Pid = pid()</v> + <v>Result = ok | {error, Reason}</v> <v>Reason = term()</v> </type> <desc> - <p>Reads a (virtual) file <c>RemoteFilename</c> from a TFTP - server.</p> - <p>If <c>LocalFilename</c> is the atom <c>binary</c>, - <c>tftp_binary</c> is used as callback module. It concatenates - all transferred blocks and returns them as one single binary - in <c>LastCallbackState</c>.</p> - <p>If <c>LocalFilename</c> is a string and there are no - registered callback modules, <c>tftp_file</c> is used as - callback module. It writes each transferred block to the file - named <c>LocalFilename</c> and returns the number of - transferred bytes in <c>LastCallbackState</c>.</p> - <p>If <c>LocalFilename</c> is a string and there are registered - callback modules, <c>LocalFilename</c> is tested against - the regexps of these and the callback module corresponding to - the first match is used, or an error tuple is returned if no - matching regexp is found.</p> - </desc> + <p>Changes configuration for all TFTP server processes.</p> - <marker id="write_file"></marker> + <marker id="change_config_pid"></marker> + </desc> </func> <func> - <name>write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name> - <fsummary>Write a (virtual) file to a TFTP server</fsummary> + <name>change_config(Pid, Options) -> Result</name> + <fsummary>Changes configuration for a TFTP daemon, server, + or client process.</fsummary> <type> - <v>RemoteFilename = string()</v> - <v>LocalFilename = binary() | string()</v> + <v>Pid = pid()</v> <v>Options = [option()]</v> - <v>LastCallbackState = term()</v> + <v>Result = ok | {error, Reason}</v> <v>Reason = term()</v> </type> <desc> - <p>Writes a (virtual) file <c>RemoteFilename</c> to a TFTP - server.</p> - <p>If <c>LocalFilename</c> is a binary, <c>tftp_binary</c> is - used as callback module. The binary is transferred block by - block and the number of transferred bytes is returned in - <c>LastCallbackState</c>.</p> - <p>If <c>LocalFilename</c> is a string and there are no - registered callback modules, <c>tftp_file</c> is used as - callback module. It reads the file named <c>LocalFilename</c> - block by block and returns the number of transferred bytes - in <c>LastCallbackState</c>.</p> - <p>If <c>LocalFilename</c> is a string and there are registered - callback modules, <c>LocalFilename</c> is tested against - the regexps of these and the callback module corresponding to - the first match is used, or an error tuple is returned if no - matching regexp is found.</p> - + <p>Changes configuration for a TFTP daemon, server, or client process.</p> <marker id="info_daemons"></marker> </desc> </func> - + <func> <name>info(daemons) -> [{Pid, Options}]</name> - <fsummary>Return information about all daemons</fsummary> + <fsummary>Returns information about all daemons.</fsummary> <type> <v>Pid = [pid()()]</v> <v>Options = [option()]</v> <v>Reason = term()</v> </type> <desc> - <p>Returns info about all TFTP daemon processes. </p> + <p>Returns information about all TFTP daemon processes.</p> <marker id="info_servers"></marker> </desc> @@ -323,14 +289,14 @@ <func> <name>info(servers) -> [{Pid, Options}]</name> - <fsummary>Return information about all servers</fsummary> + <fsummary>Returns information about all servers.</fsummary> <type> <v>Pid = [pid()()]</v> <v>Options = [option()]</v> <v>Reason = term()</v> </type> <desc> - <p>Returns info about all TFTP server processes. </p> + <p>Returns information about all TFTP server processes. </p> <marker id="info_pid"></marker> </desc> @@ -338,117 +304,136 @@ <func> <name>info(Pid) -> {ok, Options} | {error, Reason}</name> - <fsummary>Return information about a daemon, server or client process</fsummary> + <fsummary>Returns information about a daemon, server, or client process.</fsummary> <type> <v>Options = [option()]</v> <v>Reason = term()</v> </type> <desc> - <p>Returns info about a TFTP daemon, server or client process.</p> - - <marker id="change_config_daemons"></marker> + <p>Returns information about a TFTP daemon, server, or client process.</p> </desc> </func> - - <func> - <name>change_config(daemons, Options) -> [{Pid, Result}]</name> - <fsummary>Changes config for all daemons - </fsummary> + + <func> + <name>read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name> + <fsummary>Reads a (virtual) file from a TFTP server.</fsummary> <type> + <v>RemoteFilename = string()</v> + <v>LocalFilename = binary | string()</v> <v>Options = [option()]</v> - <v>Pid = pid()</v> - <v>Result = ok | {error, Reason}</v> + <v>LastCallbackState = term()</v> <v>Reason = term()</v> </type> <desc> - <p>Changes config for all TFTP daemon processes. </p> - - <marker id="change_config_servers"></marker> + <p>Reads a (virtual) file <c>RemoteFilename</c> from a TFTP + server.</p> + <p>If <c>LocalFilename</c> is the atom <c>binary</c>, + <c>tftp_binary</c> is used as callback module. It concatenates + all transferred blocks and returns them as one single binary + in <c>LastCallbackState</c>.</p> + <p>If <c>LocalFilename</c> is a string and there are no + registered callback modules, <c>tftp_file</c> is used as + callback module. It writes each transferred block to the file + named <c>LocalFilename</c> and returns the number of + transferred bytes in <c>LastCallbackState</c>.</p> + <p>If <c>LocalFilename</c> is a string and there are registered + callback modules, <c>LocalFilename</c> is tested against + the regexps of these and the callback module corresponding to + the first match is used, or an error tuple is returned if no + matching regexp is found.</p> </desc> + + <marker id="write_file"></marker> </func> - + <func> - <name>change_config(servers, Options) -> [{Pid, Result}]</name> - <fsummary>Changes config for all servers - </fsummary> + <name>start(Options) -> {ok, Pid} | {error, Reason}</name> + <fsummary>Starts a daemon process.</fsummary> <type> <v>Options = [option()]</v> <v>Pid = pid()</v> - <v>Result = ok | {error, Reason}</v> <v>Reason = term()</v> </type> <desc> - <p>Changes config for all TFTP server processes. </p> + <p>Starts a daemon process listening for UDP packets on a + port. When it receives a request for read or write, it spawns + a temporary server process handling the actual transfer + of the (virtual) file.</p> - <marker id="change_config_pid"></marker> + <marker id="read_file"></marker> </desc> </func> <func> - <name>change_config(Pid, Options) -> Result</name> - <fsummary>Changes config for a TFTP daemon, server or client process</fsummary> + <name>write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name> + <fsummary>Writes a (virtual) file to a TFTP server.</fsummary> <type> - <v>Pid = pid()</v> + <v>RemoteFilename = string()</v> + <v>LocalFilename = binary() | string()</v> <v>Options = [option()]</v> - <v>Result = ok | {error, Reason}</v> - <v>Reason = term()</v> - </type> - <desc> - <p>Changes config for a TFTP daemon, server or client process</p> - - <marker id="start2"></marker> - </desc> - </func> - - <func> - <name>start() -> ok | {error, Reason}</name> - <fsummary>Start the Inets application</fsummary> - <type> + <v>LastCallbackState = term()</v> <v>Reason = term()</v> </type> <desc> - <p>Starts the Inets application.</p> + <p>Writes a (virtual) file <c>RemoteFilename</c> to a TFTP + server.</p> + <p>If <c>LocalFilename</c> is a binary, <c>tftp_binary</c> is + used as callback module. The binary is transferred block by + block and the number of transferred bytes is returned in + <c>LastCallbackState</c>.</p> + <p>If <c>LocalFilename</c> is a string and there are no + registered callback modules, <c>tftp_file</c> is used as + callback module. It reads the file named <c>LocalFilename</c> + block by block and returns the number of transferred bytes + in <c>LastCallbackState</c>.</p> + <p>If <c>LocalFilename</c> is a string and there are registered + callback modules, <c>LocalFilename</c> is tested against + the regexps of these and the callback module corresponding to + the first match is used, or an error tuple is returned if no + matching regexp is found.</p> </desc> </func> + </funcs> <section> <marker id="tftp_callback"></marker> <title>CALLBACK FUNCTIONS</title> - <p>A <c>tftp</c> callback module should be implemented as a - <c>tftp</c> behavior and export the functions listed below.</p> - <p>On the server side the callback interaction starts with a call to + <p>A <c>tftp</c> callback module is to be implemented as a + <c>tftp</c> behavior and export the functions listed + in the following.</p> + <p>On the server side, the callback interaction starts with a call to <c>open/5</c> with the registered initial callback state. <c>open/5</c> is expected to open the (virtual) file. Then either - the <c>read/1</c> or <c>write/2</c> functions are invoked - repeatedly, once per transferred block. At each function call + function <c>read/1</c> or <c>write/2</c> is invoked + repeatedly, once per transferred block. At each function call, the state returned from the previous call is obtained. When - the last block has been encountered the <c>read/1</c> or - <c>write/2</c> functions is expected to close the (virtual) file - and return its last state. The <c>abort/3</c> function is only - used in error situations. <c>prepare/5</c> is not used on + the last block is encountered, function <c>read/1</c> or + <c>write/2</c> is expected to close the (virtual) file + and return its last state. Function <c>abort/3</c> is only + used in error situations. Function <c>prepare/5</c> is not used on the server side.</p> - <p>On the client side the callback interaction is the same, but it + <p>On the client side, the callback interaction is the same, but it starts and ends a bit differently. It starts with a call to <c>prepare/5</c> with the same arguments as <c>open/5</c> takes. - <c>prepare/5</c> is expected to validate the TFTP options, - suggested by the user and return the subset of them that it - accepts. Then the options is sent to the server which will perform + <c>prepare/5</c> is expected to validate the TFTP options + suggested by the user and to return the subset of them that it + accepts. Then the options are sent to the server, which performs the same TFTP option negotiation procedure. The options that are - accepted by the server are forwarded to the <c>open/5</c> function - on the client side. On the client side the <c>open/5</c> function - must accept all option as is or reject the transfer. Then + accepted by the server are forwarded to function <c>open/5</c> + on the client side. On the client side, function <c>open/5</c> + must accept all option as-is or reject the transfer. Then the callback interaction follows the same pattern as described - above for the server side. When the last block is encountered in - <c>read/1</c> or <c>write/2</c> the returned state is forwarded to + for the server side. When the last block is encountered in + <c>read/1</c> or <c>write/2</c>, the returned state is forwarded to the user and returned from <c>read_file</c>/3 or <c>write_file/3</c>.</p> - <p> If a callback (which performs the file access + <p> If a callback (performing the file access in the TFTP server) takes too long time (more than - the double TFTP timeout), the server will abort the - connection and send an error reply to the client. - This implies that the server will release resources + the double TFTP time-out), the server aborts the + connection and sends an error reply to the client. + This implies that the server releases resources attached to the connection faster than before. The server simply assumes that the client has given up.</p> @@ -456,21 +441,45 @@ <p>If the TFTP server receives yet another request from the same client (same host and port) while it already has an active connection to the client, it - will simply ignore the new request if the request is - equal with the first one (same filename and options). + ignores the new request if the request is + equal to the first one (same filename and options). This implies that the (new) client will be served by the already ongoing connection on the server side. By not setting up yet another connection, in - parallel with the ongoing one, the server will - consumer lesser resources. </p> + parallel with the ongoing one, the server + consumes less resources.</p> <marker id="prepare"></marker> </section> <funcs> - <func> - <name>prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name> - <fsummary>Prepare to open a file on the client side</fsummary> + <func> + <name>Module:abort(Code, Text, State) -> ok</name> + <fsummary>Aborts the file transfer.</fsummary> + <type> + <v>Code = undef | enoent | eacces | enospc</v> + <v> | badop | eexist | baduser | badopt</v> + <v> | int()</v> + <v>Text = string()</v> + <v>State = term()</v> + </type> + <desc> + <p>Invoked when the file transfer is aborted.</p> + <p>The callback function is expected to clean + up its used resources after the aborted file + transfer, such as closing open file + descriptors and so on. The function is not + invoked if any of the other callback + functions returns an error, as it is + expected that they already have cleaned up + the necessary resources. However, it is + invoked if the functions fail (crash).</p> + </desc> + </func> + + <func> + <name>Module:open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name> + <fsummary>Opens a file for read or write access.</fsummary> <type> <v>Peer = {PeerType, PeerHost, PeerPort}</v> <v>PeerType = inet | inet6</v> @@ -481,7 +490,8 @@ <v>Mode = string()</v> <v>SuggestedOptions = AcceptedOptions = [{Key, Value}]</v> <v> Key = Value = string()</v> - <v>InitialState = [] | [{root_dir, string()}]</v> + <v>State = InitialState | term()</v> + <v> InitialState = [] | [{root_dir, string()}]</v> <v>NewState = term()</v> <v>Code = undef | enoent | eacces | enospc</v> <v> | badop | eexist | baduser | badopt</v> @@ -489,23 +499,22 @@ <v>Text = string()</v> </type> <desc> - <p>Prepares to open a file on the client side.</p> - <p>No new options may be added, but the ones that are present in - <c>SuggestedOptions</c> may be omitted or replaced with new - values in <c>AcceptedOptions</c>.</p> - <p>Will be followed by a call to <c>open/4</c> before any - read/write access is performed. <c>AcceptedOptions</c> is - sent to the server which replies with those options that it - accepts. These will be forwarded to <c>open/4</c> as - <c>SuggestedOptions</c>.</p> + <p>Opens a file for read or write access.</p> + <p>On the client side, where the <c>open/5</c> call has been + preceded by a call to <c>prepare/5</c>, all options must be + accepted or rejected.</p> + <p>On the server side, where there is no preceding + <c>prepare/5</c> call, no new options can be added, but + those present in <c>SuggestedOptions</c> can be + omitted or replaced with new values in <c>AcceptedOptions</c>.</p> - <marker id="open"></marker> + <marker id="read"></marker> </desc> </func> - + <func> - <name>open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name> - <fsummary>Open a file for read or write access</fsummary> + <name>Module:prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name> + <fsummary>Prepares to open a file on the client side.</fsummary> <type> <v>Peer = {PeerType, PeerHost, PeerPort}</v> <v>PeerType = inet | inet6</v> @@ -516,8 +525,7 @@ <v>Mode = string()</v> <v>SuggestedOptions = AcceptedOptions = [{Key, Value}]</v> <v> Key = Value = string()</v> - <v>State = InitialState | term()</v> - <v> InitialState = [] | [{root_dir, string()}]</v> + <v>InitialState = [] | [{root_dir, string()}]</v> <v>NewState = term()</v> <v>Code = undef | enoent | eacces | enospc</v> <v> | badop | eexist | baduser | badopt</v> @@ -525,22 +533,23 @@ <v>Text = string()</v> </type> <desc> - <p>Opens a file for read or write access.</p> - <p>On the client side where the <c>open/5</c> call has been - preceded by a call to <c>prepare/5</c>, all options must be - accepted or rejected.</p> - <p>On the server side, where there is no preceding - <c>prepare/5</c> call, no new options may be added, but - the ones that are present in <c>SuggestedOptions</c> may be - omitted or replaced with new values in <c>AcceptedOptions</c>.</p> + <p>Prepares to open a file on the client side.</p> + <p>No new options can be added, but those present in + <c>SuggestedOptions</c> can be omitted or replaced with new + values in <c>AcceptedOptions</c>.</p> + <p>This is followed by a call to <c>open/4</c> before any + read/write access is performed. <c>AcceptedOptions</c> is + sent to the server, which replies with the options that it + accepts. These are then forwarded to <c>open/4</c> as + <c>SuggestedOptions</c>.</p> - <marker id="read"></marker> + <marker id="open"></marker> </desc> </func> <func> - <name>read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}</name> - <fsummary>Read a chunk from the file</fsummary> + <name>Module:read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}</name> + <fsummary>Reads a chunk from the file.</fsummary> <type> <v>State = NewState = term()</v> <v>Bin = binary()</v> @@ -551,13 +560,13 @@ <v>Text = string()</v> </type> <desc> - <p>Read a chunk from the file.</p> + <p>Reads a chunk from the file.</p> <p>The callback function is expected to close the file when the last file chunk is - encountered. When an error is encountered + encountered. When an error is encountered, the callback function is expected to clean up after the aborted file transfer, such as - closing open file descriptors etc. In both + closing open file descriptors, and so on. In both cases there will be no more calls to any of the callback functions.</p> @@ -566,8 +575,8 @@ </func> <func> - <name>write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}}</name> - <fsummary>Write a chunk to the file</fsummary> + <name>Module:write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}}</name> + <fsummary>Writes a chunk to the file.</fsummary> <type> <v>Bin = binary()</v> <v>State = NewState = term()</v> @@ -578,99 +587,75 @@ <v>Text = string()</v> </type> <desc> - <p>Write a chunk to the file.</p> + <p>Writes a chunk to the file.</p> <p>The callback function is expected to close the file when the last file chunk is - encountered. When an error is encountered + encountered. When an error is encountered, the callback function is expected to clean up after the aborted file transfer, such as - closing open file descriptors etc. In both + closing open file descriptors, and so on. In both cases there will be no more calls to any of the callback functions.</p> <marker id="abort"></marker> </desc> </func> - - <func> - <name>abort(Code, Text, State) -> ok</name> - <fsummary>Abort the file transfer</fsummary> - <type> - <v>Code = undef | enoent | eacces | enospc</v> - <v> | badop | eexist | baduser | badopt</v> - <v> | int()</v> - <v>Text = string()</v> - <v>State = term()</v> - </type> - <desc> - <p>Invoked when the file transfer is aborted.</p> - <p>The callback function is expected to clean - up its used resources after the aborted file - transfer, such as closing open file - descriptors etc. The function will not be - invoked if any of the other callback - functions returns an error, as it is - expected that they already have cleaned up - the necessary resources. It will however be - invoked if the functions fails (crashes).</p> - </desc> - </func> </funcs> <section> <marker id="tftp_logger"></marker> <title>LOGGER FUNCTIONS</title> - <p>A <c>tftp_logger</c> callback module should be implemented as a - <c>tftp_logger</c> behavior and export the functions listed below.</p> + <p>A <c>tftp_logger</c> callback module is to be implemented as a + <c>tftp_logger</c> behavior and export the following functions:</p> <marker id="error_msg"></marker> </section> <funcs> <func> - <name>error_msg(Format, Data) -> ok | exit(Reason)</name> - <fsummary>Log an error message</fsummary> + <name>Logger:error_msg(Format, Data) -> ok | exit(Reason)</name> + <fsummary>Logs an error message.</fsummary> <type> <v>Format = string()</v> <v>Data = [term()]</v> <v>Reason = term()</v> </type> <desc> - <p>Log an error message. - See <c>error_logger:error_msg/2 for details.</c> </p> + <p>Logs an error message. + See <c>error_logger:error_msg/2</c> for details.</p> <marker id="warning_msg"></marker> </desc> </func> <func> - <name>warning_msg(Format, Data) -> ok | exit(Reason)</name> - <fsummary>Log an error message</fsummary> + <name>Logger:info_msg(Format, Data) -> ok | exit(Reason)</name> + <fsummary>Logs an info message.</fsummary> <type> <v>Format = string()</v> <v>Data = [term()]</v> <v>Reason = term()</v> </type> <desc> - <p>Log a warning message. - See <c>error_logger:warning_msg/2 for details.</c> </p> - - <marker id="info_msg"></marker> + <p>Logs an info message. + See <c>error_logger:info_msg/2</c> for details.</p> </desc> </func> - + <func> - <name>info_msg(Format, Data) -> ok | exit(Reason)</name> - <fsummary>Log an error message</fsummary> + <name>Logger:warning_msg(Format, Data) -> ok | exit(Reason)</name> + <fsummary>Logs a warning message.</fsummary> <type> <v>Format = string()</v> <v>Data = [term()]</v> <v>Reason = term()</v> </type> <desc> - <p>Log an info message. - See <c>error_logger:info_msg/2 for details.</c> </p> + <p>Logs a warning message. + See <c>error_logger:warning_msg/2</c> for details.</p> + + <marker id="info_msg"></marker> </desc> </func> </funcs> diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 205348524a..6e6cc38c06 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1817,13 +1817,13 @@ host_header(_, URI) -> tls_upgrade(#state{status = {ssl_tunnel, #request{settings = - #http_options{ssl = {_, TLSOptions} = SocketType}} = Request}, + #http_options{ssl = {_, TLSOptions} = SocketType}, + address = Address} = Request}, session = #session{socket = TCPSocket} = Session0, options = Options} = State) -> case ssl:connect(TCPSocket, TLSOptions) of {ok, TLSSocket} -> - Address = Request#request.address, ClientClose = httpc_request:is_client_closing(Request#request.headers), SessionType = httpc_manager:session_type(Options), Session = Session0#session{ @@ -1844,7 +1844,11 @@ tls_upgrade(#state{status = status = new }, {noreply, activate_request_timeout(NewState)}; - {error, _Reason} -> + {error, Reason} -> + Error = httpc_response:error(Request, {failed_connect, + [{to_address, Address}, + {tls, TLSOptions, Reason}]}), + maybe_send_answer(Request, Error, State), {stop, normal, State#state{request = Request}} end. diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl index 10af1949a4..4bf2ba2b9b 100644 --- a/lib/inets/src/http_client/httpc_response.erl +++ b/lib/inets/src/http_client/httpc_response.erl @@ -328,7 +328,7 @@ status_service_unavailable(Response = {_, Headers, _}, Request) -> undefined -> status_server_error_50x(Response, Request); Time when (length(Time) < 3) -> % Wait only 99 s or less - NewTime = list_to_integer(Time) * 100, % time in ms + NewTime = list_to_integer(Time) * 1000, % time in ms {_, Data} = format_response(Response), {retry, {NewTime, Request}, Data}; _ -> diff --git a/lib/inets/src/http_lib/http_response.erl b/lib/inets/src/http_lib/http_response.erl index 58b30c4e9e..d13670700c 100644 --- a/lib/inets/src/http_lib/http_response.erl +++ b/lib/inets/src/http_lib/http_response.erl @@ -31,16 +31,11 @@ %% Value - string() %% %% Description: Creates a http_response_h-record used internally to -%% handle http-headers. +%% handle http-headers, assumes reversed list of headers +%% to unfold multiline headers with obs-folds %%------------------------------------------------------------------------- -headers([], Headers) -> - Headers; - -headers([Header | Tail], Headers) -> - {Key, [$: | Value]} = - lists:splitwith(fun($:) -> false; (_) -> true end, Header), - headers(Tail, headers(http_util:to_lower(string:strip(Key)), - string:strip(Value), Headers)). +headers(RevLines, Headers) -> + fill_headers(RevLines, [], Headers). %%------------------------------------------------------------------------- %% headers(#http_response_h{}) -> HeaderList @@ -68,6 +63,23 @@ header_list(Headers) -> %%%======================================================================== %%% Internal functions %%%======================================================================== +fill_headers([], _, Headers) -> + Headers; +fill_headers([[Ch|HeaderFold]|Tail], Folded, Headers) + when Ch == $\t; Ch == $\s -> + fill_headers(Tail, [HeaderFold|Folded], Headers); +fill_headers([Header | Tail], Folded, Headers) -> + Unfolded = unfold([Header|Folded]), + {Key, [$: | Value]} = + lists:splitwith(fun($:) -> false; (_) -> true end, Unfolded), + fill_headers(Tail, [], headers(http_util:to_lower(string:strip(Key)), + string:strip(Value), Headers)). + +unfold([L]) -> + L; +unfold(Folded) -> + string:join(Folded, " "). + headers("cache-control", Value, Headers) -> Headers#http_response_h{'cache-control'= Value}; headers("connection", Value, Headers) -> diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index bbe3ec9e4c..719dc4c425 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -269,7 +269,7 @@ get_socket_info(Addr, Port, Fd) -> undefined -> {Port, sock_opts(Addr, BaseOpts)}; Fd -> - {0, sock_opts(Addr, [{fd, Fd} | BaseOpts])} + {0, sock_opts([{fd, Fd} | BaseOpts])} end. %%------------------------------------------------------------------------- diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl index 79591eec29..6fe8c1776d 100644 --- a/lib/inets/src/http_lib/http_uri.erl +++ b/lib/inets/src/http_lib/http_uri.erl @@ -138,16 +138,33 @@ parse_scheme(AbsURI, Opts) -> {error, no_scheme} -> {error, no_scheme}; {SchemeStr, Rest} -> - Scheme = list_to_atom(http_util:to_lower(SchemeStr)), - SchemeDefaults = which_scheme_defaults(Opts), - case lists:keysearch(Scheme, 1, SchemeDefaults) of - {value, {Scheme, DefaultPort}} -> - {Scheme, DefaultPort, Rest}; - false -> - {Scheme, no_default_port, Rest} + case extract_scheme(SchemeStr, Opts) of + {error, Error} -> + {error, Error}; + {ok, Scheme} -> + SchemeDefaults = which_scheme_defaults(Opts), + case lists:keysearch(Scheme, 1, SchemeDefaults) of + {value, {Scheme, DefaultPort}} -> + {Scheme, DefaultPort, Rest}; + false -> + {Scheme, no_default_port, Rest} + end end end. +extract_scheme(Str, Opts) -> + case lists:keysearch(scheme_validation_fun, 1, Opts) of + {value, {scheme_validation_fun, Fun}} when is_function(Fun) -> + case Fun(Str) of + valid -> + {ok, list_to_atom(http_util:to_lower(Str))}; + {error, Error} -> + {error, Error} + end; + _ -> + {ok, list_to_atom(http_util:to_lower(Str))} + end. + parse_uri_rest(Scheme, DefaultPort, "//" ++ URIPart, Opts) -> {Authority, PathQueryFragment} = split_uri(URIPart, "[/?#]", {URIPart, ""}, 1, 0), diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile index b09877550d..b9f2290289 100644 --- a/lib/inets/src/http_server/Makefile +++ b/lib/inets/src/http_server/Makefile @@ -40,6 +40,10 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # ---------------------------------------------------- # Target Specs # ---------------------------------------------------- + +BEHAVIOUR_MODULES= \ + httpd_custom_api + MODULES = \ httpd \ httpd_acceptor \ @@ -86,10 +90,13 @@ MODULES = \ HRL_FILES = httpd.hrl httpd_internal.hrl mod_auth.hrl -ERL_FILES = $(MODULES:%=%.erl) +ERL_FILES = $(MODULES:%=%.erl)\ + $(BEHAVIOUR_MODULES:%=%.erl) TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) +BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR)) + INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"' @@ -109,11 +116,12 @@ ERL_COMPILE_FLAGS += \ # ---------------------------------------------------- # Targets # ---------------------------------------------------- +$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES) debug opt: $(TARGET_FILES) clean: - rm -f $(TARGET_FILES) + rm -f $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES) rm -f core docs: diff --git a/lib/inets/src/http_server/httpd_custom.erl b/lib/inets/src/http_server/httpd_custom.erl index a1fe058bd1..2b9701ef75 100644 --- a/lib/inets/src/http_server/httpd_custom.erl +++ b/lib/inets/src/http_server/httpd_custom.erl @@ -20,16 +20,27 @@ %% -module(httpd_custom). --export([response_header/1, request_header/1]). --export([customize_headers/3]). +-export([response_header/1, request_header/1, response_default_headers/0]). +-export([customize_headers/3, response_default_headers/1]). --include_lib("inets/src/inets_app/inets_internal.hrl"). +-include("../inets_app/inets_internal.hrl"). + +-behaviour(httpd_custom_api). + +%%-------------------------------------------------------------------- +%% Behavior API ----------------------------------- +%%-------------------------------------------------------------------- response_header(Header) -> {true, httpify(Header)}. request_header(Header) -> {true, Header}. +response_default_headers() -> + []. +%%-------------------------------------------------------------------- +%% Internal API ----------------------------------- +%%-------------------------------------------------------------------- customize_headers(?MODULE, Function, Arg) -> ?MODULE:Function(Arg); customize_headers(Module, Function, Arg) -> @@ -43,6 +54,20 @@ customize_headers(Module, Function, Arg) -> ?MODULE:Function(Arg) end. +response_default_headers(?MODULE) -> + response_default_headers(); +response_default_headers(Module) -> + try Module:response_default_headers() of + Defaults -> + [{http_util:to_lower(Key), Value} || {Key, Value} <- Defaults, + is_list(Key), is_list(Value)] + catch + _:_ -> + ?MODULE:response_default_headers() + end. +%%-------------------------------------------------------------------- +%% Internal functions ----------------------------------- +%%-------------------------------------------------------------------- httpify({Key0, Value}) -> %% make sure first letter is capital (defacto standard) Words1 = string:tokens(Key0, "-"), diff --git a/lib/webtool/src/webtool.app.src b/lib/inets/src/http_server/httpd_custom_api.erl index 6b9750c2b4..282f3a6ee6 100644 --- a/lib/webtool/src/webtool.app.src +++ b/lib/inets/src/http_server/httpd_custom_api.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2015-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -17,12 +17,15 @@ %% %% %CopyrightEnd% %% -{application,webtool, - [{description,"Toolbar lookalike for the web"}, - {vsn,"%VSN%"}, - {modules,[webtool,webtool_sup]}, - {registered,[web_tool,websup]}, - {applications,[kernel,stdlib]}, - {runtime_dependencies, ["stdlib-2.0","observer-2.0","kernel-3.0", - "inets-5.10","erts-6.0"]}]}. - +%% +-module(httpd_custom_api). + +-callback response_default_headers() -> + [{Key::string(), Value::string()}]. +-callback response_header({Key::string(), Value::string()}) -> + {true, {Key::string(), Value::string()}} | false. +-callback request_header({Key::string(), Value::string()}) -> + {true, {Key::string(), Value::string()}} | false. + +-optional_callbacks([response_default_headers/0, response_header/1, + request_header/1]). diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl index 25aea56568..e5d006c1fd 100644 --- a/lib/inets/src/http_server/httpd_request_handler.erl +++ b/lib/inets/src/http_server/httpd_request_handler.erl @@ -30,7 +30,7 @@ %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). + terminate/2, code_change/3, format_status/2]). -include("httpd.hrl"). -include("http_internal.hrl"). @@ -310,6 +310,18 @@ do_terminate(#state{mod = ModData} = State) -> cancel_request_timeout(State), httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket). +format_status(normal, [_, State]) -> + [{data, [{"StateData", State}]}]; +format_status(terminate, [_, State]) -> + Mod = (State#state.mod), + case Mod#mod.socket_type of + ip_comm -> + [{data, [{"StateData", State}]}]; + {essl, _} -> + %% Do not print ssl options in superviosr reports + [{data, [{"StateData", + State#state{mod = Mod#mod{socket_type = 'TLS'}}}]}] + end. %%-------------------------------------------------------------------- %% code_change(OldVsn, State, Extra) -> {ok, NewState} diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl index 7e73da7060..71243f525a 100644 --- a/lib/inets/src/http_server/httpd_response.erl +++ b/lib/inets/src/http_server/httpd_response.erl @@ -287,14 +287,21 @@ create_header(ConfigDb, KeyValueTupleHeaders) -> Date = httpd_util:rfc1123_date(), ContentType = "text/html", Server = server(ConfigDb), - Headers0 = add_default_headers([{"date", Date}, - {"content-type", ContentType} - | if Server=="" -> []; - true -> [{"server", Server}] - end - ], - KeyValueTupleHeaders), CustomizeCB = httpd_util:lookup(ConfigDb, customize, httpd_custom), + + CustomDefaults = httpd_custom:response_default_headers(CustomizeCB), + SystemDefaultes = ([{"date", Date}, + {"content-type", ContentType} + | if Server=="" -> []; + true -> [{"server", Server}] + end + ]), + + %% System defaults not present in custom defaults will be added + %% to defaults + Defaults = add_default_headers(SystemDefaultes, CustomDefaults), + + Headers0 = add_default_headers(Defaults, KeyValueTupleHeaders), lists:filtermap(fun(H) -> httpd_custom:customize_headers(CustomizeCB, response_header, H) end, diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl index de08624d44..f0b1942e2f 100644 --- a/lib/inets/src/http_server/httpd_sup.erl +++ b/lib/inets/src/http_server/httpd_sup.erl @@ -185,12 +185,16 @@ httpd_child_spec(ConfigFile, AcceptTimeoutDef, DebugDef) -> end. httpd_child_spec(Config, AcceptTimeout, Debug, Addr, Port, Profile) -> - Fd = proplists:get_value(fd, Config, undefined), - case Port == 0 orelse Fd =/= undefined of - true -> - httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port, Profile); - false -> - httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port, Profile) + case get_fd(Port) of + {ok, Fd} -> + case Port == 0 orelse Fd =/= undefined of + true -> + httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port, Profile); + false -> + httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port, Profile) + end; + Error -> + Error end. httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port, Profile) -> @@ -236,7 +240,7 @@ listen(Address, Port, Config) -> SocketType -> case http_transport:start(SocketType) of ok -> - Fd = proplists:get_value(fd, Config), + {ok, Fd} = get_fd(Port), IpFamily = proplists:get_value(ipfamily, Config, inet6fb4), case http_transport:listen(SocketType, Address, Port, Fd, IpFamily) of {ok, ListenSocket} -> @@ -355,3 +359,19 @@ ssl_ca_certificate_file(Config) -> File -> [{cacertfile, File}] end. + +get_fd(0) -> + {ok, undefined}; +get_fd(Port) -> + FdKey = list_to_atom("httpd_" ++ integer_to_list(Port)), + case init:get_argument(FdKey) of + {ok, [[Value]]} -> + case (catch list_to_integer(Value)) of + N when is_integer(N) -> + {ok, N}; + _ -> + {error, {bad_descriptor, Value}} + end; + _ -> + {ok, undefined} + end. diff --git a/lib/inets/src/http_server/mod_auth_server.erl b/lib/inets/src/http_server/mod_auth_server.erl index 3685c2e617..7d1e1a3431 100644 --- a/lib/inets/src/http_server/mod_auth_server.erl +++ b/lib/inets/src/http_server/mod_auth_server.erl @@ -316,7 +316,7 @@ lookup(Db, Key) -> make_name(Addr, Port, Profile) -> - httpd_util:make_name(?MODULE, Addr, Port, Profile). + httpd_util:make_name(?MODULE_STRING, Addr, Port, Profile). call(Name, Req) -> diff --git a/lib/inets/src/http_server/mod_security_server.erl b/lib/inets/src/http_server/mod_security_server.erl index 81561493a0..f9281b0fdc 100644 --- a/lib/inets/src/http_server/mod_security_server.erl +++ b/lib/inets/src/http_server/mod_security_server.erl @@ -523,10 +523,10 @@ unblock_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS, CBModule) -> ets:match_delete(ETS, {blocked_user, {User, Addr, Port, Profile, Dir, '_'}}). make_name(Addr,Port, Profile) -> - httpd_util:make_name(?MODULE,Addr,Port, Profile). + httpd_util:make_name(?MODULE_STRING, Addr, Port, Profile). make_name(Addr,Port, Profile, Num) -> - httpd_util:make_name(?MODULE,Addr,Port, + httpd_util:make_name(?MODULE_STRING, Addr,Port, atom_to_list(Profile) ++ "__" ++ integer_to_list(Num)). auth_fail_event(Mod,Addr,Port,Dir,User,Passwd) -> diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index d3da76d789..a9fbb1c3f7 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -18,9 +18,11 @@ %% %CopyrightEnd% {"%VSN%", [ + {<<"6\\..*">>,[{restart_application, inets}]}, {<<"5\\..*">>,[{restart_application, inets}]} ], [ + {<<"6\\..*">>,[{restart_application, inets}]}, {<<"5\\..*">>,[{restart_application, inets}]} ] }. diff --git a/lib/inets/src/tftp/tftp_engine.erl b/lib/inets/src/tftp/tftp_engine.erl index fa44cd61ce..282a97e720 100644 --- a/lib/inets/src/tftp/tftp_engine.erl +++ b/lib/inets/src/tftp/tftp_engine.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -63,7 +63,8 @@ -record(file_info, {peer_req, pid}). -record(sys_misc, {module, function, arguments}). -record(error, {where, code, text, filename}). --record(prepared, {status :: prep_status(), result, block_no, next_data, prev_data}). +-record(prepared, {status :: prep_status() | 'undefined', + result, block_no, next_data, prev_data}). -record(transfer_res, {status, decoded_msg, prepared}). -define(ERROR(Where, Code, Text, Filename), #error{where = Where, code = Code, text = Text, filename = Filename}). @@ -128,8 +129,8 @@ daemon_start(Options) when is_list(Options) -> daemon_init(Config) when is_record(Config, config), is_pid(Config#config.parent_pid) -> process_flag(trap_exit, true), - UdpOptions = prepare_daemon_udp(Config), - case catch gen_udp:open(Config#config.udp_port, UdpOptions) of + {Port, UdpOptions} = prepare_daemon_udp(Config), + case catch gen_udp:open(Port, UdpOptions) of {ok, Socket} -> {ok, ActualPort} = inet:port(Socket), proc_lib:init_ack({ok, self()}), @@ -157,7 +158,7 @@ prepare_daemon_udp(#config{udp_port = Port, udp_options = UdpOptions} = Config) case lists:keymember(fd, 1, UdpOptions) of true -> %% Use explicit fd - UdpOptions; + {Port, UdpOptions}; false -> %% Use fd from setuid_socket_wrap, such as -tftpd_69 InitArg = list_to_atom("tftpd_" ++ integer_to_list(Port)), @@ -165,7 +166,7 @@ prepare_daemon_udp(#config{udp_port = Port, udp_options = UdpOptions} = Config) {ok, [[FdStr]] = Badarg} when is_list(FdStr) -> case catch list_to_integer(FdStr) of Fd when is_integer(Fd) -> - [{fd, Fd} | UdpOptions]; + {0, [{fd, Fd} | lists:keydelete(ip, 1, UdpOptions)]}; {'EXIT', _} -> Text = lists:flatten(io_lib:format("Illegal prebound fd ~p: ~p", [InitArg, Badarg])), print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")), @@ -176,7 +177,7 @@ prepare_daemon_udp(#config{udp_port = Port, udp_options = UdpOptions} = Config) print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")), exit({badarg, {prebound_fd, InitArg, Badarg}}); error -> - UdpOptions + {Port, UdpOptions} end end. diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile index cae77a05f3..607ec7c182 100644 --- a/lib/inets/test/Makefile +++ b/lib/inets/test/Makefile @@ -174,7 +174,8 @@ MODULES = \ inets_appup_test \ tftp_test_lib \ tftp_SUITE \ - uri_SUITE + uri_SUITE \ + inets_socketwrap_SUITE EBIN = . @@ -203,7 +204,7 @@ INETS_FILES = inets.config $(INETS_SPECS) # inets_ftp_suite \ # inets_tftp_suite -INETS_DATADIRS = inets_SUITE_data inets_sup_SUITE_data +INETS_DATADIRS = inets_SUITE_data inets_socketwrap_SUITE_data HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data httpd_basic_SUITE_data old_httpd_SUITE_data HTTPC_DATADIRS = httpc_SUITE_data httpc_proxy_SUITE_data FTP_DATADIRS = ftp_SUITE_data @@ -250,7 +251,7 @@ ERL_COMPILE_FLAGS += \ # 1) INETS_PRIV_DIR must be created # ---------------------------------------------------- -tests debug opt: $(BUILDTARGET) +tests debug opt: $(BUILDTARGET) targets: $(TARGET_FILES) diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 5b40d08859..2ad00bdf76 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -105,6 +105,7 @@ only_simulated() -> internal_server_error, invalid_http, headers_dummy, + headers_with_obs_fold, empty_response_header, remote_socket_close, remote_socket_close_async, @@ -893,6 +894,13 @@ headers_dummy(Config) when is_list(Config) -> %%------------------------------------------------------------------------- +headers_with_obs_fold(Config) when is_list(Config) -> + Request = {url(group_name(Config), "/obs_folded_headers.html", Config), []}, + {ok, {{_,200,_}, Headers, [_|_]}} = httpc:request(get, Request, [], []), + "a b" = proplists:get_value("folded", Headers). + +%%------------------------------------------------------------------------- + invalid_headers(Config) -> Request = {url(group_name(Config), "/dummy.html", Config), [{"cookie", undefined}]}, {error, _} = httpc:request(get, Request, [], []). @@ -1713,6 +1721,13 @@ handle_uri(_,"/dummy_headers.html",_,_,Socket,_) -> send(Socket, http_chunk:encode("obar</BODY></HTML>")), http_chunk:encode_last(); +handle_uri(_,"/obs_folded_headers.html",_,_,_,_) -> + "HTTP/1.1 200 ok\r\n" + "Content-Length:5\r\n" + "Folded: a\r\n" + " b\r\n\r\n" + "Hello"; + handle_uri(_,"/capital_transfer_encoding.html",_,_,Socket,_) -> Head = "HTTP/1.1 200 ok\r\n" ++ "Transfer-Encoding:Chunked\r\n\r\n", diff --git a/lib/inets/test/httpc_proxy_SUITE.erl b/lib/inets/test/httpc_proxy_SUITE.erl index 786de1bc42..6d7af4ea5d 100644 --- a/lib/inets/test/httpc_proxy_SUITE.erl +++ b/lib/inets/test/httpc_proxy_SUITE.erl @@ -58,7 +58,7 @@ groups() -> [http_emulate_lower_versions |local_proxy_cases()]}, {local_proxy_https,[], - local_proxy_cases()}]. + local_proxy_cases() ++ local_proxy_https_cases()}]. %% internal functions @@ -77,6 +77,9 @@ local_proxy_cases() -> http_stream, http_not_modified_otp_6821]. +local_proxy_https_cases() -> + [https_connect_error]. + %%-------------------------------------------------------------------- init_per_suite(Config0) -> @@ -432,6 +435,21 @@ header_value(Name, [{HeaderName,HeaderValue}|Headers]) -> end. %%-------------------------------------------------------------------- +https_connect_error(doc) -> + ["Error from CONNECT tunnel should be returned"]; +https_connect_error(Config) when is_list(Config) -> + {HttpServer,HttpPort} = ?config(http, Config), + Method = get, + %% using HTTPS scheme with HTTP port to trigger connection error + URL = "https://" ++ HttpServer ++ ":" ++ + integer_to_list(HttpPort) ++ "/index.html", + Opts = [], + HttpOpts = [], + Request = {URL,[]}, + {error,{failed_connect,[_,{tls,_,_}]}} = + httpc:request(Method, Request, HttpOpts, Opts). + +%%-------------------------------------------------------------------- %% Internal Functions ------------------------------------------------ %%-------------------------------------------------------------------- diff --git a/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh b/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh index 9d1698c386..473024ae63 100755 --- a/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh +++ b/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh @@ -169,6 +169,8 @@ MaxRequestsPerChild 0 ViaProxyName "tinyproxy" ConnectPort $APACHE_HTTPS_PORT +# to test connect error +ConnectPort $APACHE_HTTP_PORT EOF (tinyproxy -d -c tinyproxy.conf 1>/dev/null 2>&1 </dev/null &)& wait_for_pidfile tinyproxy.pid diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index a6236f828a..b50d31a5c1 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -97,7 +97,7 @@ groups() -> {https_reload, [], [{group, reload}]}, {http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]}, {limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]}, - {custom, [], [customize]}, + {custom, [], [customize, add_default]}, {reload, [], [non_disturbing_reconfiger_dies, disturbing_reconfiger_dies, non_disturbing_1_1, @@ -1003,10 +1003,23 @@ customize(Config) when is_list(Config) -> {no_header, "Server"}, {version, Version}]). -response_header({"server", _}) -> - false; -response_header(Header) -> - {true, Header}. +add_default() -> + [{doc, "Test adding default header with custom callback"}]. + +add_default(Config) when is_list(Config) -> + Version = "HTTP/1.1", + Host = ?config(host, Config), + Type = ?config(type, Config), + ok = httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), + transport_opts(Type, Config), + ?config(node, Config), + http_request("GET /index.html ", Version, Host), + [{statuscode, 200}, + {header, "Content-Type", "text/html"}, + {header, "Date", "Override-date"}, + {header, "X-Frame-Options"}, + {version, Version}]). %%------------------------------------------------------------------------- max_header() -> @@ -1425,9 +1438,9 @@ server_config(http_limit, Config) -> %% Make sure option checking code is run {max_content_length, 100000002}] ++ server_config(http, Config); server_config(http_custom, Config) -> - [{custom, ?MODULE}] ++ server_config(http, Config); + [{customize, ?MODULE}] ++ server_config(http, Config); server_config(https_custom, Config) -> - [{custom, ?MODULE}] ++ server_config(https, Config); + [{customize, ?MODULE}] ++ server_config(https, Config); server_config(https_limit, Config) -> [{max_clients, 1}] ++ server_config(https, Config); server_config(http_basic_auth, Config) -> @@ -2030,3 +2043,14 @@ typestr(ip_comm) -> "tcp"; typestr(_) -> "ssl". + +response_header({"server", _}) -> + false; +response_header(Header) -> + {true, Header}. + +response_default_headers() -> + [%% Add new header + {"X-Frame-Options", "SAMEORIGIN"}, + %% Override built-in default + {"Date", "Override-date"}]. diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl index cb2e86c81e..a5b836f651 100644 --- a/lib/inets/test/httpd_test_lib.erl +++ b/lib/inets/test/httpd_test_lib.erl @@ -294,9 +294,9 @@ do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) -> {value, {LowerHeaderField, Value}} -> ok; false -> - ct:fail({wrong_header_field_value, LowerHeaderField, Header}); + ct:fail({wrong_header_field_value, LowerHeaderField, Header, Value}); _ -> - ct:fail({wrong_header_field_value, LowerHeaderField, Header}) + ct:fail({wrong_header_field_value, LowerHeaderField, Header, Value}) end, do_validate(Header, Rest, N, P); do_validate(Header,[{no_header, HeaderField}|Rest],N,P) -> diff --git a/lib/inets/test/inets_SUITE.erl b/lib/inets/test/inets_SUITE.erl index c3586f09e3..928d9dc391 100644 --- a/lib/inets/test/inets_SUITE.erl +++ b/lib/inets/test/inets_SUITE.erl @@ -21,7 +21,6 @@ -module(inets_SUITE). -include_lib("common_test/include/ct.hrl"). --include("test_server_line.hrl"). -include("inets_test_lib.hrl"). %% Note: This directive should only be used in test suites. @@ -37,8 +36,12 @@ all() -> groups() -> [{services_test, [], - [start_inets, start_httpc, start_httpd, start_ftpc, - start_tftpd]}, + [start_inets, + start_httpc, + start_httpd, + start_ftpc, + start_tftpd + ]}, {app_test, [], [{inets_app_test, all}]}, {appup_test, [], [{inets_appup_test, all}]}]. @@ -48,9 +51,6 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. - - - %%-------------------------------------------------------------------- %% Function: init_per_suite(Config) -> Config %% Config - [tuple()] @@ -103,14 +103,8 @@ end_per_testcase(_, Config) -> %% Test cases starts here. %%------------------------------------------------------------------------- - - -%%------------------------------------------------------------------------- - -start_inets(doc) -> - ["Test inets API functions"]; -start_inets(suite) -> - []; +start_inets() -> + [{doc, "Test inets API functions"}]. start_inets(Config) when is_list(Config) -> [_|_] = inets:service_names(), @@ -134,134 +128,85 @@ start_inets(Config) when is_list(Config) -> ok = inets:start(permanent), ok = inets:stop(). - %%------------------------------------------------------------------------- -start_httpc(doc) -> - ["Start/stop of httpc service"]; -start_httpc(suite) -> - []; +start_httpc() -> + [{doc, "Start/stop of httpc service"}]. start_httpc(Config) when is_list(Config) -> process_flag(trap_exit, true), - tsp("start_httpc -> entry with" - "~n Config: ~p", [Config]), - PrivDir = ?config(priv_dir, Config), - tsp("start_httpc -> start (empty) inets"), ok = inets:start(), - - tsp("start_httpc -> start httpc (as inets service) with profile foo"), {ok, Pid0} = inets:start(httpc, [{profile, foo}]), - tsp("start_httpc -> check running services"), Pids0 = [ServicePid || {_, ServicePid} <- inets:services()], true = lists:member(Pid0, Pids0), [_|_] = inets:services_info(), - tsp("start_httpc -> stop httpc"), inets:stop(httpc, Pid0), - tsp("start_httpc -> sleep some"), test_server:sleep(100), - tsp("start_httpc -> check running services"), Pids1 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid0, Pids1), - tsp("start_httpc -> start httpc (stand-alone) with profile bar"), {ok, Pid1} = inets:start(httpc, [{profile, bar}], stand_alone), - tsp("start_httpc -> check running services"), Pids2 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid1, Pids2), - tsp("start_httpc -> stop httpc"), ok = inets:stop(stand_alone, Pid1), receive {'EXIT', Pid1, shutdown} -> ok after 100 -> - tsf(stand_alone_not_shutdown) + ct:fail(stand_alone_not_shutdown) end, - tsp("start_httpc -> stop inets"), ok = inets:stop(), - tsp("start_httpc -> unload inets"), application:load(inets), - - tsp("start_httpc -> set inets environment (httpc profile foo)"), application:set_env(inets, services, [{httpc,[{profile, foo}, {data_dir, PrivDir}]}]), - - tsp("start_httpc -> start inets"), ok = inets:start(), - tsp("start_httpc -> check running services"), (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()), - tsp("start_httpc -> unset inets env"), application:unset_env(inets, services), - - tsp("start_httpc -> stop inets"), ok = inets:stop(), - - tsp("start_httpc -> start (empty) inets"), ok = inets:start(), - tsp("start_httpc -> start inets httpc service with profile foo"), {ok, Pid3} = inets:start(httpc, [{profile, foo}]), - - tsp("start_httpc -> stop inets service httpc with profile foo"), ok = inets:stop(httpc, foo), - - tsp("start_httpc -> check running services"), Pids3 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid3, Pids3), - - tsp("start_httpc -> stop inets"), - ok = inets:stop(), - - tsp("start_httpc -> done"), - ok. - + ok = inets:stop(). %%------------------------------------------------------------------------- -start_httpd(doc) -> - ["Start/stop of httpd service"]; -start_httpd(suite) -> - []; +start_httpd() -> + [{doc, "Start/stop of httpd service"}]. start_httpd(Config) when is_list(Config) -> process_flag(trap_exit, true), - i("start_httpd -> entry with" - "~n Config: ~p", [Config]), PrivDir = ?config(priv_dir, Config), HttpdConf = [{server_name, "httpd_test"}, {server_root, PrivDir}, - {document_root, PrivDir}, {bind_address, "localhost"}], + {document_root, PrivDir}, {bind_address, any}], - i("start_httpd -> start inets"), ok = inets:start(), - - i("start_httpd -> start httpd service"), {ok, Pid0} = inets:start(httpd, [{port, 0}, {ipfamily, inet} | HttpdConf]), Pids0 = [ServicePid || {_, ServicePid} <- inets:services()], true = lists:member(Pid0, Pids0), [_|_] = inets:services_info(), - i("start_httpd -> stop httpd service"), inets:stop(httpd, Pid0), test_server:sleep(500), Pids1 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid0, Pids1), - i("start_httpd -> start (stand-alone) httpd service"), {ok, Pid1} = inets:start(httpd, [{port, 0}, {ipfamily, inet} | HttpdConf], stand_alone), Pids2 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid1, Pids2), - i("start_httpd -> stop (stand-alone) httpd service"), ok = inets:stop(stand_alone, Pid1), receive {'EXIT', Pid1, shutdown} -> @@ -269,7 +214,6 @@ start_httpd(Config) when is_list(Config) -> after 100 -> test_server:fail(stand_alone_not_shutdown) end, - i("start_httpd -> stop inets"), ok = inets:stop(), File0 = filename:join(PrivDir, "httpd.conf"), {ok, Fd0} = file:open(File0, [write]), @@ -277,17 +221,12 @@ start_httpd(Config) when is_list(Config) -> ok = file:write(Fd0, Str), file:close(Fd0), - i("start_httpd -> [application] load inets"), application:load(inets), - i("start_httpd -> [application] set httpd services env with proplist-file"), application:set_env(inets, services, [{httpd, [{proplist_file, File0}]}]), - i("start_httpd -> start inets"), ok = inets:start(), (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()), - i("start_httpd -> [application] unset services env"), application:unset_env(inets, services), - i("start_httpd -> stop inets"), ok = inets:stop(), File1 = filename:join(PrivDir, "httpd_apache.conf"), @@ -300,68 +239,46 @@ start_httpd(Config) when is_list(Config) -> file:write(Fd1, "Port 0\r\n"), file:close(Fd1), - i("start_httpd -> [application] load inets"), application:load(inets), - i("start_httpd -> [application] set httpd services env with file"), application:set_env(inets, services, [{httpd, [{file, File1}]}]), - i("start_httpd -> start inets"), ok = inets:start(), (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()), - i("start_httpd -> [application] unset services env"), application:unset_env(inets, services), - i("start_httpd -> stop inets"), ok = inets:stop(), %% OLD format - i("start_httpd -> [application] load inets"), application:load(inets), - i("start_httpd -> [application] set httpd services OLD env"), application:set_env(inets, services, [{httpd, File1}]), - i("start_httpd -> start inets"), ok = inets:start(), (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()), - i("start_httpd -> [application] unset services enc"), application:unset_env(inets, services), - i("start_httpd -> stop inets"), ok = inets:stop(), - - i("start_httpd -> start inets"), ok = inets:start(), - i("start_httpd -> try (and fail) start httpd service - server_name"), {error, {missing_property, server_name}} = inets:start(httpd, [{port, 0}, {server_root, PrivDir}, {document_root, PrivDir}, {bind_address, "localhost"}]), - i("start_httpd -> try (and fail) start httpd service - missing document_root"), {error, {missing_property, document_root}} = inets:start(httpd, [{port, 0}, {server_name, "httpd_test"}, {server_root, PrivDir}, {bind_address, "localhost"}]), - i("start_httpd -> try (and fail) start httpd service - missing server_root"), {error, {missing_property, server_root}} = inets:start(httpd, [{port, 0}, {server_name, "httpd_test"}, {document_root, PrivDir}, {bind_address, "localhost"}]), - i("start_httpd -> try (and fail) start httpd service - missing port"), {error, {missing_property, port}} = inets:start(httpd, HttpdConf), - i("start_httpd -> stop inets"), - ok = inets:stop(), - i("start_httpd -> done"), - ok. - + ok = inets:stop(). %%------------------------------------------------------------------------- start_ftpc(doc) -> - ["Start/stop of ftpc service"]; -start_ftpc(suite) -> - []; + [{doc, "Start/stop of ftpc service"}]; start_ftpc(Config) when is_list(Config) -> process_flag(trap_exit, true), ok = inets:start(), @@ -389,7 +306,7 @@ start_ftpc(Config) when is_list(Config) -> {'EXIT', Pid1, shutdown} -> ok after 100 -> - tsf(stand_alone_not_shutdown) + ct:fail(stand_alone_not_shutdown) end, ok = inets:stop(), ok; @@ -401,15 +318,11 @@ start_ftpc(Config) when is_list(Config) -> throw:{error, not_found} -> {skip, "No available FTP servers"} end. - - %%------------------------------------------------------------------------- -start_tftpd(doc) -> - ["Start/stop of tfpd service"]; -start_tftpd(suite) -> - []; +start_tftpd() -> + [{doc, "Start/stop of tfpd service"}]. start_tftpd(Config) when is_list(Config) -> process_flag(trap_exit, true), ok = inets:start(), @@ -441,16 +354,12 @@ start_tftpd(Config) when is_list(Config) -> application:unset_env(inets, services), ok = inets:stop(). - %%------------------------------------------------------------------------- -httpd_reload(doc) -> - ["Reload httpd configuration without restarting service"]; -httpd_reload(suite) -> - []; +httpd_reload() -> + [{doc, "Reload httpd configuration without restarting service"}]. httpd_reload(Config) when is_list(Config) -> process_flag(trap_exit, true), - i("httpd_reload -> starting"), PrivDir = ?config(priv_dir, Config), DataDir = ?config(data_dir, Config), HttpdConf = [{server_name, "httpd_test"}, @@ -458,23 +367,18 @@ httpd_reload(Config) when is_list(Config) -> {document_root, PrivDir}, {bind_address, "localhost"}], - i("httpd_reload -> start inets"), - ok = inets:start(), test_server:sleep(5000), - i("httpd_reload -> inets started - start httpd service"), - {ok, Pid0} = inets:start(httpd, [{port, 0}, {ipfamily, inet} | HttpdConf]), + {ok, Pid0} = inets:start(httpd, [{port, 0}, + {ipfamily, inet} | HttpdConf]), test_server:sleep(5000), - i("httpd_reload -> httpd service started (~p) - get port", [Pid0]), [{port, Port0}] = httpd:info(Pid0, [port]), test_server:sleep(5000), - i("httpd_reload -> Port: ~p - get document root", [Port0]), [{document_root, PrivDir}] = httpd:info(Pid0, [document_root]), test_server:sleep(5000), - i("httpd_reload -> document root: ~p - reload config", [PrivDir]), ok = httpd:reload_config([{port, Port0}, {ipfamily, inet}, {server_name, "httpd_test"}, @@ -482,11 +386,8 @@ httpd_reload(Config) when is_list(Config) -> {document_root, DataDir}, {bind_address, "localhost"}], non_disturbing), test_server:sleep(5000), - io:format("~w:~w:httpd_reload - reloaded - get document root~n", [?MODULE, ?LINE]), - [{document_root, DataDir}] = httpd:info(Pid0, [document_root]), test_server:sleep(5000), - i("httpd_reload -> document root: ~p - reload config", [DataDir]), ok = httpd:reload_config([{port, Port0}, {ipfamily, inet}, {server_name, "httpd_test"}, @@ -539,23 +440,5 @@ httpd_reload(Config) when is_list(Config) -> ok = inets:stop(httpd, Pid1), application:unset_env(inets, services), - ok = inets:stop(), - i("httpd_reload -> starting"), - ok. - - -tsf(Reason) -> - test_server:fail(Reason). - -tsp(F) -> - tsp(F, []). -tsp(F, A) -> - Timestamp = inets_lib:formated_timestamp(), - test_server:format("** ~s ** ~p ~p:" ++ F ++ "~n", [Timestamp, self(), ?MODULE | A]). - -i(F) -> - i(F, []). + ok = inets:stop(). -i(F, A) -> - Timestamp = inets_lib:formated_timestamp(), - io:format("*** ~s ~w:" ++ F ++ "~n", [Timestamp, ?MODULE | A]). diff --git a/lib/inets/test/inets_socketwrap_SUITE.erl b/lib/inets/test/inets_socketwrap_SUITE.erl new file mode 100644 index 0000000000..cfbda3ccf5 --- /dev/null +++ b/lib/inets/test/inets_socketwrap_SUITE.erl @@ -0,0 +1,154 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +%% +-module(inets_socketwrap_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include("inets_test_lib.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +suite() -> + [{ct_hooks,[ts_install_cth]}]. + +all() -> + [start_httpd_fd, start_tftpd_fd]. + +init_per_suite(Config) -> + case os:type() of + {unix, linux} -> + Config; + _ -> + {skip, linux_feature} + end. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +init_per_testcase(Case, Config) -> + end_per_testcase(Case, Config), + Config. + +end_per_testcase(_, Config) -> + inets:stop(), + Config. + +%%------------------------------------------------------------------------- +start_httpd_fd() -> + [{doc, "Start/stop of httpd service with socket wrapper"}]. +start_httpd_fd(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + DataDir = ?config(data_dir, Config), + HttpdConf = [{port, 80}, {ipfamily, inet}, + {server_name, "httpd_fd_test"}, {server_root, PrivDir}, + {document_root, PrivDir}, {bind_address, any}], + case setup_node_info(node()) of + {skip, _} = Skip -> + Skip; + {Node, NodeArg} -> + InetPort = inets_test_lib:inet_port(node()), + ct:pal("Node: ~p Port ~p~n", [Node, InetPort]), + Wrapper = filename:join(DataDir, "setuid_socket_wrap"), + Cmd = Wrapper ++ + " -s -httpd_80,0:" ++ integer_to_list(InetPort) + ++ " -p " ++ os:find_executable("erl") ++ + " -- " ++ NodeArg, + ct:pal("cmd: ~p~n", [Cmd]), + case open_port({spawn, Cmd}, [stderr_to_stdout]) of + Port when is_port(Port) -> + wait_node_up(Node, 10), + ct:pal("~p", [rpc:call(Node, init, get_argument, [httpd_80])]), + ok = rpc:call(Node, inets, start, []), + {ok, Pid} = rpc:call(Node, inets, start, [httpd, HttpdConf]), + [{port, InetPort}] = rpc:call(Node, httpd, info, [Pid, [port]]), + rpc:call(Node, erlang, halt, []); + _ -> + ct:fail(open_port_failed) + end + end. +%%------------------------------------------------------------------------- +start_tftpd_fd() -> + [{doc, "Start/stop of tfpd service with socket wrapper"}]. +start_tftpd_fd(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + case setup_node_info(node()) of + {skip, _} = Skip -> + Skip; + {Node, NodeArg} -> + InetPort = inets_test_lib:inet_port(node()), + ct:pal("Node: ~p~n", [Node]), + Wrapper = filename:join(DataDir, "setuid_socket_wrap"), + Cmd = Wrapper ++ + " -s -tftpd_69,0:" ++ integer_to_list(InetPort) + ++ " -p " ++ os:find_executable("erl") ++ + " -- " ++ NodeArg, + ct:pal("cmd: ~p~n", [Cmd]), + case open_port({spawn, Cmd}, [stderr_to_stdout]) of + Port when is_port(Port) -> + wait_node_up(Node, 10), + ct:pal("~p", [rpc:call(Node, init, get_argument, [tftpd_69])]), + ok = rpc:call(Node, inets, start, []), + {ok, Pid} = rpc:call(Node, inets, start, + [tftpd,[{host, "localhost"}]]), + {ok, Info} = rpc:call(Node, tftp, info, [Pid]), + {value,{port, InetPort}} = lists:keysearch(port, 1, Info), + rpc:call(Node, erlang, halt, []); + _ -> + ct:fail(open_port_failed) + end + end. +%%------------------------------------------------------------------------- +%% Internal functions +%%------------------------------------------------------------------------- +setup_node_info(nonode@nohost) -> + {skip, needs_distributed_node}; +setup_node_info(Node) -> + Static = "-detached -noinput", + Name = "inets_fd_test", + NameSw = case net_kernel:longnames() of + false -> "-sname "; + _ -> "-name " + end, + StrNode = + Static ++ " " + ++ NameSw ++ " " ++ Name ++ " " + ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()), + [_, Location] = string:tokens(atom_to_list(Node), "$@"), + TestNode = Name ++ "@" ++ Location, + {list_to_atom(TestNode), StrNode}. + +wait_node_up(Node, 0) -> + ct:fail({failed_to_start_node, Node}); +wait_node_up(Node, N) -> + ct:pal("(Node ~p: net_adm:ping(~p)~n", [node(), Node]), + case net_adm:ping(Node) of + pong -> + ok; + pang -> + ct:sleep(5000), + wait_node_up(Node, N-1) + end. diff --git a/lib/ose/Makefile b/lib/inets/test/inets_socketwrap_SUITE_data/Makefile.src index 6119b75c3f..0933815b58 100644 --- a/lib/ose/Makefile +++ b/lib/inets/test/inets_socketwrap_SUITE_data/Makefile.src @@ -1,8 +1,8 @@ -# +# # %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 2015-2015. All Rights Reserved. +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -14,24 +14,26 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# +# # %CopyrightEnd% # -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk -# -# Macros -# +CC = @CC@ +LD = @LD@ +CFLAGS = @CFLAGS@ +CROSSLDFLAGS = @CROSSLDFLAGS@ -SUB_DIRECTORIES = src doc/src +PROGS = setuid_socket_wrap@exe@ -include vsn.mk -VSN = $(OSE_VSN) +.PHONY: all +@IFEQ@ (@os@, linux-gnu) +all: $(PROGS) +@ELSE@ +all: +@ENDIF@ -SPECIAL_TARGETS = +setuid_socket_wrap@exe@: setuid_socket_wrap@obj@ + $(LD) $(CROSSLDFLAGS) -o setuid_socket_wrap setuid_socket_wrap@obj@ @LIBS@ -# -# Default Subdir Targets -# -include $(ERL_TOP)/make/otp_subdir.mk +setuid_socket_wrap@obj@: setuid_socket_wrap.c + $(CC) -c $(CFLAGS) -o setuid_socket_wrap@obj@ setuid_socket_wrap.c diff --git a/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c b/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c new file mode 100644 index 0000000000..b28f6b1c08 --- /dev/null +++ b/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c @@ -0,0 +1,259 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1999-2009. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * %CopyrightEnd% + */ +/* + * setuid_socket_wrap.c + * + * ./a.out [-s [tag,][addr]:[port]]* [-d [tag,][addr]:[port]]* + * [-r [tag,]proto]* [-p erl_path]* -- program args + * + * Where: -s = stream socket, -d datagram socket and -r means raw socket. + * + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +struct sock_list { + struct sock_list *next; + int fd; + int type; + int protocol; + struct sockaddr_in addr; + char *arg; +}; + +int parse_addr(addr, str) + struct sockaddr_in *addr; + char *str; +{ + int port = 0; + char *cp; + struct hostent *hp; + struct servent *se; + + if ((cp = strrchr(str, (int)':')) != NULL) + *cp++ = '\0'; + if (cp) { + if (!isdigit((int)cp[0])) { + if ((se = getservbyname(cp, "tcp")) != NULL) { + port = ntohs(se->s_port); + } else { + fprintf(stderr, "unknown port %s\n", cp); + return -1; + } + } else { + port = atoi(cp); + } + } + if (port < 0 || port > 0xffff) { + fprintf(stderr, "bad port number %d\n", port); + return -1; + } + + bzero(addr, sizeof(*addr)); + addr->sin_family = AF_INET; + addr->sin_port = htons(port); + if (*str == '\000') { + addr->sin_addr.s_addr = INADDR_ANY; + } else { + if ((addr->sin_addr.s_addr = inet_addr(str)) == INADDR_NONE) { + if ((hp = gethostbyname(str)) == NULL) { + fprintf(stderr, "\"%s\" unknown host or address!\n", str); + return -1; + } else { + bcopy(hp->h_addr_list[0], &addr->sin_addr.s_addr,hp->h_length); + } + } + } + return 0; +} + +struct sock_list *new_entry(type, argstr) + int type; + char *argstr; +{ + struct sock_list *sle; + char *cp; + + sle = (struct sock_list *)malloc(sizeof(struct sock_list)); + if (!sle) + return NULL; + sle->next = NULL; + sle->fd = -1; + + if ((cp = strchr(argstr, (int)',')) != NULL) { + *cp++ = '\0'; + sle->arg = argstr; + argstr = cp; + } else { + sle->arg = "-fd"; + } + sle->type = type; + switch (type) { + case SOCK_RAW: { + struct protoent *pe; + pe = getprotobyname(argstr); + if (!pe) { + fprintf(stderr, "Unknown protocol: %s\n", argstr); + free(sle); + return NULL; + } + sle->protocol = pe->p_proto; + break; + } + case SOCK_STREAM: + case SOCK_DGRAM: + sle->protocol = 0; + if (parse_addr(&sle->addr, argstr) < 0) { + free(sle); + return NULL; + } + break; + } + return sle; +} + +int open_socket(sle) + struct sock_list *sle; +{ + sle->fd = socket(AF_INET, sle->type, sle->protocol); + if (sle->fd < 0) { + perror("socket"); + return -1; + } + if (sle->type != SOCK_RAW) { +#if 0 + printf("binding fd %d to %s:%d\n", sle->fd, + inet_ntoa(sle->addr.sin_addr), ntohs(sle->addr.sin_port)); +#endif + if (bind(sle->fd, (struct sockaddr *)&sle->addr, sizeof(sle->addr))<0){ + perror("bind"); + close(sle->fd); + return -1; + } + } + return sle->fd; +} + +int main(argc, argv) + int argc; + char *argv[]; +{ + struct sock_list *sl = NULL, *sltmp = NULL; + int count = 0; + int c; + char *run_prog = NULL; + + while ((c = getopt(argc, argv, "s:d:r:p:")) != EOF) + switch (c) { + case 's': + sltmp = new_entry(SOCK_STREAM, optarg); + if (!sltmp) { + exit(1); + } + sltmp->next = sl; + sl = sltmp; + count++; + break; + case 'd': + sltmp = new_entry(SOCK_DGRAM, optarg); + if (!sltmp) { + exit(1); + } + sltmp->next = sl; + sl = sltmp; + count++; + break; + case 'r': + sltmp = new_entry(SOCK_RAW, optarg); + if (!sltmp) { + exit(1); + } + sltmp->next = sl; + sl = sltmp; + count++; + break; + case 'p': + run_prog = optarg; + break; + default: + exit(1); + } + argc -= optind; + argv += optind; + + for(sltmp = sl; sltmp != NULL; sltmp = sltmp->next) + if (open_socket(sltmp) < 0) { + fprintf(stderr, "failed to create socket!\n"); + exit(1); + } + + setuid(getuid()); + + { + int i; + char **newargv; + char *run_prog_name; + + newargv = (char **)malloc((1 + 2*count + argc + 1) * sizeof(char*)); + + if ((run_prog_name = strrchr(run_prog, (int)'/')) == NULL) + run_prog_name = run_prog; + else + run_prog_name++; + + i = 0; + newargv[i++] = run_prog_name; + + for (; argc; argc--, argv++, i++) + newargv[i] = *argv; + for(sltmp = sl; sltmp != NULL; ) { + char *fd_str = (char *)malloc(8); + if (!fd_str) exit(1); + sprintf(fd_str, "%d", sltmp->fd); + if (sltmp->arg && *(sltmp->arg)) + newargv[i++] = sltmp->arg; + newargv[i++] = fd_str; + sl = sltmp; + sltmp = sltmp->next; + free(sl); + } + newargv[i] = (char *)NULL; + execv(run_prog, newargv); + perror("exec"); + exit(1); + } + exit(0); +} diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl index b471dcf784..f1185f7574 100644 --- a/lib/inets/test/inets_test_lib.erl +++ b/lib/inets/test/inets_test_lib.erl @@ -563,3 +563,12 @@ stop_apps(Apps) -> application:stop(App) end, Apps). +inet_port(Node) -> + {Port, Socket} = do_inet_port(Node), + rpc:call(Node, gen_tcp, close, [Socket]), + Port. + +do_inet_port(Node) -> + {ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]), + {ok, Port} = rpc:call(Node, inet, port, [Socket]), + {Port, Socket}. diff --git a/lib/inets/test/uri_SUITE.erl b/lib/inets/test/uri_SUITE.erl index bfcd7bd339..2642b8fd4e 100644 --- a/lib/inets/test/uri_SUITE.erl +++ b/lib/inets/test/uri_SUITE.erl @@ -49,7 +49,8 @@ all() -> queries, fragments, escaped, - hexed_query + hexed_query, + scheme_validation ]. %%-------------------------------------------------------------------- @@ -175,6 +176,26 @@ hexed_query(Config) when is_list(Config) -> verify_uri(URI2, Verify2), verify_uri(URI3, Verify3). +scheme_validation(Config) when is_list(Config) -> + {ok, {http,[],"localhost",80,"/",""}} = + http_uri:parse("http://localhost#fragment"), + + ValidationFun = + fun("http") -> valid; + (_) -> {error, bad_scheme} + end, + + {ok, {http,[],"localhost",80,"/",""}} = + http_uri:parse("http://localhost#fragment", + [{scheme_validation_fun, ValidationFun}]), + {error, bad_scheme} = + http_uri:parse("https://localhost#fragment", + [{scheme_validation_fun, ValidationFun}]), + %% non-fun scheme_validation_fun works as no option passed + {ok, {https,[],"localhost",443,"/",""}} = + http_uri:parse("https://localhost#fragment", + [{scheme_validation_fun, none}]). + %%-------------------------------------------------------------------- %% Internal Functions ------------------------------------------------ diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 5395df1d07..480caeca4b 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 6.0 +INETS_VSN = 6.0.2 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" diff --git a/lib/kernel/doc/src/app.xml b/lib/kernel/doc/src/app.xml index 1591d589af..d6d6167923 100644 --- a/lib/kernel/doc/src/app.xml +++ b/lib/kernel/doc/src/app.xml @@ -191,7 +191,7 @@ RTDeps [ApplicationVersion] [] start phases must be a subset of the set of phases defined for the primary application. Refer to <em>OTP Design Principles</em> for more information.</p> </item> - <tag><marker id="runtime_dependencies"><c>runtime_dependencies</c></marker></tag> + <tag><marker id="runtime_dependencies"></marker><c>runtime_dependencies</c></tag> <item><p>A list of application versions that the application depends on. An example of such an application version is <c>"kernel-3.0"</c>. Application versions specified as runtime diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml index 0fe774a73f..4d8e6ce94b 100644 --- a/lib/kernel/doc/src/application.xml +++ b/lib/kernel/doc/src/application.xml @@ -60,8 +60,9 @@ </datatype> <datatype> <!-- Parameterized opaque types are NYI: --> - <name><marker id="type-tuple_of">tuple_of(T)</marker></name> - <desc><p>A tuple where the elements are of type <c>T</c>.</p></desc> + <name>tuple_of(T)</name> + <desc><p><marker id="type-tuple_of"/> + A tuple where the elements are of type <c>T</c>.</p></desc> </datatype> </datatypes> <funcs> diff --git a/lib/kernel/doc/src/auth.xml b/lib/kernel/doc/src/auth.xml index 9ebc6f8f1a..71b1863e96 100644 --- a/lib/kernel/doc/src/auth.xml +++ b/lib/kernel/doc/src/auth.xml @@ -50,7 +50,7 @@ be established in this case. Returns <c>no</c> if <c><anno>Node</anno></c> does not exist or communication is not authorized (it has another cookie than <c>auth</c> thinks it has).</p> - <p>Use <seealso marker="net_adm#ping/1">net_adm:ping(<anno>Node</anno>)</seealso> + <p>Use <seealso marker="net_adm#ping/1">net_adm:ping(<c><anno>Node</anno></c>)</seealso> instead.</p> </desc> </func> @@ -71,7 +71,7 @@ </type_desc> <desc> <p>Use - <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(node(), <anno>Cookie</anno>)</seealso> + <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(node(), <c><anno>Cookie</anno></c>)</seealso> instead.</p> </desc> </func> @@ -94,8 +94,8 @@ <p>Sets the magic cookie of <c><anno>Node</anno></c> to <c><anno>Cookie</anno></c>, and verifies the status of the authorization. Equivalent to calling - <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(<anno>Node</anno>, <anno>Cookie</anno>)</seealso>, followed by - <seealso marker="#is_auth/1">auth:is_auth(<anno>Node</anno>)</seealso>.</p> + <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(<c><anno>Node</anno></c>, <c><anno>Cookie</anno>)</c></seealso>, followed by + <seealso marker="#is_auth/1">auth:is_auth(<c><anno>Node</anno></c>)</seealso>.</p> </desc> </func> </funcs> diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 7cdedfa0ba..4e3be35079 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -180,7 +180,7 @@ example, the call <c>erl_prim_loader:list_dir( "/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)"</c> would list the contents of a directory inside an archive. - See <seealso marker="erts:erl_prim_loader">erl_prim_loader(3)</seealso></p>. + See <seealso marker="erts:erl_prim_loader">erl_prim_loader(3)</seealso>.</p> <p>An application archive file and a regular application directory may coexist. This may be useful when there is a need of having @@ -242,7 +242,7 @@ particular useful to set the flag to <c>relaxed</c> when you want to elaborate with code loading from archives without editing the <c>boot script</c>. The default is <c>relaxed</c>. See <seealso - marker="erts:init">init(3)</seealso></p> </section> + marker="erts:init">init(3)</seealso></p></section> <section> diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index 32488a9f01..7d4a9687ea 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -233,11 +233,11 @@ <func> <name name="alog" arity="2"/> <name name="balog" arity="2"/> + <fsummary>Asynchronously log an item onto a disk log.</fsummary> <type variable="Log"/> <type variable="Term" name_i="1"/> <type variable="Bytes"/> <type name="notify_ret"/> - <fsummary>Asynchronously log an item onto a disk log.</fsummary> <desc> <p>The <c>alog/2</c> and <c>balog/2</c> functions asynchronously append an item to a disk log. The function <c>alog/2</c> is @@ -288,8 +288,8 @@ <func> <name name="block" arity="1"/> <name name="block" arity="2"/> - <type name="block_error_rsn"/> <fsummary>Block a disk log.</fsummary> + <type name="block_error_rsn"/> <desc> <p>With a call to <c>block/1,2</c> a process can block a log. If the blocking process is not an owner of the log, a temporary @@ -663,8 +663,8 @@ <func> <name name="lclose" arity="1"/> <name name="lclose" arity="2"/> - <type name="lclose_error_rsn"/> <fsummary>Close a disk log on one node.</fsummary> + <type name="lclose_error_rsn"/> <desc> <p>The function <c>lclose/1</c> closes a local log or an individual distributed log on the current node. @@ -744,6 +744,7 @@ </func> <func> <name name="open" arity="1"/> + <fsummary>Open a disk log file.</fsummary> <type name="dlog_options"/> <type name="dlog_option"/> <type name="open_ret"/> @@ -753,7 +754,6 @@ <type name="open_error_rsn"/> <type name="dlog_optattr"/> <type name="dlog_size"/> - <fsummary>Open a disk log file.</fsummary> <desc> <p>The <c><anno>ArgL</anno></c> parameter is a list of options which have the following meanings:</p> @@ -1043,8 +1043,8 @@ If </func> <func> <name name="sync" arity="1"/> - <type name="sync_error_rsn"/> <fsummary>Flush the contents of a disk log to the disk.</fsummary> + <type name="sync_error_rsn"/> <desc> <p>The <c>sync/1</c> function ensures that the contents of the log are actually written to the disk. @@ -1086,8 +1086,8 @@ If </func> <func> <name name="unblock" arity="1"/> - <type name="unblock_error_rsn"/> <fsummary>Unblock a disk log.</fsummary> + <type name="unblock_error_rsn"/> <desc> <p>The <c>unblock/1</c> function unblocks a log. A log can only be unblocked by the blocking process. diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml index d622725ba0..8d71883cf4 100644 --- a/lib/kernel/doc/src/erl_ddll.xml +++ b/lib/kernel/doc/src/erl_ddll.xml @@ -388,14 +388,14 @@ remove a monitor.</p> <p>The function accepts the following parameters:</p> <taglist> - <tag><em><anno>Tag</anno></em></tag> + <tag><em><c><anno>Tag</anno></c></em></tag> <item> <p>The monitor tag is always <c>driver</c> as this function can only be used to create driver monitors. In the future, driver monitors will be integrated with process monitors, why this parameter has to be given for consistence.</p> </item> - <tag><em><anno>Item</anno></em></tag> + <tag><em><c><anno>Item</anno></c></em></tag> <item> <p>The <c><anno>Item</anno></c> parameter specifies which driver one wants to monitor (the name of the driver) as well as @@ -642,7 +642,7 @@ </note> <p>The function accepts the following parameters:</p> <taglist> - <tag><em><anno>Path</anno></em></tag> + <tag><em><c><anno>Path</anno></c></em></tag> <item> <p>The filesystem path to the directory where the driver object file is situated. The filename of the object file @@ -665,7 +665,7 @@ to have <em>only one loader</em> of a driver one wants to upgrade in a running system! </p> </item> - <tag><em><anno>Name</anno></em></tag> + <tag><em><c><anno>Name</anno></c></em></tag> <item> <p>The name parameter is the name of the driver to be used in subsequent calls to <seealso marker="erts:erlang#open_port/2">open_port</seealso>. The @@ -678,14 +678,14 @@ with this <c><anno>Name</anno></c> parameter, much as a beam-file's module name much correspond to its filename.</p> </item> - <tag><em><anno>OptionList</anno></em></tag> + <tag><em><c><anno>OptionList</anno></c></em></tag> <item> <p>A number of options can be specified to control the loading operation. The options are given as a list of two-tuples, the tuples having the following values and meanings:</p> <taglist> - <tag><em>{driver_options, <anno>DriverOptionList</anno>}</em></tag> + <tag><em>{driver_options, <c><anno>DriverOptionList</anno></c>}</em></tag> <item> <p>This option is to provide options that will change its general behavior and will "stick" to the driver @@ -701,7 +701,7 @@ when the last <seealso marker="#users">user</seealso> calls <seealso marker="#try_unload/2">try_unload/2</seealso>, or the last process having loaded the driver exits.</p> </item> - <tag><em>{monitor, <anno>MonitorOption</anno>}</em></tag> + <tag><em>{monitor, <c><anno>MonitorOption</anno></c>}</em></tag> <item> <p>A <c><anno>MonitorOption</anno></c> tells <c>try_load/3</c> to trigger a driver monitor under certain @@ -732,7 +732,7 @@ <c>{monitor, pending_driver}</c> in production code (see the monitor discussion above). </p> </item> - <tag><em>{reload,<anno>ReloadOption</anno>}</em></tag> + <tag><em>{reload, <c><anno>ReloadOption</anno></c>}</em></tag> <item> <p>This option is used when one wants to <em>reload</em> a driver from disk, most often in a @@ -910,13 +910,13 @@ </taglist> <p>The function accepts the following parameters:</p> <taglist> - <tag><em><anno>Name</anno></em></tag> + <tag><em><c><anno>Name</anno></c></em></tag> <item> <p>The name parameter is the name of the driver to be unloaded. The name can be specified either as an <c>iolist()</c> or as an <c>atom()</c>. </p> </item> - <tag><em><anno>OptionList</anno></em></tag> + <tag><em><c><anno>OptionList</anno></c></em></tag> <item> <p>The <c><anno>OptionList</anno></c> argument can be used to specify certain behavior regarding ports as well as triggering @@ -934,7 +934,7 @@ unloads, one should use the driver option <c>kill_ports</c> when loading the driver instead.</p> </item> - <tag><em>{monitor, <anno>MonitorOption</anno>}</em></tag> + <tag><em>{monitor, <c><anno>MonitorOption</anno></c>}</em></tag> <item> <p>This option creates a driver monitor if the condition given in <c><anno>MonitorOption</anno></c> is true. The valid diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index f83fe53084..92e14c2bef 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -299,12 +299,12 @@ ok</pre> <name name="logfile" arity="1" clause_i="1"/> <name name="logfile" arity="1" clause_i="2"/> <name name="logfile" arity="1" clause_i="3"/> + <fsummary>Enable or disable error printouts to a file</fsummary> <type variable="Filename"/> <type variable="OpenReason" name_i="1"/> <type variable="CloseReason" name_i="2"/> <type variable="FilenameReason" name_i="3"/> <type name="open_error"/> - <fsummary>Enable or disable error printouts to a file</fsummary> <desc> <p>Enables or disables printout of standard events to a file.</p> <p>This is done by adding or deleting the standard event handler diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 4954568086..9cd4cfa712 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -87,9 +87,10 @@ <name name="deep_list"/> </datatype> <datatype> - <name><marker id="type-fd">fd()</marker></name> + <name>fd()</name> <desc> - <p>A file descriptor representing a file opened in <seealso + <p><marker id="type-fd"/> + A file descriptor representing a file opened in <seealso marker="#raw">raw</seealso> mode.</p> </desc> </datatype> @@ -491,7 +492,7 @@ <name name="list_dir" arity="1"/> <fsummary>List files in a directory</fsummary> <desc> - <p>Lists all files in a directory, <b>except</b> files + <p>Lists all files in a directory, <em>except</em> files with "raw" names. Returns <c>{ok, <anno>Filenames</anno>}</c> if successful. Otherwise, it returns <c>{error, <anno>Reason</anno>}</c>. @@ -1307,15 +1308,15 @@ <item> <p>The current system access to the file.</p> </item> - <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag> + <tag><c>atime = </c><seealso marker="#type-date_time">date_time()</seealso><c> | integer() >= 0</c></tag> <item> <p>The last time the file was read.</p> </item> - <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag> + <tag><c>mtime = </c><seealso marker="#type-date_time">date_time()</seealso><c> | integer() >= 0</c></tag> <item> <p>The last time the file was written.</p> </item> - <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >=0</c></tag> + <tag><c>ctime = </c><seealso marker="#type-date_time">date_time()</seealso><c> | integer() >=0</c></tag> <item> <p>The interpretation of this time field depends on the operating system. On Unix, it is the last time @@ -1745,7 +1746,7 @@ See <seealso marker="gen_tcp#controlling_process-2">gen_tcp:controlling_process/2</seealso></p> <p>If the OS used does not support sendfile, an Erlang fallback using file:read and gen_tcp:send is used.</p> - <p>The option list can contain the following options: + <p>The option list can contain the following options:</p> <taglist> <tag><c>chunk_size</c></tag> <item>The chunk size used by the erlang fallback to send @@ -1760,7 +1761,6 @@ the sendfile call will return <c>{error,einval}</c>. Introduced in Erlang/OTP 17.0. Default is false.</item> </taglist> - </p> </desc> </func> <func> @@ -1851,22 +1851,21 @@ Type <c>local</c> will interpret the time set as local, <c>universal</c> will interpret it as universal time and <c>posix</c> must be seconds since or before unix time epoch which is 1970-01-01 00:00 UTC. - Default is <c>{time, local}</c>. + Default is <c>{time, local}</c>.</p> <p>If the <c>raw</c> option is set, the file server will not be called and only informations about local files will be returned.</p> - </p> <p>The following fields are used from the record, if they are given.</p> <taglist> - <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag> + <tag><c>atime = </c><seealso marker="#type-date_time">date_time()</seealso><c> | integer() >= 0</c></tag> <item> <p>The last time the file was read.</p> </item> - <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag> + <tag><c>mtime = </c><seealso marker="#type-date_time">date_time()</seealso><c> | integer() >= 0</c></tag> <item> <p>The last time the file was written.</p> </item> - <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso> | integer() >= 0</c></tag> + <tag><c>ctime = </c><seealso marker="#type-date_time">date_time()</seealso><c> | integer() >= 0</c></tag> <item> <p>On Unix, any value give for this field will be ignored (the "ctime" for the file will be set to the current diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml index b704d90613..456108a2fe 100644 --- a/lib/kernel/doc/src/gen_sctp.xml +++ b/lib/kernel/doc/src/gen_sctp.xml @@ -77,9 +77,10 @@ <datatypes> <datatype> - <name><marker id="type-assoc_id">assoc_id()</marker></name> + <name>assoc_id()</name> <desc> - <p>An opaque term returned in for example #sctp_paddr_change{} + <p><marker id="type-assoc_id"/> + An opaque term returned in for example #sctp_paddr_change{} that identifies an association for an SCTP socket. The term is opaque except for the special value <c>0</c> that has a meaning such as "the whole endpoint" or "all future associations". @@ -98,9 +99,10 @@ <desc><marker id="type-sctp_socket"></marker></desc> </datatype> <datatype> - <name><marker id="type-sctp_socket">sctp_socket()</marker></name> + <name>sctp_socket()</name> <desc> - <p>Socket identifier returned from <c>open/*</c>.</p> + <p><marker id="type-sctp_socket"/> + Socket identifier returned from <c>open/*</c>.</p> <marker id="exports"></marker> </desc> </datatype> @@ -146,7 +148,7 @@ <c><anno>Addr</anno></c> and <c><anno>Port</anno></c>. The <c><anno>Timeout</anno></c>, is expressed in milliseconds. A socket can be associated with multiple peers.</p> - <p><b>WARNING:</b>Using a value of <c><anno>Timeout</anno></c> less than + <p><em>WARNING:</em>Using a value of <c><anno>Timeout</anno></c> less than the maximum time taken by the OS to establish an association (around 4.5 minutes if the default values from RFC 4960 are used) can result in inconsistent or incorrect return values. This is especially @@ -170,7 +172,7 @@ <p>The number of outbound and inbound streams can be set by giving an <c>sctp_initmsg</c> option to <c>connect</c> as in:</p> -<pre> connect(<anno>Socket</anno>, Ip, <anno>Port</anno>, +<pre> connect(Socket, Ip, Port>, [{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams, max_instreams=MaxInStreams}}]) </pre> <p>All options <c><anno>Opt</anno></c> are set on the socket before the diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index 8d9f09cea7..6a19e76c4f 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -78,9 +78,10 @@ do_recv(Sock, Bs) -> <name name="listen_option"/> </datatype> <datatype> - <name><marker id="type-socket">socket()</marker></name> + <name>socket()</name> <desc> - <p>As returned by accept/1,2 and connect/3,4.</p> + <p><marker id="type-socket"/> + As returned by accept/1,2 and connect/3,4.</p> <marker id="connect"></marker> </desc> </datatype> diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml index 6f34aba43c..79cd87dcef 100644 --- a/lib/kernel/doc/src/gen_udp.xml +++ b/lib/kernel/doc/src/gen_udp.xml @@ -43,9 +43,9 @@ <name name="option_name"/> </datatype> <datatype> - <name><marker id="type-socket">socket()</marker></name> + <name>socket()</name> <desc> - <p>As returned by open/1,2.</p> + <p><marker id="type-socket"/>As returned by open/1,2.</p> </desc> </datatype> </datatypes> diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index e5d7ce048a..088d78c1d6 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2015</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -117,8 +117,9 @@ fe80::204:acff:fe17:bf38 </desc> </datatype> <datatype> - <name><marker id="type-socket">socket()</marker></name> - <desc><p>See <seealso marker="gen_tcp#type-socket">gen_tcp(3)</seealso> + <name>socket()</name> + <desc><p><marker id="type-socket"></marker> + See <seealso marker="gen_tcp#type-socket">gen_tcp(3)</seealso> and <seealso marker="gen_udp#type-socket">gen_udp(3)</seealso>.</p> </desc> </datatype> @@ -222,7 +223,7 @@ fe80::204:acff:fe17:bf38 </p> <p> Do not rely too much on the order of <c><anno>Flag</anno></c> atoms or - <c><anno>Ifopt</anno></c> tuples. There are some rules, though: + <c><anno>Ifopt</anno></c> tuples. There are some rules, though:</p> <list> <item> Immediately after <c>{addr,_}</c> follows <c>{netmask,_}</c> @@ -238,7 +239,6 @@ fe80::204:acff:fe17:bf38 tuple concerns that address. </item> </list> - </p> <p> The <c>{hwaddr,_}</c> tuple is not returned on Solaris since the hardware address historically belongs to the link layer and only @@ -379,14 +379,14 @@ fe80::204:acff:fe17:bf38 <name name="ntoa" arity="1" /> <fsummary>Convert IPv6 / IPV4 adress to ascii</fsummary> <desc> - <p>Parses an <a href="#type-ip_address">ip_address()</a> and returns an IPv4 or IPv6 address string.</p> + <p>Parses an <seealso marker="#type-ip_address">ip_address()</seealso> and returns an IPv4 or IPv6 address string.</p> </desc> </func> <func> <name name="parse_ipv4_address" arity="1" /> <fsummary>Parse an IPv4 address</fsummary> <desc> - <p>Parses an IPv4 address string and returns an <a href="#type-ip4_address">ip4_address()</a>. + <p>Parses an IPv4 address string and returns an <seealso marker="#type-ip4_address">ip4_address()</seealso>. Accepts a shortened IPv4 shortened address string.</p> </desc> </func> @@ -394,14 +394,14 @@ fe80::204:acff:fe17:bf38 <name name="parse_ipv4strict_address" arity="1" /> <fsummary>Parse an IPv4 address strict.</fsummary> <desc> - <p>Parses an IPv4 address string containing four fields, i.e <b>not</b> shortened, and returns an <a href="#type-ip4_adress">ip4_address()</a>.</p> + <p>Parses an IPv4 address string containing four fields, i.e <em>not</em> shortened, and returns an <seealso marker="#type-ip4_address">ip4_address()</seealso>.</p> </desc> </func> <func> <name name="parse_ipv6_address" arity="1" /> <fsummary>Parse an IPv6 address</fsummary> <desc> - <p>Parses an IPv6 address string and returns an <a href="#type-ip6_address">ip6_address()</a>. + <p>Parses an IPv6 address string and returns an <seealso marker="#type-ip6_address">ip6_address()</seealso>. If an IPv4 address string is passed, an IPv4-mapped IPv6 address is returned.</p> </desc> </func> @@ -409,22 +409,22 @@ fe80::204:acff:fe17:bf38 <name name="parse_ipv6strict_address" arity="1" /> <fsummary>Parse an IPv6 address strict.</fsummary> <desc> - <p>Parses an IPv6 address string and returns an <a href="#type-ip6_address">ip6_address()</a>. - Does <b>not</b> accept IPv4 adresses.</p> + <p>Parses an IPv6 address string and returns an <seealso marker="#type-ip6_address">ip6_address()</seealso>. + Does <em>not</em> accept IPv4 adresses.</p> </desc> </func> <func> <name name="parse_address" arity="1" /> <fsummary>Parse an IPv4 or IPv6 address.</fsummary> <desc> - <p>Parses an IPv4 or IPv6 address string and returns an <a href="#type-ip4_address">ip4_address()</a> or <a href="#type-ip6_address">ip6_address()</a>. Accepts a shortened IPv4 address string.</p> + <p>Parses an IPv4 or IPv6 address string and returns an <seealso marker="#type-ip4_address">ip4_address()</seealso> or <seealso marker="#type-ip6_address">ip6_address()</seealso>. Accepts a shortened IPv4 address string.</p> </desc> </func> <func> <name name="parse_strict_address" arity="1" /> <fsummary>Parse an IPv4 or IPv6 address strict.</fsummary> <desc> - <p>Parses an IPv4 or IPv6 address string and returns an <a href="#type-ip4_address">ip4_address()</a> or <a href="#type-ip6_adress">ip6_address()</a>. Does <b>not</b> accept a shortened IPv4 address string.</p> + <p>Parses an IPv4 or IPv6 address string and returns an <seealso marker="#type-ip4_address">ip4_address()</seealso> or <seealso marker="#type-ip6_address">ip6_address()</seealso>. Does <em>not</em> accept a shortened IPv4 address string.</p> </desc> </func> <func> @@ -862,10 +862,10 @@ fe80::204:acff:fe17:bf38 <c>CAP_SYS_ADMIN</c> according to the documentation for setns(2). However, during testing also <c>CAP_SYS_PTRACE</c> and <c>CAP_DAC_READ_SEARCH</c> has proven to be necessary. - Example:<code> + Example:</p><code> setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp </code> - Note also that the filesystem containing the virtual machine + <p>Note also that the filesystem containing the virtual machine executable (<c>beam.smp</c> in the example above) has to be local, mounted without the <c>nosetuid</c> flag, support extended attributes and that @@ -981,6 +981,11 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp indicated length are accepted and not considered invalid due to internal buffer limitations.</p> </item> + <tag><c>{line_delimiter, Char}</c>(TCP/IP sockets)</tag> + <item> + <p>Sets the line delimiting character for line oriented protocols + (<c>line</c>). Default value is <c>$\n</c>.</p> + </item> <tag><c>{priority, Priority}</c></tag> <item> <p>Set the protocol-defined priority for all packets to be sent diff --git a/lib/kernel/doc/src/inet_res.xml b/lib/kernel/doc/src/inet_res.xml index 6a2c9b1955..851a36aba9 100644 --- a/lib/kernel/doc/src/inet_res.xml +++ b/lib/kernel/doc/src/inet_res.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2009</year><year>2013</year> + <year>2009</year><year>2015</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -77,8 +77,11 @@ query is tried for the <c>alt_nameservers</c>.</p> </section> + <section> + <title>Resolver Types</title> + <p>The following data types concern the resolver:</p> + </section> <datatypes> - <p>Resolver types:</p> <datatype> <name name="res_option"/> </datatype> @@ -88,8 +91,13 @@ <datatype> <name name="res_error"/> </datatype> - - <p><marker id="dns_types"/>DNS types:</p> + </datatypes> + <section> + <title>DNS Types</title> + <p><marker id="dns_types"/> + The following data types concern the DNS client:</p> + </section> + <datatypes> <datatype> <name name="dns_name"/> <desc><p>A string with no adjacent dots.</p></desc> @@ -106,7 +114,7 @@ <p>This is the start of a hiearchy of opaque data structures that can be examined with access functions in inet_dns that return lists of {Field,Value} tuples. The arity 2 functions - just return the value for a given field. + just return the value for a given field.</p> <pre> dns_msg() = DnsMsg inet_dns:msg(DnsMsg) -> @@ -154,18 +162,19 @@ dns_rr() = DnsRr | {version, integer()} | {z, integer()} | {data, dns_data()} ] - inet_dns:rr(DnsRr, Field) -> Value + inet_dns:rr(DnsRr, Field) -> Value</pre> -There is an info function for the types above: +<p>There is an info function for the types above:</p> +<pre> inet_dns:record_type(dns_msg()) -> msg; inet_dns:record_type(dns_header()) -> header; inet_dns:record_type(dns_query()) -> dns_query; inet_dns:record_type(dns_rr()) -> rr; -inet_dns:record_type(_) -> undefined. +inet_dns:record_type(_) -> undefined.</pre> -So; inet_dns:(inet_dns:record_type(X))(X) will convert -any of these data structures into a {Field,Value} list.</pre></p> +<p>So; inet_dns:(inet_dns:record_type(X))(X) will convert +any of these data structures into a {Field,Value} list.</p> </desc> </datatype> <datatype> @@ -272,7 +281,7 @@ any of these data structures into a {Field,Value} list.</pre></p> <p>Resolve a DNS record of the given type and class for the given name. The returned <c>dns_msg()</c> can be examined using access functions in <c>inet_db</c> as described - in <seealso marker="#dns_types">DNS types</seealso>. + in <seealso marker="#dns_types">DNS Types</seealso>. </p><p> If <c><anno>Name</anno></c> is an <c>ip_address()</c>, the domain name to query for is generated as the standard reverse diff --git a/lib/kernel/doc/src/net_adm.xml b/lib/kernel/doc/src/net_adm.xml index 1072be44a5..4ef9d361f6 100644 --- a/lib/kernel/doc/src/net_adm.xml +++ b/lib/kernel/doc/src/net_adm.xml @@ -89,8 +89,8 @@ <func> <name name="world" arity="0"/> <name name="world" arity="1"/> - <type name="verbosity"/> <fsummary>Lookup and connect to all nodes at all hosts in <c>.hosts.erlang</c></fsummary> + <type name="verbosity"/> <desc> <p>This function calls <c>names(Host)</c> for all hosts which are specified in the Erlang host file <c>.hosts.erlang</c>, @@ -110,8 +110,8 @@ <func> <name name="world_list" arity="1"/> <name name="world_list" arity="2"/> - <type name="verbosity"/> <fsummary>Lookup and connect to all nodes at specified hosts</fsummary> + <type name="verbosity"/> <desc> <p>As <c>world/0,1</c>, but the hosts are given as argument instead of being read from <c>.hosts.erlang</c>.</p> diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index b8db22aba7..1e909cb6f2 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,32 @@ </header> <p>This document describes the changes made to the Kernel application.</p> +<section><title>Kernel 4.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>A mechanism for limiting the amount of text that the + built-in error logger events will produce has been + introduced. It is useful for limiting both the size of + log files and the CPU time used to produce them.</p> + <p>This mechanism is experimental in the sense that it + may be changed if it turns out that it does not solve the + problem it is supposed to solve. In that case, there may + be backward incompatible improvements to this + mechanism.</p> + <p>See the documentation for the config parameter + <c>error_logger_format_depth</c> in the Kernel + application for information about how to turn on this + feature.</p> + <p> + Own Id: OTP-12864</p> + </item> + </list> + </section> + +</section> + <section><title>Kernel 4.0</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -423,8 +449,7 @@ Erlang/OTP has been ported to the realtime operating system OSE. The port supports both smp and non-smp emulator. For details around the port and how to started - see the User's Guide in the <seealso - marker="ose:ose_intro">ose</seealso> application. </p> + see the User's Guide in the ose application. </p> <p> Note that not all parts of Erlang/OTP has been ported. </p> <p> @@ -1192,7 +1217,7 @@ </item> <item> <p> Fix returned error from gen_tcp:accept/1,2 when - running out of ports + running out of ports.</p> <p> The {error, enfile} return value is badly misleading and confusing for this case, since the Posix ENFILE errno @@ -1201,7 +1226,7 @@ {error, system_limit}, which is consistent with e.g. various file(3) functions. inet:format_error/1 has also been updated to support system_limit in the same manner - as file:format_error/1. (Thanks to Per Hedeland)</p></p> + as file:format_error/1. (Thanks to Per Hedeland)</p> <p> Own Id: OTP-9990</p> </item> @@ -1396,7 +1421,6 @@ Own Id: OTP-9764</p> </item> <item> - <p> <list> <item><p>Correct callback spec in application module</p></item> <item><p>Refine warning about callback specs with extra ranges</p></item> <item><p>Cleanup @@ -1407,7 +1431,7 @@ analysis</p></item> <item><p>Fix crash in Dialyzer</p></item> <item><p>Variable substitution was not generalizing any unknown variables.</p></item> - </list></p> + </list> <p> Own Id: OTP-9776</p> </item> diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml index 2d2a690fea..682d4a2eac 100644 --- a/lib/kernel/doc/src/os.xml +++ b/lib/kernel/doc/src/os.xml @@ -171,8 +171,8 @@ DirOut = os:cmd("dir"), % on Win32 platform</code> </func> <func> <name name="timestamp" arity="0"/> - <type_desc variable="Timestamp">Timestamp = {MegaSecs, Secs, MicroSecs}</type_desc> <fsummary>Current OS system time on the erlang:timestamp/0 format</fsummary> + <type_desc variable="Timestamp">Timestamp = {MegaSecs, Secs, MicroSecs}</type_desc> <desc> <p>Returns current <seealso marker="erts:time_correction#OS_System_Time">OS system time</seealso> @@ -205,7 +205,7 @@ format_utc_timestamp() -> 29 Apr 2009 9:55:30.051711 </pre> <p>OS system time can also be retreived by - <c><seealso marker="#system_time/0"><c>os:system_time/0</c></seealso></c>, + <seealso marker="#system_time/0"><c>os:system_time/0</c></seealso>, and <seealso marker="#system_time/1"><c>os:system_time/1</c></seealso>.</p> </desc> </func> diff --git a/lib/kernel/doc/src/ref_man.xml.src b/lib/kernel/doc/src/ref_man.xml.src deleted file mode 100644 index 7eb48a5f1d..0000000000 --- a/lib/kernel/doc/src/ref_man.xml.src +++ /dev/null @@ -1,68 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE application SYSTEM "application.dtd"> - -<application xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>1996</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>Kernel Reference Manual</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <description> - <p>The <em>Kernel</em> application has all the code necessary to run - the Erlang runtime system itself: file servers and code servers - and so on.</p> - </description> - <xi:include href="kernel_app.xml"/> - <xi:include href="application.xml"/> - <xi:include href="auth.xml"/> - <xi:include href="code.xml"/> - <xi:include href="disk_log.xml"/> - <xi:include href="erl_boot_server.xml"/> - <xi:include href="erl_ddll.xml"/> - <xi:include href="erl_prim_loader_stub.xml"/> - <xi:include href="erlang_stub.xml"/> - <xi:include href="error_handler.xml"/> - <xi:include href="error_logger.xml"/> - <xi:include href="file.xml"/> - <xi:include href="gen_tcp.xml"/> - <xi:include href="gen_udp.xml"/> - <xi:include href="gen_sctp.xml"/> - <xi:include href="global.xml"/> - <xi:include href="global_group.xml"/> - <xi:include href="heart.xml"/> - <xi:include href="inet.xml"/> - <xi:include href="inet_res.xml"/> - <xi:include href="init_stub.xml"/> - <xi:include href="net_adm.xml"/> - <xi:include href="net_kernel.xml"/> - <xi:include href="os.xml"/> - <xi:include href="pg2.xml"/> - <xi:include href="rpc.xml"/> - <xi:include href="seq_trace.xml"/> - <xi:include href="user.xml"/> - <xi:include href="wrap_log_reader.xml"/> - <xi:include href="zlib_stub.xml"/> - <xi:include href="app.xml"/> - <xi:include href="config.xml"/> -</application> diff --git a/lib/kernel/include/file.hrl b/lib/kernel/include/file.hrl index 7cf033f7f5..36112bb040 100644 --- a/lib/kernel/include/file.hrl +++ b/lib/kernel/include/file.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -23,37 +23,40 @@ %%-------------------------------------------------------------------------- -record(file_info, - {size :: non_neg_integer(), % Size of file in bytes. - type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink', - access :: 'read' | 'write' | 'read_write' | 'none', - atime :: file:date_time() | non_neg_integer(), + {size :: non_neg_integer() | 'undefined', % Size of file in bytes. + type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink' + | 'undefined', + access :: 'read' | 'write' | 'read_write' | 'none' | 'undefined', + atime :: file:date_time() | non_neg_integer() | 'undefined', % The local time the file was last read: % {{Year, Mon, Day}, {Hour, Min, Sec}}. % atime, ctime, mtime may also be unix epochs() - mtime :: file:date_time() | non_neg_integer(), + mtime :: file:date_time() | non_neg_integer() | 'undefined', % The local time the file was last written. - ctime :: file:date_time() | non_neg_integer(), + ctime :: file:date_time() | non_neg_integer() | 'undefined', % The interpretation of this time field % is dependent on operating system. % On Unix it is the last time the file % or the inode was changed. On Windows, % it is the creation time. - mode :: non_neg_integer(), % File permissions. On Windows, + mode :: non_neg_integer() | 'undefined', + % File permissions. On Windows, % the owner permissions will be % duplicated for group and user. - links :: non_neg_integer(), + links :: non_neg_integer() | 'undefined', % Number of links to the file (1 if the % filesystem doesn't support links). - major_device :: non_neg_integer(), + major_device :: non_neg_integer() | 'undefined', % Identifies the file system (Unix), % or the drive number (A: = 0, B: = 1) % (Windows). %% The following are Unix specific. %% They are set to zero on other operating systems. - minor_device :: non_neg_integer(), % Only valid for devices. - inode :: non_neg_integer(), % Inode number for file. - uid :: non_neg_integer(), % User id for owner. - gid :: non_neg_integer()}). % Group id for owner. + minor_device :: non_neg_integer() | 'undefined', + % Only valid for devices. + inode :: non_neg_integer() | 'undefined', % Inode number for file. + uid :: non_neg_integer() | 'undefined', % User id for owner. + gid :: non_neg_integer() | 'undefined'}). % Group id for owner. -record(file_descriptor, diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index f5450f30af..9b44021872 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1310,13 +1310,20 @@ compare_arg(_Attr, _Val, _A) -> %% -> {ok, Res, log(), Cnt} | Error do_open(A) -> - L = #log{name = A#arg.name, - filename = A#arg.file, - size = A#arg.size, - head = mk_head(A#arg.head, A#arg.format), - mode = A#arg.mode, - version = A#arg.version}, - do_open2(L, A). + #arg{type = Type, format = Format, name = Name, head = Head0, + file = FName, repair = Repair, size = Size, mode = Mode, + version = V} = A, + Head = mk_head(Head0, Format), + case do_open2(Type, Format, Name, FName, Repair, Size, Mode, Head, V) of + {ok, Ret, Extra, FormatType, NoItems} -> + L = #log{name = Name, type = Type, format = Format, + filename = FName, size = Size, + format_type = FormatType, head = Head, mode = Mode, + version = V, extra = Extra}, + {ok, Ret, L, NoItems}; + Error -> + Error + end. mk_head({head, Term}, internal) -> {ok, term_to_binary(Term)}; mk_head({head, Bytes}, external) -> {ok, check_bytes(Bytes)}; @@ -1432,57 +1439,44 @@ do_inc_wrap_file(L) -> %%----------------------------------------------------------------- %% -> {ok, Reply, log(), Cnt} | Error %% Note: the header is always written, even if the log size is too small. -do_open2(L, #arg{type = halt, format = internal, name = Name, - file = FName, repair = Repair, size = Size, mode = Mode}) -> - case catch disk_log_1:int_open(FName, Repair, Mode, L#log.head) of +do_open2(halt, internal, Name, FName, Repair, Size, Mode, Head, _V) -> + case catch disk_log_1:int_open(FName, Repair, Mode, Head) of {ok, {_Alloc, FdC, {NoItems, _NoBytes}, FileSize}} -> Halt = #halt{fdc = FdC, curB = FileSize, size = Size}, - {ok, {ok, Name}, L#log{format_type = halt_int, extra = Halt}, - NoItems}; + {ok, {ok, Name}, Halt, halt_int, NoItems}; {repaired, FdC, Rec, Bad, FileSize} -> Halt = #halt{fdc = FdC, curB = FileSize, size = Size}, {ok, {repaired, Name, {recovered, Rec}, {badbytes, Bad}}, - L#log{format_type = halt_int, extra = Halt}, - Rec}; + Halt, halt_int, Rec}; Error -> Error end; -do_open2(L, #arg{type = wrap, format = internal, size = {MaxB, MaxF}, - name = Name, repair = Repair, file = FName, mode = Mode, - version = V}) -> +do_open2(wrap, internal, Name, FName, Repair, Size, Mode, Head, V) -> + {MaxB, MaxF} = Size, case catch - disk_log_1:mf_int_open(FName, MaxB, MaxF, Repair, Mode, L#log.head, V) of + disk_log_1:mf_int_open(FName, MaxB, MaxF, Repair, Mode, Head, V) of {ok, Handle, Cnt} -> - {ok, {ok, Name}, L#log{type = wrap, - format_type = wrap_int, - extra = Handle}, Cnt}; + {ok, {ok, Name}, Handle, wrap_int, Cnt}; {repaired, Handle, Rec, Bad, Cnt} -> {ok, {repaired, Name, {recovered, Rec}, {badbytes, Bad}}, - L#log{type = wrap, format_type = wrap_int, extra = Handle}, Cnt}; + Handle, wrap_int, Cnt}; Error -> Error end; -do_open2(L, #arg{type = halt, format = external, file = FName, name = Name, - size = Size, repair = Repair, mode = Mode}) -> - case catch disk_log_1:ext_open(FName, Repair, Mode, L#log.head) of +do_open2(halt, external, Name, FName, Repair, Size, Mode, Head, _V) -> + case catch disk_log_1:ext_open(FName, Repair, Mode, Head) of {ok, {_Alloc, FdC, {NoItems, _NoBytes}, FileSize}} -> Halt = #halt{fdc = FdC, curB = FileSize, size = Size}, - {ok, {ok, Name}, - L#log{format_type = halt_ext, format = external, extra = Halt}, - NoItems}; + {ok, {ok, Name}, Halt, halt_ext, NoItems}; Error -> Error end; -do_open2(L, #arg{type = wrap, format = external, size = {MaxB, MaxF}, - name = Name, file = FName, repair = Repair, mode = Mode, - version = V}) -> +do_open2(wrap, external, Name, FName, Repair, Size, Mode, Head, V) -> + {MaxB, MaxF} = Size, case catch - disk_log_1:mf_ext_open(FName, MaxB, MaxF, Repair, Mode, L#log.head, V) of + disk_log_1:mf_ext_open(FName, MaxB, MaxF, Repair, Mode, Head, V) of {ok, Handle, Cnt} -> - {ok, {ok, Name}, L#log{type = wrap, - format_type = wrap_ext, - extra = Handle, - format = external}, Cnt}; + {ok, {ok, Name}, Handle, wrap_ext, Cnt}; Error -> Error end. diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index 6c0aea070f..3262d979ee 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -152,8 +152,8 @@ users = 0 :: non_neg_integer(), %% non-linked users filename :: file:filename(), %% real name of the file owners = [] :: [{pid(), boolean()}],%% [{pid, notify}] - type = halt :: dlog_type(), - format = internal :: dlog_format(), + type :: dlog_type(), + format :: dlog_format(), format_type :: dlog_format_type(), head = none, %% none | {head, H} | {M,F,A} %% called when wraplog wraps diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index 2be1efaf24..dcabeb5e49 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2014. All Rights Reserved. +%% Copyright Ericsson AB 1996-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -459,17 +459,17 @@ init([]) -> no_trace end, + Ca = case init:get_argument(connect_all) of + {ok, [["false"]]} -> + false; + _ -> + true + end, S = #state{the_locker = start_the_locker(DoTrace), trace = T0, - the_registrar = start_the_registrar()}, - S1 = trace_message(S, {init, node()}, []), - - case init:get_argument(connect_all) of - {ok, [["false"]]} -> - {ok, S1#state{connect_all = false}}; - _ -> - {ok, S1#state{connect_all = true}} - end. + the_registrar = start_the_registrar(), + connect_all = Ca}, + {ok, trace_message(S, {init, node()}, [])}. %%----------------------------------------------------------------- %% Connection algorithm diff --git a/lib/kernel/src/global_group.erl b/lib/kernel/src/global_group.erl index 848df13c39..e71f83f9d3 100644 --- a/lib/kernel/src/global_group.erl +++ b/lib/kernel/src/global_group.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. +%% Copyright Ericsson AB 1998-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -273,7 +273,7 @@ init([]) -> {ok, #state{publish_type = PT, group_publish_type = PubTpGrp, sync_state = synced, group_name = DefGroupName, no_contact = lists:sort(DefNodes), - other_grps = DefOther}} + other_grps = DefOther, connect_all = Ca}} end. diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index da7f04089d..855c6377a3 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -671,7 +671,7 @@ stats() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% connect_options() -> [tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, - header, active, packet, packet_size, buffer, mode, deliver, + header, active, packet, packet_size, buffer, mode, deliver, line_delimiter, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw, show_econnreset]. @@ -721,6 +721,8 @@ con_opt([Opt | Opts], #connect_opts{} = R, As) -> {active,N} when is_integer(N), N < 32768, N >= -32768 -> NOpts = lists:keydelete(active, 1, R#connect_opts.opts), con_opt(Opts, R#connect_opts { opts = [{active,N}|NOpts] }, As); + {line_delimiter,C} when is_integer(C), C >= 0, C =< 255 -> + con_add(line_delimiter, C, R, Opts, As); {Name,Val} when is_atom(Name) -> con_add(Name, Val, R, Opts, As); _ -> {error, badarg} end; diff --git a/lib/kernel/src/inet6_tcp.erl b/lib/kernel/src/inet6_tcp.erl index 2ea017285c..1978307b3c 100644 --- a/lib/kernel/src/inet6_tcp.erl +++ b/lib/kernel/src/inet6_tcp.erl @@ -25,10 +25,29 @@ -export([controlling_process/2]). -export([fdopen/2]). +-export([family/0, mask/2, parse_address/1]). -export([getserv/1, getaddr/1, getaddr/2, getaddrs/1, getaddrs/2]). -include("inet_int.hrl"). +%% my address family +family() -> inet6. + +%% Apply netmask on address +mask({M1,M2,M3,M4,M5,M6,M7,M8}, {IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8}) -> + {M1 band IP1, + M2 band IP2, + M3 band IP3, + M4 band IP4, + M5 band IP5, + M6 band IP6, + M7 band IP7, + M8 band IP8 }. + +%% Parse address string +parse_address(Host) -> + inet_parse:ipv6strict_address(Host). + %% inet_tcp port lookup getserv(Port) when is_integer(Port) -> {ok, Port}; getserv(Name) when is_atom(Name) -> inet:getservbyname(Name,tcp). diff --git a/lib/kernel/src/inet6_tcp_dist.erl b/lib/kernel/src/inet6_tcp_dist.erl index a74a4916ba..3ab7f269bb 100644 --- a/lib/kernel/src/inet6_tcp_dist.erl +++ b/lib/kernel/src/inet6_tcp_dist.erl @@ -24,28 +24,6 @@ -export([listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1, is_node_name/1]). -%% internal exports - --export([accept_loop/2,do_accept/6,do_setup/6, getstat/1,tick/1]). - --import(error_logger,[error_msg/2]). - --include("net_address.hrl"). - - - --define(to_port(Socket, Data, Opts), - case inet6_tcp:send(Socket, Data, Opts) of - {error, closed} -> - self() ! {tcp_closed, Socket}, - {error, closed}; - R -> - R - end). - - --include("dist.hrl"). --include("dist_util.hrl"). %% ------------------------------------------------------------ %% Select this protocol based on node name @@ -53,14 +31,7 @@ %% ------------------------------------------------------------ select(Node) -> - case split_node(atom_to_list(Node), $@, []) of - [_, Host] -> - case inet:getaddr(Host,inet6) of - {ok,_} -> true; - _ -> false - end; - _ -> false - end. + inet_tcp_dist:gen_select(inet6_tcp, Node). %% ------------------------------------------------------------ %% Create the listen socket, i.e. the port that this erlang @@ -68,59 +39,14 @@ select(Node) -> %% ------------------------------------------------------------ listen(Name) -> - case inet6_tcp:listen(0, [{active, false}, {packet,2}]) of - {ok, Socket} -> - TcpAddress = get_tcp_address(Socket), - {_,Port} = TcpAddress#net_address.address, - case erl_epmd:register_node(Name, Port) of - {ok, Creation} -> - {ok, {Socket, TcpAddress, Creation}}; - Error -> - Error - end; - Error -> - Error - end. + inet_tcp_dist:gen_listen(inet6_tcp, Name). %% ------------------------------------------------------------ %% Accepts new connection attempts from other Erlang nodes. %% ------------------------------------------------------------ accept(Listen) -> - spawn_opt(?MODULE, accept_loop, [self(), Listen], [link, {priority, max}]). - -accept_loop(Kernel, Listen) -> - case inet6_tcp:accept(Listen) of - {ok, Socket} -> - Kernel ! {accept,self(),Socket,inet6,tcp}, - _ = controller(Kernel, Socket), - accept_loop(Kernel, Listen); - Error -> - exit(Error) - end. - -controller(Kernel, Socket) -> - receive - {Kernel, controller, Pid} -> - flush_controller(Pid, Socket), - inet6_tcp:controlling_process(Socket, Pid), - flush_controller(Pid, Socket), - Pid ! {self(), controller}; - {Kernel, unsupported_protocol} -> - exit(unsupported_protocol) - end. - -flush_controller(Pid, Socket) -> - receive - {tcp, Socket, Data} -> - Pid ! {tcp, Socket, Data}, - flush_controller(Pid, Socket); - {tcp_closed, Socket} -> - Pid ! {tcp_closed, Socket}, - flush_controller(Pid, Socket) - after 0 -> - ok - end. + inet_tcp_dist:gen_accept(inet6_tcp, Listen). %% ------------------------------------------------------------ %% Accepts a new connection attempt from another Erlang node. @@ -128,85 +54,7 @@ flush_controller(Pid, Socket) -> %% ------------------------------------------------------------ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) -> - spawn_opt(?MODULE, do_accept, - [self(), AcceptPid, Socket, MyNode, Allowed, SetupTime], - [link, {priority, max}]). - -do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> - receive - {AcceptPid, controller} -> - Timer = dist_util:start_timer(SetupTime), - case check_ip(Socket) of - true -> - HSData = #hs_data{ - kernel_pid = Kernel, - this_node = MyNode, - socket = Socket, - timer = Timer, - this_flags = 0, - allowed = Allowed, - f_send = fun(S,D) -> inet6_tcp:send(S,D) end, - f_recv = fun(S,N,T) -> inet6_tcp:recv(S,N,T) - end, - f_setopts_pre_nodeup = - fun(S) -> - inet:setopts(S, - [{active, false}, - {packet, 4}, - nodelay()]) - end, - f_setopts_post_nodeup = - fun(S) -> - inet:setopts(S, - [{active, true}, - {deliver, port}, - {packet, 4}, - nodelay()]) - end, - f_getll = fun(S) -> - inet:getll(S) - end, - f_address = fun get_remote_id/2, - mf_tick = fun ?MODULE:tick/1, - mf_getstat = fun ?MODULE:getstat/1 - }, - dist_util:handshake_other_started(HSData); - {false,IP} -> - error_msg("** Connection attempt from " - "disallowed IP ~w ** ~n", [IP]), - ?shutdown(no_node) - end - end. - - -%% we may not always want the nodelay behaviour -%% for performance reasons - -nodelay() -> - case application:get_env(kernel, dist_nodelay) of - undefined -> - {nodelay, true}; - {ok, true} -> - {nodelay, true}; - {ok, false} -> - {nodelay, false}; - _ -> - {nodelay, true} - end. - - -%% ------------------------------------------------------------ -%% Get remote information about a Socket. -%% ------------------------------------------------------------ - -get_remote_id(Socket, Node) -> - {ok, Address} = inet:peername(Socket), - [_, Host] = split_node(atom_to_list(Node), $@, []), - #net_address { - address = Address, - host = Host, - protocol = tcp, - family = inet6 }. + inet_tcp_dist:gen_accept_connection(inet6_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime). %% ------------------------------------------------------------ %% Setup a new connection to another Erlang node. @@ -214,214 +62,13 @@ get_remote_id(Socket, Node) -> %% ------------------------------------------------------------ setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> - spawn_opt(?MODULE, do_setup, - [self(), Node, Type, MyNode, LongOrShortNames, SetupTime], - [link, {priority, max}]). - -do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> - ?trace("~p~n",[{?MODULE,self(),setup,Node}]), - [Name, Address] = splitnode(Node, LongOrShortNames), - case inet:getaddr(Address, inet6) of - {ok, Ip} -> - Timer = dist_util:start_timer(SetupTime), - case erl_epmd:port_please(Name, Ip) of - {port, TcpPort, Version} -> - ?trace("port_please(~p) -> version ~p~n", - [Node,Version]), - dist_util:reset_timer(Timer), - case inet6_tcp:connect(Ip, TcpPort, - [{active, false}, - {packet,2}]) of - {ok, Socket} -> - HSData = #hs_data{ - kernel_pid = Kernel, - other_node = Node, - this_node = MyNode, - socket = Socket, - timer = Timer, - this_flags = 0, - other_version = Version, - f_send = fun inet6_tcp:send/2, - f_recv = fun inet6_tcp:recv/3, - f_setopts_pre_nodeup = - fun(S) -> - inet:setopts - (S, - [{active, false}, - {packet, 4}, - nodelay()]) - end, - f_setopts_post_nodeup = - fun(S) -> - inet:setopts - (S, - [{active, true}, - {deliver, port}, - {packet, 4}, - nodelay()]) - end, - f_getll = fun inet:getll/1, - f_address = - fun(_,_) -> - #net_address { - address = {Ip,TcpPort}, - host = Address, - protocol = tcp, - family = inet6} - end, - mf_tick = fun ?MODULE:tick/1, - mf_getstat = fun ?MODULE:getstat/1, - request_type = Type - }, - dist_util:handshake_we_started(HSData); - _ -> - %% Other Node may have closed since - %% port_please ! - ?trace("other node (~p) " - "closed since port_please.~n", - [Node]), - ?shutdown(Node) - end; - _ -> - ?trace("port_please (~p) " - "failed.~n", [Node]), - ?shutdown(Node) - end; - __Other -> - ?trace("inet_getaddr(~p) " - "failed (~p).~n", [Node,__Other]), - ?shutdown(Node) - end. + inet_tcp_dist:gen_setup(inet6_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime). %% %% Close a socket. %% close(Socket) -> inet6_tcp:close(Socket). - - -%% If Node is illegal terminate the connection setup!! -splitnode(Node, LongOrShortNames) -> - case split_node(atom_to_list(Node), $@, []) of - [Name|Tail] when Tail =/= [] -> - Host = lists:append(Tail), - case split_node(Host, $., []) of - [_] when LongOrShortNames =:= longnames -> - case inet_parse:ipv6strict_address(Host) of - {ok, _} -> - [Name, Host]; - _ -> - error_msg("** System running to use " - "fully qualified " - "hostnames **~n" - "** Hostname ~s is illegal **~n", - [Host]), - ?shutdown(Node) - end; - L when length(L) > 1, LongOrShortNames =:= shortnames -> - error_msg("** System NOT running to use fully qualified " - "hostnames **~n" - "** Hostname ~s is illegal **~n", - [Host]), - ?shutdown(Node); - _ -> - [Name, Host] - end; - [_] -> - error_msg("** Nodename ~p illegal, no '@' character **~n", - [Node]), - ?shutdown(Node); - _ -> - error_msg("** Nodename ~p illegal **~n", [Node]), - ?shutdown(Node) - end. - -split_node([Chr|T], Chr, Ack) -> [lists:reverse(Ack)|split_node(T, Chr, [])]; -split_node([H|T], Chr, Ack) -> split_node(T, Chr, [H|Ack]); -split_node([], _, Ack) -> [lists:reverse(Ack)]. - -%% ------------------------------------------------------------ -%% Fetch local information about a Socket. -%% ------------------------------------------------------------ -get_tcp_address(Socket) -> - {ok, Address} = inet:sockname(Socket), - {ok, Host} = inet:gethostname(), - #net_address { - address = Address, - host = Host, - protocol = tcp, - family = inet6 - }. - -%% ------------------------------------------------------------ -%% Do only accept new connection attempts from nodes at our -%% own LAN, if the check_ip environment parameter is true. -%% ------------------------------------------------------------ -check_ip(Socket) -> - case application:get_env(check_ip) of - {ok, true} -> - case get_ifs(Socket) of - {ok, IFs, IP} -> - check_ip(IFs, IP); - _ -> - ?shutdown(no_node) - end; - _ -> - true - end. - -get_ifs(Socket) -> - case inet:peername(Socket) of - {ok, {IP, _}} -> - case inet:getif(Socket) of - {ok, IFs} -> {ok, IFs, IP}; - Error -> Error - end; - Error -> - Error - end. - -check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) -> - case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of - {M, M} -> true; - _ -> check_ip(IFs, PeerIP) - end; -check_ip([], PeerIP) -> - {false, PeerIP}. -mask({M1,M2,M3,M4,M5,M6,M7,M8}, {IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8}) -> - {M1 band IP1, - M2 band IP2, - M3 band IP3, - M4 band IP4, - M5 band IP5, - M6 band IP6, - M7 band IP7, - M8 band IP8 }. - is_node_name(Node) when is_atom(Node) -> - case split_node(atom_to_list(Node), $@, []) of - [_,_Host] -> true; - _ -> false - end; -is_node_name(_Node) -> - false. -tick(Sock) -> - ?to_port(Sock,[],[force]). -getstat(Socket) -> - case inet:getstat(Socket, [recv_cnt, send_cnt, send_pend]) of - {ok, Stat} -> - split_stat(Stat,0,0,0); - Error -> - Error - end. - -split_stat([{recv_cnt, R}|Stat], _, W, P) -> - split_stat(Stat, R, W, P); -split_stat([{send_cnt, W}|Stat], R, _, P) -> - split_stat(Stat, R, W, P); -split_stat([{send_pend, P}|Stat], R, W, _) -> - split_stat(Stat, R, W, P); -split_stat([], R, W, P) -> - {ok, R, W, P}. - + inet_tcp_dist:is_node_name(Node). diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl index 803fae846e..a0d5344f11 100644 --- a/lib/kernel/src/inet_config.erl +++ b/lib/kernel/src/inet_config.erl @@ -188,9 +188,6 @@ do_load_resolv({win32,Type}, longnames) -> win32_load_from_registry(Type), inet_db:set_lookup([native]); -do_load_resolv({ose,_}, _) -> - inet_db:set_lookup([file]); - do_load_resolv(_, _) -> inet_db:set_lookup([native]). diff --git a/lib/kernel/src/inet_dns_record_adts.pl b/lib/kernel/src/inet_dns_record_adts.pl index 657d2b9d35..6d719d836e 100644 --- a/lib/kernel/src/inet_dns_record_adts.pl +++ b/lib/kernel/src/inet_dns_record_adts.pl @@ -57,7 +57,8 @@ while(<DATA>) { $" = ','; $\ = "\n"; -while( my ($Name, $r) = each(%Names)) { +foreach my $Name (sort keys %Names) { + my $r = $Names{$Name}; # Create substitutions for this Name my ($Record, @Fields) = @{ $r }; my @FieldMatchValues; @@ -110,7 +111,8 @@ while( my ($Name, $r) = each(%Names)) { for my $i ( 0 .. $#INDEX ) { my $line = $INDEX[$i]; if ($line =~ s/^[*]//) { - while( my ($Name, $r) = each(%Names)) { + foreach my $Name (sort keys %Names) { + my $r = $Names{$Name}; my ($Record) = @{ $r }; $_ = $line; s/Name\b/$Name/g; diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl index bfe4c9ec8c..e7c6cf8ae2 100644 --- a/lib/kernel/src/inet_int.hrl +++ b/lib/kernel/src/inet_int.hrl @@ -149,6 +149,7 @@ -define(INET_LOPT_MSGQ_LOWTRMRK, 37). -define(INET_LOPT_NETNS, 38). -define(INET_LOPT_TCP_SHOW_ECONNRESET, 39). +-define(INET_LOPT_LINE_DELIM, 40). % Specific SCTP options: separate range: -define(SCTP_OPT_RTOINFO, 100). -define(SCTP_OPT_ASSOCINFO, 101). diff --git a/lib/kernel/src/inet_tcp.erl b/lib/kernel/src/inet_tcp.erl index b5c758c02c..f551af9709 100644 --- a/lib/kernel/src/inet_tcp.erl +++ b/lib/kernel/src/inet_tcp.erl @@ -27,11 +27,25 @@ -export([controlling_process/2]). -export([fdopen/2]). +-export([family/0, mask/2, parse_address/1]). -export([getserv/1, getaddr/1, getaddr/2, getaddrs/1, getaddrs/2]). - -include("inet_int.hrl"). +%% my address family +family() -> inet. + +%% Apply netmask on address +mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) -> + {M1 band IP1, + M2 band IP2, + M3 band IP3, + M4 band IP4}. + +%% Parse address string +parse_address(Host) -> + inet_parse:ipv4strict_address(Host). + %% inet_tcp port lookup getserv(Port) when is_integer(Port) -> {ok, Port}; getserv(Name) when is_atom(Name) -> inet:getservbyname(Name,tcp). diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl index 1bdc1c9ed8..64b28bb49b 100644 --- a/lib/kernel/src/inet_tcp_dist.erl +++ b/lib/kernel/src/inet_tcp_dist.erl @@ -24,9 +24,13 @@ -export([listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1, is_node_name/1]). +%% Generalized dist API +-export([gen_listen/2, gen_accept/2, gen_accept_connection/6, + gen_setup/6, gen_select/2]). + %% internal exports --export([accept_loop/2,do_accept/6,do_setup/6,getstat/1,tick/1]). +-export([accept_loop/3,do_accept/7,do_setup/7,getstat/1]). -import(error_logger,[error_msg/2]). @@ -34,15 +38,6 @@ --define(to_port(Socket, Data, Opts), - case inet_tcp:send(Socket, Data, Opts) of - {error, closed} -> - self() ! {tcp_closed, Socket}, - {error, closed}; - R -> - R - end). - -include("dist.hrl"). -include("dist_util.hrl"). @@ -53,8 +48,15 @@ %% ------------------------------------------------------------ select(Node) -> + gen_select(inet_tcp, Node). + +gen_select(Driver, Node) -> case split_node(atom_to_list(Node), $@, []) of - [_,_Host] -> true; + [_, Host] -> + case inet:getaddr(Host, Driver:family()) of + {ok,_} -> true; + _ -> false + end; _ -> false end. @@ -64,9 +66,12 @@ select(Node) -> %% ------------------------------------------------------------ listen(Name) -> - case do_listen([{active, false}, {packet,2}, {reuseaddr, true}]) of + gen_listen(inet_tcp, Name). + +gen_listen(Driver, Name) -> + case do_listen(Driver, [{active, false}, {packet,2}, {reuseaddr, true}]) of {ok, Socket} -> - TcpAddress = get_tcp_address(Socket), + TcpAddress = get_tcp_address(Driver, Socket), {_,Port} = TcpAddress#net_address.address, case erl_epmd:register_node(Name, Port) of {ok, Creation} -> @@ -78,7 +83,7 @@ listen(Name) -> Error end. -do_listen(Options) -> +do_listen(Driver, Options) -> {First,Last} = case application:get_env(kernel,inet_dist_listen_min) of {ok,N} when is_integer(N) -> case application:get_env(kernel, @@ -91,14 +96,14 @@ do_listen(Options) -> _ -> {0,0} end, - do_listen(First, Last, listen_options([{backlog,128}|Options])). + do_listen(Driver, First, Last, listen_options([{backlog,128}|Options])). -do_listen(First,Last,_) when First > Last -> +do_listen(_Driver, First,Last,_) when First > Last -> {error,eaddrinuse}; -do_listen(First,Last,Options) -> - case inet_tcp:listen(First, Options) of +do_listen(Driver, First,Last,Options) -> + case Driver:listen(First, Options) of {error, eaddrinuse} -> - do_listen(First+1,Last,Options); + do_listen(Driver, First+1,Last,Options); Other -> Other end. @@ -124,23 +129,26 @@ listen_options(Opts0) -> %% ------------------------------------------------------------ accept(Listen) -> - spawn_opt(?MODULE, accept_loop, [self(), Listen], [link, {priority, max}]). + gen_accept(inet_tcp, Listen). -accept_loop(Kernel, Listen) -> - case inet_tcp:accept(Listen) of +gen_accept(Driver, Listen) -> + spawn_opt(?MODULE, accept_loop, [Driver, self(), Listen], [link, {priority, max}]). + +accept_loop(Driver, Kernel, Listen) -> + case Driver:accept(Listen) of {ok, Socket} -> - Kernel ! {accept,self(),Socket,inet,tcp}, - _ = controller(Kernel, Socket), - accept_loop(Kernel, Listen); + Kernel ! {accept,self(),Socket,Driver:family(),tcp}, + _ = controller(Driver, Kernel, Socket), + accept_loop(Driver, Kernel, Listen); Error -> exit(Error) end. -controller(Kernel, Socket) -> +controller(Driver, Kernel, Socket) -> receive {Kernel, controller, Pid} -> flush_controller(Pid, Socket), - inet_tcp:controlling_process(Socket, Pid), + Driver:controlling_process(Socket, Pid), flush_controller(Pid, Socket), Pid ! {self(), controller}; {Kernel, unsupported_protocol} -> @@ -165,15 +173,18 @@ flush_controller(Pid, Socket) -> %% ------------------------------------------------------------ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) -> + gen_accept_connection(inet_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime). + +gen_accept_connection(Driver, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> spawn_opt(?MODULE, do_accept, - [self(), AcceptPid, Socket, MyNode, Allowed, SetupTime], + [Driver, self(), AcceptPid, Socket, MyNode, Allowed, SetupTime], [link, {priority, max}]). -do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> +do_accept(Driver, Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> receive {AcceptPid, controller} -> Timer = dist_util:start_timer(SetupTime), - case check_ip(Socket) of + case check_ip(Driver, Socket) of true -> HSData = #hs_data{ kernel_pid = Kernel, @@ -182,9 +193,8 @@ do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> timer = Timer, this_flags = 0, allowed = Allowed, - f_send = fun(S,D) -> inet_tcp:send(S,D) end, - f_recv = fun(S,N,T) -> inet_tcp:recv(S,N,T) - end, + f_send = fun Driver:send/2, + f_recv = fun Driver:recv/3, f_setopts_pre_nodeup = fun(S) -> inet:setopts(S, @@ -203,8 +213,8 @@ do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> f_getll = fun(S) -> inet:getll(S) end, - f_address = fun get_remote_id/2, - mf_tick = fun ?MODULE:tick/1, + f_address = fun(S, Node) -> get_remote_id(Driver, S, Node) end, + mf_tick = fun(S) -> tick(Driver, S) end, mf_getstat = fun ?MODULE:getstat/1 }, dist_util:handshake_other_started(HSData); @@ -235,13 +245,13 @@ nodelay() -> %% ------------------------------------------------------------ %% Get remote information about a Socket. %% ------------------------------------------------------------ -get_remote_id(Socket, Node) -> +get_remote_id(Driver, Socket, Node) -> case inet:peername(Socket) of {ok,Address} -> case split_node(atom_to_list(Node), $@, []) of [_,Host] -> #net_address{address=Address,host=Host, - protocol=tcp,family=inet}; + protocol=tcp,family=Driver:family()}; _ -> %% No '@' or more than one '@' in node name. ?shutdown(no_node) @@ -256,14 +266,18 @@ get_remote_id(Socket, Node) -> %% ------------------------------------------------------------ setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> + gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime). + +gen_setup(Driver, Node, Type, MyNode, LongOrShortNames, SetupTime) -> spawn_opt(?MODULE, do_setup, - [self(), Node, Type, MyNode, LongOrShortNames, SetupTime], + [Driver, self(), Node, Type, MyNode, LongOrShortNames, SetupTime], [link, {priority, max}]). -do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> +do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> ?trace("~p~n",[{inet_tcp_dist,self(),setup,Node}]), - [Name, Address] = splitnode(Node, LongOrShortNames), - case inet:getaddr(Address, inet) of + [Name, Address] = splitnode(Driver, Node, LongOrShortNames), + AddressFamily = Driver:family(), + case inet:getaddr(Address, AddressFamily) of {ok, Ip} -> Timer = dist_util:start_timer(SetupTime), case erl_epmd:port_please(Name, Ip) of @@ -272,7 +286,7 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> [Node,Version]), dist_util:reset_timer(Timer), case - inet_tcp:connect( + Driver:connect( Ip, TcpPort, connect_options([{active, false}, {packet, 2}])) of @@ -285,8 +299,8 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> timer = Timer, this_flags = 0, other_version = Version, - f_send = fun inet_tcp:send/2, - f_recv = fun inet_tcp:recv/3, + f_send = fun Driver:send/2, + f_recv = fun Driver:recv/3, f_setopts_pre_nodeup = fun(S) -> inet:setopts @@ -311,9 +325,9 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> address = {Ip,TcpPort}, host = Address, protocol = tcp, - family = inet} + family = AddressFamily} end, - mf_tick = fun ?MODULE:tick/1, + mf_tick = fun(S) -> tick(Driver, S) end, mf_getstat = fun ?MODULE:getstat/1, request_type = Type }, @@ -353,18 +367,23 @@ close(Socket) -> %% If Node is illegal terminate the connection setup!! -splitnode(Node, LongOrShortNames) -> +splitnode(Driver, Node, LongOrShortNames) -> case split_node(atom_to_list(Node), $@, []) of [Name|Tail] when Tail =/= [] -> Host = lists:append(Tail), case split_node(Host, $., []) of [_] when LongOrShortNames =:= longnames -> - error_msg("** System running to use " - "fully qualified " - "hostnames **~n" - "** Hostname ~s is illegal **~n", - [Host]), - ?shutdown(Node); + case Driver:parse_address(Host) of + {ok, _} -> + [Name, Host]; + _ -> + error_msg("** System running to use " + "fully qualified " + "hostnames **~n" + "** Hostname ~s is illegal **~n", + [Host]), + ?shutdown(Node) + end; L when length(L) > 1, LongOrShortNames =:= shortnames -> error_msg("** System NOT running to use fully qualified " "hostnames **~n" @@ -390,26 +409,26 @@ split_node([], _, Ack) -> [lists:reverse(Ack)]. %% ------------------------------------------------------------ %% Fetch local information about a Socket. %% ------------------------------------------------------------ -get_tcp_address(Socket) -> +get_tcp_address(Driver, Socket) -> {ok, Address} = inet:sockname(Socket), {ok, Host} = inet:gethostname(), #net_address { address = Address, host = Host, protocol = tcp, - family = inet + family = Driver:family() }. %% ------------------------------------------------------------ %% Do only accept new connection attempts from nodes at our %% own LAN, if the check_ip environment parameter is true. %% ------------------------------------------------------------ -check_ip(Socket) -> +check_ip(Driver, Socket) -> case application:get_env(check_ip) of {ok, true} -> case get_ifs(Socket) of {ok, IFs, IP} -> - check_ip(IFs, IP); + check_ip(Driver, IFs, IP); _ -> ?shutdown(no_node) end; @@ -428,20 +447,14 @@ get_ifs(Socket) -> Error end. -check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) -> - case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of +check_ip(Driver, [{OwnIP, _, Netmask}|IFs], PeerIP) -> + case {Driver:mask(Netmask, PeerIP), Driver:mask(Netmask, OwnIP)} of {M, M} -> true; - _ -> check_ip(IFs, PeerIP) + _ -> check_ip(Driver, IFs, PeerIP) end; -check_ip([], PeerIP) -> +check_ip(_Driver, [], PeerIP) -> {false, PeerIP}. -mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) -> - {M1 band IP1, - M2 band IP2, - M3 band IP3, - M4 band IP4}. - is_node_name(Node) when is_atom(Node) -> case split_node(atom_to_list(Node), $@, []) of [_, _Host] -> true; @@ -450,8 +463,14 @@ is_node_name(Node) when is_atom(Node) -> is_node_name(_Node) -> false. -tick(Sock) -> - ?to_port(Sock,[],[force]). +tick(Driver, Socket) -> + case Driver:send(Socket, [], [force]) of + {error, closed} -> + self() ! {tcp_closed, Socket}, + {error, closed}; + R -> + R + end. getstat(Socket) -> case inet:getstat(Socket, [recv_cnt, send_cnt, send_pend]) of diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index c9327e4f31..b5555ca1a5 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -116,6 +116,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-7.0", "stdlib-2.5", "sasl-2.4"]} + {runtime_dependencies, ["erts-7.0", "stdlib-2.6", "sasl-2.6"]} ] }. diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 701aafc717..3fda55d1a9 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,7 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 + [{<<"4\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 %% Down to - max one major revision back - [{<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 + [{<<"4\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 }. diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 3330b38d84..ffb899e5ca 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -93,7 +93,7 @@ unsetenv(_) -> %%% End of BIFs -spec type() -> {Osfamily, Osname} when - Osfamily :: unix | win32 | ose, + Osfamily :: unix | win32, Osname :: atom(). type() -> diff --git a/lib/kernel/test/bif_SUITE.erl b/lib/kernel/test/bif_SUITE.erl index c3840f3d16..dd3010567a 100644 --- a/lib/kernel/test/bif_SUITE.erl +++ b/lib/kernel/test/bif_SUITE.erl @@ -33,6 +33,7 @@ spawn_failures/1, run_fun/1, + decode_packet_delim/1, wilderness/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -516,6 +517,15 @@ fetch_proc_vals(Pid) -> {value,{heap_size,HS}} = lists:keysearch(heap_size, 1, PI), ?line {Ls, P, FA, HS}. +decode_packet_delim(doc) -> + ["Test erlang:packet_delim/3 with {line_delimiter,0} option"]; +decode_packet_delim(suite) -> + []; +decode_packet_delim(Config) when is_list(Config) -> + {ok,<<"abc",0>>,<<"efg",0>>} = + erlang:decode_packet(line, <<"abc",0,"efg",0>>, [{line_delimiter, 0}]), + {more, undefined} = erlang:decode_packet(line, <<"abc",0,"efg",0>>, []). + % This testcase should probably be moved somewhere else wilderness(doc) -> ["Test that memory allocation command line options affecting the" diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index 0803cf428f..ffcde5e458 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -260,46 +260,41 @@ multiple_slaves(doc) -> ["Start nodes in parallell, all using the 'inet' loading method, ", "verify that the boot server manages"]; multiple_slaves(Config) when is_list(Config) -> - case os:type() of - {ose,_} -> - {comment, "OSE: multiple nodes not supported"}; - _ -> - ?line Name = erl_prim_test_multiple_slaves, - ?line Host = host(), - ?line Cookie = atom_to_list(erlang:get_cookie()), - ?line IpStr = ip_str(Host), - ?line LFlag = get_loader_flag(os:type()), - ?line Args = LFlag ++ " -hosts " ++ IpStr ++ - " -setcookie " ++ Cookie, - - NoOfNodes = 10, % no of slave nodes to be started - - NamesAndNodes = - lists:map(fun(N) -> - NameN = atom_to_list(Name) ++ - integer_to_list(N), - NodeN = NameN ++ "@" ++ Host, - {list_to_atom(NameN),list_to_atom(NodeN)} - end, lists:seq(1, NoOfNodes)), - - ?line Nodes = start_multiple_nodes(NamesAndNodes, Args, []), - - %% "queue up" the nodes to wait for the boot server to respond - %% (note: test_server supervises each node start by accept() - %% on a socket, the timeout value for the accept has to be quite - %% long for this test to work). - ?line test_server:sleep(test_server:seconds(5)), - %% start the code loading circus! - ?line {ok,BootPid} = erl_boot_server:start_link([Host]), - %% give the nodes a chance to boot up before attempting to stop them - ?line test_server:sleep(test_server:seconds(10)), + ?line Name = erl_prim_test_multiple_slaves, + ?line Host = host(), + ?line Cookie = atom_to_list(erlang:get_cookie()), + ?line IpStr = ip_str(Host), + ?line LFlag = get_loader_flag(os:type()), + ?line Args = LFlag ++ " -hosts " ++ IpStr ++ + " -setcookie " ++ Cookie, + + NoOfNodes = 10, % no of slave nodes to be started + + NamesAndNodes = + lists:map(fun(N) -> + NameN = atom_to_list(Name) ++ + integer_to_list(N), + NodeN = NameN ++ "@" ++ Host, + {list_to_atom(NameN),list_to_atom(NodeN)} + end, lists:seq(1, NoOfNodes)), + + ?line Nodes = start_multiple_nodes(NamesAndNodes, Args, []), + + %% "queue up" the nodes to wait for the boot server to respond + %% (note: test_server supervises each node start by accept() + %% on a socket, the timeout value for the accept has to be quite + %% long for this test to work). + ?line test_server:sleep(test_server:seconds(5)), + %% start the code loading circus! + ?line {ok,BootPid} = erl_boot_server:start_link([Host]), + %% give the nodes a chance to boot up before attempting to stop them + ?line test_server:sleep(test_server:seconds(10)), - ?line wait_and_shutdown(lists:reverse(Nodes), 30), + ?line wait_and_shutdown(lists:reverse(Nodes), 30), - ?line unlink(BootPid), - ?line exit(BootPid, kill), - ok - end. + ?line unlink(BootPid), + ?line exit(BootPid, kill), + ok. start_multiple_nodes([{Name,Node} | NNs], Args, Started) -> ?line {ok,Node} = start_node(Name, Args, [{wait, false}]), diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 8856be31c2..5263130574 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -167,12 +167,7 @@ init_per_suite(Config) when is_list(Config) -> ok -> [{sasl,started}] end, - ok = case os:type() of - {ose,_} -> - ok; - _ -> - application:start(os_mon) - end, + application:start(os_mon), case os:type() of {win32, _} -> @@ -198,12 +193,7 @@ end_per_suite(Config) when is_list(Config) -> ok end, - case os:type() of - {ose,_} -> - ok; - _ -> - application:stop(os_mon) - end, + application:stop(os_mon), case proplists:get_value(sasl, Config) of started -> application:stop(sasl); @@ -888,10 +878,7 @@ open1(Config) when is_list(Config) -> ?line io:format(Fd1,Str,[]), ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof), ?line Str = io:get_line(Fd1,''), - ?line case io:get_line(Fd2,'') of - Str -> Str; - eof -> Str - end, + ?line Str = io:get_line(Fd2,''), ?line ok = ?FILE_MODULE:close(Fd2), ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof), ?line ok = ?FILE_MODULE:truncate(Fd1), @@ -2346,9 +2333,6 @@ e_rename(Config) when is_list(Config) -> %% At least Windows NT can %% successfully move a file to %% another drive. - ok; - {ose, _} -> - %% disabled for now ok end, [] = flush(), diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index a051d504b2..962471c20c 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -31,7 +31,7 @@ init_per_testcase/2, end_per_testcase/2, t_connect_timeout/1, t_accept_timeout/1, t_connect_bad/1, - t_recv_timeout/1, t_recv_eof/1, + t_recv_timeout/1, t_recv_eof/1, t_recv_delim/1, t_shutdown_write/1, t_shutdown_both/1, t_shutdown_error/1, t_shutdown_async/1, t_fdopen/1, t_fdconnect/1, t_implicit_inet6/1]). @@ -48,7 +48,7 @@ all() -> groups() -> [{t_accept, [], [t_accept_timeout]}, {t_connect, [], [t_connect_timeout, t_connect_bad]}, - {t_recv, [], [t_recv_timeout, t_recv_eof]}]. + {t_recv, [], [t_recv_timeout, t_recv_eof, t_recv_delim]}]. @@ -131,6 +131,21 @@ t_recv_eof(Config) when is_list(Config) -> ?line {error, closed} = gen_tcp:recv(Client, 0), ok. +t_recv_delim(doc) -> "Test using message delimiter $X"; +t_recv_delim(suite) -> []; +t_recv_delim(Config) when is_list(Config) -> + {ok, L} = gen_tcp:listen(0, []), + {ok, Port} = inet:port(L), + Opts = [{active,false},{packet,line},{line_delimiter,$X}], + {ok, Client} = gen_tcp:connect(localhost, Port, Opts), + {ok, A} = gen_tcp:accept(L), + ok = gen_tcp:send(A, "abcXefgX"), + {ok, "abcX"} = gen_tcp:recv(Client, 0, 0), + {ok, "efgX"} = gen_tcp:recv(Client, 0, 0), + ok = gen_tcp:close(Client), + ok = gen_tcp:close(A), + ok. + %%% gen_tcp:shutdown/2 t_shutdown_write(Config) when is_list(Config) -> diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 81c6dcd0fd..3adca83ec9 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -58,14 +58,6 @@ oct_acceptor/1, otp_7731_server/1, zombie_server/2, do_iter_max_socks/2]). -init_per_testcase(wrapping_oct, Config) when is_list(Config) -> - Dog = case os:type() of - {ose,_} -> - test_server:timetrap(test_server:minutes(20)); - _Else -> - test_server:timetrap(test_server:seconds(600)) - end, - [{watchdog, Dog}|Config]; init_per_testcase(iter_max_socks, Config) when is_list(Config) -> Dog = case os:type() of {win32,_} -> @@ -74,14 +66,6 @@ init_per_testcase(iter_max_socks, Config) when is_list(Config) -> test_server:timetrap(test_server:seconds(240)) end, [{watchdog, Dog}|Config]; -init_per_testcase(accept_system_limit, Config) when is_list(Config) -> - case os:type() of - {ose,_} -> - {skip,"Skip in OSE"}; - _ -> - Dog = test_server:timetrap(test_server:seconds(240)), - [{watchdog,Dog}|Config] - end; init_per_testcase(wrapping_oct, Config) when is_list(Config) -> Dog = test_server:timetrap(test_server:seconds(600)), [{watchdog, Dog}|Config]; diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 3e6d8492f7..366231d2cc 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -455,10 +455,7 @@ open1(Config) when is_list(Config) -> ?line ?PRIM_FILE:write(Fd1,Str), ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof), ?line {ok, Str} = ?PRIM_FILE:read(Fd1,Length), - ?line case ?PRIM_FILE:read(Fd2,Length) of - {ok,Str} -> Str; - eof -> Str - end, + ?line {ok, Str} = ?PRIM_FILE:read(Fd2,Length), ?line ok = ?PRIM_FILE:close(Fd2), ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof), ?line ok = ?PRIM_FILE:truncate(Fd1), @@ -1629,7 +1626,7 @@ e_rename(Config) when is_list(Config) -> %% successfully move a file to %% another drive. ok; - {unix, _ } -> + _ -> OtherFs = "/tmp", ?line NameOnOtherFs = filename:join(OtherFs, @@ -1653,10 +1650,7 @@ e_rename(Config) when is_list(Config) -> Else -> Else end, - Com; - {ose, _} -> - %% disabled for now - ok + Com end, ?line test_server:timetrap_cancel(Dog), Comment. diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index c912da0091..d549033302 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 4.0 +KERNEL_VSN = 4.1 diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index c4f937f183..8650e03a60 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -39,7 +39,39 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.</p> - <section><title>Mnesia 4.13</title> + <section><title>Mnesia 4.13.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a process and file descriptor leak in + mnesia:restore/2.</p> + <p> + Own Id: OTP-13025 Aux Id: seq12957 </p> + </item> + </list> + </section> + +</section> + +<section><title>Mnesia 4.13.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Improved index updates to avoid a timing glitch in + dirty_index_read.</p> + <p> + Own Id: OTP-12972</p> + </item> + </list> + </section> + +</section> + +<section><title>Mnesia 4.13</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/mnesia/src/mnesia_bup.erl b/lib/mnesia/src/mnesia_bup.erl index 0e653f2bc4..1f150ae38b 100644 --- a/lib/mnesia/src/mnesia_bup.erl +++ b/lib/mnesia/src/mnesia_bup.erl @@ -157,10 +157,11 @@ fallback_to_schema(Fname) -> read_schema(Mod, Opaque) -> R = #restore{bup_module = Mod, bup_data = Opaque}, try read_schema_section(R) of - {_, {_Header, Schema, _}} -> Schema + {R2, {_Header, Schema, _}} -> + close_read(R2), + Schema catch throw:{error,_} = Error -> Error - after close_read(R) end. %% Open backup media and extract schema @@ -173,8 +174,13 @@ read_schema_section(R) -> do_read_schema_section(R) -> R2 = safe_apply(R, open_read, [R#restore.bup_data]), - {R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]), - do_read_schema_section(R3, verify_header(RawSchema), []). + try + {R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]), + do_read_schema_section(R3, verify_header(RawSchema), []) + catch T:E -> + close_read(R2), + erlang:raise(T,E,erlang:get_stacktrace()) + end. do_read_schema_section(R, {ok, B, C, []}, Acc) -> case safe_apply(R, read, [R#restore.bup_data]) of diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl index 81ed5a8f1a..0c882c0df6 100644 --- a/lib/mnesia/src/mnesia_index.erl +++ b/lib/mnesia/src/mnesia_index.erl @@ -70,17 +70,24 @@ add_index(Index, Tab, Key, Obj, Old) -> add_index2([{Pos, Ixt} |Tail], bag, Tab, K, Obj, OldRecs) -> db_put(Ixt, {element(Pos, Obj), K}), add_index2(Tail, bag, Tab, K, Obj, OldRecs); -add_index2([{Pos, Ixt} |Tail], Type, Tab, K, Obj, OldRecs) -> +add_index2([{Pos, Ixt} |Tail], Type, Tab, K, Obj, OldRecs0) -> %% Remove old tuples in index if Tab is updated - case OldRecs of - undefined -> - Old = mnesia_lib:db_get(Tab, K), - del_ixes(Ixt, Old, Pos, K); - Old -> - del_ixes(Ixt, Old, Pos, K) - end, - db_put(Ixt, {element(Pos, Obj), K}), - add_index2(Tail, Type, Tab, K, Obj, OldRecs); + OldRecs1 = case OldRecs0 of + undefined -> mnesia_lib:db_get(Tab, K); + _ -> OldRecs0 + end, + IdxVal = element(Pos, Obj), + case [Old || Old <- OldRecs1, element(Pos, Old) =/= IdxVal] of + [] when OldRecs1 =:= [] -> %% Write + db_put(Ixt, {element(Pos, Obj), K}), + add_index2(Tail, Type, Tab, K, Obj, OldRecs0); + [] -> %% when OldRecs1 =/= [] Update without modifying index field + add_index2(Tail, Type, Tab, K, Obj, OldRecs0); + OldRecs -> %% Update + db_put(Ixt, {element(Pos, Obj), K}), + del_ixes(Ixt, OldRecs, Pos, K), + add_index2(Tail, Type, Tab, K, Obj, OldRecs0) + end; add_index2([], _, _Tab, _K, _Obj, _) -> ok. delete_index(Index, Tab, K) -> diff --git a/lib/mnesia/test/mnesia_dirty_access_test.erl b/lib/mnesia/test/mnesia_dirty_access_test.erl index 89aff2b3b8..0d57e5a1b1 100644 --- a/lib/mnesia/test/mnesia_dirty_access_test.erl +++ b/lib/mnesia/test/mnesia_dirty_access_test.erl @@ -401,9 +401,26 @@ dirty_index_read(Config, Storage) -> ?match({'EXIT', _}, mnesia:dirty_index_read(Tab, 2, BadValPos)), ?match({'EXIT', _}, mnesia:dirty_index_read(foo, 2, ValPos)), ?match({'EXIT', _}, mnesia:dirty_index_read([], 2, ValPos)), - + + mnesia:dirty_write({Tab, 5, 1}), + ?match(ok, index_read_loop(Tab, 0)), + ?verify_mnesia(Nodes, []). + +index_read_loop(Tab, N) when N =< 1000 -> + spawn_link(fun() -> + mnesia:transaction(fun() -> mnesia:write({Tab, 5, 1}) end) + end), + case mnesia:dirty_match_object({Tab, '_', 1}) of + [{Tab, 5, 1}] -> + index_read_loop(Tab, N+1); + Other -> {N, Other} + end; +index_read_loop(_, _) -> + ok. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl index 89f2861661..e605fa7926 100644 --- a/lib/mnesia/test/mnesia_evil_backup.erl +++ b/lib/mnesia/test/mnesia_evil_backup.erl @@ -232,7 +232,13 @@ restore(Config, Op) -> Res21 = [{Tab2, N, N+1} || N <- lists:seq(1, 11)], Res31 = [[{Tab3, N, N+1}, {Tab3, N, N+44}] || N <- lists:seq(1, 10)], - + Check = fun() -> + [disk_log:pid2name(X) || + X <- processes(), Data <- [process_info(X, [current_function])], + Data =/= undefined, + element(1, element(2, lists:keyfind(current_function, 1, Data)))=:= disk_log] + end, + Before = Check(), ?match({atomic, [Tab1]}, Restore(File1, [{Op, [Tab1]}, {skip_tables, Tabs -- [Tab1]}])), case Op of @@ -319,6 +325,8 @@ restore(Config, Op) -> end, ?match(ok, file:delete(File1)), ?match(ok, file:delete(File2)), + ?match([], Check() -- Before), + ?verify_mnesia(Nodes, []). diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index 79dd495c4b..0fe5b5db8b 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1 +1 @@ -MNESIA_VSN = 4.13 +MNESIA_VSN = 4.13.2 diff --git a/lib/observer/src/cdv_ets_cb.erl b/lib/observer/src/cdv_ets_cb.erl index 9e6e72e08d..bac8b56fc3 100644 --- a/lib/observer/src/cdv_ets_cb.erl +++ b/lib/observer/src/cdv_ets_cb.erl @@ -97,7 +97,7 @@ info_fields() -> [{"Id", id}, {"Name", name}, {"Slot", slot}, - {"Owner", owner}, + {"Owner", pid}, {"Data Structure", data_type} ]}, {"Settings", diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index f2ce51b2af..b66b4d59c9 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -1572,7 +1572,7 @@ get_etsinfo(Fd,EtsTable = #ets_table{details=Ds},WS) -> get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{fixed=>Val}},WS); "Type" -> Val = val(Fd), - get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{data_type=>Val}},WS); + get_etsinfo(Fd,EtsTable#ets_table{data_type=Val},WS); "Protection" -> Val = val(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{protection=>Val}},WS); diff --git a/lib/observer/src/observer_sys_wx.erl b/lib/observer/src/observer_sys_wx.erl index d6183d0249..dfd15380f2 100644 --- a/lib/observer/src/observer_sys_wx.erl +++ b/lib/observer/src/observer_sys_wx.erl @@ -83,11 +83,11 @@ update_syspage(#sys_wx_state{node = Node, fields=Fields, sizer=Sizer}) -> info_fields() -> Info = [{"System and Architecture", [{"System Version", otp_release}, - {"Erts Version", version}, + {"ERTS Version", version}, {"Compiled for", system_architecture}, {"Emulator Wordsize", wordsize_external}, {"Process Wordsize", wordsize_internal}, - {"Smp Support", smp_support}, + {"SMP Support", smp_support}, {"Thread Support", threads}, {"Async thread pool size", thread_pool_size} ]}, @@ -106,7 +106,7 @@ info_fields() -> {"Atoms", {bytes, atom}}, {"Binaries", {bytes, binary}}, {"Code", {bytes, code}}, - {"Ets", {bytes, ets}} + {"ETS", {bytes, ets}} ]}, {"Statistics", right, [{"Up time", {time_ms, uptime}}, diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml index add8229955..59d46de02a 100644 --- a/lib/odbc/doc/src/notes.xml +++ b/lib/odbc/doc/src/notes.xml @@ -32,7 +32,31 @@ <p>This document describes the changes made to the odbc application. </p> - <section><title>ODBC 2.11</title> + <section><title>ODBC 2.11.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + New application variable to set timeout of internal + communication setup between the erlang code and the + c-port program that interfaces the odbc driver. This can + be useful if you have an underlying system that is slow + due to heavy load at startup.</p> + <p> + With this environment variable you can easily bypass and + tailor odbc to the needs of the underlying actual system + without changing the configuration. Which is a good thing + because this value is very system specific.</p> + <p> + Own Id: OTP-12935</p> + </item> + </list> + </section> + +</section> + +<section><title>ODBC 2.11</title> <section><title>Improvements and New Features</title> <list> diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk index d4dc6bbe1d..c7c84560d1 100644 --- a/lib/odbc/vsn.mk +++ b/lib/odbc/vsn.mk @@ -1 +1 @@ -ODBC_VSN = 2.11 +ODBC_VSN = 2.11.1 diff --git a/lib/os_mon/doc/src/cpu_sup.xml b/lib/os_mon/doc/src/cpu_sup.xml index 524426ce86..51e1a4c9d6 100644 --- a/lib/os_mon/doc/src/cpu_sup.xml +++ b/lib/os_mon/doc/src/cpu_sup.xml @@ -63,7 +63,7 @@ measure.</p> <p>A server which receives just enough requests to never become idle will score a CPU utilization of 100%. If the server receives - 50% more requests, it will still scores 100%. When the system load + 50% more requests, it will still score 100%. When the system load is calculated with the percentage formula shown previously, the load will increase from 80% to 87%.</p> <p>The <c>avg1/0</c>, <c>avg5/0</c>, and <c>avg15/0</c> functions diff --git a/lib/ose/doc/man3/.gitignore b/lib/ose/doc/man3/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/ose/doc/man3/.gitignore +++ /dev/null diff --git a/lib/ose/doc/man6/.gitignore b/lib/ose/doc/man6/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/ose/doc/man6/.gitignore +++ /dev/null diff --git a/lib/ose/doc/pdf/.gitignore b/lib/ose/doc/pdf/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/ose/doc/pdf/.gitignore +++ /dev/null diff --git a/lib/ose/doc/src/.gitignore b/lib/ose/doc/src/.gitignore deleted file mode 100644 index 860e9e703e..0000000000 --- a/lib/ose/doc/src/.gitignore +++ /dev/null @@ -1 +0,0 @@ -ose.xml diff --git a/lib/ose/doc/src/Makefile b/lib/ose/doc/src/Makefile deleted file mode 100644 index 7ebd4125ba..0000000000 --- a/lib/ose/doc/src/Makefile +++ /dev/null @@ -1,133 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2012. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions 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=$(OSE_VSN) -APPLICATION=ose - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) - -# ---------------------------------------------------- -# Help application directory specification -# ---------------------------------------------------- -EDOC_DIR = $(ERL_TOP)/lib/edoc -SYNTAX_TOOLS_DIR = $(ERL_TOP)/lib/syntax_tools - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- -XML_APPLICATION_FILES = ref_man.xml - -XML_REF3_FILES = \ - ose.xml \ - ose_erl_driver.xml - -XML_REF6_FILES = ose_app.xml - -XML_PART_FILES = part.xml -XML_CHAPTER_FILES = notes.xml ose_intro.xml ose_signals_chapter.xml - -BOOK_FILES = book.xml - -XML_FILES = \ - $(BOOK_FILES) $(XML_CHAPTER_FILES) \ - $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \ - $(XML_APPLICATION_FILES) - -# ---------------------------------------------------- - -HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ - $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) - -INFO_FILE = ../../info - -MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) -MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6) - -HTML_REF_MAN_FILE = $(HTMLDIR)/index.html - -TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf - -SPECS_FILES = - -TOP_SPECS_FILE = - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -XML_FLAGS += - -SPECS_FLAGS = -I../../include -I../../../kernel/include - -OSE_SRC_DIR = ../../src - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- -docs: man pdf html - -$(TOP_PDF_FILE): $(XML_FILES) - -pdf: $(TOP_PDF_FILE) - -html: $(HTML_REF_MAN_FILE) - -man: $(MAN3_FILES) $(MAN6_FILES) - -ose.xml: $(OSE_SRC_DIR)/ose.erl - escript $(DOCGEN)/priv/bin/xml_from_edoc.escript\ - $(OSE_SRC_DIR)/$(@:%.xml=%.erl) - -debug opt: - -clean clean_docs: - rm -rf $(HTMLDIR)/* - rm -f $(MAN3DIR)/* - rm -f $(MAN6DIR)/* - rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) - rm -f $(SPECDIR)/* - rm -f errs core *~ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_docs_spec: docs - $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DIR) "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(HTMLDIR)/* \ - "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3" - $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6" - $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6" - -release_spec: diff --git a/lib/ose/doc/src/book.xml b/lib/ose/doc/src/book.xml deleted file mode 100644 index d62e0d32f4..0000000000 --- a/lib/ose/doc/src/book.xml +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE book SYSTEM "book.dtd"> - -<book xmlns:xi="http://www.w3.org/2001/XInclude"> - <header titlestyle="normal"> - <copyright> - <year>2014</year><year>2014</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>OSE</title> - <prepared>Lukas Larsson</prepared> - <docno></docno> - <date>2014-01-08</date> - <rev>1.0</rev> - <file>book.xml</file> - </header> - <insidecover> - </insidecover> - <pagetext>OSE</pagetext> - <preamble> - <contents level="2"></contents> - </preamble> - <parts> - <xi:include href="part.xml"/> - </parts> - <applications> - <xi:include href="ref_man.xml"/> - </applications> - <releasenotes> - <xi:include href="notes.xml"/> - </releasenotes> - <listofterms></listofterms> - <index></index> -</book> diff --git a/lib/ose/doc/src/notes.xml b/lib/ose/doc/src/notes.xml deleted file mode 100644 index 06881b6c99..0000000000 --- a/lib/ose/doc/src/notes.xml +++ /dev/null @@ -1,109 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2014</year><year>2014</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>OSE Release Notes</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - <file>notes.xml</file> - </header> - <p>This document describes the changes made to the OSE application.</p> - -<section><title>Ose 1.1</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Change license text from Erlang Public License to Apache - Public License v2</p> - <p> - Own Id: OTP-12845</p> - </item> - </list> - </section> - -</section> - -<section><title>Ose 1.0.2</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Add missing release notes for the OSE application.</p> - <p> - Own Id: OTP-12177</p> - </item> - </list> - </section> - -</section> - -<section><title>Ose 1.0.1</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Fix some spelling mistakes in documentation</p> - <p> - Own Id: OTP-12152</p> - </item> - </list> - </section> - -</section> - -<section><title>Ose 1.0</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Erlang/OTP has been ported to the realtime operating - system OSE. The port supports both smp and non-smp - emulator. For details around the port and how to started - see the User's Guide in the <seealso - marker="ose:ose_intro">ose</seealso> application. </p> - <p> - Note that not all parts of Erlang/OTP has been ported. </p> - <p> - Notable things that work are: non-smp and smp emulators, - OSE signal interaction, crypto, asn1, run_erl/to_erl, - tcp, epmd, distribution and most if not all non-os - specific functionality of Erlang.</p> - <p> - Notable things that does not work are: udp/sctp, os_mon, - erl_interface, binding of schedulers.</p> - <p> - Own Id: OTP-11334</p> - </item> - </list> - </section> - -</section> - -</chapter> diff --git a/lib/ose/doc/src/ose_app.xml b/lib/ose/doc/src/ose_app.xml deleted file mode 100644 index d555f0ec4f..0000000000 --- a/lib/ose/doc/src/ose_app.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE appref SYSTEM "appref.dtd"> - -<appref> - <header> - <copyright> - <year>2014</year><year>2014</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>Enea OSE</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <app>ose</app> - <appsummary>The OSE Application</appsummary> - <description> - <p>The OSE application contains modules and documentation that only - applies when running Erlang/OTP on Enea OSE.</p> - </description> - -</appref> diff --git a/lib/ose/doc/src/ose_erl_driver.xml b/lib/ose/doc/src/ose_erl_driver.xml deleted file mode 100644 index b804c29d2d..0000000000 --- a/lib/ose/doc/src/ose_erl_driver.xml +++ /dev/null @@ -1,111 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE cref SYSTEM "cref.dtd"> - -<cref> - <header> - <copyright> - <year>2013</year><year>2014</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>erl_driver for Enea OSE</title> - <prepared>Lukas Larsson</prepared> - <docno></docno> - <date>2014-01-08</date> - <rev>A</rev> - <file>ose_erl_driver.xml</file> - </header> - <lib>ose_erl_driver</lib> - <libsummary>Linked-in drivers in Enea OSE</libsummary> - <description> - <p>Writing Linked-in drivers that also work on Enea OSE is very similar for - how you would do it for Unix. The difference from Unix is that - driver_select, ready_input and ready_output all work with signals - instead of file descriptors. This means that the driver_select is - used to specify which type of signal should trigger calls to - ready_input/ready_output. The functions described below are available - to driver programmers on Enea OSE to facilitate this. - </p> - </description> - <section> - <title>DATA TYPES</title> - - <taglist> - <tag><marker id="union_SIGNAL"/>union SIGNAL</tag> - <item>See the Enea OSE SPI documentation for a description.</item> - <tag><marker id="SIGSELECT"/>SIGSELECT</tag> - <item>See the Enea OSE SPI documentation for a description.</item> - <tag><marker id="ErlDrvEvent"/>ErlDrvEvent</tag> - <item>The <c>ErlDrvEvent</c> is a handle to a signal number and id combination. It is passed to <seealso marker="erts:erl_driver#driver_select">driver_select(3)</seealso>.</item> - <tag><marker id="ErlDrvOseEventId"/>ErlDrvOseEventId</tag> - <item>This is the id used to associate a specific signal to a - certain driver instance. </item> - </taglist> - </section> - <funcs> - <func> - <name><ret>union SIGNAL *</ret><nametext>erl_drv_ose_get_signal(ErlDrvEvent drv_event)</nametext></name> - <desc> - <marker id="erl_drv_ose_get_signal"></marker> - <p>Fetch the next signal associated with <c>drv_event</c>. - Signals will be returned in the order which they were received and - when no more signals are available <c>NULL</c> will be returned. - Use this function in the ready_input/ready_output callbacks - to get signals.</p> - </desc> - </func> - <func> - <name><ret>ErlDrvEvent</ret><nametext>erl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, ErlDrvOseEventId (*resolve_signal)(union SIGNAL* sig), void *extra)</nametext></name> - <desc> - <marker id="erl_drv_ose_event_alloc"></marker> - <p>Create a new <c>ErlDrvEvent</c> associated with <c>signo</c>, - <c>id</c> and uses the <c>resolve_signal</c> function to extract - the <c>id</c> from a signal with <c>signo</c>. The <c>extra</c> - parameter can be used for additional data. See - <seealso marker="ose_signals_chapter#driver"> - Signals in a Linked-in driver</seealso> in the OSE User's Guide. - </p> - </desc> - </func> - <func> - <name><ret>void</ret><nametext>erl_drv_ose_event_free(ErlDrvEvent drv_event)</nametext></name> - <desc> - <marker id="erl_drv_ose_event_free"></marker> - <p>Free a <c>ErlDrvEvent</c>. This should always be done in the - <seealso marker="erts:driver_entry#stop_select">stop_select</seealso> - callback when the event is no longer being used.</p> - </desc> - </func> - <func> - <name><ret>void</ret><nametext>erl_drv_ose_event_fetch(ErlDrvEvent drv_event, SIGSELECT *signo, ErlDrvOseEventId *id, void **extra)</nametext></name> - <desc> - <marker id="erl_drv_ose_event_fetch"></marker> - <p>Write the signal number, id and any extra data associated with <c>drv_event</c> - into <c>*signo</c> and <c>*id</c> respectively. <c>NULL</c> can be - also passed as <c>signo</c> or <c>id</c> in order to ignore that field. - </p> - </desc> - </func> - </funcs> - <section> - <title>SEE ALSO</title> - <p> - <seealso marker="erts:driver_entry">driver_entry(3)</seealso>, - <seealso marker="erts:erl_driver">erl_driver(3)</seealso> - </p> - </section> -</cref> diff --git a/lib/ose/doc/src/ose_intro.xml b/lib/ose/doc/src/ose_intro.xml deleted file mode 100644 index 982516c8bd..0000000000 --- a/lib/ose/doc/src/ose_intro.xml +++ /dev/null @@ -1,154 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2013</year><year>2014</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>Introduction</title> - <prepared>Lukas Larsson</prepared> - <docno></docno> - <date>2014-01-08</date> - <rev>A</rev> - <file>ose_intro.xml</file> - </header> - - <section> - <title>Features</title> - </section> - - <section> - <title>Starting Erlang/OTP</title> - <p> - Starting Erlang/OTP on OSE is not as simple as on Unix/Windows (yet). - First of all you have to explicitly use the beam (or beam.smp) executables - found in erts-X.Y.Z/bin as the load module that you run. This in turn - means that you have to supply the raw beam arguments to the emulator - when starting. Fortunately <c>erl</c> on Unix/Windows has a - undocumented flag called <c>-emu_args_exit</c> that can be used to - figure out what the arguments to beam look like. For example:</p> - <code># erl +Mut false +A 10 +S 4:4 +Muycs256 +P 2096 +Q 2096 -emu_args_exit --Mut -false --A -10 --S -4:4 --Muycs256 --P -2096 --Q -2096 --- --root -/usr/local/lib/erlang --progname -erl --- --home -/home/erlang ---</code> - <p> - The arguments are printed on separate lines to make it possible to know - what has to be quoted with ". Each line is one quotable unit. - So taking the arguments above you can supply them to pm_create or - just execute directly on the command line. For example:</p> - <code>rtose@acp3400> pm_install erlang /mst/erlang/erts-6.0/bin/beam.smp -rtose@acp3400> pm_create -c ARGV="-Mut false -A 10 -S 4:4 -Muycs256 -P 2096 -Q 2099 -- -root /mst/erlang -progname erl -- -home /mst/erlang --" erlang -pid: 0x110059 -rtose@acp3400> pm_start 0x110059</code> - <p> - Also note that since we are running erl to figure out the arguments on a - separate machine the paths have to be updated. In the example above - <c>/usr/local/lib/erlang</c> was replaced by <c>/mst/erlang/</c>. The - goal is to in future releases not have to do the special argument handling - but for now (OTP 17.0) you have to do it. - </p> - <note> - Because of a limitation in the way the OSE handles stdio when starting - load modules using pm_install/create the Erlang shell only reads every - other command from stdin. However if you start Erlang using run_erl - you do not have this problem. So it is highly recommended that you - start Erlang using run_erl. - </note> - </section> - - <section> - <title>run_erl and to_erl</title> - <p> - In OSE run_erl and to_erl are combined into a single load module called - run_erl_lm. Installing and starting the load module will add two new - shell commands called run_erl and to_erl. They work in exactly the same - way as the unix variants of run_erl and to_erl, except that the read - and write pipes have to be placed under the /pipe vm. One additional - option also exists to run_erl on ose: - <taglist> - <tag><c>-block Name</c></tag> - <item>The name of the install handle and block that will be created/used by - installing and exectuting the first part of the command. If nothing - if given the basename of the load module will be used for this value. - Example: - <code>pm_install erlang /path/to/erlang/vm/beam.smp -run_erl -daemon -block erlang /pipe/ /mst/erlang_logs/ "beam.smp -A 1 -- -root /mst/erlang -- -home /mst --"</code> - </item> - </taglist> - The same argument munching as when starting Erlang/OTP without run_erl - has to be done. If <c>-daemon</c> is given then all error printouts - are sent to the ramlog. - See also - <seealso marker="erts:run_erl">run_erl</seealso> for more details. - </p> - <p> - Below is an example of how to get started with <c>run_erl_lm</c>. - <code>rtose@acp3400> pm_install run_erl_lm /mst/erlang/erts-6.0/bin/run_erl_lm -rtose@acp3400> pm_create run_erl_lm -pid: 0x1c005d -rtose@acp3400> pm_start 0x1c005d -rtose@acp3400> mkdir /mst/erlang_log -rtose@acp3400> run_erl -daemon /pipe/ /mst/erlang_log/ "/mst/erlang/erts-6.0/bin/beam.smp -A 1 -- -root /mst/erlang -- -home /mst --" -rtose@acp3400> to_erl -Attaching to /pipe/erlang.pipe.1 (^C to exit) -os:type(). -{ose,release} -2> -'to_erl' terminated.</code> - Note that Ctrl-C is used instead of Ctrl-D to exit the to_erl shell. - </p> - </section> - - <section> - <title>epmd</title> - <p> - In OSE epmd will not be started automatically so if you want to use - Erlang distribution you have to manually start epmd. - </p> - </section> - - <section> - <title>VM Process Priorities</title> - <p> - It is possible to set the priorities you want for the OSE processes that - thr emulator creates in the lmconf. An example of how to do it can be - found in the default lmconf file in - $ERL_TOP/erts/emulator/sys/ose/beam.lmconf. - </p> - </section> - -</chapter> diff --git a/lib/ose/doc/src/ose_signals_chapter.xml b/lib/ose/doc/src/ose_signals_chapter.xml deleted file mode 100644 index bcf2259577..0000000000 --- a/lib/ose/doc/src/ose_signals_chapter.xml +++ /dev/null @@ -1,240 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2013</year><year>2014</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>Interacting with Enea OSE</title> - <prepared>Lukas Larsson</prepared> - <docno></docno> - <date>2014-01-08</date> - <rev>A</rev> - <file>ose_signals_chapter.xml</file> - </header> - - <marker id="introduction"></marker> - <section> - <title>Introduction</title> - <p>The main way which programs on Enea OSE interact is through the - usage of message passing, much the same way as Erlang processes - communicate. There are two ways in which an Erlang programmer can - interact with the signals sent from other Enea OSE processes; either - through the provided <c>ose</c> module, or by writing a custom linked-in - driver. This User's Guide describes and provides examples for both - approaches. - </p> - </section> - - <marker id="erlang"></marker> - <section> - <title>Signals in Erlang</title> - <p>Erlang/OTP on OSE provides a erlang module called - <seealso marker="ose:ose">ose</seealso> that can be used to interact - with other OSE processes using message passing. The api in the module - is very similar to the native OSE api, so for details of how the - functions work please refer to the official OSE documenation. Below - is an example usage of the API. - </p> - <code>1> P1 = ose:open("p1"). -#Port>0.344> -2> ose:hunt(P1,"p2"). -{#Port>0.344>,1} -3> P2 = ose:open("p2"). -#Port>0.355> -4> flush(). -Shell got {mailbox_up,#Port>0.344>,{#Port>0.344>,1},852189} -ok -5> ose:listen(P1,[1234]). -ok -6> ose:send(P2,ose:get_id(P1),1234,>>"hello">>). -ok -7> flush(). -Shell got {message,#Port>0.344>,{852189,1245316,1234,>>"hello">>}} -ok</code> - </section> - - <marker id="driver"></marker> - <section> - <title>Signals in a Linked-in driver</title> - <p> - Writing Linked-in drivers for OSE is very similar to how it is done - for Unix/Windows. It is only the way in which the driver subscribes - and consumed external events that is different. In Unix (and Windows) - file descriptiors (and Event Objects) are used to select on. On OSE - we use signals to deliver the same functionality. There are two large - differences between a signal and an fd. - </p> - <p> - In OSE it is not possible for a signal number to be a unique identifier - for a resource in the same way as an fd is. For example; let's say we - implement a driver that does an asynchronous hunt that uses signal - number 1234 as the hunt_sig. If we want to be able to have multiple - hunt ports running at the same time we have to have someway of routing - the signal to the correct port. This is achieved by supplying a secondary - id that can be retrieved through the meta-data or payload of the signal, - e.g: - <code>ErlDrvEvent event = erl_drv_ose_event_alloc(1234,port,resolver);</code> - The event you get back from - <seealso marker="ose_erl_driver#erl_drv_ose_event_alloc"> - erl_drv_ose_event_alloc</seealso> can then be used by - <seealso marker="erts:erl_driver#driver_select">driver_select</seealso> - to subscribe to signals. The first argument is just the signal number - that we are interested in. The second is the id that we choose to use, - in this case the port id that we got in the - <seealso marker="erts:driver_entry#start">start</seealso> callback is - used. The third argument is a function pointer to a function that can - be used to figure out the id from a given signal. The fourth argument can - point to any additional data you might want to associate with the event. - There is a complete. You can examine the data contained in the event with - <seealso marker="ose_erl_driver#erl_drv_ose_event_fetch">erl_drv_ose_event_fetch</seealso> - , eg: - <code>erl_drv_ose_event_fetch(event, &signal, &port, (void **)&extra);</code> - example of what this could look like in - <seealso marker="#example">the next section</seealso>. - <note>It is very important to issue the driver_select call before - any of the signals you are interested in are sent. If driver_select - is called after the signal is sent, there is a high probability that it - will be lost.</note> - </p> - <p> - The other difference from unix is that in OSE the payload of the event - (i.e. the signal data) is already received when the ready_output/input - callbacks are called. This means that you access the data of a signal - by calling <seealso marker="ose_erl_driver#erl_drv_ose_get_signal"> - erl_drv_ose_get_signal</seealso>. Additionally multiple signals might be - associated with the event, so you should call - <seealso marker="ose_erl_driver#erl_drv_ose_get_signal"> - erl_drv_ose_get_signal</seealso> until <c>NULL</c> is returned. - </p> - </section> - - <marker id="example"></marker> - <section> - <title>Example Linked-in driver</title> -<code>#include "erl_driver.h" -#include "ose.h" - -struct huntsig { - SIGSELECT signo; - ErlDrvPort port; -}; - -union SIGNAL { - SIGSELECT signo; - struct huntsig; -} - -/* Here we have to get the id from the signal. In this case we use the - port id since we have control over the data structure of the signal. - It is however possible to use anything in here. The only restriction - is that the same id has to be used for all signals of the same number.*/ -ErlDrvOseEventId resolver(union SIGNAL *sig) { - return (ErlDrvOseEventId)sig->huntsig.port; -} - -static int drv_init(void) { return 0; }; - -static ErlDrvData drv_start(ErlDrvPort port, char *command) { - return (ErlDrvData)port; -} - -static ErlDrvSSizeT control(ErlDrvData driver_data, unsigned int cmd, - char *buf, ErlDrvSizeT len, - char **rbuf, ErlDrvSizeT rlen) { - ErlDrvPort port = (ErlDrvPort)driver_data; - - /* An example of extra data to associate with the event */ - char *extra_data = driver_alloc(80); - snprintf("extra_data, "Event, sig_no: 1234, and port: %d", port); - - /* Create a new event to select on */ - ErlDrvOseEvent evt = erl_drv_ose_event_alloc(1234,port,resolver, extra_data); - - /* Make sure to do the select call _BEFORE_ the signal arrives. - The signal might get lost if the hunt call is done before the - select. */ - driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,1); - - union SIGNAL *sig = alloc(sizeof(union SIGNAL),1234); - sig->huntsig.port = port; - hunt("testprocess",0,NULL,&sig); - return 0; -} - -static void ready_input(ErlDrvData driver_data, ErlDrvEvent evt) { - char *extra_data; - /* Get the first signal payload from the event */ - union SIGNAL *sig = erl_drv_ose_get_signal(evt); - ErlDrvPort port = (ErlDrvPort)driver_data; - while (sig != NULL) { - if (sig->signo == 1234) { - /* Print out the string we added as the extra parameter */ - erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&extra_data); - printf("We've received: %s\n", extra_data); - - /* If it is our signal we send a message with the sender of the signal - to the controlling erlang process */ - ErlDrvTermData reply[] = { ERL_DRV_UINT, (ErlDrvUInt)sender(&sig) }; - erl_drv_send_term(port,reply,sizeof(reply) / sizeof(reply[0])); - } - - /* Cleanup the signal and deselect on the event. - Note that the event itself has to be free'd in the stop_select - callback. */ - free_buf(&sig); - driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,0); - - /* There could be more than one signal waiting in this event, so - we have to loop until sig == NULL */ - sig = erl_drv_ose_get_signal(evt); - } -} - -static void stop_select(ErlDrvEvent event, void *reserved) -{ - /* Free the extra_data */ - erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&extra_data); - driver_free(extra_data); - - /* Free the event itself */ - erl_drv_ose_event_free(event); -} - -/** - * Setup the driver entry for the Erlang runtime - **/ -ErlDrvEntry ose_signal_driver_entry = { - .init = drv_init, - .start = drv_start, - .stop = drv_stop, - .ready_input = ready_input, - .driver_name = DRIVER_NAME, - .control = control, - .extended_marker = ERL_DRV_EXTENDED_MARKER, - .major_version = ERL_DRV_EXTENDED_MAJOR_VERSION, - .minor_version = ERL_DRV_EXTENDED_MINOR_VERSION, - .driver_flags = ERL_DRV_FLAG_USE_PORT_LOCKING, - .stop_select = stop_select -}; -</code> - </section> - -</chapter> diff --git a/lib/ose/doc/src/part.xml b/lib/ose/doc/src/part.xml deleted file mode 100644 index 0c9ebd16c0..0000000000 --- a/lib/ose/doc/src/part.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2014</year> - <year>2014</year> - <holder>Ericsson AB, All Rights Reserved</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - The Initial Developer of the Original Code is Ericsson AB. - </legalnotice> - - <title>OSE User's Guide</title> - <prepared>Lukas Larsson</prepared> - <docno></docno> - <date>2014-01-08</date> - <rev>1.0</rev> - <file>part.xml</file> - </header> - <description> - <p><em>OSE</em>.</p> - </description> - <xi:include href="ose_intro.xml"/> - <xi:include href="ose_signals_chapter.xml"/> -</part> diff --git a/lib/ose/doc/src/ref_man.xml b/lib/ose/doc/src/ref_man.xml deleted file mode 100644 index 964e5ab8ff..0000000000 --- a/lib/ose/doc/src/ref_man.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE application SYSTEM "application.dtd"> - -<application xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2014</year><year>2014</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>OSE Reference Manual</title> - <prepared>Lukas Larsson</prepared> - <docno></docno> - <date>2014-01-08</date> - <rev>1.0</rev> - <file>ref_man.xml</file> - </header> - <description> - <p>The Standard Erlang Libraries application, <em>STDLIB</em>, - contains modules for manipulating lists, strings and files etc.</p> - <br></br> - </description> - <xi:include href="ose_app.xml"/> - <xi:include href="ose.xml"/> - <xi:include href="ose_erl_driver.xml"/> -</application> diff --git a/lib/ose/ebin/.gitignore b/lib/ose/ebin/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/ose/ebin/.gitignore +++ /dev/null diff --git a/lib/ose/include/.gitignore b/lib/ose/include/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/ose/include/.gitignore +++ /dev/null diff --git a/lib/ose/info b/lib/ose/info deleted file mode 100644 index 85c07dbe82..0000000000 --- a/lib/ose/info +++ /dev/null @@ -1,2 +0,0 @@ -group: misc Miscellaneous Applications -short: Description of Enea OSE specific functionality diff --git a/lib/ose/src/Makefile b/lib/ose/src/Makefile deleted file mode 100644 index a89e9392e9..0000000000 --- a/lib/ose/src/Makefile +++ /dev/null @@ -1,107 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2013. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions 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=$(OSE_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/ose-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- -MODULES= \ - ose - -HRL_FILES= - -INTERNAL_HRL_FILES= - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET) - -APP_FILE= ose.app - -APP_SRC= $(APP_FILE).src -APP_TARGET= $(EBIN)/$(APP_FILE) - -APPUP_FILE= ose.appup - -APPUP_SRC= $(APPUP_FILE).src -APPUP_TARGET= $(EBIN)/$(APPUP_FILE) - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- - -ifeq ($(NATIVE_LIBS_ENABLED),yes) -ERL_COMPILE_FLAGS += +native -endif -ERL_COMPILE_FLAGS += -I../include -I../../kernel/include -Werror - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: $(TARGET_FILES) - -clean: - rm -f $(TARGET_FILES) - rm -f core - rm -f erl_parse.erl - -docs: - -# ---------------------------------------------------- -# Special Build Targets -# ---------------------------------------------------- - -$(APP_TARGET): $(APP_SRC) ../vsn.mk - $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ - -$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk - $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/src" - $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src" - $(INSTALL_DIR) "$(RELSYSDIR)/include" - $(INSTALL_DIR) "$(RELSYSDIR)/ebin" - $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin" - -release_docs_spec: - -# ---------------------------------------------------- -# Dependencies -- alphabetically, please -# ---------------------------------------------------- diff --git a/lib/ose/src/ose.app.src b/lib/ose/src/ose.app.src deleted file mode 100644 index 036779eb16..0000000000 --- a/lib/ose/src/ose.app.src +++ /dev/null @@ -1,28 +0,0 @@ -%% This is an -*- erlang -*- file. -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% -{application, ose, - [{description, "Enea OSE specific modules"}, - {vsn, "%VSN%"}, - {modules, [ose]}, - {registered,[]}, - {applications, [stdlib,kernel]}, - {env, []}, - {runtime_dependencies, ["stdlib-2.0","erts-6.0"]}]}. diff --git a/lib/ose/src/ose.appup.src b/lib/ose/src/ose.appup.src deleted file mode 100644 index 28b6da3439..0000000000 --- a/lib/ose/src/ose.appup.src +++ /dev/null @@ -1,23 +0,0 @@ -%% -*- erlang -*- -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -{"%VSN%", - [ - ], - [ - ]}. diff --git a/lib/ose/src/ose.erl b/lib/ose/src/ose.erl deleted file mode 100644 index 5534dba4d4..0000000000 --- a/lib/ose/src/ose.erl +++ /dev/null @@ -1,453 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2013. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% -%% @doc Interface module for OSE messaging and process monitoring from Erlang -%% -%% For each mailbox created through {@link open/1} a OSE phantom process with -%% that name is started. Since phantom processes are used the memory footprint -%% of each mailbox is quite small. -%% -%% To receive messages you first have to subscribe to the specific message -%% numbers that you are interested in with {@link listen/2}. The messages -%% will be sent to the Erlang process that created the mailbox. -%% -%% @end -%% --module(ose). - -%%============================================================================== -%% Exported API -%%============================================================================== --export([open/1, - close/1, - get_id/1, - get_name/2, - hunt/2, - dehunt/2, - attach/2, - detach/2, - send/4, - send/5, - listen/2 - ]). - -%%============================================================================== -%% Types -%%============================================================================== --opaque mailbox() :: port(). -%% Mailbox handle. Implemented as an erlang port. - --opaque mailbox_id() :: integer(). -%% Mailbox ID, this is the same as the process id of an OSE process. -%% An integer. - --type message_number() :: 0..4294967295. -%% OSE Signal number - --opaque hunt_ref() :: {mailbox(),integer()}. -%% Reference from a hunt request. This term will be included -%% in a successful hunt response. - --opaque attach_ref() :: {mailbox(),integer()}. -%% Reference from an attach request. This term will be included -%% in the term returned when the attached mailbox disappears. - --export_type([mailbox_id/0, - message_number/0, - mailbox/0, - hunt_ref/0, - attach_ref/0]). - -%%============================================================================== -%% Defines -%%============================================================================== --define(DRIVER_NAME, "ose_signal_drv"). --define(GET_SPID, 1). --define(GET_NAME, 2). --define(HUNT, 100). --define(DEHUNT, 101). --define(ATTACH, 102). --define(DETACH, 103). --define(SEND, 104). --define(SEND_W_S, 105). --define(LISTEN, 106). --define(OPEN, 200). - --define(INT_32BIT(Int),(is_integer(Int) andalso (Int >= 0) andalso (Int < (1 bsl 32)))). - -%%============================================================================== -%% API functions -%%============================================================================== - -%%------------------------------------------------------------------------------ -%% @doc Create a mailbox with the given name and return a port that handles -%% the mailbox. -%% -%% An OSE phantom process with the given name will be created that will send any -%% messages sent through this mailbox. Any messages sent to the new OSE process -%% will automatically be converted to an Erlang message and sent to the Erlang -%% process that calls this function. See {@link listen/2} for details about the -%% format of the message sent. -%% -%% The caller gets linked to the created mailbox. -%% -%% raises: `badarg' | `system_limit' -%% -%% @see listen/2 -%% @end -%%------------------------------------------------------------------------------ --spec open(Name) -> Port when - Name :: iodata(), - Port :: mailbox(). -open(Name) -> - try open_port({spawn_driver,?DRIVER_NAME}, [binary]) of - Port -> - try port_command(Port,[?OPEN,Name]) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - close(Port), - erlang:error(Error,[Name]); - {ose_drv_reply,Port,ok} -> - Port - end - catch - error:badarg -> close(Port),erlang:error(badarg,[Name]) - end - catch - error:badarg -> erlang:error(badarg,[Name]) - end. - -%%------------------------------------------------------------------------------ -%% @doc Close a mailbox -%% -%% This kills the OSE phantom process associated with this mailbox. -%% -%% Will also consume any ``{'EXIT',Port,_}'' message from the port that comes -%% due to the port closing when the calling process traps exits. -%% -%% raises: `badarg' -%% @end -%%------------------------------------------------------------------------------ --spec close(Port) -> ok when - Port :: mailbox(). -close(Port) when is_port(Port) -> - %% Copied from prim_inet - case erlang:process_info(self(), trap_exit) of - {trap_exit,true} -> - link(Port), - catch erlang:port_close(Port), - receive {'EXIT',Port,_} -> ok end; - {trap_exit,false} -> - catch erlang:port_close(Port), - ok - end; -close(NotPort) -> - erlang:error(badarg,[NotPort]). - -%%------------------------------------------------------------------------------ -%% @doc Get the mailbox id for the given port. -%% -%% The mailbox id is the same as the OSE process id of the OSE phantom process -%% that this mailbox represents. -%% -%% raises: `badarg' -%% @end -%%------------------------------------------------------------------------------ --spec get_id(Port) -> Pid when - Port :: mailbox(), - Pid :: mailbox_id(). -get_id(Port) -> - try port_control(Port, ?GET_SPID, <<>>) of - <<Spid:32>> -> Spid - catch error:_Error -> - erlang:error(badarg,[Port]) - end. - -%%------------------------------------------------------------------------------ -%% @doc Get the mailbox name for the given mailbox id. -%% -%% The mailbox name is the name of the OSE process with process id Pid. -%% -%% This call will fail with badarg if the underlying system does not support -%% getting the name from a process id. -%% -%% raises: `badarg' -%% @end -%%------------------------------------------------------------------------------ --spec get_name(Port, Pid) -> Name | undefined when - Port :: mailbox(), - Pid :: mailbox_id(), - Name :: binary(). -get_name(Port, Pid) when ?INT_32BIT(Pid) -> - try port_control(Port, ?GET_NAME, <<Pid:32>>) of - [] -> undefined; - Res -> Res - catch error:_Error -> - erlang:error(badarg,[Port,Pid]) - end; -get_name(Port, Pid) -> - erlang:error(badarg,[Port,Pid]). - - -%%------------------------------------------------------------------------------ -%% @doc Hunt for OSE process by name. -%% -%% Will send `{mailbox_up, Port, Ref, MboxId}' -%% to the calling process when the OSE process becomes available. -%% -%% Returns a reference term that can be used to cancel the hunt -%% using {@link dehunt/2}. -%% -%% raises: `badarg' -%% -%% @end -%%------------------------------------------------------------------------------ --spec hunt(Port, HuntPath) -> Ref when - Port :: mailbox(), - HuntPath :: iodata(), - Ref :: hunt_ref(). -hunt(Port, HuntPath) -> - try port_command(Port, [?HUNT,HuntPath]) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - erlang:error(Error,[Port,HuntPath]); - {ose_drv_reply,Port,Ref} -> - Ref - end - catch error:_Error -> - erlang:error(badarg,[Port,HuntPath]) - end. - -%%------------------------------------------------------------------------------ -%% @doc Stop hunting for OSE process. -%% -%% If a message for this hunt has been sent but not received -%% by the calling process, it is removed from the message queue. -%% Note that this only works if the same process that did -%% the hunt does the dehunt. -%% -%% raises: `badarg' -%% -%% @see hunt/2 -%% @end -%%------------------------------------------------------------------------------ --spec dehunt(Port, Ref) -> ok when - Port :: mailbox(), - Ref :: hunt_ref(). -dehunt(Port, {Port,Ref}) when ?INT_32BIT(Ref) -> - try port_command(Port, <<?DEHUNT:8, Ref:32>>) of - true -> - receive - {ose_drv_reply,Port,{error,enoent}} -> - %% enoent could mean that it is in the message queue - receive - {mailbox_up, Port, {Port,Ref}, _} -> - ok - after 0 -> - ok - end; - {ose_drv_reply,Port,ok} -> - ok - end - catch error:_Error -> - erlang:error(badarg,[Port,{Port,Ref}]) - end; -dehunt(Port,Ref) -> - erlang:error(badarg,[Port,Ref]). - -%%------------------------------------------------------------------------------ -%% @doc Attach to an OSE process. -%% -%% Will send `{mailbox_down, Port, Ref, MboxId}' -%% to the calling process if the OSE process exits. -%% -%% Returns a reference that can be used to cancel the attachment -%% using {@link detach/2}. -%% -%% raises: `badarg' | `enomem' -%% -%% @end -%%------------------------------------------------------------------------------ --spec attach(Port,Pid) -> Ref when - Port :: mailbox(), - Pid :: mailbox_id(), - Ref :: attach_ref(). -attach(Port, Spid) when ?INT_32BIT(Spid) -> - try port_command(Port, <<?ATTACH:8, Spid:32>>) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - erlang:error(Error,[Port,Spid]); - {ose_drv_reply,Port,Ref} -> - Ref - end - catch error:_Error -> - erlang:error(badarg,[Port,Spid]) - end; -attach(Port,Spid) -> - erlang:error(badarg,[Port,Spid]). - - -%%------------------------------------------------------------------------------ -%% @doc Remove attachment to an OSE process. -%% -%% If a message for this monitor has been sent but not received -%% by the calling process, it is removed from the message queue. -%% Note that this only works of the same process -%% that did the attach does the detach. -%% -%% raises: `badarg' -%% -%% @see attach/2 -%% @end -%%------------------------------------------------------------------------------ --spec detach(Port,Ref) -> ok when - Port :: mailbox(), - Ref :: attach_ref(). -detach(Port, {Port,Ref} ) when ?INT_32BIT(Ref) -> - try port_command(Port, <<?DETACH:8, Ref:32>>) of - true -> - receive - {ose_drv_reply,Port,{error,enoent}} -> - %% enoent could mean that it is in the message queue - receive - {mailbox_down,Port,{Port,Ref},_} -> - ok - after 0 -> - ok - end; - {ose_drv_reply,Port,ok} -> - ok - end - catch error:_Error -> - erlang:error(badarg,[Port,{Port,Ref}]) - end; -detach(Port,Ref) -> - erlang:error(badarg,[Port,Ref]). - -%%------------------------------------------------------------------------------ -%% @doc Send an OSE message. -%% -%% The message is sent from the OSE process' own ID that is: `get_id(Port)'. -%% -%% raises: `badarg' -%% -%% @see send/5 -%% @end -%%------------------------------------------------------------------------------ --spec send(Port,Pid,SigNo,SigData) -> ok when - Port :: mailbox(), - Pid :: mailbox_id(), - SigNo :: message_number(), - SigData :: iodata(). -send(Port, Spid, SigNo, SigData) when ?INT_32BIT(Spid), ?INT_32BIT(SigNo) -> - try erlang:port_command(Port, [<<?SEND:8, Spid:32, SigNo:32>>, SigData]) of - true -> ok - catch error:_Error -> - erlang:error(badarg,[Port,Spid,SigNo,SigData]) - end; -send(Port,Spid,SigNo,SigData) -> - erlang:error(badarg,[Port,Spid,SigNo,SigData]). - - -%%------------------------------------------------------------------------------ -%% @doc Send an OSE message with different sender. -%% -%% As {@link send/4} but the sender will be `SenderPid'. -%% -%% raises: `badarg' -%% -%% @see send/4 -%% @end -%%------------------------------------------------------------------------------ --spec send(Port,Pid,SenderPid,SigNo,SigData) -> ok when - Port :: mailbox(), - Pid :: mailbox_id(), - SenderPid :: mailbox_id(), - SigNo :: message_number(), - SigData :: iodata(). -send(Port, Spid, SenderPid, SigNo, SigData) - when ?INT_32BIT(Spid), ?INT_32BIT(SenderPid), ?INT_32BIT(SigNo) -> - try erlang:port_command(Port, [<<?SEND_W_S:8, Spid:32, SenderPid:32, - SigNo:32>>, SigData]) of - true -> ok - catch error:_Error -> - erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]) - end; -send(Port,Spid,SenderPid,SigNo,SigData) -> - erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]). - -%%------------------------------------------------------------------------------ -%% @doc Start listening for specified OSE signal numbers. -%% -%% The mailbox will send `{message,Port,{FromMboxId,ToMboxId,MsgNo,MsgData}}' -%% to the process that created the mailbox when an OSE message with any -%% of the specified `SigNos' arrives. -%% -%% Repeated calls to listen will replace the current set of signal numbers to -%% listen to. i.e -%% -%% ```1>ose:listen(MsgB,[1234,12345]). -%% ok -%% 2> ose:listen(MsgB,[1234,123456]). -%% ok.''' -%% -%% The above will first listen for signals with numbers 1234 and 12345, and then -%% replace that with only listening to 1234 and 123456. -%% -%% With the current implementation it is not possible to listen to all signal -%% numbers. -%% -%% raises: `badarg' | `enomem' -%% -%% @end -%%------------------------------------------------------------------------------ --spec listen(Port, SigNos) -> ok when - Port :: mailbox(), - SigNos :: list(message_number()). -listen(Port, SigNos) when is_list(SigNos) -> - USSigNos = lists:usort(SigNos), - BinSigNos = try - << <<SigNo:32>> || - SigNo <- USSigNos, - ?INT_32BIT(SigNo) orelse erlang:error(badarg) - >> - catch _:_ -> - erlang:error(badarg,[Port,SigNos]) - end, - try port_command(Port, [?LISTEN, BinSigNos]) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - erlang:error(Error,[Port,SigNos]); - {ose_drv_reply,Port,Else} -> - Else - end - catch error:_Error -> - erlang:error(badarg,[Port,SigNos]) - end; -listen(Port, SigNos) -> - erlang:error(badarg,[Port,SigNos]). - - -%%%============================================================================= -%%% Internal functions -%%%============================================================================= diff --git a/lib/ose/test/Makefile b/lib/ose/test/Makefile deleted file mode 100644 index 7e2080ba38..0000000000 --- a/lib/ose/test/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= \ - ose_SUITE - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) - -INSTALL_PROGS= $(TARGET_FILES) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/ose_test - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- - -ERL_MAKE_FLAGS += -ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \ - -I$(ERL_TOP)/lib/kernel/include - -EBIN = . - -EMAKEFILE=Emakefile -COVERFILE=ose.cover - -# ---------------------------------------------------- -# 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) ose.spec $(EMAKEFILE) \ - $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)" - chmod -R u+w "$(RELSYSDIR)" - @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) - -release_docs_spec: diff --git a/lib/ose/test/ose.cover b/lib/ose/test/ose.cover deleted file mode 100644 index 7b846cfaf6..0000000000 --- a/lib/ose/test/ose.cover +++ /dev/null @@ -1,2 +0,0 @@ -%% -*- erlang -*- -{incl_app,ose,details}. diff --git a/lib/ose/test/ose.spec b/lib/ose/test/ose.spec deleted file mode 100644 index c897e8cd16..0000000000 --- a/lib/ose/test/ose.spec +++ /dev/null @@ -1 +0,0 @@ -{suites,"../ose_test",all}. diff --git a/lib/ose/test/ose_SUITE.erl b/lib/ose/test/ose_SUITE.erl deleted file mode 100644 index 31d950bd03..0000000000 --- a/lib/ose/test/ose_SUITE.erl +++ /dev/null @@ -1,766 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(ose_SUITE). - -%-compile(export_all). - --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2,init_per_testcase/2, - end_per_testcase/2]). --export([ - basic/1,stress/1,multi_msg_numbers/1,multi_mailboxes/1, - hunt/1,multi_hunt/1,dehunt/1,multi_dehunt/1, - attach/1,multi_attach/1,detach/1,multi_detach/1, - open_errors/1,close_errors/1,get_id_errors/1,get_name_errors/1, - hunt_errors/1,dehunt_errors/1,attach_errors/1,detach_errors/1, - send_errors/1,send_w_s_errors/1,listen_errors/1 - ]). - --define(INTERFACE,ose). - - -init_per_testcase(_Func, Config) -> - Config. -end_per_testcase(_Func, _Config) -> - ok. - -suite() -> [{timeout,{30,seconds}}]. - -all() -> - [ - basic,stress,multi_msg_numbers,multi_mailboxes, - hunt,multi_hunt,dehunt,multi_dehunt, - attach,multi_attach,detach,multi_detach, - - open_errors,close_errors,get_id_errors,get_name_errors, - hunt_errors,dehunt_errors,attach_errors,detach_errors, - send_errors,send_w_s_errors,listen_errors - ]. - -groups() -> - []. - -init_per_suite(Config) -> - case os:type() of - {ose,_} -> - Config; - _Else -> - {skip,"Only run on OSE"} - end. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -basic(_Config) -> - - [P1,P2] = multi_open(2,[42]), - P1Id = ?INTERFACE:get_id(P1), - P2Id = ?INTERFACE:get_id(P2), - - ok = ?INTERFACE:send(P2,P1Id,42,<<"ping">>), - receive - {message,P1,V1} -> - {P2Id,P1Id,42,<<"ping">>} = V1, - ?INTERFACE:send(P1,P2Id,42,<<"pong">>); - Else1 -> - ct:fail({got_wrong_message,Else1}) - end, - - receive - {message,P2,V2} -> - {P1Id,P2Id,42,<<"pong">>} = V2; - Else2 -> - ct:fail({got_wrong_message,Else2}) - end, - - ?INTERFACE:close(P1), - ?INTERFACE:close(P2). - -%% Send 1000 messages and see if we can cope and that msg order is preserved -stress(_Config) -> - - Iterations = 1000, - - [P1,P2] = multi_open(2,[42]), - P1Id = ?INTERFACE:get_id(P1), - P2Id = ?INTERFACE:get_id(P2), - - spawn(fun() -> - n(fun(N) -> - Msg = [<<"ping">>|integer_to_list(N)], - ?INTERFACE:send(P2,P1Id,42,Msg) - end,Iterations) - end), - timer:sleep(100), - n(fun(N) -> - receive - {message,P1,Value} -> - Int = integer_to_binary(N), - {P2Id,P1Id,42,<<"ping",Int/binary>>} = Value, - ok; - Else -> - ct:fail({got_wrong_message,Else}) - end - end,Iterations), - - ?INTERFACE:close(P1), - ?INTERFACE:close(P2). - -%% Listen to 1000 different message numbers and send some random messages -multi_msg_numbers(_Config) -> - - Iterations = 100, - - [P1,P2] = multi_open(2,lists:seq(2000,3000)), - P1Id = ?INTERFACE:get_id(P1), - - n(fun(_) -> - Num = random:uniform(1000)+2000, - ?INTERFACE:send(P2,P1Id,Num,<<"ping",(integer_to_binary(Num))/binary>>) - end,Iterations), - - n(fun(_) -> - receive - {message,P1,{_,_,Id,<<"ping",Num/binary>>}} when Id > 2000; - Id =< 3000 -> - Id = binary_to_integer(Num), - ok; - Else -> - ct:fail({got_wrong_message,Else}) - end - end,Iterations), - - ?INTERFACE:close(P1), - ?INTERFACE:close(P2). - - -%% Create 100 mailboxes and send messages to them -multi_mailboxes(_Config) -> - - Mailboxes = 100, - - [P1|MBs] = multi_open(Mailboxes,[42]), - - [?INTERFACE:send(P1,?INTERFACE:get_id(P),42,[<<"ping">>,?INTERFACE:get_name(P,?INTERFACE:get_id(P))]) || P <- MBs], - - [receive - {message,P,Value} -> - Name = ?INTERFACE:get_name(P,?INTERFACE:get_id(P)), - {_,_,42,<<"ping",Name/binary>>} = Value, - ok - end || P <- MBs], - - [?INTERFACE:close(P) || P <- [P1|MBs]], - ok. - -hunt(_Config) -> - [P1,P2] = multi_open(2,[]), - - Ref = ?INTERFACE:hunt(P1,"p2"), - receive - {mailbox_up,P1,Ref,Pid} -> - Pid = ?INTERFACE:get_id(P2), - ?INTERFACE:close(P1), - ?INTERFACE:close(P2); - Else -> - ct:fail({got_wrong_message,Else,Ref}) - end. - -multi_hunt(_Config) -> - - Iterations = 100, - - P = ?INTERFACE:open("p"), - - Refs = [?INTERFACE:hunt(P,"p"++integer_to_list(N))|| N <- lists:seq(1,Iterations)], - - Pids = [begin - Prt = ?INTERFACE:open("p"++integer_to_list(N)), - Pid = ?INTERFACE:get_id(Prt), - ?INTERFACE:close(Prt), - Pid - end || N <- lists:seq(1,Iterations)], - - [receive - {mailbox_up,P,Ref,Pid} -> - ok - after 10 -> - ct:fail({did_not_get,Pid,Ref}) - end || {Pid,Ref} <- lists:zip(Pids,Refs)], - ?INTERFACE:close(P). - - -dehunt(_Config) -> - [P1] = multi_open(1,[]), - Ref = ?INTERFACE:hunt(P1,"p2"), - receive - _Else -> ct:fail({got,_Else}) - after 1000 -> - ok - end, - P2 = ?INTERFACE:open("p2"), - - % Make sure any messages are sent - receive after 10 -> ok end, - - ok = ?INTERFACE:dehunt(P1,Ref), - - % Make sure no messages are received - receive - _Else2 -> ct:fail({got,_Else2}) - after 1000 -> - ?INTERFACE:close(P1), - ?INTERFACE:close(P2) - end. - -%%% -%%% This testcase basically: -%%% spawn 10 processes that in parallel -%%% adds some hunts for different OSE processes -%%% maybe create hunted OSE process -%%% dehunt half of the hunts -%%% create more hunts -%%% if not created create hunted OSE process -%%% veryify that all expected hunt messages are received -%%% verify that all processes exited correctly -%%% -%%% This complex test is done to make sure that the internal handling -%%% of dehunt works as expected. -%%% -multi_dehunt(_Config) -> - [P1] = multi_open(1,[]), - - Scenario = - fun(Iterations) -> - - Hunted = "p"++integer_to_list(Iterations), - %% Start a couple of hunts - Refs = [?INTERFACE:hunt(P1,Hunted) || _ <- lists:seq(1,Iterations)], - - %% We alternate if the process is opened before or after the dehunt - P2O = if Iterations rem 2 == 0 -> - ?INTERFACE:open(Hunted); - true -> - undefined - end, - - %% Remove half of them - {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> - ok = ?INTERFACE:dehunt(P1,Ref), - {[],Acc+1}; - (Ref,Acc) -> - {Ref,Acc+1} - end,0,Refs), - - %% Add some new ones - NewRefs = [?INTERFACE:hunt(P1,Hunted) - || _ <- lists:seq(1,Iterations div 4)] - ++ lists:flatten(RemRefs), - - P2 = if P2O == undefined -> - ?INTERFACE:open(Hunted); - true -> - P2O - end, - P2Id = ?INTERFACE:get_id(P2), - - %% Receive all the expected ones - lists:foreach(fun(Ref) -> - receive - {mailbox_up,P1,Ref,P2Id} -> - ok - after 1000 -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), - ok = Ref - end - end,NewRefs), - - %% Check that no other have arrived - receive - _Else -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{got, _Else}}]), - ok = _Else - after 100 -> - ok - end, - ?INTERFACE:close(P2) - end, - - Self = self(), - - n(fun(N) -> - spawn(fun() -> Self ! - Scenario(N*25) - end), - ok - end,10), - - n(fun(_N) -> - receive ok -> ok - after 60000 -> ct:fail(failed) - end - end,10), - ?INTERFACE:close(P1). - -attach(_Config) -> - [P1,P2] = multi_open(2,[]), - - P2Id = ?INTERFACE:get_id(P2), - Ref = ?INTERFACE:attach(P1,P2Id), - ?INTERFACE:close(P2), - receive - {mailbox_down,P1,Ref,P2Id} -> - ?INTERFACE:close(P1); - _Else -> - ct:fail({got,_Else, {P1,Ref,P2Id}}) - after 1000 -> - ct:fail({did_not_get,P1,Ref,P2Id}) - end. - -multi_attach(_Config) -> - - Iterations = 100, - - [P1|Pids] = multi_open(Iterations,[]), - - Refs = [{?INTERFACE:get_id(Pid),?INTERFACE:attach(P1,?INTERFACE:get_id(Pid))} || Pid <- Pids], - - [?INTERFACE:close(Pid) || Pid <- Pids], - - [receive - {mailbox_down,P1,Ref,Pid} -> - ok - after 10000 -> - ct:fail({did_not_get,Pid,Ref}) - end || {Pid,Ref} <- Refs], - ?INTERFACE:close(P1). - -detach(_Config) -> - [P1,P2] = multi_open(2,[]), - P2Id = ?INTERFACE:get_id(P2), - Ref = ?INTERFACE:attach(P1,P2Id), - receive - _Else -> ct:fail({got,_Else}) - after 100 -> - ok - end, - - ?INTERFACE:close(P2), - - % Make sure any messages are sent - receive after 10 -> ok end, - - ?INTERFACE:detach(P1,Ref), - - % Make sure no messages are received - receive - _Else2 -> ct:fail({got,_Else2}) - after 1000 -> - ?INTERFACE:close(P1) - end. - -%%% -%%% This testcase basically: -%%% spawn 10 processes that in parallel -%%% adds some attach for different OSE processes -%%% maybe close OSE process -%%% dehunt half of the hunts -%%% create more hunts -%%% if not closed close attached OSE process -%%% veryify that all expected attach messages are received -%%% verify that all processes exited correctly -%%% -%%% This complex test is done to make sure that the internal handling -%%% of dehunt works as expected. -%%% -multi_detach(_Config) -> - [P1] = multi_open(1,[]), - - Scenario = - fun(Iterations) -> - - Attached = ?INTERFACE:open("p"++integer_to_list(Iterations)), - AttachedId = ?INTERFACE:get_id(Attached), - %% Start a couple of attachs - Refs = [?INTERFACE:attach(P1,AttachedId) || _ <- lists:seq(1,Iterations)], - - %% We alternate if the process is closed before or after the detach - P2O = if Iterations rem 2 == 0 -> - ?INTERFACE:close(Attached); - true -> - undefined - end, - - %% Remove half of them - {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> - ok = ?INTERFACE:detach(P1,Ref), - {[],Acc+1}; - (Ref,Acc) -> - {Ref,Acc+1} - end,0,Refs), - - %% Add some new ones - NewRefs = [?INTERFACE:attach(P1,AttachedId) - || _ <- lists:seq(1,Iterations div 4)] - ++ lists:flatten(RemRefs), - - if P2O == undefined -> - ?INTERFACE:close(Attached); - true -> - P2O - end, - - %% Receive all the expected ones - lists:foreach(fun(Ref) -> - receive - {mailbox_down,P1,Ref,AttachedId} -> - ok - after 1000 -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), - ok = Ref - end - end,NewRefs), - - %% Check that no other have arrived - receive - _Else -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{got, _Else}}]), - ok = _Else - after 100 -> - ok - end - end, - - Self = self(), - - n(fun(N) -> - spawn(fun() -> Self ! - Scenario(N*5) - end), - ok - end,10), - - n(fun(_N) -> - receive ok -> ok - after 60000 -> ct:fail(failed) - end - end,10), - ?INTERFACE:close(P1). - - -open_errors(_Config) -> - {'EXIT',{badarg,[{?INTERFACE,open,[inval],_}|_]}} = - (catch ?INTERFACE:open(inval)), - {'EXIT',{badarg,[{?INTERFACE,open,[["p"|1]],_}|_]}} = - (catch ?INTERFACE:open(["p"|1])), - {'EXIT',{badarg,[{?INTERFACE,open,[["p",1234]],_}|_]}} = - (catch ?INTERFACE:open(["p",1234])), - - ok. - -close_errors(_Config) -> - {'EXIT',{badarg,[{?INTERFACE,close,[inval],_}|_]}} = - (catch ?INTERFACE:close(inval)), - - P1 = ?INTERFACE:open("p1"), - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:close(P1). - - -get_id_errors(_Config) -> - {'EXIT',{badarg,[{?INTERFACE,get_id,[inval],_}|_]}} = - (catch ?INTERFACE:get_id(inval)), - - P1 = ?INTERFACE:open("p1"), - ok = ?INTERFACE:close(P1), - {'EXIT',{badarg,[{?INTERFACE,get_id,[P1],_}|_]}} = - (catch ?INTERFACE:get_id(P1)), - - ok. - -get_name_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,inval],_}|_]}} = - (catch ?INTERFACE:get_name(P1,inval)), - - undefined = ?INTERFACE:get_name(P1,1234), - - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - ok = ?INTERFACE:close(P1), - {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,P2Id],_}|_]}} = - (catch ?INTERFACE:get_name(P1,P2Id)), - ?INTERFACE:close(P2), - - P3 = ?INTERFACE:open([255]), - <<255>> = ?INTERFACE:get_name(P3, ?INTERFACE:get_id(P3)), - ?INTERFACE:close(P3), - - ok. - -hunt_errors(_Config) -> - - {'EXIT',{badarg,[{?INTERFACE,hunt,[inval,"hello"],_}|_]}} = - (catch ?INTERFACE:hunt(inval,"hello")), - - P1 = ?INTERFACE:open("p1"), - {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello",12345]],_}|_]}} = - (catch ?INTERFACE:hunt(P1,["hello",12345])), - - P2 = ?INTERFACE:open(<<255>>), - P2Pid = ?INTERFACE:get_id(P2), - Ref = ?INTERFACE:hunt(P1,[255]), - receive - {mailbox_up,P1,Ref,P2Pid} -> - ok; - Else -> - ct:fail({got,Else,{mailbox_up,P1,Ref,P2Pid}}) - after 150 -> - ct:fail({did_not_get,{mailbox_up,P1,Ref,P2Pid}}) - end, - - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:close(P2), - {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello"]],_}|_]}} = - (catch ?INTERFACE:hunt(P1,["hello"])), - - ok. - -dehunt_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - Ref = ?INTERFACE:hunt(P1,"p2"), - - {'EXIT',{badarg,[{?INTERFACE,dehunt,[inval,Ref],_}|_]}} = - (catch ?INTERFACE:dehunt(inval,Ref)), - - {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,inval],_}|_]}} = - (catch ?INTERFACE:dehunt(P1,inval)), - - ok = ?INTERFACE:dehunt(P1,Ref), - ok = ?INTERFACE:dehunt(P1,Ref), - - ok = ?INTERFACE:close(P1), - - {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,Ref],_}|_]}} = - (catch ?INTERFACE:dehunt(P1,Ref)), - - case ?INTERFACE of - ose -> ok; - _ -> - P2 = ?INTERFACE:open("p2"), - ok = ?INTERFACE:close(P2) - end, - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -attach_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - - {'EXIT',{badarg,[{?INTERFACE,attach,[inval,P2Id],_}|_]}} = - (catch ?INTERFACE:attach(inval,P2Id)), - - {'EXIT',{badarg,[{?INTERFACE,attach,[P1,[12345]],_}|_]}} = - (catch ?INTERFACE:attach(P1,[12345])), - - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:close(P2), - {'EXIT',{badarg,[{?INTERFACE,attach,[P1,P2Id],_}|_]}} = - (catch ?INTERFACE:attach(P1,P2Id)), - - ok. - -detach_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - - Ref = ?INTERFACE:attach(P1,P2Id), - - {'EXIT',{badarg,[{?INTERFACE,detach,[inval,Ref],_}|_]}} = - (catch ?INTERFACE:detach(inval,Ref)), - - {'EXIT',{badarg,[{?INTERFACE,detach,[P1,inval],_}|_]}} = - (catch ?INTERFACE:detach(P1,inval)), - - ok = ?INTERFACE:detach(P1,Ref), - ok = ?INTERFACE:detach(P1,Ref), - - case ?INTERFACE of - ose -> ok; - _ -> - ok = ?INTERFACE:close(P1) - end, - - ok = ?INTERFACE:close(P2), - ok = ?INTERFACE:close(P1), - - {'EXIT',{badarg,[{?INTERFACE,detach,[P1,Ref],_}|_]}} = - (catch ?INTERFACE:detach(P1,Ref)), - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -send_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - - {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(inval,P2Id,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P1,inval,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,inval,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,inval,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,inval,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,inval],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,42,inval)), - - ok = ?INTERFACE:close(P2), - ok = ?INTERFACE:send(P1,P2Id,42,"hello"), - ok = ?INTERFACE:close(P1), - - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,42,"hello")), - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -send_w_s_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P1Id = ?INTERFACE:get_id(P1), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - P3 = ?INTERFACE:open("p3"), - P3Id = ?INTERFACE:get_id(P3), - - {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,P1Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(inval,P2Id,P1Id,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,-1,P1Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P2,-1,P1Id,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,1 bsl 32,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P2,P2Id,1 bsl 32,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,inval,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P2,P2Id,P1Id,inval,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,42,inval],_}|_]}} = - (catch ?INTERFACE:send(P2,P2Id,P1Id,42,inval)), - - ok = ?INTERFACE:close(P3), - ok = ?INTERFACE:send(P2,P3Id,P1Id,42,"hello"), - - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:send(P2,P2Id,P1Id,42,"hello"), - ok = ?INTERFACE:close(P2), - - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,P1Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,P1Id,42,"hello")), - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -listen_errors(_Config) -> - - P1 = ?INTERFACE:open("p1"), - P1Id = ?INTERFACE:get_id(P1), - - {'EXIT',{badarg,[{?INTERFACE,listen,[inval,[42]],_}|_]}} = - (catch ?INTERFACE:listen(inval,[42])), - {'EXIT',{badarg,[{?INTERFACE,listen,[P1,inval],_}|_]}} = - (catch ?INTERFACE:listen(P1,inval)), - {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[1 bsl 33]],_}|_]}} = - (catch ?INTERFACE:listen(P1,[1 bsl 33])), - - ok = ?INTERFACE:listen(P1,[42,42,42,42,42,42,42,42,42,42,42,42,42]), - - case ?INTERFACE of - ose -> ok; - _ -> - ?INTERFACE:send(P1,P1Id,42,"hello"), - timer:sleep(50), - ?INTERFACE:listen(P1,[]), - ?INTERFACE:send(P1,P1Id,42,"hello2"), - - receive - {message,P1,42,"hello"} -> ok - end, - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end - end, - - ok = ?INTERFACE:close(P1), - {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[42]],_}|_]}} = - (catch ?INTERFACE:listen(P1,[42])), - - ok. - -%% -%% Internal functions -%% -multi_open(N,ListenNums) -> - multi_open(N,ListenNums,[]). - -multi_open(0,_,Acc) -> - Acc; -multi_open(N,ListenNums,Acc) -> - P = ?INTERFACE:open("p"++integer_to_list(N)), - ok = ?INTERFACE:listen(P,ListenNums), - multi_open(N-1,ListenNums,[P|Acc]). - -n(_F,0) -> - ok; -n(F,N) -> - ok = F(N), - n(F,N-1). - - -flush() -> - receive - Msg -> - [Msg|flush()] - after 0 -> - [] - end. diff --git a/lib/ose/vsn.mk b/lib/ose/vsn.mk deleted file mode 100644 index fb1cf8219f..0000000000 --- a/lib/ose/vsn.mk +++ /dev/null @@ -1 +0,0 @@ -OSE_VSN = 1.1 diff --git a/lib/parsetools/doc/src/leex.xml b/lib/parsetools/doc/src/leex.xml index 7ee0633dac..85680f58a6 100644 --- a/lib/parsetools/doc/src/leex.xml +++ b/lib/parsetools/doc/src/leex.xml @@ -47,7 +47,7 @@ Token = tuple()</code> <v>LeexRet = {ok, Scannerfile} | {ok, Scannerfile, Warnings} | error - | {error, Warnings, Errors}</v> + | {error, Errors, Warnings}</v> <v>Scannerfile = filename()</v> <v>Warnings = Errors = [{filename(), [ErrorInfo]}]</v> <v>ErrorInfo = {ErrorLine, module(), Reason}</v> diff --git a/lib/parsetools/doc/src/yecc.xml b/lib/parsetools/doc/src/yecc.xml index 8c356099e7..87fdfcdaef 100644 --- a/lib/parsetools/doc/src/yecc.xml +++ b/lib/parsetools/doc/src/yecc.xml @@ -52,7 +52,7 @@ <v>Grammarfile = filename()</v> <v>Options = Option | [Option]</v> <v>Option = - see below -</v> - <v>YeccRet = {ok, Parserfile} | {ok, Parserfile, Warnings} | error | {error, Warnings, Errors}</v> + <v>YeccRet = {ok, Parserfile} | {ok, Parserfile, Warnings} | error | {error, Errors, Warnings}</v> <v>Parserfile = filename()</v> <v>Warnings = Errors = [{filename(), [ErrorInfo]}]</v> <v>ErrorInfo = {ErrorLine, module(), Reason}</v> diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml index 87db5bd9f4..8034d7fade 100644 --- a/lib/public_key/doc/src/notes.xml +++ b/lib/public_key/doc/src/notes.xml @@ -35,6 +35,21 @@ <file>notes.xml</file> </header> +<section><title>Public_Key 1.0.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Document enhancements</p> + <p> + Own Id: OTP-12986</p> + </item> + </list> + </section> + +</section> + <section><title>Public_Key 1.0</title> <section><title>Improvements and New Features</title> diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 209de2bdf7..b247618efc 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -498,13 +498,13 @@ <name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} </name> <fsummary>Performs a basic path validation according to RFC 5280.</fsummary> <type> - <v>TrustedCert = #'OTPCertificate'{} | der_encode() | atom()</v> + <v>TrustedCert = #'OTPCertificate'{} | der_encoded() | atom()</v> <d>Normally a trusted certificate, but it can also be a path-validation error that can be discovered while constructing the input to this function and that is to be run through the <c>verify_fun</c>. Examples are <c>unknown_ca</c> and <c>selfsigned_peer.</c> </d> - <v>CertChain = [der_encode()]</v> + <v>CertChain = [der_encoded()]</v> <d>A list of DER-encoded certificates in trust order ending with the peer certificate.</d> <v>Options = proplists:proplist()</v> <v>PublicKeyInfo = {?'rsaEncryption' | ?'id-dsa', diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl index 7680d0ce59..82042550a0 100644 --- a/lib/public_key/src/pubkey_ssh.erl +++ b/lib/public_key/src/pubkey_ssh.erl @@ -21,9 +21,12 @@ -include("public_key.hrl"). --export([decode/2, encode/2]). +-export([decode/2, encode/2 + ]). -define(UINT32(X), X:32/unsigned-big-integer). +-define(STRING(X), ?UINT32((size(X))), (X)/binary). + %% Max encoded line length is 72, but conformance examples use 68 %% Comment from rfc 4716: "The following are some examples of public %% key files that are compliant (note that the examples all wrap @@ -31,13 +34,16 @@ %% are still compliant.)" So we choose to use 68 also. -define(ENCODED_LINE_LENGTH, 68). + %%==================================================================== %% Internal application API %%==================================================================== %%-------------------------------------------------------------------- -spec decode(binary(), public_key | public_key:ssh_file()) -> - [{public_key:public_key(), Attributes::list()}]. + [{public_key:public_key(), Attributes::list()}] + ; (binary(), ssh2_pubkey) -> public_key:public_key() + . %% %% Description: Decodes a ssh file-binary. %%-------------------------------------------------------------------- @@ -50,15 +56,21 @@ decode(Bin, public_key)-> end; decode(Bin, rfc4716_public_key) -> rfc4716_decode(Bin); +decode(Bin, ssh2_pubkey) -> + ssh2_pubkey_decode(Bin); decode(Bin, Type) -> openssh_decode(Bin, Type). %%-------------------------------------------------------------------- -spec encode([{public_key:public_key(), Attributes::list()}], public_key:ssh_file()) -> - binary(). + binary() + ; (public_key:public_key(), ssh2_pubkey) -> binary() + . %% %% Description: Encodes a list of ssh file entries. %%-------------------------------------------------------------------- +encode(Bin, ssh2_pubkey) -> + ssh2_pubkey_encode(Bin); encode(Entries, Type) -> iolist_to_binary(lists:map(fun({Key, Attributes}) -> do_encode(Type, Key, Attributes) @@ -130,7 +142,12 @@ rfc4716_pubkey_decode(<<?UINT32(Len), Type:Len/binary, {erlint(SizeY, Y), #'Dss-Parms'{p = erlint(SizeP, P), q = erlint(SizeQ, Q), - g = erlint(SizeG, G)}}. + g = erlint(SizeG, G)}}; +rfc4716_pubkey_decode(<<?UINT32(Len), ECDSA_SHA2_etc:Len/binary, + ?UINT32(SizeId), Id:SizeId/binary, + ?UINT32(SizeQ), Q:SizeQ/binary>>) -> + <<"ecdsa-sha2-", Id/binary>> = ECDSA_SHA2_etc, + {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}. openssh_decode(Bin, FileType) -> Lines = binary:split(Bin, <<"\n">>, [global]), @@ -184,46 +201,42 @@ do_openssh_decode(known_hosts = FileType, [Line | Lines], Acc) -> end; do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) -> - case split_n(2, Line, []) of - [KeyType, Base64Enc] when KeyType == <<"ssh-rsa">>; - KeyType == <<"ssh-dss">> -> + [KeyType, Base64Enc | Comment0] = split_n(2, Line, []), + KnownKeyType = + case KeyType of + <<"ssh-rsa">> -> true; + <<"ssh-dss">> -> true; + <<"ecdsa-sha2-",Curve/binary>> -> is_ssh_curvename(Curve); + _ -> false + end, + + case Comment0 of + [] when KnownKeyType==true -> do_openssh_decode(FileType, Lines, [{openssh_pubkey_decode(KeyType, Base64Enc), []} | Acc]); - [KeyType, Base64Enc | Comment0] when KeyType == <<"ssh-rsa">>; - KeyType == <<"ssh-dss">> -> + _ when KnownKeyType==true -> Comment = string:strip(string_decode(iolist_to_binary(Comment0)), right, $\n), do_openssh_decode(FileType, Lines, [{openssh_pubkey_decode(KeyType, Base64Enc), [{comment, Comment}]} | Acc]) end. + decode_comment([]) -> []; decode_comment(Comment) -> [{comment, string_decode(iolist_to_binary(Comment))}]. -openssh_pubkey_decode(<<"ssh-rsa">>, Base64Enc) -> - <<?UINT32(StrLen), _:StrLen/binary, - ?UINT32(SizeE), E:SizeE/binary, - ?UINT32(SizeN), N:SizeN/binary>> - = base64:mime_decode(Base64Enc), - #'RSAPublicKey'{modulus = erlint(SizeN, N), - publicExponent = erlint(SizeE, E)}; -openssh_pubkey_decode(<<"ssh-dss">>, Base64Enc) -> - <<?UINT32(StrLen), _:StrLen/binary, - ?UINT32(SizeP), P:SizeP/binary, - ?UINT32(SizeQ), Q:SizeQ/binary, - ?UINT32(SizeG), G:SizeG/binary, - ?UINT32(SizeY), Y:SizeY/binary>> - = base64:mime_decode(Base64Enc), - {erlint(SizeY, Y), - #'Dss-Parms'{p = erlint(SizeP, P), - q = erlint(SizeQ, Q), - g = erlint(SizeG, G)}}; -openssh_pubkey_decode(KeyType, Base64Enc) -> - {KeyType, base64:mime_decode(Base64Enc)}. +openssh_pubkey_decode(Type, Base64Enc) -> + try + ssh2_pubkey_decode(Type, base64:mime_decode(Base64Enc)) + catch + _:_ -> + {Type, base64:mime_decode(Base64Enc)} + end. + erlint(MPIntSize, MPIntValue) -> Bits= MPIntSize * 8, @@ -347,10 +360,9 @@ line_end("") -> line_end(Comment) -> [" ", Comment, "\n"]. -key_type(#'RSAPublicKey'{}) -> - <<"ssh-rsa">>; -key_type({_, #'Dss-Parms'{}}) -> - <<"ssh-dss">>. +key_type(#'RSAPublicKey'{}) -> <<"ssh-rsa">>; +key_type({_, #'Dss-Parms'{}}) -> <<"ssh-dss">>; +key_type({#'ECPoint'{}, {namedCurve,Curve}}) -> <<"ecdsa-sha2-", (public_key:oid2ssh_curvename(Curve))/binary>>. comma_list_encode([Option], []) -> Option; @@ -380,20 +392,49 @@ ssh2_pubkey_encode({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) -> PBin/binary, QBin/binary, GBin/binary, - YBin/binary>>. - -is_key_field(<<"ssh-dss">>) -> - true; -is_key_field(<<"ssh-rsa">>) -> - true; -is_key_field(<<"ecdsa-sha2-nistp256">>) -> - true; -is_key_field(<<"ecdsa-sha2-nistp384">>) -> - true; -is_key_field(<<"ecdsa-sha2-nistp521">>) -> - true; -is_key_field(_) -> - false. + YBin/binary>>; +ssh2_pubkey_encode(Key={#'ECPoint'{point = Q}, {namedCurve,OID}}) -> + TypeStr = key_type(Key), + StrLen = size(TypeStr), + IdB = public_key:oid2ssh_curvename(OID), + <<?UINT32(StrLen), TypeStr:StrLen/binary, + (string(IdB))/binary, + (string(Q))/binary>>. + + +ssh2_pubkey_decode(Bin = <<?UINT32(Len), Type:Len/binary, _/binary>>) -> + ssh2_pubkey_decode(Type, Bin). + +ssh2_pubkey_decode(<<"ssh-rsa">>, + <<?UINT32(Len), _:Len/binary, + ?UINT32(SizeE), E:SizeE/binary, + ?UINT32(SizeN), N:SizeN/binary>>) -> + #'RSAPublicKey'{modulus = erlint(SizeN, N), + publicExponent = erlint(SizeE, E)}; + +ssh2_pubkey_decode(<<"ssh-dss">>, + <<?UINT32(Len), _:Len/binary, + ?UINT32(SizeP), P:SizeP/binary, + ?UINT32(SizeQ), Q:SizeQ/binary, + ?UINT32(SizeG), G:SizeG/binary, + ?UINT32(SizeY), Y:SizeY/binary>>) -> + {erlint(SizeY, Y), + #'Dss-Parms'{p = erlint(SizeP, P), + q = erlint(SizeQ, Q), + g = erlint(SizeG, G)}}; +ssh2_pubkey_decode(<<"ecdsa-sha2-",Id/binary>>, + <<?UINT32(Len), ECDSA_SHA2_etc:Len/binary, + ?UINT32(SizeId), Id:SizeId/binary, + ?UINT32(SizeQ), Q:SizeQ/binary>>) -> + <<"ecdsa-sha2-", Id/binary>> = ECDSA_SHA2_etc, + {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}. + + + +is_key_field(<<"ssh-dss">>) -> true; +is_key_field(<<"ssh-rsa">>) -> true; +is_key_field(<<"ecdsa-sha2-",Id/binary>>) -> is_ssh_curvename(Id); +is_key_field(_) -> false. is_bits_field(Part) -> try list_to_integer(binary_to_list(Part)) of @@ -507,3 +548,14 @@ int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 -> list_to_binary(Ds); int_to_bin_neg(X,Ds) -> int_to_bin_neg(X bsr 8, [(X band 255)|Ds]). + + +string(X) when is_binary(X) -> + << ?STRING(X) >>; +string(X) -> + << ?STRING(list_to_binary(X)) >>. + +is_ssh_curvename(Id) -> try public_key:ssh_curvename2oid(Id) of _ -> true + catch _:_ -> false + end. + diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 2f4cc64c2a..8288f68f7f 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -47,6 +47,7 @@ pkix_normalize_name/1, pkix_path_validation/3, ssh_decode/2, ssh_encode/2, + ssh_curvename2oid/1, oid2ssh_curvename/1, pkix_crls_validate/3, pkix_dist_point/1, pkix_dist_points/1, @@ -711,7 +712,9 @@ pkix_crls_validate(OtpCert, DPAndCRLs0, Options) -> %%-------------------------------------------------------------------- --spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}]. +-spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}] + ; (binary(), ssh2_pubkey) -> public_key() + . %% %% Description: Decodes a ssh file-binary. In the case of know_hosts %% or auth_keys the binary may include one or more lines of the @@ -724,12 +727,15 @@ ssh_decode(SshBin, Type) when is_binary(SshBin), Type == rfc4716_public_key; Type == openssh_public_key; Type == auth_keys; - Type == known_hosts -> + Type == known_hosts; + Type == ssh2_pubkey -> pubkey_ssh:decode(SshBin, Type). %%-------------------------------------------------------------------- --spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) -> - binary(). +-spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) -> binary() + ; (public_key(), ssh2_pubkey) -> binary() + . +%% %% Description: Encodes a list of ssh file entries (public keys and %% attributes) to a binary. Possible attributes depends on the file %% type. @@ -738,10 +744,30 @@ ssh_encode(Entries, Type) when is_list(Entries), Type == rfc4716_public_key; Type == openssh_public_key; Type == auth_keys; - Type == known_hosts -> + Type == known_hosts; + Type == ssh2_pubkey -> pubkey_ssh:encode(Entries, Type). %%-------------------------------------------------------------------- +-spec ssh_curvename2oid(binary()) -> oid(). + +%% Description: Converts from the ssh name of elliptic curves to +%% the OIDs. +%%-------------------------------------------------------------------- +ssh_curvename2oid(<<"nistp256">>) -> ?'secp256r1'; +ssh_curvename2oid(<<"nistp384">>) -> ?'secp384r1'; +ssh_curvename2oid(<<"nistp521">>) -> ?'secp521r1'. + +%%-------------------------------------------------------------------- +-spec oid2ssh_curvename(oid()) -> binary(). + +%% Description: Converts from elliptic curve OIDs to the ssh name. +%%-------------------------------------------------------------------- +oid2ssh_curvename(?'secp256r1') -> <<"nistp256">>; +oid2ssh_curvename(?'secp384r1') -> <<"nistp384">>; +oid2ssh_curvename(?'secp521r1') -> <<"nistp521">>. + +%%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- do_verify(DigestOrPlainText, DigestType, Signature, diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl index 6f142c951c..5e677f31d6 100644 --- a/lib/public_key/test/public_key_SUITE.erl +++ b/lib/public_key/test/public_key_SUITE.erl @@ -49,8 +49,10 @@ groups() -> [{pem_decode_encode, [], [dsa_pem, rsa_pem, encrypted_pem, dh_pem, cert_pem, pkcs7_pem, pkcs10_pem]}, {ssh_public_key_decode_encode, [], - [ssh_rsa_public_key, ssh_dsa_public_key, ssh_rfc4716_rsa_comment, - ssh_rfc4716_dsa_comment, ssh_rfc4716_rsa_subject, ssh_known_hosts, + [ssh_rsa_public_key, ssh_dsa_public_key, ssh_ecdsa_public_key, + ssh_rfc4716_rsa_comment, ssh_rfc4716_dsa_comment, + ssh_rfc4716_rsa_subject, + ssh_known_hosts, ssh_auth_keys, ssh1_known_hosts, ssh1_auth_keys, ssh_openssh_public_key_with_comment, ssh_openssh_public_key_long_header]}, {sign_verify, [], [rsa_sign_verify, dsa_sign_verify]} @@ -291,6 +293,32 @@ ssh_dsa_public_key(Config) when is_list(Config) -> public_key:ssh_decode(EncodedOpenSsh, public_key). %%-------------------------------------------------------------------- + +ssh_ecdsa_public_key() -> + [{doc, "ssh ecdsa public key decode/encode"}]. +ssh_ecdsa_public_key(Config) when is_list(Config) -> + Datadir = ?config(data_dir, Config), + + {ok, ECDSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_ecdsa_pub")), + [{PubKey, Attributes1}] = public_key:ssh_decode(ECDSARawSsh2, public_key), + [{PubKey, Attributes1}] = public_key:ssh_decode(ECDSARawSsh2, rfc4716_public_key), + + {ok, ECDSARawOpenSsh} = file:read_file(filename:join(Datadir, "openssh_ecdsa_pub")), + [{PubKey, Attributes2}] = public_key:ssh_decode(ECDSARawOpenSsh, public_key), + [{PubKey, Attributes2}] = public_key:ssh_decode(ECDSARawOpenSsh, openssh_public_key), + + %% Can not check EncodedSSh == ECDSARawSsh2 and EncodedOpenSsh + %% = ECDSARawOpenSsh as line breakpoints may differ + + EncodedSSh = public_key:ssh_encode([{PubKey, Attributes1}], rfc4716_public_key), + EncodedOpenSsh = public_key:ssh_encode([{PubKey, Attributes2}], openssh_public_key), + + [{PubKey, Attributes1}] = + public_key:ssh_decode(EncodedSSh, public_key), + [{PubKey, Attributes2}] = + public_key:ssh_decode(EncodedOpenSsh, public_key). + +%%-------------------------------------------------------------------- ssh_rfc4716_rsa_comment() -> [{doc, "Test comment header and rsa key"}]. ssh_rfc4716_rsa_comment(Config) when is_list(Config) -> diff --git a/lib/public_key/test/public_key_SUITE_data/openssh_ecdsa_pub b/lib/public_key/test/public_key_SUITE_data/openssh_ecdsa_pub new file mode 100644 index 0000000000..a49b4264b8 --- /dev/null +++ b/lib/public_key/test/public_key_SUITE_data/openssh_ecdsa_pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIJrVlKYIT+MlxxRx5BFXisHHkcGMAAKv2dguUeOsutsYyzs9JAczvl6c+Sypra5+qOi2LHPXw6GGluuXcOssOM= uabhnil@elxadlj3q32 diff --git a/lib/public_key/test/public_key_SUITE_data/ssh2_ecdsa_pub b/lib/public_key/test/public_key_SUITE_data/ssh2_ecdsa_pub new file mode 100644 index 0000000000..702e5c4fde --- /dev/null +++ b/lib/public_key/test/public_key_SUITE_data/ssh2_ecdsa_pub @@ -0,0 +1,6 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +Comment: "256-bit ECDSA, converted by uabhnil@elxadlj3q32 from OpenSSH" +AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIJrVlKYIT+MlxxRx5 +BFXisHHkcGMAAKv2dguUeOsutsYyzs9JAczvl6c+Sypra5+qOi2LHPXw6GGluuXcOssOM= + +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index 7f752529f0..f762473a58 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1 +1 @@ -PUBLIC_KEY_VSN = 1.0 +PUBLIC_KEY_VSN = 1.0.1 diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl index 4c3f76bdc6..9ac22b9450 100644 --- a/lib/reltool/src/reltool.hrl +++ b/lib/reltool/src/reltool.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2012. All Rights Reserved. +%% Copyright Ericsson AB 2009-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -141,15 +141,15 @@ app_name :: '_' | app_name(), incl_cond :: '_' | incl_cond() | undefined, debug_info :: '_' | debug_info() | undefined, - is_app_mod :: '_' | boolean(), - is_ebin_mod :: '_' | boolean(), - uses_mods :: '$2' | [mod_name()], - exists :: '_' | boolean(), + is_app_mod :: '_' | boolean() | undefined, + is_ebin_mod :: '_' | boolean() | undefined, + uses_mods :: '$2' | [mod_name()] | undefined, + exists :: '_' | boolean() | undefined, %% Dynamic - status :: '_' | status(), - used_by_mods :: '_' | [mod_name()], - is_pre_included :: '_' | boolean() | undefined, - is_included :: '_' | boolean() | undefined + status = ok :: '_' | status(), + used_by_mods = [] :: '_' | [mod_name()], + is_pre_included :: '_' | boolean() | undefined, + is_included :: '_' | boolean() | undefined }). -record(app_info, @@ -177,10 +177,10 @@ name :: '_' | app_name(), is_escript :: '_' | boolean() | {inlined, escript_app_name()}, use_selected_vsn :: '_' | vsn | dir | undefined, - active_dir :: '_' | dir(), + active_dir :: '_' | dir() | undefined, sorted_dirs :: '_' | [dir()], - vsn :: '_' | app_vsn(), - label :: '_' | app_label(), + vsn :: '_' | app_vsn() | undefined, + label :: '_' | app_label() | undefined, info :: '_' | #app_info{} | undefined, mods :: '_' | [#mod{}], @@ -192,21 +192,21 @@ debug_info :: '_' | debug_info() | undefined, app_file :: '_' | app_file() | undefined, app_type :: '_' | app_type() | undefined, - incl_app_filters :: '_' | [#regexp{}], - excl_app_filters :: '_' | [#regexp{}], - incl_archive_filters :: '_' | [#regexp{}], - excl_archive_filters :: '_' | [#regexp{}], - archive_opts :: '_' | [archive_opt()], + incl_app_filters :: '_' | [#regexp{}] | undefined, + excl_app_filters :: '_' | [#regexp{}] | undefined, + incl_archive_filters :: '_' | [#regexp{}] | undefined, + excl_archive_filters :: '_' | [#regexp{}] | undefined, + archive_opts :: '_' | [archive_opt()] | undefined, %% Dynamic status :: '_' | status(), - uses_mods :: '_' | [mod_name()], - used_by_mods :: '_' | [mod_name()], - uses_apps :: '_' | [app_name()], - used_by_apps :: '_' | [app_name()], + uses_mods :: '_' | [mod_name()] | undefined, + used_by_mods :: '_' | [mod_name()] | undefined, + uses_apps :: '_' | [app_name()] | undefined, + used_by_apps :: '_' | [app_name()] | undefined, is_pre_included :: '_' | '$2' | boolean() | undefined, is_included :: '_' | '$1' | boolean() | undefined, - rels :: '_' | [rel_name()] + rels :: '_' | [rel_name()] | undefined }). -record(rel_app, @@ -237,7 +237,7 @@ rels :: [#rel{}], emu_name :: emu_name(), profile :: profile(), - excl_lib :: excl_lib(), + excl_lib :: excl_lib() | undefined, incl_sys_filters :: [#regexp{}], excl_sys_filters :: [#regexp{}], incl_app_filters :: [#regexp{}], diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in index 448b8c62c2..aeacee0655 100644 --- a/lib/runtime_tools/c_src/Makefile.in +++ b/lib/runtime_tools/c_src/Makefile.in @@ -102,12 +102,7 @@ endif _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) -ifneq ($(findstring ose,$(TARGET)),ose) debug opt valgrind: $(SOLIBS) $(OBJDIR) $(LIBDIR) $(NIF_LIB) -else -# We do not build this on OSE -debug opt valgrind: -endif DYNTRACE_OBJS = $(before_DTrace_OBJS) @@ -159,10 +154,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj" $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" -ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(DYNTRACE_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(NIF_LIB) $(SOLIBS) "$(RELSYSDIR)/priv/lib" -endif release_docs_spec: diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml index 1a11806211..2065627026 100644 --- a/lib/runtime_tools/doc/src/dbg.xml +++ b/lib/runtime_tools/doc/src/dbg.xml @@ -1030,9 +1030,9 @@ hello</pre> <fsummary>Stop the <c>dbg</c>server and the tracing of all processes.</fsummary> <desc> <p>Stops the <c>dbg</c> server and clears all trace flags for - all processes and all trace patterns for all functions. Also + all processes and all local trace patterns for all functions. Also shuts down all trace clients and closes all trace ports.</p> - <p>Note that no trace patterns are affected by this + <p>Note that no global trace patterns are affected by this function.</p> </desc> </func> @@ -1040,8 +1040,7 @@ hello</pre> <name>stop_clear() -> ok</name> <fsummary>Stop the <c>dbg</c>server and the tracing of all processes, and clears trace patterns.</fsummary> <desc> - <p>Same as stop/0, but also clears all trace patterns on local - and global functions calls.</p> + <p>Same as stop/0, but also clears all trace patterns on global functions calls.</p> </desc> </func> </funcs> diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml index 36ea42762a..5945ef6490 100644 --- a/lib/sasl/doc/src/notes.xml +++ b/lib/sasl/doc/src/notes.xml @@ -31,6 +31,32 @@ </header> <p>This document describes the changes made to the SASL application.</p> +<section><title>SASL 2.6</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>A mechanism for limiting the amount of text that the + built-in error logger events will produce has been + introduced. It is useful for limiting both the size of + log files and the CPU time used to produce them.</p> + <p>This mechanism is experimental in the sense that it + may be changed if it turns out that it does not solve the + problem it is supposed to solve. In that case, there may + be backward incompatible improvements to this + mechanism.</p> + <p>See the documentation for the config parameter + <c>error_logger_format_depth</c> in the Kernel + application for information about how to turn on this + feature.</p> + <p> + Own Id: OTP-12864</p> + </item> + </list> + </section> + +</section> + <section><title>SASL 2.5</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/sasl/src/sasl.app.src b/lib/sasl/src/sasl.app.src index 7864e84773..705bb73fc5 100644 --- a/lib/sasl/src/sasl.app.src +++ b/lib/sasl/src/sasl.app.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -46,6 +46,6 @@ {env, [{sasl_error_logger, tty}, {errlog_type, all}]}, {mod, {sasl, []}}, - {runtime_dependencies, ["tools-2.6.14","stdlib-2.0","kernel-3.0", + {runtime_dependencies, ["tools-2.6.14","stdlib-2.6","kernel-4.1", "erts-6.0"]}]}. diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src index eddb5a3fd0..2c8812f566 100644 --- a/lib/sasl/src/sasl.appup.src +++ b/lib/sasl/src/sasl.appup.src @@ -18,7 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 + [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 %% Down to - max one major revision back - [{<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 + [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 }. diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl index cf0ed5fcfc..825a7f6e86 100644 --- a/lib/sasl/test/systools_SUITE.erl +++ b/lib/sasl/test/systools_SUITE.erl @@ -1640,25 +1640,21 @@ app_start_type_relup(Dir2,Name2,Config) -> %% ?t:format("Dn: ~p",[DownInstructions]), [{load_object_code, {mnesia, _, _}}, {load_object_code, {runtime_tools, _, _}}, - {load_object_code, {webtool, _, _}}, {load_object_code, {snmp, _, _}}, {load_object_code, {xmerl, _, _}}, point_of_no_return | UpInstructionsT] = UpInstructions, true = lists:member({apply,{application,start,[mnesia,permanent]}}, UpInstructionsT), true = lists:member({apply,{application,start,[runtime_tools,transient]}}, UpInstructionsT), - true = lists:member({apply,{application,start,[webtool,temporary]}}, UpInstructionsT), true = lists:member({apply,{application,load,[snmp]}}, UpInstructionsT), false = lists:any(fun({apply,{application,_,[xmerl|_]}}) -> true; (_) -> false end, UpInstructionsT), [point_of_no_return | DownInstructionsT] = DownInstructions, true = lists:member({apply,{application,stop,[mnesia]}}, DownInstructionsT), true = lists:member({apply,{application,stop,[runtime_tools]}}, DownInstructionsT), - true = lists:member({apply,{application,stop,[webtool]}}, DownInstructionsT), true = lists:member({apply,{application,stop,[snmp]}}, DownInstructionsT), true = lists:member({apply,{application,stop,[xmerl]}}, DownInstructionsT), true = lists:member({apply,{application,unload,[mnesia]}}, DownInstructionsT), true = lists:member({apply,{application,unload,[runtime_tools]}}, DownInstructionsT), - true = lists:member({apply,{application,unload,[webtool]}}, DownInstructionsT), true = lists:member({apply,{application,unload,[snmp]}}, DownInstructionsT), true = lists:member({apply,{application,unload,[xmerl]}}, DownInstructionsT), ok. @@ -2207,7 +2203,6 @@ create_script(latest_app_start_type1,Config) -> create_script(latest_app_start_type2,Config) -> OtherApps = [{mnesia,current,permanent}, {runtime_tools,current,transient}, - {webtool,current,temporary}, {snmp,current,load}, {xmerl,current,none}], Apps = core_apps(current) ++ OtherApps, diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk index e07b36f4ba..959d9c88d5 100644 --- a/lib/sasl/vsn.mk +++ b/lib/sasl/vsn.mk @@ -1 +1 @@ -SASL_VSN = 2.5 +SASL_VSN = 2.6 diff --git a/lib/snmp/doc/src/snmp_advanced_agent.xml b/lib/snmp/doc/src/snmp_advanced_agent.xml index 717f7426c6..b17246438d 100644 --- a/lib/snmp/doc/src/snmp_advanced_agent.xml +++ b/lib/snmp/doc/src/snmp_advanced_agent.xml @@ -340,7 +340,7 @@ SEQUENCE { empDepNo INTEGER, empName DisplayString, - empTelNo DisplayString + empTelNo DisplayString, empStatus RowStatus } </code> diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 9d498c0fdc..bb111c8e0e 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,140 @@ <file>notes.xml</file> </header> +<section><title>Ssh 4.1.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Add a 1024 group to the list of key group-exchange groups</p> + <p> + Own Id: OTP-13046</p> + </item> + </list> + </section> + +</section> + +<section><title>Ssh 4.1.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + A new option <c>max_channels</c> limits the number of + channels with active server-side subsystems that are + accepted.</p> + <p> + Own Id: OTP-13036</p> + </item> + </list> + </section> + +</section> + +<section><title>Ssh 4.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Send an understandable disconnect message when the key + exchange phase can't find a common algorithm. There are + also some test cases added.</p> + <p> + Own Id: OTP-11531</p> + </item> + <item> + <p> + The third parameter in <c>ssh_sftp:write_file</c> is now + accepting iolists again. Unicode handling adjusted.</p> + <p> + Own Id: OTP-12853 Aux Id: seq12891 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + First part of ssh test suite re-organization and + extension.</p> + <p> + Own Id: OTP-12230</p> + </item> + <item> + <p> + The key exchange algorithms 'ecdh-sha2-nistp256', + 'ecdh-sha2-nistp384' and 'ecdh-sha2-nistp521' are + implemented. See RFC 5656.</p> + <p> + This raises the security level considerably.</p> + <p> + Own Id: OTP-12622 Aux Id: OTP-12671, OTP-12672 </p> + </item> + <item> + <p> + The key exchange algorithm 'diffie-hellman-group14-sha1' + is implemented. See RFC 4253.</p> + <p> + This raises the security level.</p> + <p> + Own Id: OTP-12671 Aux Id: OTP-12672, OTP-12622 </p> + </item> + <item> + <p> + The key exchange algorithms + 'diffie-hellman-group-exchange-sha1' and + 'diffie-hellman-group-exchange-sha256' are implemented. + See RFC 4419.</p> + <p> + This raises the security level.</p> + <p> + Own Id: OTP-12672 Aux Id: OTP-12671, OTP-12622 </p> + </item> + <item> + <p> + Adding random length extra padding as recommended in RFC + 4253 section 6.</p> + <p> + Own Id: OTP-12831</p> + </item> + <item> + <p> + New test library for low-level protocol testing. There is + also a test suite using it for some preliminary tests. + The intention is to build on that for more testing of + individual ssh messages. See + <c>lib/ssh/test/ssh_trpt_test_lib.erl</c> and + <c>ssh_protocol_SUITE.erl</c> in the same directory.</p> + <p> + Own Id: OTP-12858</p> + </item> + <item> + <p> + Increased default values for + diffie-hellman-group-exchange-sha* to Min = 1024, N = + 6144, Max = 8192.</p> + <p> + Added 6144 and 8192 bit default gex groups.</p> + <p> + Own Id: OTP-12937</p> + </item> + <item> + <p> + The mac algorithm 'hmac-sha2-512' is implemented. See RFC + 6668.</p> + <p> + Own Id: OTP-12938</p> + </item> + </list> + </section> + +</section> + <section><title>Ssh 4.0</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index cf5e8f1aff..2b190c98b6 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -40,18 +40,24 @@ <list type="bulleted"> <item>For application dependencies see <seealso marker="SSH_app"> ssh(6)</seealso> </item> <item>Supported SSH version is 2.0.</item> - <item>Supported public key algorithms: ssh-rsa and ssh-dss.</item> - <item>Supported MAC algorithms: hmac-sha2-256 and hmac-sha1.</item> - <item>Supported encryption algorithms: aes128-ctr, aes128-cb and 3des-cbc.</item> - <item>Supported key exchange algorithms: diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256.</item> - <item>Supported compression algorithms: none, zlib, [email protected],</item> + <item>Supported public key algorithms: ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa and ssh-dss.</item> + <item>Supported MAC algorithms: hmac-sha2-256, hmac-sha2-512 and hmac-sha1.</item> + <item>Supported encryption algorithms: aes256-ctr, aes192-ctr, aes128-ctr, aes128-cb and 3des-cbc.</item> + <item>Supported key exchange algorithms: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group-exchange-sha256 and diffie-hellman-group1-sha1</item> + <item>Supported compression algorithms: none, [email protected] and zlib</item> <item>Supports unicode filenames if the emulator and the underlaying OS support it. See section DESCRIPTION in the <seealso marker="kernel:file">file</seealso> manual page in <c>kernel</c> for information about this subject.</item> <item>Supports unicode in shell and CLI.</item> </list> - + <p>The actual set of algorithms can vary depending on which OpenSSL crypto library that is installed on the machine. + For the list on a particular installation, use the command <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>. + The user may override the default algorithm configuration both on the server side and the client side. + See the option preferred_algorithms in the <seealso marker="#daemon/1">daemon</seealso> and + <seealso marker="#connect/3">connect</seealso> functions. +</p> + </section> <section> @@ -243,7 +249,7 @@ kex is implicit but public_key is set explicitly.</p> <tag><c><![CDATA[{dh_gex_limits,{Min=integer(),I=integer(),Max=integer()}}]]></c></tag> <item> <p>Sets the three diffie-hellman-group-exchange parameters that guides the connected server in choosing a group. - See RFC 4419 for the function of thoose. The default value is <c>{512, 1024, 4096}</c>. + See RFC 4419 for the function of thoose. The default value is <c>{1024, 6144, 8192}</c>. </p> </item> @@ -501,6 +507,15 @@ kex is implicit but public_key is set explicitly.</p> </p> </item> + <tag><c><![CDATA[{max_channels, pos_integer()}]]></c></tag> + <item> + <p>The maximum number of channels with active remote subsystem that are accepted for + each connection to this daemon</p> + <p>By default, this option is not set. This means that the number is not limited. + </p> + </item> + + <tag><c><![CDATA[{parallel_login, boolean()}]]></c></tag> <item> <p>If set to false (the default value), only one login is handled at a time. diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 132de71aed..049018b21c 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -117,9 +117,9 @@ channel_info(ConnectionRef, ChannelId, Options) -> ssh_connection_handler:channel_info(ConnectionRef, ChannelId, Options). %%-------------------------------------------------------------------- --spec daemon(integer()) -> {ok, pid()}. --spec daemon(integer(), proplists:proplist()) -> {ok, pid()}. --spec daemon(any | inet:ip_address(), integer(), proplists:proplist()) -> {ok, pid()}. +-spec daemon(integer()) -> {ok, pid()} | {error, term()}. +-spec daemon(integer(), proplists:proplist()) -> {ok, pid()} | {error, term()}. +-spec daemon(any | inet:ip_address(), integer(), proplists:proplist()) -> {ok, pid()} | {error, term()}. %% Description: Starts a server listening for SSH connections %% on the given port. @@ -385,12 +385,15 @@ handle_option([{rekey_limit, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{max_sessions, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{max_channels, _} = Opt|Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{negotiation_timeout, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{parallel_login, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); -handle_option([parallel_login|Rest], SocketOptions, SshOptions) -> - handle_option(Rest, SocketOptions, [handle_ssh_option({parallel_login,true}) | SshOptions]); +%% (Is handled by proplists:unfold above:) +%% handle_option([parallel_login|Rest], SocketOptions, SshOptions) -> +%% handle_option(Rest, SocketOptions, [handle_ssh_option({parallel_login,true}) | SshOptions]); handle_option([{minimal_remote_max_packet_size, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{id_string, _ID} = Opt|Rest], SocketOptions, SshOptions) -> @@ -443,6 +446,8 @@ handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value Opt; handle_ssh_option({max_sessions, Value} = Opt) when is_integer(Value), Value>0 -> Opt; +handle_ssh_option({max_channels, Value} = Opt) when is_integer(Value), Value>0 -> + Opt; handle_ssh_option({negotiation_timeout, Value} = Opt) when is_integer(Value); Value == infinity -> Opt; handle_ssh_option({parallel_login, Value} = Opt) when Value==true ; Value==false -> diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index 462c98f503..fc9d60c500 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -37,13 +37,16 @@ -define(FALSE, 0). -define(TRUE, 1). %% basic binary constructors --define(BOOLEAN(X), X:8/unsigned-big-integer). --define(BYTE(X), X:8/unsigned-big-integer). --define(UINT16(X), X:16/unsigned-big-integer). --define(UINT32(X), X:32/unsigned-big-integer). --define(UINT64(X), X:64/unsigned-big-integer). +-define(BOOLEAN(X), (X):8/unsigned-big-integer). +-define(BYTE(X), (X):8/unsigned-big-integer). +-define(UINT16(X), (X):16/unsigned-big-integer). +-define(UINT32(X), (X):32/unsigned-big-integer). +-define(UINT64(X), (X):64/unsigned-big-integer). -define(STRING(X), ?UINT32((size(X))), (X)/binary). +-define(DEC_BIN(X,Len), ?UINT32(Len), X:Len/binary ). +-define(DEC_MPINT(I,Len), ?UINT32(Len), I:Len/big-signed-integer-unit:8 ). + %% building macros -define(boolean(X), case X of @@ -133,7 +136,6 @@ userauth_supported_methods, % string() eg "keyboard-interactive,password" userauth_methods, % list( string() ) eg ["keyboard-interactive", "password"] kb_tries_left = 0, % integer(), num tries left for "keyboard-interactive" - kb_data, userauth_preference, available_host_keys, authenticated = false diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index a91b8c200e..04749fcf8e 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -31,8 +31,7 @@ -export([publickey_msg/1, password_msg/1, keyboard_interactive_msg/1, service_request_msg/1, init_userauth_request_msg/1, userauth_request_msg/1, handle_userauth_request/3, - handle_userauth_info_request/3, handle_userauth_info_response/2, - default_public_key_algorithms/0 + handle_userauth_info_request/3, handle_userauth_info_response/2 ]). %%-------------------------------------------------------------------- @@ -42,27 +41,29 @@ publickey_msg([Alg, #ssh{user = User, session_id = SessionId, service = Service, opts = Opts} = Ssh]) -> - Hash = sha, %% Maybe option?! KeyCb = proplists:get_value(key_cb, Opts, ssh_file), - case KeyCb:user_key(Alg, Opts) of - {ok, Key} -> - StrAlgo = algorithm_string(Alg), - PubKeyBlob = encode_public_key(Key), - SigData = build_sig_data(SessionId, - User, Service, PubKeyBlob, StrAlgo), - Sig = ssh_transport:sign(SigData, Hash, Key), - SigBlob = list_to_binary([?string(StrAlgo), ?binary(Sig)]), - ssh_transport:ssh_packet( - #ssh_msg_userauth_request{user = User, - service = Service, - method = "publickey", - data = [?TRUE, - ?string(StrAlgo), - ?binary(PubKeyBlob), - ?binary(SigBlob)]}, - Ssh); + {ok, PrivKey} -> + StrAlgo = atom_to_list(Alg), + case encode_public_key(StrAlgo, ssh_transport:extract_public_key(PrivKey)) of + not_ok -> + not_ok; + PubKeyBlob -> + SigData = build_sig_data(SessionId, + User, Service, PubKeyBlob, StrAlgo), + Sig = ssh_transport:sign(SigData, Hash, PrivKey), + SigBlob = list_to_binary([?string(StrAlgo), ?binary(Sig)]), + ssh_transport:ssh_packet( + #ssh_msg_userauth_request{user = User, + service = Service, + method = "publickey", + data = [?TRUE, + ?string(StrAlgo), + ?binary(PubKeyBlob), + ?binary(SigBlob)]}, + Ssh) + end; _Error -> not_ok end. @@ -121,7 +122,7 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) -> Algs = proplists:get_value(public_key, proplists:get_value(preferred_algorithms, Opts, []), - default_public_key_algorithms()), + ssh_transport:default_algorithms(public_key)), Prefs = method_preference(Algs), ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User, userauth_preference = Prefs, @@ -153,7 +154,7 @@ userauth_request_msg(#ssh{userauth_methods = Methods, not_ok -> userauth_request_msg(Ssh); Result -> - Result + {Pref,Result} end; false -> userauth_request_msg(Ssh) @@ -299,8 +300,7 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User, >> }, {not_authorized, {User, undefined}, - ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User, - kb_data = Msg + ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User })} end; @@ -313,6 +313,8 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User, #ssh_msg_userauth_failure{authentications = Methods, partial_success = false}, Ssh)}. + + handle_userauth_info_request( #ssh_msg_userauth_info_request{name = Name, instruction = Instr, @@ -330,36 +332,19 @@ handle_userauth_info_request( handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1, data = <<?UINT32(Sz), Password:Sz/binary>>}, #ssh{opts = Opts, - kb_tries_left = KbTriesLeft0, - kb_data = InfoMsg, + kb_tries_left = KbTriesLeft, user = User, userauth_supported_methods = Methods} = Ssh) -> - KbTriesLeft = KbTriesLeft0 - 1, case check_password(User, unicode:characters_to_list(Password), Opts) of true -> {authorized, User, ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)}; - false when KbTriesLeft > 0 -> - UserAuthInfoMsg = - InfoMsg#ssh_msg_userauth_info_request{ - name = "", - instruction = - lists:concat( - ["Bad user or password, try again. ", - integer_to_list(KbTriesLeft), - " tries left."]) - }, - {not_authorized, {User, undefined}, - ssh_transport:ssh_packet(UserAuthInfoMsg, - Ssh#ssh{kb_tries_left = KbTriesLeft})}; - false -> {not_authorized, {User, {error,"Bad user or password"}}, ssh_transport:ssh_packet(#ssh_msg_userauth_failure{ authentications = Methods, partial_success = false}, - Ssh#ssh{kb_data = undefined, - kb_tries_left = 0} + Ssh#ssh{kb_tries_left = max(KbTriesLeft-1, 0)} )} end; @@ -371,8 +356,6 @@ handle_userauth_info_response(#ssh_msg_userauth_info_response{}, language = "en"}). -default_public_key_algorithms() -> ?PREFERRED_PK_ALGS. - %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -447,10 +430,7 @@ build_sig_data(SessionId, User, Service, KeyBlob, Alg) -> ?binary(KeyBlob)], list_to_binary(Sig). -algorithm_string('ssh-rsa') -> - "ssh-rsa"; -algorithm_string('ssh-dss') -> - "ssh-dss". + decode_keyboard_interactive_prompts(_NumPrompts, Data) -> ssh_message:decode_keyboard_interactive_prompts(Data, []). @@ -501,23 +481,18 @@ keyboard_interact_fun(KbdInteractFun, Name, Instr, PromptInfos, NumPrompts) -> language = "en"}}) end. -decode_public_key_v2(<<?UINT32(Len0), _:Len0/binary, - ?UINT32(Len1), E:Len1/big-signed-integer-unit:8, - ?UINT32(Len2), N:Len2/big-signed-integer-unit:8>> - ,"ssh-rsa") -> - {ok, #'RSAPublicKey'{publicExponent = E, modulus = N}}; -decode_public_key_v2(<<?UINT32(Len0), _:Len0/binary, - ?UINT32(Len1), P:Len1/big-signed-integer-unit:8, - ?UINT32(Len2), Q:Len2/big-signed-integer-unit:8, - ?UINT32(Len3), G:Len3/big-signed-integer-unit:8, - ?UINT32(Len4), Y:Len4/big-signed-integer-unit:8>> - , "ssh-dss") -> - {ok, {Y, #'Dss-Parms'{p = P, q = Q, g = G}}}; - -decode_public_key_v2(_, _) -> - {error, bad_format}. - -encode_public_key(#'RSAPrivateKey'{publicExponent = E, modulus = N}) -> - ssh_bits:encode(["ssh-rsa",E,N], [string,mpint,mpint]); -encode_public_key(#'DSAPrivateKey'{p = P, q = Q, g = G, y = Y}) -> - ssh_bits:encode(["ssh-dss",P,Q,G,Y], [string,mpint,mpint,mpint,mpint]). +decode_public_key_v2(Bin, _Type) -> + try + public_key:ssh_decode(Bin, ssh2_pubkey) + of + Key -> {ok, Key} + catch + _:_ -> {error, bad_format} + end. + +encode_public_key(_Alg, Key) -> + try + public_key:ssh_encode(Key, ssh2_pubkey) + catch + _:_ -> not_ok + end. diff --git a/lib/ssh/src/ssh_auth.hrl b/lib/ssh/src/ssh_auth.hrl index 71f222f6d7..5197a42fa4 100644 --- a/lib/ssh/src/ssh_auth.hrl +++ b/lib/ssh/src/ssh_auth.hrl @@ -24,8 +24,6 @@ -define(SUPPORTED_AUTH_METHODS, "publickey,keyboard-interactive,password"). --define(PREFERRED_PK_ALGS, ['ssh-rsa','ssh-dss']). - -define(SSH_MSG_USERAUTH_REQUEST, 50). -define(SSH_MSG_USERAUTH_FAILURE, 51). -define(SSH_MSG_USERAUTH_SUCCESS, 52). diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl index 64d2113125..266c64fd4f 100644 --- a/lib/ssh/src/ssh_connection.erl +++ b/lib/ssh/src/ssh_connection.erl @@ -935,14 +935,27 @@ encode_ip(Addr) when is_list(Addr) -> end end. -start_channel(Cb, Id, Args, SubSysSup) -> - start_channel(Cb, Id, Args, SubSysSup, undefined). +start_channel(Cb, Id, Args, SubSysSup, Opts) -> + start_channel(Cb, Id, Args, SubSysSup, undefined, Opts). -start_channel(Cb, Id, Args, SubSysSup, Exec) -> +start_channel(Cb, Id, Args, SubSysSup, Exec, Opts) -> ChildSpec = child_spec(Cb, Id, Args, Exec), ChannelSup = ssh_subsystem_sup:channel_supervisor(SubSysSup), + assert_limit_num_channels_not_exceeded(ChannelSup, Opts), ssh_channel_sup:start_child(ChannelSup, ChildSpec). +assert_limit_num_channels_not_exceeded(ChannelSup, Opts) -> + MaxNumChannels = proplists:get_value(max_channels, Opts, infinity), + NumChannels = length([x || {_,_,worker,[ssh_channel]} <- + supervisor:which_children(ChannelSup)]), + if + %% Note that NumChannels is BEFORE starting a new one + NumChannels < MaxNumChannels -> + ok; + true -> + throw(max_num_channels_exceeded) + end. + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -998,9 +1011,11 @@ child_spec(Callback, Id, Args, Exec) -> start_cli(#connection{cli_spec = no_cli}, _) -> {error, cli_disabled}; -start_cli(#connection{cli_spec = {CbModule, Args}, exec = Exec, +start_cli(#connection{options = Options, + cli_spec = {CbModule, Args}, + exec = Exec, sub_system_supervisor = SubSysSup}, ChannelId) -> - start_channel(CbModule, ChannelId, Args, SubSysSup, Exec). + start_channel(CbModule, ChannelId, Args, SubSysSup, Exec, Options). start_subsytem(BinName, #connection{options = Options, sub_system_supervisor = SubSysSup}, @@ -1008,7 +1023,7 @@ start_subsytem(BinName, #connection{options = Options, Name = binary_to_list(BinName), case check_subsystem(Name, Options) of {Callback, Opts} when is_atom(Callback), Callback =/= none -> - start_channel(Callback, ChannelId, Opts, SubSysSup); + start_channel(Callback, ChannelId, Opts, SubSysSup, Options); {Other, _} when Other =/= none -> {error, legacy_option_not_supported} end. diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index fcd66b80c0..7fb86c1108 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -49,7 +49,10 @@ -export([hello/2, kexinit/2, key_exchange/2, key_exchange_dh_gex_init/2, key_exchange_dh_gex_reply/2, new_keys/2, - userauth/2, connected/2, + service_request/2, connected/2, + userauth/2, + userauth_keyboard_interactive/2, + userauth_keyboard_interactive_info_response/2, error/2]). -export([init/1, handle_event/3, @@ -82,7 +85,12 @@ recbuf }). --type state_name() :: hello | kexinit | key_exchange | new_keys | userauth | connection. +-type state_name() :: hello | kexinit | key_exchange | key_exchange_dh_gex_init | + key_exchange_dh_gex_reply | new_keys | service_request | + userauth | userauth_keyboard_interactive | + userauth_keyboard_interactive_info_response | + connection. + -type gen_fsm_state_return() :: {next_state, state_name(), term()} | {next_state, state_name(), term(), timeout()} | {stop, term(), term()}. @@ -474,28 +482,30 @@ new_keys(#ssh_msg_newkeys{} = Msg, #state{ssh_params = Ssh0} = State0) -> after_new_keys(next_packet(State0#state{ssh_params = Ssh})). %%-------------------------------------------------------------------- --spec userauth(#ssh_msg_service_request{} | #ssh_msg_service_accept{} | - #ssh_msg_userauth_request{} | #ssh_msg_userauth_info_request{} | - #ssh_msg_userauth_info_response{} | #ssh_msg_userauth_success{} | - #ssh_msg_userauth_failure{} | #ssh_msg_userauth_banner{}, - #state{}) -> gen_fsm_state_return(). +-spec service_request(#ssh_msg_service_request{} | #ssh_msg_service_accept{}, + #state{}) -> gen_fsm_state_return(). %%-------------------------------------------------------------------- - -userauth(#ssh_msg_service_request{name = "ssh-userauth"} = Msg, +service_request(#ssh_msg_service_request{name = "ssh-userauth"} = Msg, #state{ssh_params = #ssh{role = server, session_id = SessionId} = Ssh0} = State) -> {ok, {Reply, Ssh}} = ssh_auth:handle_userauth_request(Msg, SessionId, Ssh0), send_msg(Reply, State), {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}; -userauth(#ssh_msg_service_accept{name = "ssh-userauth"}, - #state{ssh_params = #ssh{role = client, - service = "ssh-userauth"} = Ssh0} = - State) -> +service_request(#ssh_msg_service_accept{name = "ssh-userauth"}, + #state{ssh_params = #ssh{role = client, + service = "ssh-userauth"} = Ssh0} = + State) -> {Msg, Ssh} = ssh_auth:init_userauth_request_msg(Ssh0), send_msg(Msg, State), - {next_state, userauth, next_packet(State#state{auth_user = Ssh#ssh.user, ssh_params = Ssh})}; + {next_state, userauth, next_packet(State#state{auth_user = Ssh#ssh.user, ssh_params = Ssh})}. +%%-------------------------------------------------------------------- +-spec userauth(#ssh_msg_userauth_request{} | #ssh_msg_userauth_info_request{} | + #ssh_msg_userauth_info_response{} | #ssh_msg_userauth_success{} | + #ssh_msg_userauth_failure{} | #ssh_msg_userauth_banner{}, + #state{}) -> gen_fsm_state_return(). +%%-------------------------------------------------------------------- userauth(#ssh_msg_userauth_request{service = "ssh-connection", method = "none"} = Msg, #state{ssh_params = #ssh{session_id = SessionId, role = server, @@ -520,7 +530,11 @@ userauth(#ssh_msg_userauth_request{service = "ssh-connection", Pid ! ssh_connected, connected_fun(User, Address, Method, Opts), {next_state, connected, - next_packet(State#state{auth_user = User, ssh_params = Ssh})}; + next_packet(State#state{auth_user = User, ssh_params = Ssh#ssh{authenticated = true}})}; + {not_authorized, {User, Reason}, {Reply, Ssh}} when Method == "keyboard-interactive" -> + retry_fun(User, Address, Reason, Opts), + send_msg(Reply, State), + {next_state, userauth_keyboard_interactive, next_packet(State#state{ssh_params = Ssh})}; {not_authorized, {User, Reason}, {Reply, Ssh}} -> retry_fun(User, Address, Reason, Opts), send_msg(Reply, State), @@ -530,30 +544,6 @@ userauth(#ssh_msg_userauth_request{service = "ssh-connection", userauth(Msg#ssh_msg_userauth_request{method="none"}, State) end; -userauth(#ssh_msg_userauth_info_request{} = Msg, - #state{ssh_params = #ssh{role = client, - io_cb = IoCb} = Ssh0} = State) -> - {ok, {Reply, Ssh}} = ssh_auth:handle_userauth_info_request(Msg, IoCb, Ssh0), - send_msg(Reply, State), - {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}; - -userauth(#ssh_msg_userauth_info_response{} = Msg, - #state{ssh_params = #ssh{role = server, - peer = {_, Address}} = Ssh0, - opts = Opts, starter = Pid} = State) -> - case ssh_auth:handle_userauth_info_response(Msg, Ssh0) of - {authorized, User, {Reply, Ssh}} -> - send_msg(Reply, State), - Pid ! ssh_connected, - connected_fun(User, Address, "keyboard-interactive", Opts), - {next_state, connected, - next_packet(State#state{auth_user = User, ssh_params = Ssh})}; - {not_authorized, {User, Reason}, {Reply, Ssh}} -> - retry_fun(User, Address, Reason, Opts), - send_msg(Reply, State), - {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} - end; - userauth(#ssh_msg_userauth_success{}, #state{ssh_params = #ssh{role = client} = Ssh, starter = Pid} = State) -> Pid ! ssh_connected, @@ -580,19 +570,25 @@ userauth(#ssh_msg_userauth_failure{authentications = Methodes}, {disconnect, DisconnectMsg, {Msg, Ssh}} -> send_msg(Msg, State), handle_disconnect(DisconnectMsg, State#state{ssh_params = Ssh}); - {Msg, Ssh} -> + {"keyboard-interactive", {Msg, Ssh}} -> + send_msg(Msg, State), + {next_state, userauth_keyboard_interactive, next_packet(State#state{ssh_params = Ssh})}; + {_Method, {Msg, Ssh}} -> send_msg(Msg, State), {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} end; %% The prefered authentication method failed try next method -userauth(#ssh_msg_userauth_failure{}, +userauth(#ssh_msg_userauth_failure{}, #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> case ssh_auth:userauth_request_msg(Ssh0) of {disconnect, DisconnectMsg,{Msg, Ssh}} -> send_msg(Msg, State), handle_disconnect(DisconnectMsg, State#state{ssh_params = Ssh}); - {Msg, Ssh} -> + {"keyboard-interactive", {Msg, Ssh}} -> + send_msg(Msg, State), + {next_state, userauth_keyboard_interactive, next_packet(State#state{ssh_params = Ssh})}; + {_Method, {Msg, Ssh}} -> send_msg(Msg, State), {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} end; @@ -607,6 +603,40 @@ userauth(#ssh_msg_userauth_banner{message = Msg}, io:format("~s", [Msg]), {next_state, userauth, next_packet(State)}. + + +userauth_keyboard_interactive(#ssh_msg_userauth_info_request{} = Msg, + #state{ssh_params = #ssh{role = client, + io_cb = IoCb} = Ssh0} = State) -> + {ok, {Reply, Ssh}} = ssh_auth:handle_userauth_info_request(Msg, IoCb, Ssh0), + send_msg(Reply, State), + {next_state, userauth_keyboard_interactive_info_response, next_packet(State#state{ssh_params = Ssh})}; + +userauth_keyboard_interactive(#ssh_msg_userauth_info_response{} = Msg, + #state{ssh_params = #ssh{role = server, + peer = {_, Address}} = Ssh0, + opts = Opts, starter = Pid} = State) -> + case ssh_auth:handle_userauth_info_response(Msg, Ssh0) of + {authorized, User, {Reply, Ssh}} -> + send_msg(Reply, State), + Pid ! ssh_connected, + connected_fun(User, Address, "keyboard-interactive", Opts), + {next_state, connected, + next_packet(State#state{auth_user = User, ssh_params = Ssh#ssh{authenticated = true}})}; + {not_authorized, {User, Reason}, {Reply, Ssh}} -> + retry_fun(User, Address, Reason, Opts), + send_msg(Reply, State), + {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} + end. + + + +userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_failure{}, State) -> + userauth(Msg, State); + +userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_success{}, State) -> + userauth(Msg, State). + %%-------------------------------------------------------------------- -spec connected({#ssh_msg_kexinit{}, binary()}, %%| %% #ssh_msg_kexdh_init{}, #state{}) -> gen_fsm_state_return(). @@ -1236,9 +1266,9 @@ supported_host_keys(client, _, Options) -> proplists:get_value(preferred_algorithms,Options,[]) ) of undefined -> - ssh_auth:default_public_key_algorithms(); + ssh_transport:default_algorithms(public_key); L -> - L -- (L--ssh_auth:default_public_key_algorithms()) + L -- (L--ssh_transport:default_algorithms(public_key)) end of [] -> @@ -1250,21 +1280,17 @@ supported_host_keys(client, _, Options) -> {stop, {shutdown, Reason}} end; supported_host_keys(server, KeyCb, Options) -> - Algs= [atom_to_list(A) || A <- proplists:get_value(public_key, proplists:get_value(preferred_algorithms,Options,[]), - ssh_auth:default_public_key_algorithms() + ssh_transport:default_algorithms(public_key) ), available_host_key(KeyCb, A, Options) - ], - Algs. - + ]. %% Alg :: atom() available_host_key(KeyCb, Alg, Opts) -> element(1, catch KeyCb:host_key(Alg, Opts)) == ok. - send_msg(Msg, #state{socket = Socket, transport_cb = Transport}) -> Transport:send(Socket, Msg). @@ -1563,10 +1589,10 @@ after_new_keys(#state{renegotiate = false, ssh_params = #ssh{role = client} = Ssh0} = State) -> {Msg, Ssh} = ssh_auth:service_request_msg(Ssh0), send_msg(Msg, State), - {next_state, userauth, State#state{ssh_params = Ssh}}; + {next_state, service_request, State#state{ssh_params = Ssh}}; after_new_keys(#state{renegotiate = false, ssh_params = #ssh{role = server}} = State) -> - {next_state, userauth, State}. + {next_state, service_request, State}. after_new_keys_events({sync, _Event, From}, {stop, _Reason, _StateData}=Terminator) -> gen_fsm:reply(From, {error, closed}), diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index b98a8a8410..c087ce14d7 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -52,8 +52,20 @@ host_key(Algorithm, Opts) -> %% so probably we could hardcod Password = ignore, but %% we keep it as an undocumented option for now. Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore), - decode(File, Password). - + case decode(File, Password) of + {ok,Key} -> + case {Key,Algorithm} of + {#'RSAPrivateKey'{}, 'ssh-rsa'} -> {ok,Key}; + {#'DSAPrivateKey'{}, 'ssh-dss'} -> {ok,Key}; + {#'ECPrivateKey'{parameters = {namedCurve, ?'secp256r1'}}, 'ecdsa-sha2-nistp256'} -> {ok,Key}; + {#'ECPrivateKey'{parameters = {namedCurve, ?'secp384r1'}}, 'ecdsa-sha2-nistp384'} -> {ok,Key}; + {#'ECPrivateKey'{parameters = {namedCurve, ?'secp521r1'}}, 'ecdsa-sha2-nistp521'} -> {ok,Key}; + _ -> + {error,bad_keytype_in_file} + end; + Other -> + Other + end. is_auth_key(Key, User,Opts) -> case lookup_user_key(Key, User, Opts) of @@ -81,16 +93,15 @@ user_key(Algorithm, Opts) -> %% Internal functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -file_base_name('ssh-rsa') -> - "ssh_host_rsa_key"; -file_base_name('ssh-dss') -> - "ssh_host_dsa_key"; -file_base_name(_) -> - "ssh_host_key". +file_base_name('ssh-rsa' ) -> "ssh_host_rsa_key"; +file_base_name('ssh-dss' ) -> "ssh_host_dsa_key"; +file_base_name('ecdsa-sha2-nistp256') -> "ssh_host_ecdsa_key"; +file_base_name('ecdsa-sha2-nistp384') -> "ssh_host_ecdsa_key"; +file_base_name('ecdsa-sha2-nistp521') -> "ssh_host_ecdsa_key"; +file_base_name(_ ) -> "ssh_host_key". decode(File, Password) -> - try - {ok, decode_ssh_file(read_ssh_file(File), Password)} + try {ok, decode_ssh_file(read_ssh_file(File), Password)} catch throw:Reason -> {error, Reason}; @@ -215,20 +226,18 @@ do_lookup_host_key(KeyToMatch, Host, Alg, Opts) -> Error -> Error end. -identity_key_filename('ssh-dss') -> - "id_dsa"; -identity_key_filename('ssh-rsa') -> - "id_rsa". - -identity_pass_phrase("ssh-dss") -> - dsa_pass_phrase; -identity_pass_phrase('ssh-dss') -> - dsa_pass_phrase; -identity_pass_phrase('ssh-rsa') -> - rsa_pass_phrase; -identity_pass_phrase("ssh-rsa") -> - rsa_pass_phrase. - +identity_key_filename('ssh-dss' ) -> "id_dsa"; +identity_key_filename('ssh-rsa' ) -> "id_rsa"; +identity_key_filename('ecdsa-sha2-nistp256') -> "id_ecdsa"; +identity_key_filename('ecdsa-sha2-nistp384') -> "id_ecdsa"; +identity_key_filename('ecdsa-sha2-nistp521') -> "id_ecdsa". + +identity_pass_phrase("ssh-dss" ) -> dsa_pass_phrase; +identity_pass_phrase("ssh-rsa" ) -> rsa_pass_phrase; +identity_pass_phrase("ecdsa-sha2-"++_) -> ecdsa_pass_phrase; +identity_pass_phrase(P) when is_atom(P) -> + identity_pass_phrase(atom_to_list(P)). + lookup_host_key_fd(Fd, KeyToMatch, Host, KeyType) -> case io:get_line(Fd, '') of eof -> @@ -267,6 +276,13 @@ key_match(#'RSAPublicKey'{}, 'ssh-rsa') -> true; key_match({_, #'Dss-Parms'{}}, 'ssh-dss') -> true; +key_match({#'ECPoint'{},{namedCurve,Curve}}, Alg) -> + case atom_to_list(Alg) of + "ecdsa-sha2-"++IdS -> + Curve == public_key:ssh_curvename2oid(list_to_binary(IdS)); + _ -> + false + end; key_match(_, _) -> false. diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl index cb1dcb67c5..b6c4496be2 100644 --- a/lib/ssh/src/ssh_message.erl +++ b/lib/ssh/src/ssh_message.erl @@ -30,7 +30,7 @@ -include("ssh_auth.hrl"). -include("ssh_transport.hrl"). --export([encode/1, decode/1, encode_host_key/1, decode_keyboard_interactive_prompts/2]). +-export([encode/1, decode/1, decode_keyboard_interactive_prompts/2]). encode(#ssh_msg_global_request{ name = Name, @@ -227,8 +227,8 @@ encode(#ssh_msg_kexdh_reply{ f = F, h_sig = Signature }) -> - EncKey = encode_host_key(Key), - EncSign = encode_sign(Key, Signature), + EncKey = public_key:ssh_encode(Key, ssh2_pubkey), + EncSign = encode_signature(Key, Signature), ssh_bits:encode([?SSH_MSG_KEXDH_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); encode(#ssh_msg_kex_dh_gex_request{ @@ -255,16 +255,16 @@ encode(#ssh_msg_kex_dh_gex_reply{ f = F, h_sig = Signature }) -> - EncKey = encode_host_key(Key), - EncSign = encode_sign(Key, Signature), + EncKey = public_key:ssh_encode(Key, ssh2_pubkey), + EncSign = encode_signature(Key, Signature), ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) -> ssh_bits:encode([?SSH_MSG_KEX_ECDH_INIT, Q_c], [byte, mpint]); encode(#ssh_msg_kex_ecdh_reply{public_host_key = Key, q_s = Q_s, h_sig = Sign}) -> - EncKey = encode_host_key(Key), - EncSign = encode_sign(Key, Sign), + EncKey = public_key:ssh_encode(Key, ssh2_pubkey), + EncSign = encode_signature(Key, Sign), ssh_bits:encode([?SSH_MSG_KEX_ECDH_REPLY, EncKey, Q_s, EncSign], [byte, binary, mpint, binary]); encode(#ssh_msg_ignore{data = Data}) -> @@ -280,8 +280,7 @@ encode(#ssh_msg_debug{always_display = Bool, %% Connection Messages -decode(<<?BYTE(?SSH_MSG_GLOBAL_REQUEST), ?UINT32(Len), Name:Len/binary, - ?BYTE(Bool), Data/binary>>) -> +decode(<<?BYTE(?SSH_MSG_GLOBAL_REQUEST), ?DEC_BIN(Name,__0), ?BYTE(Bool), Data/binary>>) -> #ssh_msg_global_request{ name = Name, want_reply = erl_boolean(Bool), @@ -292,8 +291,7 @@ decode(<<?BYTE(?SSH_MSG_REQUEST_SUCCESS), Data/binary>>) -> decode(<<?BYTE(?SSH_MSG_REQUEST_FAILURE)>>) -> #ssh_msg_request_failure{}; decode(<<?BYTE(?SSH_MSG_CHANNEL_OPEN), - ?UINT32(Len), Type:Len/binary, - ?UINT32(Sender), ?UINT32(Window), ?UINT32(Max), + ?DEC_BIN(Type,__0), ?UINT32(Sender), ?UINT32(Window), ?UINT32(Max), Data/binary>>) -> #ssh_msg_channel_open{ channel_type = binary_to_list(Type), @@ -313,7 +311,7 @@ decode(<<?BYTE(?SSH_MSG_CHANNEL_OPEN_CONFIRMATION), ?UINT32(Recipient), ?UINT32( data = Data }; decode(<<?BYTE(?SSH_MSG_CHANNEL_OPEN_FAILURE), ?UINT32(Recipient), ?UINT32(Reason), - ?UINT32(Len0), Desc:Len0/binary, ?UINT32(Len1), Lang:Len1/binary >>) -> + ?DEC_BIN(Desc,__0), ?DEC_BIN(Lang,__1) >> ) -> #ssh_msg_channel_open_failure{ recipient_channel = Recipient, reason = Reason, @@ -326,13 +324,13 @@ decode(<<?BYTE(?SSH_MSG_CHANNEL_WINDOW_ADJUST), ?UINT32(Recipient), ?UINT32(Byte bytes_to_add = Bytes }; -decode(<<?BYTE(?SSH_MSG_CHANNEL_DATA), ?UINT32(Recipient), ?UINT32(Len), Data:Len/binary>>) -> +decode(<<?BYTE(?SSH_MSG_CHANNEL_DATA), ?UINT32(Recipient), ?DEC_BIN(Data,__0)>>) -> #ssh_msg_channel_data{ recipient_channel = Recipient, data = Data }; decode(<<?BYTE(?SSH_MSG_CHANNEL_EXTENDED_DATA), ?UINT32(Recipient), - ?UINT32(DataType), ?UINT32(Len), Data:Len/binary>>) -> + ?UINT32(DataType), ?DEC_BIN(Data,__0)>>) -> #ssh_msg_channel_extended_data{ recipient_channel = Recipient, data_type_code = DataType, @@ -347,8 +345,7 @@ decode(<<?BYTE(?SSH_MSG_CHANNEL_CLOSE), ?UINT32(Recipient)>>) -> recipient_channel = Recipient }; decode(<<?BYTE(?SSH_MSG_CHANNEL_REQUEST), ?UINT32(Recipient), - ?UINT32(Len), RequestType:Len/binary, - ?BYTE(Bool), Data/binary>>) -> + ?DEC_BIN(RequestType,__0), ?BYTE(Bool), Data/binary>>) -> #ssh_msg_channel_request{ recipient_channel = Recipient, request_type = unicode:characters_to_list(RequestType), @@ -366,9 +363,7 @@ decode(<<?BYTE(?SSH_MSG_CHANNEL_FAILURE), ?UINT32(Recipient)>>) -> %%% Auth Messages decode(<<?BYTE(?SSH_MSG_USERAUTH_REQUEST), - ?UINT32(Len0), User:Len0/binary, - ?UINT32(Len1), Service:Len1/binary, - ?UINT32(Len2), Method:Len2/binary, + ?DEC_BIN(User,__0), ?DEC_BIN(Service,__1), ?DEC_BIN(Method,__2), Data/binary>>) -> #ssh_msg_userauth_request{ user = unicode:characters_to_list(User), @@ -378,7 +373,7 @@ decode(<<?BYTE(?SSH_MSG_USERAUTH_REQUEST), }; decode(<<?BYTE(?SSH_MSG_USERAUTH_FAILURE), - ?UINT32(Len0), Auths:Len0/binary, + ?DEC_BIN(Auths,__0), ?BYTE(Bool)>>) -> #ssh_msg_userauth_failure { authentications = unicode:characters_to_list(Auths), @@ -388,16 +383,14 @@ decode(<<?BYTE(?SSH_MSG_USERAUTH_FAILURE), decode(<<?BYTE(?SSH_MSG_USERAUTH_SUCCESS)>>) -> #ssh_msg_userauth_success{}; -decode(<<?BYTE(?SSH_MSG_USERAUTH_BANNER), - ?UINT32(Len0), Banner:Len0/binary, - ?UINT32(Len1), Lang:Len1/binary>>) -> +decode(<<?BYTE(?SSH_MSG_USERAUTH_BANNER), ?DEC_BIN(Banner,__0), ?DEC_BIN(Lang,__1) >>) -> #ssh_msg_userauth_banner{ message = Banner, language = Lang }; -decode(<<?BYTE(?SSH_MSG_USERAUTH_INFO_REQUEST), ?UINT32(Len0), Name:Len0/binary, - ?UINT32(Len1), Inst:Len1/binary, ?UINT32(Len2), Lang:Len2/binary, +decode(<<?BYTE(?SSH_MSG_USERAUTH_INFO_REQUEST), + ?DEC_BIN(Name,__0), ?DEC_BIN(Inst,__1), ?DEC_BIN(Lang,__2), ?UINT32(NumPromtps), Data/binary>>) -> #ssh_msg_userauth_info_request{ name = Name, @@ -407,15 +400,14 @@ decode(<<?BYTE(?SSH_MSG_USERAUTH_INFO_REQUEST), ?UINT32(Len0), Name:Len0/binary, data = Data}; %%% Unhandled message, also masked by same 1:st byte value as ?SSH_MSG_USERAUTH_INFO_REQUEST: -decode(<<?BYTE(?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ), ?UINT32(Len0), Prompt:Len0/binary, - ?UINT32(Len1), Lang:Len1/binary>>) -> +decode(<<?BYTE(?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ), ?DEC_BIN(Prompt,__0), ?DEC_BIN(Lang,__1) >>) -> #ssh_msg_userauth_passwd_changereq{ prompt = Prompt, languge = Lang }; %%% Unhandled message, also masked by same 1:st byte value as ?SSH_MSG_USERAUTH_INFO_REQUEST: -decode(<<?BYTE(?SSH_MSG_USERAUTH_PK_OK), ?UINT32(Len), Alg:Len/binary, KeyBlob/binary>>) -> +decode(<<?BYTE(?SSH_MSG_USERAUTH_PK_OK), ?DEC_BIN(Alg,__0), KeyBlob/binary>>) -> #ssh_msg_userauth_pk_ok{ algorithm_name = Alg, key_blob = KeyBlob @@ -430,18 +422,15 @@ decode(<<?BYTE(?SSH_MSG_USERAUTH_INFO_RESPONSE), ?UINT32(Num), Data/binary>>) -> decode(<<?BYTE(?SSH_MSG_KEXINIT), Cookie:128, Data/binary>>) -> decode_kex_init(Data, [Cookie, ssh_msg_kexinit], 10); -decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_INIT), ?UINT32(Len), E:Len/big-signed-integer-unit:8>>) -> +decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_INIT), ?DEC_MPINT(E,__0)>>) -> #ssh_msg_kexdh_init{e = E }; -decode(<<"dh", ?BYTE(?SSH_MSG_KEXDH_REPLY), - ?UINT32(Len0), Key:Len0/binary, - ?UINT32(Len1), F:Len1/big-signed-integer-unit:8, - ?UINT32(Len2), Hashsign:Len2/binary>>) -> +decode(<<"dh", ?BYTE(?SSH_MSG_KEXDH_REPLY), ?DEC_BIN(Key,__0), ?DEC_MPINT(F,__1), ?DEC_BIN(Hashsign,__2)>>) -> #ssh_msg_kexdh_reply{ - public_host_key = decode_host_key(Key), + public_host_key = public_key:ssh_decode(Key, ssh2_pubkey), f = F, - h_sig = decode_sign(Hashsign) + h_sig = decode_signature(Hashsign) }; decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REQUEST), ?UINT32(Min), ?UINT32(N), ?UINT32(Max)>>) -> @@ -456,57 +445,48 @@ decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_REQUEST_OLD), ?UINT32(N)>>) -> n = N }; -decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_GROUP), - ?UINT32(Len0), Prime:Len0/big-signed-integer-unit:8, - ?UINT32(Len1), Generator:Len1/big-signed-integer-unit:8>>) -> +decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_GROUP), ?DEC_MPINT(Prime,__0), ?DEC_MPINT(Generator,__1) >>) -> #ssh_msg_kex_dh_gex_group{ p = Prime, g = Generator }; -decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_INIT), ?UINT32(Len), E:Len/big-signed-integer-unit:8>>) -> +decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_INIT), ?DEC_MPINT(E,__0)>>) -> #ssh_msg_kex_dh_gex_init{ e = E }; -decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REPLY), - ?UINT32(Len0), Key:Len0/binary, - ?UINT32(Len1), F:Len1/big-signed-integer-unit:8, - ?UINT32(Len2), Hashsign:Len2/binary>>) -> +decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REPLY), ?DEC_BIN(Key,__0), ?DEC_MPINT(F,__1), ?DEC_BIN(Hashsign,__2)>>) -> #ssh_msg_kex_dh_gex_reply{ - public_host_key = decode_host_key(Key), + public_host_key = public_key:ssh_decode(Key, ssh2_pubkey), f = F, - h_sig = decode_sign(Hashsign) + h_sig = decode_signature(Hashsign) }; -decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), - ?UINT32(Len0), Q_c:Len0/big-signed-integer-unit:8>>) -> +decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_MPINT(Q_c,__0)>>) -> #ssh_msg_kex_ecdh_init{ q_c = Q_c }; decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_REPLY), - ?UINT32(Len1), Key:Len1/binary, - ?UINT32(Len2), Q_s:Len2/big-signed-integer-unit:8, - ?UINT32(Len3), Sig:Len3/binary>>) -> + ?DEC_BIN(Key,__1), ?DEC_MPINT(Q_s,__2), ?DEC_BIN(Sig,__3)>>) -> #ssh_msg_kex_ecdh_reply{ - public_host_key = decode_host_key(Key), + public_host_key = public_key:ssh_decode(Key, ssh2_pubkey), q_s = Q_s, - h_sig = decode_sign(Sig) + h_sig = decode_signature(Sig) }; -decode(<<?SSH_MSG_SERVICE_REQUEST, ?UINT32(Len0), Service:Len0/binary>>) -> +decode(<<?SSH_MSG_SERVICE_REQUEST, ?DEC_BIN(Service,__0)>>) -> #ssh_msg_service_request{ name = unicode:characters_to_list(Service) }; -decode(<<?SSH_MSG_SERVICE_ACCEPT, ?UINT32(Len0), Service:Len0/binary>>) -> +decode(<<?SSH_MSG_SERVICE_ACCEPT, ?DEC_BIN(Service,__0)>>) -> #ssh_msg_service_accept{ name = unicode:characters_to_list(Service) }; -decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), - ?UINT32(Len0), Desc:Len0/binary, ?UINT32(Len1), Lang:Len1/binary>>) -> +decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), ?DEC_BIN(Desc,__0), ?DEC_BIN(Lang,__1)>>) -> #ssh_msg_disconnect{ code = Code, description = unicode:characters_to_list(Desc), @@ -514,8 +494,7 @@ decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), }; %% Accept bad disconnects from ancient openssh clients that doesn't send language tag. Use english as a work-around. -decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), - ?UINT32(Len0), Desc:Len0/binary>>) -> +decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), ?DEC_BIN(Desc,__0)>>) -> #ssh_msg_disconnect{ code = Code, description = unicode:characters_to_list(Desc), @@ -525,21 +504,25 @@ decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), decode(<<?SSH_MSG_NEWKEYS>>) -> #ssh_msg_newkeys{}; -decode(<<?BYTE(?SSH_MSG_IGNORE), ?UINT32(Len), Data:Len/binary>>) -> +decode(<<?BYTE(?SSH_MSG_IGNORE), ?DEC_BIN(Data,__0)>>) -> #ssh_msg_ignore{data = Data}; decode(<<?BYTE(?SSH_MSG_UNIMPLEMENTED), ?UINT32(Seq)>>) -> #ssh_msg_unimplemented{sequence = Seq}; -decode(<<?BYTE(?SSH_MSG_DEBUG), ?BYTE(Bool), ?UINT32(Len0), Msg:Len0/binary, - ?UINT32(Len1), Lang:Len1/binary>>) -> +decode(<<?BYTE(?SSH_MSG_DEBUG), ?BYTE(Bool), ?DEC_BIN(Msg,__0), ?DEC_BIN(Lang,__1)>>) -> #ssh_msg_debug{always_display = erl_boolean(Bool), message = Msg, language = Lang}. +%%%================================================================ +%%% +%%% Helper functions +%%% + decode_keyboard_interactive_prompts(<<>>, Acc) -> lists:reverse(Acc); -decode_keyboard_interactive_prompts(<<?UINT32(Len), Prompt:Len/binary, ?BYTE(Bool), Bin/binary>>, +decode_keyboard_interactive_prompts(<<?DEC_BIN(Prompt,__0), ?BYTE(Bool), Bin/binary>>, Acc) -> decode_keyboard_interactive_prompts(Bin, [{Prompt, erl_boolean(Bool)} | Acc]). @@ -555,43 +538,25 @@ decode_kex_init(<<?BYTE(Bool)>>, Acc, 0) -> %% See rfc 4253 7.1 X = 0, list_to_tuple(lists:reverse([X, erl_boolean(Bool) | Acc])); -decode_kex_init(<<?UINT32(Len), Data:Len/binary, Rest/binary>>, Acc, N) -> +decode_kex_init(<<?DEC_BIN(Data,__0), Rest/binary>>, Acc, N) -> Names = string:tokens(unicode:characters_to_list(Data), ","), decode_kex_init(Rest, [Names | Acc], N -1). +%%%================================================================ +%%% +%%% Signature decode/encode +%%% -decode_sign(<<?UINT32(Len), _Alg:Len/binary, ?UINT32(_), Signature/binary>>) -> +decode_signature(<<?DEC_BIN(_Alg,__0), ?UINT32(_), Signature/binary>>) -> Signature. -decode_host_key(<<?UINT32(Len), Alg:Len/binary, Rest/binary>>) -> - decode_host_key(Alg, Rest). - -decode_host_key(<<"ssh-rsa">>, <<?UINT32(Len0), E:Len0/big-signed-integer-unit:8, - ?UINT32(Len1), N:Len1/big-signed-integer-unit:8>>) -> - #'RSAPublicKey'{publicExponent = E, - modulus = N}; - -decode_host_key(<<"ssh-dss">>, - <<?UINT32(Len0), P:Len0/big-signed-integer-unit:8, - ?UINT32(Len1), Q:Len1/big-signed-integer-unit:8, - ?UINT32(Len2), G:Len2/big-signed-integer-unit:8, - ?UINT32(Len3), Y:Len3/big-signed-integer-unit:8>>) -> - {Y, #'Dss-Parms'{p = P, - q = Q, - g = G}}. - -encode_host_key(#'RSAPublicKey'{modulus = N, publicExponent = E}) -> - ssh_bits:encode(["ssh-rsa", E, N], [string, mpint, mpint]); -encode_host_key({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) -> - ssh_bits:encode(["ssh-dss", P, Q, G, Y], - [string, mpint, mpint, mpint, mpint]); -encode_host_key(#'RSAPrivateKey'{modulus = N, publicExponent = E}) -> - ssh_bits:encode(["ssh-rsa", E, N], [string, mpint, mpint]); -encode_host_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) -> - ssh_bits:encode(["ssh-dss", P, Q, G, Y], - [string, mpint, mpint, mpint, mpint]). -encode_sign(#'RSAPrivateKey'{}, Signature) -> + +encode_signature(#'RSAPublicKey'{}, Signature) -> ssh_bits:encode(["ssh-rsa", Signature],[string, binary]); -encode_sign(#'DSAPrivateKey'{}, Signature) -> - ssh_bits:encode(["ssh-dss", Signature],[string, binary]). +encode_signature({_, #'Dss-Parms'{}}, Signature) -> + ssh_bits:encode(["ssh-dss", Signature],[string, binary]); +encode_signature({#'ECPoint'{}, {namedCurve,OID}}, Signature) -> + CurveName = public_key:oid2ssh_curvename(OID), + ssh_bits:encode([<<"ecdsa-sha2-",CurveName/binary>>, Signature], [binary,binary]). + diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 2b6f0a3cdc..d622ec27fc 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -44,7 +44,8 @@ handle_kexdh_reply/2, handle_kex_ecdh_init/2, handle_kex_ecdh_reply/2, - unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1, + extract_public_key/1, + unpack/3, decompress/2, ssh_packet/2, pack/2, pack/3, msg_data/1, sign/3, verify/4]). %%%---------------------------------------------------------------------------- @@ -65,9 +66,8 @@ default_algorithms() -> [{K,default_algorithms(K)} || K <- algo_classes()]. algo_classes() -> [kex, public_key, cipher, mac, compression]. -default_algorithms(compression) -> - %% Do not announce '[email protected]' because there seem to be problems - supported_algorithms(compression, same(['[email protected]'])); +%% default_algorithms(kex) -> % Example of how to disable an algorithm +%% supported_algorithms(kex, ['ecdh-sha2-nistp521']); default_algorithms(Alg) -> supported_algorithms(Alg). @@ -79,18 +79,27 @@ supported_algorithms(kex) -> [ {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {ec_curve,secp256r1}, {hashs,sha256}]}, {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {ec_curve,secp384r1}, {hashs,sha384}]}, + {'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]}, + {'diffie-hellman-group-exchange-sha256', [{public_keys,dh}, {hashs,sha256}]}, + {'diffie-hellman-group-exchange-sha1', [{public_keys,dh}, {hashs,sha}]}, {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {ec_curve,secp521r1}, {hashs,sha512}]}, - {'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]}, - {'diffie-hellman-group-exchange-sha256', [{public_keys,dh}, {hashs,sha256}]}, - {'diffie-hellman-group-exchange-sha1', [{public_keys,dh}, {hashs,sha}]}, - {'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]} + {'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]} ]); supported_algorithms(public_key) -> - ssh_auth:default_public_key_algorithms(); + select_crypto_supported( + [{'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {ec_curve,secp256r1}]}, + {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {ec_curve,secp384r1}]}, + {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {ec_curve,secp521r1}]}, + {'ssh-rsa', [{public_keys,rsa}, {hashs,sha} ]}, + {'ssh-dss', [{public_keys,dss}, {hashs,sha} ]} + ]); + supported_algorithms(cipher) -> same( select_crypto_supported( - [{'aes128-ctr', [{ciphers,aes_ctr}]}, + [{'aes256-ctr', [{ciphers,{aes_ctr,256}}]}, + {'aes192-ctr', [{ciphers,{aes_ctr,192}}]}, + {'aes128-ctr', [{ciphers,{aes_ctr,128}}]}, {'aes128-cbc', [{ciphers,aes_cbc128}]}, {'3des-cbc', [{ciphers,des3_cbc}]} ] @@ -98,20 +107,22 @@ supported_algorithms(cipher) -> supported_algorithms(mac) -> same( select_crypto_supported( - [{'hmac-sha2-512', [{hashs,sha512}]}, - {'hmac-sha2-256', [{hashs,sha256}]}, + [{'hmac-sha2-256', [{hashs,sha256}]}, + {'hmac-sha2-512', [{hashs,sha512}]}, {'hmac-sha1', [{hashs,sha}]} ] )); supported_algorithms(compression) -> - same(['none','zlib','[email protected]']). + same(['none', + '[email protected]', + 'zlib' + ]). - -supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) -> - [{client2server,As1},{server2client,As2}] = supported_algorithms(Key), - [{client2server,As1--BL1},{server2client,As2--BL2}]; -supported_algorithms(Key, BlackList) -> - supported_algorithms(Key) -- BlackList. +%% Dialyzer complains when not called...supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) -> +%% Dialyzer complains when not called... [{client2server,As1},{server2client,As2}] = supported_algorithms(Key), +%% Dialyzer complains when not called... [{client2server,As1--BL1},{server2client,As2--BL2}]; +%% Dialyzer complains when not called...supported_algorithms(Key, BlackList) -> +%% Dialyzer complains when not called... supported_algorithms(Key) -- BlackList. select_crypto_supported(L) -> Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()], @@ -124,10 +135,25 @@ crypto_supported_curves() -> end. crypto_supported(Conditions, Supported) -> - lists:all( fun({Tag,CryptoName}) -> - lists:member(CryptoName, proplists:get_value(Tag,Supported,[])) + lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) -> + crypto_name_supported(Tag,CryptoName,Supported); + ({Tag,{Name=aes_ctr,Len}}) when is_integer(Len) -> + crypto_name_supported(Tag,Name,Supported) andalso + ctr_len_supported(Name,Len) end, Conditions). +crypto_name_supported(Tag, CryptoName, Supported) -> + lists:member(CryptoName, proplists:get_value(Tag,Supported,[])). + +ctr_len_supported(Name, Len) -> + try + crypto:stream_encrypt(crypto:stream_init(Name, <<0:Len>>, <<0:128>>), <<"">>) + of + {_,X} -> is_binary(X) + catch + _:_ -> false + end. + same(Algs) -> [{client2server,Algs}, {server2client,Algs}]. @@ -303,9 +329,7 @@ verify_algorithm(#alg{encrypt = undefined}) -> false; verify_algorithm(#alg{decrypt = undefined}) -> false; verify_algorithm(#alg{compress = undefined}) -> false; verify_algorithm(#alg{decompress = undefined}) -> false; - -verify_algorithm(#alg{kex = Kex}) -> lists:member(Kex, supported_algorithms(kex)); -verify_algorithm(_) -> false. +verify_algorithm(#alg{kex = Kex}) -> lists:member(Kex, supported_algorithms(kex)). %%%---------------------------------------------------------------- %%% @@ -319,11 +343,12 @@ key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group1-sha1' ; {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}}; -key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group-exchange-sha1' ; - Kex == 'diffie-hellman-group-exchange-sha256' -> - Min = ?DEFAULT_DH_GROUP_MIN, - NBits = ?DEFAULT_DH_GROUP_NBITS, - Max = ?DEFAULT_DH_GROUP_MAX, +key_exchange_first_msg(Kex, Ssh0=#ssh{opts=Opts}) when Kex == 'diffie-hellman-group-exchange-sha1' ; + Kex == 'diffie-hellman-group-exchange-sha256' -> + {Min,NBits,Max} = + proplists:get_value(dh_gex_limits, Opts, {?DEFAULT_DH_GROUP_MIN, + ?DEFAULT_DH_GROUP_NBITS, + ?DEFAULT_DH_GROUP_MAX}), {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kex_dh_gex_request{min = Min, n = NBits, @@ -354,13 +379,15 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, 1=<E, E=<(P-1) -> {Public, Private} = generate_key(dh, [P,G]), K = compute_key(dh, E, Private, [P,G]), - Key = get_host_key(Ssh0), - H = kex_h(Ssh0, Key, E, Public, K), - H_SIG = sign_host_key(Ssh0, Key, H), - {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_reply{public_host_key = Key, - f = Public, - h_sig = H_SIG - }, Ssh0), + MyPrivHostKey = get_host_key(Ssh0), + MyPubHostKey = extract_public_key(MyPrivHostKey), + H = kex_h(Ssh0, MyPubHostKey, E, Public, K), + H_SIG = sign_host_key(Ssh0, MyPrivHostKey, H), + {SshPacket, Ssh1} = + ssh_packet(#ssh_msg_kexdh_reply{public_host_key = MyPubHostKey, + f = Public, + h_sig = H_SIG + }, Ssh0), {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}, shared_secret = K, exchanged_hash = H, @@ -375,7 +402,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, }) end. -handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, +handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = PeerPubHostKey, f = F, h_sig = H_SIG}, #ssh{keyex_key = {{Private, Public}, {G, P}}} = Ssh0) -> @@ -383,9 +410,9 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, if 1=<F, F=<(P-1)-> K = compute_key(dh, F, Private, [P,G]), - H = kex_h(Ssh0, HostKey, Public, F, K), + H = kex_h(Ssh0, PeerPubHostKey, Public, F, K), - case verify_host_key(Ssh0, HostKey, H, H_SIG) of + case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of ok -> {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), {ok, SshPacket, Ssh#ssh{shared_secret = K, @@ -454,11 +481,12 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E}, K = compute_key(dh, E, Private, [P,G]), if 1<K, K<(P-1) -> - HostKey = get_host_key(Ssh0), - H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, E, Public, K), - H_SIG = sign_host_key(Ssh0, HostKey, H), + MyPrivHostKey = get_host_key(Ssh0), + MyPubHostKey = extract_public_key(MyPrivHostKey), + H = kex_h(Ssh0, MyPubHostKey, Min, NBits, Max, P, G, E, Public, K), + H_SIG = sign_host_key(Ssh0, MyPrivHostKey, H), {SshPacket, Ssh} = - ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, + ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = MyPubHostKey, f = Public, h_sig = H_SIG}, Ssh0), {ok, SshPacket, Ssh#ssh{shared_secret = K, @@ -482,7 +510,7 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E}, }) end. -handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, +handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = PeerPubHostKey, f = F, h_sig = H_SIG}, #ssh{keyex_key = {{Private, Public}, {G, P}}, @@ -494,9 +522,9 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, K = compute_key(dh, F, Private, [P,G]), if 1<K, K<(P-1) -> - H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K), + H = kex_h(Ssh0, PeerPubHostKey, Min, NBits, Max, P, G, Public, F, K), - case verify_host_key(Ssh0, HostKey, H, H_SIG) of + case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of ok -> {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), {ok, SshPacket, Ssh#ssh{shared_secret = K, @@ -539,11 +567,12 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, true -> {MyPublic, MyPrivate} = generate_key(ecdh, Curve), K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), - HostKey = get_host_key(Ssh0), - H = kex_h(Ssh0, Curve, HostKey, PeerPublic, MyPublic, K), - H_SIG = sign_host_key(Ssh0, HostKey, H), + MyPrivHostKey = get_host_key(Ssh0), + MyPubHostKey = extract_public_key(MyPrivHostKey), + H = kex_h(Ssh0, Curve, MyPubHostKey, PeerPublic, MyPublic, K), + H_SIG = sign_host_key(Ssh0, MyPrivHostKey, H), {SshPacket, Ssh1} = - ssh_packet(#ssh_msg_kex_ecdh_reply{public_host_key = HostKey, + ssh_packet(#ssh_msg_kex_ecdh_reply{public_host_key = MyPubHostKey, q_s = MyPublic, h_sig = H_SIG}, Ssh0), @@ -561,7 +590,7 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, }) end. -handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = HostKey, +handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, q_s = PeerPublic, h_sig = H_SIG}, #ssh{keyex_key = {{MyPublic,MyPrivate}, Curve}} = Ssh0 @@ -570,8 +599,8 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = HostKey, case ecdh_validate_public_key(PeerPublic, Curve) of true -> K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), - H = kex_h(Ssh0, Curve, HostKey, MyPublic, PeerPublic, K), - case verify_host_key(Ssh0, HostKey, H, H_SIG) of + H = kex_h(Ssh0, Curve, PeerPubHostKey, MyPublic, PeerPublic, K), + case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of ok -> {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), {ok, SshPacket, Ssh#ssh{shared_secret = K, @@ -596,7 +625,61 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = HostKey, end. -ecdh_validate_public_key(_, _) -> true. % FIXME: Far too many false positives :) +%%%---------------------------------------------------------------- +%%% +%%% Standards for Efficient Cryptography Group, "Elliptic Curve Cryptography", SEC 1 +%%% Section 3.2.2.1 +%%% + +ecdh_validate_public_key(Key, Curve) -> + case key_size(Curve) of + undefined -> + false; + + Sz -> + case dec_key(Key, Sz) of + {ok,Q} -> + case crypto:ec_curve(Curve) of + {{prime_field,P}, {A, B, _Seed}, + _P0Bin, _OrderBin, _CoFactorBin} -> + on_curve(Q, bin2int(A), bin2int(B), bin2int(P)) + end; + + {error,compressed_not_implemented} -> % Be a bit generous... + true; + + _Error -> + false + end + end. + + +on_curve({X,Y}, A, B, P) when 0 =< X,X =< (P-1), + 0 =< Y,Y =< (P-1) -> + %% Section 3.2.2.1, point 2 + (Y*Y) rem P == (X*X*X + A*X + B) rem P; +on_curve(_, _, _, _) -> + false. + + +bin2int(B) -> + Sz = erlang:bit_size(B), + <<I:Sz/big-unsigned-integer>> = B, + I. + +key_size(secp256r1) -> 256; +key_size(secp384r1) -> 384; +key_size(secp521r1) -> 528; % Round 521 up to closest 8-bits. +key_size(_) -> undefined. + + +dec_key(Key, NBits) -> + Size = 8 + 2*NBits, + case <<Key:Size>> of + <<4:8, X:NBits, Y:NBits>> -> {ok,{X,Y}}; + <<4:8, _/binary>> -> {error,bad_format}; + _ -> {error,compressed_not_implemented} + end. %%%---------------------------------------------------------------- handle_new_keys(#ssh_msg_newkeys{}, Ssh0) -> @@ -623,33 +706,49 @@ get_host_key(SSH) -> #ssh{key_cb = Mod, opts = Opts, algorithms = ALG} = SSH, case Mod:host_key(ALG#alg.hkey, Opts) of - {ok, #'RSAPrivateKey'{} = Key} -> - Key; - {ok, #'DSAPrivateKey'{} = Key} -> - Key; + {ok, #'RSAPrivateKey'{} = Key} -> Key; + {ok, #'DSAPrivateKey'{} = Key} -> Key; + {ok, #'ECPrivateKey'{} = Key} -> Key; Result -> exit({error, {Result, unsupported_key_type}}) end. -sign_host_key(_Ssh, #'RSAPrivateKey'{} = Private, H) -> - Hash = sha, - _Signature = sign(H, Hash, Private); -sign_host_key(_Ssh, #'DSAPrivateKey'{} = Private, H) -> - Hash = sha, - _RawSignature = sign(H, Hash, Private). +sign_host_key(_Ssh, PrivateKey, H) -> + sign(H, sign_host_key_sha(PrivateKey), PrivateKey). + +sign_host_key_sha(#'ECPrivateKey'{parameters = {namedCurve,OID}}) -> sha(OID); +sign_host_key_sha(#'RSAPrivateKey'{}) -> sha; +sign_host_key_sha(#'DSAPrivateKey'{}) -> sha. + + +extract_public_key(#'RSAPrivateKey'{modulus = N, publicExponent = E}) -> + #'RSAPublicKey'{modulus = N, publicExponent = E}; +extract_public_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) -> + {Y, #'Dss-Parms'{p=P, q=Q, g=G}}; +extract_public_key(#'ECPrivateKey'{parameters = {namedCurve,OID}, + publicKey = Q}) -> + {#'ECPoint'{point=Q}, {namedCurve,OID}}. + verify_host_key(SSH, PublicKey, Digest, Signature) -> - case verify(Digest, sha, Signature, PublicKey) of + case verify(Digest, host_key_sha(PublicKey), Signature, PublicKey) of false -> {error, bad_signature}; true -> known_host_key(SSH, PublicKey, public_algo(PublicKey)) end. -public_algo(#'RSAPublicKey'{}) -> - 'ssh-rsa'; -public_algo({_, #'Dss-Parms'{}}) -> - 'ssh-dss'. + +host_key_sha(#'RSAPublicKey'{}) -> sha; +host_key_sha({_, #'Dss-Parms'{}}) -> sha; +host_key_sha({#'ECPoint'{},{namedCurve,OID}}) -> sha(OID). + +public_algo(#'RSAPublicKey'{}) -> 'ssh-rsa'; +public_algo({_, #'Dss-Parms'{}}) -> 'ssh-dss'; +public_algo({#'ECPoint'{},{namedCurve,OID}}) -> + Curve = public_key:oid2ssh_curvename(OID), + list_to_atom("ecdsa-sha2-" ++ binary_to_list(Curve)). + accepted_host(Ssh, PeerName, Opts) -> case proplists:get_value(silently_accept_hosts, Opts, false) of @@ -830,11 +929,18 @@ ssh_packet(Msg, Ssh) -> BinMsg = ssh_message:encode(Msg), pack(BinMsg, Ssh). +pack(Data, Ssh=#ssh{}) -> + pack(Data, Ssh, 0). + +%%% Note: pack/3 is only to be called from tests that wants +%%% to deliberetly send packets with wrong PacketLength! +%%% Use pack/2 for all other purposes! pack(Data0, #ssh{encrypt_block_size = BlockSize, send_sequence = SeqNum, send_mac = MacAlg, send_mac_key = MacKey, random_length_padding = RandomLengthPadding} - = Ssh0) when is_binary(Data0) -> + = Ssh0, + PacketLenDeviationForTests) when is_binary(Data0) -> {Ssh1, Data} = compress(Ssh0, Data0), PL = (BlockSize - ((4 + 1 + size(Data)) rem BlockSize)) rem BlockSize, MinPaddingLen = if PL < 4 -> PL + BlockSize; @@ -847,7 +953,7 @@ pack(Data0, #ssh{encrypt_block_size = BlockSize, end, PaddingLen = MinPaddingLen + ExtraPaddingLen, Padding = ssh_bits:random(PaddingLen), - PacketLen = 1 + PaddingLen + size(Data), + PacketLen = 1 + PaddingLen + size(Data) + PacketLenDeviationForTests, PacketData = <<?UINT32(PacketLen),?BYTE(PaddingLen), Data/binary, Padding/binary>>, {Ssh2, EncPacket} = encrypt(Ssh1, PacketData), @@ -889,6 +995,10 @@ sign(SigData, Hash, #'DSAPrivateKey'{} = Key) -> DerSignature = public_key:sign(SigData, Hash, Key), #'Dss-Sig-Value'{r = R, s = S} = public_key:der_decode('Dss-Sig-Value', DerSignature), <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>; +sign(SigData, Hash, Key = #'ECPrivateKey'{}) -> + DerEncodedSign = public_key:sign(SigData, Hash, Key), + #'ECDSA-Sig-Value'{r=R, s=S} = public_key:der_decode('ECDSA-Sig-Value', DerEncodedSign), + ssh_bits:encode([R,S], [mpint,mpint]); sign(SigData, Hash, Key) -> public_key:sign(SigData, Hash, Key). @@ -896,55 +1006,18 @@ verify(PlainText, Hash, Sig, {_, #'Dss-Parms'{}} = Key) -> <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>> = Sig, Signature = public_key:der_encode('Dss-Sig-Value', #'Dss-Sig-Value'{r = R, s = S}), public_key:verify(PlainText, Hash, Signature, Key); +verify(PlainText, Hash, Sig, {#'ECPoint'{},_} = Key) -> + <<?UINT32(Rlen),R:Rlen/big-signed-integer-unit:8, + ?UINT32(Slen),S:Slen/big-signed-integer-unit:8>> = Sig, + Sval = #'ECDSA-Sig-Value'{r=R, s=S}, + DerEncodedSig = public_key:der_encode('ECDSA-Sig-Value',Sval), + public_key:verify(PlainText, Hash, DerEncodedSig, Key); verify(PlainText, Hash, Sig, Key) -> public_key:verify(PlainText, Hash, Sig, Key). -%% public key algorithms -%% -%% ssh-dss REQUIRED sign Raw DSS Key -%% ssh-rsa RECOMMENDED sign Raw RSA Key -%% x509v3-sign-rsa OPTIONAL sign X.509 certificates (RSA key) -%% x509v3-sign-dss OPTIONAL sign X.509 certificates (DSS key) -%% spki-sign-rsa OPTIONAL sign SPKI certificates (RSA key) -%% spki-sign-dss OPTIONAL sign SPKI certificates (DSS key) -%% pgp-sign-rsa OPTIONAL sign OpenPGP certificates (RSA key) -%% pgp-sign-dss OPTIONAL sign OpenPGP certificates (DSS key) -%% - -%% key exchange -%% -%% diffie-hellman-group1-sha1 REQUIRED -%% diffie-hellman-group14-sha1 REQUIRED -%% -%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Encryption -%% -%% chiphers %% -%% 3des-cbc REQUIRED -%% three-key 3DES in CBC mode -%% blowfish-cbc OPTIONAL Blowfish in CBC mode -%% twofish256-cbc OPTIONAL Twofish in CBC mode, -%% with 256-bit key -%% twofish-cbc OPTIONAL alias for "twofish256-cbc" (this -%% is being retained for -%% historical reasons) -%% twofish192-cbc OPTIONAL Twofish with 192-bit key -%% twofish128-cbc OPTIONAL Twofish with 128-bit key -%% aes256-cbc OPTIONAL AES in CBC mode, -%% with 256-bit key -%% aes192-cbc OPTIONAL AES with 192-bit key -%% aes128-cbc RECOMMENDED AES with 128-bit key -%% serpent256-cbc OPTIONAL Serpent in CBC mode, with -%% 256-bit key -%% serpent192-cbc OPTIONAL Serpent with 192-bit key -%% serpent128-cbc OPTIONAL Serpent with 128-bit key -%% arcfour OPTIONAL the ARCFOUR stream cipher -%% idea-cbc OPTIONAL IDEA in CBC mode -%% cast128-cbc OPTIONAL CAST-128 in CBC mode -%% none OPTIONAL no encryption; NOT RECOMMENDED +%% Encryption %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -975,18 +1048,46 @@ encrypt_init(#ssh{encrypt = 'aes128-cbc', role = server} = Ssh) -> encrypt_block_size = 16, encrypt_ctx = IV}}; encrypt_init(#ssh{encrypt = 'aes128-ctr', role = client} = Ssh) -> - IV = hash(Ssh, "A", 128), + IV = hash(Ssh, "A", 128), <<K:16/binary>> = hash(Ssh, "C", 128), State = crypto:stream_init(aes_ctr, K, IV), {ok, Ssh#ssh{encrypt_keys = K, encrypt_block_size = 16, encrypt_ctx = State}}; +encrypt_init(#ssh{encrypt = 'aes192-ctr', role = client} = Ssh) -> + IV = hash(Ssh, "A", 128), + <<K:24/binary>> = hash(Ssh, "C", 192), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = State}}; +encrypt_init(#ssh{encrypt = 'aes256-ctr', role = client} = Ssh) -> + IV = hash(Ssh, "A", 128), + <<K:32/binary>> = hash(Ssh, "C", 256), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = State}}; encrypt_init(#ssh{encrypt = 'aes128-ctr', role = server} = Ssh) -> - IV = hash(Ssh, "B", 128), + IV = hash(Ssh, "B", 128), <<K:16/binary>> = hash(Ssh, "D", 128), State = crypto:stream_init(aes_ctr, K, IV), {ok, Ssh#ssh{encrypt_keys = K, encrypt_block_size = 16, + encrypt_ctx = State}}; +encrypt_init(#ssh{encrypt = 'aes192-ctr', role = server} = Ssh) -> + IV = hash(Ssh, "B", 128), + <<K:24/binary>> = hash(Ssh, "D", 192), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = State}}; +encrypt_init(#ssh{encrypt = 'aes256-ctr', role = server} = Ssh) -> + IV = hash(Ssh, "B", 128), + <<K:32/binary>> = hash(Ssh, "D", 256), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, encrypt_ctx = State}}. encrypt_final(Ssh) -> @@ -1013,6 +1114,14 @@ encrypt(#ssh{encrypt = 'aes128-cbc', encrypt(#ssh{encrypt = 'aes128-ctr', encrypt_ctx = State0} = Ssh, Data) -> {State, Enc} = crypto:stream_encrypt(State0,Data), + {Ssh#ssh{encrypt_ctx = State}, Enc}; +encrypt(#ssh{encrypt = 'aes192-ctr', + encrypt_ctx = State0} = Ssh, Data) -> + {State, Enc} = crypto:stream_encrypt(State0,Data), + {Ssh#ssh{encrypt_ctx = State}, Enc}; +encrypt(#ssh{encrypt = 'aes256-ctr', + encrypt_ctx = State0} = Ssh, Data) -> + {State, Enc} = crypto:stream_encrypt(State0,Data), {Ssh#ssh{encrypt_ctx = State}, Enc}. @@ -1053,12 +1162,40 @@ decrypt_init(#ssh{decrypt = 'aes128-ctr', role = client} = Ssh) -> {ok, Ssh#ssh{decrypt_keys = K, decrypt_block_size = 16, decrypt_ctx = State}}; +decrypt_init(#ssh{decrypt = 'aes192-ctr', role = client} = Ssh) -> + IV = hash(Ssh, "B", 128), + <<K:24/binary>> = hash(Ssh, "D", 192), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = State}}; +decrypt_init(#ssh{decrypt = 'aes256-ctr', role = client} = Ssh) -> + IV = hash(Ssh, "B", 128), + <<K:32/binary>> = hash(Ssh, "D", 256), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = State}}; decrypt_init(#ssh{decrypt = 'aes128-ctr', role = server} = Ssh) -> IV = hash(Ssh, "A", 128), <<K:16/binary>> = hash(Ssh, "C", 128), State = crypto:stream_init(aes_ctr, K, IV), {ok, Ssh#ssh{decrypt_keys = K, decrypt_block_size = 16, + decrypt_ctx = State}}; +decrypt_init(#ssh{decrypt = 'aes192-ctr', role = server} = Ssh) -> + IV = hash(Ssh, "A", 128), + <<K:24/binary>> = hash(Ssh, "C", 192), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = State}}; +decrypt_init(#ssh{decrypt = 'aes256-ctr', role = server} = Ssh) -> + IV = hash(Ssh, "A", 128), + <<K:32/binary>> = hash(Ssh, "C", 256), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, decrypt_ctx = State}}. @@ -1084,6 +1221,14 @@ decrypt(#ssh{decrypt = 'aes128-cbc', decrypt_keys = Key, decrypt(#ssh{decrypt = 'aes128-ctr', decrypt_ctx = State0} = Ssh, Data) -> {State, Enc} = crypto:stream_decrypt(State0,Data), + {Ssh#ssh{decrypt_ctx = State}, Enc}; +decrypt(#ssh{decrypt = 'aes192-ctr', + decrypt_ctx = State0} = Ssh, Data) -> + {State, Enc} = crypto:stream_decrypt(State0,Data), + {Ssh#ssh{decrypt_ctx = State}, Enc}; +decrypt(#ssh{decrypt = 'aes256-ctr', + decrypt_ctx = State0} = Ssh, Data) -> + {State, Enc} = crypto:stream_decrypt(State0,Data), {Ssh#ssh{decrypt_ctx = State}, Enc}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1168,17 +1313,8 @@ decompress(#ssh{decompress = '[email protected]', decompress_ctx = Context, authe {Ssh, list_to_binary(Decompressed)}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% MAC calculation %% -%% hmac-sha1 REQUIRED HMAC-SHA1 (digest length = key -%% length = 20) -%% hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 (digest -%% length = 12, key length = 20) -%% hmac-md5 OPTIONAL HMAC-MD5 (digest length = key -%% length = 16) -%% hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 (digest -%% length = 12, key length = 16) -%% none OPTIONAL no MAC; NOT RECOMMENDED +%% MAC calculation %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1268,52 +1404,58 @@ hash(K, H, Ki, N, HASH) -> hash(K, H, <<Ki/binary, Kj/binary>>, N-128, HASH). kex_h(SSH, Key, E, F, K) -> + KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version, SSH#ssh.c_keyinit, SSH#ssh.s_keyinit, - ssh_message:encode_host_key(Key), E,F,K], + KeyBin, E,F,K], [string,string,binary,binary,binary, mpint,mpint,mpint]), crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). %% crypto:hash(sha,L). kex_h(SSH, Curve, Key, Q_c, Q_s, K) -> + KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version, SSH#ssh.c_keyinit, SSH#ssh.s_keyinit, - ssh_message:encode_host_key(Key), Q_c, Q_s, K], + KeyBin, Q_c, Q_s, K], [string,string,binary,binary,binary, mpint,mpint,mpint]), crypto:hash(sha(Curve), L). kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> L = if Min==-1; Max==-1 -> + KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), Ts = [string,string,binary,binary,binary, uint32, mpint,mpint,mpint,mpint,mpint], ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version, SSH#ssh.c_keyinit,SSH#ssh.s_keyinit, - ssh_message:encode_host_key(Key), NBits, Prime, Gen, E,F,K], + KeyBin, NBits, Prime, Gen, E,F,K], Ts); true -> + KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), Ts = [string,string,binary,binary,binary, uint32,uint32,uint32, mpint,mpint,mpint,mpint,mpint], ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version, SSH#ssh.c_keyinit,SSH#ssh.s_keyinit, - ssh_message:encode_host_key(Key), Min, NBits, Max, + KeyBin, Min, NBits, Max, Prime, Gen, E,F,K], Ts) end, crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). -sha('nistp256') -> sha256; -sha('secp256r1')-> sha256; -sha('nistp384') -> sha384; -sha('secp384r1')-> sha384; -sha('nistp521') -> sha512; -sha('secp521r1')-> sha512; + +sha(secp256r1) -> sha256; +sha(secp384r1) -> sha384; +sha(secp521r1) -> sha512; sha('diffie-hellman-group1-sha1') -> sha; sha('diffie-hellman-group14-sha1') -> sha; sha('diffie-hellman-group-exchange-sha1') -> sha; -sha('diffie-hellman-group-exchange-sha256') -> sha256. +sha('diffie-hellman-group-exchange-sha256') -> sha256; +sha(?'secp256r1') -> sha(secp256r1); +sha(?'secp384r1') -> sha(secp384r1); +sha(?'secp521r1') -> sha(secp521r1). + mac_key_size('hmac-sha1') -> 20*8; mac_key_size('hmac-sha1-96') -> 20*8; @@ -1350,7 +1492,7 @@ dh_gex_group(Min, N, Max, undefined) -> dh_gex_group(Min, N, Max, dh_gex_default_groups()); dh_gex_group(Min, N, Max, Groups) -> %% First try to find an exact match. If not an exact match, select the largest possible. - {_,Group} = + {_Size,Group} = lists:foldl( fun(_, {I,G}) when I==N -> %% If we have an exact match already: use that one diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index d962b1111f..337f455279 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -30,10 +30,10 @@ -define(DEFAULT_CLIENT_VERSION, {2, 0}). -define(DEFAULT_SERVER_VERSION, {2, 0}). --define(MAX_NUM_ALGORITHMS, 100). +-define(MAX_NUM_ALGORITHMS, 200). -define(DEFAULT_DH_GROUP_MIN, 1024). --define(DEFAULT_DH_GROUP_NBITS, 6144). +-define(DEFAULT_DH_GROUP_NBITS, 2048). -define(DEFAULT_DH_GROUP_MAX, 8192). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -258,7 +258,8 @@ {8192, {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF}}). --define(dh_default_groups, [?dh_group14, +-define(dh_default_groups, [?dh_group1, + ?dh_group14, ?dh_group15, ?dh_group16, ?dh_group17, diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index e67fa2469f..2ab83d84e1 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -23,6 +23,7 @@ -module(ssh_algorithms_SUITE). -include_lib("common_test/include/ct.hrl"). +-include_lib("ssh/src/ssh_transport.hrl"). %% Note: This directive should only be used in test suites. -compile(export_all). @@ -57,7 +58,7 @@ groups() -> ], AlgoTcSet = - [{Alg, [], specific_test_cases(Tag,Alg,SshcAlgos,SshdAlgos)} + [{Alg, [parallel], specific_test_cases(Tag,Alg,SshcAlgos,SshdAlgos)} || {Tag,Algs} <- ErlAlgos ++ DoubleAlgos, Alg <- Algs], @@ -72,11 +73,19 @@ init_per_suite(Config) -> "OS ssh:~n=======~n~p~n~n~n" "Erl ssh:~n========~n~p~n~n~n" "Installed ssh client:~n=====================~n~p~n~n~n" - "Installed ssh server:~n=====================~n~p~n~n~n", - [os:cmd("ssh -V"), + "Installed ssh server:~n=====================~n~p~n~n~n" + "Misc values:~n============~n" + " -- Default dh group exchange parameters ({min,def,max}): ~p~n" + " -- dh_default_groups: ~p~n" + " -- Max num algorithms: ~p~n" + ,[os:cmd("ssh -V"), ssh:default_algorithms(), ssh_test_lib:default_algorithms(sshc), - ssh_test_lib:default_algorithms(sshd)]), + ssh_test_lib:default_algorithms(sshd), + {?DEFAULT_DH_GROUP_MIN,?DEFAULT_DH_GROUP_NBITS,?DEFAULT_DH_GROUP_MAX}, + [KeyLen || {KeyLen,_} <- ?dh_default_groups], + ?MAX_NUM_ALGORITHMS + ]), ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]), catch crypto:stop(), case catch crypto:start() of @@ -101,7 +110,8 @@ init_per_group(Group, Config) -> Config; false -> %% An algorithm group - [[{name,Tag}]|_] = ?config(tc_group_path, Config), + Tag = proplists:get_value(name, + hd(?config(tc_group_path, Config))), Alg = Group, PA = case split(Alg) of @@ -162,6 +172,21 @@ simple_exec(Config) -> ssh_test_lib:std_simple_exec(Host, Port, Config). %%-------------------------------------------------------------------- +%% Testing all default groups +simple_exec_group14(Config) -> simple_exec_group(2048, Config). +simple_exec_group15(Config) -> simple_exec_group(3072, Config). +simple_exec_group16(Config) -> simple_exec_group(4096, Config). +simple_exec_group17(Config) -> simple_exec_group(6144, Config). +simple_exec_group18(Config) -> simple_exec_group(8192, Config). + +simple_exec_group(I, Config) -> + Min = I-100, + Max = I+100, + {Host,Port} = ?config(srvr_addr, Config), + ssh_test_lib:std_simple_exec(Host, Port, Config, + [{dh_gex_limits,{Min,I,Max}}]). + +%%-------------------------------------------------------------------- %% Use the ssh client of the OS to connect sshc_simple_exec(Config) -> PrivDir = ?config(priv_dir, Config), @@ -254,6 +279,17 @@ specific_test_cases(Tag, Alg, SshcAlgos, SshdAlgos) -> [sshd_simple_exec]; _ -> [] + end ++ + case {Tag,Alg} of + {kex,_} when Alg == 'diffie-hellman-group-exchange-sha1' ; + Alg == 'diffie-hellman-group-exchange-sha256' -> + [simple_exec_group14, + simple_exec_group15, + simple_exec_group16, + simple_exec_group17, + simple_exec_group18]; + _ -> + [] end. supports(Tag, Alg, Algos) -> diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 51431da48e..400edb4d2c 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -77,6 +77,9 @@ all() -> appup_test, {group, dsa_key}, {group, rsa_key}, + {group, ecdsa_sha2_nistp256_key}, + {group, ecdsa_sha2_nistp384_key}, + {group, ecdsa_sha2_nistp521_key}, {group, dsa_pass_key}, {group, rsa_pass_key}, {group, internal_error}, @@ -89,6 +92,9 @@ all() -> groups() -> [{dsa_key, [], basic_tests()}, {rsa_key, [], basic_tests()}, + {ecdsa_sha2_nistp256_key, [], basic_tests()}, + {ecdsa_sha2_nistp384_key, [], basic_tests()}, + {ecdsa_sha2_nistp521_key, [], basic_tests()}, {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, {internal_error, [], [internal_error]} @@ -117,8 +123,6 @@ end_per_suite(_Config) -> ssh:stop(), crypto:stop(). %%-------------------------------------------------------------------- -init_per_group(hardening_tests, Config) -> - init_per_group(dsa_key, Config); init_per_group(dsa_key, Config) -> DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), @@ -129,6 +133,39 @@ init_per_group(rsa_key, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:setup_rsa(DataDir, PrivDir), Config; +init_per_group(ecdsa_sha2_nistp256_key, Config) -> + case lists:member('ecdsa-sha2-nistp256', + ssh_transport:default_algorithms(public_key)) of + true -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_ecdsa("256", DataDir, PrivDir), + Config; + false -> + {skip, unsupported_pub_key} + end; +init_per_group(ecdsa_sha2_nistp384_key, Config) -> + case lists:member('ecdsa-sha2-nistp384', + ssh_transport:default_algorithms(public_key)) of + true -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_ecdsa("384", DataDir, PrivDir), + Config; + false -> + {skip, unsupported_pub_key} + end; +init_per_group(ecdsa_sha2_nistp521_key, Config) -> + case lists:member('ecdsa-sha2-nistp521', + ssh_transport:default_algorithms(public_key)) of + true -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_ecdsa("521", DataDir, PrivDir), + Config; + false -> + {skip, unsupported_pub_key} + end; init_per_group(rsa_pass_key, Config) -> DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), @@ -190,8 +227,6 @@ init_per_group(dir_options, Config) -> init_per_group(_, Config) -> Config. -end_per_group(hardening_tests, Config) -> - end_per_group(dsa_key, Config); end_per_group(dsa_key, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:clean_dsa(PrivDir), @@ -362,30 +397,36 @@ exec(Config) when is_list(Config) -> %%-------------------------------------------------------------------- %%% Test that compression option works exec_compressed(Config) when is_list(Config) -> - process_flag(trap_exit, true), - SystemDir = filename:join(?config(priv_dir, Config), system), - UserDir = ?config(priv_dir, Config), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, - {preferred_algorithms,[{compression, [zlib]}]}, - {failfun, fun ssh_test_lib:failfun/2}]), + case ssh_test_lib:ssh_supports(zlib, compression) of + false -> + {skip, "zlib compression is not supported"}; + + true -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, + {preferred_algorithms,[{compression, [zlib]}]}, + {failfun, fun ssh_test_lib:failfun/2}]), - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user_dir, UserDir}, - {user_interaction, false}]), - {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), - success = ssh_connection:exec(ConnectionRef, ChannelId, - "1+1.", infinity), - Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}}, - case ssh_test_lib:receive_exec_result(Data) of - expected -> - ok; - Other -> - ct:fail(Other) - end, - ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), - ssh:stop_daemon(Pid). + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}]), + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId, + "1+1.", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ok; + Other -> + ct:fail(Other) + end, + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), + ssh:stop_daemon(Pid) + end. %%-------------------------------------------------------------------- %%% Idle timeout test @@ -428,6 +469,8 @@ shell(Config) when is_list(Config) -> ErlShellStart -> ct:log("Erlang shell start: ~p~n", [ErlShellStart]), do_shell(IO, Shell) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -456,11 +499,15 @@ cli(Config) when is_list(Config) -> {ssh_cm, ConnectionRef, {data,0,0, <<"\r\nYou are accessing a dummy, type \"q\" to exit\r\n\n">>}} -> ok = ssh_connection:send(ConnectionRef, ChannelId, <<"q">>) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId}} -> ok + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -599,7 +646,7 @@ peername_sockname(Config) when is_list(Config) -> host_equal(HostSockSrv, Host), PortSockSrv = Port after 10000 -> - throw(timeout) + ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. host_equal(H1, H2) -> @@ -633,7 +680,7 @@ close(Config) when is_list(Config) -> {ssh_cm, Client,{closed, ChannelId}} -> ok after 5000 -> - ct:fail(timeout) + ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -708,22 +755,28 @@ shell_unicode_string(Config) -> %%-------------------------------------------------------------------- %%% Test basic connection with openssh_zlib openssh_zlib_basic_test(Config) -> - SystemDir = filename:join(?config(priv_dir, Config), system), - UserDir = ?config(priv_dir, Config), + case ssh_test_lib:ssh_supports(['[email protected]',none], compression) of + {false,L} -> + {skip, io_lib:format("~p compression is not supported",[L])}; - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {preferred_algorithms,[{compression, ['[email protected]']}]}, - {failfun, fun ssh_test_lib:failfun/2}]), - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user_dir, UserDir}, - {user_interaction, false}, - {preferred_algorithms,[{compression, ['[email protected]', - none]}]} - ]), - ok = ssh:close(ConnectionRef), - ssh:stop_daemon(Pid). + true -> + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {preferred_algorithms,[{compression, ['[email protected]']}]}, + {failfun, fun ssh_test_lib:failfun/2}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}, + {preferred_algorithms,[{compression, ['[email protected]', + none]}]} + ]), + ok = ssh:close(ConnectionRef), + ssh:stop_daemon(Pid) + end. %%-------------------------------------------------------------------- ssh_info_print(Config) -> @@ -825,22 +878,32 @@ do_shell(IO, Shell) -> receive Echo0 -> ct:log("Echo: ~p ~n", [Echo0]) + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive ?NEWLINE -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive Result0 = <<"2">> -> ct:log("Result: ~p~n", [Result0]) + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive ?NEWLINE -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive ErlPrompt1 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt1]) + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, exit(Shell, kill). %%Does not seem to work in the testserver! diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256 b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256 new file mode 100644 index 0000000000..4b1eb12eaa --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIJfCaBKIIKhjbJl5F8BedqlXOQYDX5ba9Skypllmx/w+oAoGCCqGSM49 +AwEHoUQDQgAE49RbK2xQ/19ji3uDPM7uT4692LbwWF1TiaA9vUuebMGazoW/98br +N9xZu0L1AWwtEjs3kmJDTB7eJEGXnjUAcQ== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256.pub new file mode 100644 index 0000000000..a0147e60fa --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOPUWytsUP9fY4t7gzzO7k+Ovdi28FhdU4mgPb1LnmzBms6Fv/fG6zfcWbtC9QFsLRI7N5JiQ0we3iRBl541AHE= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384 b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384 new file mode 100644 index 0000000000..4e8aa40959 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384 @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDCYXb6OSAZyXRfLXOtMo43za197Hdc/T0YKjgQQjwDt6rlRwqTh7v7S +PV2kXwNGdWigBwYFK4EEACKhZANiAARN2khlJUOOIiwsWHEALwDieeZR96qL4pUd +ci7aeGaczdUK5jOA9D9zmBZtSYTfO8Cr7ekVghDlcWAIJ/BXcswgQwSEQ6wyfaTF +8FYfyr4l3u9IirsnyaFzeIgeoNis8Gw= +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384.pub new file mode 100644 index 0000000000..41e722e545 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBE3aSGUlQ44iLCxYcQAvAOJ55lH3qovilR1yLtp4ZpzN1QrmM4D0P3OYFm1JhN87wKvt6RWCEOVxYAgn8FdyzCBDBIRDrDJ9pMXwVh/KviXe70iKuyfJoXN4iB6g2KzwbA== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521 b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521 new file mode 100644 index 0000000000..7196f46e97 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521 @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHbAgEBBEFMadoz4ckEcClfqXa2tiUuYkJdDfwq+/iFQcpt8ESuEd26IY/vm47Q +9UzbPkO4ou8xkNsQ3WvCRQBBWtn5O2kUU6AHBgUrgQQAI6GBiQOBhgAEAde5BRu5 +01/jS0jRk212xsb2DxPrxNpgp6IMCV8TA4Eps+8bSqHB091nLiBcP422HXYfuCd7 +XDjSs8ihcmhp0hCRASLqZR9EzW9W/SOt876May1Huj5X+WSO6RLe7vPn9vmf7kHf +pip6m7M7qp2qGgQ3q2vRwS2K/O6156ohiOlmuuFs +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521.pub new file mode 100644 index 0000000000..8f059120bc --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHXuQUbudNf40tI0ZNtdsbG9g8T68TaYKeiDAlfEwOBKbPvG0qhwdPdZy4gXD+Nth12H7gne1w40rPIoXJoadIQkQEi6mUfRM1vVv0jrfO+jGstR7o+V/lkjukS3u7z5/b5n+5B36YqepuzO6qdqhoEN6tr0cEtivzuteeqIYjpZrrhbA== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256 b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256 new file mode 100644 index 0000000000..2979ea88ed --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIMe4MDoit0t8RzSVPwkCBemQ9fhXL+xnTSAWISw8HNCioAoGCCqGSM49 +AwEHoUQDQgAEo2q7U3P6r0W5WGOLtM78UQtofM9UalEhiZeDdiyylsR/RR17Op0s +VPGSADLmzzgcucLEKy17j2S+oz42VUJy5A== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256.pub new file mode 100644 index 0000000000..85dc419345 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNqu1Nz+q9FuVhji7TO/FELaHzPVGpRIYmXg3YsspbEf0UdezqdLFTxkgAy5s84HLnCxCste49kvqM+NlVCcuQ= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384 b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384 new file mode 100644 index 0000000000..fb1a862ded --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384 @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDArxbDfh3p1okrD9wQw6jJ4d4DdlBPD5GqXE8bIeRJiK41Sh40LgvPw +mkqEDSXK++CgBwYFK4EEACKhZANiAAScl43Ih2lWTDKrSox5ve5uiTXil4smsup3 +CfS1XPjKxgBAmlfBim8izbdrT0BFdQzz2joduNMtpt61wO4rGs6jm0UP7Kim9PC7 +Hneb/99fIYopdMH5NMnk60zGO1uZ2vc= +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384.pub new file mode 100644 index 0000000000..428d5fb7d7 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBJyXjciHaVZMMqtKjHm97m6JNeKXiyay6ncJ9LVc+MrGAECaV8GKbyLNt2tPQEV1DPPaOh240y2m3rXA7isazqObRQ/sqKb08Lsed5v/318hiil0wfk0yeTrTMY7W5na9w== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521 b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521 new file mode 100644 index 0000000000..3e51ec2ecd --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521 @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIB8O1BFkl2HQjQLRLonEZ97da/h39DMa9/0/hvPZWAI8gUPEQcHxRx +U7b09p3Zh+EBbMFq8+1ae9ds+ZTxE4WFSvKgBwYFK4EEACOhgYkDgYYABAAlWVjq +Bzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/ +vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5 +ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521.pub new file mode 100644 index 0000000000..017a29f4da --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAlWVjqBzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl index fbcf06290a..1b93cc9c32 100644 --- a/lib/ssh/test/ssh_connection_SUITE.erl +++ b/lib/ssh/test/ssh_connection_SUITE.erl @@ -48,7 +48,8 @@ all() -> gracefull_invalid_long_start, gracefull_invalid_long_start_no_nl, stop_listener, - start_subsystem_on_closed_channel + start_subsystem_on_closed_channel, + max_channels_option ]. groups() -> [{openssh, [], payload() ++ ptty()}]. @@ -119,20 +120,28 @@ simple_exec(Config) when is_list(Config) -> receive {ssh_cm, ConnectionRef, {data, ChannelId0, 0, <<"testing\n">>}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, %% receive close messages receive {ssh_cm, ConnectionRef, {eof, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -154,20 +163,28 @@ small_cat(Config) when is_list(Config) -> receive {ssh_cm, ConnectionRef, {data, ChannelId0, 0, Data}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, %% receive close messages receive {ssh_cm, ConnectionRef, {eof, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- big_cat() -> @@ -211,11 +228,15 @@ big_cat(Config) when is_list(Config) -> %% receive close messages (eof already consumed) receive {ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} -> - ok + ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -234,14 +255,20 @@ send_after_exit(Config) when is_list(Config) -> receive {ssh_cm, ConnectionRef, {eof, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef, {exit_status, ChannelId0, _ExitStatus}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, case ssh_connection:send(ConnectionRef, ChannelId0, Data, 2000) of {error, closed} -> ok; @@ -455,6 +482,8 @@ gracefull_invalid_version(Config) when is_list(Config) -> {tcp_closed, S} -> ok end + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. gracefull_invalid_start(Config) when is_list(Config) -> @@ -475,6 +504,8 @@ gracefull_invalid_start(Config) when is_list(Config) -> {tcp_closed, S} -> ok end + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. gracefull_invalid_long_start(Config) when is_list(Config) -> @@ -495,6 +526,8 @@ gracefull_invalid_long_start(Config) when is_list(Config) -> {tcp_closed, S} -> ok end + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. @@ -516,6 +549,8 @@ gracefull_invalid_long_start_no_nl(Config) when is_list(Config) -> {tcp_closed, S} -> ok end + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. stop_listener() -> @@ -606,6 +641,88 @@ start_subsystem_on_closed_channel(Config) -> ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- +max_channels_option() -> + [{doc, "Test max_channels option"}]. + +max_channels_option(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {max_channels, 3}, + {subsystems, [{"echo_n", {ssh_echo_server, [4000000]}}]} + ]), + + ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, true}, + {user_dir, UserDir}]), + + {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId2} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId3} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId4} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId5} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, _ChannelId6} = ssh_connection:session_channel(ConnectionRef, infinity), + + %%%---- shell + ok = ssh_connection:shell(ConnectionRef,ChannelId0), + receive + {ssh_cm,ConnectionRef, {data, ChannelId0, 0, <<"Eshell",_/binary>>}} -> + ok + after 5000 -> + ct:fail("CLI Timeout") + end, + + %%%---- subsystem "echo_n" + success = ssh_connection:subsystem(ConnectionRef, ChannelId1, "echo_n", infinity), + + %%%---- exec #1 + success = ssh_connection:exec(ConnectionRef, ChannelId2, "testing1.\n", infinity), + receive + {ssh_cm, ConnectionRef, {data, ChannelId2, 0, <<"testing1",_/binary>>}} -> + ok + after 5000 -> + ct:fail("Exec #1 Timeout") + end, + + %%%---- ptty + success = ssh_connection:ptty_alloc(ConnectionRef, ChannelId3, []), + + %%%---- exec #2 + failure = ssh_connection:exec(ConnectionRef, ChannelId4, "testing2.\n", infinity), + + %%%---- close the shell + ok = ssh_connection:send(ConnectionRef, ChannelId0, "exit().\n", 5000), + + %%%---- wait for the subsystem to terminate + receive + {ssh_cm,ConnectionRef,{closed,ChannelId0}} -> ok + after 5000 -> + ct:log("Timeout waiting for '{ssh_cm,~p,{closed,~p}}'~n" + "Message queue:~n~p", + [ConnectionRef,ChannelId0,erlang:process_info(self(),messages)]), + ct:fail("exit Timeout",[]) + end, + + %%%---- exec #3 + success = ssh_connection:exec(ConnectionRef, ChannelId5, "testing3.\n", infinity), + receive + {ssh_cm, ConnectionRef, {data, ChannelId5, 0, <<"testing3",_/binary>>}} -> + ok + after 5000 -> + ct:fail("Exec #3 Timeout") + end, + + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- big_cat_rx(ConnectionRef, ChannelId) -> diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl index d64c78da35..cf15ca4253 100644 --- a/lib/ssh/test/ssh_options_SUITE.erl +++ b/lib/ssh/test/ssh_options_SUITE.erl @@ -656,6 +656,8 @@ ssh_connect_arg4_timeout(_Config) -> %% Get listening port Port = receive {port,Server,ServerPort} -> ServerPort + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, %% try to connect with a timeout, but "supervise" it @@ -861,6 +863,8 @@ ssh_connect_nonegtimeout_connected(Config, Parallel) -> ct:sleep(round(Factor * NegTimeOut)), one_shell_op(IO, NegTimeOut) + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, exit(Shell, kill). @@ -869,13 +873,13 @@ one_shell_op(IO, TimeOut) -> ct:log("One shell op: Waiting for prompter"), receive ErlPrompt0 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt0]) - after TimeOut -> ct:fail("Timeout waiting for promter") + after TimeOut -> ct:fail("Timeout waiting for promter") end, IO ! {input, self(), "2*3*7.\r\n"}, receive Echo0 -> ct:log("Echo: ~p ~n", [Echo0]) - after TimeOut -> ct:fail("Timeout waiting for echo") + after TimeOut -> ct:fail("Timeout waiting for echo") end, receive @@ -888,7 +892,7 @@ one_shell_op(IO, TimeOut) -> receive Result0 -> ct:log("Result: ~p~n", [Result0]) - after TimeOut -> ct:fail("Timeout waiting for result") + after TimeOut -> ct:fail("Timeout waiting for result") end. %%-------------------------------------------------------------------- @@ -1016,9 +1020,13 @@ fake_daemon(_Config) -> {ok,S} = Rsa, receive {tcp, S, Id} -> Parent ! {id,self(),Id} + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end end), %% Get listening host and port receive {sockname,Server,ServerHost,ServerPort} -> {Server, ServerHost, ServerPort} + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index d8e99799e2..b84ccac885 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -46,7 +46,10 @@ suite() -> all() -> [{group,tool_tests}, - {group,kex} + {group,kex}, + {group,service_requests}, + {group,packet_size_error}, + {group,field_size_error} ]. groups() -> @@ -55,13 +58,25 @@ groups() -> lib_match, lib_no_match ]}, + {packet_size_error, [], [packet_length_too_large, + packet_length_too_short]}, + + {field_size_error, [], [service_name_length_too_large, + service_name_length_too_short]}, + {kex, [], [no_common_alg_server_disconnects, no_common_alg_client_disconnects, gex_client_init_default_noexact, gex_client_init_default_exact, gex_client_init_option_groups, gex_client_init_option_groups_file - ]} + ]}, + {service_requests, [], [bad_service_name, + bad_long_service_name, + bad_very_long_service_name, + empty_service_name, + bad_service_name_then_correct + ]} ]. @@ -91,7 +106,7 @@ init_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; [] end, start_std_daemon(Config, - [{preferred_algorithms, ssh_transport:supported_algorithms()} + [{preferred_algorithms, ssh:default_algorithms()} | Opts]); init_per_testcase(_TestCase, Config) -> check_std_daemon_works(Config, ?LINE). @@ -114,25 +129,10 @@ end_per_testcase(_TestCase, Config) -> %%% Connect to an erlang server and check that the testlib acts as a client. lib_works_as_client(Config) -> %% Connect and negotiate keys - {ok,InitialState} = - ssh_trpt_test_lib:exec( - [{set_options, [print_ops, print_seqnums, print_messages]}, - {connect, - server_host(Config),server_port(Config), - [{preferred_algorithms,[{kex,['diffie-hellman-group1-sha1']}]}, - {silently_accept_hosts, true}, - {user_dir, user_dir(Config)}, - {user_interaction, false}]}, - receive_hello, - {send, hello}, - {send, ssh_msg_kexinit}, - {match, #ssh_msg_kexinit{_='_'}, receive_msg}, - {send, ssh_msg_kexdh_init}, - {match,# ssh_msg_kexdh_reply{_='_'}, receive_msg}, - {send, #ssh_msg_newkeys{}}, - {match, #ssh_msg_newkeys{_='_'}, receive_msg} - ] - ), + {ok,InitialState} = ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}] + ), + {ok,AfterKexState} = connect_and_kex(Config, InitialState), %% Do the authentcation {User,Pwd} = server_user_password(Config), @@ -147,7 +147,7 @@ lib_works_as_client(Config) -> ?STRING(unicode:characters_to_binary(Pwd))>> }}, {match, #ssh_msg_userauth_success{_='_'}, receive_msg} - ], InitialState), + ], AfterKexState), %% Disconnect {ok,_} = @@ -327,6 +327,8 @@ no_common_alg_client_disconnects(Config) -> X -> ct:log("¤¤¤¤¤"), ct:fail(X) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%%-------------------------------------------------------------------- @@ -373,6 +375,106 @@ do_gex_client_init(Config, {Min,N,Max}, {_,{G,P}}) -> ] ). + +%%%-------------------------------------------------------------------- +bad_service_name(Config) -> + bad_service_name(Config, "kfglkjf"). + +bad_long_service_name(Config) -> + bad_service_name(Config, + lists:duplicate(?SSH_MAX_PACKET_SIZE div 2, $a)). + +bad_very_long_service_name(Config) -> + bad_service_name(Config, + lists:duplicate(4*?SSH_MAX_PACKET_SIZE, $a)). + +empty_service_name(Config) -> + bad_service_name(Config, ""). + +bad_service_name_then_correct(Config) -> + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, #ssh_msg_service_request{name = "kdjglkfdjgkldfjglkdfjglkfdjglkj"}}, + {send, #ssh_msg_service_request{name = "ssh-connection"}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + + +bad_service_name(Config, Name) -> + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, #ssh_msg_service_request{name = Name}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + +%%%-------------------------------------------------------------------- +packet_length_too_large(Config) -> bad_packet_length(Config, +4). + +packet_length_too_short(Config) -> bad_packet_length(Config, -4). + +bad_packet_length(Config, LengthExcess) -> + PacketFun = + fun(Msg, Ssh) -> + BinMsg = ssh_message:encode(Msg), + ssh_transport:pack(BinMsg, Ssh, LengthExcess) + end, + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, {special, + #ssh_msg_service_request{name="ssh-userauth"}, + PacketFun}}, + %% Prohibit remote decoder starvation: + {send, #ssh_msg_service_request{name="ssh-userauth"}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + +%%%-------------------------------------------------------------------- +service_name_length_too_large(Config) -> bad_service_name_length(Config, +4). + +service_name_length_too_short(Config) -> bad_service_name_length(Config, -4). + + +bad_service_name_length(Config, LengthExcess) -> + PacketFun = + fun(#ssh_msg_service_request{name=Service}, Ssh) -> + BinName = list_to_binary(Service), + BinMsg = + <<?BYTE(?SSH_MSG_SERVICE_REQUEST), + %% A bad string encoding of Service: + ?UINT32(size(BinName)+LengthExcess), BinName/binary + >>, + ssh_transport:pack(BinMsg, Ssh) + end, + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, {special, + #ssh_msg_service_request{name="ssh-userauth"}, + PacketFun} }, + %% Prohibit remote decoder starvation: + {send, #ssh_msg_service_request{name="ssh-userauth"}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + %%%================================================================ %%%==== Internal functions ======================================== %%%================================================================ @@ -480,3 +582,24 @@ std_connect(Host, Port, Config, Opts) -> 30000). %%%---------------------------------------------------------------- +connect_and_kex(Config) -> + connect_and_kex(Config, ssh_trpt_test_lib:exec([]) ). + +connect_and_kex(Config, InitialState) -> + ssh_trpt_test_lib:exec( + [{connect, + server_host(Config),server_port(Config), + [{preferred_algorithms,[{kex,['diffie-hellman-group1-sha1']}]}, + {silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false}]}, + receive_hello, + {send, hello}, + {send, ssh_msg_kexinit}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + {send, ssh_msg_kexdh_init}, + {match,# ssh_msg_kexdh_reply{_='_'}, receive_msg}, + {send, #ssh_msg_newkeys{}}, + {match, #ssh_msg_newkeys{_='_'}, receive_msg} + ], + InitialState). diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl index 9daa6efc02..ef631d54bd 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE.erl +++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl @@ -89,9 +89,10 @@ rekey_limit(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "rekey.data"), - {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[]), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 4500}]), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 6000}, + {max_random_length_padding,0}]), {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), Kex1 = get_kex_init(ConnectionRef), @@ -132,13 +133,13 @@ renegotiate1(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "renegotiate1.data"), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[]), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), RPort = ssh_test_lib:inet_port(), {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, []), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), Kex1 = get_kex_init(ConnectionRef), @@ -170,12 +171,12 @@ renegotiate2(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "renegotiate2.data"), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[]), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), RPort = ssh_test_lib:inet_port(), {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, []), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), Kex1 = get_kex_init(ConnectionRef), diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 32fdec9842..698af259c8 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -526,6 +526,8 @@ async_read(Config) when is_list(Config) -> ok; Msg -> ct:fail(Msg) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- async_write() -> @@ -593,6 +595,8 @@ pos_read(Config) when is_list(Config) -> ok; Msg -> ct:fail(Msg) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, NewData1 = "hopp", @@ -618,6 +622,8 @@ pos_write(Config) when is_list(Config) -> ok; Msg -> ct:fail(Msg) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, ok = ssh_sftp:pwrite(Sftp, Handle, eof, list_to_binary("!")), diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index 94a54ec9db..6b03a2b763 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -683,6 +683,8 @@ reply(Cm, Channel, RBuf) -> closed; {ssh_cm, Cm, Msg} -> ct:fail(Msg) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 6d568125bb..5816b708f2 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -93,9 +93,12 @@ std_connect(Config, Host, Port, ExtraOpts) -> | ExtraOpts]). std_simple_sftp(Host, Port, Config) -> + std_simple_sftp(Host, Port, Config, []). + +std_simple_sftp(Host, Port, Config, Opts) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "test.data"), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, []), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, Opts), {ok, ChannelRef} = ssh_sftp:start_channel(ConnectionRef), Data = crypto:rand_bytes(proplists:get_value(std_simple_sftp_size,Config,10)), ok = ssh_sftp:write_file(ChannelRef, DataFile, Data), @@ -104,7 +107,10 @@ std_simple_sftp(Host, Port, Config) -> Data == ReadData. std_simple_exec(Host, Port, Config) -> - ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, []), + std_simple_exec(Host, Port, Config, []). + +std_simple_exec(Host, Port, Config, Opts) -> + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, Opts), {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), success = ssh_connection:exec(ConnectionRef, ChannelId, "23+21-2.", infinity), Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"42\n">>}}, @@ -157,7 +163,9 @@ loop_io_server(TestCase, Buff0) -> {'EXIT',_, _} -> erlang:display('ssh_test_lib:loop_io_server/2 EXIT'), ok - end. + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) + end. io_request({put_chars, Chars}, TestCase, _, _, Buff) -> reply(TestCase, Chars), @@ -206,6 +214,8 @@ receive_exec_result(Msg) -> Other -> ct:log("Other ~p", [Other]), {unexpected_msg, Other} + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. @@ -286,6 +296,7 @@ setup_dsa(DataDir, UserDir) -> file:make_dir(System), file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")), file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")), +ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), setup_dsa_known_host(DataDir, UserDir), setup_dsa_auth_keys(DataDir, UserDir). @@ -294,10 +305,21 @@ setup_rsa(DataDir, UserDir) -> System = filename:join(UserDir, "system"), file:make_dir(System), file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")), - file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key.pub")), + file:copy(filename:join(DataDir, "ssh_host_rsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")), +ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), setup_rsa_known_host(DataDir, UserDir), setup_rsa_auth_keys(DataDir, UserDir). +setup_ecdsa(Size, DataDir, UserDir) -> + file:copy(filename:join(DataDir, "id_ecdsa"++Size), filename:join(UserDir, "id_ecdsa")), + System = filename:join(UserDir, "system"), + file:make_dir(System), + file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size), filename:join(System, "ssh_host_ecdsa_key")), + file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size++".pub"), filename:join(System, "ssh_host_ecdsa_key.pub")), +ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), + setup_ecdsa_known_host(Size, System, UserDir), + setup_ecdsa_auth_keys(Size, UserDir, UserDir). + clean_dsa(UserDir) -> del_dirs(filename:join(UserDir, "system")), file:delete(filename:join(UserDir,"id_dsa")), @@ -349,6 +371,11 @@ setup_rsa_known_host(SystemDir, UserDir) -> [{Key, _}] = public_key:ssh_decode(SshBin, public_key), setup_known_hosts(Key, UserDir). +setup_ecdsa_known_host(_Size, SystemDir, UserDir) -> + {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_ecdsa_key.pub")), + [{Key, _}] = public_key:ssh_decode(SshBin, public_key), + setup_known_hosts(Key, UserDir). + setup_known_hosts(Key, UserDir) -> {ok, Hostname} = inet:gethostname(), {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet), @@ -376,6 +403,14 @@ setup_rsa_auth_keys(Dir, UserDir) -> PKey = #'RSAPublicKey'{publicExponent = E, modulus = N}, setup_auth_keys([{ PKey, [{comment, "Test"}]}], UserDir). +setup_ecdsa_auth_keys(_Size, Dir, UserDir) -> + {ok, Pem} = file:read_file(filename:join(Dir, "id_ecdsa")), + ECDSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))), + #'ECPrivateKey'{publicKey = Q, + parameters = Param = {namedCurve,_Id0}} = ECDSA, + PKey = #'ECPoint'{point = Q}, + setup_auth_keys([{ {PKey,Param}, [{comment, "Test"}]}], UserDir). + setup_auth_keys(Keys, Dir) -> AuthKeys = public_key:ssh_encode(Keys, auth_keys), AuthKeysFile = filename:join(Dir, "authorized_keys"), @@ -424,6 +459,14 @@ openssh_sanity_check(Config) -> {skip, Str} end. +openssh_supports(ClientOrServer, Tag, Alg) when ClientOrServer == sshc ; + ClientOrServer == sshd -> + SSH_algos = ssh_test_lib:default_algorithms(ClientOrServer), + L = proplists:get_value(Tag, SSH_algos, []), + lists:member(Alg, L) orelse + lists:member(Alg, proplists:get_value(client2server, L, [])) orelse + lists:member(Alg, proplists:get_value(server2client, L, [])). + %%-------------------------------------------------------------------- %% Check if we have a "newer" ssh client that supports these test cases @@ -443,7 +486,63 @@ check_ssh_client_support2(P) -> -1 end. -default_algorithms(Host, Port) -> +%%%-------------------------------------------------------------------- +%%% Probe a server or a client about algorithm support + +default_algorithms(sshd) -> + default_algorithms(sshd, "localhost", 22); + +default_algorithms(sshc) -> + default_algorithms(sshc, []). + +default_algorithms(sshd, Host, Port) -> + try run_fake_ssh( + ssh_trpt_test_lib:exec( + [{connect,Host,Port, [{silently_accept_hosts, true}, + {user_interaction, false}]}])) + catch + _C:_E -> + ct:pal("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]), + [] + end. + +default_algorithms(sshc, DaemonOptions) -> + Parent = self(), + %% Start a process handling one connection on the server side: + Srvr = + spawn_link( + fun() -> + Parent ! + {result, self(), + try + {ok,InitialState} = ssh_trpt_test_lib:exec(listen), + Parent ! {hostport,self(),ssh_trpt_test_lib:server_host_port(InitialState)}, + run_fake_ssh( + ssh_trpt_test_lib:exec([{accept, DaemonOptions}], + InitialState)) + catch + _C:_E -> + ct:pal("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]), + [] + end} + end), + + receive + {hostport,Srvr,{_Host,Port}} -> + spawn(fun()-> os:cmd(lists:concat(["ssh -o \"StrictHostKeyChecking no\" -p ",Port," localhost"])) end) + after ?TIMEOUT -> + ct:fail("No server respons 1") + end, + + receive + {result,Srvr,L} -> + L + after ?TIMEOUT -> + ct:fail("No server respons 2") + end. + + +run_fake_ssh({ok,InitialState}) -> KexInitPattern = #ssh_msg_kexinit{ kex_algorithms = '$kex_algorithms', @@ -456,61 +555,35 @@ default_algorithms(Host, Port) -> compression_algorithms_server_to_client = '$compression_algorithms_server_to_client', _ = '_' }, + {ok,E} = ssh_trpt_test_lib:exec([{set_options,[silent]}, + {send, hello}, + receive_hello, + {send, ssh_msg_kexinit}, + {match, KexInitPattern, receive_msg}, + close_socket + ], + InitialState), + [Kex, PubKey, EncC2S, EncS2C, MacC2S, MacS2C, CompC2S, CompS2C] = + ssh_trpt_test_lib:instantiate(['$kex_algorithms', + '$server_host_key_algorithms', + '$encryption_algorithms_client_to_server', + '$encryption_algorithms_server_to_client', + '$mac_algorithms_client_to_server', + '$mac_algorithms_server_to_client', + '$compression_algorithms_client_to_server', + '$compression_algorithms_server_to_client' + ], E), + [{kex, to_atoms(Kex)}, + {public_key, to_atoms(PubKey)}, + {cipher, [{client2server, to_atoms(EncC2S)}, + {server2client, to_atoms(EncS2C)}]}, + {mac, [{client2server, to_atoms(MacC2S)}, + {server2client, to_atoms(MacS2C)}]}, + {compression, [{client2server, to_atoms(CompC2S)}, + {server2client, to_atoms(CompS2C)}]}]. + - try ssh_trpt_test_lib:exec( - [{connect,Host,Port, [{silently_accept_hosts, true}, - {user_interaction, false}]}, - {send,hello}, - receive_hello, - {send, ssh_msg_kexinit}, - {match, KexInitPattern, receive_msg}, - close_socket]) - of - {ok,E} -> - [Kex, PubKey, EncC2S, EncS2C, MacC2S, MacS2C, CompC2S, CompS2C] = - ssh_trpt_test_lib:instantiate(['$kex_algorithms', - '$server_host_key_algorithms', - '$encryption_algorithms_client_to_server', - '$encryption_algorithms_server_to_client', - '$mac_algorithms_client_to_server', - '$mac_algorithms_server_to_client', - '$compression_algorithms_client_to_server', - '$compression_algorithms_server_to_client' - ], E), - [{kex, to_atoms(Kex)}, - {public_key, to_atoms(PubKey)}, - {cipher, [{client2server, to_atoms(EncC2S)}, - {server2client, to_atoms(EncS2C)}]}, - {mac, [{client2server, to_atoms(MacC2S)}, - {server2client, to_atoms(MacS2C)}]}, - {compression, [{client2server, to_atoms(CompC2S)}, - {server2client, to_atoms(CompS2C)}]}]; - _ -> - [] - catch - _:_ -> - [] - end. - - -default_algorithms(sshd) -> - default_algorithms("localhost", 22); -default_algorithms(sshc) -> - case os:find_executable("ssh") of - false -> - []; - _ -> - Cipher = sshc(cipher), - Mac = sshc(mac), - [{kex, sshc(kex)}, - {public_key, sshc(key)}, - {cipher, [{client2server, Cipher}, - {server2client, Cipher}]}, - {mac, [{client2server, Mac}, - {server2client, Mac}]} - ] - end. - +%%-------------------------------------------------------------------- sshc(Tag) -> to_atoms( string:tokens(os:cmd(lists:concat(["ssh -Q ",Tag])), "\n") @@ -552,4 +625,24 @@ algo_intersection(_, _) -> to_atoms(L) -> lists:map(fun erlang:list_to_atom/1, L). - +%%%---------------------------------------------------------------- +ssh_supports(Alg, SshDefaultAlg_tag) -> + SupAlgs = + case proplists:get_value(SshDefaultAlg_tag, + ssh:default_algorithms()) of + [{_K1,L1}, {_K2,L2}] -> + lists:usort(L1++L2); + L -> + L + end, + if + is_atom(Alg) -> + lists:member(Alg, SupAlgs); + is_list(Alg) -> + case Alg--SupAlgs of + [] -> + true; + UnSup -> + {false,UnSup} + end + end. diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 104c1f9107..d1dfa2efdf 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -45,7 +45,6 @@ all() -> groups() -> [{erlang_client, [], [erlang_shell_client_openssh_server, - erlang_client_openssh_server_exec, erlang_client_openssh_server_exec_compressed, erlang_client_openssh_server_setenv, erlang_client_openssh_server_publickey_rsa, @@ -54,12 +53,7 @@ groups() -> erlang_client_openssh_server_kexs, erlang_client_openssh_server_nonexistent_subsystem ]}, - {erlang_server, [], [erlang_server_openssh_client_exec, - erlang_server_openssh_client_exec_compressed, - erlang_server_openssh_client_pulic_key_dsa, - erlang_server_openssh_client_cipher_suites, - erlang_server_openssh_client_macs, - erlang_server_openssh_client_kexs]} + {erlang_server, [], [erlang_server_openssh_client_public_key_dsa]} ]. init_per_suite(Config) -> @@ -88,7 +82,7 @@ init_per_group(erlang_server, Config) -> init_per_group(erlang_client, Config) -> CommonAlgs = ssh_test_lib:algo_intersection( ssh:default_algorithms(), - ssh_test_lib:default_algorithms("localhost", 22)), + ssh_test_lib:default_algorithms(sshd)), [{common_algs,CommonAlgs} | Config]; init_per_group(_, Config) -> Config. @@ -100,18 +94,21 @@ end_per_group(erlang_server, Config) -> end_per_group(_, Config) -> Config. -init_per_testcase(erlang_server_openssh_client_cipher_suites, Config) -> - check_ssh_client_support(Config); - -init_per_testcase(erlang_server_openssh_client_macs, Config) -> - check_ssh_client_support(Config); - -init_per_testcase(erlang_server_openssh_client_kexs, Config) -> - check_ssh_client_support(Config); - -init_per_testcase(erlang_client_openssh_server_kexs, Config) -> - check_ssh_client_support(Config); +init_per_testcase(erlang_server_openssh_client_public_key_dsa, Config) -> + case ssh_test_lib:openssh_supports(sshc, public_key, 'ssh-dss') of + true -> + init_per_testcase('__default__',Config); + false -> + {skip,"openssh client does not support DSA"} + end; +init_per_testcase(erlang_client_openssh_server_publickey_dsa, Config) -> + case ssh_test_lib:openssh_supports(sshd, public_key, 'ssh-dss') of + true -> + init_per_testcase('__default__',Config); + false -> + {skip,"openssh client does not support DSA"} + end; init_per_testcase(_TestCase, Config) -> ssh:start(), Config. @@ -182,23 +179,29 @@ erlang_client_openssh_server_exec_compressed() -> erlang_client_openssh_server_exec_compressed(Config) when is_list(Config) -> CompressAlgs = [zlib, '[email protected]',none], - ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, - {user_interaction, false}, - {preferred_algorithms, - [{compression,CompressAlgs}]}]), - {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), - success = ssh_connection:exec(ConnectionRef, ChannelId, - "echo testing", infinity), - Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}}, - case ssh_test_lib:receive_exec_result(Data) of - expected -> - ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId); - {unexpected_msg,{ssh_cm, ConnectionRef, - {exit_status, ChannelId, 0}} = ExitStatus} -> - ct:log("0: Collected data ~p", [ExitStatus]), - ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId); - Other -> - ct:fail(Other) + case ssh_test_lib:ssh_supports(CompressAlgs, compression) of + {false,L} -> + {skip, io_lib:format("~p compression is not supported",[L])}; + + true -> + ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}, + {preferred_algorithms, + [{compression,CompressAlgs}]}]), + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId, + "echo testing", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId); + {unexpected_msg,{ssh_cm, ConnectionRef, + {exit_status, ChannelId, 0}} = ExitStatus} -> + ct:log("0: Collected data ~p", [ExitStatus]), + ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId); + Other -> + ct:fail(Other) + end end. %%-------------------------------------------------------------------- @@ -252,202 +255,6 @@ erlang_client_openssh_server_kexs(Config) when is_list(Config) -> end. %%-------------------------------------------------------------------- -erlang_server_openssh_client_exec() -> - [{doc, "Test that exec command works."}]. - -erlang_server_openssh_client_exec(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - - - ct:sleep(500), - - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " 1+1.", - - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("Did not receive answer") - - end, - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -erlang_server_openssh_client_cipher_suites() -> - [{doc, "Test that we can connect with different cipher suites."}]. - -erlang_server_openssh_client_cipher_suites(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - - ct:sleep(500), - - OpenSshCiphers = - ssh_test_lib:to_atoms( - string:tokens(os:cmd("ssh -Q cipher"), "\n")), - ErlCiphers = - proplists:get_value(client2server, - proplists:get_value(cipher, ssh:default_algorithms())), - CommonCiphers = - ssh_test_lib:algo_intersection(ErlCiphers, OpenSshCiphers), - - comment(CommonCiphers), - - lists:foreach( - fun(Cipher) -> - Cmd = lists:concat(["ssh -p ",Port, - " -o UserKnownHostsFile=",KnownHosts," ",Host," ", - " -c ",Cipher," 1+1."]), - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("~p Did not receive answer",[Cipher]) - end - end, CommonCiphers), - - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -erlang_server_openssh_client_macs() -> - [{doc, "Test that we can connect with different MACs."}]. - -erlang_server_openssh_client_macs(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - - - ct:sleep(500), - - OpenSshMacs = - ssh_test_lib:to_atoms( - string:tokens(os:cmd("ssh -Q mac"), "\n")), - ErlMacs = - proplists:get_value(client2server, - proplists:get_value(mac, ssh:default_algorithms())), - CommonMacs = - ssh_test_lib:algo_intersection(ErlMacs, OpenSshMacs), - - comment(CommonMacs), - - lists:foreach( - fun(MAC) -> - Cmd = lists:concat(["ssh -p ",Port, - " -o UserKnownHostsFile=",KnownHosts," ",Host," ", - " -o MACs=",MAC," 1+1."]), - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("~p Did not receive answer",[MAC]) - end - end, CommonMacs), - - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -erlang_server_openssh_client_kexs() -> - [{doc, "Test that we can connect with different KEXs."}]. - -erlang_server_openssh_client_kexs(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}, - {preferred_algorithms, - [{kex,ssh_transport:supported_algorithms(kex)}]} - ]), - ct:sleep(500), - - OpenSshKexs = - ssh_test_lib:to_atoms( - string:tokens(os:cmd("ssh -Q kex"), "\n")), - ErlKexs = - proplists:get_value(kex, ssh:default_algorithms()), - CommonKexs = - ssh_test_lib:algo_intersection(ErlKexs, OpenSshKexs), - - comment(CommonKexs), - - lists:foreach( - fun(Kex) -> - Cmd = lists:concat(["ssh -p ",Port, - " -o UserKnownHostsFile=",KnownHosts," ",Host," ", - " -o KexAlgorithms=",Kex," 1+1."]), - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:log("~p Did not receive answer",[Kex]) - end - end, CommonKexs), - - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -erlang_server_openssh_client_exec_compressed() -> - [{doc, "Test that exec command works."}]. - -erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - -%% CompressAlgs = [zlib, '[email protected]'], % Does not work - CompressAlgs = [zlib], - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {preferred_algorithms, - [{compression, CompressAlgs}]}, - {failfun, fun ssh_test_lib:failfun/2}]), - - ct:sleep(500), - - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ " -C "++ Host ++ " 1+1.", - SshPort = open_port({spawn, Cmd}, [binary]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("Did not receive answer") - - end, - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- erlang_client_openssh_server_setenv() -> [{doc, "Test api function ssh_connection:setenv"}]. @@ -543,9 +350,9 @@ erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) -> {skip, "no ~/.ssh/id_dsa"} end. %%-------------------------------------------------------------------- -erlang_server_openssh_client_pulic_key_dsa() -> +erlang_server_openssh_client_public_key_dsa() -> [{doc, "Validate using dsa publickey."}]. -erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) -> +erlang_server_openssh_client_public_key_dsa(Config) when is_list(Config) -> SystemDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), KnownHosts = filename:join(PrivDir, "known_hosts"), @@ -642,6 +449,8 @@ receive_hej() -> ct:log("Extra info: ~p~n", [Info]), receive_hej() end + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. receive_logout() -> @@ -651,11 +460,15 @@ receive_logout() -> receive <<"Connection closed">> -> ok + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end; Info -> ct:log("Extra info when logging out: ~p~n", [Info]), receive_logout() - end. + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) + end. receive_normal_exit(Shell) -> receive @@ -665,6 +478,8 @@ receive_normal_exit(Shell) -> receive_normal_exit(Shell); Other -> ct:fail({unexpected_msg, Other}) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. extra_logout() -> diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index caf9bac3b6..4269529ae8 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -73,7 +73,10 @@ exec(Op, S0=#s{}) -> op(Op, S1)) of S = #s{} -> - print_traces(S), + case proplists:get_value(silent,S#s.opts) of + true -> ok; + _ -> print_traces(S) + end, {ok,S} catch {fail,Reason,Se} -> @@ -383,7 +386,14 @@ send(S0, Line) when is_binary(Line) -> fun(X) when X==true;X==detail -> {"Send line~n~p~n",[Line]} end), send_bytes(Line, S#s{return_value = Line}); -%%% Msg = #ssh_msg_*{} +send(S0, {special,Msg,PacketFun}) when is_tuple(Msg), + is_function(PacketFun,2) -> + S = opt(print_messages, S0, + fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end), + {Packet, C} = PacketFun(Msg, S#s.ssh), + send_bytes(Packet, S#s{ssh = C, %%inc_send_seq_num(C), + return_value = Msg}); + send(S0, Msg) when is_tuple(Msg) -> S = opt(print_messages, S0, fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end), @@ -743,7 +753,7 @@ print_traces(S) -> [case Len-length(Acc)-1 of 0 -> io_lib:format(Fmt,Args); - N -> + _N -> io_lib:format(lists:concat(['~p --------~n',Fmt]), [Len-length(Acc)-1|Args]) end | Acc] diff --git a/lib/ssh/test/ssh_upgrade_SUITE.erl b/lib/ssh/test/ssh_upgrade_SUITE.erl index 85f4d36258..0d936c118b 100644 --- a/lib/ssh/test/ssh_upgrade_SUITE.erl +++ b/lib/ssh/test/ssh_upgrade_SUITE.erl @@ -46,20 +46,17 @@ all() -> init_per_suite(Config0) -> catch crypto:stop(), - try {crypto:start(), erlang:system_info({wordsize, internal}) == - erlang:system_info({wordsize, external})} of - {ok, true} -> - case ct_release_test:init(Config0) of - {skip, Reason} -> - {skip, Reason}; - Config -> - ssh:start(), - Config - end; - {ok, false} -> - {skip, "Test server will not handle halfwordemulator correctly. Skip as halfwordemulator is deprecated"} + try crypto:start() of + ok -> + case ct_release_test:init(Config0) of + {skip, Reason} -> + {skip, Reason}; + Config -> + ssh:start(), + Config + end catch _:_ -> - {skip, "Crypto did not start"} + {skip, "Crypto did not start"} end. end_per_suite(Config) -> diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index b305eedcdc..d828bccd29 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,4 +1,4 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.1 +SSH_VSN = 4.2 APP_VSN = "ssh-$(SSH_VSN)" diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index b87b1b4fa7..6faa3d5f9a 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -26,7 +26,63 @@ <file>notes.xml</file> </header> <p>This document describes the changes made to the SSL application.</p> - <section><title>SSL 7.0</title> + <section><title>SSL 7.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Add DER encoded ECPrivateKey as valid input format for + key option.</p> + <p> + Own Id: OTP-12974</p> + </item> + <item> + <p> + Correct return value of default session callback module</p> + <p> + This error had the symptom that the client check for + unique session would always fail, potentially making the + client session table grow a lot and causing long setup + times.</p> + <p> + Own Id: OTP-12980</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add possibility to downgrade an SSL/TLS connection to a + tcp connection, and give back the socket control to a + user process.</p> + <p> + This also adds the possibility to specify a timeout to + the ssl:close function.</p> + <p> + Own Id: OTP-11397</p> + </item> + <item> + <p> + Add application setting to be able to change fatal alert + shutdown timeout, also shorten the default timeout. The + fatal alert timeout is the number of milliseconds between + sending of a fatal alert and closing the connection. + Waiting a little while improves the peers chances to + properly receiving the alert so it may shutdown + gracefully.</p> + <p> + Own Id: OTP-12832</p> + </item> + </list> + </section> + +</section> + +<section><title>SSL 7.0</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 6c977bdb74..22ac98c24e 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -766,6 +766,21 @@ fun(srp, Username :: string(), UserState :: term()) -> </func> <func> + <name>close(SslSocket, How) -> ok | {ok, port()} | {error, Reason}</name> + <fsummary>Closes an SSL connection.</fsummary> + <type> + <v>SslSocket = sslsocket()</v> + <v>How = timeout() | {NewController::pid(), timeout()} </v> + <v>Reason = term()</v> + </type> + <desc><p>Closes or downgrades an SSL connection, in the later case the transport + connection will be handed over to the <c>NewController</c> process after reciving + the TLS close alert from the peer. The retuned transport socket will have + the following options set [{active, false}, {packet, 0}, {mode, binary}].</p> + </desc> + </func> + + <func> <name>connection_info(SslSocket) -> {ok, {ProtocolVersion, CipherSuite}} | {error, Reason}</name> <fsummary>Returns the Negotiated Protocol version and cipher suite. diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml index 2b6dc7e8be..51ce0cedf1 100644 --- a/lib/ssl/doc/src/ssl_app.xml +++ b/lib/ssl/doc/src/ssl_app.xml @@ -87,6 +87,17 @@ marker="ssl#clear_pem_cache-0">ssl:clear_pem_cache/0</seealso> </item> + <tag><c><![CDATA[alert_timeout = integer() <optional>]]></c></tag> + <item> + <p> + Number of milliseconds between sending of a fatal alert and + closing the connection. Waiting a little while improves the + peers chances to properly receiving the alert so it may + shutdown gracefully. Defaults to 5000 milliseconds. + </p> + </item> + + </taglist> </section> diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src index 1476336039..8d5bd6f8d8 100644 --- a/lib/ssl/src/ssl.appup.src +++ b/lib/ssl/src/ssl.appup.src @@ -1,12 +1,24 @@ %% -*- erlang -*- {"%VSN%", [ + {<<"7\\.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, + {load_module, ssl_connection, soft_purge, soft_purge, []}, + {load_module, tls_connection, soft_purge, soft_purge, []}, + {load_module, ssl_session, soft_purge, soft_purge, []}, + {load_module, ssl_session_cache, soft_purge, soft_purge, []} + ]}, {<<"6\\..*">>, [{restart_application, ssl}]}, {<<"5\\..*">>, [{restart_application, ssl}]}, {<<"4\\..*">>, [{restart_application, ssl}]}, {<<"3\\..*">>, [{restart_application, ssl}]} ], [ + {<<"7\\.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, + {load_module, ssl_connection, soft_purge, soft_purge, []}, + {load_module, tls_connection, soft_purge, soft_purge, []}, + {load_module, ssl_session, soft_purge, soft_purge, []}, + {load_module, ssl_session_cache, soft_purge, soft_purge, []} + ]}, {<<"6\\..*">>, [{restart_application, ssl}]}, {<<"5\\..*">>, [{restart_application, ssl}]}, {<<"4\\..*">>, [{restart_application, ssl}]}, diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 9f2af73204..03495cfd90 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -34,7 +34,7 @@ listen/2, transport_accept/1, transport_accept/2, ssl_accept/1, ssl_accept/2, ssl_accept/3, controlling_process/2, peername/1, peercert/1, sockname/1, - close/1, shutdown/2, recv/2, recv/3, send/2, getopts/2, setopts/2 + close/1, close/2, shutdown/2, recv/2, recv/3, send/2, getopts/2, setopts/2 ]). %% SSL/TLS protocol handling -export([cipher_suites/0, cipher_suites/1, suite_definition/1, @@ -99,7 +99,8 @@ stop() -> connect(Socket, SslOptions) when is_port(Socket) -> connect(Socket, SslOptions, infinity). -connect(Socket, SslOptions0, Timeout) when is_port(Socket) -> +connect(Socket, SslOptions0, Timeout) when is_port(Socket), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> {Transport,_,_,_} = proplists:get_value(cb_info, SslOptions0, {gen_tcp, tcp, tcp_closed, tcp_error}), EmulatedOptions = ssl_socket:emulated_options(), @@ -125,7 +126,7 @@ connect(Socket, SslOptions0, Timeout) when is_port(Socket) -> connect(Host, Port, Options) -> connect(Host, Port, Options, infinity). -connect(Host, Port, Options, Timeout) -> +connect(Host, Port, Options, Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> try handle_options(Options) of {ok, Config} -> do_connect(Host,Port,Config,Timeout) @@ -175,7 +176,7 @@ transport_accept(#sslsocket{pid = {ListenSocket, #config{transport_info = {Transport,_,_, _} =CbInfo, connection_cb = ConnectionCb, ssl = SslOpts, - emulated = Tracker}}}, Timeout) -> + emulated = Tracker}}}, Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> case Transport:accept(ListenSocket, Timeout) of {ok, Socket} -> {ok, EmOpts} = ssl_socket:get_emulated_opts(Tracker), @@ -208,15 +209,16 @@ transport_accept(#sslsocket{pid = {ListenSocket, ssl_accept(ListenSocket) -> ssl_accept(ListenSocket, infinity). -ssl_accept(#sslsocket{} = Socket, Timeout) -> +ssl_accept(#sslsocket{} = Socket, Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> ssl_connection:handshake(Socket, Timeout); ssl_accept(ListenSocket, SslOptions) when is_port(ListenSocket) -> ssl_accept(ListenSocket, SslOptions, infinity). -ssl_accept(#sslsocket{} = Socket, [], Timeout) -> +ssl_accept(#sslsocket{} = Socket, [], Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity)-> ssl_accept(#sslsocket{} = Socket, Timeout); -ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts0, Timeout) -> +ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts0, Timeout) when + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity)-> try {ok, EmOpts, InheritedSslOpts} = ssl_socket:get_all_opts(Tracker), SslOpts = handle_options(SslOpts0, InheritedSslOpts), @@ -224,7 +226,8 @@ ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts0, Timeout) -> catch Error = {error, _Reason} -> Error end; -ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) -> +ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> {Transport,_,_,_} = proplists:get_value(cb_info, SslOptions, {gen_tcp, tcp, tcp_closed, tcp_error}), EmulatedOptions = ssl_socket:emulated_options(), @@ -247,11 +250,27 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) -> %% Description: Close an ssl connection %%-------------------------------------------------------------------- close(#sslsocket{pid = Pid}) when is_pid(Pid) -> - ssl_connection:close(Pid); + ssl_connection:close(Pid, {close, ?DEFAULT_TIMEOUT}); close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}) -> Transport:close(ListenSocket). %%-------------------------------------------------------------------- +-spec close(#sslsocket{}, integer() | {pid(), integer()}) -> term(). +%% +%% Description: Close an ssl connection +%%-------------------------------------------------------------------- +close(#sslsocket{pid = TLSPid}, + {Pid, Timeout} = DownGrade) when is_pid(TLSPid), + is_pid(Pid), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> + ssl_connection:close(TLSPid, {close, DownGrade}); +close(#sslsocket{pid = TLSPid}, Timeout) when is_pid(TLSPid), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> + ssl_connection:close(TLSPid, {close, Timeout}); +close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}, _) -> + Transport:close(ListenSocket). + +%%-------------------------------------------------------------------- -spec send(#sslsocket{}, iodata()) -> ok | {error, reason()}. %% %% Description: Sends data over the ssl connection @@ -269,7 +288,8 @@ send(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport, _, _, _} %%-------------------------------------------------------------------- recv(Socket, Length) -> recv(Socket, Length, infinity). -recv(#sslsocket{pid = Pid}, Length, Timeout) when is_pid(Pid) -> +recv(#sslsocket{pid = Pid}, Length, Timeout) when is_pid(Pid), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity)-> ssl_connection:recv(Pid, Length, Timeout); recv(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _}}}}, _,_) when is_port(Listen)-> @@ -804,6 +824,7 @@ validate_option(key, {KeyType, Value}) when is_binary(Value), KeyType == dsa; %% Backwards compatibility KeyType == 'RSAPrivateKey'; KeyType == 'DSAPrivateKey'; + KeyType == 'ECPrivateKey'; KeyType == 'PrivateKeyInfo' -> {KeyType, Value}; diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 5b754c16bc..f8afbdb41d 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -41,7 +41,7 @@ socket_control/4, socket_control/5]). %% User Events --export([send/2, recv/3, close/1, shutdown/2, +-export([send/2, recv/3, close/2, shutdown/2, new_user/2, get_opts/2, set_opts/2, session_info/1, peer_certificate/1, renegotiation/1, negotiated_protocol/1, prf/5, connection_information/1 @@ -171,18 +171,19 @@ connection_information(Pid) when is_pid(Pid) -> sync_send_all_state_event(Pid, connection_information). %%-------------------------------------------------------------------- --spec close(pid()) -> ok | {error, reason()}. +-spec close(pid(), {close, Timeout::integer() | + {NewController::pid(), Timeout::integer()}}) -> + ok | {ok, port()} | {error, reason()}. %% %% Description: Close an ssl connection %%-------------------------------------------------------------------- -close(ConnectionPid) -> - case sync_send_all_state_event(ConnectionPid, close) of +close(ConnectionPid, How) -> + case sync_send_all_state_event(ConnectionPid, How) of {error, closed} -> ok; Other -> Other end. - %%-------------------------------------------------------------------- -spec shutdown(pid(), atom()) -> ok | {error, reason()}. %% @@ -706,12 +707,12 @@ handle_sync_event({start, Timeout}, StartFrom, StateName, #state{role = Role, s {stop, normal, {error, Error}, State0} end; -handle_sync_event(close, _, StateName, #state{protocol_cb = Connection} = State) -> - %% Run terminate before returning - %% so that the reuseaddr inet-option will work - %% as intended. - (catch Connection:terminate(user_close, StateName, State)), - {stop, normal, ok, State#state{terminated = true}}; +handle_sync_event({close, _} = Close, _, StateName, #state{protocol_cb = Connection} = State) -> + %% Run terminate before returning so that the reuseaddr + %% inet-option and possible downgrade will work as intended. + Result = Connection:terminate(Close, StateName, State), + {stop, normal, Result, State#state{terminated = true}}; + handle_sync_event({shutdown, How0}, _, StateName, #state{transport_cb = Transport, negotiated_version = Version, @@ -901,41 +902,46 @@ terminate(_, _, #state{terminated = true}) -> %% we want to guarantee that Transport:close has been called %% when ssl:close/1 returns. ok; -terminate({shutdown, transport_closed}, StateName, #state{send_queue = SendQueue, - renegotiation = Renegotiate} = State) -> - handle_unrecv_data(StateName, State), +terminate({shutdown, transport_closed} = Reason, + _StateName, #state{send_queue = SendQueue, protocol_cb = Connection, + socket = Socket, transport_cb = Transport, + renegotiation = Renegotiate} = State) -> handle_trusted_certs_db(State), notify_senders(SendQueue), - notify_renegotiater(Renegotiate); - -terminate({shutdown, own_alert}, _StateName, #state{send_queue = SendQueue, - renegotiation = Renegotiate} = State) -> + notify_renegotiater(Renegotiate), + Connection:close(Reason, Socket, Transport, undefined, undefined); +terminate({shutdown, own_alert}, _StateName, #state{send_queue = SendQueue, protocol_cb = Connection, + socket = Socket, transport_cb = Transport, + renegotiation = Renegotiate} = State) -> handle_trusted_certs_db(State), notify_senders(SendQueue), - notify_renegotiater(Renegotiate); + notify_renegotiater(Renegotiate), + case application:get_env(ssl, alert_timeout) of + {ok, Timeout} when is_integer(Timeout) -> + Connection:close({timeout, Timeout}, Socket, Transport, undefined, undefined); + _ -> + Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, undefined, undefined) + end; terminate(Reason, connection, #state{negotiated_version = Version, protocol_cb = Connection, - connection_states = ConnectionStates, + connection_states = ConnectionStates0, + ssl_options = #ssl_options{padding_check = Check}, transport_cb = Transport, socket = Socket, send_queue = SendQueue, renegotiation = Renegotiate} = State) -> handle_trusted_certs_db(State), notify_senders(SendQueue), notify_renegotiater(Renegotiate), - BinAlert = terminate_alert(Reason, Version, ConnectionStates), + {BinAlert, ConnectionStates} = terminate_alert(Reason, Version, ConnectionStates0), Transport:send(Socket, BinAlert), - case Connection of - tls_connection -> - tls_connection:workaround_transport_delivery_problems(Socket, Transport); - _ -> - ok - end; -terminate(_Reason, _StateName, #state{transport_cb = Transport, + Connection:close(Reason, Socket, Transport, ConnectionStates, Check); + +terminate(Reason, _StateName, #state{transport_cb = Transport, protocol_cb = Connection, socket = Socket, send_queue = SendQueue, renegotiation = Renegotiate} = State) -> handle_trusted_certs_db(State), notify_senders(SendQueue), notify_renegotiater(Renegotiate), - Transport:close(Socket). + Connection:close(Reason, Socket, Transport, undefined, undefined). format_status(normal, [_, State]) -> [{data, [{"StateData", State}]}]; @@ -1758,30 +1764,17 @@ get_timeout(#state{ssl_options=#ssl_options{hibernate_after = undefined}}) -> get_timeout(#state{ssl_options=#ssl_options{hibernate_after = HibernateAfter}}) -> HibernateAfter. -terminate_alert(Reason, Version, ConnectionStates) when Reason == normal; - Reason == user_close -> - {BinAlert, _} = ssl_alert:encode(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), - Version, ConnectionStates), - BinAlert; -terminate_alert({shutdown, _}, Version, ConnectionStates) -> - {BinAlert, _} = ssl_alert:encode(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), - Version, ConnectionStates), - BinAlert; +terminate_alert(normal, Version, ConnectionStates) -> + ssl_alert:encode(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), + Version, ConnectionStates); +terminate_alert({Reason, _}, Version, ConnectionStates) when Reason == close; + Reason == shutdown -> + ssl_alert:encode(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), + Version, ConnectionStates); terminate_alert(_, Version, ConnectionStates) -> - {BinAlert, _} = ssl_alert:encode(?ALERT_REC(?FATAL, ?INTERNAL_ERROR), - Version, ConnectionStates), - BinAlert. - -handle_unrecv_data(StateName, #state{socket = Socket, transport_cb = Transport, - protocol_cb = Connection} = State) -> - ssl_socket:setopts(Transport, Socket, [{active, false}]), - case Transport:recv(Socket, 0, 0) of - {error, closed} -> - ok; - {ok, Data} -> - Connection:handle_close_alert(Data, StateName, State) - end. + ssl_alert:encode(?ALERT_REC(?FATAL, ?INTERNAL_ERROR), + Version, ConnectionStates). handle_trusted_certs_db(#state{ssl_options = #ssl_options{cacertfile = <<>>, cacerts = []}}) -> %% No trusted certs specified diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl index 9a58f2b8f7..bb41ef2b62 100644 --- a/lib/ssl/src/ssl_connection.hrl +++ b/lib/ssl/src/ssl_connection.hrl @@ -48,27 +48,28 @@ socket_options :: #socket_options{}, connection_states :: #connection_states{} | secret_printout(), protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hrl - tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout(), - cert_db :: reference(), + tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout() + | 'undefined', + cert_db :: reference() | 'undefined', session :: #session{} | secret_printout(), session_cache :: db_handle(), session_cache_cb :: atom(), crl_db :: term(), - negotiated_version :: ssl_record:ssl_version(), + negotiated_version :: ssl_record:ssl_version() | 'undefined', client_certificate_requested = false :: boolean(), key_algorithm :: ssl_cipher:key_algo(), hashsign_algorithm = {undefined, undefined}, cert_hashsign_algorithm, - public_key_info :: ssl_handshake:public_key_info(), - private_key :: public_key:private_key() | secret_printout(), + public_key_info :: ssl_handshake:public_key_info() | 'undefined', + private_key :: public_key:private_key() | secret_printout() | 'undefined', diffie_hellman_params:: #'DHParameter'{} | undefined | secret_printout(), diffie_hellman_keys :: {PublicKey :: binary(), PrivateKey :: binary()} | #'ECPrivateKey'{} | undefined | secret_printout(), - psk_identity :: binary(), % server psk identity hint - srp_params :: #srp_user{} | secret_printout(), - srp_keys ::{PublicKey :: binary(), PrivateKey :: binary()} | secret_printout(), - premaster_secret :: binary() | secret_printout() , + psk_identity :: binary() | 'undefined', % server psk identity hint + srp_params :: #srp_user{} | secret_printout() | 'undefined', + srp_keys ::{PublicKey :: binary(), PrivateKey :: binary()} | secret_printout() | 'undefined', + premaster_secret :: binary() | secret_printout() | 'undefined', file_ref_db :: db_handle(), - cert_db_ref :: certdb_ref(), + cert_db_ref :: certdb_ref() | 'undefined', bytes_to_read :: undefined | integer(), %% bytes to read in passive mode user_data_buffer :: undefined | binary() | secret_printout(), renegotiation :: undefined | {boolean(), From::term() | internal | peer}, @@ -81,7 +82,7 @@ expecting_finished = false ::boolean(), negotiated_protocol = undefined :: undefined | binary(), client_ecc, % {Curves, PointFmt} - tracker :: pid(), %% Tracker process for listen socket + tracker :: pid() | 'undefined', %% Tracker process for listen socket sni_hostname = undefined }). diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index 3851b2bc6e..007723c982 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -90,16 +90,16 @@ validate_extensions_fun, depth :: integer(), certfile :: binary(), - cert :: public_key:der_encoded() | secret_printout(), + cert :: public_key:der_encoded() | secret_printout() | 'undefined', keyfile :: binary(), - key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()} | secret_printout(), - password :: string() | secret_printout(), - cacerts :: [public_key:der_encoded()] | secret_printout(), + key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()} | secret_printout() | 'undefined', + password :: string() | secret_printout() | 'undefined', + cacerts :: [public_key:der_encoded()] | secret_printout() | 'undefined', cacertfile :: binary(), dh :: public_key:der_encoded() | secret_printout(), - dhfile :: binary() | secret_printout(), + dhfile :: binary() | secret_printout() | 'undefined', user_lookup_fun, % server option, fun to lookup the user - psk_identity :: binary() | secret_printout() , + psk_identity :: binary() | secret_printout() | 'undefined', srp_identity, % client option {User, Password} ciphers, % %% Local policy for the server if it want's to reuse the session @@ -115,7 +115,7 @@ %% undefined if not hibernating, or number of ms of %% inactivity after which ssl_connection will go into %% hibernation - hibernate_after :: boolean(), + hibernate_after :: boolean() | 'undefined', %% This option should only be set to true by inet_tls_dist erl_dist = false :: boolean(), alpn_advertised_protocols = undefined :: [binary()] | undefined , diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl index 1770faf1ff..0d6cc93a20 100644 --- a/lib/ssl/src/ssl_session.erl +++ b/lib/ssl/src/ssl_session.erl @@ -100,14 +100,14 @@ select_session([], _, _) -> no_session; select_session(Sessions, #ssl_options{ciphers = Ciphers}, OwnCert) -> IsNotResumable = - fun([_Id, Session]) -> + fun(Session) -> not (resumable(Session#session.is_resumable) andalso lists:member(Session#session.cipher_suite, Ciphers) andalso (OwnCert == Session#session.own_certificate)) end, case lists:dropwhile(IsNotResumable, Sessions) of [] -> no_session; - [[Id, _]|_] -> Id + [Session | _] -> Session#session.session_id end. is_resumable(_, _, #ssl_options{reuse_sessions = false}, _, _, _, _) -> diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl index 11ed310477..cfc48cd935 100644 --- a/lib/ssl/src/ssl_session_cache.erl +++ b/lib/ssl/src/ssl_session_cache.erl @@ -83,7 +83,7 @@ foldl(Fun, Acc0, Cache) -> %%-------------------------------------------------------------------- select_session(Cache, PartialKey) -> ets:select(Cache, - [{{{PartialKey,'$1'}, '$2'},[],['$$']}]). + [{{{PartialKey,'_'}, '$1'},[],['$1']}]). %%-------------------------------------------------------------------- %%% Internal functions diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 7fda2377ee..3093508f61 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -54,7 +54,7 @@ %% Alert and close handling -export([send_alert/2, handle_own_alert/4, handle_close_alert/3, handle_normal_shutdown/3, handle_unexpected_message/3, - workaround_transport_delivery_problems/2, alert_user/6, alert_user/9 + close/5, alert_user/6, alert_user/9 ]). %% Data handling @@ -924,8 +924,7 @@ handle_own_alert(Alert, Version, StateName, try %% Try to tell the other side {BinMsg, _} = ssl_alert:encode(Alert, Version, ConnectionStates), - Transport:send(Socket, BinMsg), - workaround_transport_delivery_problems(Socket, Transport) + Transport:send(Socket, BinMsg) catch _:_ -> %% Can crash if we are in a uninitialized state ignore end, @@ -977,21 +976,57 @@ invalidate_session(client, Host, Port, Session) -> invalidate_session(server, _, Port, Session) -> ssl_manager:invalidate_session(Port, Session). -workaround_transport_delivery_problems(Socket, gen_tcp = Transport) -> +%% User downgrades connection +%% When downgrading an TLS connection to a transport connection +%% we must recive the close message before releasing the +%% transport socket. +close({close, {Pid, Timeout}}, Socket, Transport, ConnectionStates, Check) when is_pid(Pid) -> + ssl_socket:setopts(Transport, Socket, [{active, false}, {packet, ssl_tls}]), + case Transport:recv(Socket, 0, Timeout) of + {ok, {ssl_tls, Socket, ?ALERT, Version, Fragment}} -> + case tls_record:decode_cipher_text(#ssl_tls{type = ?ALERT, + version = Version, + fragment = Fragment + }, ConnectionStates, Check) of + {#ssl_tls{fragment = Plain}, _} -> + [Alert| _] = decode_alerts(Plain), + downgrade(Alert, Transport, Socket, Pid) + end; + {error, timeout} -> + {error, timeout}; + _ -> + {error, no_tls_close} + end; +%% User closes or recursive call! +close({close, Timeout}, Socket, Transport = gen_tcp, _,_) -> + ssl_socket:setopts(Transport, Socket, [{active, false}]), + Transport:shutdown(Socket, write), + _ = Transport:recv(Socket, 0, Timeout), + ok; +%% Peer closed socket +close({shutdown, transport_closed}, Socket, Transport = gen_tcp, ConnectionStates, Check) -> + close({close, 0}, Socket, Transport, ConnectionStates, Check); +%% We generate fatal alert +close({shutdown, own_alert}, Socket, Transport = gen_tcp, ConnectionStates, Check) -> %% Standard trick to try to make sure all %% data sent to the tcp port is really delivered to the %% peer application before tcp port is closed so that the peer will %% get the correct TLS alert message and not only a transport close. - ssl_socket:setopts(Transport, Socket, [{active, false}]), - Transport:shutdown(Socket, write), - %% Will return when other side has closed or after 30 s + %% Will return when other side has closed or after timout millisec %% e.g. we do not want to hang if something goes wrong %% with the network but we want to maximise the odds that %% peer application gets all data sent on the tcp connection. - Transport:recv(Socket, 0, 30000); -workaround_transport_delivery_problems(Socket, Transport) -> + close({close, ?DEFAULT_TIMEOUT}, Socket, Transport, ConnectionStates, Check); +%% Other +close(_, Socket, Transport, _,_) -> Transport:close(Socket). - +downgrade(#alert{description = ?CLOSE_NOTIFY}, Transport, Socket, Pid) -> + ssl_socket:setopts(Transport, Socket, [{active, false}, {packet, 0}, {mode, binary}]), + Transport:controlling_process(Socket, Pid), + {ok, Socket}; +downgrade(_, _,_,_) -> + {error, no_tls_close}. + convert_state(#state{ssl_options = Options} = State, up, "5.3.5", "5.3.6") -> State#state{ssl_options = convert_options_partial_chain(Options, up)}; convert_state(#state{ssl_options = Options} = State, down, "5.3.6", "5.3.5") -> diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl index 85152fda22..3a9f21ea99 100644 --- a/lib/ssl/test/ssl_ECC_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_SUITE.erl @@ -46,7 +46,7 @@ groups() -> {'tlsv1', [], all_versions_groups()}, {'erlang_server', [], key_cert_combinations()}, {'erlang_client', [], key_cert_combinations()}, - {'erlang', [], key_cert_combinations()} + {'erlang', [], key_cert_combinations() ++ misc()} ]. all_versions_groups ()-> @@ -65,6 +65,9 @@ key_cert_combinations() -> client_rsa_server_ecdsa ]. +misc()-> + [client_ecdsa_server_ecdsa_with_raw_key]. + %%-------------------------------------------------------------------- init_per_suite(Config0) -> end_per_suite(Config0), @@ -189,6 +192,32 @@ client_rsa_server_ecdsa(Config) when is_list(Config) -> SOpts = ?config(server_ecdsa_verify_opts, Config), basic_test(COpts, SOpts, Config). +client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) -> + COpts = ?config(client_ecdsa_opts, Config), + SOpts = ?config(server_ecdsa_verify_opts, Config), + ServerCert = proplists:get_value(certfile, SOpts), + ServerKeyFile = proplists:get_value(keyfile, SOpts), + {ok, PemBin} = file:read_file(ServerKeyFile), + PemEntries = public_key:pem_decode(PemBin), + {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries), + ServerKey = {'ECPrivateKey', Key}, + ServerCA = proplists:get_value(cacertfile, SOpts), + ClientCert = proplists:get_value(certfile, COpts), + ClientKey = proplists:get_value(keyfile, COpts), + ClientCA = proplists:get_value(cacertfile, COpts), + SType = ?config(server_type, Config), + CType = ?config(client_type, Config), + {Server, Port} = start_server_with_raw_key(SType, + ClientCA, ServerCA, + ServerCert, + ServerKey, + Config), + Client = start_client(CType, Port, ServerCA, ClientCA, + ClientCert, + ClientKey, Config), + check_result(Server, SType, Client, CType), + close(Server, Client). + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- @@ -247,9 +276,7 @@ start_server(openssl, CA, OwnCa, Cert, Key, Config) -> OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), true = port_command(OpenSslPort, "Hello world"), {OpenSslPort, Port}; - start_server(erlang, CA, _, Cert, Key, Config) -> - {_, ServerNode, _} = ssl_test_lib:run_where(Config), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, @@ -260,6 +287,17 @@ start_server(erlang, CA, _, Cert, Key, Config) -> [{verify, verify_peer}, {cacertfile, CA}, {certfile, Cert}, {keyfile, Key}]}]), {Server, ssl_test_lib:inet_port(Server)}. +start_server_with_raw_key(erlang, CA, _, Cert, Key, Config) -> + {_, ServerNode, _} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, + []}}, + {options, + [{verify, verify_peer}, {cacertfile, CA}, + {certfile, Cert}, {key, Key}]}]), + {Server, ssl_test_lib:inet_port(Server)}. check_result(Server, erlang, Client, erlang) -> ssl_test_lib:check_result(Server, ok, Client, ok); diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 378f42c2ee..6f6107de2c 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -129,6 +129,8 @@ api_tests() -> controlling_process, upgrade, upgrade_with_timeout, + downgrade, + close_with_timeout, shutdown, shutdown_write, shutdown_both, @@ -320,7 +322,8 @@ init_per_testcase(rizzo, Config) -> Config; init_per_testcase(TestCase, Config) when TestCase == ssl_accept_timeout; - TestCase == client_closes_socket -> + TestCase == client_closes_socket; + TestCase == downgrade -> ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), ct:timetrap({seconds, 15}), Config; @@ -1408,6 +1411,53 @@ upgrade_with_timeout(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- +downgrade() -> + [{doc,"Test that you can downgarde an ssl connection to an tcp connection"}]. +downgrade(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, tls_downgrade, []}}, + {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, tls_downgrade, []}}, + {options, [{active, false} |ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +close_with_timeout() -> + [{doc,"Test normal (not downgrade) ssl:close/2"}]. +close_with_timeout(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, tls_close, []}}, + {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, tls_close, []}}, + {options, [{active, false} |ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok). + + +%%-------------------------------------------------------------------- tcp_connect() -> [{doc,"Test what happens when a tcp tries to connect, i,e. a bad (ssl) packet is sent first"}]. @@ -3931,6 +3981,33 @@ connect_dist_c(S) -> {ok, Test} = ssl:recv(S, 0, 10000), ok. +tls_downgrade(Socket) -> + ok = ssl_test_lib:send_recv_result(Socket), + case ssl:close(Socket, {self(), 10000}) of + {ok, TCPSocket} -> + inet:setopts(TCPSocket, [{active, true}]), + gen_tcp:send(TCPSocket, "Downgraded"), + receive + {tcp, TCPSocket, <<"Downgraded">>} -> + ok; + {tcp_closed, TCPSocket} -> + ct:pal("Peer timed out, downgrade aborted"), + ok; + Other -> + {error, Other} + end; + {error, timeout} -> + ct:pal("Timed out, downgrade aborted"), + ok; + Fail -> + {error, Fail} + end. + +tls_close(Socket) -> + ok = ssl_test_lib:send_recv_result(Socket), + ok = ssl:close(Socket, 5000). + + %% First two clauses handles 1/n-1 splitting countermeasure Rizzo/Duong-Beast treashold(N, {3,0}) -> (N div 2) + 1; diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl index 8ddc5db4b2..924898f6fa 100644 --- a/lib/ssl/test/ssl_session_cache_SUITE.erl +++ b/lib/ssl/test/ssl_session_cache_SUITE.erl @@ -45,7 +45,8 @@ all() -> [session_cleanup, session_cache_process_list, - session_cache_process_mnesia]. + session_cache_process_mnesia, + client_unique_session]. groups() -> []. @@ -90,8 +91,8 @@ init_per_testcase(session_cleanup, Config) -> ct:timetrap({seconds, 20}), Config; -init_per_testcase(_TestCase, Config) -> - ct:timetrap({seconds, 5}), +init_per_testcase(client_unique_session, Config) -> + ct:timetrap({seconds, 20}), Config. init_customized_session_cache(Type, Config) -> @@ -131,10 +132,40 @@ end_per_testcase(_, Config) -> %%-------------------------------------------------------------------- %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- +client_unique_session() -> + [{doc, "Test session table does not grow when client " + "sets up many connections"}]. +client_unique_session(Config) when is_list(Config) -> + process_flag(trap_exit, true), + 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, {ssl_test_lib, no_result, []}}, + {tcp_options, [{active, false}]}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + LastClient = clients_start(Server, + ClientNode, Hostname, Port, ClientOpts, 20), + receive + {LastClient, {ok, _}} -> + ok + end, + {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), + [_, _,_, _, Prop] = StatusInfo, + State = ssl_test_lib:state(Prop), + ClientCache = element(2, State), + 1 = ets:info(ClientCache, size), + + ssl_test_lib:close(Server, 500), + ssl_test_lib:close(LastClient). + session_cleanup() -> [{doc, "Test that sessions are cleand up eventually, so that the session table " "does not grow and grow ..."}]. -session_cleanup(Config)when is_list(Config) -> +session_cleanup(Config) when is_list(Config) -> process_flag(trap_exit, true), ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -148,9 +179,9 @@ session_cleanup(Config)when is_list(Config) -> Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, - {port, Port}, {host, Hostname}, + {port, Port}, {host, Hostname}, {mfa, {ssl_test_lib, no_result, []}}, - {from, self()}, {options, ClientOpts}]), + {from, self()}, {options, ClientOpts}]), SessionInfo = receive {Server, Info} -> @@ -325,8 +356,8 @@ select_session(Cache, PartialKey) -> mnesia -> Sel = fun() -> mnesia:select(Cache, - [{{Cache,{PartialKey,'$1'}, '$2'}, - [],['$$']}]) + [{{Cache,{PartialKey,'_'}, '$1'}, + [],['$1']}]) end, {atomic, Res} = mnesia:transaction(Sel), Res @@ -354,8 +385,8 @@ session_loop(Sess) -> Pid ! {self(), Res}, session_loop(Sess); {Pid,select_session,PKey} -> - Sel = fun({{PKey0, Id},Session}, Acc) when PKey == PKey0 -> - [[Id, Session]|Acc]; + Sel = fun({{PKey0, _Id},Session}, Acc) when PKey == PKey0 -> + [Session | Acc]; (_,Acc) -> Acc end, @@ -370,3 +401,23 @@ session_loop(Sess) -> session_cache_process(_Type,Config) when is_list(Config) -> ssl_basic_SUITE:reuse_session(Config). + + +clients_start(_Server, ClientNode, Hostname, Port, ClientOpts, 0) -> + %% Make sure session is registered + ct:sleep(?SLEEP * 2), + ssl_test_lib:start_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {?MODULE, connection_info_result, []}}, + {from, self()}, {options, ClientOpts}]); +clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N) -> + spawn_link(ssl_test_lib, start_client, + [[{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {ssl_test_lib, no_result, []}}, + {from, self()}, {options, ClientOpts}]]), + Server ! listen, + clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N-1). + +connection_info_result(Socket) -> + ssl:connection_information(Socket, [protocol, cipher_suite]). diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 8317148aa5..f25f6f9425 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -226,6 +226,17 @@ run_client(Opts) -> ct:log("~p:~p~nClient faild several times: connection failed: ~p ~n", [?MODULE,?LINE, Reason]), Pid ! {self(), {error, Reason}} end; + {error, econnreset = Reason} -> + case get(retries) of + N when N < 5 -> + ct:log("~p:~p~neconnreset retries=~p sleep ~p",[?MODULE,?LINE, N,?SLEEP]), + put(retries, N+1), + ct:sleep(?SLEEP), + run_client(Opts); + _ -> + ct:log("~p:~p~nClient faild several times: connection failed: ~p ~n", [?MODULE,?LINE, Reason]), + Pid ! {self(), {error, Reason}} + end; {error, Reason} -> ct:log("~p:~p~nClient: connection failed: ~p ~n", [?MODULE,?LINE, Reason]), Pid ! {connect_failed, Reason}; @@ -241,7 +252,21 @@ close(Pid) -> receive {'DOWN', Monitor, process, Pid, Reason} -> erlang:demonitor(Monitor), - ct:log("~p:~p~nPid: ~p down due to:~p ~n", [?MODULE,?LINE, Pid, Reason]) + ct:log("~p:~p~nPid: ~p down due to:~p ~n", [?MODULE,?LINE, Pid, Reason]) + + end. + +close(Pid, Timeout) -> + ct:log("~p:~p~n Close ~p ~n", [?MODULE,?LINE, Pid]), + Monitor = erlang:monitor(process, Pid), + Pid ! close, + receive + {'DOWN', Monitor, process, Pid, Reason} -> + erlang:demonitor(Monitor), + ct:log("~p:~p~nPid: ~p down due to:~p ~n", [?MODULE,?LINE, Pid, Reason]) + after + Timeout -> + exit(Pid, kill) end. check_result(Server, ServerMsg, Client, ClientMsg) -> @@ -360,7 +385,7 @@ cert_options(Config) -> SNIServerAKeyFile = filename:join([?config(priv_dir, Config), "a.server", "key.pem"]), SNIServerBCertFile = filename:join([?config(priv_dir, Config), "b.server", "cert.pem"]), SNIServerBKeyFile = filename:join([?config(priv_dir, Config), "b.server", "key.pem"]), - [{client_opts, [{ssl_imp, new},{reuseaddr, true}]}, + [{client_opts, []}, {client_verification_opts, [{cacertfile, ClientCaCertFile}, {certfile, ClientCertFile}, {keyfile, ClientKeyFile}, diff --git a/lib/ssl/test/ssl_upgrade_SUITE.erl b/lib/ssl/test/ssl_upgrade_SUITE.erl index 17b0240fe8..f5f4b25b23 100644 --- a/lib/ssl/test/ssl_upgrade_SUITE.erl +++ b/lib/ssl/test/ssl_upgrade_SUITE.erl @@ -28,7 +28,8 @@ config, server, client, - soft + soft, + result_proxy }). all() -> @@ -39,20 +40,19 @@ all() -> init_per_suite(Config0) -> catch crypto:stop(), - try {crypto:start(), erlang:system_info({wordsize, internal}) == erlang:system_info({wordsize, external})} of - {ok, true} -> - case ct_release_test:init(Config0) of - {skip, Reason} -> - {skip, Reason}; - Config -> - {ok, _} = make_certs:all(?config(data_dir, Config), - ?config(priv_dir, Config)), - ssl_test_lib:cert_options(Config) - end; - {ok, false} -> - {skip, "Test server will not handle halfwordemulator correctly. Skip as halfwordemulator is deprecated"} + try crypto:start() of + ok -> + case ct_release_test:init(Config0) of + {skip, Reason} -> + {skip, Reason}; + Config -> + Result = + {ok, _} = make_certs:all(?config(data_dir, Config), + ?config(priv_dir, Config)), + ssl_test_lib:cert_options(Config) + end catch _:_ -> - {skip, "Crypto did not start"} + {skip, "Crypto did not start"} end. end_per_suite(Config) -> @@ -77,45 +77,58 @@ upgrade_init(CTData, #state{config = Config} = State) -> {ok, {_, _, Up, _Down}} = ct_release_test:get_appup(CTData, ssl), ct:pal("Up: ~p", [Up]), Soft = is_soft(Up), %% It is symmetrical, if upgrade is soft so is downgrade + Pid = spawn(?MODULE, result_proxy_init, [[]]), case Soft of true -> - {Server, Client} = soft_start_connection(Config), + {Server, Client} = soft_start_connection(Config, Pid), State#state{server = Server, client = Client, - soft = Soft}; + soft = Soft, + result_proxy = Pid}; false -> - State#state{soft = Soft} + State#state{soft = Soft, result_proxy = Pid} end. -upgrade_upgraded(_, #state{soft = false, config = Config} = State) -> - {Server, Client} = restart_start_connection(Config), - ssl_test_lib:check_result(Server, ok, Client, ok), +upgrade_upgraded(_, #state{soft = false, config = Config, result_proxy = Pid} = State) -> + ct:pal("Restart upgrade ~n", []), + {Server, Client} = restart_start_connection(Config, Pid), + Result = check_result(Pid, Server, Client), ssl_test_lib:close(Server), ssl_test_lib:close(Client), + ok = Result, State; upgrade_upgraded(_, #state{server = Server0, client = Client0, - config = Config, soft = true} = State) -> + config = Config, soft = true, + result_proxy = Pid} = State) -> + ct:pal("Soft upgrade: ~n", []), Server0 ! changed_version, Client0 ! changed_version, - ssl_test_lib:check_result(Server0, ok, Client0, ok), + Result = check_result(Pid, Server0, Client0), ssl_test_lib:close(Server0), ssl_test_lib:close(Client0), - {Server, Client} = soft_start_connection(Config), + ok = Result, + {Server, Client} = soft_start_connection(Config, Pid), State#state{server = Server, client = Client}. -upgrade_downgraded(_, #state{soft = false, config = Config} = State) -> - {Server, Client} = restart_start_connection(Config), - ssl_test_lib:check_result(Server, ok, Client, ok), +upgrade_downgraded(_, #state{soft = false, config = Config, result_proxy = Pid} = State) -> + ct:pal("Restart downgrade: ~n", []), + {Server, Client} = restart_start_connection(Config, Pid), + Result = check_result(Pid, Server, Client), ssl_test_lib:close(Server), ssl_test_lib:close(Client), + Pid ! stop, + ok = Result, State; -upgrade_downgraded(_, #state{server = Server, client = Client, soft = true} = State) -> +upgrade_downgraded(_, #state{server = Server, client = Client, soft = true, result_proxy = Pid} = State) -> + ct:pal("Soft downgrade: ~n", []), Server ! changed_version, Client ! changed_version, - ssl_test_lib:check_result(Server, ok, Client, ok), + Result = check_result(Pid, Server, Client), + Pid ! stop, ssl_test_lib:close(Server), ssl_test_lib:close(Client), + ok = Result, State. use_connection(Socket) -> @@ -125,36 +138,35 @@ use_connection(Socket) -> ssl_test_lib:send_recv_result_active(Socket) end. -soft_start_connection(Config) -> +soft_start_connection(Config, ResulProxy) -> ClientOpts = ?config(client_verification_opts, 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, use_connection, []}}, - {options, ServerOpts}]), + Server = start_server([{node, ServerNode}, {port, 0}, + {from, ResulProxy}, + {mfa, {?MODULE, use_connection, []}}, + {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, use_connection, []}}, - {options, ClientOpts}]), + Port = inet_port(ResulProxy, Server), + Client = start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, ResulProxy}, + {mfa, {?MODULE, use_connection, []}}, + {options, ClientOpts}]), {Server, Client}. -restart_start_connection(Config) -> +restart_start_connection(Config, ResulProxy) -> ClientOpts = ?config(client_verification_opts, 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()}, + Server = start_server([{node, ServerNode}, {port, 0}, + {from, ResulProxy}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, ServerOpts}]), - - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Port = inet_port(ResulProxy, Server), + Client = start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, ResulProxy}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, ClientOpts}]), {Server, Client}. @@ -163,3 +175,103 @@ is_soft([{restart_application, ssl}]) -> false; is_soft(_) -> true. + +result_proxy_init(Args) -> + result_proxy_loop(Args). + +result_proxy_loop(Args) -> + receive + {Pid, {check_result, Server, Client}} -> + Result = do_check_result(Server, ok, Client, ok), + Pid ! {self(), Result}, + result_proxy_loop(Args); + {Pid, port, Server} -> + Port = recv_port(Server), + Pid ! Port, + result_proxy_loop(Args); + {Pid, listen} -> + recv_listen(), + Pid ! ok, + result_proxy_loop(Args); + {Pid, connected} -> + Connected = recv_connected(), + Pid ! Connected, + result_proxy_loop(Args) + end. + +check_result(Pid, Server, Client) -> + Pid ! {self(), {check_result, Server, Client}}, + receive + {Pid, Result} -> + Result + end. + +do_check_result(Server, ServerMsg, Client, ClientMsg) -> + receive + {Server, ServerMsg} -> + do_check_result(Client, ClientMsg); + + {Client, ClientMsg} -> + do_check_result(Server, ServerMsg); + Unexpected -> + {{expected, {Client, ClientMsg}}, + {expected, {Server, ServerMsg}}, {got, Unexpected}} + end. + +do_check_result(Pid, Msg) -> + receive + {Pid, Msg} -> + ok; + Unexpected -> + {{expected, {Pid, Msg}}, + {got, Unexpected}} + end. + +inet_port(Pid, Server) -> + Pid ! {self(), port, Server}, + receive + {port, Port} -> + Port + end. + +recv_port(Server) -> + receive + {Server, {port, Port}} -> + {port, Port} + end. + +recv_connected() -> + receive + {connected, _Socket} -> + ok; + {connect_failed, Reason} -> + {connect_failed, Reason} + end. + + +start_server(Args) -> + Pid = proplists:get_value(from, Args), + Result = spawn_link(ssl_test_lib, run_server, [Args]), + Pid ! {self(), listen}, + receive + ok -> + ok + end, + Result. + +start_client(Args) -> + Pid = proplists:get_value(from, Args), + Result = spawn_link(ssl_test_lib, run_client_init, [lists:delete(return_socket, Args)]), + Pid ! {self(), connected}, + receive + ok -> + Result; + Reason -> + exit(Reason) + end. + +recv_listen()-> + receive + {listen, up} -> + ok + end. diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 171147adf2..4587c448f6 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 7.0 +SSL_VSN = 7.1 diff --git a/lib/stdlib/doc/src/array.xml b/lib/stdlib/doc/src/array.xml index 28b4435938..0f33e2621c 100644 --- a/lib/stdlib/doc/src/array.xml +++ b/lib/stdlib/doc/src/array.xml @@ -164,7 +164,7 @@ the default value cannot be confused with the values of set entries.</p> </fsummary> <desc><marker id="from_list-1"/> -<p>Equivalent to <seealso marker="#from_list-2">from_list(<anno>List</anno>, undefined)</seealso>.</p> +<p>Equivalent to <seealso marker="#from_list-2">from_list(<c><anno>List</anno></c>, undefined)</seealso>.</p> </desc></func> <func> <name name="from_list" arity="2"/> @@ -184,7 +184,7 @@ the default value cannot be confused with the values of set entries.</p> </fsummary> <desc><marker id="from_orddict-1"/> -<p>Equivalent to <seealso marker="#from_orddict-2">from_orddict(<anno>Orddict</anno>, undefined)</seealso>.</p> +<p>Equivalent to <seealso marker="#from_orddict-2">from_orddict(<c><anno>Orddict</anno></c>, undefined)</seealso>.</p> </desc></func> <func> <name name="from_orddict" arity="2"/> diff --git a/lib/stdlib/doc/src/assert_hrl.xml b/lib/stdlib/doc/src/assert_hrl.xml index b85be514d8..ef4f928e57 100644 --- a/lib/stdlib/doc/src/assert_hrl.xml +++ b/lib/stdlib/doc/src/assert_hrl.xml @@ -77,9 +77,6 @@ erlc -DNOASSERT=true *.erl</code> </description> <section> - </section> - - <section> <title>Macros</title> <taglist> <tag><c>assert(BoolExpr)</c></tag> @@ -94,12 +91,12 @@ erlc -DNOASSERT=true *.erl</code> <tag><c>assertMatch(GuardedPattern, Expr)</c></tag> <item><p>Tests that <c>Expr</c> completes normally yielding a value - that matches <c>GuardedPattern</c>. For example: + that matches <c>GuardedPattern</c>. For example:</p> <code type="none"> - ?assertMatch({bork, _}, f())</code></p> - <p>Note that a guard <c>when ...</c> can be included: + ?assertMatch({bork, _}, f())</code> + <p>Note that a guard <c>when ...</c> can be included:</p> <code type="none"> - ?assertMatch({bork, X} when X > 0, f())</code></p> + ?assertMatch({bork, X} when X > 0, f())</code> </item> <tag><c>assertNotMatch(GuardedPattern, Expr)</c></tag> diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml index c556180b8b..7c89c8b43e 100644 --- a/lib/stdlib/doc/src/beam_lib.xml +++ b/lib/stdlib/doc/src/beam_lib.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2000</year><year>2013</year> + <year>2000</year><year>2015</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -71,6 +71,7 @@ using <seealso marker="#strip/1">strip/1</seealso>, <seealso marker="#strip_files/1">strip_files/1</seealso> and/or <seealso marker="#strip_release/1">strip_release/1</seealso>.</p> + </section> <section> <title>Reconstructing source code</title> <p>Here is an example of how to reconstruct source code from @@ -152,7 +153,6 @@ keys.</p> </note> </section> - </section> <datatypes> <datatype> @@ -224,6 +224,13 @@ <funcs> <func> + <name name="all_chunks" arity="1"/> + <fsummary>Read all chunks from a BEAM file or binary</fsummary> + <desc> + <p>Reads chunk data for all chunks.</p> + </desc> + </func> + <func> <name name="chunks" arity="2"/> <fsummary>Read selected chunks from a BEAM file or binary</fsummary> <desc> @@ -251,6 +258,13 @@ </desc> </func> <func> + <name name="build_module" arity="1"/> + <fsummary>Creates a BEAM module from a list of chunks</fsummary> + <desc> + <p>Builds a BEAM module (as a binary) from a list of chunks.</p> + </desc> + </func> + <func> <name name="version" arity="1"/> <fsummary>Read the BEAM file's module version</fsummary> <desc> diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml index 063f3048e0..2682198fe5 100644 --- a/lib/stdlib/doc/src/binary.xml +++ b/lib/stdlib/doc/src/binary.xml @@ -299,8 +299,8 @@ </func> <func> <name name="match" arity="3"/> - <type name="part"/> <fsummary>Searches for the first match of a pattern in a binary</fsummary> + <type name="part"/> <desc> <p>Searches for the first occurrence of <c><anno>Pattern</anno></c> in <c><anno>Subject</anno></c> and @@ -353,8 +353,8 @@ </func> <func> <name name="matches" arity="3"/> - <type name="part"/> <fsummary>Searches for all matches of a pattern in a binary</fsummary> + <type name="part"/> <desc> <p>Works like <c>match/2</c>, but the <c><anno>Subject</anno></c> is searched until diff --git a/lib/stdlib/doc/src/c.xml b/lib/stdlib/doc/src/c.xml index a0f18bd899..e5238fa7db 100644 --- a/lib/stdlib/doc/src/c.xml +++ b/lib/stdlib/doc/src/c.xml @@ -121,12 +121,12 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w </func> <func> <name>lc(Files) -> ok</name> + <fsummary>Compile a list of files</fsummary> <type> <v>Files = [File]</v> <v>File = <seealso marker="file#type-filename">file:filename() </seealso></v> </type> - <fsummary>Compile a list of files</fsummary> <desc> <p>Compiles a list of files by calling <c>compile:file(File, [report_errors, report_warnings])</c> for each <c>File</c> in <c>Files</c>.</p> diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml index a8d933dc83..853184dc0f 100644 --- a/lib/stdlib/doc/src/calendar.xml +++ b/lib/stdlib/doc/src/calendar.xml @@ -130,11 +130,11 @@ <func> <name name="date_to_gregorian_days" arity="1"/> <name name="date_to_gregorian_days" arity="3"/> + <fsummary>Compute the number of days from year 0 up to the given date</fsummary> <type variable="Date" name_i="1"/> <type variable="Year"/> <type variable="Month"/> <type variable="Day"/> - <fsummary>Compute the number of days from year 0 up to the given date</fsummary> <desc> <p>This function computes the number of gregorian days starting with year 0 and ending at the given date.</p> @@ -347,11 +347,11 @@ <func> <name name="valid_date" arity="1"/> <name name="valid_date" arity="3"/> + <fsummary>Check if a date is valid</fsummary> <type variable="Date" name_i="1"/> <type variable="Year"/> <type variable="Month"/> <type variable="Day"/> - <fsummary>Check if a date is valid</fsummary> <desc> <p>This function checks if a date is a valid.</p> </desc> diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml index 14237b6f90..a0d3f95b6a 100644 --- a/lib/stdlib/doc/src/dets.xml +++ b/lib/stdlib/doc/src/dets.xml @@ -316,20 +316,20 @@ bytes.</p> </item> <item> - <p><c>{filename, <seealso marker="file#type-name">file:name()</seealso>}</c>, + <p><c>{filename, </c><seealso marker="file#type-name">file:name()</seealso><c>}</c>, the name of the file where objects are stored.</p> </item> <item> - <p><c>{keypos, <seealso marker="#type-keypos">keypos()</seealso>} - </c>, the position of the key.</p> + <p><c>{keypos, </c><seealso marker="#type-keypos">keypos()</seealso> + <c>}</c>, the position of the key.</p> </item> <item> <p><c>{size, integer() >= 0}</c>, the number of objects stored in the table.</p> </item> <item> - <p><c>{type, <seealso marker="#type-type">type()</seealso>}</c>, - the type of the table.</p> + <p><c>{type, </c><seealso marker="#type-type">type()</seealso> + <c>}</c>, the type of the table.</p> </item> </list> </desc> @@ -345,12 +345,12 @@ allowed:</p> <list type="bulleted"> <item> - <p><c>{access, <seealso marker="#type-access">access()</seealso>} - </c>, the access mode.</p> + <p><c>{access, </c><seealso marker="#type-access">access()</seealso> + <c>}</c>, the access mode.</p> </item> <item> - <p><c>{auto_save, <seealso marker="#type-auto_save"> - auto_save()</seealso>}</c>, the auto save interval.</p> + <p><c>{auto_save, </c><seealso marker="#type-auto_save"> + auto_save()</seealso><c>}</c>, the auto save interval.</p> </item> <item> <p><c>{bchunk_format, binary()}</c>, an opaque binary @@ -730,16 +730,16 @@ ok tuples where the following values are allowed:</p> <list type="bulleted"> <item> - <p><c>{access, <seealso marker="#type-access"> - access()</seealso>}</c>. It is possible to open + <p><c>{access, </c><seealso marker="#type-access"> + access()</seealso><c>}</c>. It is possible to open existing tables in read-only mode. A table which is opened in read-only mode is not subjected to the automatic file reparation algorithm if it is later opened after a crash. The default value is <c>read_write</c>.</p> </item> <item> - <p><c>{auto_save, <seealso marker="#type-auto_save"> - auto_save()</seealso>}</c>, the auto save + <p><c>{auto_save, </c><seealso marker="#type-auto_save"> + auto_save()</seealso><c>}</c>, the auto save interval. If the interval is an integer <c>Time</c>, the table is flushed to disk whenever it is not accessed for <c>Time</c> milliseconds. A table that has been flushed @@ -749,18 +749,18 @@ ok is 180000 (3 minutes).</p> </item> <item> - <p><c>{estimated_no_objects, <seealso marker="#type-no_slots"> - no_slots()</seealso>}</c>. Equivalent to the + <p><c>{estimated_no_objects, </c><seealso marker="#type-no_slots"> + no_slots()</seealso><c>}</c>. Equivalent to the <c>min_no_slots</c> option.</p> </item> <item> - <p><c>{file, <seealso marker="file#type-name"> - file:name()</seealso>}</c>, the name of the file to be + <p><c>{file, </c><seealso marker="file#type-name"> + file:name()</seealso><c>}</c>, the name of the file to be opened. The default value is the name of the table.</p> </item> <item> - <p><c>{max_no_slots, <seealso marker="#type-no_slots"> - no_slots()</seealso>}</c>, the maximum number + <p><c>{max_no_slots, </c><seealso marker="#type-no_slots"> + no_slots()</seealso><c>}</c>, the maximum number of slots that will be used. The default value as well as the maximal value is 32 M. Note that a higher value may increase the fragmentation of the table, and conversely, @@ -769,16 +769,16 @@ ok 9 tables.</p> </item> <item> - <p><c>{min_no_slots, <seealso marker="#type-no_slots"> - no_slots()</seealso>}</c>. Application + <p><c>{min_no_slots, </c><seealso marker="#type-no_slots"> + no_slots()</seealso><c>}</c>. Application performance can be enhanced with this flag by specifying, when the table is created, the estimated number of different keys that will be stored in the table. The default value as well as the minimum value is 256.</p> </item> <item> - <p><c>{keypos, <seealso marker="#type-keypos"> - keypos()</seealso>}</c>, the position of the + <p><c>{keypos, </c><seealso marker="#type-keypos"> + keypos()</seealso><c>}</c>, the position of the element of each object to be used as key. The default value is 1. The ability to explicitly state the key position is most convenient when we want to store Erlang @@ -815,12 +815,12 @@ ok already open.</p> </item> <item> - <p><c>{type, <seealso marker="#type-type">type()</seealso>}</c>, + <p><c>{type, </c><seealso marker="#type-type">type()</seealso><c>}</c>, the type of the table. The default value is <c>set</c>.</p> </item> <item> - <p><c>{version, <seealso marker="#type-version"> - version()</seealso>}</c>, the version of the format + <p><c>{version, </c><seealso marker="#type-version"> + version()</seealso><c>}</c>, the version of the format used for the table. The default value is <c>9</c>. Tables on the format used before OTP R8 can be created by giving the value <c>8</c>. A version 8 table can be converted to @@ -1036,8 +1036,8 @@ ok specification that matches all objects.</p> </item> <item> - <p><c>{select, <seealso marker="#type-match_spec"> - match_spec()}</seealso></c>. As for <c>select</c> + <p><c>{select, </c><seealso marker="#type-match_spec"> + match_spec()</seealso><c>}</c>. As for <c>select</c> the table is traversed by calling <c>dets:select/3</c> and <c>dets:select/1</c>. The difference is that the match specification is explicitly given. This is how to diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml index 49dc68e103..291be6c08b 100644 --- a/lib/stdlib/doc/src/digraph.xml +++ b/lib/stdlib/doc/src/digraph.xml @@ -103,13 +103,15 @@ <desc><p>A digraph as returned by <c>new/0,1</c>.</p></desc> </datatype> <datatype> - <name><marker id="type-edge">edge()</marker></name> + <name>edge()</name> + <desc><p><marker id="type-edge"/></p></desc> </datatype> <datatype> <name name="label"/> </datatype> <datatype> - <name><marker id="type-vertex">vertex()</marker></name> + <name>vertex()</name> + <desc><p><marker id="type-vertex"/></p></desc> </datatype> </datatypes> <funcs> diff --git a/lib/stdlib/doc/src/digraph_utils.xml b/lib/stdlib/doc/src/digraph_utils.xml index 6a4db2e963..639069543c 100644 --- a/lib/stdlib/doc/src/digraph_utils.xml +++ b/lib/stdlib/doc/src/digraph_utils.xml @@ -122,8 +122,9 @@ <datatypes> <datatype> - <name><marker id="type-digraph">digraph()</marker></name> - <desc><p>A digraph as returned by <c>digraph:new/0,1</c>.</p></desc> + <name>digraph()</name> + <desc><p><marker id="type-digraph"/> + A digraph as returned by <c>digraph:new/0,1</c>.</p></desc> </datatype> </datatypes> <funcs> diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml index fe2944bbf7..8c901f57ec 100644 --- a/lib/stdlib/doc/src/epp.xml +++ b/lib/stdlib/doc/src/epp.xml @@ -39,7 +39,7 @@ by <c>compile</c> to preprocess macros and include files before the actual parsing takes place.</p> <p>The Erlang source file <marker - id="encoding"><em>encoding</em></marker> is selected by a + id="encoding"/><em>encoding</em> is selected by a comment in one of the first two lines of the source file. The first string that matches the regular expression <c>coding\s*[:=]\s*([-a-zA-Z0-9])+</c> selects the encoding. If diff --git a/lib/stdlib/doc/src/erl_anno.xml b/lib/stdlib/doc/src/erl_anno.xml index be0ffe6f4d..ddc8b8c765 100644 --- a/lib/stdlib/doc/src/erl_anno.xml +++ b/lib/stdlib/doc/src/erl_anno.xml @@ -44,7 +44,7 @@ <p>This module implements an abstract type that is used by the Erlang Compiler and its helper modules for holding data such as column, line number, and text. The data type is a collection of - <marker id="annotations"><em>annotations</em></marker> as + <marker id="annotations"/><em>annotations</em> as described in the following.</p> <p>The Erlang Token Scanner returns tokens with a subset of the following annotations, depending on the options:</p> @@ -102,8 +102,8 @@ <datatypes> <datatype> - <name><marker id="type-anno">anno()</marker></name> - <desc><p>A collection of annotations.</p> + <name>anno()</name> + <desc><p><marker id="type-anno"/>A collection of annotations.</p> </desc> </datatype> <datatype> @@ -133,8 +133,8 @@ <funcs> <func> <name name="column" arity="1"/> - <type name="column"></type> <fsummary>Return the column</fsummary> + <type name="column"></type> <desc> <p>Returns the column of the annotations <anno>Anno</anno>. </p> @@ -142,8 +142,8 @@ </func> <func> <name name="end_location" arity="1"/> - <type name="location"></type> <fsummary>Return the end location of the text</fsummary> + <type name="location"></type> <desc> <p>Returns the end location of the text of the annotations <anno>Anno</anno>. If there is no text, @@ -153,8 +153,8 @@ </func> <func> <name name="file" arity="1"/> - <type name="filename"></type> <fsummary>Return the filename</fsummary> + <type name="filename"></type> <desc> <p>Returns the filename of the annotations <anno>Anno</anno>. If there is no filename, <c>undefined</c> is returned. @@ -180,8 +180,8 @@ </func> <func> <name name="generated" arity="1"/> - <type name="generated"></type> <fsummary>Return the generated Boolean</fsummary> + <type name="generated"></type> <desc> <p>Returns <c>true</c> if the annotations <anno>Anno</anno> has been marked as generated. The default is to return @@ -199,8 +199,8 @@ </func> <func> <name name="line" arity="1"/> - <type name="line"></type> <fsummary>Return the line</fsummary> + <type name="line"></type> <desc> <p>Returns the line of the annotations <anno>Anno</anno>. </p> @@ -208,8 +208,8 @@ </func> <func> <name name="location" arity="1"/> - <type name="location"></type> <fsummary>Return the location</fsummary> + <type name="location"></type> <desc> <p>Returns the location of the annotations <anno>Anno</anno>. </p> @@ -217,16 +217,16 @@ </func> <func> <name name="new" arity="1"/> - <type name="location"></type> <fsummary>Create a new collection of annotations</fsummary> + <type name="location"></type> <desc> <p>Creates a new collection of annotations given a location.</p> </desc> </func> <func> <name name="set_file" arity="2"/> - <type name="filename"></type> <fsummary>Modify the filename</fsummary> + <type name="filename"></type> <desc> <p>Modifies the filename of the annotations <anno>Anno</anno>. </p> @@ -234,8 +234,8 @@ </func> <func> <name name="set_generated" arity="2"/> - <type name="generated"></type> <fsummary>Modify the generated marker</fsummary> + <type name="generated"></type> <desc> <p>Modifies the generated marker of the annotations <anno>Anno</anno>. @@ -244,8 +244,8 @@ </func> <func> <name name="set_line" arity="2"/> - <type name="line"></type> <fsummary>Modify the line</fsummary> + <type name="line"></type> <desc> <p>Modifies the line of the annotations <anno>Anno</anno>. </p> @@ -253,8 +253,8 @@ </func> <func> <name name="set_location" arity="2"/> - <type name="location"></type> <fsummary>Modify the location</fsummary> + <type name="location"></type> <desc> <p>Modifies the location of the annotations <anno>Anno</anno>. </p> @@ -262,8 +262,8 @@ </func> <func> <name name="set_record" arity="2"/> - <type name="record"></type> <fsummary>Modify the record marker</fsummary> + <type name="record"></type> <desc> <p>Modifies the record marker of the annotations <anno>Anno</anno>. </p> @@ -271,8 +271,8 @@ </func> <func> <name name="set_text" arity="2"/> - <type name="text"></type> <fsummary>Modify the text</fsummary> + <type name="text"></type> <desc> <p>Modifies the text of the annotations <anno>Anno</anno>. </p> @@ -280,8 +280,8 @@ </func> <func> <name name="text" arity="1"/> - <type name="text"></type> <fsummary>Return the text</fsummary> + <type name="text"></type> <desc> <p>Returns the text of the annotations <anno>Anno</anno>. If there is no text, <c>undefined</c> is returned. diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml index fdd776b7f1..0938b5dec3 100644 --- a/lib/stdlib/doc/src/erl_parse.xml +++ b/lib/stdlib/doc/src/erl_parse.xml @@ -174,8 +174,8 @@ </func> <func> <name name="abstract" arity="2"/> - <type name="encoding_func"/> <fsummary>Convert an Erlang term into an abstract form</fsummary> + <type name="encoding_func"/> <desc> <p>Converts the Erlang data structure <c><anno>Data</anno></c> into an abstract form of type <c><anno>AbsTerm</anno></c>.</p> diff --git a/lib/stdlib/doc/src/erl_pp.xml b/lib/stdlib/doc/src/erl_pp.xml index c9d9e2723d..4b8a571c81 100644 --- a/lib/stdlib/doc/src/erl_pp.xml +++ b/lib/stdlib/doc/src/erl_pp.xml @@ -48,8 +48,8 @@ <datatype> <name name="hook_function"/> <desc> - <p>The optional argument <marker id="hook_function"> - <c>HookFunction</c></marker>, shown in the functions described below, + <p>The optional argument <marker id="hook_function"/> + <c>HookFunction</c>, shown in the functions described below, defines a function which is called when an unknown form occurs where there should be a valid expression.</p> diff --git a/lib/stdlib/doc/src/erl_scan.xml b/lib/stdlib/doc/src/erl_scan.xml index 18e988e286..ee0d6b6033 100644 --- a/lib/stdlib/doc/src/erl_scan.xml +++ b/lib/stdlib/doc/src/erl_scan.xml @@ -40,39 +40,15 @@ </description> <datatypes> <datatype> - <name name="attribute_info"></name> - </datatype> - <datatype> - <name name="attributes"></name> - </datatype> - <datatype> - <name name="attributes_data"></name> - </datatype> - <datatype> <name name="category"></name> </datatype> <datatype> - <name name="column"></name> - </datatype> - <datatype> <name name="error_description"></name> </datatype> <datatype> <name name="error_info"></name> </datatype> <datatype> - <name name="info_line"></name> - </datatype> - <datatype> - <name name="info_location"></name> - </datatype> - <datatype> - <name name="line"></name> - </datatype> - <datatype> - <name name="location"></name> - </datatype> - <datatype> <name name="option"></name> </datatype> <datatype> @@ -88,9 +64,6 @@ <name name="token"></name> </datatype> <datatype> - <name name="token_info"></name> - </datatype> - <datatype> <name name="tokens"></name> </datatype> <datatype> @@ -122,25 +95,23 @@ <anno>StartLocation</anno>, [])</c>.</p> <p><c><anno>StartLocation</anno></c> indicates the initial location when scanning starts. If <c><anno>StartLocation</anno></c> is a line, - <c>attributes()</c> as well as <c><anno>EndLocation</anno></c> and + <c>Anno</c> as well as <c><anno>EndLocation</anno></c> and <c><anno>ErrorLocation</anno></c> will be lines. If <c><anno>StartLocation</anno></c> is a pair of a line and a column - <c>attributes()</c> takes the form of an opaque compound + <c>Anno</c> takes the form of an opaque compound data type, and <c><anno>EndLocation</anno></c> and <c><anno>ErrorLocation</anno></c> will be pairs of a line and a column. The <em>token - attributes</em> contain information about the column and the + annotations</em> contain information about the column and the line where the token begins, as well as the text of the token (if the <c>text</c> option is given), all of which can - be accessed by calling <seealso - marker="#token_info/1">token_info/1,2</seealso>, <seealso - marker="#attributes_info/1">attributes_info/1,2</seealso>, + be accessed by calling <seealso marker="#column/1">column/1</seealso>, <seealso marker="#line/1">line/1</seealso>, <seealso marker="#location/1">location/1</seealso>, and <seealso marker="#text/1">text/1</seealso>.</p> <p>A <em>token</em> is a tuple containing information about - syntactic category, the token attributes, and the actual + syntactic category, the token annotations, and the actual terminal symbol. For punctuation characters (e.g. <c>;</c>, <c>|</c>) and reserved words, the category and the symbol coincide, and the token is represented by a two-tuple. @@ -172,7 +143,7 @@ <item><p>Short for <c>[return_comments, return_white_spaces]</c>.</p> </item> <tag><c>text</c></tag> - <item><p>Include the token's text in the token attributes. The + <item><p>Include the token's text in the token annotation. The text is the part of the input corresponding to the token.</p> </item> </taglist> @@ -181,10 +152,10 @@ <func> <name name="tokens" arity="3"/> <name name="tokens" arity="4"/> + <fsummary>Re-entrant scanner</fsummary> <type name="char_spec"/> <type name="return_cont"/> <type_desc name="return_cont">An opaque continuation</type_desc> - <fsummary>Re-entrant scanner</fsummary> <desc> <p>This is the re-entrant scanner which scans characters until a <em>dot</em> ('.' followed by a white space) or @@ -306,150 +277,6 @@ </desc> </func> <func> - <name name="token_info" arity="1"/> - <fsummary>Return information about a token</fsummary> - <desc> - <p>Returns a list containing information about the token - <c><anno>Token</anno></c>. The order of the - <c><anno>TokenInfoTuple</anno></c>s is not - defined. See <seealso - marker="#token_info/2">token_info/2</seealso> for - information about specific - <c><anno>TokenInfoTuple</anno></c>s.</p> - <p>Note that if <c>token_info(Token, TokenItem)</c> returns - <c>undefined</c> for some <c>TokenItem</c>, the - item is not included in <c><anno>TokenInfo</anno></c>.</p> - </desc> - </func> - <func> - <name name="token_info" arity="2" clause_i="1"/> - <name name="token_info" arity="2" clause_i="2"/> - <type name="token_item"/> - <type name="attribute_item"/> - <fsummary>Return information about a token</fsummary> - <desc> - <p>Returns a list containing information about the token - <c><anno>Token</anno></c>. If one single - <c><anno>TokenItem</anno></c> is given the returned value is - the corresponding - <c>TokenInfoTuple</c>, or <c>undefined</c> if the - <c>TokenItem</c> has no value. If a list of - <c><anno>TokenItem</anno></c>s is given the result is a list of - <c><anno>TokenInfoTuple</anno></c>. The - <c><anno>TokenInfoTuple</anno></c>s will - appear with the corresponding <c><anno>TokenItem</anno></c>s in - the same order as the <c><anno>TokenItem</anno></c>s - appear in the list of <c>TokenItem</c>s. - <c><anno>TokenItem</anno></c>s with no value are not included - in the list of <c><anno>TokenInfoTuple</anno></c>.</p> - <p>The following <c><anno>TokenInfoTuple</anno></c>s with corresponding - <c><anno>TokenItem</anno></c>s are valid:</p> - <taglist> - <tag><c>{category, <seealso marker="#type-category"> - category()</seealso>}</c></tag> - <item><p>The category of the token.</p> - </item> - <tag><c>{column, <seealso marker="#type-column"> - column()</seealso>}</c></tag> - <item><p>The column where the token begins.</p> - </item> - <tag><c>{length, integer() > 0}</c></tag> - <item><p>The length of the token's text.</p> - </item> - <tag><c>{line, <seealso marker="#type-line"> - line()</seealso>}</c></tag> - <item><p>The line where the token begins.</p> - </item> - <tag><c>{location, <seealso marker="#type-location"> - location()</seealso>}</c></tag> - <item><p>The line and column where the token begins, or - just the line if the column unknown.</p> - </item> - <tag><c>{symbol, <seealso marker="#type-symbol"> - symbol()</seealso>}</c></tag> - <item><p>The token's symbol.</p> - </item> - <tag><c>{text, string()}</c></tag> - <item><p>The token's text.</p> - </item> - </taglist> - </desc> - </func> - <func> - <name name="attributes_info" arity="1"/> - <fsummary>Return information about token attributes</fsummary> - <desc> - <p>Returns a list containing information about the token - attributes <c><anno>Attributes</anno></c>. The order of the - <c><anno>AttributeInfoTuple</anno></c>s is not defined. - See <seealso - marker="#attributes_info/2">attributes_info/2</seealso> for - information about specific - <c><anno>AttributeInfoTuple</anno></c>s.</p> - <p>Note that if <c>attributes_info(Token, AttributeItem)</c> - returns <c>undefined</c> for some <c>AttributeItem</c> in - the list above, the item is not included in - <c><anno>AttributesInfo</anno></c>.</p> - </desc> - </func> - <func> - <name name="attributes_info" arity="2" clause_i="1"/> - <name name="attributes_info" arity="2" clause_i="2"/> - <fsummary>Return information about a token attributes</fsummary> - <type name="attribute_item"/> - <desc> - <p>Returns a list containing information about the token - attributes <c><anno>Attributes</anno></c>. If one single - <c><anno>AttributeItem</anno></c> is given the returned value is the - corresponding <c><anno>AttributeInfoTuple</anno></c>, - or <c>undefined</c> if the <c><anno>AttributeItem</anno></c> - has no value. If a list of <c><anno>AttributeItem</anno></c> - is given the result is a list of - <c><anno>AttributeInfoTuple</anno></c>. - The <c><anno>AttributeInfoTuple</anno></c>s - will appear with the corresponding <c><anno>AttributeItem</anno></c>s - in the same order as the <c><anno>AttributeItem</anno></c>s - appear in the list of <c><anno>AttributeItem</anno></c>s. - <c><anno>AttributeItem</anno></c>s with no - value are not included in the list of - <c><anno>AttributeInfoTuple</anno></c>.</p> - <p>The following <c><anno>AttributeInfoTuple</anno></c>s with - corresponding <c><anno>AttributeItem</anno></c>s are valid:</p> - <taglist> - <tag><c>{column, <seealso marker="#type-column"> - column()</seealso>}</c></tag> - <item><p>The column where the token begins.</p> - </item> - <tag><c>{length, integer() > 0}</c></tag> - <item><p>The length of the token's text.</p> - </item> - <tag><c>{line, <seealso marker="#type-line"> - line()</seealso>}</c></tag> - <item><p>The line where the token begins.</p> - </item> - <tag><c>{location, <seealso marker="#type-location"> - location()</seealso>}</c></tag> - <item><p>The line and column where the token begins, or - just the line if the column unknown.</p> - </item> - <tag><c>{text, string()}</c></tag> - <item><p>The token's text.</p> - </item> - </taglist> - </desc> - </func> - <func> - <name name="set_attribute" arity="3"/> - <fsummary>Set a token attribute value</fsummary> - <desc> - <p>Sets the value of the <c>line</c> attribute of the token - attributes <c><anno>Attributes</anno></c>.</p> - <p>The <c><anno>SetAttributeFun</anno></c> is called with the value of - the <c>line</c> attribute, and is to return the new value of - the <c>line</c> attribute.</p> - </desc> - </func> - <func> <name name="format_error" arity="1"/> <fsummary>Format an error descriptor</fsummary> <desc> diff --git a/lib/stdlib/doc/src/erl_tar.xml b/lib/stdlib/doc/src/erl_tar.xml index 0fa5a55c5b..898b55df72 100644 --- a/lib/stdlib/doc/src/erl_tar.xml +++ b/lib/stdlib/doc/src/erl_tar.xml @@ -442,7 +442,7 @@ structure like a file descriptor, a sftp channel id or such. The different <c>Fun</c> clauses operates on that very term. </p> - <p>The fun clauses parameter lists are: + <p>The fun clauses parameter lists are:</p> <taglist> <tag><c>(write, {UserPrivate,DataToWrite})</c></tag> <item>Write the term <c>DataToWrite</c> using <c>UserPrivate</c></item> @@ -457,7 +457,6 @@ <tag><c></c></tag> <item></item> </taglist> - </p> <p>A complete <c>Fun</c> parameter for reading and writing on files using the <seealso marker="kernel:file">file module</seealso> could be: </p> diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index 03b995e4de..7b01109ff8 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -132,9 +132,10 @@ <name name="access"/> </datatype> <datatype> - <name><marker id="type-continuation">continuation()</marker></name> + <name>continuation()</name> <desc> - <p>Opaque continuation used by <seealso marker="#select/1"> + <p><marker id="type-continuation"/> + Opaque continuation used by <seealso marker="#select/1"> <c>select/1,3</c></seealso>, <seealso marker="#select_reverse/1"> <c>select_reverse/1,3</c></seealso>, <seealso marker="#match/1"> @@ -448,13 +449,13 @@ Error: fun containing local Erlang function calls <item><c>{owner, pid()}</c> <br></br> The pid of the owner of the table.</item> - <item><c>{protection, <seealso marker="#type-access">access()</seealso>}</c> <br></br> + <item><c>{protection, </c><seealso marker="#type-access">access()</seealso><c>}</c> <br></br> The table access rights.</item> <item><c>{size, integer() >= 0</c> <br></br> The number of objects inserted in the table.</item> - <item><c>{type, <seealso marker="#type-type">type()</seealso>}</c> <br></br> + <item><c>{type, </c><seealso marker="#type-type">type()</seealso><c>}</c> <br></br> The table type.</item> <item><c>{read_concurrency, boolean()}</c> <br></br> @@ -916,7 +917,7 @@ ets:select(Table,MatchSpec),</code> </item> <item> <p><c>{keypos,<anno>Pos</anno>}</c> - Specfies which element in the stored tuples should be + Specifies which element in the stored tuples should be used as key. By default, it is the first element, i.e. <c><anno>Pos</anno>=1</c>. However, this is not always appropriate. In particular, we do not want the first element to be the @@ -1626,6 +1627,7 @@ true</pre> <name name="update_counter" arity="4" clause_i="2"/> <name name="update_counter" arity="3" clause_i="3"/> <name name="update_counter" arity="4" clause_i="3"/> + <fsummary>Update a counter object in an ETS table.</fsummary> <type variable="Tab"/> <type variable="Key"/> <type variable="UpdateOp" name_i="1"/> @@ -1633,7 +1635,6 @@ true</pre> <type variable="Threshold" name_i="1"/> <type variable="SetValue" name_i="1"/> <type variable="Default"/> - <fsummary>Update a counter object in an ETS table.</fsummary> <desc> <p>This function provides an efficient way to update one or more counters, without the hassle of having to look up an object, update @@ -1700,11 +1701,11 @@ true</pre> <func> <name name="update_element" arity="3" clause_i="1"/> <name name="update_element" arity="3" clause_i="2"/> + <fsummary>Updates the <c>Pos</c>:th element of the object with a given key in an ETS table.</fsummary> <type variable="Tab"/> <type variable="Key"/> <type variable="Value"/> <type variable="Pos"/> - <fsummary>Updates the <c>Pos</c>:th element of the object with a given key in an ETS table.</fsummary> <desc> <p>This function provides an efficient way to update one or more elements within an object, without the hassle of having to look up, diff --git a/lib/stdlib/doc/src/file_sorter.xml b/lib/stdlib/doc/src/file_sorter.xml index 30e09c17b0..f033eebec7 100644 --- a/lib/stdlib/doc/src/file_sorter.xml +++ b/lib/stdlib/doc/src/file_sorter.xml @@ -223,82 +223,82 @@ output(L) -> <datatypes> <datatype> - <name name="file_name"/><br/> + <name name="file_name"/> </datatype> <datatype> - <name name="file_names"/><br/> + <name name="file_names"/> </datatype> <datatype> - <name name="i_command"/><br/> + <name name="i_command"/> </datatype> <datatype> - <name name="i_reply"/><br/> + <name name="i_reply"/> </datatype> <datatype> - <name name="infun"/><br/> + <name name="infun"/> </datatype> <datatype> - <name name="input"/><br/> + <name name="input"/> </datatype> <datatype> - <name name="input_reply"/><br/> + <name name="input_reply"/> </datatype> <datatype> - <name name="o_command"/><br/> + <name name="o_command"/> </datatype> <datatype> - <name name="o_reply"/><br/> + <name name="o_reply"/> </datatype> <datatype> - <name name="object"/><br/> + <name name="object"/> </datatype> <datatype> - <name name="outfun"/><br/> + <name name="outfun"/> </datatype> <datatype> - <name name="output"/><br/> + <name name="output"/> </datatype> <datatype> - <name name="output_reply"/><br/> + <name name="output_reply"/> </datatype> <datatype> - <name name="value"/><br/> + <name name="value"/> </datatype> <datatype> - <name name="options"/><br/> + <name name="options"/> </datatype> <datatype> - <name name="option"/><br/> + <name name="option"/> </datatype> <datatype> - <name name="format"/><br/> + <name name="format"/> </datatype> <datatype> - <name name="format_fun"/><br/> + <name name="format_fun"/> </datatype> <datatype> - <name name="header_length"/><br/> + <name name="header_length"/> </datatype> <datatype> - <name name="key_pos"/><br/> + <name name="key_pos"/> </datatype> <datatype> - <name name="no_files"/><br/> + <name name="no_files"/> </datatype> <datatype> - <name name="order"/><br/> + <name name="order"/> </datatype> <datatype> - <name name="order_fun"/><br/> + <name name="order_fun"/> </datatype> <datatype> - <name name="size"/><br/> + <name name="size"/> </datatype> <datatype> - <name name="tmp_directory"/><br/> + <name name="tmp_directory"/> </datatype> <datatype> - <name name="reason"/><br/> + <name name="reason"/> </datatype> </datatypes> diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml index 1efac1535a..c4bab45781 100644 --- a/lib/stdlib/doc/src/gen_event.xml +++ b/lib/stdlib/doc/src/gen_event.xml @@ -716,7 +716,7 @@ gen_event:stop -----> Module:terminate/2 the purposes described below.</p> </note> <p>This function is called by a gen_event process when:</p> - <list typed="bulleted"> + <list type="bulleted"> <item>One of <seealso marker="sys#get_status/1">sys:get_status/1,2</seealso> is invoked to get the gen_event status. <c>Opt</c> is set @@ -740,7 +740,7 @@ gen_event:stop -----> Module:terminate/2 customises the details of the current state of the event handler. Any term is allowed for <c>Status</c>. The gen_event module uses <c>Status</c> as follows:</p> - <list typed="bulleted"> + <list type="bulleted"> <item>When <c>sys:get_status/1,2</c> is called, gen_event ensures that its return value contains <c>Status</c> in place of the event handler's actual state term.</item> diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml index 5f7b5a3437..4d594b8eb2 100644 --- a/lib/stdlib/doc/src/gen_fsm.xml +++ b/lib/stdlib/doc/src/gen_fsm.xml @@ -339,11 +339,12 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 </desc> </func> <func> - <name>reply(Caller, Reply) -> true</name> + <name>reply(Caller, Reply) -> Result</name> <fsummary>Send a reply to a caller.</fsummary> <type> <v>Caller - see below</v> <v>Reply = term()</v> + <v>Result = term()</v> </type> <desc> <p>This function can be used by a gen_fsm to explicitly send a @@ -358,6 +359,8 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 which will be given back to the client as the return value of <c>sync_send_event/2,3</c> or <c>sync_send_all_state_event/2,3</c>.</p> + <p>The return value <c>Result</c> is not further defined, and + should always be ignored.</p> </desc> </func> <func> @@ -802,7 +805,7 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 module state data.</p> </note> <p>This function is called by a gen_fsm process when:</p> - <list typed="bulleted"> + <list type="bulleted"> <item>One of <seealso marker="sys#get_status/1">sys:get_status/1,2</seealso> is invoked to get the gen_fsm status. <c>Opt</c> is set to diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml index c31e869db8..6d04771cd4 100644 --- a/lib/stdlib/doc/src/gen_server.xml +++ b/lib/stdlib/doc/src/gen_server.xml @@ -673,7 +673,7 @@ gen_server:abcast -----> Module:handle_cast/2 module state.</p> </note> <p>This function is called by a gen_server process when:</p> - <list typed="bulleted"> + <list type="bulleted"> <item>One of <seealso marker="sys#get_status/1">sys:get_status/1,2</seealso> is invoked to get the gen_server status. <c>Opt</c> is set diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml index edf3c51b4c..4655c8662f 100644 --- a/lib/stdlib/doc/src/io.xml +++ b/lib/stdlib/doc/src/io.xml @@ -132,8 +132,8 @@ <func> <name name="get_chars" arity="2"/> <name name="get_chars" arity="3"/> - <type name="server_no_data"/> <fsummary>Read a specified number of characters</fsummary> + <type name="server_no_data"/> <desc> <p>Reads <c><anno>Count</anno></c> characters from standard input (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. It @@ -162,8 +162,8 @@ <func> <name name="get_line" arity="1"/> <name name="get_line" arity="2"/> - <type name="server_no_data"/> <fsummary>Read a line</fsummary> + <type name="server_no_data"/> <desc> <p>Reads a line from the standard input (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. It returns:</p> @@ -300,8 +300,8 @@ <func> <name name="read" arity="1"/> <name name="read" arity="2"/> - <type name="server_no_data"/> <fsummary>Read a term</fsummary> + <type name="server_no_data"/> <desc> <p>Reads a term <c><anno>Term</anno></c> from the standard input (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. It @@ -330,8 +330,8 @@ <func> <name name="read" arity="3"/> <name name="read" arity="4"/> - <type name="server_no_data"/> <fsummary>Read a term</fsummary> + <type name="server_no_data"/> <desc> <p>Reads a term <c><anno>Term</anno></c> from <c><anno>IoDevice</anno></c>, prompting it with <c><anno>Prompt</anno></c>. Reading starts at location @@ -698,8 +698,8 @@ ok <func> <name name="fread" arity="2"/> <name name="fread" arity="3"/> - <type name="server_no_data"/> <fsummary>Read formatted input</fsummary> + <type name="server_no_data"/> <desc> <p>Reads characters from the standard input (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. Interprets the characters in @@ -870,8 +870,8 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in <name name="scan_erl_exprs" arity="2"/> <name name="scan_erl_exprs" arity="3"/> <name name="scan_erl_exprs" arity="4"/> - <type name="server_no_data"/> <fsummary>Read and tokenize Erlang expressions</fsummary> + <type name="server_no_data"/> <desc> <p>Reads data from the standard input (<c>IoDevice</c>), prompting it with <c>Prompt</c>. Reading starts at location @@ -919,8 +919,8 @@ enter><input>1.0er.</input> <name name="scan_erl_form" arity="2"/> <name name="scan_erl_form" arity="3"/> <name name="scan_erl_form" arity="4"/> - <type name="server_no_data"/> <fsummary>Read and tokenize an Erlang form</fsummary> + <type name="server_no_data"/> <desc> <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. Starts reading @@ -939,9 +939,9 @@ enter><input>1.0er.</input> <name name="parse_erl_exprs" arity="2"/> <name name="parse_erl_exprs" arity="3"/> <name name="parse_erl_exprs" arity="4"/> + <fsummary>Read, tokenize and parse Erlang expressions</fsummary> <type name="parse_ret"/> <type name="server_no_data"/> - <fsummary>Read, tokenize and parse Erlang expressions</fsummary> <desc> <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>), prompting it with @@ -990,9 +990,9 @@ enter><input>abc("hey".</input> <name name="parse_erl_form" arity="2"/> <name name="parse_erl_form" arity="3"/> <name name="parse_erl_form" arity="4"/> + <fsummary>Read, tokenize and parse an Erlang form</fsummary> <type name="parse_form_ret"/> <type name="server_no_data"/> - <fsummary>Read, tokenize and parse an Erlang form</fsummary> <desc> <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. Starts reading at diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml index 46edd9fe16..89ba5238b5 100644 --- a/lib/stdlib/doc/src/lists.xml +++ b/lib/stdlib/doc/src/lists.xml @@ -283,8 +283,8 @@ flatmap(Fun, List1) -> </func> <func> <name name="keyfind" arity="3"/> - <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <fsummary>Search for an element in a list of tuples</fsummary> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> <p>Searches the list of tuples <c><anno>TupleList</anno></c> for a tuple whose <c><anno>N</anno></c>th element compares equal to <c><anno>Key</anno></c>. @@ -311,8 +311,8 @@ flatmap(Fun, List1) -> </func> <func> <name name="keymember" arity="3"/> - <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <fsummary>Test for membership of a list of tuples</fsummary> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> <p>Returns <c>true</c> if there is a tuple in <c><anno>TupleList</anno></c> whose <c><anno>N</anno></c>th element compares equal to <c><anno>Key</anno></c>, otherwise @@ -346,8 +346,8 @@ flatmap(Fun, List1) -> </func> <func> <name name="keysearch" arity="3"/> - <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <fsummary>Search for an element in a list of tuples</fsummary> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> <p>Searches the list of tuples <c><anno>TupleList</anno></c> for a tuple whose <c><anno>N</anno></c>th element compares equal to <c><anno>Key</anno></c>. diff --git a/lib/stdlib/doc/src/math.xml b/lib/stdlib/doc/src/math.xml index 31e838d741..aee6c3f238 100644 --- a/lib/stdlib/doc/src/math.xml +++ b/lib/stdlib/doc/src/math.xml @@ -72,9 +72,9 @@ <name name="log10" arity="1"/> <name name="pow" arity="2"/> <name name="sqrt" arity="1"/> + <fsummary>Diverse math functions</fsummary> <type variable="X" name_i="7"/> <type variable="Y" name_i="7"/> - <fsummary>Diverse math functions</fsummary> <desc> <p>A collection of math functions which return floats. Arguments are numbers. </p> diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index 514ac37d90..c84ca9c8ad 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -31,6 +31,71 @@ </header> <p>This document describes the changes made to the STDLIB application.</p> +<section><title>STDLIB 2.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> In OTP 18.0, <c>qlc</c> does not handle syntax errors + well. This bug has been fixed. </p> + <p> + Own Id: OTP-12946</p> + </item> + <item> + <p> + Optimize zip:unzip/2 when uncompressing to memory.</p> + <p> + Own Id: OTP-12950</p> + </item> + <item> + <p> + The <c>stdlib</c> reference manual is updated to show + correct information about the return value of + <c>gen_fsm:reply/2</c>.</p> + <p> + Own Id: OTP-12973</p> + </item> + <item> + <p>re:split2,3 and re:replace/3,4 now correctly handles + pre-compiled patterns that have been compiled using the + '<c>unicode</c>' option.</p> + <p> + Own Id: OTP-12977</p> + </item> + <item> + <p> + Export <c>shell:catch_exception/1</c> as documented.</p> + <p> + Own Id: OTP-12990</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>A mechanism for limiting the amount of text that the + built-in error logger events will produce has been + introduced. It is useful for limiting both the size of + log files and the CPU time used to produce them.</p> + <p>This mechanism is experimental in the sense that it + may be changed if it turns out that it does not solve the + problem it is supposed to solve. In that case, there may + be backward incompatible improvements to this + mechanism.</p> + <p>See the documentation for the config parameter + <c>error_logger_format_depth</c> in the Kernel + application for information about how to turn on this + feature.</p> + <p> + Own Id: OTP-12864</p> + </item> + </list> + </section> + +</section> + <section><title>STDLIB 2.5</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -89,8 +154,9 @@ Correct <c>maps</c> module error exceptions </p> <p> Bad input to maps module function will now yield the - following exceptions: <list> <item>{badmap,NotMap} - or,</item> <item>badarg</item> </list></p> + following exceptions:</p> + <list> <item>{badmap, NotMap}, or </item> <item>badarg.</item> + </list> <p> Own Id: OTP-12657</p> </item> @@ -188,12 +254,11 @@ <p> <c>proc_lib:stop/1,3</c> is used by the following functions:</p> - <p> <list> <item><c>gen_server:stop/1,3</c> (new)</item> <item><c>gen_fsm:stop/1,3</c> (new)</item> <item><c>gen_event:stop/1,3</c> (modified to be synchronous)</item> <item><c>wx_object:stop/1,3</c> - (new)</item> </list></p> + (new)</item> </list> <p> Own Id: OTP-11173 Aux Id: seq12353 </p> </item> @@ -800,8 +865,7 @@ also implemented by the generic behaviours <c>gen_server</c>, <c>gen_event</c> and <c>gen_fsm</c>.</p> <p> - The potential incompatibility refers to</p> - <p> + The potential incompatibility refers to:</p> <list> <item>The previous behaviour of intercepting the system message and passing a tuple of size 2 as the last argument to <c>sys:handle_system_msg/6</c> is no longer @@ -809,7 +873,7 @@ <c>StateFun</c> in <c>sys:replace_state/2,3</c> fails is changed from being totally silent to possibly (if the callback module does not catch) throw an exception in the - client process.</item> </list></p> + client process.</item> </list> <p> (Thanks to James Fish and Steve Vinoski)</p> <p> @@ -971,22 +1035,28 @@ <p> EEP43: New data type - Maps</p> <p> - With Maps you may for instance: <taglist> <item><c>M0 = - #{ a => 1, b => 2}, % create - associations</c></item> <item><c>M1 = M0#{ a := 10 }, % - update values</c></item> <item><c>M2 = M1#{ "hi" => - "hello"}, % add new associations</c></item> <item><c>#{ - "hi" := V1, a := V2, b := V3} = M2. % match keys with - values</c></item> </taglist></p> + With Maps you may for instance:</p> + <taglist> + <tag/> <item><c>M0 = #{ a => 1, b => 2}, % create + associations</c></item> + <tag/><item><c>M1 = M0#{ a := 10 }, % update values</c></item> + <tag/><item><c>M2 = M1#{ "hi" => + "hello"}, % add new associations</c></item> + <tag/><item><c>#{ "hi" := V1, a := V2, b := V3} = M2. + % match keys with values</c></item> + </taglist> <p> For information on how to use Maps please see Map Expressions in the <seealso marker="doc/reference_manual:expressions#map_expressions"> Reference Manual</seealso>.</p> <p> The current implementation is without the following - features: <taglist> <item>No variable keys</item> - <item>No single value access</item> <item>No map - comprehensions</item> </taglist></p> + features:</p> + <taglist> + <tag/><item>No variable keys</item> + <tag/><item>No single value access</item> + <tag/><item>No map comprehensions</item> + </taglist> <p> Note that Maps is <em>experimental</em> during OTP 17.0.</p> <p> @@ -1737,13 +1807,15 @@ supervisor or for the problematic child.</p> <p> This introduces some incompatibilities in stdlib due to - new return values from supervisor: <list> + new return values from supervisor:</p> + <list> <item>restart_child/2 can now return {error,restarting}</item> <item>delete_child/2 can now return {error,restarting}</item> <item>which_children/1 returns a list of {Id,Child,Type,Mods}, where Child, in addition to the old pid() or 'undefined', now also can be - 'restarting'.</item> </list></p> + 'restarting'.</item> + </list> <p> *** POTENTIAL INCOMPATIBILITY ***</p> <p> @@ -1759,10 +1831,10 @@ Own Id: OTP-9782 Aux Id: seq11964 </p> </item> <item> - <p> Use universal time as base in error logger + <p> Use universal time as base in error logger</p> <p> Previous conversion used the deprecated - calendar:local_time_to_universal_time/1 </p></p> + calendar:local_time_to_universal_time/1 </p> <p> Own Id: OTP-9854</p> </item> @@ -2519,10 +2591,10 @@ Own Id: OTP-8989 Aux Id: seq11741 </p> </item> <item> - <p>Fix exception generation in the io module + <p>Fix exception generation in the io module</p> <p> Some functions did not generate correct badarg exception - on a badarg exception.</p></p> + on a badarg exception.</p> <p> Own Id: OTP-9045</p> </item> diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml index 91a4012ce9..a1bf67d332 100644 --- a/lib/stdlib/doc/src/random.xml +++ b/lib/stdlib/doc/src/random.xml @@ -76,9 +76,15 @@ dictionary, and returns the old state.</p> <p>One easy way of obtaining a unique value to seed with is to:</p> <code type="none"> - random:seed(<seealso marker="erts:erlang#phash2/1">erlang:phash2</seealso>([<seealso marker="erts:erlang#node/0">node()</seealso>]), - <seealso marker="erts:erlang#monotonic_time/0">erlang:monotonic_time()</seealso>, - <seealso marker="erts:erlang#unique_integer/0">erlang:unique_integer()</seealso>)</code> +random:seed(erlang:phash2([node()]), + erlang:monotonic_time(), + erlang:unique_integer())</code> + <p>See <seealso marker="erts:erlang#phash2/1"> + erlang:phash2/1</seealso>, <seealso marker="erts:erlang#node/0"> + node/0</seealso>, <seealso marker="erts:erlang#monotonic_time/0"> + erlang:monotonic_time/0</seealso>, and + <seealso marker="erts:erlang#unique_integer/0"> + erlang:unique_integer/0</seealso>) for details.</p> </desc> </func> <func> diff --git a/lib/stdlib/doc/src/re.xml b/lib/stdlib/doc/src/re.xml index 46b382a6be..8c19926b10 100644 --- a/lib/stdlib/doc/src/re.xml +++ b/lib/stdlib/doc/src/re.xml @@ -205,8 +205,8 @@ This option makes it possible to include comments inside complicated patterns. N </func> <func> <name name="run" arity="3"/> - <type_desc variable="CompileOpt">See <seealso marker="#compile_options">compile/2</seealso> above.</type_desc> <fsummary>Match a subject against regular expression and capture subpatterns</fsummary> + <type_desc variable="CompileOpt">See <seealso marker="#compile_options">compile/2</seealso> above.</type_desc> <desc> <p>Executes a regexp matching, returning <c>match/{match, @@ -881,11 +881,11 @@ nomatch </desc> </func> </funcs> - - <marker id="regexp_syntax"></marker> + <section> <title>PERL LIKE REGULAR EXPRESSIONS SYNTAX</title> - <p>The following sections contain reference material for the + <p><marker id="regexp_syntax"></marker> + The following sections contain reference material for the regular expressions used by this module. The regular expression reference is based on the PCRE documentation, with changes in cases where the re module behaves differently to the PCRE library.</p> @@ -2070,7 +2070,7 @@ supported, and an error is given if they are encountered.</p> <p>By default, in UTF modes, characters with values greater than 255 do not match any of the POSIX character classes. However, if the PCRE_UCP option is passed -to <b>pcre_compile()</b>, some of the classes are changed so that Unicode +to <em>pcre_compile()</em>, some of the classes are changed so that Unicode character properties are used. This is achieved by replacing the POSIX classes by other sequences, as follows:</p> @@ -2078,10 +2078,10 @@ by other sequences, as follows:</p> <tag>[:alnum:]</tag> <item>becomes <em>\p{Xan}</em></item> <tag>[:alpha:]</tag> <item>becomes <em>\p{L}</em></item> <tag>[:blank:]</tag> <item>becomes <em>\h</em></item> - <tag>[:digit:</tag>] <item>becomes <em>\p{Nd}</em></item> + <tag>[:digit:]</tag> <item>becomes <em>\p{Nd}</em></item> <tag>[:lower:]</tag> <item>becomes <em>\p{Ll}</em></item> <tag>[:space:]</tag> <item>becomes <em>\p{Xps}</em></item> - <tag>[:upper:</tag>] <item>becomes <em>\p{Lu}</em></item> + <tag>[:upper:]</tag> <item>becomes <em>\p{Lu}</em></item> <tag>[:word:]</tag> <item>becomes <em>\p{Xwd}</em></item> </taglist> @@ -3059,7 +3059,7 @@ default newline convention is in force:</p> <quote><p> abc #comment \n still comment</p></quote> -<p>On encountering the # character, <b>pcre_compile()</b> skips along, looking for +<p>On encountering the # character, <em>pcre_compile()</em> skips along, looking for a newline in the pattern. The sequence \n is still literal at this stage, so it does not terminate the comment. Only an actual character with the code value 0x0a (the default newline) does so.</p> diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml index 5d7648d9a1..53f6ca957a 100644 --- a/lib/stdlib/doc/src/sofs.xml +++ b/lib/stdlib/doc/src/sofs.xml @@ -398,8 +398,9 @@ fun(S) -> sofs:partition(1, S) end </datatype> <datatype> <!-- Parameterized opaque types are NYI: --> - <name><marker id="type-tuple_of">tuple_of(T)</marker></name> - <desc><p>A tuple where the elements are of type <c>T</c>.</p></desc> + <name>tuple_of(T)</name> + <desc><p><marker id="type-tuple_of"/> + A tuple where the elements are of type <c>T</c>.</p></desc> </datatype> </datatypes> <funcs> diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index f08b752998..24ff251ce3 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -353,7 +353,7 @@ <desc> <p>Dynamically adds a child specification to the supervisor <c><anno>SupRef</anno></c> which starts the corresponding child process.</p> - <p><marker id="SupRef"><c><anno>SupRef</anno></c></marker> can be:</p> + <p><marker id="SupRef"/><c><anno>SupRef</anno></c> can be:</p> <list type="bulleted"> <item>the pid,</item> <item><c>Name</c>, if the supervisor is locally registered,</item> diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index 6ec515849e..d400f72e1d 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -238,8 +238,8 @@ <p>These functions are intended only to help with debugging. They are provided for convenience, allowing developers to avoid having to create their own state extraction functions and also avoid having to interactively extract state from the return values of - <c><seealso marker="#get_status-1">get_status/1</seealso></c> or - <c><seealso marker="#get_status-2">get_status/2</seealso></c> while debugging.</p> + <seealso marker="#get_status-1"><c>get_status/1</c></seealso> or + <seealso marker="#get_status-2"><c>get_status/2</c></seealso> while debugging.</p> </note> <p>The value of <c><anno>State</anno></c> varies for different types of processes. For a <c>gen_server</c> process, the returned <c><anno>State</anno></c> diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml index e002f519b9..7609487300 100644 --- a/lib/stdlib/doc/src/timer.xml +++ b/lib/stdlib/doc/src/timer.xml @@ -85,7 +85,6 @@ <name name="send_after" arity="3"/> <fsummary>Send <c>Message</c>to <c>Pid</c>after a specified <c>Time</c>.</fsummary> <desc> - <p> <taglist> <tag><c>send_after/3</c></tag> <item> @@ -99,7 +98,6 @@ <p>Same as <c>send_after(<anno>Time</anno>, self(), <anno>Message</anno>)</c>.</p> </item> </taglist> - </p> </desc> </func> <func> @@ -109,7 +107,6 @@ <name name="exit_after" arity="3"/> <fsummary>Send an exit signal with <c>Reason</c>after a specified <c>Time</c>.</fsummary> <desc> - <p> <taglist> <tag><c>exit_after/3</c></tag> <item> @@ -130,7 +127,6 @@ <p>Same as <c>exit_after(<anno>Time</anno>, self(), kill)</c>. </p> </item> </taglist> - </p> </desc> </func> <func> @@ -147,7 +143,6 @@ <name name="send_interval" arity="3"/> <fsummary>Send <c>Message</c>repeatedly at intervals of <c>Time</c>.</fsummary> <desc> - <p> <taglist> <tag><c>send_interval/3</c></tag> <item> @@ -161,7 +156,6 @@ <p>Same as <c>send_interval(<anno>Time</anno>, self(), <anno>Message</anno>)</c>.</p> </item> </taglist> - </p> </desc> </func> <func> @@ -192,7 +186,6 @@ Function, Arguments)</c> or <c>apply(Fun, Arguments)</c></fsummary> <type_desc variable="Time">In microseconds</type_desc> <desc> - <p> <taglist> <tag><c>tc/3</c></tag> <item> @@ -213,7 +206,6 @@ </item> </taglist> - </p> </desc> </func> <func> diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml index 19ddf1cbd6..966eec49f5 100644 --- a/lib/stdlib/doc/src/unicode.xml +++ b/lib/stdlib/doc/src/unicode.xml @@ -133,7 +133,7 @@ <c>latin1</c>, or have characters encoded as one of the UTF-encodings, which is given as the <c><anno>InEncoding</anno></c> parameter. Only when the <c><anno>InEncoding</anno></c> is one of the UTF - encodings, integers in the list are allowed to be grater than + encodings, integers in the list are allowed to be greater than 255.</p> <p>If <c><anno>InEncoding</anno></c> is <c>latin1</c>, the <c><anno>Data</anno></c> parameter diff --git a/lib/stdlib/doc/src/zip.xml b/lib/stdlib/doc/src/zip.xml index 4500995c34..186c8ac724 100644 --- a/lib/stdlib/doc/src/zip.xml +++ b/lib/stdlib/doc/src/zip.xml @@ -126,7 +126,7 @@ </datatype> <datatype> <name name="filename"/> - <p>The name of a zip file.</p> + <desc><p>The name of a zip file.</p></desc> </datatype> <datatype><name name="extension"/></datatype> <datatype><name name="extension_spec"/></datatype> diff --git a/lib/stdlib/include/erl_bits.hrl b/lib/stdlib/include/erl_bits.hrl index 8405a55d55..2a54587a17 100644 --- a/lib/stdlib/include/erl_bits.hrl +++ b/lib/stdlib/include/erl_bits.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% Copyright Ericsson AB 1999-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -26,10 +26,10 @@ -type bt_unit() :: 1..256. -record(bittype, { - type :: bt_type(), - unit :: bt_unit(), %% element unit - sign :: bt_sign(), - endian :: bt_endian() + type :: bt_type() | 'undefined', + unit :: bt_unit() | 'undefined', %% element unit + sign :: bt_sign() | 'undefined', + endian :: bt_endian() | 'undefined' }). -record(bitdefault, { diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl index b93ce97cd3..6e00401dce 100644 --- a/lib/stdlib/src/beam_lib.erl +++ b/lib/stdlib/src/beam_lib.erl @@ -308,6 +308,17 @@ make_crypto_key(des3_cbc=Type, String) -> <<K3:8/binary,IVec:8/binary>> = erlang:md5([First|reverse(String)]), {Type,[K1,K2,K3],IVec,8}. +-spec build_module(Chunks) -> {'ok', Binary} when + Chunks :: [{chunkid(), dataB()}], + Binary :: binary(). + +build_module(Chunks0) -> + Chunks = list_to_binary(build_chunks(Chunks0)), + Size = byte_size(Chunks), + 0 = Size rem 4, % Assertion: correct padding? + {ok, <<"FOR1", (Size+4):32, "BEAM", Chunks/binary>>}. + + %% %% Local functions %% @@ -419,12 +430,6 @@ strip_file(File) -> end end. -build_module(Chunks0) -> - Chunks = list_to_binary(build_chunks(Chunks0)), - Size = byte_size(Chunks), - 0 = Size rem 4, % Assertion: correct padding? - {ok, <<"FOR1", (Size+4):32, "BEAM", Chunks/binary>>}. - build_chunks([{Id, Data} | Chunks]) -> BId = list_to_binary(Id), Size = byte_size(Data), @@ -867,7 +872,7 @@ mandatory_chunks() -> %%% can use it. %%% ==================================================================== --record(state, {crypto_key_f :: crypto_fun()}). +-record(state, {crypto_key_f :: crypto_fun() | 'undefined'}). -define(CRYPTO_KEY_SERVER, beam_lib__crypto_key_server). diff --git a/lib/stdlib/src/edlin.erl b/lib/stdlib/src/edlin.erl index 8c7a984f1c..19444c0502 100644 --- a/lib/stdlib/src/edlin.erl +++ b/lib/stdlib/src/edlin.erl @@ -227,6 +227,8 @@ key_map($F, meta_o) -> end_of_line; key_map($\177, none) -> backward_delete_char; key_map($\177, meta) -> backward_kill_word; key_map($[, meta) -> meta_left_sq_bracket; +key_map($H, meta_left_sq_bracket) -> beginning_of_line; +key_map($F, meta_left_sq_bracket) -> end_of_line; key_map($D, meta_left_sq_bracket) -> backward_char; key_map($C, meta_left_sq_bracket) -> forward_char; % support a few <CTRL>+<CURSOR LEFT|RIGHT> combinations... @@ -237,8 +239,10 @@ key_map($[, meta_meta) -> meta_csi; key_map($C, meta_csi) -> forward_word; key_map($D, meta_csi) -> backward_word; key_map($1, meta_left_sq_bracket) -> {csi, "1"}; +key_map($3, meta_left_sq_bracket) -> {csi, "3"}; key_map($5, meta_left_sq_bracket) -> {csi, "5"}; key_map($5, {csi, "1;"}) -> {csi, "1;5"}; +key_map($~, {csi, "3"}) -> forward_delete_char; key_map($C, {csi, "5"}) -> forward_word; key_map($C, {csi, "1;5"}) -> forward_word; key_map($D, {csi, "5"}) -> backward_word; diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index d3124ac593..c8bba579cc 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -49,7 +49,8 @@ -define(DEFAULT_ENCODING, utf8). %% Epp state record. --record(epp, {file :: file:io_device(), %Current file +-record(epp, {file :: file:io_device() + | 'undefined', %Current file location=1, %Current location delta=0 :: non_neg_integer(), %Offset from Location (-file) name="" :: file:name(), %Current file name diff --git a/lib/stdlib/src/erl_anno.erl b/lib/stdlib/src/erl_anno.erl index 143318aa55..d32c34dabd 100644 --- a/lib/stdlib/src/erl_anno.erl +++ b/lib/stdlib/src/erl_anno.erl @@ -33,7 +33,7 @@ -export_type([anno_term/0]). --define(LN(L), is_integer(L)). +-define(LN(L), is_integer(L), L >= 0). -define(COL(C), (is_integer(C) andalso C >= 1)). %% Location. @@ -52,13 +52,13 @@ | {'record', record()} | {'text', string()}. --type anno() :: location() | [annotation(), ...]. +-opaque anno() :: location() | [annotation(), ...]. -type anno_term() :: term(). -type column() :: pos_integer(). -type generated() :: boolean(). -type filename() :: file:filename_all(). --type line() :: integer(). +-type line() :: non_neg_integer(). -type location() :: line() | {line(), column()}. -type record() :: boolean(). -type text() :: string(). @@ -90,9 +90,13 @@ to_term(Anno) -> -ifdef(DEBUG). from_term(Term) when is_list(Term) -> Term; +from_term(Line) when is_integer(Line), Line < 0 -> % Before OTP 19 + set_generated(true, new(-Line)); from_term(Term) -> [{location, Term}]. -else. +from_term(Line) when is_integer(Line), Line < 0 -> % Before OTP 19 + set_generated(true, new(-Line)); from_term(Term) -> Term. -endif. @@ -198,18 +202,11 @@ file(Anno) -> Anno :: anno(). generated(Line) when ?ALINE(Line) -> - Line =< 0; + false; generated({Line, Column}) when ?ALINE(Line), ?ACOLUMN(Column) -> - Line =< 0; + false; generated(Anno) -> - _ = anno_info(Anno, generated, false), - {location, Location} = lists:keyfind(location, 1, Anno), - case Location of - {Line, _Column} -> - Line =< 0; - Line -> - Line =< 0 - end. + anno_info(Anno, generated, false). -spec line(Anno) -> line() when Anno :: anno(). @@ -226,18 +223,11 @@ line(Anno) -> Anno :: anno(). location(Line) when ?ALINE(Line) -> - abs(Line); -location({Line, Column}) when ?ALINE(Line), ?ACOLUMN(Column) -> - {abs(Line), Column}; + Line; +location({Line, Column}=Location) when ?ALINE(Line), ?ACOLUMN(Column) -> + Location; location(Anno) -> - case anno_info(Anno, location) of - Line when Line < 0 -> - -Line; - {Line, Column} when Line < 0 -> - {-Line, Column}; - Location -> - Location - end. + anno_info(Anno, location). -spec record(Anno) -> record() when Anno :: anno(). @@ -270,31 +260,8 @@ set_file(File, Anno) -> Generated :: generated(), Anno :: anno(). -set_generated(true, Line) when ?ALINE(Line) -> - -abs(Line); -set_generated(false, Line) when ?ALINE(Line) -> - abs(Line); -set_generated(true, {Line, Column}) when ?ALINE(Line), - ?ACOLUMN(Column) -> - {-abs(Line),Column}; -set_generated(false, {Line, Column}) when ?ALINE(Line), - ?ACOLUMN(Column) -> - {abs(Line),Column}; set_generated(Generated, Anno) -> - _ = set(generated, Generated, Anno), - {location, Location} = lists:keyfind(location, 1, Anno), - NewLocation = - case Location of - {Line, Column} when Generated -> - {-abs(Line), Column}; - {Line, Column} when not Generated -> - {abs(Line), Column}; - Line when Generated -> - -abs(Line); - Line when not Generated -> - abs(Line) - end, - lists:keyreplace(location, 1, Anno, {location, NewLocation}). + set(generated, Generated, Anno). -spec set_line(Line, Anno) -> Anno when Line :: line(), @@ -313,38 +280,17 @@ set_line(Line, Anno) -> Anno :: anno(). set_location(Line, L) when ?ALINE(L), ?LLINE(Line) -> - new_location(fix_line(Line, L)); + new_location(Line); set_location(Line, {L, Column}) when ?ALINE(L), ?ACOLUMN(Column), ?LLINE(Line) -> - new_location(fix_line(Line, L)); + new_location(Line); set_location({L, C}=Loc, Line) when ?ALINE(Line), ?LLINE(L), ?LCOLUMN(C) -> - new_location(fix_location(Loc, Line)); + new_location(Loc); set_location({L, C}=Loc, {Line, Column}) when ?ALINE(Line), ?ACOLUMN(Column), ?LLINE(L), ?LCOLUMN(C) -> - new_location(fix_location(Loc, Line)); + new_location(Loc); set_location(Location, Anno) -> - _ = set(location, Location, Anno), - {location, OldLocation} = lists:keyfind(location, 1, Anno), - NewLocation = - case {Location, OldLocation} of - {{_Line, _Column}=Loc, {L, _C}} -> - fix_location(Loc, L); - {Line, {L, _C}} -> - fix_line(Line, L); - {{_Line, _Column}=Loc, L} -> - fix_location(Loc, L); - {Line, L} -> - fix_line(Line, L) - end, - lists:keyreplace(location, 1, Anno, {location, NewLocation}). - -fix_location({Line, Column}, OldLine) -> - {fix_line(Line, OldLine), Column}. - -fix_line(Line, OldLine) when OldLine < 0, Line > 0 -> - -Line; -fix_line(Line, _OldLine) -> - Line. + set(location, Location, Anno). -spec set_record(Record, Anno) -> Anno when Record :: record(), @@ -383,7 +329,7 @@ set_anno(Item, Value, Anno) -> _ -> lists:keyreplace(Item, 1, Anno, {Item, Value}) end, - simplify(R) + reset_simplify(R) end. reset(Anno, Item) -> diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index c4cb5fdc80..a5f0e7dbd3 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -31,12 +31,8 @@ -export([is_guard_expr/1]). -export([bool_option/4,value_option/3,value_option/7]). --export([modify_line/2]). - -import(lists, [member/2,map/2,foldl/3,foldr/3,mapfoldl/3,all/2,reverse/1]). --deprecated([{modify_line, 2, next_major_release}]). - %% bool_option(OnOpt, OffOpt, Default, Options) -> boolean(). %% value_option(Flag, Default, Options) -> Value. %% value_option(Flag, Default, OnOpt, OnVal, OffOpt, OffVal, Options) -> @@ -79,7 +75,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> %%-define(DEBUGF(X,Y), io:format(X, Y)). -define(DEBUGF(X,Y), void). --type line() :: erl_anno:line(). % a convenient alias +-type line() :: erl_anno:anno(). % a convenient alias -type fa() :: {atom(), arity()}. % function+arity -type ta() :: {atom(), arity()}. % type+arity @@ -238,6 +234,9 @@ format_error({removed, MFA, ReplacementMFA, Rel}) -> "use ~s", [format_mfa(MFA), Rel, format_mfa(ReplacementMFA)]); format_error({removed, MFA, String}) when is_list(String) -> io_lib:format("~s: ~s", [format_mfa(MFA), String]); +format_error({removed_type, MNA, ReplacementMNA, Rel}) -> + io_lib:format("the type ~s was removed in ~s; use ~s instead", + [format_mna(MNA), Rel, format_mna(ReplacementMNA)]); format_error({obsolete_guard, {F, A}}) -> io_lib:format("~p/~p obsolete", [F, A]); format_error({too_many_arguments,Arity}) -> @@ -413,6 +412,9 @@ format_mfa({M, F, A}) when is_integer(A) -> format_mf(M, F, ArityString) when is_atom(M), is_atom(F) -> atom_to_list(M) ++ ":" ++ atom_to_list(F) ++ "/" ++ ArityString. +format_mna({M, N, A}) when is_integer(A) -> + atom_to_list(M) ++ ":" ++ atom_to_list(N) ++ gen_type_paren(A). + format_where(L) when is_integer(L) -> io_lib:format("(line ~p)", [L]); format_where({L,C}) when is_integer(L), is_integer(C) -> @@ -3482,13 +3484,6 @@ vt_no_unused(Vt) -> [V || {_,{_,U,_L}}=V <- Vt, U =/= unused]. copy_expr(Expr, Anno) -> erl_parse:map_anno(fun(_A) -> Anno end, Expr). -%% modify_line(Form, Fun) -> Form -%% modify_line(Expression, Fun) -> Expression -%% Applies Fun to each line number occurrence. - -modify_line(T, F0) -> - erl_parse:map_anno(F0, T). - %% Check a record_info call. We have already checked that it is not %% shadowed by an import. @@ -3557,6 +3552,7 @@ deprecated_function(Line, M, F, As, St) -> St end. +-dialyzer({no_match, deprecated_type/5}). deprecated_type(L, M, N, As, St) -> NAs = length(As), case otp_internal:obsolete_type(M, N, NAs) of @@ -3567,6 +3563,8 @@ deprecated_type(L, M, N, As, St) -> false -> St end; + {removed, Replacement, Rel} -> + add_warning(L, {removed_type, {M,N,NAs}, Replacement, Rel}, St); no -> St end. diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index e82282421e..ae42a8f0b1 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -525,11 +525,6 @@ Erlang code. -export([type_inop_prec/1,type_preop_prec/1]). -export([map_anno/2, fold_anno/3, mapfold_anno/3, new_anno/1, anno_to_term/1, anno_from_term/1]). --export([set_line/2,get_attribute/2,get_attributes/1]). - --deprecated([{set_line, 2, next_major_release}, - {get_attribute, 2, next_major_release}, - {get_attributes, 1, next_major_release}]). %% The following directive is needed for (significantly) faster compilation %% of the generated .erl file by the HiPE compiler. Please do not remove. @@ -795,31 +790,11 @@ record_fields([{match,_Am,{atom,Aa,A},Expr}|Fields]) -> [{record_field,Aa,{atom,Aa,A},Expr}|record_fields(Fields)]; record_fields([{typed,Expr,TypeInfo}|Fields]) -> [Field] = record_fields([Expr]), - TypeInfo1 = - case Expr of - {match, _, _, _} -> TypeInfo; %% If we have an initializer. - {atom, Aa, _} -> - case has_undefined(TypeInfo) of - false -> - lift_unions(abstract2(undefined, Aa), TypeInfo); - true -> - TypeInfo - end - end, - [{typed_record_field,Field,TypeInfo1}|record_fields(Fields)]; + [{typed_record_field,Field,TypeInfo}|record_fields(Fields)]; record_fields([Other|_Fields]) -> ret_err(?anno(Other), "bad record field"); record_fields([]) -> []. -has_undefined({atom,_,undefined}) -> - true; -has_undefined({ann_type,_,[_,T]}) -> - has_undefined(T); -has_undefined({type,_,union,Ts}) -> - lists:any(fun has_undefined/1, Ts); -has_undefined(_) -> - false. - term(Expr) -> try normalise(Expr) catch _:_R -> ret_err(?anno(Expr), "bad attribute") @@ -1118,28 +1093,6 @@ type_preop_prec('-') -> {600,700}; type_preop_prec('bnot') -> {600,700}; type_preop_prec('#') -> {700,800}. -%%% [Experimental]. The parser just copies the attributes of the -%%% scanner tokens to the abstract format. This design decision has -%%% been hidden to some extent: use set_line() and get_attribute() to -%%% access the second element of (almost all) of the abstract format -%%% tuples. A typical use is to negate line numbers to prevent the -%%% compiler from emitting warnings and errors. The second element can -%%% (of course) be set to any value, but then these functions no -%%% longer apply. To get all present attributes as a property list -%%% get_attributes() should be used. - --compile({nowarn_deprecated_function,{erl_scan,set_attribute,3}}). -set_line(L, F) -> - erl_scan:set_attribute(line, L, F). - --compile({nowarn_deprecated_function,{erl_scan,attributes_info,2}}). -get_attribute(L, Name) -> - erl_scan:attributes_info(L, Name). - --compile({nowarn_deprecated_function,{erl_scan,attributes_info,1}}). -get_attributes(L) -> - erl_scan:attributes_info(L). - -spec map_anno(Fun, Abstr) -> NewAbstr when Fun :: fun((Anno) -> Anno), Anno :: erl_anno:anno(), diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl index d2f53816b8..47223b129c 100644 --- a/lib/stdlib/src/erl_scan.erl +++ b/lib/stdlib/src/erl_scan.erl @@ -52,25 +52,15 @@ %%% External exports -export([string/1,string/2,string/3,tokens/3,tokens/4, - format_error/1,reserved_word/1, - token_info/1,token_info/2, - attributes_info/1,attributes_info/2,set_attribute/3]). + format_error/1,reserved_word/1]). -export([column/1,end_location/1,line/1,location/1,text/1, category/1,symbol/1]). --deprecated([{attributes_info, 1, next_major_release}, - {attributes_info, 2, next_major_release}, - {set_attribute, 3, next_major_release}, - {token_info, 1, next_major_release}, - {token_info, 2, next_major_release}]). - %%% Private -export([continuation_location/1]). -export_type([error_info/0, - line/0, - location/0, options/0, return_cont/0, token/0, @@ -85,29 +75,18 @@ -define(ALINE(L), is_integer(L)). -define(STRING(S), is_list(S)). -define(RESWORDFUN(F), is_function(F, 1)). --define(SETATTRFUN(F), is_function(F, 1)). -type category() :: atom(). --type column() :: pos_integer(). % Deprecated --type line() :: integer(). % Deprecated --type location() :: line() | {line(),column()}. % Deprecated -type resword_fun() :: fun((atom()) -> boolean()). -type option() :: 'return' | 'return_white_spaces' | 'return_comments' | 'text' | {'reserved_word_fun', resword_fun()}. -type options() :: option() | [option()]. -type symbol() :: atom() | float() | integer() | string(). --type info_line() :: integer() | term(). --type attributes_data() - :: [{'column', column()} | {'line', info_line()} | {'text', string()}] - | {line(), column()}. -%% The fact that {line(),column()} is a possible attributes() type -%% is hidden. --type attributes() :: line() | attributes_data(). --type token() :: {category(), attributes(), symbol()} - | {category(), attributes()}. +-type token() :: {category(), Anno :: erl_anno:anno(), symbol()} + | {category(), Anno :: erl_anno:anno()}. -type tokens() :: [token()]. -type error_description() :: term(). --type error_info() :: {location(), module(), error_description()}. +-type error_info() :: {erl_anno:location(), module(), error_description()}. %%% Local record. -record(erl_scan, @@ -136,8 +115,8 @@ format_error(Other) -> String :: string(), Return :: {'ok', Tokens :: tokens(), EndLocation} | {'error', ErrorInfo :: error_info(), ErrorLocation}, - EndLocation :: location(), - ErrorLocation :: location(). + EndLocation :: erl_anno:location(), + ErrorLocation :: erl_anno:location(). string(String) -> string(String, 1, []). @@ -145,9 +124,9 @@ string(String) -> String :: string(), Return :: {'ok', Tokens :: tokens(), EndLocation} | {'error', ErrorInfo :: error_info(), ErrorLocation}, - StartLocation :: location(), - EndLocation :: location(), - ErrorLocation :: location(). + StartLocation :: erl_anno:location(), + EndLocation :: erl_anno:location(), + ErrorLocation :: erl_anno:location(). string(String, StartLocation) -> string(String, StartLocation, []). @@ -156,9 +135,9 @@ string(String, StartLocation) -> Options :: options(), Return :: {'ok', Tokens :: tokens(), EndLocation} | {'error', ErrorInfo :: error_info(), ErrorLocation}, - StartLocation :: location(), - EndLocation :: location(), - ErrorLocation :: location(). + StartLocation :: erl_anno:location(), + EndLocation :: erl_anno:location(), + ErrorLocation :: erl_anno:location(). string(String, Line, Options) when ?STRING(String), ?ALINE(Line) -> string1(String, options(Options), Line, no_col, []); string(String, {Line,Column}, Options) when ?STRING(String), @@ -167,20 +146,23 @@ string(String, {Line,Column}, Options) when ?STRING(String), string1(String, options(Options), Line, Column, []). -type char_spec() :: string() | 'eof'. --type cont_fun() :: fun((char_spec(), #erl_scan{}, line(), column(), +-type cont_fun() :: fun((char_spec(), #erl_scan{}, + erl_anno:line(), erl_anno:column(), tokens(), any()) -> any()). -opaque return_cont() :: {erl_scan_continuation, - string(), column(), tokens(), line(), + string(), erl_anno:column(), tokens(), + erl_anno:line(), #erl_scan{}, any(), cont_fun()}. --type tokens_result() :: {'ok', Tokens :: tokens(), EndLocation :: location()} - | {'eof', EndLocation :: location()} +-type tokens_result() :: {'ok', Tokens :: tokens(), + EndLocation :: erl_anno:location()} + | {'eof', EndLocation :: erl_anno:location()} | {'error', ErrorInfo :: error_info(), - EndLocation :: location()}. + EndLocation :: erl_anno:location()}. -spec tokens(Continuation, CharSpec, StartLocation) -> Return when Continuation :: return_cont() | [], CharSpec :: char_spec(), - StartLocation :: location(), + StartLocation :: erl_anno:location(), Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()} | {'more', Continuation1 :: return_cont()}. tokens(Cont, CharSpec, StartLocation) -> @@ -189,7 +171,7 @@ tokens(Cont, CharSpec, StartLocation) -> -spec tokens(Continuation, CharSpec, StartLocation, Options) -> Return when Continuation :: return_cont() | [], CharSpec :: char_spec(), - StartLocation :: location(), + StartLocation :: erl_anno:location(), Options :: options(), Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()} | {'more', Continuation1 :: return_cont()}. @@ -257,155 +239,6 @@ symbol({_Category,_Anno,Symbol}) -> symbol(T) -> erlang:error(badarg, [T]). --type attribute_item() :: 'column' | 'length' | 'line' - | 'location' | 'text'. --type info_location() :: location() | term(). --type attribute_info() :: {'column', column()}| {'length', pos_integer()} - | {'line', info_line()} - | {'location', info_location()} - | {'text', string()}. --type token_item() :: 'category' | 'symbol' | attribute_item(). --type token_info() :: {'category', category()} | {'symbol', symbol()} - | attribute_info(). - --spec token_info(Token) -> TokenInfo when - Token :: token(), - TokenInfo :: [TokenInfoTuple :: token_info()]. -token_info(Token) -> - Items = [category,column,length,line,symbol,text], % undefined order - token_info(Token, Items). - --spec token_info(Token, TokenItem) -> TokenInfoTuple | 'undefined' when - Token :: token(), - TokenItem :: token_item(), - TokenInfoTuple :: token_info(); - (Token, TokenItems) -> TokenInfo when - Token :: token(), - TokenItems :: [TokenItem :: token_item()], - TokenInfo :: [TokenInfoTuple :: token_info()]. -token_info(_Token, []) -> - []; -token_info(Token, [Item|Items]) when is_atom(Item) -> - case token_info(Token, Item) of - undefined -> - token_info(Token, Items); - TokenInfo when is_tuple(TokenInfo) -> - [TokenInfo|token_info(Token, Items)] - end; -token_info({Category,_Attrs}, category=Item) -> - {Item,Category}; -token_info({Category,_Attrs,_Symbol}, category=Item) -> - {Item,Category}; -token_info({Category,_Attrs}, symbol=Item) -> - {Item,Category}; -token_info({_Category,_Attrs,Symbol}, symbol=Item) -> - {Item,Symbol}; -token_info({_Category,Attrs}, Item) -> - attributes_info(Attrs, Item); -token_info({_Category,Attrs,_Symbol}, Item) -> - attributes_info(Attrs, Item). - --spec attributes_info(Attributes) -> AttributesInfo when - Attributes :: attributes(), - AttributesInfo :: [AttributeInfoTuple :: attribute_info()]. -attributes_info(Attributes) -> - Items = [column,length,line,text], % undefined order - attributes_info(Attributes, Items). - --spec attributes_info - (Attributes, AttributeItem) -> AttributeInfoTuple | 'undefined' when - Attributes :: attributes(), - AttributeItem :: attribute_item(), - AttributeInfoTuple :: attribute_info(); - (Attributes, AttributeItems) -> AttributeInfo when - Attributes :: attributes(), - AttributeItems :: [AttributeItem :: attribute_item()], - AttributeInfo :: [AttributeInfoTuple :: attribute_info()]. -attributes_info(_Attrs, []) -> - []; -attributes_info(Attrs, [A|As]) when is_atom(A) -> - case attributes_info(Attrs, A) of - undefined -> - attributes_info(Attrs, As); - AttributeInfo when is_tuple(AttributeInfo) -> - [AttributeInfo|attributes_info(Attrs, As)] - end; -attributes_info({Line,Column}, column=Item) when ?ALINE(Line), - ?COLUMN(Column) -> - {Item,Column}; -attributes_info(Line, column) when ?ALINE(Line) -> - undefined; -attributes_info(Attrs, column=Item) -> - case attr_info(Attrs, Item) of - undefined -> - case erl_anno:column(Attrs) of - undefined -> - undefined; - Column -> - {Item,Column} - end; - T -> - T - end; -attributes_info(Attrs, length=Item) -> - case attributes_info(Attrs, text) of - undefined -> - undefined; - {text,Text} -> - {Item,length(Text)} - end; -attributes_info(Line, line=Item) when ?ALINE(Line) -> - {Item,Line}; -attributes_info({Line,Column}, line=Item) when ?ALINE(Line), - ?COLUMN(Column) -> - {Item,Line}; -attributes_info(Attrs, line=Item) -> - case attr_info(Attrs, Item) of - undefined -> - case attr_info(Attrs, location) of - {location,{Line,_Column}} -> - {Item,Line}; - {location,Line} -> - {Item,Line}; - undefined -> - undefined - end; - T -> - T - end; -attributes_info({Line,Column}=Location, location=Item) when ?ALINE(Line), - ?COLUMN(Column) -> - {Item,Location}; -attributes_info(Line, location=Item) when ?ALINE(Line) -> - {Item,Line}; -attributes_info(Attrs, location=Item) -> - {line,Line} = attributes_info(Attrs, line), - case attributes_info(Attrs, column) of - undefined -> - %% If set_attribute() has assigned a term such as {17,42} - %% to 'line', then Line will look like {Line,Column}. One - %% should not use 'location' but 'line' and 'column' in - %% such special cases. - {Item,Line}; - {column,Column} -> - {Item,{Line,Column}} - end; -attributes_info({Line,Column}, text) when ?ALINE(Line), ?COLUMN(Column) -> - undefined; -attributes_info(Line, text) when ?ALINE(Line) -> - undefined; -attributes_info(Attrs, text=Item) -> - attr_info(Attrs, Item); -attributes_info(T1, T2) -> - erlang:error(badarg, [T1,T2]). - --spec set_attribute(AttributeItem, Attributes, SetAttributeFun) -> Attributes when - AttributeItem :: 'line', - Attributes :: attributes(), - SetAttributeFun :: fun((info_line()) -> info_line()). -set_attribute(Tag, Attributes, Fun) when ?SETATTRFUN(Fun) -> - set_attr(Tag, Attributes, Fun). - %%% %%% Local functions %%% @@ -471,62 +304,6 @@ expand_opt(return, Os) -> expand_opt(O, Os) -> [O|Os]. -attr_info(Attrs, Item) -> - try lists:keyfind(Item, 1, Attrs) of - {_Item, _Value} = T -> - T; - false -> - undefined - catch - _:_ -> - erlang:error(badarg, [Attrs, Item]) - end. - --spec set_attr('line', attributes(), fun((line()) -> line())) -> attributes(). - -set_attr(line, Line, Fun) when ?ALINE(Line) -> - Ln = Fun(Line), - if - ?ALINE(Ln) -> - Ln; - true -> - [{line,Ln}] - end; -set_attr(line, {Line,Column}, Fun) when ?ALINE(Line), ?COLUMN(Column) -> - Ln = Fun(Line), - if - ?ALINE(Ln) -> - {Ln,Column}; - true -> - [{line,Ln},{column,Column}] - end; -set_attr(line=Tag, Attrs, Fun) when is_list(Attrs) -> - case lists:keyfind(Tag, 1, Attrs) of - {line,Line} -> - case lists:keyreplace(Tag, 1, Attrs, {line,Fun(Line)}) of - [{line,Ln}] when ?ALINE(Ln) -> - Ln; - As -> - As - end; - false -> - {location, Location} = lists:keyfind(location, 1, Attrs), - Ln = case Location of - {Line,Column} when ?ALINE(Line), ?COLUMN(Column) -> - {Fun(Line),Column}; - _ -> - Fun(Location) - end, - case lists:keyreplace(location, 1, Attrs, {location,Ln}) of - [{location,Ln}] when ?ALINE(Ln) -> - Ln; - As -> - As - end - end; -set_attr(T1, T2, T3) -> - erlang:error(badarg, [T1,T2,T3]). - tokens1(Cs, St, Line, Col, Toks, Fun, Any) when ?STRING(Cs); Cs =:= eof -> case Fun(Cs, St, Line, Col, Toks, Any) of {more,{Cs0,Ncol,Ntoks,Nline,Nany,Nfun}} -> diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl index 48c471924e..fea1656051 100644 --- a/lib/stdlib/src/error_logger_file_h.erl +++ b/lib/stdlib/src/error_logger_file_h.erl @@ -94,14 +94,8 @@ handle_call(filename, #st{filename=File}=State) -> handle_call(_Query, State) -> {ok, {error, bad_query}, State}. -terminate(_Reason, State) -> - case State of - {Fd, _File, _Prev} -> - ok = file:close(Fd); - _ -> - ok - end, - []. +terminate(_Reason, #st{fd=Fd}) -> + file:close(Fd). code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index 41b49f4a86..b8ce311c35 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -38,7 +38,7 @@ -record(state, {file :: file:filename(), module :: module(), forms_or_bin, - source :: source(), + source :: source() | 'undefined', n_errors :: non_neg_integer(), mode :: mode(), exports_main :: boolean(), @@ -49,9 +49,9 @@ -type emu_args() :: string(). -record(sections, {type, - shebang :: shebang(), - comment :: comment(), - emu_args :: emu_args(), + shebang :: shebang() | 'undefined', + comment :: comment() | 'undefined', + emu_args :: emu_args() | 'undefined', body}). -record(extract_options, {compile_source}). diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 2d77888512..90ef364d1a 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -586,49 +586,40 @@ obsolete_1(asn1rt, utf8_list_to_binary, 1) -> %% Added in OTP 18. obsolete_1(core_lib, get_anno, 1) -> - {deprecated,{cerl,get_ann,1}}; + {removed,{cerl,get_ann,1},"19"}; obsolete_1(core_lib, set_anno, 2) -> - {deprecated,{cerl,set_ann,2}}; + {removed,{cerl,set_ann,2},"19"}; obsolete_1(core_lib, is_literal, 1) -> - {deprecated,{cerl,is_literal,1}}; + {removed,{cerl,is_literal,1},"19"}; obsolete_1(core_lib, is_literal_list, 1) -> - {deprecated,"deprecated; use lists:all(fun cerl:is_literal/1, L)" + {removed,"removed; use lists:all(fun cerl:is_literal/1, L)" " instead"}; obsolete_1(core_lib, literal_value, 1) -> - {deprecated,{core_lib,concrete,1}}; + {removed,{core_lib,concrete,1},"19"}; obsolete_1(erl_scan, set_attribute, 3) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:set_line/2 instead"}; + {removed,{erl_anno,set_line,2},"19.0"}; obsolete_1(erl_scan, attributes_info, 1) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_anno:{column,line,location,text}/1 instead"}; obsolete_1(erl_scan, attributes_info, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_anno:{column,line,location,text}/1 instead"}; obsolete_1(erl_scan, token_info, 1) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_scan:{category,column,line,location,symbol,text}/1 instead"}; obsolete_1(erl_scan, token_info, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_scan:{category,column,line,location,symbol,text}/1 instead"}; obsolete_1(erl_parse, set_line, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:set_line/2 instead"}; + {removed,{erl_anno,set_line,2},"19.0"}; obsolete_1(erl_parse, get_attributes, 1) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_anno:{column,line,location,text}/1 instead"}; obsolete_1(erl_parse, get_attribute, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_anno:{column,line,location,text}/1 instead"}; obsolete_1(erl_lint, modify_line, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_parse:map_anno/2 instead"}; + {removed,{erl_parse,map_anno,2},"19.0"}; obsolete_1(ssl, negotiated_next_protocol, 1) -> {deprecated,{ssl,negotiated_protocol,1}}; @@ -698,26 +689,24 @@ is_snmp_agent_function(_, _) -> false. -spec obsolete_type(module(), atom(), arity()) -> 'no' | {tag(), string()} | {tag(), mfas(), release()}. +-dialyzer({no_match, obsolete_type/3}). obsolete_type(Module, Name, NumberOfVariables) -> case obsolete_type_1(Module, Name, NumberOfVariables) of -%% {deprecated=Tag,{_,_,_}=Replacement} -> -%% {Tag,Replacement,"in a future release"}; + {deprecated=Tag,{_,_,_}=Replacement} -> + {Tag,Replacement,"in a future release"}; {_,String}=Ret when is_list(String) -> Ret; -%% {_,_,_}=Ret -> -%% Ret; + {_,_,_}=Ret -> + Ret; no -> no end. obsolete_type_1(erl_scan,column,0) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:column() instead"}; + {removed,{erl_anno,column,0},"19.0"}; obsolete_type_1(erl_scan,line,0) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:line() instead"}; + {removed,{erl_anno,line,0},"19.0"}; obsolete_type_1(erl_scan,location,0) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:location() instead"}; + {removed,{erl_anno,location,0},"19.0"}; obsolete_type_1(_,_,_) -> no. diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl index e5d9fc51d2..80bfe38970 100644 --- a/lib/stdlib/src/re.erl +++ b/lib/stdlib/src/re.erl @@ -132,8 +132,9 @@ split(Subject,RE) -> split(Subject,RE,Options) -> try - {NewOpt,Convert,Unicode,Limit,Strip,Group} = - process_split_params(Options,iodata,false,-1,false,false), + {NewOpt,Convert,Limit,Strip,Group} = + process_split_params(Options,iodata,-1,false,false), + Unicode = check_for_unicode(RE, Options), FlatSubject = to_binary(Subject, Unicode), case compile_split(RE,NewOpt) of {error,_Err} -> @@ -324,8 +325,8 @@ replace(Subject,RE,Replacement) -> replace(Subject,RE,Replacement,Options) -> try - {NewOpt,Convert,Unicode} = - process_repl_params(Options,iodata,false), + {NewOpt,Convert} = process_repl_params(Options,iodata), + Unicode = check_for_unicode(RE, Options), FlatSubject = to_binary(Subject, Unicode), FlatReplacement = to_binary(Replacement, Unicode), IoList = do_replace(FlatSubject,Subject,RE,FlatReplacement,NewOpt), @@ -367,65 +368,59 @@ do_replace(FlatSubject,Subject,RE,Replacement,Options) -> apply_mlist(FlatSubject,Replacement,[Slist]) end. -process_repl_params([],Convert,Unicode) -> - {[],Convert,Unicode}; -process_repl_params([unicode|T],C,_U) -> - {NT,NC,NU} = process_repl_params(T,C,true), - {[unicode|NT],NC,NU}; -process_repl_params([report_errors|_],_,_) -> +process_repl_params([],Convert) -> + {[],Convert}; +process_repl_params([report_errors|_],_) -> throw(badopt); -process_repl_params([{capture,_,_}|_],_,_) -> +process_repl_params([{capture,_,_}|_],_) -> throw(badopt); -process_repl_params([{capture,_}|_],_,_) -> +process_repl_params([{capture,_}|_],_) -> throw(badopt); -process_repl_params([{return,iodata}|T],_C,U) -> - process_repl_params(T,iodata,U); -process_repl_params([{return,list}|T],_C,U) -> - process_repl_params(T,list,U); -process_repl_params([{return,binary}|T],_C,U) -> - process_repl_params(T,binary,U); -process_repl_params([{return,_}|_],_,_) -> +process_repl_params([{return,iodata}|T],_C) -> + process_repl_params(T,iodata); +process_repl_params([{return,list}|T],_C) -> + process_repl_params(T,list); +process_repl_params([{return,binary}|T],_C) -> + process_repl_params(T,binary); +process_repl_params([{return,_}|_],_) -> throw(badopt); -process_repl_params([H|T],C,U) -> - {NT,NC,NU} = process_repl_params(T,C,U), - {[H|NT],NC,NU}. - -process_split_params([],Convert,Unicode,Limit,Strip,Group) -> - {[],Convert,Unicode,Limit,Strip,Group}; -process_split_params([unicode|T],C,_U,L,S,G) -> - {NT,NC,NU,NL,NS,NG} = process_split_params(T,C,true,L,S,G), - {[unicode|NT],NC,NU,NL,NS,NG}; -process_split_params([trim|T],C,U,_L,_S,G) -> - process_split_params(T,C,U,-1,true,G); -process_split_params([{parts,0}|T],C,U,_L,_S,G) -> - process_split_params(T,C,U,-1,true,G); -process_split_params([{parts,N}|T],C,U,_L,_S,G) when is_integer(N), N >= 1 -> - process_split_params(T,C,U,N-1,false,G); -process_split_params([{parts,infinity}|T],C,U,_L,_S,G) -> - process_split_params(T,C,U,-1,false,G); -process_split_params([{parts,_}|_],_,_,_,_,_) -> +process_repl_params([H|T],C) -> + {NT,NC} = process_repl_params(T,C), + {[H|NT],NC}. + +process_split_params([],Convert,Limit,Strip,Group) -> + {[],Convert,Limit,Strip,Group}; +process_split_params([trim|T],C,_L,_S,G) -> + process_split_params(T,C,-1,true,G); +process_split_params([{parts,0}|T],C,_L,_S,G) -> + process_split_params(T,C,-1,true,G); +process_split_params([{parts,N}|T],C,_L,_S,G) when is_integer(N), N >= 1 -> + process_split_params(T,C,N-1,false,G); +process_split_params([{parts,infinity}|T],C,_L,_S,G) -> + process_split_params(T,C,-1,false,G); +process_split_params([{parts,_}|_],_,_,_,_) -> throw(badopt); -process_split_params([group|T],C,U,L,S,_G) -> - process_split_params(T,C,U,L,S,true); -process_split_params([global|_],_,_,_,_,_) -> +process_split_params([group|T],C,L,S,_G) -> + process_split_params(T,C,L,S,true); +process_split_params([global|_],_,_,_,_) -> throw(badopt); -process_split_params([report_errors|_],_,_,_,_,_) -> +process_split_params([report_errors|_],_,_,_,_) -> throw(badopt); -process_split_params([{capture,_,_}|_],_,_,_,_,_) -> +process_split_params([{capture,_,_}|_],_,_,_,_) -> throw(badopt); -process_split_params([{capture,_}|_],_,_,_,_,_) -> +process_split_params([{capture,_}|_],_,_,_,_) -> throw(badopt); -process_split_params([{return,iodata}|T],_C,U,L,S,G) -> - process_split_params(T,iodata,U,L,S,G); -process_split_params([{return,list}|T],_C,U,L,S,G) -> - process_split_params(T,list,U,L,S,G); -process_split_params([{return,binary}|T],_C,U,L,S,G) -> - process_split_params(T,binary,U,L,S,G); -process_split_params([{return,_}|_],_,_,_,_,_) -> +process_split_params([{return,iodata}|T],_C,L,S,G) -> + process_split_params(T,iodata,L,S,G); +process_split_params([{return,list}|T],_C,L,S,G) -> + process_split_params(T,list,L,S,G); +process_split_params([{return,binary}|T],_C,L,S,G) -> + process_split_params(T,binary,L,S,G); +process_split_params([{return,_}|_],_,_,_,_) -> throw(badopt); -process_split_params([H|T],C,U,L,S,G) -> - {NT,NC,NU,NL,NS,NG} = process_split_params(T,C,U,L,S,G), - {[H|NT],NC,NU,NL,NS,NG}. +process_split_params([H|T],C,L,S,G) -> + {NT,NC,NL,NS,NG} = process_split_params(T,C,L,S,G), + {[H|NT],NC,NL,NS,NG}. apply_mlist(Subject,Replacement,Mlist) -> do_mlist(Subject,Subject,0,precomp_repl(Replacement), Mlist). diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index c64123a207..f215a66812 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -23,7 +23,7 @@ -export([whereis_evaluator/0, whereis_evaluator/1]). -export([start_restricted/1, stop_restricted/0]). -export([local_allowed/3, non_local_allowed/3]). --export([prompt_func/1, strings/1]). +-export([catch_exception/1, prompt_func/1, strings/1]). -define(LINEMAX, 30). -define(CHAR_MAX, 60). diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl index 24fc8ce204..4e629a5e56 100644 --- a/lib/stdlib/src/slave.erl +++ b/lib/stdlib/src/slave.erl @@ -289,10 +289,7 @@ register_unique_name(Number) -> %% no need to use rsh. mk_cmd(Host, Name, Args, Waiter, Prog0) -> - Prog = case os:type() of - {ose,_} -> mk_ose_prog(Prog0); - _ -> quote_progname(Prog0) - end, + Prog = quote_progname(Prog0), BasicCmd = lists:concat([Prog, " -detached -noinput -master ", node(), " ", long_or_short(), Name, "@", Host, @@ -312,24 +309,6 @@ mk_cmd(Host, Name, Args, Waiter, Prog0) -> end end. -%% On OSE we have to pass the beam arguments directory to the slave -%% process. To find out what arguments that should be passed on we -%% make an assumption. All arguments after the last "--" should be -%% skipped. So given these arguments: -%% -Muycs256 -A 1 -- -root /mst/ -progname beam.debug.smp -- -home /mst/ -- -kernel inetrc '"/mst/inetrc.conf"' -- -name test@localhost -%% we send -%% -Muycs256 -A 1 -- -root /mst/ -progname beam.debug.smp -- -home /mst/ -- -kernel inetrc '"/mst/inetrc.conf"' -- -%% to the slave with whatever other args that are added in mk_cmd. -mk_ose_prog(Prog) -> - SkipTail = fun("--",[]) -> - ["--"]; - (_,[]) -> - []; - (Arg,Args) -> - [Arg," "|Args] - end, - [Prog,tl(lists:foldr(SkipTail,[],erlang:system_info(emu_args)))]. - %% This is an attempt to distinguish between spaces in the program %% path and spaces that separate arguments. The program is quoted to %% allow spaces in the path. diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src index 4400956943..7f9bbbf649 100644 --- a/lib/stdlib/src/stdlib.app.src +++ b/lib/stdlib/src/stdlib.app.src @@ -105,7 +105,7 @@ dets]}, {applications, [kernel]}, {env, []}, - {runtime_dependencies, ["sasl-2.4","kernel-4.0","erts-7.0","crypto-3.3", + {runtime_dependencies, ["sasl-2.6","kernel-4.1","erts-7.0","crypto-3.3", "compiler-5.0"]} ]}. diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 828e1d9aa4..5f61752655 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -18,7 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}], %% 17.0-17.5 + [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, %% OTP-18.0.* + {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}], %% 17.0-17.5 %% Down to - max one major revision back - [{<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}] %% 17.0-17.5 + [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, %% OTP-18.0.* + {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}] %% 17.0-17.5 }. diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 3c77501c0f..23f3aaee1f 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2014. All Rights Reserved. +%% Copyright Ericsson AB 1996-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -107,11 +107,13 @@ -define(SET, sets:set). -record(state, {name, - strategy :: strategy(), + strategy :: strategy() | 'undefined', children = [] :: [child_rec()], - dynamics :: ?DICT(pid(), list()) | ?SET(pid()), - intensity :: non_neg_integer(), - period :: pos_integer(), + dynamics :: {'dict', ?DICT(pid(), list())} + | {'set', ?SET(pid())} + | 'undefined', + intensity :: non_neg_integer() | 'undefined', + period :: pos_integer() | 'undefined', restarts = [], module, args}). @@ -577,7 +579,7 @@ handle_cast({try_again_restart,Pid}, #state{children=[Child]}=State) when ?is_simple(State) -> RT = Child#child.restart_type, RPid = restarting(Pid), - case dynamic_child_args(RPid, dynamics_db(RT, State#state.dynamics)) of + case dynamic_child_args(RPid, RT, State#state.dynamics) of {ok, Args} -> {M, F, _} = Child#child.mfargs, NChild = Child#child{pid = RPid, mfargs = {M, F, Args}}, @@ -735,7 +737,7 @@ handle_start_child(Child, State) -> restart_child(Pid, Reason, #state{children = [Child]} = State) when ?is_simple(State) -> RestartType = Child#child.restart_type, - case dynamic_child_args(Pid, dynamics_db(RestartType, State#state.dynamics)) of + case dynamic_child_args(Pid, RestartType, State#state.dynamics) of {ok, Args} -> {M, F, _} = Child#child.mfargs, NChild = Child#child{pid = Pid, mfargs = {M, F, Args}}, @@ -812,14 +814,16 @@ restart(simple_one_for_one, Child, State) -> State#state.dynamics)), case do_start_child_i(M, F, A) of {ok, Pid} -> - NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)}, + DynamicsDb = {dict, ?DICTS:store(Pid, A, Dynamics)}, + NState = State#state{dynamics = DynamicsDb}, {ok, NState}; {ok, Pid, _Extra} -> - NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)}, + DynamicsDb = {dict, ?DICTS:store(Pid, A, Dynamics)}, + NState = State#state{dynamics = DynamicsDb}, {ok, NState}; {error, Error} -> - NState = State#state{dynamics = ?DICTS:store(restarting(OldPid), A, - Dynamics)}, + DynamicsDb = {dict, ?DICTS:store(restarting(OldPid), A, Dynamics)}, + NState = State#state{dynamics = DynamicsDb}, report_error(start_error, Error, Child, State#state.name), {try_again, NState} end; @@ -1083,7 +1087,7 @@ wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz, {timeout, TRef, kill} -> ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids), - wait_dynamic_children(Child, Pids, Sz-1, undefined, EStack) + wait_dynamic_children(Child, Pids, Sz, undefined, EStack) end. %%----------------------------------------------------------------- @@ -1102,31 +1106,32 @@ save_child(Child, #state{children = Children} = State) -> State#state{children = [Child |Children]}. save_dynamic_child(temporary, Pid, _, #state{dynamics = Dynamics} = State) -> - State#state{dynamics = ?SETS:add_element(Pid, dynamics_db(temporary, Dynamics))}; + DynamicsDb = dynamics_db(temporary, Dynamics), + State#state{dynamics = {set, ?SETS:add_element(Pid, DynamicsDb)}}; save_dynamic_child(RestartType, Pid, Args, #state{dynamics = Dynamics} = State) -> - State#state{dynamics = ?DICTS:store(Pid, Args, dynamics_db(RestartType, Dynamics))}. + DynamicsDb = dynamics_db(RestartType, Dynamics), + State#state{dynamics = {dict, ?DICTS:store(Pid, Args, DynamicsDb)}}. dynamics_db(temporary, undefined) -> ?SETS:new(); dynamics_db(_, undefined) -> ?DICTS:new(); -dynamics_db(_,Dynamics) -> - Dynamics. - -dynamic_child_args(Pid, Dynamics) -> - case ?SETS:is_set(Dynamics) of - true -> - {ok, undefined}; - false -> - ?DICTS:find(Pid, Dynamics) - end. +dynamics_db(_, {_Tag, DynamicsDb}) -> + DynamicsDb. + +dynamic_child_args(_Pid, temporary, _DynamicsDb) -> + {ok, undefined}; +dynamic_child_args(Pid, _RT, {dict, DynamicsDb}) -> + ?DICTS:find(Pid, DynamicsDb); +dynamic_child_args(_Pid, _RT, undefined) -> + error. state_del_child(#child{pid = Pid, restart_type = temporary}, State) when ?is_simple(State) -> NDynamics = ?SETS:del_element(Pid, dynamics_db(temporary, State#state.dynamics)), - State#state{dynamics = NDynamics}; + State#state{dynamics = {set, NDynamics}}; state_del_child(#child{pid = Pid, restart_type = RType}, State) when ?is_simple(State) -> NDynamics = ?DICTS:erase(Pid, dynamics_db(RType, State#state.dynamics)), - State#state{dynamics = NDynamics}; + State#state{dynamics = {dict, NDynamics}}; state_del_child(Child, State) -> NChildren = del_child(Child#child.name, State#state.children), State#state{children = NChildren}. @@ -1160,19 +1165,19 @@ split_child(_, [], After) -> get_child(Name, State) -> get_child(Name, State, false). + get_child(Pid, State, AllowPid) when AllowPid, is_pid(Pid) -> get_dynamic_child(Pid, State); get_child(Name, State, _) -> lists:keysearch(Name, #child.name, State#state.children). get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) -> - DynamicsDb = dynamics_db(Child#child.restart_type, Dynamics), - case is_dynamic_pid(Pid, DynamicsDb) of + case is_dynamic_pid(Pid, Dynamics) of true -> {value, Child#child{pid=Pid}}; false -> RPid = restarting(Pid), - case is_dynamic_pid(RPid, DynamicsDb) of + case is_dynamic_pid(RPid, Dynamics) of true -> {value, Child#child{pid=RPid}}; false -> @@ -1183,13 +1188,12 @@ get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) -> end end. -is_dynamic_pid(Pid, Dynamics) -> - case ?SETS:is_set(Dynamics) of - true -> - ?SETS:is_element(Pid, Dynamics); - false -> - ?DICTS:is_key(Pid, Dynamics) - end. +is_dynamic_pid(Pid, {dict, Dynamics}) -> + ?DICTS:is_key(Pid, Dynamics); +is_dynamic_pid(Pid, {set, Dynamics}) -> + ?SETS:is_element(Pid, Dynamics); +is_dynamic_pid(_Pid, undefined) -> + false. replace_child(Child, State) -> Chs = do_replace_child(Child, State#state.children), diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl index cca9b967d5..75eebba6c6 100644 --- a/lib/stdlib/test/base64_SUITE.erl +++ b/lib/stdlib/test/base64_SUITE.erl @@ -30,7 +30,8 @@ %% Test cases must be exported. -export([base64_encode/1, base64_decode/1, base64_otp_5635/1, base64_otp_6279/1, big/1, illegal/1, mime_decode/1, - mime_decode_to_string/1, roundtrip/1]). + mime_decode_to_string/1, + roundtrip_1/1, roundtrip_2/1, roundtrip_3/1, roundtrip_4/1]). init_per_testcase(_, Config) -> Dog = test_server:timetrap(?t:minutes(4)), @@ -50,10 +51,11 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [base64_encode, base64_decode, base64_otp_5635, base64_otp_6279, big, illegal, mime_decode, mime_decode_to_string, - roundtrip]. + {group, roundtrip}]. groups() -> - []. + [{roundtrip, [parallel], + [roundtrip_1, roundtrip_2, roundtrip_3, roundtrip_4]}]. init_per_suite(Config) -> Config. @@ -242,21 +244,33 @@ mime_decode_to_string(Config) when is_list(Config) -> %%------------------------------------------------------------------------- -roundtrip(Config) when is_list(Config) -> - Sizes = lists:seq(1, 255) ++ lists:seq(2400-5, 2440), - roundtrip_1(Sizes, []). +roundtrip_1(Config) when is_list(Config) -> + do_roundtrip(1). -roundtrip_1([NextSize|Sizes], Current) -> +roundtrip_2(Config) when is_list(Config) -> + do_roundtrip(2). + +roundtrip_3(Config) when is_list(Config) -> + do_roundtrip(3). + +roundtrip_4(Config) when is_list(Config) -> + do_roundtrip(4). + +do_roundtrip(Offset) -> + Sizes = lists:seq(Offset, 255, 4) ++ lists:seq(2400-6+Offset, 2440, 4), + do_roundtrip_1(Sizes, []). + +do_roundtrip_1([NextSize|Sizes], Current) -> Len = length(Current), io:format("~p", [Len]), - do_roundtrip(Current), + do_roundtrip_2(Current), Next = random_byte_list(NextSize - Len, Current), - roundtrip_1(Sizes, Next); -roundtrip_1([], Last) -> + do_roundtrip_1(Sizes, Next); +do_roundtrip_1([], Last) -> io:format("~p", [length(Last)]), - do_roundtrip(Last). + do_roundtrip_2(Last). -do_roundtrip(List) -> +do_roundtrip_2(List) -> Bin = list_to_binary(List), Base64Bin = base64:encode(List), Base64Bin = base64:encode(Bin), diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index 4e5df661b3..199d2f193d 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -826,14 +826,14 @@ otp_8130(Config) when is_list(Config) -> "-define(a, 3.14).\n" "t() -> ?a.\n"), ?line {ok,Epp} = epp:open(File, []), - ?line ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE', - 'MACHINE','MODULE','MODULE_STRING'] = macs(Epp), + PreDefMacs = macs(Epp), + ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE', + 'MACHINE','MODULE','MODULE_STRING'] = PreDefMacs, ?line {ok,[{'-',_},{atom,_,file}|_]} = epp:scan_erl_form(Epp), ?line {ok,[{'-',_},{atom,_,module}|_]} = epp:scan_erl_form(Epp), ?line {ok,[{atom,_,t}|_]} = epp:scan_erl_form(Epp), ?line {eof,_} = epp:scan_erl_form(Epp), - ?line ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE', - 'MACHINE','MODULE','MODULE_STRING',a] = macs(Epp), + [a] = macs(Epp) -- PreDefMacs, ?line epp:close(Epp), %% escript @@ -1528,8 +1528,11 @@ compile_test(Config, Test0) -> warnings(File, Ws) -> case lists:append([W || {F, W} <- Ws, F =:= File]) of - [] -> []; - L -> {warnings, L} + [] -> + []; + L -> + call_format_error(L), + {warnings, L} end. compile_file(File, Opts) -> @@ -1540,12 +1543,20 @@ compile_file(File, Opts) -> end. errs([{File,Es}|L], File) -> + call_format_error(Es), Es ++ errs(L, File); errs([_|L], File) -> errs(L, File); errs([], _File) -> []. +%% Smoke test and coverage of format_error/1. +call_format_error([{_,M,E}|T]) -> + _ = M:format_error(E), + call_format_error(T); +call_format_error([]) -> + ok. + epp_parse_file(File, Opts) -> case epp:parse_file(File, Opts) of {ok, Forms} -> diff --git a/lib/stdlib/test/erl_anno_SUITE.erl b/lib/stdlib/test/erl_anno_SUITE.erl index 66b02151a0..0369455846 100644 --- a/lib/stdlib/test/erl_anno_SUITE.erl +++ b/lib/stdlib/test/erl_anno_SUITE.erl @@ -34,7 +34,7 @@ init_per_testcase/2, end_per_testcase/2]). -export([new/1, is_anno/1, generated/1, end_location/1, file/1, - line/1, location/1, record/1, text/1, bad/1, neg_line/1]). + line/1, location/1, record/1, text/1, bad/1]). -export([parse_abstract/1, mapfold_anno/1]). @@ -43,7 +43,7 @@ all() -> groups() -> [{anno, [], [new, is_anno, generated, end_location, file, - line, location, record, text, bad, neg_line]}, + line, location, record, text, bad]}, {parse, [], [parse_abstract, mapfold_anno]}]. suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -229,74 +229,6 @@ bad(_Config) -> (catch erl_anno:record(bad)), % 1st arg not opaque ok. -neg_line(doc) -> - ["Test negative line numbers (OTP 18)"]; -neg_line(_Config) -> - neg_line1(false), - neg_line1(true), - ok. - -neg_line1(TextToo) -> - Minus8_0 = erl_anno:new(-8), - Plus8_0 = erl_anno:new(8), - Minus8C_0 = erl_anno:new({-8, 17}), - Plus8C_0 = erl_anno:new({8, 17}), - - [Minus8, Plus8, Minus8C, Plus8C] = - [case TextToo of - true -> - erl_anno:set_text("foo", A); - false -> - A - end || A <- [Minus8_0, Plus8_0, Minus8C_0, Plus8C_0]], - - tst(-3, erl_anno:set_location(3, Minus8)), - tst(-3, erl_anno:set_location(-3, Plus8)), - tst(-3, erl_anno:set_location(-3, Minus8)), - tst({-3,9}, erl_anno:set_location({3, 9}, Minus8)), - tst({-3,9}, erl_anno:set_location({-3, 9}, Plus8)), - tst({-3,9}, erl_anno:set_location({-3, 9}, Minus8)), - tst(-3, erl_anno:set_location(3, Minus8C)), - tst(-3, erl_anno:set_location(-3, Plus8C)), - tst(-3, erl_anno:set_location(-3, Minus8C)), - tst({-3,9}, erl_anno:set_location({3, 9}, Minus8C)), - tst({-3,9}, erl_anno:set_location({-3, 9}, Plus8C)), - tst({-3,9}, erl_anno:set_location({-3, 9}, Minus8C)), - - tst(-8, erl_anno:set_generated(true, Plus8)), - tst(-8, erl_anno:set_generated(true, Minus8)), - tst({-8,17}, erl_anno:set_generated(true, Plus8C)), - tst({-8,17}, erl_anno:set_generated(true, Minus8C)), - tst(8, erl_anno:set_generated(false, Plus8)), - tst(8, erl_anno:set_generated(false, Minus8)), - tst({8,17}, erl_anno:set_generated(false, Plus8C)), - tst({8,17}, erl_anno:set_generated(false, Minus8C)), - - tst(-3, erl_anno:set_line(3, Minus8)), - tst(-3, erl_anno:set_line(-3, Plus8)), - tst(-3, erl_anno:set_line(-3, Minus8)), - tst({-3,17}, erl_anno:set_line(3, Minus8C)), - tst({-3,17}, erl_anno:set_line(-3, Plus8C)), - tst({-3,17}, erl_anno:set_line(-3, Minus8C)), - ok. - -tst(Term, Anno) -> - ?format("Term: ~p\n", [Term]), - ?format("Anno: ~p\n", [Anno]), - case anno_to_term(Anno) of - Term -> - ok; - Else -> - case lists:keyfind(location, 1, Else) of - {location, Term} -> - ok; - _Else2 -> - ?format("Else2 ~p\n", [_Else2]), - io:format("expected ~p\n got ~p\n", [Term, Else]), - exit({Term, Else}) - end - end. - parse_abstract(doc) -> ["Test erl_parse:new_anno/1, erl_parse:anno_to_term/1" ", and erl_parse:anno_from_term/1"]; diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 0424e2b967..6c07dc1ec6 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -65,7 +65,7 @@ too_many_arguments/1, basic_errors/1,bin_syntax_errors/1, predef/1, - maps/1,maps_type/1,otp_11851/1,otp_12195/1 + maps/1,maps_type/1,otp_11851/1 ]). % Default timetrap timeout (set in init_per_testcase). @@ -94,7 +94,7 @@ all() -> bif_clash, behaviour_basic, behaviour_multiple, otp_11861, otp_7550, otp_8051, format_warn, {group, on_load}, too_many_arguments, basic_errors, bin_syntax_errors, predef, - maps, maps_type, otp_11851, otp_12195]. + maps, maps_type, otp_11851]. groups() -> [{unused_vars_warn, [], @@ -3835,40 +3835,6 @@ otp_11851(Config) when is_list(Config) -> [] = run(Config, Ts), ok. -otp_12195(doc) -> - "OTP-12195: Check obsolete types (tailor made for OTP 18)."; -otp_12195(Config) when is_list(Config) -> - Ts = [{otp_12195_1, - <<"-export_type([r1/0]). - -type r1() :: erl_scan:line() - | erl_scan:column() - | erl_scan:location() - | erl_anno:line().">>, - [], - {warnings,[{2,erl_lint, - {deprecated_type,{erl_scan,line,0}, - "deprecated (will be removed in OTP 19); " - "use erl_anno:line() instead"}}, - {3,erl_lint, - {deprecated_type,{erl_scan,column,0}, - "deprecated (will be removed in OTP 19); use " - "erl_anno:column() instead"}}, - {4,erl_lint, - {deprecated_type,{erl_scan,location,0}, - "deprecated (will be removed in OTP 19); " - "use erl_anno:location() instead"}}]}}, - {otp_12195_2, - <<"-export_type([r1/0]). - -compile(nowarn_deprecated_type). - -type r1() :: erl_scan:line() - | erl_scan:column() - | erl_scan:location() - | erl_anno:line().">>, - [], - []}], - [] = run(Config, Ts), - ok. - run(Config, Tests) -> F = fun({N,P,Ws,E}, BadL) -> case catch run_test(Config, P, Ws) of diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index 389fd059f6..9bb193d865 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -928,7 +928,9 @@ otp_8522(Config) when is_list(Config) -> ?line {ok, _} = compile:file(FileName, [{outdir,?privdir},debug_info]), BF = filename("otp_8522", Config), ?line {ok, A} = beam_lib:chunks(BF, [abstract_code]), - ?line 5 = count_atom(A, undefined), + %% OTP-12719: Since 'undefined' is no longer added by the Erlang + %% Parser, the number of 'undefined' is 4. It used to be 5. + ?line 4 = count_atom(A, undefined), ok. count_atom(A, A) -> @@ -1062,7 +1064,7 @@ otp_9147(Config) when is_list(Config) -> ?line {ok, Bin} = file:read_file(PFileName), %% The parentheses around "F1 :: a | b" are new (bugfix). ?line true = - lists:member("-record(undef,{f1 :: undefined | (F1 :: a | b)}).", + lists:member("-record(undef,{f1 :: F1 :: a | b}).", string:tokens(binary_to_list(Bin), "\n")), ok. diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl index 12ea3d128c..db669aae99 100644 --- a/lib/stdlib/test/erl_scan_SUITE.erl +++ b/lib/stdlib/test/erl_scan_SUITE.erl @@ -191,8 +191,7 @@ otp_7810(Config) when is_list(Config) -> ?line ok = more_chars(), ?line ok = more_options(), - ?line ok = attributes_info(), - ?line ok = set_attribute(), + ?line ok = anno_info(), ok. @@ -269,7 +268,7 @@ punctuations() -> comments() -> ?line test("a %%\n b"), - {ok,[],1} = erl_scan_string("%"), + ?line {ok,[],1} = erl_scan_string("%"), ?line test("a %%\n b"), {ok,[{atom,{1,1},a},{atom,{2,2},b}],{2,3}} = erl_scan_string("a %%\n b", {1,1}), @@ -338,7 +337,7 @@ base_integers() -> erl_scan:string(Str) end || {BS,S} <- [{"3","3"},{"15","f"}, {"12","c"}] ], - {ok,[{integer,1,239},{'@',1}],1} = erl_scan_string("16#ef@"), + ?line {ok,[{integer,1,239},{'@',1}],1} = erl_scan_string("16#ef@"), {ok,[{integer,{1,1},239},{'@',{1,6}}],{1,7}} = erl_scan_string("16#ef@", {1,1}, []), {ok,[{integer,{1,1},14},{atom,{1,5},g@}],{1,7}} = @@ -387,20 +386,15 @@ dots() -> R2 = erl_scan_string(S, {1,1}, []) end || {S, R, R2} <- Dot], - ?line {ok,[{dot,_}=T1],{1,2}} = erl_scan:string(".", {1,1}, text), - ?line [{column,1},{length,1},{line,1},{text,"."}] = - erl_scan:token_info(T1, [column, length, line, text]), - ?line {ok,[{dot,_}=T2],{1,3}} = erl_scan:string(".%", {1,1}, text), - ?line [{column,1},{length,1},{line,1},{text,"."}] = - erl_scan:token_info(T2, [column, length, line, text]), - ?line {ok,[{dot,_}=T3],{1,6}} = + {ok,[{dot,_}=T1],{1,2}} = erl_scan:string(".", {1,1}, text), + [1, 1, "."] = token_info(T1), + {ok,[{dot,_}=T2],{1,3}} = erl_scan:string(".%", {1,1}, text), + [1, 1, "."] = token_info(T2), + {ok,[{dot,_}=T3],{1,6}} = erl_scan:string(".% öh", {1,1}, text), - ?line [{column,1},{length,1},{line,1},{text,"."}] = - erl_scan:token_info(T3, [column, length, line, text]), - ?line {error,{{1,2},erl_scan,char},{1,3}} = - erl_scan:string(".$", {1,1}), - ?line {error,{{1,2},erl_scan,char},{1,4}} = - erl_scan:string(".$\\", {1,1}), + [1, 1, "."] = token_info(T3), + {error,{{1,2},erl_scan,char},{1,3}} = erl_scan:string(".$", {1,1}), + {error,{{1,2},erl_scan,char},{1,4}} = erl_scan:string(".$\\", {1,1}), test_string(". ", [{dot,{1,1}}]), test_string(". ", [{dot,{1,1}}]), @@ -413,18 +407,18 @@ dots() -> test_string(".a", [{'.',{1,1}},{atom,{1,2},a}]), test_string("%. \n. ", [{dot,{2,1}}]), - ?line {more,C} = erl_scan:tokens([], "%. ",{1,1}, return), + {more,C} = erl_scan:tokens([], "%. ",{1,1}, return), {done,{ok,[{comment,{1,1},"%. "}, {white_space,{1,4},"\n"}, {dot,{2,1}}], {2,3}}, ""} = erl_scan_tokens(C, "\n. ", {1,1}, return), % any loc, any options - ?line [test_string(S, R) || - {S, R} <- [{".$\n", [{'.',{1,1}},{char,{1,2},$\n}]}, - {"$\\\n", [{char,{1,1},$\n}]}, - {"'\\\n'", [{atom,{1,1},'\n'}]}, - {"$\n", [{char,{1,1},$\n}]}] ], + [test_string(S, R) || + {S, R} <- [{".$\n", [{'.',{1,1}},{char,{1,2},$\n}]}, + {"$\\\n", [{char,{1,1},$\n}]}, + {"'\\\n'", [{atom,{1,1},'\n'}]}, + {"$\n", [{char,{1,1},$\n}]}] ], ok. chars() -> @@ -540,8 +534,8 @@ eof() -> %% A dot followed by eof is special: ?line {more, C} = erl_scan:tokens([], "a.", 1), - {done,{ok,[{atom,1,a},{dot,1}],1},eof} = erl_scan_tokens(C,eof,1), - {ok,[{atom,1,foo},{dot,1}],1} = erl_scan_string("foo."), + ?line {done,{ok,[{atom,1,a},{dot,1}],1},eof} = erl_scan_tokens(C,eof,1), + ?line {ok,[{atom,1,foo},{dot,1}],1} = erl_scan_string("foo."), %% With column. {more, CCol} = erl_scan:tokens([], "a.", {1,1}), @@ -655,145 +649,72 @@ options() -> ok. more_options() -> - ?line {ok,[{atom,A1,foo}],{19,20}} = + {ok,[{atom,_,foo}=T1],{19,20}} = erl_scan:string("foo", {19,17},[]), - ?line [{column,17},{line,19}] = erl_scan:attributes_info(A1), - ?line {done,{ok,[{atom,A2,foo},{dot,_}],{19,22}},[]} = + {19,17} = erl_scan:location(T1), + {done,{ok,[{atom,_,foo}=T2,{dot,_}],{19,22}},[]} = erl_scan:tokens([], "foo. ", {19,17}, [bad_opt]), % type error - ?line [{column,17},{line,19}] = erl_scan:attributes_info(A2), - ?line {ok,[{atom,A3,foo}],{19,20}} = + {19,17} = erl_scan:location(T2), + {ok,[{atom,_,foo}=T3],{19,20}} = erl_scan:string("foo", {19,17},[text]), - ?line [{column,17},{length,3},{line,19},{text,"foo"}] = - erl_scan:attributes_info(A3), + {19,17} = erl_scan:location(T3), + "foo" = erl_scan:text(T3), - ?line {ok,[{atom,A4,foo}],1} = erl_scan:string("foo", 1, [text]), - ?line [{length,3},{line,1},{text,"foo"}] = erl_scan:attributes_info(A4), + {ok,[{atom,_,foo}=T4],1} = erl_scan:string("foo", 1, [text]), + 1 = erl_scan:line(T4), + 1 = erl_scan:location(T4), + "foo" = erl_scan:text(T4), ok. token_info() -> - ?line {ok,[T1],_} = erl_scan:string("foo", {1,18}, [text]), + {ok,[T1],_} = erl_scan:string("foo", {1,18}, [text]), {'EXIT',{badarg,_}} = - (catch {foo, erl_scan:token_info(T1, foo)}), % type error - ?line {line,1} = erl_scan:token_info(T1, line), - ?line {column,18} = erl_scan:token_info(T1, column), - ?line {length,3} = erl_scan:token_info(T1, length), - ?line {text,"foo"} = erl_scan:token_info(T1, text), - ?line [{category,atom},{column,18},{length,3},{line,1}, - {symbol,foo},{text,"foo"}] = - erl_scan:token_info(T1), - ?line [{length,3},{column,18}] = - erl_scan:token_info(T1, [length, column]), - ?line [{location,{1,18}}] = - erl_scan:token_info(T1, [location]), - ?line {category,atom} = erl_scan:token_info(T1, category), - ?line [{symbol,foo}] = erl_scan:token_info(T1, [symbol]), - - ?line {ok,[T2],_} = erl_scan:string("foo", 1, []), - ?line {line,1} = erl_scan:token_info(T2, line), - ?line undefined = erl_scan:token_info(T2, column), - ?line undefined = erl_scan:token_info(T2, length), - ?line undefined = erl_scan:token_info(T2, text), - ?line {location,1} = erl_scan:token_info(T2, location), - ?line [{category,atom},{line,1},{symbol,foo}] = erl_scan:token_info(T2), - ?line [{line,1}] = erl_scan:token_info(T2, [length, line]), - - ?line {ok,[T3],_} = erl_scan:string("=", 1, []), - ?line [{line,1}] = erl_scan:token_info(T3, [column, line]), - ?line {category,'='} = erl_scan:token_info(T3, category), - ?line [{symbol,'='}] = erl_scan:token_info(T3, [symbol]), + (catch {foo, erl_scan:category(foo)}), % type error + {'EXIT',{badarg,_}} = + (catch {foo, erl_scan:symbol(foo)}), % type error + atom = erl_scan:category(T1), + foo = erl_scan:symbol(T1), + + {ok,[T2],_} = erl_scan:string("foo", 1, []), + 1 = erl_scan:line(T2), + undefined = erl_scan:column(T2), + undefined = erl_scan:text(T2), + 1 = erl_scan:location(T2), + + {ok,[T3],_} = erl_scan:string("=", 1, []), + '=' = erl_scan:category(T3), + '=' = erl_scan:symbol(T3), ok. -attributes_info() -> - ?line {'EXIT',_} = - (catch {foo,erl_scan:attributes_info(foo)}), % type error - [{line,18}] = erl_scan:attributes_info(erl_anno:new(18)), - {location,19} = - erl_scan:attributes_info(erl_anno:new(19), location), - ?line {ok,[{atom,A0,foo}],_} = erl_scan:string("foo", 19, [text]), - ?line {location,19} = erl_scan:attributes_info(A0, location), - - ?line {ok,[{atom,A3,foo}],_} = erl_scan:string("foo", {1,3}, [text]), - ?line {line,1} = erl_scan:attributes_info(A3, line), - ?line {column,3} = erl_scan:attributes_info(A3, column), - ?line {location,{1,3}} = erl_scan:attributes_info(A3, location), - ?line {text,"foo"} = erl_scan:attributes_info(A3, text), - - ?line {ok,[{atom,A4,foo}],_} = erl_scan:string("foo", 2, [text]), - ?line {line,2} = erl_scan:attributes_info(A4, line), - ?line undefined = erl_scan:attributes_info(A4, column), - ?line {location,2} = erl_scan:attributes_info(A4, location), - ?line {text,"foo"} = erl_scan:attributes_info(A4, text), - - ?line {ok,[{atom,A5,foo}],_} = erl_scan:string("foo", {1,3}, []), - ?line {line,1} = erl_scan:attributes_info(A5, line), - ?line {column,3} = erl_scan:attributes_info(A5, column), - ?line {location,{1,3}} = erl_scan:attributes_info(A5, location), - ?line undefined = erl_scan:attributes_info(A5, text), - - ?line undefined = erl_scan:attributes_info([], line), % type error +anno_info() -> + {'EXIT',_} = + (catch {foo,erl_scan:line(foo)}), % type error + {ok,[{atom,_,foo}=T0],_} = erl_scan:string("foo", 19, [text]), + 19 = erl_scan:location(T0), + 19 = erl_scan:end_location(T0), + + {ok,[{atom,_,foo}=T3],_} = erl_scan:string("foo", {1,3}, [text]), + 1 = erl_scan:line(T3), + 3 = erl_scan:column(T3), + {1,3} = erl_scan:location(T3), + {1,6} = erl_scan:end_location(T3), + "foo" = erl_scan:text(T3), + + {ok,[{atom,_,foo}=T4],_} = erl_scan:string("foo", 2, [text]), + 2 = erl_scan:line(T4), + undefined = erl_scan:column(T4), + 2 = erl_scan:location(T4), + "foo" = erl_scan:text(T4), + + {ok,[{atom,_,foo}=T5],_} = erl_scan:string("foo", {1,3}, []), + 1 = erl_scan:line(T5), + 3 = erl_scan:column(T5), + {1,3} = erl_scan:location(T5), + undefined = erl_scan:text(T5), ok. -set_attribute() -> - F = fun(Line) -> -Line end, - Anno2 = erl_anno:new(2), - A0 = erl_scan:set_attribute(line, Anno2, F), - {line, -2} = erl_scan:attributes_info(A0, line), - ?line {ok,[{atom,A1,foo}],_} = erl_scan:string("foo", {9,17}), - ?line A2 = erl_scan:set_attribute(line, A1, F), - ?line {line,-9} = erl_scan:attributes_info(A2, line), - ?line {location,{-9,17}} = erl_scan:attributes_info(A2, location), - ?line [{line,-9},{column,17}] = - erl_scan:attributes_info(A2, [line,column,text]), - - F2 = fun(Line) -> {17,Line} end, - ?line Attr1 = erl_scan:set_attribute(line, 2, F2), - ?line {line,{17,2}} = erl_scan:attributes_info(Attr1, line), - ?line undefined = erl_scan:attributes_info(Attr1, column), - ?line {location,{17,2}} = % a bit mixed up - erl_scan:attributes_info(Attr1, location), - - ?line A3 = erl_scan:set_attribute(line, A1, F2), - ?line {line,{17,9}} = erl_scan:attributes_info(A3, line), - ?line {location,{{17,9},17}} = erl_scan:attributes_info(A3, location), - ?line [{line,{17,9}},{column,17}] = - erl_scan:attributes_info(A3, [line,column,text]), - - ?line {ok,[{atom,A4,foo}],_} = erl_scan:string("foo", {9,17}, [text]), - ?line A5 = erl_scan:set_attribute(line, A4, F), - ?line {line,-9} = erl_scan:attributes_info(A5, line), - ?line {location,{-9,17}} = erl_scan:attributes_info(A5, location), - ?line [{line,-9},{column,17},{text,"foo"}] = - erl_scan:attributes_info(A5, [line,column,text]), - - ?line {ok,[{atom,A6,foo}],_} = erl_scan:string("foo", 11, [text]), - ?line A7 = erl_scan:set_attribute(line, A6, F2), - %% Incompatible with pre 18: - %% {line,{17,11}} = erl_scan:attributes_info(A7, line), - {line,17} = erl_scan:attributes_info(A7, line), - ?line {location,{17,11}} = % mixed up - erl_scan:attributes_info(A7, location), - %% Incompatible with pre 18: - %% [{line,{17,11}},{text,"foo"}] = - %% erl_scan:attributes_info(A7, [line,column,text]), - [{line,17},{column,11},{text,"foo"}] = - erl_scan:attributes_info(A7, [line,column,text]), - - ?line {'EXIT',_} = - (catch {foo, erl_scan:set_attribute(line, [], F2)}), % type error - ?line {'EXIT',{badarg,_}} = - (catch {foo, erl_scan:set_attribute(column, [], F2)}), % type error - - Attr10 = erl_anno:new(8), - Attr20 = erl_scan:set_attribute(line, Attr10, - fun(L) -> {nos,'X',L} end), - %% OTP-9412 - Attr30 = erl_scan:set_attribute(line, Attr20, - fun({nos,_V,VL}) -> VL end), - 8 = erl_anno:to_term(Attr30), - ok. - column_errors() -> ?line {error,{{1,1},erl_scan,{string,$',""}},{1,3}} = % $' erl_scan:string("'\\",{1,1}), @@ -892,14 +813,13 @@ unicode() -> erl_scan_string(Qs, 1), {ok,[Q2],{1,9}} = erl_scan:string("$\\x{aaa}", {1,1}, [text]), - [{category,char},{column,1},{length,8}, - {line,1},{symbol,16#aaa},{text,Qs}] = - erl_scan:token_info(Q2), + [{category,char},{column,1},{line,1},{symbol,16#aaa},{text,Qs}] = + token_info_long(Q2), U1 = "\"\\x{aaa}\"", - {ok,[{string,A1,[2730]}],{1,10}} = erl_scan:string(U1, {1,1}, [text]), - [{line,1},{column,1},{text,"\"\\x{aaa}\""}] = - erl_scan:attributes_info(A1, [line, column, text]), + {ok,[{string,_,[2730]}=T1],{1,10}} = erl_scan:string(U1, {1,1}, [text]), + {1,1} = erl_scan:location(T1), + "\"\\x{aaa}\"" = erl_scan:text(T1), {ok,[{string,1,[2730]}],1} = erl_scan_string(U1, 1), U2 = "\"\\x41\\x{fff}\\x42\"", @@ -1012,16 +932,13 @@ otp_10302(Config) when is_list(Config) -> Qs = "$\\x{aaa}", {ok,[{char,1,2730}],1} = erl_scan_string(Qs, 1), {ok,[Q2],{1,9}} = erl_scan:string(Qs,{1,1},[text]), - [{category,char},{column,1},{length,8}, - {line,1},{symbol,16#aaa},{text,Qs}] = - erl_scan:token_info(Q2), - - Tags = [category, column, length, line, symbol, text], + [{category,char},{column,1},{line,1},{symbol,16#aaa},{text,Qs}] = + token_info_long(Q2), U1 = "\"\\x{aaa}\"", {ok,[T1],{1,10}} = erl_scan:string(U1, {1,1}, [text]), - [{category,string},{column,1},{length,9},{line,1}, - {symbol,[16#aaa]},{text,U1}] = erl_scan:token_info(T1, Tags), + [{category,string},{column,1},{line,1},{symbol,[16#aaa]},{text,U1}] = + token_info_long(T1), U2 = "\"\\x41\\x{fff}\\x42\"", {ok,[{string,1,[65,4095,66]}],1} = erl_scan_string(U2, 1), @@ -1353,9 +1270,7 @@ test_wsc([], []) -> ok; test_wsc([Token|Tokens], [Token2|Tokens2]) -> [Text, Text2] = [Text || - {text, Text} <- - [erl_scan:token_info(T, text) || - T <- [Token, Token2]]], + Text <- [erl_scan:text(T) || T <- [Token, Token2]]], Sz = erts_debug:size(Text), Sz2 = erts_debug:size({Text, Text2}), IsCompacted = Sz2 < 2*Sz+erts_debug:size({a,a}), @@ -1394,7 +1309,7 @@ all_same(L, Char) -> newlines_first([]) -> ok; newlines_first([Token|Tokens]) -> - {text,Text} = erl_scan:token_info(Token, text), + Text = erl_scan:text(Token), Nnls = length([C || C <- Text, C =:= $\n]), OK = case Text of [$\n|_] -> @@ -1414,7 +1329,7 @@ select_tokens(Tokens, Tags) -> lists:filter(fun(T) -> lists:member(element(1, T), Tags) end, Tokens). simplify([Token|Tokens]) -> - {line,Line} = erl_scan:token_info(Token, line), + Line = erl_scan:line(Token), [setelement(2, Token, erl_anno:new(Line)) | simplify(Tokens)]; simplify([]) -> []. @@ -1423,17 +1338,31 @@ get_text(Tokens) -> lists:flatten( [T || Token <- Tokens, - ({text,T} = erl_scan:token_info(Token, text)) =/= []]). + (T = erl_scan:text(Token)) =/= []]). test_decorated_tokens(String, Tokens) -> ToksAttrs = token_attrs(Tokens), test_strings(ToksAttrs, String, 1, 1). token_attrs(Tokens) -> - [{L,C,Len,T} || + [{L,C,length(T),T} || Token <- Tokens, - ([{line,L},{column,C},{length,Len},{text,T}] = - erl_scan:token_info(Token, [line,column,length,text])) =/= []]. + ([C,L,T] = token_info(Token)) =/= []]. + +token_info(T) -> + Column = erl_scan:column(T), + Line = erl_scan:line(T), + Text = erl_scan:text(T), + [Column, Line, Text]. + +token_info_long(T) -> + Column = erl_scan:column(T), + Line = erl_scan:line(T), + Text = erl_scan:text(T), + Category = erl_scan:category(T), + Symbol = erl_scan:symbol(T), + [{category,Category},{column,Column},{line,Line}, + {symbol,Symbol},{text,Text}]. test_strings([], _S, Line, Column) -> {Line,Column}; @@ -1514,8 +1443,7 @@ consistent_attributes([Ts | TsL]) -> L = [T || T <- Ts, is_integer(element(2, T))], case L of [] -> - TagsL = [[Tag || {Tag,_} <- - erl_scan:attributes_info(element(2, T))] || + TagsL = [[Tag || {Tag,_} <- defined(token_info_long(T))] || T <- Ts], case lists:usort(TagsL) of [_] -> @@ -1531,6 +1459,9 @@ consistent_attributes([Ts | TsL]) -> Ts end. +defined(L) -> + [{T,V} || {T,V} <- L, V =/= undefined]. + family_list(L) -> sofs:to_external(family(L)). diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl index b0b9c717a1..c82b1b62ef 100644 --- a/lib/stdlib/test/error_logger_h_SUITE.erl +++ b/lib/stdlib/test/error_logger_h_SUITE.erl @@ -65,6 +65,12 @@ logfile(Config) -> error_logger:logfile(close), analyse_events(Log, Ev, [AtNode], unlimited), + [] = [{X, file:pid2name(X)} || X <- processes(), Data <- [process_info(X, [current_function])], + Data =/= undefined, + element(1, element(2, lists:keyfind(current_function, 1, Data))) + =:= file_io_server, + file:pid2name(X) =:= {ok, Log}], + test_server:stop_node(Node), cleanup(Log), diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index ae431d66d9..1b80f555d7 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -731,10 +731,6 @@ chk_normal_tab_struct_size() -> % ?line ok % end. --define(DB_TREE_STACK_NEED,50). % The static stack for a tree, in halfword pointers are two internal words - % so the stack gets twice as big --define(DB_HASH_SIZEOF_EXTSEG,260). % The segment size in words, in halfword this will be twice as large. - adjust_xmem([T1,T2,T3,T4], {A0,B0,C0,D0} = _Mem0) -> %% Adjust for 64-bit, smp, and os: %% Table struct size may differ. @@ -748,19 +744,7 @@ adjust_xmem([T1,T2,T3,T4], {A0,B0,C0,D0} = _Mem0) -> % end, TabDiff = ?TAB_STRUCT_SZ, - Mem1 = {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff}, - - case {erlang:system_info({wordsize,internal}),erlang:system_info({wordsize,external})} of - %% Halfword, corrections for regular pointers occupying two internal words. - {4,8} -> - {A1,B1,C1,D1} = Mem1, - {A1+4*ets:info(T1, size)+?DB_TREE_STACK_NEED, - B1+3*ets:info(T2, size)+?DB_HASH_SIZEOF_EXTSEG, - C1+3*ets:info(T3, size)+?DB_HASH_SIZEOF_EXTSEG, - D1+3*ets:info(T4, size)+?DB_HASH_SIZEOF_EXTSEG}; - _ -> - Mem1 - end. + {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff}. t_whitebox(doc) -> ["Diverse whitebox testes"]; diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl index fd47da8150..4372e77df9 100644 --- a/lib/stdlib/test/filename_SUITE.erl +++ b/lib/stdlib/test/filename_SUITE.erl @@ -97,20 +97,11 @@ absname(Config) when is_list(Config) -> ?line file:set_cwd(Cwd), ok; - Type -> - case Type of - {unix, _} -> - ?line ok = file:set_cwd("/usr"), - ?line "/usr/foo" = filename:absname(foo), - ?line "/usr/foo" = filename:absname("foo"), - ?line "/usr/../ebin" = filename:absname("../ebin"); - {ose, _} -> - ?line ok = file:set_cwd("/romfs"), - ?line "/romfs/foo" = filename:absname(foo), - ?line "/romfs/foo" = filename:absname("foo"), - ?line "/romfs/../ebin" = filename:absname("../ebin") - end, - + {unix, _} -> + ?line ok = file:set_cwd("/usr"), + ?line "/usr/foo" = filename:absname(foo), + ?line "/usr/foo" = filename:absname("foo"), + ?line "/usr/../ebin" = filename:absname("../ebin"), ?line file:set_cwd("/"), ?line "/foo" = filename:absname(foo), ?line "/foo" = filename:absname("foo"), @@ -494,18 +485,10 @@ absname_bin(Config) when is_list(Config) -> ?line file:set_cwd(Cwd), ok; - Type -> - case Type of - {unix,_} -> - ?line ok = file:set_cwd(<<"/usr">>), - ?line <<"/usr/foo">> = filename:absname(<<"foo">>), - ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>); - {ose,_} -> - ?line ok = file:set_cwd(<<"/romfs">>), - ?line <<"/romfs/foo">> = filename:absname(<<"foo">>), - ?line <<"/romfs/../ebin">> = filename:absname(<<"../ebin">>) - end, - + {unix, _} -> + ?line ok = file:set_cwd(<<"/usr">>), + ?line <<"/usr/foo">> = filename:absname(<<"foo">>), + ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>), ?line file:set_cwd(<<"/">>), ?line <<"/foo">> = filename:absname(<<"foo">>), ?line <<"/../ebin">> = filename:absname(<<"../ebin">>), diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl index 7a6fcba4e5..b019f98b69 100644 --- a/lib/stdlib/test/gen_event_SUITE.erl +++ b/lib/stdlib/test/gen_event_SUITE.erl @@ -412,7 +412,6 @@ notify(Config) when is_list(Config) -> ok end, ?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:notify(my_dummy_handler, Event), ?line receive @@ -445,7 +444,6 @@ notify(Config) when is_list(Config) -> end, ?line ok = gen_event:notify(my_dummy_handler, {swap_event, {dummy1_h, 9}, swap}), - ?t:sleep(1000), ?line [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:notify(my_dummy_handler, Event), ?line receive @@ -485,7 +483,6 @@ notify(Config) when is_list(Config) -> ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), ?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:notify(my_dummy_handler, do_crash), @@ -496,7 +493,6 @@ notify(Config) when is_list(Config) -> ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), ?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:notify(my_dummy_handler, delete_event), @@ -529,7 +525,6 @@ sync_notify(Config) when is_list(Config) -> end, ?line ok = gen_event:sync_notify(my_dummy_handler, {swap_event, dummy1_h, swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:sync_notify(my_dummy_handler, Event), ?line receive @@ -562,7 +557,6 @@ sync_notify(Config) when is_list(Config) -> end, ?line ok = gen_event:sync_notify(my_dummy_handler, {swap_event, {dummy1_h, 9}, swap}), - ?t:sleep(1000), ?line [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:sync_notify(my_dummy_handler, Event), ?line receive @@ -603,7 +597,6 @@ sync_notify(Config) when is_list(Config) -> ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), ?line ok = gen_event:sync_notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:sync_notify(my_dummy_handler, do_crash), @@ -615,7 +608,6 @@ sync_notify(Config) when is_list(Config) -> ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), ?line ok = gen_event:sync_notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:sync_notify(my_dummy_handler, delete_event), @@ -789,7 +781,6 @@ info(Config) when is_list(Config) -> ok end, ?line my_dummy_handler ! {swap_info,dummy1_h,swap}, - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line my_dummy_handler ! Info, ?line receive @@ -821,7 +812,6 @@ info(Config) when is_list(Config) -> ok end, ?line my_dummy_handler ! {swap_info,{dummy1_h,2},swap}, - ?t:sleep(1000), ?line [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler), ?line my_dummy_handler ! Info, ?line receive @@ -853,7 +843,6 @@ info(Config) when is_list(Config) -> ok end, ?line my_dummy_handler ! {swap_info,dummy1_h,swap}, - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line my_dummy_handler ! Info, ?line receive diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl index 41de016f8d..1cff990697 100644 --- a/lib/stdlib/test/id_transform_SUITE.erl +++ b/lib/stdlib/test/id_transform_SUITE.erl @@ -56,47 +56,26 @@ end_per_group(_GroupName, Config) -> id_transform(doc) -> "Test erl_id_trans."; id_transform(Config) when is_list(Config) -> - ?line File=filename:join([code:lib_dir(stdlib),"examples", - "erl_id_trans.erl"]), - ?line {ok,erl_id_trans,Bin}=compile:file(File,[binary]), - ?line {module,erl_id_trans}=code:load_binary(erl_id_trans,File,Bin), - ?line case test_server:purify_is_running() of - false -> - Dog = ct:timetrap(?t:hours(1)), - ?line Res = run_in_test_suite(), - ?t:timetrap_cancel(Dog), - Res; - true -> - {skip,"Purify (too slow)"} - end. + File = filename:join([code:lib_dir(stdlib),"examples", + "erl_id_trans.erl"]), + {ok,erl_id_trans,Bin} = compile:file(File,[binary]), + {module,erl_id_trans} = code:load_binary(erl_id_trans, File, Bin), + case test_server:purify_is_running() of + false -> + Dog = ct:timetrap(?t:hours(1)), + Res = run_in_test_suite(), + ?t:timetrap_cancel(Dog), + Res; + true -> + {skip,"Valgrind (too slow)"} + end. run_in_test_suite() -> - LibDir = code:lib_dir(), SuperDir = filename:dirname(filename:dirname(code:which(?MODULE))), TestDirs = filelib:wildcard(filename:join([SuperDir,"*_test"])), - {All,Res} = case LibDir of - "/clearcase/otp/erts/lib" -> - %% Only test_suites 'cause clearcase is too slow... - {false,run_list(TestDirs)}; - _ -> - {true,run_codepath_and(TestDirs)} - end, - Comment0 = case All of - true -> []; - false -> "Only testsuite directories traversed" - end, - case Res of - {error,Reason} when Comment0 =/= [] -> - {failed,Comment0++"; "++Reason}; - {error,Reason} -> - {failed,Reason}; - ok -> - {comment,Comment0} - end. - -run_codepath_and(DirList) -> AbsDirs = [filename:absname(X) || X <- code:get_path()], - run_list(ordsets:from_list([X || X <- AbsDirs] ++ DirList)). + Dirs = ordsets:from_list(AbsDirs ++ TestDirs), + run_list(Dirs). run_list(PathL) -> io:format("Where to search for beam files:\n~p\n", [PathL]), @@ -123,7 +102,7 @@ run_list(PathL) -> end, case length(SevereFailures) of 0 -> ok; - Len -> {error,integer_to_list(Len)++" failures"} + Len -> {failed,integer_to_list(Len)++" failures"} end. diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 5df09b6a79..0e897631ff 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -29,10 +29,11 @@ manpage/1, otp_6708/1, otp_7084/1, otp_7421/1, io_lib_collect_line_3_wb/1, cr_whitespace_in_string/1, io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1, - printable_range/1, + printable_range/1, bad_printable_range/1, io_lib_print_binary_depth_one/1, otp_10302/1, otp_10755/1, otp_10836/1, io_lib_width_too_small/1, - io_with_huge_message_queue/1, format_string/1]). + io_with_huge_message_queue/1, format_string/1, + maps/1, coverage/1]). -export([pretty/2]). @@ -70,10 +71,10 @@ all() -> manpage, otp_6708, otp_7084, otp_7421, io_lib_collect_line_3_wb, cr_whitespace_in_string, io_fread_newlines, otp_8989, io_lib_fread_literal, - printable_range, + printable_range, bad_printable_range, io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836, io_lib_width_too_small, io_with_huge_message_queue, - format_string]. + format_string, maps, coverage]. groups() -> []. @@ -2062,8 +2063,6 @@ printable_range(Suite) when is_list(Suite) -> [{args, " +pclatin1 -pa " ++ Pa}]), unicode = rpc:call(UNode,io,printable_range,[]), latin1 = rpc:call(LNode,io,printable_range,[]), - {error, _} = test_server:start_node(printable_range_unnicode, slave, - [{args, " +pcunnicode -pa " ++ Pa}]), PrettyOptions = [{column,1}, {line_length,109}, {depth,30}, @@ -2071,48 +2070,69 @@ printable_range(Suite) when is_list(Suite) -> {record_print_fun, fun(_,_) -> no end}, {encoding,unicode}], - 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib_pretty,print, - [{hello, [1024,1025]}, - PrettyOptions]))), - 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib_pretty,print, - [{hello, [1024,1025]}, - PrettyOptions]))), - 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib_pretty,print, - [{hello, [1024,1025]}, - PrettyOptions]))), - 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib_pretty,print, - [{hello, <<1024/utf8,1025/utf8>>}, - PrettyOptions]))), - 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib_pretty,print, - [{hello, <<1024/utf8,1025/utf8>>}, - PrettyOptions]))), - 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib_pretty,print, - [{hello, <<1024/utf8,1025/utf8>>}, - PrettyOptions]))), + PrintableControls = "\t\v\b\f\e\r\n", + + 1025 = print_max(UNode, [{hello, [1024,1025]}, + PrettyOptions]), + 125 = print_max(LNode, [{hello, [1024,1025]}, + PrettyOptions]), + 125 = print_max(DNode, [{hello, [1024,1025]}, + PrettyOptions]), + 1025 = print_max(UNode, [{hello, <<1024/utf8,1025/utf8>>}, + PrettyOptions]), + 125 = print_max(LNode, [{hello, <<1024/utf8,1025/utf8>>}, + PrettyOptions]), + 125 = print_max(DNode, [{hello, <<1024/utf8,1025/utf8>>}, + PrettyOptions]), + $v = print_max(UNode, [PrintableControls,PrettyOptions]), + $v = print_max(LNode, [PrintableControls,PrettyOptions]), + $v = print_max(DNode, [PrintableControls,PrettyOptions]), + 16#10FFFF = print_max(UNode, + [<<16#10FFFF/utf8,"\t\v\b\f\e\r\n">>, + PrettyOptions]), + $> = print_max(LNode, + [<<16#10FFFF/utf8,"\t\v\b\f\e\r\n">>, + PrettyOptions]), + $> = print_max(DNode, + [<<16#10FFFF/utf8,"\t\v\b\f\e\r\n">>, + PrettyOptions]), - 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib,format, - ["~tp",[{hello, [1024,1025]}]]))), - 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib,format, - ["~tp",[{hello, [1024,1025]}]]))), - 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib,format, - ["~tp",[{hello, [1024,1025]}]]))), - 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib,format, - ["~tp", - [{hello, - <<1024/utf8,1025/utf8>>}]]))), - 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib,format, - ["~tp", - [{hello, - <<1024/utf8,1025/utf8>>}]]))), - 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib,format, - ["~tp", - [{hello, - <<1024/utf8,1025/utf8>>}]]))), + 1025 = format_max(UNode, ["~tp", [{hello, [1024,1025]}]]), + 125 = format_max(LNode, ["~tp", [{hello, [1024,1025]}]]), + 125 = format_max(DNode, ["~tp", [{hello, [1024,1025]}]]), + 1025 = format_max(UNode, ["~tp", [{hello, <<1024/utf8,1025/utf8>>}]]), + 125 = format_max(LNode, ["~tp", [{hello, <<1024/utf8,1025/utf8>>}]]), + 125 = format_max(DNode, ["~tp", [{hello, <<1024/utf8,1025/utf8>>}]]), + + $\e = format_max(UNode, ["~ts", [PrintableControls]]), + $\e = format_max(LNode, ["~ts", [PrintableControls]]), + $\e = format_max(DNode, ["~ts", [PrintableControls]]), + test_server:stop_node(UNode), test_server:stop_node(LNode), test_server:stop_node(DNode), ok. +print_max(Node, Args) -> + rpc_call_max(Node, io_lib_pretty, print, Args). + +format_max(Node, Args) -> + rpc_call_max(Node, io_lib, format, Args). + +rpc_call_max(Node, M, F, Args) -> + lists:max(lists:flatten(rpc:call(Node, M, F, Args))). + +%% Make sure that a bad specification for a printable range is rejected. +bad_printable_range(Config) when is_list(Config) -> + Cmd = lists:concat([lib:progname()," +pcunnnnnicode -run erlang halt"]), + case os:cmd(Cmd) of + "bad range of printable characters" ++ _ -> + ok; + String -> + io:format("~s\n", [String]), + ?t:fail() + end. + io_lib_print_binary_depth_one(doc) -> "Test binaries printed with a depth of one behave correctly"; io_lib_print_binary_depth_one(Suite) when is_list(Suite) -> @@ -2225,7 +2245,7 @@ compile_file(File, Text, Config) -> after ok %file:delete(Fname) end. -io_lib_width_too_small(Config) -> +io_lib_width_too_small(_Config) -> "**" = lists:flatten(io_lib:format("~2.3w", [3.14])), "**" = lists:flatten(io_lib:format("~2.5w", [3.14])), ok. @@ -2271,8 +2291,113 @@ writes(N, F1) -> file:write(F1, "hello\n"), writes(N - 1, F1). -format_string(Config) -> +format_string(_Config) -> %% All but padding is tested by fmt/2. "xxxxxxsssx" = fmt("~10.4.xs", ["sss"]), "xxxxxxsssx" = fmt("~10.4.*s", [$x, "sss"]), ok. + +maps(_Config) -> + %% Note that order in which a map is printed is arbitrary. In + %% practice, small maps (non-HAMT) are printed in key order, but + %% the breakpoint for creating big maps (HAMT) is lower in the + %% debug-compiled run-time system than in the optimized run-time + %% system. + %% + %% Therefore, play it completely safe by not assuming any order + %% in a map with more than one element. + + "#{}" = fmt("~w", [#{}]), + "#{a=>b}" = fmt("~w", [#{a=>b}]), + re_fmt(<<"#\\{(a=>b|c=>d),[.][.][.]=>[.][.][.]\\}">>, + "~W", [#{a=>b,c=>d},2]), + re_fmt(<<"#\\{(a=>b|c=>d|e=>f),[.][.][.]=>[.][.][.],[.][.][.]\\}">>, + "~W", [#{a=>b,c=>d,e=>f},2]), + + "#{}" = fmt("~p", [#{}]), + "#{a => b}" = fmt("~p", [#{a=>b}]), + "#{...}" = fmt("~P", [#{a=>b},1]), + re_fmt(<<"#\\{(a => b|c => d),[.][.][.]\\}">>, + "~P", [#{a=>b,c=>d},2]), + re_fmt(<<"#\\{(a => b|c => d|e => f),[.][.][.]\\}">>, + "~P", [#{a=>b,c=>d,e=>f},2]), + + List = [{I,I*I} || I <- lists:seq(1, 20)], + Map = maps:from_list(List), + + "#{...}" = fmt("~P", [Map,1]), + + %% Print a map and parse it back to a map. + S = fmt("~p\n", [Map]), + io:format("~p\n", [S]), + Map = parse_map(S), + + %% Smoke test of a map as key. + MapAsKey = #{Map => "value"}, + io:format("~s\n", [fmt("~p", [MapAsKey])]), + ok. + +re_fmt(Pattern, Format, Args) -> + S = list_to_binary(fmt(Format, Args)), + case re:run(S, Pattern, [{capture,none}]) of + nomatch -> + io:format("Pattern: ~s", [Pattern]), + io:format("Result: ~s", [S]), + ?t:fail(); + match -> + ok + end. + +%% Parse a map consisting of integer keys and values. +parse_map(S0) -> + S1 = parse_expect(S0, "#{"), + {M,S2} = parse_map_1(S1), + S = parse_expect(S2, "}"), + S = "", + M. + +parse_map_1(S0) -> + {Key,S1} = parse_number(S0), + S2 = parse_expect(S1, "=>"), + {Val,S3} = parse_number(S2), + case S3 of + ","++S4 -> + S5 = parse_skip_ws(S4), + {Map,S} = parse_map_1(S5), + {Map#{Key=>Val},S}; + S -> + {#{Key=>Val},S} + end. + +parse_number(S) -> + parse_number(S, none). + +parse_number([C|S], Acc0) when $0 =< C, C =< $9 -> + Acc = case Acc0 of + none -> 0; + _ when is_integer(Acc0) -> Acc0 + end, + parse_number(S, Acc*10+C-$0); +parse_number(S, Acc) -> + {Acc,parse_skip_ws(S)}. + +parse_expect([H|T1], [H|T2]) -> + parse_expect(T1, T2); +parse_expect(S, []) -> + parse_skip_ws(S). + +parse_skip_ws([C|S]) when C =< $\s -> + parse_skip_ws(S); +parse_skip_ws(S) -> + S. + +%% Cover the last uncovered lines for completeness. +coverage(_Config) -> + S1 = io_lib_pretty:print({a,term}, fun(_, _) -> no end), + io:format("~s\n", [S1]), + + %% The tuple of arity three will be ignored. + S2 = io_lib_pretty:print(lists:seq(1, 100), [{depth,1,1}]), + io:format("~s\n", [S2]), + + ok. diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl index 1337b7dde2..811c7ed7bb 100644 --- a/lib/stdlib/test/io_proto_SUITE.erl +++ b/lib/stdlib/test/io_proto_SUITE.erl @@ -1378,47 +1378,43 @@ rtnode(C,N) -> rtnode(Commands,Nodename,ErlPrefix) -> rtnode(Commands,Nodename,ErlPrefix,[]). rtnode(Commands,Nodename,ErlPrefix,Extra) -> - ?line case get_progs() of - {error,_Reason} -> - ?line {skip,"No runerl present"}; - {RunErl,ToErl,Erl} -> - ?line case create_tempdir() of - {error, Reason2} -> - ?line {skip, Reason2}; - Tempdir -> - ?line SPid = - start_runerl_node(RunErl,ErlPrefix++ - "\\\""++Erl++"\\\"", - Tempdir,Nodename, Extra), - ?line CPid = start_toerl_server(ToErl,Tempdir), - ?line erase(getline_skipped), - ?line Res = - (catch get_and_put(CPid, Commands,1)), - ?line case stop_runerl_node(CPid) of - {error,_} -> - ?line CPid2 = - start_toerl_server - (ToErl,Tempdir), - ?line erase(getline_skipped), - ?line ok = get_and_put - (CPid2, - [{putline,[7]}, - {sleep, - timeout(short)}, - {putline,""}, - {getline," -->"}, - {putline,"s"}, - {putline,"c"}, - {putline,""}],1), - ?line stop_runerl_node(CPid2); - _ -> - ?line ok - end, - ?line wait_for_runerl_server(SPid), - ?line ok = ?RM_RF(Tempdir), - ?line ok = Res - end - end. + case get_progs() of + {error,_Reason} -> + {skip,"No runerl present"}; + {RunErl,ToErl,Erl} -> + case create_tempdir() of + {error, Reason2} -> + {skip, Reason2}; + Tempdir -> + SPid = start_runerl_node(RunErl, ErlPrefix++ + "\\\""++Erl++"\\\"", + Tempdir, Nodename, Extra), + CPid = start_toerl_server(ToErl, Tempdir), + put(getline_skipped, []), + Res = (catch get_and_put(CPid, Commands, 1)), + case stop_runerl_node(CPid) of + {error,_} -> + CPid2 = start_toerl_server(ToErl, Tempdir), + put(getline_skipped, []), + ok = get_and_put + (CPid2, + [{putline,[7]}, + {sleep, + timeout(short)}, + {putline,""}, + {getline," -->"}, + {putline,"s"}, + {putline,"c"}, + {putline,""}], 1), + stop_runerl_node(CPid2); + _ -> + ok + end, + wait_for_runerl_server(SPid), + ok = ?RM_RF(Tempdir), + ok = Res + end + end. timeout(long) -> 2 * timeout(normal); @@ -1462,57 +1458,51 @@ get_and_put(CPid, [{sleep, X}|T],N) -> after X -> get_and_put(CPid,T,N+1) end; -get_and_put(CPid, [{getline, Match}|T],N) -> +get_and_put(CPid, [{getline_pred,Pred,Msg}|T]=T0, N) + when is_function(Pred) -> ?dbg({getline, Match}), CPid ! {self(), {get_line, timeout(normal)}}, receive {get_line, timeout} -> error_logger:error_msg("~p: getline timeout waiting for \"~s\" " "(command number ~p, skipped: ~p)~n", - [?MODULE, Match,N,get(getline_skipped)]), + [?MODULE,Msg,N,get(getline_skipped)]), {error, timeout}; {get_line, Data} -> ?dbg({data,Data}), - case lists:prefix(Match, Data) of - true -> - erase(getline_skipped), + case Pred(Data) of + yes -> + put(getline_skipped, []), get_and_put(CPid, T,N+1); - false -> - case get(getline_skipped) of - undefined -> - put(getline_skipped,[Data]); - List -> - put(getline_skipped,List ++ [Data]) - end, - get_and_put(CPid, [{getline, Match}|T],N) + no -> + error_logger:error_msg("~p: getline match failure " + "\"~s\" " + "(command number ~p)\n", + [?MODULE,Msg,N]), + {error, no_match}; + maybe -> + List = get(getline_skipped), + put(getline_skipped, List ++ [Data]), + get_and_put(CPid, T0, N) end end; +get_and_put(CPid, [{getline, Match}|T],N) -> + ?dbg({getline, Match}), + F = fun(Data) -> + case lists:prefix(Match, Data) of + true -> yes; + false -> maybe + end + end, + get_and_put(CPid, [{getline_pred,F,Match}|T], N); get_and_put(CPid, [{getline_re, Match}|T],N) -> - ?dbg({getline_re, Match}), - CPid ! {self(), {get_line, timeout(normal)}}, - receive - {get_line, timeout} -> - error_logger:error_msg("~p: getline_re timeout waiting for \"~s\" " - "(command number ~p, skipped: ~p)~n", - [?MODULE, Match,N,get(getline_skipped)]), - {error, timeout}; - {get_line, Data} -> - ?dbg({data,Data}), - case re:run(Data, Match,[{capture,none}]) of - match -> - erase(getline_skipped), - get_and_put(CPid, T,N+1); - _ -> - case get(getline_skipped) of - undefined -> - put(getline_skipped,[Data]); - List -> - put(getline_skipped,List ++ [Data]) - end, - get_and_put(CPid, [{getline_re, Match}|T],N) - end - end; - + F = fun(Data) -> + case re:run(Data, Match, [{capture,none}]) of + match -> yes; + _ -> maybe + end + end, + get_and_put(CPid, [{getline_pred,F,Match}|T], N); get_and_put(CPid, [{putline_raw, Line}|T],N) -> ?dbg({putline_raw, Line}), CPid ! {self(), {send_line, Line}}, @@ -1801,10 +1791,22 @@ get_data_within(Port, Timeout, Acc) -> end. get_default_shell() -> + Match = fun(Data) -> + case lists:prefix("undefined", Data) of + true -> + yes; + false -> + case re:run(Data, "<\\d+[.]\\d+[.]\\d+>", + [{capture,none}]) of + match -> no; + _ -> maybe + end + end + end, try rtnode([{putline,""}, {putline, "whereis(user_drv)."}, - {getline, "undefined"}],[]), + {getline_pred, Match, "matching of user_drv pid"}], []), old catch _E:_R -> ?dbg({_E,_R}), diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index e886a797f0..a0f7fd2744 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -38,13 +38,13 @@ % Test cases must be exported. -export([member/1, reverse/1, keymember/1, keysearch_keyfind/1, - keystore/1, keytake/1, + keystore/1, keytake/1, keyreplace/1, append_1/1, append_2/1, seq_loop/1, seq_2/1, seq_3/1, seq_2_e/1, seq_3_e/1, sublist_2/1, sublist_3/1, sublist_2_e/1, sublist_3_e/1, flatten_1/1, flatten_2/1, flatten_1_e/1, flatten_2_e/1, - dropwhile/1, + dropwhile/1, takewhile/1, sort_1/1, sort_stable/1, merge/1, rmerge/1, sort_rand/1, usort_1/1, usort_stable/1, umerge/1, rumerge/1,usort_rand/1, keymerge/1, rkeymerge/1, @@ -62,7 +62,7 @@ zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1, filter_partition/1, otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1, - suffix/1, subtract/1, droplast/1]). + suffix/1, subtract/1, droplast/1, hof/1]). %% Sort randomized lists until stopped. %% @@ -81,37 +81,51 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [{group, append}, reverse, member, keymember, - keysearch_keyfind, keystore, keytake, dropwhile, {group,sort}, - {group, usort}, {group, keysort}, {group, ukeysort}, - {group, funsort}, {group, ufunsort}, {group, sublist}, - {group, flatten}, {group, seq}, zip_unzip, zip_unzip3, - zipwith, zipwith3, filter_partition, {group, tickets}, - suffix, subtract]. + [{group, append}, + {group, key}, + {group,sort}, + {group, usort}, + {group, keysort}, + {group, ukeysort}, + {group, funsort}, + {group, ufunsort}, + {group, sublist}, + {group, flatten}, + {group, seq}, + {group, tickets}, + {group, zip}, + {group, misc}]. groups() -> - [{append, [], [append_1, append_2]}, - {usort, [], + [{append, [parallel], [append_1, append_2]}, + {usort, [parallel], [umerge, rumerge, usort_1, usort_rand, usort_stable]}, - {keysort, [], + {keysort, [parallel], [keymerge, rkeymerge, keysort_1, keysort_rand, keysort_i, keysort_stable, keysort_error]}, - {sort,[],[merge, rmerge, sort_1, sort_rand]}, - {ukeysort, [], + {key, [parallel], [keymember, keysearch_keyfind, keystore, + keytake, keyreplace]}, + {sort,[parallel],[merge, rmerge, sort_1, sort_rand]}, + {ukeysort, [parallel], [ukeymerge, rukeymerge, ukeysort_1, ukeysort_rand, ukeysort_i, ukeysort_stable, ukeysort_error]}, - {funsort, [], + {funsort, [parallel], [funmerge, rfunmerge, funsort_1, funsort_stable, funsort_error, funsort_rand]}, - {ufunsort, [], + {ufunsort, [parallel], [ufunmerge, rufunmerge, ufunsort_1, ufunsort_stable, ufunsort_error, ufunsort_rand]}, - {seq, [], [seq_loop, seq_2, seq_3, seq_2_e, seq_3_e]}, - {sublist, [], + {seq, [parallel], [seq_loop, seq_2, seq_3, seq_2_e, seq_3_e]}, + {sublist, [parallel], [sublist_2, sublist_3, sublist_2_e, sublist_3_e]}, - {flatten, [], + {flatten, [parallel], [flatten_1, flatten_2, flatten_1_e, flatten_2_e]}, - {tickets, [], [otp_5939, otp_6023, otp_6606, otp_7230]}]. + {tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]}, + {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]}, + {misc, [parallel], [reverse, member, dropwhile, takewhile, + filter_partition, suffix, subtract, + hof]} + ]. init_per_suite(Config) -> Config. @@ -345,6 +359,33 @@ dropwhile(Config) when is_list(Config) -> ok. +takewhile(Config) when is_list(Config) -> + F = fun(C) -> C =/= $@ end, + + [] = lists:takewhile(F, []), + [a] = lists:takewhile(F, [a]), + [a,b] = lists:takewhile(F, [a,b]), + [a,b,c] = lists:takewhile(F, [a,b,c]), + + [] = lists:takewhile(F, [$@]), + [] = lists:takewhile(F, [$@,$@]), + [a] = lists:takewhile(F, [a,$@]), + + [$k] = lists:takewhile(F, [$k,$@]), + [$k,$l] = lists:takewhile(F, [$k,$l,$@,$@]), + [a] = lists:takewhile(F, [a,$@,$@,$@]), + + [] = lists:takewhile(F, [$@,a,$@,b]), + [] = lists:takewhile(F, [$@,$@,a,$@,b]), + [] = lists:takewhile(F, [$@,$@,$@,a,$@,b]), + + Long = lists:seq(1, 1024), + Shorter = lists:seq(1, 400), + + Shorter = lists:takewhile(fun(E) -> E =< 400 end, Long), + + ok. + keystore(doc) -> ["OTP-XXX."]; keystore(suite) -> []; @@ -382,6 +423,17 @@ keytake(Config) when is_list(Config) -> ?line false = lists:keytake(4, 2, L), ok. +%% Test lists:keyreplace/4. +keyreplace(Config) when is_list(Config) -> + [{new,42}] = lists:keyreplace(k, 1, [{k,1}], {new,42}), + [atom,{new,a,b}] = lists:keyreplace(k, 1, [atom,{k,1}], {new,a,b}), + [a,{x,y,z}] = lists:keyreplace(a, 5, [a,{x,y,z}], {no,use}), + + %% Error cases. + {'EXIT',_} = (catch lists:keyreplace(k, 1, [], not_tuple)), + {'EXIT',_} = (catch lists:keyreplace(k, 0, [], {a,b})), + ok. + merge(doc) -> ["merge functions"]; merge(suite) -> []; merge(Config) when is_list(Config) -> @@ -2326,19 +2378,25 @@ sublist_3_e(Config) when is_list(Config) -> -define(flatten_error1(X), ?line {'EXIT', _} = (catch lists:flatten(X))). -define(flatten_error2(X,Y), ?line {'EXIT', _} = (catch lists:flatten(X,Y))). -flatten_1(doc) -> ["flatten/1"]; -flatten_1(suite) -> []; +%% Test lists:flatten/1,2 and lists:flatlength/1. flatten_1(Config) when is_list(Config) -> - ?line [] = lists:flatten([]), - ?line [1,2] = lists:flatten([1,2]), - ?line [1,2] = lists:flatten([1,[2]]), - ?line [1,2] = lists:flatten([[1],2]), - ?line [1,2] = lists:flatten([[1],[2]]), - ?line [1,2] = lists:flatten([[1,2]]), - ?line [a,b,c,d] = lists:flatten([[a],[b,c,[d]]]), + [] = lists_flatten([]), + [1,2] = lists_flatten([1,2]), + [1,2] = lists_flatten([1,[2]]), + [1,2] = lists_flatten([[1],2]), + [1,2] = lists_flatten([[1],[2]]), + [1,2] = lists_flatten([[1,2]]), + [a,b,c,d] = lists_flatten([[a],[b,c,[d]]]), ok. +lists_flatten(List) -> + Flat = lists:flatten(List), + Flat = lists:flatten(List, []), + Len = lists:flatlength(List), + Len = length(Flat), + Flat. + flatten_1_e(doc) -> ["flatten/1 error cases"]; flatten_1_e(suite) -> []; flatten_1_e(Config) when is_list(Config) -> @@ -2351,11 +2409,11 @@ flatten_1_e(Config) when is_list(Config) -> %%% clear-cut. Right now, I think that any term should be allowed. %%% But I also wish this function didn't exist at all. -flatten_2(doc) -> ["flatten/2"]; -flatten_2(suite) -> []; +%% Test lists:flatten/2. flatten_2(Config) when is_list(Config) -> - ?line [] = lists:flatten([]), - ?line [a] = lists:flatten([a]), + [] = lists:flatten([], []), + [a] = lists:flatten([a], []), + [a,b,c,[no,flatten]] = lists:flatten([[a,[b,c]]], [[no,flatten]]), ok. flatten_2_e(doc) -> ["flatten/2 error cases"]; @@ -2651,3 +2709,40 @@ droplast(Config) when is_list(Config) -> ?line {'EXIT', {function_clause, _}} = (catch lists:droplast(x)), ok. + +%% Briefly test the common high-order functions to ensure they +%% are covered. +hof(Config) when is_list(Config) -> + L = [1,2,3], + [1,4,9] = lists:map(fun(N) -> N*N end, L), + [1,4,5,6] = lists:flatmap(fun(1) -> [1]; + (2) -> []; + (3) -> [4,5,6] + end, L), + [{1,[a]},{2,[b]},{3,[c]}] = + lists:keymap(fun(A) -> [A] end, 2, [{1,a},{2,b},{3,c}]), + + [1,3] = lists:filter(fun(N) -> N rem 2 =:= 1 end, L), + FilterMapFun = fun(1) -> true; + (2) -> {true,42}; + (3) -> false + end, + [1,42] = lists:filtermap(FilterMapFun, L), + [1,42] = lists:zf(FilterMapFun, L), + + [3,2,1] = lists:foldl(fun(E, A) -> [E|A] end, [], L), + [1,2,3] = lists:foldr(fun(E, A) -> [E|A] end, [], L), + {[1,4,9],[3,2,1]} = lists:mapfoldl(fun(E, A) -> + {E*E,[E|A]} + end, [], L), + {[1,4,9],[1,2,3]} = lists:mapfoldr(fun(E, A) -> + {E*E,[E|A]} + end, [], L), + + true = lists:any(fun(N) -> N =:= 2 end, L), + false = lists:any(fun(N) -> N =:= 42 end, L), + + true = lists:all(fun(N) -> is_integer(N) end, L), + false = lists:all(fun(N) -> N rem 2 =:= 0 end, L), + + ok. diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl index 3a8fa74d36..f7a6a38138 100644 --- a/lib/stdlib/test/proc_lib_SUITE.erl +++ b/lib/stdlib/test/proc_lib_SUITE.erl @@ -80,81 +80,123 @@ end_per_group(_GroupName, Config) -> crash(Config) when is_list(Config) -> error_logger:add_report_handler(?MODULE, self()), - Pid = proc_lib:spawn(?MODULE, sp1, []), - Pid ! die, - ?line Report = receive - {crash_report, Pid, Report0} -> Report0 - after 2000 -> test_server:fail(no_crash_report) - end, - ?line proc_lib:format(Report), - ?line [PidRep, []] = Report, - ?line {value, {initial_call,{?MODULE,sp1,[]}}} = - lists:keysearch(initial_call, 1, PidRep), - Self = self(), - ?line {value, {ancestors,[Self]}} = - lists:keysearch(ancestors, 1, PidRep), - ?line {value, {error_info,{exit,die,_StackTrace1}}} = - lists:keysearch(error_info, 1, PidRep), - - F = fun sp1/0, - Pid1 = proc_lib:spawn(node(), F), - Pid1 ! die, - ?line [PidRep1, []] = receive - {crash_report, Pid1, Report1} -> Report1 - after 2000 -> test_server:fail(no_crash_report) - end, - ?line {value, {initial_call,{Fmod,Fname,[]}}} = - lists:keysearch(initial_call, 1, PidRep1), - ?line {module,Fmod} = erlang:fun_info(F, module), - ?line {name,Fname} = erlang:fun_info(F, name), - ?line {value, {ancestors,[Self]}} = - lists:keysearch(ancestors, 1, PidRep1), - ?line {value, {error_info,{exit,die,_StackTrace2}}} = - lists:keysearch(error_info, 1, PidRep1), - - Pid2 = proc_lib:spawn(?MODULE, sp2, []), - test_server:sleep(100), - ?line {?MODULE,sp2,[]} = proc_lib:initial_call(Pid2), - ?line {?MODULE,sp2,0} = proc_lib:translate_initial_call(Pid2), - Pid2 ! die, - ?line [Pid2Rep, [{neighbour, LinkRep}]] = - receive - {crash_report, Pid2, Report2} -> Report2 - after 2000 -> test_server:fail(no_crash_report) - end, - ?line {value, {initial_call,{?MODULE,sp2,[]}}} = - lists:keysearch(initial_call, 1, Pid2Rep), - ?line {value, {ancestors,[Self]}} = - lists:keysearch(ancestors, 1, Pid2Rep), - ?line {value, {error_info,{exit,die,_StackTrace3}}} = - lists:keysearch(error_info, 1, Pid2Rep), - ?line {value, {initial_call,{?MODULE,sp1,[]}}} = - lists:keysearch(initial_call, 1, LinkRep), - %% Make sure that we don't get a crash report if a process %% terminates with reason 'shutdown' or reason {shutdown,Reason}. - ?line process_flag(trap_exit, true), - ?line Pid3 = proc_lib:spawn_link(erlang, apply, - [fun() -> exit(shutdown) end,[]]), - - ?line Pid4 = proc_lib:spawn_link(erlang, apply, - [fun() -> exit({shutdown,{a,b,c}}) end,[]]), + process_flag(trap_exit, true), + Pid0 = proc_lib:spawn_link(erlang, apply, + [fun() -> exit(shutdown) end,[]]), + Pid1 = proc_lib:spawn_link(erlang, apply, + [fun() -> exit({shutdown,{a,b,c}}) end,[]]), + + receive {'EXIT',Pid0,shutdown} -> ok end, + receive {'EXIT',Pid1,{shutdown,{a,b,c}}} -> ok end, + process_flag(trap_exit, false), + %% We expect any unexpected messages to be caught below, + %% so we don't have explicitly wait some time to be sure. + + %% Spawn export function. + Pid2 = proc_lib:spawn(?MODULE, sp1, []), + Pid2 ! die, + Exp2 = [{initial_call,{?MODULE,sp1,[]}}, + {ancestors,[self()]}, + {error_info,{exit,die,{stacktrace}}}], + analyse_crash(Pid2, Exp2, []), - ?line receive {'EXIT',Pid3,shutdown} -> ok end, - ?line receive {'EXIT',Pid4,{shutdown,{a,b,c}}} -> ok end, - ?line process_flag(trap_exit, false), + %% Spawn fun. + F = fun sp1/0, + Pid3 = proc_lib:spawn(node(), F), + Pid3 ! die, + {module,?MODULE} = erlang:fun_info(F, module), + {name,Fname} = erlang:fun_info(F, name), + Exp3 = [{initial_call,{?MODULE,Fname,[]}}, + {ancestors,[self()]}, + {error_info,{exit,die,{stacktrace}}}], + analyse_crash(Pid3, Exp3, []), - receive - Any -> - ?line ?t:fail({unexpected_message,Any}) - after 2000 -> - ok - end, + %% Spawn function with neighbour. + Pid4 = proc_lib:spawn(?MODULE, sp2, []), + test_server:sleep(100), + {?MODULE,sp2,[]} = proc_lib:initial_call(Pid4), + {?MODULE,sp2,0} = proc_lib:translate_initial_call(Pid4), + Pid4 ! die, + Exp4 = [{initial_call,{?MODULE,sp2,[]}}, + {ancestors,[self()]}, + {error_info,{exit,die,{stacktrace}}}], + Links4 = [[{initial_call,{?MODULE,sp1,[]}}, + {ancestors,[Pid4,self()]}]], + analyse_crash(Pid4, Exp4, Links4), + + %% Make sure that we still get a crash report if the + %% process dictionary have been tampered with. + + Pid5 = proc_lib:spawn(erlang, apply, + [fun() -> + erase(), + exit(abnormal) + end,[]]), + Exp5 = [{initial_call,absent}, + {ancestors,[]}, + {error_info,{exit,abnormal,{stacktrace}}}], + analyse_crash(Pid5, Exp5, []), error_logger:delete_report_handler(?MODULE), ok. +analyse_crash(Pid, Expected0, ExpLinks) -> + Expected = [{pid,Pid}|Expected0], + receive + {crash_report, Pid, Report} -> + _ = proc_lib:format(Report), %Smoke test. + [Crash,Links] = Report, + analyse_crash_1(Expected, Crash), + analyse_links(ExpLinks, Links); + Unexpected -> + io:format("~p\n", [Unexpected]), + test_server:fail(unexpected_message) + after 5000 -> + test_server:fail(no_crash_report) + end. + +analyse_links([H|Es], [{neighbour,N}|Links]) -> + analyse_crash_1(H, N), + analyse_links(Es, Links); +analyse_links([], []) -> + ok. +analyse_crash_1([{Key,absent}|T], Report) -> + false = lists:keymember(Key, 1, Report), + analyse_crash_1(T, Report); +analyse_crash_1([{Key,Pattern}|T], Report) -> + case lists:keyfind(Key, 1, Report) of + false -> + io:format("~p", [Report]), + test_server:fail({missing_key,Key}); + {Key,Info} -> + try + match_info(Pattern, Info) + catch + no_match -> + io:format("key: ~p", [Key]), + io:format("pattern: ~p", [Pattern]), + io:format("actual: ~p", [Report]), + test_server:fail(no_match) + end, + analyse_crash_1(T, Report) + end; +analyse_crash_1([], _Report) -> + []. + +match_info(T, T) -> + ok; +match_info({stacktrace}, Stk) when is_list(Stk) -> + ok; +match_info([H1|T1], [H2|T2]) -> + match_info(H1, H2), + match_info(T1, T2); +match_info(Tuple1, Tuple2) when tuple_size(Tuple1) =:= tuple_size(Tuple2) -> + match_info(tuple_to_list(Tuple1), tuple_to_list(Tuple2)); +match_info(_, _) -> + throw(no_match). sync_start_nolink(Config) when is_list(Config) -> _Pid = spawn_link(?MODULE, sp5, [self()]), @@ -369,7 +411,7 @@ init_dont_hang(Config) when is_list(Config) -> end. init_dont_hang_init(_Parent) -> - 1 = 2. + error(bad_init). %% Test proc_lib:stop/1,3 stop(_Config) -> @@ -453,7 +495,7 @@ stop(_Config) -> ok. system_terminate(crash,_Parent,_Deb,_State) -> - 1 = 2; + error({badmatch,2}); system_terminate(Reason,_Parent,_Deb,_State) -> exit(Reason). diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl index b03caebe91..111bf620de 100644 --- a/lib/stdlib/test/rand_SUITE.erl +++ b/lib/stdlib/test/rand_SUITE.erl @@ -25,7 +25,9 @@ ]). -export([interval_int/1, interval_float/1, seed/1, - api_eq/1, reference/1, basic_stats/1, + api_eq/1, reference/1, + basic_stats_uniform_1/1, basic_stats_uniform_2/1, + basic_stats_normal/1, plugin/1, measure/1 ]). @@ -51,11 +53,13 @@ all() -> [seed, interval_int, interval_float, api_eq, reference, - basic_stats, + {group, basic_stats}, plugin, measure ]. -groups() -> []. +groups() -> + [{basic_stats, [parallel], + [basic_stats_uniform_1, basic_stats_uniform_2, basic_stats_normal]}]. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. @@ -291,14 +295,19 @@ gen(_, _, Acc) -> lists:reverse(Acc). %% The algorithms must have good properties to begin with %% -basic_stats(doc) -> ["Check that the algorithms generate sound values."]; -basic_stats(suite) -> []; -basic_stats(Config) when is_list(Config) -> - io:format("Testing uniform~n",[]), +%% Check that the algorithms generate sound values. + +basic_stats_uniform_1(Config) when is_list(Config) -> [basic_uniform_1(?LOOP, rand:seed_s(Alg), 0.0, array:new([{default, 0}])) || Alg <- algs()], + ok. + +basic_stats_uniform_2(Config) when is_list(Config) -> [basic_uniform_2(?LOOP, rand:seed_s(Alg), 0, array:new([{default, 0}])) || Alg <- algs()], + ok. + +basic_stats_normal(Config) when is_list(Config) -> io:format("Testing normal~n",[]), [basic_normal_1(?LOOP, rand:seed_s(Alg), 0, 0) || Alg <- algs()], ok. diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl index b8c20d9745..d78d6153da 100644 --- a/lib/stdlib/test/re_SUITE.erl +++ b/lib/stdlib/test/re_SUITE.erl @@ -28,7 +28,7 @@ pcre_compile_workspace_overflow/1,re_infinite_loop/1, re_backwards_accented/1,opt_dupnames/1,opt_all_names/1,inspect/1, opt_no_start_optimize/1,opt_never_utf/1,opt_ucp/1, - match_limit/1,sub_binaries/1]). + match_limit/1,sub_binaries/1,copt/1]). -include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). @@ -319,32 +319,26 @@ replace_return(doc) -> ["Tests return options of replace together with global searching"]; replace_return(Config) when is_list(Config) -> Dog = ?t:timetrap(?t:minutes(3)), - ?line {'EXIT',{badarg,_}} = (catch re:replace("na","(a","")), - ?line <<"nasse">> = re:replace(<<"nisse">>,"i","a",[{return,binary}]), - ?line <<"ABCÅXABCXA">> = re:replace("ABC\305abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary}]), - - ?line [<<"ABCÅ">>, - <<"X">>, - <<"ABC">>, - <<"X">> | - <<"A">> ] = - re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,iodata}]), - ?line "ABCÅXABCXA" = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,list},unicode]), - ?line <<65,66,67,195,133,88,65,66,67,88,65>> = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary},unicode]), - ?line <<65,66,67,195,133,88,65,66,67,97,98,99,100,65>> = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[{return,binary},unicode]), - ?line <<"iXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\9X",[{return,binary}]), - ?line <<"jXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\10X",[{return,binary}]), - ?line <<"Xk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\11X",[{return,binary}]), - ?line <<"9X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g9X",[{return,binary}]), - ?line <<"0X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g10X",[{return,binary}]), - ?line <<"X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g11X",[{return,binary}]), - ?line <<"971">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{9}7",[{return,binary}]), - ?line <<"071">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{10}7",[{return,binary}]), - ?line <<"71">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{11}7",[{return,binary}]), - ?line "a\x{400}bcX" = re:replace("a\x{400}bcd","d","X",[global,{return,list},unicode]), - ?line <<"a",208,128,"bcX">> = re:replace("a\x{400}bcd","d","X",[global,{return,binary},unicode]), - ?line "a\x{400}bcd" = re:replace("a\x{400}bcd","Z","X",[global,{return,list},unicode]), - ?line <<"a",208,128,"bcd">> = re:replace("a\x{400}bcd","Z","X",[global,{return,binary},unicode]), + {'EXIT',{badarg,_}} = (catch re:replace("na","(a","")), + ok = replacetest(<<"nisse">>,"i","a",[{return,binary}],<<"nasse">>), + ok = replacetest("ABC\305abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary}],<<"ABCÅXABCXA">>), + ok = replacetest("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,iodata}],[<<"ABCÅ">>,<<"X">>,<<"ABC">>,<<"X">>|<<"A">>]), + ok = replacetest("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,list},unicode],"ABCÅXABCXA"), + ok = replacetest("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary},unicode],<<65,66,67,195,133,88,65,66,67,88,65>>), + ok = replacetest("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[{return,binary},unicode],<<65,66,67,195,133,88,65,66,67,97,98,99,100,65>>), + ok = replacetest("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\9X",[{return,binary}],<<"iXk">>), + ok = replacetest("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\10X",[{return,binary}],<<"jXk">>), + ok = replacetest("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\11X",[{return,binary}],<<"Xk">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g9X",[{return,binary}],<<"9X1">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g10X",[{return,binary}],<<"0X1">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g11X",[{return,binary}],<<"X1">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{9}7",[{return,binary}],<<"971">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{10}7",[{return,binary}],<<"071">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{11}7",[{return,binary}],<<"71">>), + ok = replacetest("a\x{400}bcd","d","X",[global,{return,list},unicode],"a\x{400}bcX"), + ok = replacetest("a\x{400}bcd","d","X",[global,{return,binary},unicode],<<"a",208,128,"bcX">>), + ok = replacetest("a\x{400}bcd","Z","X",[global,{return,list},unicode],"a\x{400}bcd"), + ok = replacetest("a\x{400}bcd","Z","X",[global,{return,binary},unicode],<<"a",208,128,"bcd">>), ?t:timetrap_cancel(Dog), ok. @@ -389,6 +383,35 @@ crtest(Subject,RE,Options,true,Result) -> error end. +replacetest(Subject,RE,Replacement,Options,Result) -> + Result = re:replace(Subject,RE,Replacement,Options), + {CompileOptions,ReplaceOptions} = lists:partition(fun copt/1, Options), + {ok,MP} = re:compile(RE,CompileOptions), + Result = re:replace(Subject,MP,Replacement,ReplaceOptions), + ok. + +splittest(Subject,RE,Options,Result) -> + Result = re:split(Subject,RE,Options), + {CompileOptions,SplitOptions} = lists:partition(fun copt/1, Options), + {ok,MP} = re:compile(RE,CompileOptions), + Result = re:split(Subject,MP,SplitOptions), + ok. + +copt(caseless) -> true; +copt(no_start_optimize) -> true; +copt(never_utf) -> true; +copt(ucp) -> true; +copt(dollar_endonly) -> true; +copt(dotall) -> true; +copt(extended) -> true; +copt(firstline) -> true; +copt(multiline) -> true; +copt(no_auto_capture) -> true; +copt(dupnames) -> true; +copt(ungreedy) -> true; +copt(unicode) -> true; +copt(_) -> false. + split_autogen(doc) -> ["Test split with autogenerated erlang module"]; split_autogen(Config) when is_list(Config) -> @@ -401,43 +424,23 @@ split_options(doc) -> ["Test special options to split."]; split_options(Config) when is_list(Config) -> Dog = ?t:timetrap(?t:minutes(1)), - ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]] = re:split("a b c ","( )",[group,trim]), - ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]] = re:split("a b c ","( )",[group,{parts,0}]), - ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]] = - re:split("a b c ","( )",[{parts,infinity},group]), - ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]] = - re:split("a b c ","( )",[group]), - ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>], - [<<"c">>,<<" ">>],[<<"d">>,<<" ">>]] = - re:split(" a b c d ","( +)",[group,trim]), - ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>], - [<<"c">>,<<" ">>],[<<"d">>,<<" ">>]] = - re:split(" a b c d ","( +)",[{parts,0},group]), - ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>], - [<<"c">>,<<" ">>],[<<"d">>,<<" ">>],[<<>>]] = - re:split(" a b c d ","( +)",[{parts,infinity},group]), - ?line [[<<"a">>,<<" ">>],[<<"b c d">>]] = - re:split("a b c d","( +)",[{parts,2},group]), - ?line [[[967]," "],["b c d"]] = - re:split([967]++" b c d","( +)", - [{parts,2},group,{return,list},unicode]), - ?line [[<<207,135>>,<<" ">>],[<<"b c d">>]] = - re:split([967]++" b c d","( +)", - [{parts,2},group,{return,binary},unicode]), - ?line {'EXIT',{badarg,_}} = - (catch re:split([967]++" b c d","( +)", - [{parts,2},group,{return,binary}])), - ?line {'EXIT',{badarg,_}} = - (catch re:split("a b c d","( +)",[{parts,-2}])), - ?line {'EXIT',{badarg,_}} = - (catch re:split("a b c d","( +)",[{parts,banan}])), - ?line {'EXIT',{badarg,_}} = - (catch re:split("a b c d","( +)",[{capture,all}])), - ?line {'EXIT',{badarg,_}} = - (catch re:split("a b c d","( +)",[{capture,[],binary}])), + ok = splittest("a b c ","( )",[group,trim],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]]), + ok = splittest("a b c ","( )",[group,{parts,0}],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]]), + ok = splittest("a b c ","( )",[{parts,infinity},group],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]]), + ok = splittest("a b c ","( )",[group],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]]), + ok = splittest(" a b c d ","( +)",[group,trim],[[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<"d">>,<<" ">>]]), + ok = splittest(" a b c d ","( +)",[{parts,0},group],[[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<"d">>,<<" ">>]]), + ok = splittest(" a b c d ","( +)",[{parts,infinity},group],[[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<"d">>,<<" ">>],[<<>>]]), + ok = splittest("a b c d","( +)",[{parts,2},group],[[<<"a">>,<<" ">>],[<<"b c d">>]]), + ok = splittest([967]++" b c d","( +)",[{parts,2},group,{return,list},unicode],[[[967]," "],["b c d"]]), + ok = splittest([967]++" b c d","( +)",[{parts,2},group,{return,binary},unicode],[[<<207,135>>,<<" ">>],[<<"b c d">>]]), + {'EXIT',{badarg,_}} = (catch re:split([967]++" b c d","( +)",[{parts,2},group,{return,binary}])), + {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{parts,-2}])), + {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{parts,banan}])), + {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{capture,all}])), + {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{capture,[],binary}])), % Parts 0 is equal to no parts specification (implicit strip) - ?line ["a"," ","b"," ","c"," ","d"] = - re:split("a b c d","( *)",[{parts,0},{return,list}]), + ok = splittest("a b c d","( *)",[{parts,0},{return,list}],["a"," ","b"," ","c"," ","d"]), ?t:timetrap_cancel(Dog), ok. diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index a1f2a946b1..3387d74e57 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 2.5 +STDLIB_VSN = 2.6 diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 3f2a3e05dd..97b5797b06 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -355,7 +355,7 @@ %% where `Pos' `Ann' and `Comments' are the corresponding values of a %% `tree' or `wrapper' record. --record(attr, {pos = 0 :: term(), +-record(attr, {pos = erl_anno:new(0) :: term(), ann = [] :: [term()], com = none :: 'none' | #com{}}). -type syntaxTreeAttributes() :: #attr{}. diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl index db7f0939a3..f2de12b410 100644 --- a/lib/syntax_tools/src/erl_tidy.erl +++ b/lib/syntax_tools/src/erl_tidy.erl @@ -937,7 +937,7 @@ hidden_uses_2(Tree, Used) -> -record(env, {file :: file:filename(), module :: atom(), - current :: fa(), + current :: fa() | 'undefined', imports = dict:new() :: dict:dict(atom(), atom()), context = normal :: context(), verbosity = 1 :: 0 | 1 | 2, @@ -949,10 +949,10 @@ hidden_uses_2(Tree, Used) -> new_guard_tests = true :: boolean(), old_guard_tests = false :: boolean()}). --record(st, {varc :: non_neg_integer(), +-record(st, {varc :: non_neg_integer() | 'undefined', used = sets:new() :: sets:set({atom(), arity()}), imported :: sets:set({atom(), arity()}), - vars :: sets:set(atom()), + vars :: sets:set(atom()) | 'undefined', functions :: sets:set({atom(), arity()}), new_forms = [] :: [erl_syntax:syntaxTree()], rename :: dict:dict(mfa(), {atom(), atom()})}). @@ -1064,13 +1064,13 @@ visit_clause(Tree, Env, St0) -> visit_infix_expr(Tree, #env{context = guard_test}, St0) -> %% Detect transition from guard test to guard expression. - visit_other(Tree, #env{context = guard_expr}, St0); + visit_other(Tree, #env{context = guard_expr, file = ""}, St0); visit_infix_expr(Tree, Env, St0) -> visit_other(Tree, Env, St0). visit_prefix_expr(Tree, #env{context = guard_test}, St0) -> %% Detect transition from guard test to guard expression. - visit_other(Tree, #env{context = guard_expr}, St0); + visit_other(Tree, #env{context = guard_expr, file = ""}, St0); visit_prefix_expr(Tree, Env, St0) -> visit_other(Tree, Env, St0). diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl index eac5af5540..4557678f9d 100644 --- a/lib/syntax_tools/src/igor.erl +++ b/lib/syntax_tools/src/igor.erl @@ -1594,10 +1594,11 @@ alias_expansions_2(Modules, Table) -> preserved :: boolean(), no_headers :: boolean(), notes :: notes(), - map :: map_fun(), + map :: map_fun() | 'undefined', renaming :: fun((atom()) -> map_fun()), expand :: dict:dict({atom(), integer()}, - {atom(), {atom(), integer()}}), + {atom(), {atom(), integer()}}) + | 'undefined', redirect :: dict:dict(atom(), atom()) }). diff --git a/lib/syntax_tools/src/merl.erl b/lib/syntax_tools/src/merl.erl index 690306c17b..163ce48bbc 100644 --- a/lib/syntax_tools/src/merl.erl +++ b/lib/syntax_tools/src/merl.erl @@ -514,15 +514,17 @@ parse_forms([]) -> parse_2(Ts) -> %% one or more comma-separated expressions? %% (recall that Ts has no dot tokens if we get to this stage) - case erl_parse:parse_exprs(Ts ++ [{dot,0}]) of + A = a0(), + case erl_parse:parse_exprs(Ts ++ [{dot,A}]) of {ok, Exprs} -> Exprs; {error, E} -> - parse_3(Ts ++ [{'end',0}, {dot,0}], [E]) + parse_3(Ts ++ [{'end',A}, {dot,A}], [E]) end. parse_3(Ts, Es) -> %% try-clause or clauses? - case erl_parse:parse_exprs([{'try',0}, {atom,0,true}, {'catch',0} | Ts]) of + A = a0(), + case erl_parse:parse_exprs([{'try',A}, {atom,A,true}, {'catch',A} | Ts]) of {ok, [{'try',_,_,_,_,_}=X]} -> %% get the right kind of qualifiers in the clause patterns erl_syntax:try_expr_handlers(X); @@ -533,7 +535,8 @@ parse_3(Ts, Es) -> parse_4(Ts, Es) -> %% fun-clause or clauses? (`(a)' is also a pattern, but `(a,b)' isn't, %% so fun-clauses must be tried before normal case-clauses - case erl_parse:parse_exprs([{'fun',0} | Ts]) of + A = a0(), + case erl_parse:parse_exprs([{'fun',A} | Ts]) of {ok, [{'fun',_,{clauses,Cs}}]} -> Cs; {error, E} -> parse_5(Ts, [E|Es]) @@ -541,7 +544,8 @@ parse_4(Ts, Es) -> parse_5(Ts, Es) -> %% case-clause or clauses? - case erl_parse:parse_exprs([{'case',0}, {atom,0,true}, {'of',0} | Ts]) of + A = a0(), + case erl_parse:parse_exprs([{'case',A}, {atom,A,true}, {'of',A} | Ts]) of {ok, [{'case',_,_,Cs}]} -> Cs; {error, E} -> %% select the best error to report @@ -1210,7 +1214,7 @@ merge_comments(StartLine, Cs, [], Acc) -> merge_comments(StartLine, [], [], [erl_syntax:set_pos( erl_syntax:comment(Indent, Text), - StartLine + Line - 1) + anno(StartLine + Line - 1)) || {Line, _, Indent, Text} <- Cs] ++ Acc); merge_comments(StartLine, [C|Cs], [T|Ts], Acc) -> {Line, _Col, Indent, Text} = C, @@ -1228,3 +1232,9 @@ merge_comments(StartLine, [C|Cs], [T|Ts], Acc) -> [erl_syntax:comment(Indent, Text)], T), merge_comments(StartLine, Cs, [Tc|Ts], Acc) end. + +a0() -> + anno(0). + +anno(Location) -> + erl_anno:new(Location). diff --git a/lib/syntax_tools/src/merl_transform.erl b/lib/syntax_tools/src/merl_transform.erl index 66b06c8137..fe58b6a122 100644 --- a/lib/syntax_tools/src/merl_transform.erl +++ b/lib/syntax_tools/src/merl_transform.erl @@ -68,8 +68,7 @@ case_guard([{expr,_}, {text,Text}]) -> erl_syntax:is_literal(Text). case_body([{expr,Expr}, {text,_Text}], T) -> - pre_expand_case(Expr, erl_syntax:case_expr_clauses(T), - erl_syntax:get_pos(T)). + pre_expand_case(Expr, erl_syntax:case_expr_clauses(T), get_location(T)). post(T) -> merl:switch( @@ -79,7 +78,7 @@ post(T) -> lists:all(fun erl_syntax:is_literal/1, [F|As]) end, fun ([{args, As}, {function, F}]) -> - Line = erl_syntax:get_pos(F), + Line = get_location(F), [F1|As1] = lists:map(fun erl_syntax:concrete/1, [F|As]), eval_call(Line, F1, As1, T) end}, @@ -118,7 +117,7 @@ expand_qquote(_As, T, _StartPos) -> expand_template(F, [Pattern | Args], T) -> case erl_syntax:is_literal(Pattern) of true -> - Line = erl_syntax:get_pos(Pattern), + Line = get_location(Pattern), As = [erl_syntax:concrete(Pattern)], merl:qquote(Line, "merl:_@function(_@pattern, _@args)", [{function, F}, @@ -260,3 +259,12 @@ is_erlang_var([C|_]) when C >= $A, C =< $Z ; C >= $À, C =< $Þ, C /= $× -> true; is_erlang_var(_) -> false. + +get_location(T) -> + Pos = erl_syntax:get_pos(T), + case erl_anno:is_anno(Pos) of + true -> + erl_anno:location(Pos); + false -> + Pos + end. diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml index 939a07dcef..da956de9ef 100644 --- a/lib/test_server/doc/src/notes.xml +++ b/lib/test_server/doc/src/notes.xml @@ -298,7 +298,7 @@ configuration function or test specification term), the affected test cases get the status <c>user_skipped</c> instead.</p> <p>This update has meant a few changes that - may affect Common Test users in various ways: <list> + may affect Common Test users in various ways:</p> <list> <item>The test results and statistics will be affected, which is important to know when running regression tests and comparing results to previous test runs.</item> @@ -318,7 +318,7 @@ <c>auto_skipped</c> rather than <c>user_skipped</c> as before.</item> <item>The event messages that Common Test generates during test runs have been affected by this - update. For details see OTP-11524.</item> </list> </p> + update. For details see OTP-11524.</item> </list> <p> Own Id: OTP-11305 Aux Id: OTP-11524 </p> </item> @@ -445,7 +445,7 @@ that were not opened with the {encoding,utf8} option. If then the argument contained unicode characters above 255, the file descriptor would crash. This has been corrected - by the following modifications: <list> <item> Since the + by the following modifications:</p> <list> <item> Since the 'unexpected_io' log file is used only when the test case HTML file is not available (e.g. between test cases), this file is now also a HTML file and as other @@ -467,7 +467,7 @@ path to the last run.<timestamp> directory, is now dependent on the file name mode of the VM. If file names are expected to be unicode, then the 'last_name' file is - UTF-8 encoded, else it is latin1 encoded. </item> </list></p> + UTF-8 encoded, else it is latin1 encoded. </item> </list> <p> Also, ~tp has been changed back to ~p unless it is somehow likely that the argument includes strings. It is @@ -615,7 +615,7 @@ </item> <item> <p> - Update common test modules to handle unicode <list> + Update common test modules to handle Unicode:</p> <list> <item> Use UTF-8 encoding for all HTML files, except the HTML version of the test suite generated with erl2html2:convert, which will have the same encoding as @@ -626,7 +626,7 @@ unicode:characters_to_list and unicode:characters_to_binary for conversion between binaries and strings instead of binary_to_list and - list_to_binary. </item> </list></p> + list_to_binary. </item> </list> </item> </list> </section> diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl index 2c63103264..e281c9de1b 100644 --- a/lib/test_server/src/erl2html2.erl +++ b/lib/test_server/src/erl2html2.erl @@ -170,23 +170,32 @@ get_line(Anno) -> %%%----------------------------------------------------------------- %%% Find the line number of the last expression in the function find_clause_lines([{clause,CL,_Params,_Op,Exprs}], CLs) -> % last clause - try tuple_to_list(lists:last(Exprs)) of - [_Type,ExprLine | _] when is_integer(ExprLine) -> - {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(ExprLine)}; - [tree,_ | Exprs1] -> + case classify_exprs(Exprs) of + {anno, Anno} -> + {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(Anno)}; + {tree, Exprs1} -> find_clause_lines([{clause,CL,undefined,undefined,Exprs1}], CLs); - [macro,{_var,ExprLine,_MACRO} | _] when is_integer(ExprLine) -> - {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(ExprLine)}; - _ -> - {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(CL)} - catch - _:_ -> + unknown -> {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(CL)} end; - find_clause_lines([{clause,CL,_Params,_Op,_Exprs} | Cs], CLs) -> find_clause_lines(Cs, [{clause,get_line(CL)}|CLs]). +classify_exprs(Exprs) -> + case tuple_to_list(lists:last(Exprs)) of + [macro,{_var,Anno,_MACRO} | _] -> + {anno, Anno}; + [T,ExprAnno | Exprs1] -> + case erl_anno:is_anno(ExprAnno) of + true -> + {anno, ExprAnno}; + false when T =:= tree -> + {tree, Exprs1}; + false -> + unknown + end + end. + %%%----------------------------------------------------------------- %%% Add a link target for each line and one for each function definition. build_html(SFd,DFd,Encoding,FuncsAndCs) -> diff --git a/lib/test_server/src/test_server_gl.erl b/lib/test_server/src/test_server_gl.erl index c5ec3ccbe6..31098d9726 100644 --- a/lib/test_server/src/test_server_gl.erl +++ b/lib/test_server/src/test_server_gl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012-2013. All Rights Reserved. +%% Copyright Ericsson AB 2012-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ -export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2]). -record(st, {tc_supervisor :: 'none'|pid(), %Test case supervisor - tc :: mfa(), %Current test case MFA + tc :: mfa() | 'undefined', %Current test case MFA minor :: 'none'|pid(), %Minor fd minor_monitor, %Monitor ref for minor fd capture :: 'none'|pid(), %Capture output diff --git a/lib/test_server/src/ts_lib.erl b/lib/test_server/src/ts_lib.erl index 61bd55a654..7c3f450194 100644 --- a/lib/test_server/src/ts_lib.erl +++ b/lib/test_server/src/ts_lib.erl @@ -250,12 +250,10 @@ do_test(Rest, Vars, Test) -> {Result,Comment,Rest2}. %% extract an argument -get_arg([$ |Rest], Vars, Stop, Acc) -> - get_arg(Rest, Vars, Stop, Acc); get_arg([$(|Rest], Vars, Stop, _) -> get_arg(Rest, Vars, Stop, []); get_arg([Stop|Rest], Vars, Stop, Acc) -> - Arg = lists:reverse(Acc), + Arg = string:strip(lists:reverse(Acc)), Subst = subst(Arg, Vars), {Subst,Rest}; get_arg([C|Rest], Vars, Stop, Acc) -> diff --git a/lib/tools/Makefile b/lib/tools/Makefile index 2699ffab51..fef33743c0 100644 --- a/lib/tools/Makefile +++ b/lib/tools/Makefile @@ -24,7 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # Macros # ---------------------------------------------------- -SUB_DIRECTORIES = c_src src doc/src examples priv emacs +SUB_DIRECTORIES = c_src src doc/src examples emacs include vsn.mk VSN = $(TOOLS_VSN) diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in index 66bba229f6..e8bce149b1 100644 --- a/lib/tools/c_src/Makefile.in +++ b/lib/tools/c_src/Makefile.in @@ -97,11 +97,8 @@ DRIVERS= ifneq ($(strip $(ETHR_LIB_NAME)),) # Need ethread package for emem -ifneq ($(findstring ose,$(TARGET)),ose) -# Do not build on OSE PROGS += $(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@ endif -endif EMEM_OBJ_DIR=$(OBJ_DIR)/emem CREATE_DIRS += $(EMEM_OBJ_DIR) @@ -152,12 +149,7 @@ ERTS_LIB = $(ERL_TOP/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE _create_dirs := $(shell mkdir -p $(CREATE_DIRS)) -ifneq ($(findstring ose,$(TARGET)),ose) all: $(PROGS) $(DRIVERS) -else -# Do not build dynamic files on OSE -all: -endif $(ERTS_LIB): $(make_verbose)cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE) diff --git a/lib/tools/doc/src/cover_chapter.xml b/lib/tools/doc/src/cover_chapter.xml index 2f7f8d8083..c3f1570477 100644 --- a/lib/tools/doc/src/cover_chapter.xml +++ b/lib/tools/doc/src/cover_chapter.xml @@ -451,48 +451,5 @@ ok <p>When Cover is stopped, all Cover compiled modules are unloaded.</p> </section> </section> - - <section> - <title>Using the Web Based User Interface to Cover</title> - - <section> - <title>Introduction</title> - <p>To ease the use of Cover there is a web based user interface - to Cover called WebCover. WebCover is designed to be started - and used via WebTool. It is possible to Cover compile Erlang - modules and to generate printable Cover and Call analyses via - the web based user interface.</p> - </section> - - <section> - <title>Start the Web Based User Interface to Cover</title> - <p>To start WebCover you can either start WebTool, point a - browser to the start page of WebTool and start WebCover from - there, or you can use the <c>start_webtool</c> script to start - Webtool, WebCover and a browser. See WebTool documentation for - further information.</p> - <p>Currently WebCover is only compatible - with Internet Explorer and Netscape Navigator 4.0 and higher.</p> - </section> - - <section> - <title>Navigating WebCover</title> - <p>From the menu in the lefthand frame you can select the - <c>Nodes</c>, <c>Compile</c>, <c>Import</c> or <c>Result</c> - page.</p> - <p>From the <c>Nodes</c> page you can add remote nodes to - participate in the coverage analysis. Coverage data from all - involved nodes will then be merged during analysis.</p> - <p>From the <c>Compile</c> page you can Cover compile <c>.erl</c> - or <c>.beam</c> files.</p> - <p>From the <c>Import</c> page you can import coverage data from - a previous analysis. Imported data will then be merged with - the current coverage data. <em>Note</em> that it is only possible to - import files with the extension <c>.coverdata</c>.</p> - <p>From the <c>Result</c> page you can analyse, reset or export - coverage data.</p> - <p>Please follow the instructions on each page.</p> - </section> - </section> </chapter> diff --git a/lib/tools/doc/src/eprof.xml b/lib/tools/doc/src/eprof.xml index 7dccd927ca..8e37d49c99 100644 --- a/lib/tools/doc/src/eprof.xml +++ b/lib/tools/doc/src/eprof.xml @@ -131,13 +131,13 @@ <name>analyze() -> ok</name> <name>analyze(Type) -> ok</name> <name>analyze(Type,Options) -> ok</name> + <fsummary>Display profiling results per process.</fsummary> <type> <v>Type = procs | total</v> <v>Options = [{filter, Filter} | {sort, Sort}</v> <v>Filter = [{calls, integer()} | {time, float()}]</v> <v>Sort = time | calls | mfa</v> </type> - <fsummary>Display profiling results per process.</fsummary> <desc> <p>Call this function when profiling has been stopped to display the results per process, that is:</p> diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index e788814564..bf27d2a3e5 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -31,6 +31,25 @@ </header> <p>This document describes the changes made to the Tools application.</p> +<section><title>Tools 2.8.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + If a module includes eunit.hrl, a parse transform adds + the function test/0 on line 0 in the module. A bug in + OTP-18.0 caused cover:analyse_to_file/1 to fail to insert + cover data in the output file when line 0 existed in the + cover data table. This is now corrected.</p> + <p> + Own Id: OTP-12981</p> + </item> + </list> + </section> + +</section> + <section><title>Tools 2.8</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el index 4aa1ab7d38..466bf139b9 100644 --- a/lib/tools/emacs/erlang.el +++ b/lib/tools/emacs/erlang.el @@ -4236,7 +4236,7 @@ This function is designed to be a member of a criteria list." This function is designed to be a member of a criteria list." (save-excursion (beginning-of-line) - (when (save-match-data (looking-at "-\\(spec\\|type\\)")) + (when (save-match-data (looking-at "-\\(spec\\|type\\|callback\\)")) 'stop))) diff --git a/lib/ose/doc/html/.gitignore b/lib/tools/priv/.gitignore index e69de29bb2..e69de29bb2 100644 --- a/lib/ose/doc/html/.gitignore +++ b/lib/tools/priv/.gitignore diff --git a/lib/tools/priv/Makefile b/lib/tools/priv/Makefile deleted file mode 100644 index aa4aaa2fc8..0000000000 --- a/lib/tools/priv/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# ``Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# The Initial Developer of the Original Code is Ericsson Utvecklings AB. -# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -# AB. All Rights Reserved.'' -# -# $Id$ -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../vsn.mk -VSN = $(TOOLS_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -HTDOCS_FILES = index.html - -TOOL_FILES = cover.tool - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: - -clean: - -docs: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/priv" - $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv" - $(INSTALL_DATA) $(TOOL_FILES) "$(RELSYSDIR)/priv" - -release_docs_spec: - - - diff --git a/lib/tools/priv/cover.tool b/lib/tools/priv/cover.tool deleted file mode 100644 index 9e72f89ff4..0000000000 --- a/lib/tools/priv/cover.tool +++ /dev/null @@ -1,2 +0,0 @@ -{version,"1.2"}. -[{config_func,{cover_web,configData,[]}}]. diff --git a/lib/tools/priv/index.html b/lib/tools/priv/index.html deleted file mode 100644 index 6b60ef5d0a..0000000000 --- a/lib/tools/priv/index.html +++ /dev/null @@ -1,10 +0,0 @@ -<HTML> -<HEAD> -<TITLE>Erlang webb tools </TITLE> -</HEAD> -<FRAMESET COLS="250,*"> -<FRAME NAME="menu" SRC="/webcover/erl/cover_web/menu_frame"> -<FRAME NAME="main" SRC="/webcover/erl/cover_web/compile_frame"> -</FRAMESET> -</HTML> - diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile index 9fcfb79628..7301ff856a 100644 --- a/lib/tools/src/Makefile +++ b/lib/tools/src/Makefile @@ -37,7 +37,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(VSN) MODULES= \ cover \ - cover_web \ eprof \ fprof \ cprof \ diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 8d1cb96504..1d7d112c06 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -20,9 +20,7 @@ -module(cover). %% -%% This module implements the Erlang coverage tool. The module named -%% cover_web implements a user interface for the coverage tool to run -%% under webtool. +%% This module implements the Erlang coverage tool. %% %% ARCHITECTURE %% The coverage tool consists of one process on each node involved in @@ -2437,7 +2435,7 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) -> "\n\n"]), Pattern = {#bump{module=Module,line='$1',_='_'},'$2'}, - MS = [{Pattern,[],[{{'$1','$2'}}]}], + MS = [{Pattern,[{is_integer,'$1'},{'>','$1',0}],[{{'$1','$2'}}]}], CovLines = lists:keysort(1,ets:select(?COLLECTION_TABLE, MS)), print_lines(Module, CovLines, InFd, OutFd, 1, HTML), diff --git a/lib/tools/src/cover_web.erl b/lib/tools/src/cover_web.erl deleted file mode 100644 index ae8b3f25cf..0000000000 --- a/lib/tools/src/cover_web.erl +++ /dev/null @@ -1,1185 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(cover_web). --author('[email protected]'). --behaviour(gen_server). - -%%Export of configuration function --export([configData/0]). -%% External exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). - --export([start_link/0,start/0,stop/0]). --export([menu_frame/2,nodes_frame/2,import_frame/2, - compile_frame/2,result_frame/2]). --export([list_dir/2,compile/2,add_node/2,remove_node/2,result/2, - calls/2,coverage/2,import/2]). - --record(state,{dir}). - --include_lib("kernel/include/file.hrl"). - -%% Timeouts --define(DEFAULT_TIME,10000). --define(MAX_COMPILE_TIME,60000). --define(MAX_ANALYSE_TIME,30000). - -%% Colors --define(INFO_BG_COLOR,"#C0C0EA"). - -%%%---------------------------------------------------------------------- -%%% API - called from erlang shell -%%%---------------------------------------------------------------------- -%% Start webtool and webcover from erlang shell -start() -> - webtool:start(), - webtool:start_tools([],"app=webcover"), - ok. - -%% Stop webtool and webcover from erlang shell -stop() -> - webtool:stop_tools([],"app=webcover"), - webtool:stop(). - - - -%%%---------------------------------------------------------------------- -%%% API - called from webtool -%%%---------------------------------------------------------------------- -start_link() -> - gen_server:start_link({local, webcover_server},cover_web, [], []). - - -nodes_frame(Env,Input)-> - call({nodes_frame,Env,Input}). - -add_node(Env,Input)-> - call({add_node,Env,Input}). - -remove_node(Env,Input)-> - call({remove_node,Env,Input}). - -compile_frame(Env,Input)-> - call({compile_frame,Env,Input}). - -list_dir(Env,Input) -> - call({list_dir,Env,Input}). - -compile(Env,Input)-> - call({compile,Env,Input},?MAX_COMPILE_TIME). - -result_frame(Env,Input)-> - call({result_frame,Env,Input}). - -result(Env,Input) -> - call({result,Env,Input},?MAX_ANALYSE_TIME). - -calls(Env,Input) -> - call({calls,Env,Input}). - -coverage(Env,Input) -> - call({coverage,Env,Input}). - -import_frame(Env,Input)-> - call({import_frame,Env,Input}). - -import(Env,Input)-> - call({import,Env,Input}). - -menu_frame(Env,Input)-> - call({menu_frame,Env,Input}). - -call(Msg) -> - call(Msg,?DEFAULT_TIME). -call(Msg,Time) -> - gen_server:call(webcover_server,Msg,Time). - - - -configData()-> - {webcover,[{web_data,{"WebCover","/webcover"}}, - {alias,{"/webcover",code:priv_dir(tools)}}, - {alias,{erl_alias,"/webcover/erl",[cover_web]}}, - {start,{child,{{local,webcover_server}, - {cover_web,start_link,[]}, - permanent,100,worker,[cover_web]}}} - ]}. - - -%%%---------------------------------------------------------------------- -%%% Callback functions from gen_server -%%%---------------------------------------------------------------------- - -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%%---------------------------------------------------------------------- -init([]) -> - cover:start(), - CS = whereis(cover_server), - link(CS), - GL = spawn_link(fun group_leader_proc/0), - group_leader(GL,CS), - - %% Must trap exists in order to have terminate/2 executed when - %% crashing because of a linked process crash. - process_flag(trap_exit,true), - {ok,Cwd} = file:get_cwd(), - {ok, #state{dir=Cwd}}. - -group_leader_proc() -> - register(cover_group_leader_proc,self()), - group_leader_loop([]). -group_leader_loop(Warnings) -> - receive - {io_request,From,ReplyAs,{put_chars,io_lib,Func,[Format,Args]}} -> - Msg = (catch io_lib:Func(Format,Args)), - From ! {io_reply,ReplyAs,ok}, - case lists:member(Msg,Warnings) of - true -> group_leader_loop(Warnings); - false -> group_leader_loop([Msg|Warnings]) - end; - {io_request,From,ReplyAs,{put_chars,_Encoding,io_lib,Func,[Format,Args]}} -> - Msg = (catch io_lib:Func(Format,Args)), - From ! {io_reply,ReplyAs,ok}, - case lists:member(Msg,Warnings) of - true -> group_leader_loop(Warnings); - false -> group_leader_loop([Msg|Warnings]) - end; - IoReq when element(1,IoReq)=:= io_request -> - group_leader() ! IoReq, - group_leader_loop(Warnings); - {From,get_warnings} -> - Warnings1 = - receive - {io_request,From,ReplyAs, - {put_chars,io_lib,Func,[Format,Args]}} -> - Msg = (catch io_lib:Func(Format,Args)), - From ! {io_reply,ReplyAs,ok}, - case lists:member(Msg,Warnings) of - true -> Warnings; - false -> [Msg|Warnings] - end - after 0 -> - Warnings - end, - From ! {warnings,Warnings1}, - group_leader_loop([]) - end. - -%%---------------------------------------------------------------------- -%% Func: handle_call/3 -%% Returns: {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | (terminate/2 is called) -%% {stop, Reason, State} (terminate/2 is called) -%%---------------------------------------------------------------------- -handle_call({nodes_frame,_Env,_Input},_From,State)-> - {reply,nodes_frame1(),State}; - -handle_call({add_node,_Env,Input},_From,State)-> - {reply,do_add_node(Input),State}; - -handle_call({remove_node,_Env,Input},_From,State)-> - {reply,do_remove_node(Input),State}; - -handle_call({compile_frame,_Env,_Input},_From,State)-> - {reply,compile_frame1(State#state.dir),State}; - -handle_call({list_dir,_Env,Input},_From,State)-> - Dir = get_input_data(Input,"path"), - case filelib:is_dir(Dir) of - true -> - {reply,compile_frame1(Dir),State#state{dir=Dir}}; - false -> - Err = Dir ++ " is not a directory", - {reply,compile_frame1(State#state.dir,Err),State} - end; -handle_call({compile,_Env,Input},_From,State)-> - {reply,do_compile(Input,State#state.dir),State}; - -handle_call({result_frame,_Env,_Input},_From,State)-> - {reply,result_frame1(),State}; - -handle_call({result,_Env,Input},_From,State)-> - {reply,handle_result(Input),State}; - -handle_call({calls,_Env,Input},_From,State)-> - {reply,call_page(Input),State}; - -handle_call({coverage,_Env,Input},_From,State)-> - {reply,coverage_page(Input),State}; - -handle_call({import_frame,_Env,_Input},_From,State)-> - {ok,Cwd} = file:get_cwd(), - {reply,import_frame1(Cwd),State}; - -handle_call({import,_Env,Input},_From,State)-> - {reply,do_import(Input),State}; - -handle_call({menu_frame,_Env,_Input},_From,State)-> - {reply,menu_frame1(),State}; - -handle_call(_Request, _From, State) -> - Reply = bad_request, - {reply, Reply, State}. - - -%%---------------------------------------------------------------------- -%% Func: handle_cast/2 -%% Returns: {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} (terminate/2 is called) -%%---------------------------------------------------------------------- -handle_cast(_Msg, State) -> - {noreply, State}. - -%%---------------------------------------------------------------------- -%% Func: handle_info/2 -%% Returns: {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} (terminate/2 is called) -%%---------------------------------------------------------------------- -handle_info({'EXIT',_Pid,Reason}, State) -> - {stop, Reason, State}. - -%%---------------------------------------------------------------------- -%% Func: terminate/2 -%% Purpose: Shutdown the server -%% Returns: any (ignored by gen_server) -%%---------------------------------------------------------------------- -terminate(_Reason, _State) -> - cover:stop(), - ok. - -%%-------------------------------------------------------------------- -%% Func: code_change/3 -%% Purpose: Convert process state when code is changed -%% Returns: {ok, NewState} -%%-------------------------------------------------------------------- -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%%---------------------------------------------------------------------- -%%% Internal functions -%%%---------------------------------------------------------------------- - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The functions that creates the whole pages by collecting all the %% -%% neccessary data for each page. These functions are the public %% -%% interface. %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%---------------------------------------------------------------------- -%% Returns the page to the left frame -%%---------------------------------------------------------------------- -menu_frame1()-> - [header(),html_header(""),menu_body(),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user can add and remove nodes -%%---------------------------------------------------------------------- - -nodes_frame1()-> - nodes_frame1([]). -nodes_frame1(Err)-> - [header(),html_header("Add/remove nodes"),nodes_body(Err),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user can cover compile modules -%%---------------------------------------------------------------------- - -compile_frame1(Dir)-> - compile_frame1(Dir,[]). -compile_frame1(Dir,Err) -> - [header(),html_header("Cover compile"),compile_body(Dir,Err),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user can handle results -%%---------------------------------------------------------------------- - -result_frame1()-> - result_frame1([]). -result_frame1(Err) -> - [header(),html_header("Show cover results"),result_body(Err),html_end()]. - -%%---------------------------------------------------------------------- -%%The beginning of the page that clear the cover information on a cover -%%compiled module -%%---------------------------------------------------------------------- -call_page(Input)-> - [header(),html_header("Code coverage"),call_result(Input),html_end()]. - -coverage_page(Input)-> - [header(),html_header("Code coverage"),coverage_result(Input),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user an import files -%%---------------------------------------------------------------------- -import_frame1(Dir) -> - import_frame1(Dir,""). -import_frame1(Dir,Err) -> - [header(),html_header("Import coverdata"),import_body(Dir,Err),html_end()]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The functions that build the body of the menu frame %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -menu_body() -> - Nodes = cover:which_nodes(), - Modules = cover:modules(), - Imported = cover:imported(), - ["<A HREF=\"./nodes_frame\" TARGET=\"main\">Nodes</A><BR>\n", - "<A HREF=\"./compile_frame\" TARGET=\"main\">Compile</A><BR>\n", - "<A HREF=\"./import_frame\" TARGET=\"main\">Import</A><BR>\n", - "<A HREF=\"./result_frame\" TARGET=\"main\">Result</A>\n", - "<P><B>Nodes:</B>\n", - "<UL>\n", - lists:map(fun(N) -> "<LI>"++atom_to_list(N)++"</LI>\n" end,[node()|Nodes]), - "</UL>\n", - "<P><B>Compiled modules:</B>\n", - "<UL>\n", - lists:map(fun(M) -> "<LI>"++atom_to_list(M)++"</LI>\n" end,Modules), - "</UL>\n", - "<P><B>Imported files:</B>\n", - "<UL>\n", - "<FONT SIZE=-1>\n", - lists:map(fun(F) -> - Short = filename:basename(F), - "<LI TITLE=\""++F++"\">"++Short++"</LI>\n" end,Imported), - "</FONT>\n", - "</UL>\n"]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The functions that build the body of the nodes frame %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nodes_body(Err) -> - CN = cover:which_nodes(), - Fun = fun(N) -> - NStr = atom_to_list(N), - ["<OPTION VALUE=",NStr, - " onClick=\"node.value=selected_node.value\">",NStr, - "</OPTION>\n"] - end, - AllNodes = lists:append(lists:map(Fun,nodes()--CN)), - CoverNodes = lists:append(lists:map(Fun,CN)), - - [reload_menu_script(Err), - "<H1 ALIGN=center>Nodes</H1>\n", - "<TABLE BORDER=0 WIDTH=600 ALIGN=center>\n", - "<TR><TD BGCOLOR=",?INFO_BG_COLOR," COLSPAN=2>\n", - "<P>You can run cover over several nodes simultaneously. Coverage data\n", - "from all involved nodes will be merged during analysis.\n", - "<P>Select or enter node names to add or remove here.\n", - "</TD></TR>\n", - "<TR><TD COLSPAN=2><BR><BR></TD></TR>\n", - "<FORM ACTION=\"./add_node\" NAME=add_node>\n", - "<TR><TD VALIGN=top>Add node:</TD>\n", - "<TD><INPUT TYPE=text NAME=\"node\" SIZE=40 >", - "<INPUT TYPE=submit\n", - " onClick=\"if(!node.value){node.value=selected_node.value};\" VALUE=Add>" - "<BR><SELECT NAME=selected_node TITLE=\"Select node\">\n", - AllNodes ++ - "</SELECT>\n", - "</TD></TR>\n" - "</FORM>\n", - "<TR><TD COLSPAN=2><BR><BR></TD></TR>\n", - "<FORM ACTION=\"./remove_node\" NAME=remove_node>\n", - "<TR><TD>Remove node:</TD>\n", - "<TD><SELECT NAME=node TITLE=\"Select node\">\n", - CoverNodes ++ - "</SELECT>\n", - "<INPUT TYPE=submit VALUE=Remove>" - "</TD></TR>\n", - "</FORM>", - "</TABLE>"]. - - -do_add_node(Input) -> - NodeStr = get_input_data(Input, "node"), - Node = list_to_atom(NodeStr), - case net_adm:ping(Node) of - pong -> - cover:start(Node), - nodes_frame1(); - pang -> - nodes_frame1("Node \\\'" ++ NodeStr ++ "\\\' is not alive") - end. - -do_remove_node(Input) -> - Node = list_to_atom(get_input_data(Input, "node")), - cover:stop(Node), - nodes_frame1(). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that is used when the user wants to compile something % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -compile_body(Dir,Err) -> - Erls = filelib:wildcard(filename:join(Dir,"*.erl")), - Beams = filelib:wildcard(filename:join(Dir,"*.beam")), - - [reload_menu_script(Err), - "<H1 ALIGN=center>Compile</H1>\n", - "<TABLE WIDTH=600 ALIGN=center BORDER=0>\n", - "<TR><TD COLSPAN=3 BGCOLOR=",?INFO_BG_COLOR,">\n", - "Each module which shall be part of the cover analysis must be prepared\n", - "or 'cover compiled'. On this page you can select .erl files and/or\n", - ".beam files to include in the analysis. If you select a .erl file it\n", - "will first be compiled with the Erlang compiler and then prepared for\n", - "coverage analysis. If you select a .beam file it will be prepared for\n", - "coverage analysis directly.\n", - "</TD></TR>\n", - "<FORM ACTION=\"./list_dir\" NAME=list_dir>\n", - "<TR><TD WIDTH=30% BGCOLOR=",?INFO_BG_COLOR," ROWSPAN=2>\n", - "To list a different directory, enter the directory name here.\n", - "</TD>\n", - "<TH COLSPAN=2><BR>List directory:<BR></TH>\n", - "</TR>\n", - "<TR><TD ALIGN=center COLSPAN=2>\n", - "<INPUT TYPE=text NAME=\"path\" SIZE=40 VALUE=",Dir,">", - "<INPUT TYPE=submit VALUE=Ok>", - "<BR><BR></TD></TR>\n", - "</FORM>\n", - "<FORM ACTION=\"./compile\" NAME=compile_selection>\n", - "<TR><TD BGCOLOR=",?INFO_BG_COLOR," ROWSPAN=2>\n", - "<P>Select one or more .erl or .beam files to prepare for coverage\n" - "analysis, and click the \"Compile\" button.\n", - "<P>To reload the original file after coverage analysis is complete,\n" - "select one or more files and click the \"Uncompile\" button, or\n", - "simply click the \"Uncompile all\" button to reload all originals.\n" - "</TD>\n", - "<TH>.erl files</TH><TH>.beam files</TH></TR>\n", - "<TR><TD ALIGN=center VALIGN=top>\n", - "<SELECT NAME=erl TITLE=\"Select .erl files to compile\" MULTIPLE=true", - " SIZE=15>\n", - list_modules(Erls) ++ - "</SELECT></TD>\n", - "<TD ALIGN=center VALIGN=top>\n", - "<SELECT NAME=beam TITLE=\"Select .beam files to compile\"MULTIPLE=true", - " SIZE=15>\n", - list_modules(Beams) ++ - "</SELECT></TD></TR>\n" - "<TR><TD BGCOLOR=",?INFO_BG_COLOR," ROWSPAN=2>\n", - "Compile options are only needed for .erl files. The options must be\n" - "given e.g. like this: \n" - "<FONT SIZE=-1>[{i,\"/my/path/include\"},{i,\"/other/path/\"}]</FONT>\n" - "</TD>\n", - "<TH COLSPAN=2><BR>Compile options:<BR></TH>\n", - "</TR>\n", - "<TR><TD COLSPAN=2 ALIGN=center>\n", - "<INPUT TYPE=text NAME=\"options\" SIZE=40>\n", - "<INPUT TYPE=hidden NAME=\"action\"></TD></TR>\n", - "<TR><TD></TD><TD ALIGN=center COLSPAN=2>\n", - "<INPUT TYPE=submit onClick=\"action.value=\'compile\';\"VALUE=Compile>", - "<INPUT TYPE=submit onClick=\"action.value=\'uncompile\';\" ", - "VALUE=Uncompile>", - "<INPUT TYPE=submit onClick=\"action.value=\'uncompile_all\';\" ", - "VALUE=\"Uncompile all\">", - "<BR><INPUT TYPE=reset VALUE=\"Reset form\"></TD></TR>\n", - "</FORM>\n", - "</TABLE>\n"]. - -list_modules([File|Files]) -> - Mod = filename:basename(File), - ["<OPTION VALUE=",File," onDblClick=\"action.value=\'compile\';submit();\">", - Mod,"</OPTION>\n" | list_modules(Files)]; -list_modules([]) -> - []. - -do_compile(Input,Dir) -> - {Erls,Beams,Opts,Action} = get_compile_input(parse(Input),[],[]), - Errs = - case Action of - "compile" -> - do_compile(Erls,Beams,Opts,[]); - "uncompile" -> - do_uncompile(Erls++Beams); - "uncompile_all" -> - do_uncompile(cover:modules()) - end, - compile_frame1(Dir,Errs). - -get_compile_input([{"erl",File}|Input],Erl,Beam) -> - get_compile_input(Input,[File|Erl],Beam); -get_compile_input([{"beam",File}|Input],Erl,Beam) -> - get_compile_input(Input,Erl,[File|Beam]); -get_compile_input([{"options",Opts0},{"action",Action}],Erl,Beam) -> - Opts = parse_options(Opts0), - {Erl,Beam,Opts,Action}. - -do_compile([Erl|Erls],Beams,Opts,Errs) -> - case cover:compile_module(Erl,Opts) of - {ok,_} -> - do_compile(Erls,Beams,Opts,Errs); - {error,File} -> - do_compile(Erls,Beams,Opts,["\\n"++File|Errs]) - end; -do_compile([],[Beam|Beams],Opts,Errs) -> - case cover:compile_beam(Beam) of - {ok,_} -> - do_compile([],Beams,Opts,Errs); - {error,{no_abstract_code,File}} -> - do_compile([],Beams,Opts,["\\n"++File++" (no_abstract_code)"|Errs]) - end; -do_compile([],[],_,[]) -> - []; -do_compile([],[],_,Errs) -> - "Compilation failed for the following files:" ++ Errs. - -parse_options(Options)-> - case erl_scan:string(Options ++".") of - {ok,Tokens,_Line} -> - case erl_parse:parse_exprs(Tokens) of - {ok,X}-> - case lists:map(fun erl_parse:normalise/1, X) of - [List] when is_list(List) -> List; - List -> List - end; - _ -> - [] - end; - _ -> - [] - end. - - -do_uncompile(Files) -> - lists:foreach( - fun(File) -> - Module = - if is_atom(File) -> - File; - true -> - ModStr = filename:basename(filename:rootname(File)), - list_to_atom(ModStr) - end, - case code:which(Module) of - cover_compiled -> - code:purge(Module), - case code:load_file(Module) of - {module, Module} -> - ok; - {error, _Reason2} -> - code:delete(Module) - end; - _ -> - ok - end - end, - Files), - []. - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the page for coverage analysis% -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -result_body(Err) -> - [reload_menu_script(Err), - "<H1 ALIGN=center>Result</H1>\n", - "<TABLE BORDER=0 WIDTH=600 ALIGN=center>\n", - "<TR><TD BGCOLOR=",?INFO_BG_COLOR,">\n", - "<P>After executing all your tests you can view the result of the\n", - "coverage analysis here. For each module you can\n", - "<DL>\n", - "<DT><B>Analyse to file</B></DT>\n", - "<DD>The source code of the module is shown with the number of calls\n", - "to each line stated in the left margin. Lines which are never called\n", - "are colored red.</DD>\n", - "<DT><B>Analyse coverage</B></DT>\n", - "<DD>Show the number of covered and uncovered lines in the module.</DD>\n", - "<DT><B>Analyse calls</B></DT>\n", - "<DD>Show the number of calls in the module.</DD>\n", - "<DT><B>Reset module</B></DT>\n", - "<DD>Delete all coverage data for the module.</DD>\n", - "<DT><B>Export module</B></DT>\n", - "<DD>Write all coverage data for the module to a file. The data can\n", - "later be imported from the \"Import\" page.</DD>\n", - "</DL>\n", - "<P>You can also reset or export data for all modules with the\n", - "<B>Reset all</B> and <B>Export all</B> actions respectively. For these\n", - "two actions there is no need to select a module.\n", - "<P>Select module and action from the drop down menus below, and click\n", - "the \"Execute\" button.\n", - "</TD></TR>\n", - "<TR><TD><BR><BR>\n", - result_selections(), - "</TD></TR></TABLE>"]. - -result_selections() -> - ModList = filter_modlist(cover:modules()++cover:imported_modules(),[]), - - ["<FORM ACTION=\"./result\" NAME=result_selection>\n", - "<TABLE WIDTH=\"300\" BORDER=0 ALIGN=center>\n", - "<TR><TD ALIGN=left>\n", - "Module:\n", - "<BR><SELECT NAME=module TITLE=\"Select module\">\n", - ModList ++ - "</SELECT>\n", - "</TD>\n", - "<TD ALIGN=left>\n", - "Action:\n", - "<BR><SELECT NAME=action TITLE=\"Select action\">\n", - "<OPTION VALUE=\"analyse_to_file\">Analyse to file</OPTION>\n" - "<OPTION VALUE=\"coverage\">Analyse coverage</OPTION>\n" - "<OPTION VALUE=\"calls\">Analyse calls</OPTION>\n" - "<OPTION VALUE=\"reset\">Reset module</OPTION>\n" - "<OPTION VALUE=\"reset_all\">Reset all</OPTION>\n" - "<OPTION VALUE=\"export\">Export module</OPTION>\n" - "<OPTION VALUE=\"export_all\">Export all</OPTION>\n" - "</SELECT>\n", - "</TD>\n", - "<TD ALIGN=center VALIGN=bottom><INPUT TYPE=submit VALUE=Execute>\n" - "</TD></TR>\n" - "</TABLE>\n", - "</FORM>\n"]. - -filter_modlist([M|Ms],Already) -> - case lists:member(M,Already) of - true -> - filter_modlist(Ms,Already); - false -> - MStr = atom_to_list(M), - ["<OPTION VALUE=",MStr,">",MStr,"</OPTION>\n" | - filter_modlist(Ms,[M|Already])] - end; -filter_modlist([],_Already) -> - []. - - - -handle_result(Input) -> - case parse(Input) of - [{"module",M},{"action",A}] -> - case A of - "analyse_to_file" -> - case cover:analyse_to_file(list_to_atom(M),[html]) of - {ok,File} -> - case file:read_file(File) of - {ok,HTML}-> - file:delete(File), - [header(), - reload_menu_script(""), - binary_to_list(HTML)]; - _ -> - result_frame1("Can not read file" ++ File) - end; - {error,no_source_code_found} -> - result_frame1("No source code found for \\\'" ++ - M ++ "\\\'") - end; - "calls" -> - call_page(Input); - "coverage" -> - coverage_page(Input); - "reset" -> - cover:reset(list_to_atom(M)), - result_frame1("Coverage data for \\\'" ++ M ++ - "\\\' is now reset"); - "reset_all" -> - cover:reset(), - result_frame1("All coverage data is now reset"); - "export" -> - ExportFile = generate_filename(M), - cover:export(ExportFile,list_to_atom(M)), - result_frame1("Coverage data for \\\'" ++ M ++ - "\\\' is now exported to file \\\"" ++ - ExportFile ++ "\\\""); - "export_all" -> - ExportFile = generate_filename("COVER"), - cover:export(ExportFile), - result_frame1( - "All coverage data is now exported to file \\\"" ++ - ExportFile ++ "\\\"") - end; - [{"action",_A}] -> - result_frame1("No module is selected") - end. - -generate_filename(Prefix) -> - {ok,Cwd} = file:get_cwd(), - filename:join(Cwd,Prefix ++ "_" ++ ts() ++ ".coverdata"). - -ts() -> - {{Y,M,D},{H,Min,S}} = calendar:now_to_local_time(erlang:timestamp()), - io_lib:format("~4.4.0w~2.2.0w~2.2.0w-~2.2.0w~2.2.0w~2.2.0w", - [Y,M,D,H,Min,S]). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the page that shows the calls % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -call_result(Input)-> - Mod = list_to_atom(get_input_data(Input, "module")), - case cover:analyse(Mod,calls) of - {error,_}-> - error_body(); - {ok,_} -> - call_result2(Mod,Input) - end. - -call_result2(Mod,Input)-> - Result = - case get_input_data(Input,"what") of - "mod" -> - call_result(mod,Mod); - "func" -> - call_result(func,Mod); - "clause" -> - call_result(clause,Mod); - _-> - call_result(all,Mod) - end, - result_choice("calls",Mod) ++ Result. - -result_choice(Level,Mod)-> - ModStr=atom_to_list(Mod), - [reload_menu_script(""), - "<TABLE WIDTH=100%><TR>\n", - "<TD><A HREF=./",Level,"?module=",ModStr,"&what=all>All Data</A></TD>\n", - "<TD><A HREF=./",Level,"?module=",ModStr,"&what=mod>Module</A></TD>\n", - "<TD><A HREF=./",Level,"?module=",ModStr,"&what=func>Function</A></TD>\n", - "<TD><A HREF=./",Level,"?module=",ModStr,"&what=clause>Clause</A></TD>\n", - "</TR></TABLE><BR>\n"]. - -call_result(Mode,Module)-> - Content = - case Mode of - mod-> - format_cover_call(cover:analyse(Module,calls,module),mod); - func-> - format_cover_call(cover:analyse(Module,calls,function),func); - clause-> - format_cover_call(cover:analyse(Module,calls,clause),clause); - _-> - format_cover_call(cover:analyse(Module,calls,module),mod) ++ - format_cover_call(cover:analyse(Module,calls,function),func)++ - format_cover_call(cover:analyse(Module,calls,clause),clause) - end, - getModDate(Module,date())++"<BR>"++ - "<TABLE WIDTH=\"100%\" BORDER=1>" - ++ Content ++"</TABLE>". - - -format_cover_call({error,_},_)-> - ["<TR><TD>\n", - "<BR><BR><BR><BR>\n", - "<FONT SIZE=5>The selected module is not Cover Compiled</FONT>\n", - "<BR>\n", - "</TD></TR>\n"]; - -format_cover_call({ok,{Mod,Calls}},mod)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=5><B>Module calls</B></TD></TR>\n", - "<TR><TD COLSPAN=4><I>Module</I></TD>", - "<TD ALIGN=\"right\"><I>Number of calls</I></TD></TR>\n", - "<TR><TD COLSPAN=4>" ++ atom_to_list(Mod) ++"</TD>" - "<TD ALIGN=\"right\">" ++ integer_to_list(Calls)++"</TD></TR>\n"]; - -format_cover_call({ok,Calls},func)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=5><B>Function calls</B></TD></TR>\n", - "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>", - "<TD COLSPAN=2 ALIGN=\"right\"><I>Arity</I></TD>", - "<TD ALIGN=\"right\"><I>Number of calls </I></TD></TR>\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity},Nr_of_calls})-> - ["<TR><TD WIDTH=\"20%\">"++ atom_to_list(Mod)++"</TD>\n", - "<TD WIDTH=\"20%\" >" ++ atom_to_list(Func) ++" </TD>\n", - "<TD COLSPAN=2 WIDTH=\"40%\" ALIGN=\"right\">", - integer_to_list(Arity), - "</TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Nr_of_calls), - "</TD></TR>\n"] - end, - Calls))]; - -format_cover_call({ok,Calls},clause)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=5><B>Clause calls</B></TD></TR>\n", - "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>", - "<TD ALIGN=\"right\"><I>Arity</I></TD>", - "<TD ALIGN=\"right\"><I>Ordinal</I></TD>", - "<TD ALIGN=\"right\"><I>Number of calls</I></TD></TR>\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity,Ord},Nr_of_calls})-> - ["<TR><TD WIDTH=\"20%\" >", atom_to_list(Mod), "</TD>\n", - "<TD WIDTH=\"20%\" >", atom_to_list(Func), "</TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Arity), - "</TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Ord), - "</TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Nr_of_calls), - "</TD></TR>\n"] - end, - Calls))]. - - -error_body()-> - ["<TABLE WIDTH=\"100%\" BORDER=1>\n", - "<TR ALIGN=\"center\">\n", - "<TD>\n", - "<BR><BR><BR><BR><BR><BR>\n", - "<FONT SIZE=5>The selected module is not Cover Compiled</FONT>\n", - "<BR>\n", - "</TD>\n", - "</TR>\n", - "</TABLE>\n"]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the page that shows coverage % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -coverage_result(Input)-> - Mod = list_to_atom(get_input_data(Input, "module")), - case cover:analyse(Mod,coverage) of - {error,_}-> - error_body(); - {ok,_} -> - coverage_result2(Mod,Input) - end. - -coverage_result2(Mod,Input)-> - Result = - case get_input_data(Input,"what") of - "mod" -> - coverage_result(mod,Mod); - "func" -> - coverage_result(func,Mod); - "clause" -> - coverage_result(clause,Mod); - _-> - coverage_result(all,Mod) - end, - result_choice("coverage",Mod) ++ Result. - -coverage_result(Mode,Module)-> - Content = - case Mode of - mod-> - format_cover_coverage(cover:analyse(Module,coverage,module), - mod); - func-> - format_cover_coverage(cover:analyse(Module,coverage,function), - func); - clause-> - format_cover_coverage(cover:analyse(Module,coverage,clause), - clause); - _-> - format_cover_coverage(cover:analyse(Module,coverage,module), - mod) ++ - format_cover_coverage(cover:analyse(Module,coverage,function), - func)++ - format_cover_coverage(cover:analyse(Module,coverage,clause), - clause) - end, - getModDate(Module,date())++"<BR>"++ - "<TABLE WIDTH=\"100%\" BORDER=1>" - ++ Content ++"</TABLE>". - -getModDate(Module,{Year,Mon,Day})-> - "<TABLE> - <TR> - <TD>Module:</TD> - <TD>" ++ atom_to_list(Module) ++ "</TD> - </TR> - <TR> - <TD>Date:</TD> - <TD>" ++ integer_to_list(Day) ++ "/" ++ - integer_to_list(Mon) ++" - "++ - integer_to_list(Year) ++ - "</TD> - </TR> - </TABLE>". - - -format_cover_coverage({error,_},_)-> - "<TR><TD> - <BR><BR><BR><BR> - <FONT SIZE=5>The selected module is not Cover Compiled</FONT> - <BR> - </TD></TR>"; - - -format_cover_coverage({ok,{Mod,{Cov,Not_cov}}},mod)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6><B>Module coverage</B></TD></TR>\n", - "<TR><TD COLSPAN=4><I>Module</I></TD>\n", - "<TD ALIGN=\"right\"><I>Covered</I></TD>\n" - "<TD ALIGN=\"RIGHT\" NOWRAP=\"true\"><I>Not Covered</I></TD>\n", - "</TR>\n", - "<TR><TD COLSPAN=4>", atom_to_list(Mod), "</TD>\n" - "<TD ALIGN=\"right\">", integer_to_list(Cov), "</TD>\n" - "<TD ALIGN=\"right\" >", integer_to_list(Not_cov), "</TD></TR>\n"]; - -format_cover_coverage({ok,Cov_res},func)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6><B>Function coverage</B></TD>\n", - "</TR>\n", - "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>", - "<TD ALIGN=\"right\"><I>Arity</I></TD>", - "<TD COLSPAN=2 ALIGN=\"right\"><I>Covered</I></TD>", - "<TD ALIGN=\"right\" STYLE=\"white-space:nowrap\"><I>Not Covered</I></TD>", - "</TR>\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity},{Cov,Not_cov}})-> - ["<TR><TD WIDTH=\"20%\" >"++ atom_to_list(Mod) ++" </TD>\n", - "<TD WIDTH=\"20%\" >" ++ atom_to_list(Func) ++"</TD>\n", - "<TD WIDTH=\"40%\" ALIGN=\"right\">", - integer_to_list(Arity), - "</TD>\n", - "<TD WIDTH=\"40%\" ALIGN=\"right\" COLSPAN=2>", - integer_to_list(Cov), - "</TD>\n" - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Not_cov), - "</TD></TR>\n"] - end, - Cov_res))]; - -format_cover_coverage({ok,Cov_res},clause)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6><B>Clause coverage</B></TD></TR>\n", - "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>\n", - "<TD ALIGN=\"right\"><I>Arity</I></TD>\n", - "<TD ALIGN=\"right\"><I>Ordinal<I></TD>\n", - "<TD ALIGN=\"right\">Covered</TD>\n", - "<TD ALIGN=\"right\" STYLE=\"white-space:nowrap\">Not Covered</TD></TR>\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity,Ord},{Cov,Not_cov}})-> - ["<TR><TD WIDTH=\"20%\" >"++ atom_to_list(Mod) ++"</TD>\n", - "<TD WIDTH=\"20%\" >" ++ atom_to_list(Func) ++" </TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Arity), - "</TD>\n" - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Ord), - "</TD>\n" - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Cov), - "</TD>\n" - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Not_cov), - "</TD></TR>\n"] - end, - Cov_res))]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the import page % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -import_body(Dir,Err) -> - [reload_menu_script(Err), - "<H1 ALIGN=center>Import</H1>\n", - "<TABLE BORDER=0 WIDTH=600 ALIGN=center>\n", - "<TR><TD BGCOLOR=",?INFO_BG_COLOR,">\n", - "<P>You can import coverage data from a previous analysis. If you do so\n", - "the imported data will be merged with the current coverage data.\n", - "<P>You can export data from the current analysis from the \"Result\"\n", - "page.\n", - "<P>Select the file to import here.\n", - "</TD></TR>\n", - "<TR><TD ALIGN=center><BR><BR>\n", - "<FORM NAME=change_import_dir METHOD=post ACTION=\"./import\">\n", - "<B>Change directory:</B><BR>\n", - "<INPUT TYPE=text NAME=\"file\" SIZE=30 VALUE=",Dir,">", - "<INPUT TYPE=hidden NAME=dir VALUE=",Dir,">\n", - "<INPUT TYPE=submit VALUE=Ok><BR>\n", - "</FORM>\n", - browse_import(Dir), - "</TABLE>"]. - -browse_import(Dir) -> - {ok,List} = file:list_dir(Dir), - Sorted = lists:reverse(lists:sort(List)), - {Dirs,Files} = filter_files(Dir,Sorted,[],[]), - ["<FORM NAME=browse_import METHOD=post ACTION=\"./import\">\n" - "<SELECT NAME=file TITLE=\"Select import file\" SIZE=10>\n", - "<OPTION VALUE=\"..\" onDblClick=submit()>../</OPTION>\n", - Dirs, - Files, - "</SELECT>\n", - "<INPUT TYPE=hidden NAME=dir VALUE=",Dir,">\n", - "<BR><INPUT TYPE=submit VALUE=Ok>\n" - "</FORM>\n"]. - -filter_files(Dir,[File|Files],Ds,Fs) -> - case filename:extension(File) of - ".coverdata" -> - Fs1 = ["<OPTION VALUE=",File," onDblClick=submit()>", - File,"</OPTION>\n" | Fs], - filter_files(Dir,Files,Ds,Fs1); - _ -> - FullName = filename:join(Dir,File), - case filelib:is_dir(FullName) of - true -> - Ds1 = ["<OPTION VALUE=",File," onDblClick=submit()>", - File,"/</OPTION>\n" | Ds], - filter_files(Dir,Files,Ds1,Fs); - false -> - filter_files(Dir,Files,Ds,Fs) - end - end; -filter_files(_Dir,[],Ds,Fs) -> - {Ds,Fs}. - - - - -do_import(Input) -> - case parse(Input) of - [{"file",File0},{"dir",Dir}] -> - File = filename:join(Dir,File0), - case filelib:is_dir(File) of - true -> - import_frame1(File); - false -> - case filelib:is_file(File) of - true -> - case cover:import(File) of - ok -> - import_frame1(Dir); - {error,{cant_open_file,ExportFile,_Reason}} -> - import_frame1(Dir, - "Error importing file\\n\\\"" - ++ ExportFile ++ "\\\"") - end; - false -> - import_frame1(Dir, - "Error importing file\\n\\\"" ++ - File ++ "\\\"") - end - end; - [{"dir",Dir}] -> - import_frame1(Dir,"No file is selected") - end. - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% Different private helper functions % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%Create the Header for the page If we now the mimetype use that type %% -%%otherwise use text %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -header() -> - header("text/html"). -header(MimeType) -> - "Pragma:no-cache\r\n" ++ - "Content-type: " ++ MimeType ++ "\r\n\r\n". - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%Create the Htmlheader set the title of the page %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -html_header(Title) -> - "<HTML>\n" ++ - "<HEAD>\n" ++ - "<TITLE>" ++ Title ++ "</TITLE>\n" ++ - "</HEAD>\n" - "<BODY BGCOLOR=\"#FFFFFF\">\n". - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Close the body- and Html tags %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -html_end()-> - "</BODY></HTML>". - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% A script which reloads the menu frame and possibly pops up an alert%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -reload_menu_script(Err) -> - ["<SCRIPT>\n", - "function reloadMenu()\n", - " {\n", - " parent.menu.document.location.href=\"./menu_frame\";\n", - case Err of - "" -> ""; - _ -> " alert(\""++Err++"\");\n" - end, - case get_warnings() of - [] -> - ""; - Warnings -> - " alert(\""++fix_newline(lists:flatten(Warnings))++"\");\n" - end, - " }\n", - "</SCRIPT>\n", - "<BODY onLoad=reloadMenu() BGCOLOR=\"#FFFFFF\">"]. - -fix_newline([$\n|Rest]) -> - [$\\,$n|fix_newline(Rest)]; -fix_newline([$"|Rest]) -> - [$\\,$"|fix_newline(Rest)]; -fix_newline([Char|Rest]) -> - [Char|fix_newline(Rest)]; -fix_newline([]) -> - []. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Control the input data and return the intresting values or error % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -get_input_data(Input,Key)-> - case lists:keysearch(Key,1,parse(Input)) of - {value,{Key,Value}} -> - Value; - false -> - undefined - end. - -parse(Input) -> - httpd:parse_query(Input). - - -get_warnings() -> - cover_group_leader_proc ! {self(), get_warnings}, - receive {warnings,Warnings} -> - Warnings - end. diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl index e8b3d242e4..9ee75a688a 100644 --- a/lib/tools/src/lcnt.erl +++ b/lib/tools/src/lcnt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -94,12 +94,12 @@ -record(stats, { file :: atom(), - line :: non_neg_integer(), + line :: non_neg_integer() | 'undefined', tries :: non_neg_integer(), colls :: non_neg_integer(), time :: non_neg_integer(), % us nt :: non_neg_integer(), % #timings collected - hist :: tuple() % histogram + hist :: tuple() | 'undefined' % histogram }). -record(lock, { @@ -757,7 +757,7 @@ list2lock([F|Fs], Ls) -> stats2stats([]) -> []; stats2stats([Stat|Stats]) -> - Sz = tuple_size(#stats{}), + Sz = record_info(size, stats), [stat2stat(Stat,Sz)|stats2stats(Stats)]. stat2stat(Stat,Sz) when tuple_size(Stat) =:= Sz -> Stat; diff --git a/lib/tools/src/tools.app.src b/lib/tools/src/tools.app.src index 978b54719c..a00969eabe 100644 --- a/lib/tools/src/tools.app.src +++ b/lib/tools/src/tools.app.src @@ -21,7 +21,6 @@ [{description, "DEVTOOLS CXC 138 16"}, {vsn, "%VSN%"}, {modules, [cover, - cover_web, eprof, fprof, instrument, @@ -36,12 +35,12 @@ xref_utils ] }, - {registered,[webcover_server]}, + {registered, []}, {applications, [kernel, stdlib]}, {env, [{file_util_search_methods,[{"", ""}, {"ebin", "esrc"}, {"ebin", "src"}]} ] }, - {runtime_dependencies, ["webtool-0.8.10","stdlib-2.5","runtime_tools-1.8.14", + {runtime_dependencies, ["stdlib-2.5","runtime_tools-1.8.14", "kernel-3.0","inets-5.10","erts-7.0", "compiler-5.0"]} ] diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl index 931e3e2cfa..25c9317608 100644 --- a/lib/tools/test/cover_SUITE.erl +++ b/lib/tools/test/cover_SUITE.erl @@ -31,7 +31,7 @@ otp_5031/1, eif/1, otp_5305/1, otp_5418/1, otp_6115/1, otp_7095/1, otp_8188/1, otp_8270/1, otp_8273/1, otp_8340/1, otp_10979_hanging_node/1, compile_beam_opts/1, eep37/1, - analyse_no_beam/1]). + analyse_no_beam/1, line_0/1]). -export([do_coverage/1]). @@ -55,7 +55,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> NoStartStop = [eif,otp_5305,otp_5418,otp_7095,otp_8273, otp_8340,otp_8188,compile_beam_opts,eep37, - analyse_no_beam], + analyse_no_beam, line_0], StartStop = [start, compile, analyse, misc, stop, distribution, reconnect, die_and_reconnect, dont_reconnect_after_stop, stop_node_after_disconnect, @@ -1727,6 +1727,26 @@ analyse_no_beam(Config) when is_list(Config) -> ok = file:set_cwd(Cwd), ok. +%% When including eunit.hrl, a parse transform adds the function +%% test/0 to line 0 in your module. A bug in OTP-18.0 caused +%% cover:analyse_to_file/1 to fail to insert cover data in the output +%% file in this situation. The test below tests that this bug is +%% corrected. +line_0(Config) -> + ok = file:set_cwd(filename:join(?config(data_dir, Config), + "include_eunit_hrl")), + {ok, cover_inc_eunit} = compile:file(cover_inc_eunit,[debug_info]), + {ok, cover_inc_eunit} = cover:compile_beam(cover_inc_eunit), + {ok, CovOut} = cover:analyse_to_file(cover_inc_eunit), + + {ok,Bin} = file:read_file(CovOut), + Match = <<"0..| ok.\n">>, % "0.." is missing when bug is there + S = byte_size(Bin)-byte_size(Match), + <<_:S/binary,Match/binary>> = Bin, + ok. + + + %%--Auxiliary------------------------------------------------------------ analyse_expr(Expr, Config) -> diff --git a/lib/tools/test/cover_SUITE_data/include_eunit_hrl/cover_inc_eunit.erl b/lib/tools/test/cover_SUITE_data/include_eunit_hrl/cover_inc_eunit.erl new file mode 100644 index 0000000000..c1fe7939d2 --- /dev/null +++ b/lib/tools/test/cover_SUITE_data/include_eunit_hrl/cover_inc_eunit.erl @@ -0,0 +1,6 @@ +-module(cover_inc_eunit). +-compile(export_all). +-include_lib("eunit/include/eunit.hrl"). + +func() -> + ok. diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl index ad47b31443..71c8b1a277 100644 --- a/lib/tools/test/xref_SUITE.erl +++ b/lib/tools/test/xref_SUITE.erl @@ -1151,17 +1151,13 @@ read_expected(Version) -> {POS8+4,{FF,{a,b,1}}}, {POS8+4,{FF,{erlang,apply,2}}}, {POS8+5,{FF,{erlang,apply,2}}}, - {POS8+6,{FF,{erlang,apply,3}}}, {POS8+6,{FF,{m,f,1}}}, - {POS8+7,{FF,{erlang,apply,3}}}, - {POS9+1,{FF,{erlang,apply,3}}}, {POS9+1,{FF,{read,bi,0}}}, {POS9+2,{FF,{a,b,1}}}, {POS9+2,{FF,{erlang,apply,2}}}, {POS9+3,{FF,{erlang,apply,2}}}, {POS9+4,{FF,{erlang,apply,2}}}, {POS9+4,{FF,{erlang,not_a_function,1}}}, - {POS9+5,{FF,{erlang,apply,3}}}, {POS9+5,{FF,{mod,func,2}}}, {POS9+6,{FF,{erlang,apply,1}}}, {POS9+7,{FF,{erlang,apply,2}}}, @@ -1169,17 +1165,11 @@ read_expected(Version) -> {POS9+8,{FF,{q,f,1}}}, {POS10+4,{FF,{erlang,apply,2}}}, {POS10+5,{FF,{mod1,fun1,1}}}, - {POS11+1,{FF,{erlang,apply,3}}}, - {POS11+2,{FF,{erlang,apply,3}}}, - {POS11+3,{FF,{erlang,apply,3}}}, - {POS11+4,{FF,{erlang,apply,3}}}, {POS11+6,{FF,{erlang,apply,2}}}, {POS12+1,{FF,{erlang,apply,2}}}, {POS12+4,{FF,{erlang,apply,2}}}, - {POS12+5,{FF,{erlang,apply,3}}}, {POS12+5,{FF,{m3,f3,2}}}, {POS12+7,{FF,{erlang,apply,2}}}, - {POS12+8,{FF,{erlang,apply,3}}}, {POS13+1,{FF,{dm,df,1}}}, {POS13+6,{{read,bi,0},{foo,module_info,0}}}, {POS13+7,{{read,bi,0},{read,module_info,0}}}, @@ -1189,10 +1179,6 @@ read_expected(Version) -> OK = case Version of abstract_v1 -> - [{POS8+3, {FF,{erlang,apply,3}}}, - {POS10+1, {FF,{erlang,apply,3}}}, - {POS10+6, {FF,{erlang,apply,3}}}] - ++ [{0,{FF,{read,'$F_EXPR',178}}}, {0,{FF,{modul,'$F_EXPR',179}}}] ++ O1; @@ -1213,13 +1199,25 @@ read_expected(Version) -> {POS3+3, {FF,{erlang,spawn_link,3}}}, {POS3+4, {FF,{erlang,spawn_link,3}}}, {POS6+4, {FF,{erlang,spawn,3}}}, + {POS8+6,{FF,{erlang,apply,3}}}, + {POS8+7,{FF,{erlang,apply,3}}}, + {POS9+1,{FF,{erlang,apply,3}}}, + {POS9+5,{FF,{erlang,apply,3}}}, + {POS11+1,{FF,{erlang,apply,3}}}, + {POS11+2,{FF,{erlang,apply,3}}}, + {POS11+3,{FF,{erlang,apply,3}}}, + {POS11+4,{FF,{erlang,apply,3}}}, + {POS12+5,{FF,{erlang,apply,3}}}, + {POS12+8,{FF,{erlang,apply,3}}}, {POS13+5, {{read,bi,0},{erlang,length,1}}}, {POS14+3, {{read,bi,0},{erlang,length,1}}}], %% Operators (OTP-8647): OKB = case Version of abstract_v1 -> - []; + [{POS8+3, {FF,{erlang,apply,3}}}, + {POS10+1, {FF,{erlang,apply,3}}}, + {POS10+6, {FF,{erlang,apply,3}}}]; _ -> [{POS13+16, {{read,bi,0},{erlang,'!',2}}}, {POS13+16, {{read,bi,0},{erlang,'-',1}}}, diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index 68c3f6e29c..e4eda213ba 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1 +1 @@ -TOOLS_VSN = 2.8 +TOOLS_VSN = 2.8.1 diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl index ec00bfaba0..562530c868 100644 --- a/lib/typer/src/typer.erl +++ b/lib/typer/src/typer.erl @@ -1012,15 +1012,7 @@ compile_error(Reason) -> -spec msg(string()) -> 'ok'. msg(Msg) -> - case os:type() of - {unix, _} -> % Output a message on 'stderr', if possible - P = open_port({fd, 0, 2}, [out]), - port_command(P, Msg), - true = port_close(P), - ok; - _ -> % win32 - io:format("~s", [Msg]) - end. + io:format(standard_error, "~s", [Msg]). %%-------------------------------------------------------------------- %% Version and help messages. diff --git a/lib/webtool/AUTHORS b/lib/webtool/AUTHORS deleted file mode 100644 index 5f173dd264..0000000000 --- a/lib/webtool/AUTHORS +++ /dev/null @@ -1,4 +0,0 @@ -Original Authors and Contributors: - -Siri Hansen -Martin Gustafsson diff --git a/lib/webtool/Makefile b/lib/webtool/Makefile deleted file mode 100644 index 9afcb87af2..0000000000 --- a/lib/webtool/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2001-2009. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Common Macros -# ---------------------------------------------------- - -SUB_DIRECTORIES = src priv doc/src - -include vsn.mk -VSN = $(WEBTOOL_VSN) - -SPECIAL_TARGETS = - -# ---------------------------------------------------- -# Default Subdir Targets -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_subdir.mk - - diff --git a/lib/webtool/doc/html/.gitignore b/lib/webtool/doc/html/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/webtool/doc/html/.gitignore +++ /dev/null diff --git a/lib/webtool/doc/man1/.gitignore b/lib/webtool/doc/man1/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/webtool/doc/man1/.gitignore +++ /dev/null diff --git a/lib/webtool/doc/man3/.gitignore b/lib/webtool/doc/man3/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/webtool/doc/man3/.gitignore +++ /dev/null diff --git a/lib/webtool/doc/pdf/.gitignore b/lib/webtool/doc/pdf/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/webtool/doc/pdf/.gitignore +++ /dev/null diff --git a/lib/webtool/doc/src/Makefile b/lib/webtool/doc/src/Makefile deleted file mode 100644 index 57de52a616..0000000000 --- a/lib/webtool/doc/src/Makefile +++ /dev/null @@ -1,132 +0,0 @@ -# ``Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# The Initial Developer of the Original Code is Ericsson Utvecklings AB. -# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -# AB. All Rights Reserved.'' -# -# $Id$ -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../../vsn.mk -VSN=$(WEBTOOL_VSN) -APPLICATION=webtool - -DOC_EXTRA_FRONT_PAGE_INFO=Important note: \ -The Webtool application is obsolete and will be removed \ -in the next major OTP release - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- -XML_APPLICATION_FILES = ref_man.xml - -XML_REF1_FILES = start_webtool.xml - -XML_REF3_FILES = webtool.xml - -XML_PART_FILES = \ - part.xml \ - part_notes.xml \ - part_notes_history.xml - -XML_CHAPTER_FILES = \ - webtool_chapter.xml \ - notes.xml \ - notes_history.xml - -BOOK_FILES = book.xml - -XML_FILES = \ - $(BOOK_FILES) $(XML_CHAPTER_FILES) \ - $(XML_PART_FILES) $(XML_REF3_FILES) \ - $(XML_REF1_FILES) $(XML_APPLICATION_FILES) - -GIF_FILES = - -# ---------------------------------------------------- - -HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ - $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) - -INFO_FILE = ../../info - -MAN1_FILES = $(XML_REF1_FILES:%.xml=$(MAN1DIR)/%.1) -MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) - -HTML_REF_MAN_FILE = $(HTMLDIR)/index.html - -TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -XML_FLAGS += -DVIPS_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- -$(HTMLDIR)/%.gif: %.gif - $(INSTALL_DATA) $< $@ - -docs: pdf html man - -$(TOP_PDF_FILE): $(XML_FILES) - -pdf: $(TOP_PDF_FILE) - -html: gifs $(HTML_REF_MAN_FILE) - - -clean clean_docs: - rm -rf $(HTMLDIR)/* - rm -f $(MAN1DIR)/* - rm -f $(MAN3DIR)/* - rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) - rm -f errs core *~ - -man: $(MAN1_FILES) $(MAN3_FILES) - -gifs: $(GIF_FILES:%=$(HTMLDIR)/%) - -debug opt: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_docs_spec: docs - $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DIR) "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(HTMLDIR)/* \ - "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man1" - $(INSTALL_DATA) $(MAN1_FILES) "$(RELEASE_PATH)/man/man1" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3" - $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3" - -release_spec: - diff --git a/lib/webtool/doc/src/book.xml b/lib/webtool/doc/src/book.xml deleted file mode 100644 index feccee7c62..0000000000 --- a/lib/webtool/doc/src/book.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE book SYSTEM "book.dtd"> - -<book xmlns:xi="http://www.w3.org/2001/XInclude"> - <header titlestyle="normal"> - <copyright> - <year>2001</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>WebTool</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev>1.0</rev> - </header> - <insidecover> - </insidecover> - <pagetext>WebTool</pagetext> - <preamble> - </preamble> - <parts lift="no"> - <xi:include href="part.xml"/> - </parts> - <applications> - <xi:include href="ref_man.xml"/> - </applications> - <releasenotes> - <xi:include href="notes.xml"/> - </releasenotes> - <listofterms></listofterms> - <index></index> -</book> - diff --git a/lib/webtool/doc/src/fascicules.xml b/lib/webtool/doc/src/fascicules.xml deleted file mode 100644 index 37feca543f..0000000000 --- a/lib/webtool/doc/src/fascicules.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE fascicules SYSTEM "fascicules.dtd"> - -<fascicules> - <fascicule file="part" href="part_frame.html" entry="no"> - User's Guide - </fascicule> - <fascicule file="ref_man" href="ref_man_frame.html" entry="yes"> - Reference Manual - </fascicule> - <fascicule file="part_notes" href="part_notes_frame.html" entry="no"> - Release Notes - </fascicule> - <fascicule file="" href="../../../../doc/print.html" entry="no"> - Off-Print - </fascicule> -</fascicules> - diff --git a/lib/webtool/doc/src/notes.xml b/lib/webtool/doc/src/notes.xml deleted file mode 100644 index 21309261a8..0000000000 --- a/lib/webtool/doc/src/notes.xml +++ /dev/null @@ -1,253 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2004</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>Webtool Release Notes</title> - <prepared>otp_appnotes</prepared> - <docno>nil</docno> - <date>nil</date> - <rev>nil</rev> - <file>notes.xml</file> - </header> - <p>This document describes the changes made to the Webtool - application.</p> - -<section><title>WebTool 0.9</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - The Webtool application has been marked as obsolete and - will be removed from OTP in the next major release (OTP - 19.0).</p> - <p> - Own Id: OTP-10922 Aux Id: OTP-12705 </p> - </item> - </list> - </section> - -</section> - -<section><title>WebTool 0.8.10</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Application upgrade (appup) files are corrected for the - following applications: </p> - <p> - <c>asn1, common_test, compiler, crypto, debugger, - dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, - inets, observer, odbc, os_mon, otp_mibs, parsetools, - percept, public_key, reltool, runtime_tools, ssh, - syntax_tools, test_server, tools, typer, webtool, wx, - xmerl</c></p> - <p> - A new test utility for testing appup files is added to - test_server. This is now used by most applications in - OTP.</p> - <p> - (Thanks to Tobias Schlager)</p> - <p> - Own Id: OTP-11744</p> - </item> - </list> - </section> - -</section> - -<section><title>WebTool 0.8.9.2</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Misc build updates</p> - <p> - Own Id: OTP-10784</p> - </item> - </list> - </section> - -</section> - -<section><title>WebTool 0.8.9.1</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Miscellaneous documentation build updates</p> - <p> - Own Id: OTP-9813</p> - </item> - </list> - </section> - -</section> - -<section><title>WebTool 0.8.9</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Do not install *.bat files on non-win32 machines (Thanks - to Hans Ulrich Niedermann)</p> - <p> - Own Id: OTP-9515</p> - </item> - </list> - </section> - -</section> - -<section><title>WebTool 0.8.8</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Various small documentation fixes (Thanks to Bernard - Duggan)</p> - <p> - Own Id: OTP-9172</p> - </item> - </list> - </section> - -</section> - -<section><title>WebTool 0.8.7</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Up until now Netscape has been the default web browser on - Unix/Linux. Webtool has now been updated to start Firefox - as default browser instead.</p> - <p> - Own Id: OTP-8651 Aux Id: OTP-8650 </p> - </item> - </list> - </section> - -</section> - -<section><title>WebTool 0.8.6</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Misc updates</p> - <p> - Own Id: OTP-8456</p> - </item> - </list> - </section> - -</section> - -<section><title>WebTool 0.8.5</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - The documentation is now built with open source tools - (xsltproc and fop) that exists on most platforms. One - visible change is that the frames are removed.</p> - <p> - Own Id: OTP-8201</p> - </item> - </list> - </section> - -</section> - -<section><title>WebTool 0.8.4</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p>The copyright notices have been updated.</p> - <p> - Own Id: OTP-7851</p> - </item> - </list> - </section> - -</section> -<section><title>WebTool 0.8.3.2</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Minor updates.</p> - <p> - Own Id: OTP-6998</p> - </item> - </list> - </section> - -</section> - - <section> - <title>WebTool 0.8.3.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Minor Makefile changes.</p> - <p>Own Id: OTP-6689</p> - </item> - <item> - <p>Obsolete guard tests (such as list()) have been replaced - with the modern guard tests (such as is_list()).</p> - <p>Own Id: OTP-6725</p> - </item> - </list> - </section> - </section> - - <section> - <title>WebTool 0.8.3</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Removed some dead code discovered by Dialyzer.</p> - <p>Own Id: OTP-6041</p> - </item> - </list> - </section> - </section> -</chapter> - diff --git a/lib/webtool/doc/src/notes_history.xml b/lib/webtool/doc/src/notes_history.xml deleted file mode 100644 index 792475d948..0000000000 --- a/lib/webtool/doc/src/notes_history.xml +++ /dev/null @@ -1,74 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2006</year> - <year>2013</year> - <holder>Ericsson AB, All Rights Reserved</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - The Initial Developer of the Original Code is Ericsson AB. - </legalnotice> - - <title>Webtool Release Notes History</title> - <prepared>otp_appnotes</prepared> - <docno>nil</docno> - <date>nil</date> - <rev>nil</rev> - </header> - - <section> - <title>Webtool 0.8.2</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Bugfix: <c>webtool</c> crashed when trying to find a free - port number if connection failed with other reason than - <c>econnrefused</c>.</p> - <p>Own Id: OTP-5166</p> - </item> - </list> - </section> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Misc improvements:</p> - <list type="bulleted"> - <item>The function <c>debug_app/1</c> and some error - printouts are added to simplify debugging of own - application.</item> - <item>Multiple webtool instances can now be started on - the same host. If the default port (8888) is in use, port - 8889 is tried. If 8889 is also used, 8890 is tried and so - on. Max number of ports tried is 256.</item> - <item><em>Incompatible:</em> If <c>Data</c> is set to - <c>PortNumber</c> in <c>start(Path,Data)</c>, the default - data will be used for ip-number (<c>127.0.0.1</c>) and - server name (<c>localhost</c>).</item> - </list> - <p>*** POTENTIAL INCOMPATIBILITY ***</p> - <p>Own Id: OTP-4724</p> - </item> - </list> - </section> - </section> -</chapter> - diff --git a/lib/webtool/doc/src/part.xml b/lib/webtool/doc/src/part.xml deleted file mode 100644 index b0c4ee310d..0000000000 --- a/lib/webtool/doc/src/part.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2001</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>WebTool User's Guide</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <description> - <p><em>WebTool</em> provides a easy way to use web based tools with - Erlang/OTP. It configures and starts a webserver as well as all - available tools.</p> - </description> - <xi:include href="webtool_chapter.xml"/> -</part> - diff --git a/lib/webtool/doc/src/part_notes.xml b/lib/webtool/doc/src/part_notes.xml deleted file mode 100644 index db2b790f3f..0000000000 --- a/lib/webtool/doc/src/part_notes.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2004</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>WebTool Release Notes</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <description> - <p><em>WebTool</em> provides an easy way to use web based tools with - Erlang/OTP. It configures and starts a webserver as well as all - available tools.</p> - <p>For information about older versions, see - <url href="part_notes_history_frame.html">Release Notes History</url>.</p> - </description> - <xi:include href="notes"/> -</part> - diff --git a/lib/webtool/doc/src/part_notes_history.xml b/lib/webtool/doc/src/part_notes_history.xml deleted file mode 100644 index 50ce62e58d..0000000000 --- a/lib/webtool/doc/src/part_notes_history.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part> - <header> - <copyright> - <year>2006</year> - <year>2013</year> - <holder>Ericsson AB, All Rights Reserved</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - The Initial Developer of the Original Code is Ericsson AB. - </legalnotice> - - <title>WebTool Release Notes History</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <description> - <p><em>WebTool</em> provides a easy way to use web based tools with - Erlang/OTP. It configures and starts a webserver as well as all - available tools.</p> - </description> - <include file="notes_history"></include> -</part> - diff --git a/lib/webtool/doc/src/ref_man.xml b/lib/webtool/doc/src/ref_man.xml deleted file mode 100644 index aa81392b11..0000000000 --- a/lib/webtool/doc/src/ref_man.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE application SYSTEM "application.dtd"> - -<application xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2001</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>WebTool Reference Manual</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <description> - <p><em>WebTool</em> provides an easy way to use web based tools with - Erlang/OTP. It configures and starts a webserver as well as all - available tools.</p> - </description> - <xi:include href="webtool.xml"/> - <xi:include href="start_webtool.xml"/> -</application> - diff --git a/lib/webtool/doc/src/start_webtool.xml b/lib/webtool/doc/src/start_webtool.xml deleted file mode 100644 index e9c94c4271..0000000000 --- a/lib/webtool/doc/src/start_webtool.xml +++ /dev/null @@ -1,104 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE comref SYSTEM "comref.dtd"> - -<comref> - <header> - <copyright> - <year>2003</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>start_webtool</title> - <prepared></prepared> - <responsible></responsible> - <docno>1</docno> - <approved></approved> - <checked></checked> - <date>2003-06-18</date> - <rev></rev> - <file>start_webtool.sgml</file> - </header> - <com>start_webtool</com> - <comsummary>WebTool Start Script</comsummary> - <description> - <p>The <c>start_webtool</c> script starts WebTool, a WebTool - application and a web browser pointing to this application.</p> - </description> - <funcs> - <func> - <name>start_webtool application [ browser ]</name> - <fsummary>Start a WebTool Application</fsummary> - <desc> - <p>Starts WebTool, the given WebTool Application and a web - browser pointing to this application. - </p> - <p>If no argument is given, a list of available applications - is displayed, e.g.</p> - <pre> ->start_webtool -Starting webtool... -WebTool is available at http://localhost:8888/ -Or http://127.0.0.1:8888/ - -Usage: start_webtool application [ browser ] - -Available applications are: [orber,appmon,crashdump_viewer,webcover] -Default browser is 'iexplore' (Internet Explorer) on Windows or else 'firefox' </pre> - <p>To start any of the listed applications, give the - application name as the first argument, e.g.</p> - <pre> ->start_webtool webcover -Starting webtool... -WebTool is available at http://localhost:8888/ -Or http://127.0.0.1:8888/ -Starting webcover... -Sending URL to netscape...done </pre> - <p>The WebTool application WebCover is then started and the - default browser is used. The default browser is Internet - Explorer on Windows or else Firefox. - </p> - <p>To use another browser, give the browser's start command - as the second argument, e.g.</p> - <pre> ->start_webtool webcover mozilla -Starting webtool... -WebTool is available at http://localhost:8888/ -Or http://127.0.0.1:8888/ -Starting webcover... -Sending URL to mozilla...done </pre> - <p>If the given browser name is not known to WebTool, WebTool - will run it as a command with the start URL as the only - argument, e.g.</p> - <pre> ->start_webtool webcover mybrowser -Starting webtool... -WebTool is available at http://localhost:8888/ -Or http://127.0.0.1:8888/ -Starting webcover... -Starting mybrowser... </pre> - <p>Here the command <c>"mybrowser http://localhost:8888/webcover"</c> is executed. - </p> - </desc> - </func> - </funcs> - - <section> - <title>See Also</title> - <p><seealso marker="webtool">webtool(3)</seealso></p> - </section> -</comref> - diff --git a/lib/webtool/doc/src/webtool.xml b/lib/webtool/doc/src/webtool.xml deleted file mode 100644 index 2647518dae..0000000000 --- a/lib/webtool/doc/src/webtool.xml +++ /dev/null @@ -1,157 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE erlref SYSTEM "erlref.dtd"> - -<erlref> - <header> - <copyright> - <year>2001</year> - <year>2013</year> - <holder>Ericsson AB, All Rights Reserved</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - The Initial Developer of the Original Code is Ericsson AB. - </legalnotice> - - <title>webtool</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <module>webtool</module> - <modulesummary>WebTool is a tool used to simplify the implementation of web based tools with Erlang/OTP.</modulesummary> - <description> - <p>WebTool makes it easy to use web based tools with Erlang/OTP. WebTool - configures and starts the webserver httpd.</p> - </description> - <funcs> - <func> - <name>start()-> {ok,Pid}| {stop,Reason}</name> - <fsummary>Start WebTool.</fsummary> - <desc> - <p>Start WebTool with default data, i.e. port 8888, ip-number - 127.0.0.1, and server-name <c>localhost</c>. If port 8888 is - in use, port 8889 is tried instead. If 8889 is also in use, - 8890 is tried and so on. Max number of ports tried is 256. - </p> - <p>The <c>mime.types</c> file and WebTool's own HTML files - are assumed to be in the directory - <c><![CDATA[webtool-<vsn>/priv/root/conf]]></c>.</p> - </desc> - </func> - <func> - <name>start(Path,Data)->{ok,Pid}|{stop,Reason}</name> - <fsummary>Start WebTool with default configuration.</fsummary> - <type> - <v>Path = string() | standard_path</v> - <v>Data = [Port,Address,Name] | PortNumber | standard_data</v> - <v>Port = {port,PortNumber}</v> - <v>Address = {bind_address,IpNumber}</v> - <v>Name = {server_name,ServerName}</v> - <v>PortNumber = integer()</v> - <v>IpNumber = tuple(), e.g. {127,0,0,1}</v> - <v>ServerName = string()</v> - <v>Pid = pid()</v> - </type> - <desc> - <p>Use this function to start WebTool if the default port, - ip-number,servername or path can not be used.</p> - <p><c>Path</c> is the directory where the <c>mime.types</c> - file and WebTool's own HTML files are located. By default - this is <c><![CDATA[webtool-<vsn>/priv]]></c>, and in most cases there - is no need to change this. If <c>Path</c> is set to - <c>standard_path</c> the default will be used.</p> - <p>If <c>Data</c> is set to <c>PortNumber</c>, the default data - will be used for ip-number (<c>127.0.0.1</c>) and server - name (<c>localhost</c>).</p> - </desc> - </func> - <func> - <name>stop()->void</name> - <fsummary>Stop WebTool.</fsummary> - <desc> - <p>Stop WebTool and the tools started by WebTool.</p> - </desc> - </func> - <func> - <name>debug_app(Module)->void</name> - <fsummary>Debug a WebTool application.</fsummary> - <type> - <v>Module = atom()</v> - </type> - <desc> - <p>Debug a WebTool application by tracing all functions in the - given module which are called from WebTool.</p> - </desc> - </func> - <func> - <name>stop_debug()->void</name> - <fsummary>Stop debugging an application and format the trace log.</fsummary> - <desc> - <p>Stop the tracing started by <c>debug_app/1</c>, and format - the trace log.</p> - </desc> - </func> - </funcs> - - <section> - <title>CALLBACK FUNCTIONS</title> - <p>The following callback function must be implemented by each web - based tool that will be used via WebTool. When started, WebTool - searches the Erlang code path for *.tool files to locate all web - based tools and their callback functions. See the <seealso marker="webtool_chapter">WebTool User's Guide</seealso> for more - information about the *.tool files.</p> - </section> - <funcs> - <func> - <name>Module:Func(Data)-> {Name,WebData}|error</name> - <fsummary>Returns configuration data needed by WebTool to configure and start a tool.</fsummary> - <type> - <v>Data = term()</v> - <v>Name = atom()</v> - <v>WebData = [WebOptions]</v> - <v>WebOptions = LinkData | Alias | Start</v> - <v>LinkData = {web_data,{ToolName,Url}}</v> - <v>Alias = {alias,{VirtualPath,RealPath}} | {alias,{erl_alias,Path,[Modules]}</v> - <v>Start = {start,StartData}</v> - <v>ToolName = Url = VirtualPath = RealPath = Path = string()</v> - <v>Modules = atom()</v> - <v>StartData = AppData | ChildSpec | Func</v> - <v>AppData = {app,AppName}</v> - <v>ChildSpec = {child,child_spec()}</v> - <d>See the Reference Manual for the module supervisor in the STDLIB application for details about child_spec().</d> - <v>Func = {func,{StartMod,StartFunc,StartArg}, {StopMod,StopFunc,StopArg}}</v> - <v>AppName = StartMod = StartFunc = StopMod = StopFunc =atom()</v> - <v>StartArg = StopArg = [term()]</v> - </type> - <desc> - <p>This is the configuration function (<c>config_func</c>) - which must be stated in the <c>*.tool</c> file.</p> - <p>The function is called by WebTool at startup to retrieve the - data needed to start and configure the tool. <c>LinkData</c> is - used by WebTool to create the link to the tool. <c>Alias</c> is - used to create the aliases needed by the webserver. <c>Start</c> - is used to start and stop the tool.</p> - </desc> - </func> - </funcs> - - <section> - <title>See Also</title> - <p><seealso marker="start_webtool">start_webtool(1)</seealso>, - <seealso marker="webtool_chapter">WebTool User's Guide</seealso></p> - </section> -</erlref> - diff --git a/lib/webtool/doc/src/webtool_chapter.xml b/lib/webtool/doc/src/webtool_chapter.xml deleted file mode 100644 index 160a42f855..0000000000 --- a/lib/webtool/doc/src/webtool_chapter.xml +++ /dev/null @@ -1,246 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2001</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>WebTool User Guide</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - <file>webtool_chapter.xml</file> - </header> - - <section> - <title>Introduction </title> - <p>WebTool provides an easy and efficient way to implement web - based tools with Erlang/OTP. WebTool configures and starts the - webserver and the various web based tools.</p> - <p>All tools that shall run under WebTool must have a *.tool - file in the code path or in its priv directory. When WebTool - starts it searches the code path for such files. For each - <c>ebin</c> directory in the path, the <c>priv</c> directory is - also searched. The *.tool files contain the configuration data - for each web based tool.</p> - </section> - - <section> - <title>Starting WebTool</title> - <p>Start WebTool by calling the function <c>webtool:start/0</c> or - <c>webtool:start/2</c>. If <c>webtool:start/0</c> is used the - start page of WebTool is available at - <em>http://localhost:8888/</em> or - <em>http://127.0.0.1:8888/</em>, and the directory containing - the root directory for the webserver, is assumed to be - <c><![CDATA[webtool-<vsn>/priv]]></c>.</p> - <p>Use <c>webtool:start/2</c> if the default path for the root - directory, port, ip-number or server name can not be used. See - the Reference Manual for <seealso marker="webtool">webtool</seealso> for more information.</p> - <p>WebTool, with the default configuration as in <c>start/0</c>, - can also be started with the <c>start_webtool</c> script which - is available in the <c>priv</c> directory of the WebTool - application. See the Reference Manual for <seealso marker="start_webtool">start_webtool</seealso> for further - information about this script. For Windows users, the batch file - <c>start_webtool.bat</c> can be used for the same purpose.</p> - </section> - - <section> - <title>Using WebTool</title> - <p>Start WebTool and point the browser to the corresponding URL. - At the top of the page there is a frame with a link named - <em>WebTool</em>. Click that link and a page where it is - possible to start the available tools will appear in the main - frame.</p> - </section> - - <section> - <title>Start a web based tool</title> - <p>Click on the link labeled <em>WebTool</em> in the topmost frame, - select the checkbox for each tool to start and - click on the button labeled <em>Start</em>. A link to each tool - that WebTool succeeded to start will appear in the topmost frame.</p> - </section> - - <section> - <title>Stop a web based tool</title> - <p>Click on the link labeled <em>WebTool</em> in the topmost - frame. Select <em>Stop Tools</em> in the left frame. Select the - checkbox for each tool to stop and click on the button labeled - <em>Stop</em>.</p> - </section> - - <section> - <title>Develop new web based tools</title> - <p>WebTool can be used as a framework when developing new web based - tools.</p> - <p>A web based tool running under WebTool will typically consist of - three parts.</p> - <list type="bulleted"> - <item>A *.tool file which defines how WebTool can find the tool's - configuration data</item> - <item>The Erlang code generating the web interface to the tool (HTML - code)</item> - <item>The tool itself.</item> - </list> - <p>In most cases it is a good idea to separate the code for - creation of the html-pages and the code for the logic. This - increases the readability of the code and the logic might be - possible to reuse.</p> - - <section> - <title>The *.tool file</title> - <p>When WebTool starts it searches the current path for - <c>*.tool</c> files to find all available tools. The *.tool - file contains a version identifier and a list of tuples which - is the configuration data. The version identifier specifies - the *.tool file version, i.e. not the version of - webtool. Currently the only valid version is "1.2" and the - only valid configuration tag is - <c>config_func</c>. <c>config_func</c> specifies which - function WebTool must call to get further configuration data - for the tool. This means that a *.tool file generally must - look like this:</p> - <code type="none"> - {version,"1.2"}. - [{config_func,{Module,Function,Arguments}}]. </code> - <p><c>Module</c> is the name of the module where the callback - function is defined. <c>Function</c> is the name of the - callback function, and <c>Arguments</c> is the list of - arguments to the callback function.</p> - </section> - - <section> - <title>The configuration function</title> - <p>The *.tool file points out a configuration function. This - function must return a list of configuration parameters (see - the Reference Manual for <seealso marker="webtool">webtool</seealso>).</p> - <p>The <c>web_data</c> parameter is mandatory and it specifies - the name of the tool and the link to the tool's start - page. All other parameters are optional.</p> - <p>If the tool requires any processes to run, the <c>start</c> - parameter specifies the function that WebTool must call in - order to start the process(es).</p> - <p>The <c>alias</c> parameters are passed directly on to the - webserver (INETS). The webserver has three ways to create - dynamic web pages CGI, Eval Scheme and Erl Scheme. All tools - running under WebTool must use Erl Scheme.</p> - <p>Erl Scheme tries to resemble plain CGI. The big difference is - that Erl Scheme can only execute Erlang code. The code will - furthermore be executed on the same instance as the webserver.</p> - <p>An URL which calls an Erlang function with Erl Scheme can have - the following syntax:</p> - <code type="none"><![CDATA[ -http://Servername:Port/ErlScriptAlias/Mod/Func<?QueryString> ]]></code> - <p>An <c>alias</c> parameter in the configuration function can be - an ErlScriptAlias as used in the above URL. The definition of - an ErlScriptAlias shall be like this:</p> - <p><c>{alias,{erl_alias,Path,[Modules]}}</c>, e.g.</p> - <p><c>{alias,{erl_alias,"/testtool",[helloworld]}}</c></p> - <p>The following URL will then cause a call to the function - helloworld:helloworld/2 (if WebTool is started with default - settings i.e. servername "localhost" and port 8888):</p> - <p><c>http://localhost:8888/testtool/helloworld/helloworld</c></p> - <p>Note that the module <c>helloworld</c> must be in the code - path of the node running WebTool.</p> - <p>Functions that are called via the Erl Scheme must take two - arguments, <c>Environment</c> and <c>Input</c>. - </p> - <list type="bulleted"> - <item><c>Environment</c> is a list of key/value tuples.</item> - <item><c>Input</c> is the part of the URL after the "?", i.e. the - part of the URL containing name-value pairs. If the page was - called with the URL: - <br></br> -<c><![CDATA[http://localhost:8888/testtool/helloworld/helloworld?input1=one&input2=two]]></c> <br></br> -<c>Input</c> will be the string - <c><![CDATA["input1=one&input2=two"]]></c>. In the module - <c>httpd</c> in the INETS application there is a function - <c>parse_query</c> which will parse such a string and return - a list of key-value tuples.</item> - </list> - <p>An <c>alias</c> parameter in the configuration function can - also be a normal path alias. This can e.g. be used to point - out a directory where HTML files are stored. The following - definition states that the URL - <c>http://localhost:8888/mytool_home/</c> really points to the - directory <c>/usr/local/otp/lib/myapp-1.0/priv</c>:</p> - <p><c>{alias,{"/mytool_home","/usr/local/otp/lib/myapp-1.0/priv"}}</c></p> - <p>See the INETS documentation, especially the module - <c>mod_esi</c>, for a more in depth coverage of the Erl Scheme.</p> - </section> - - <section> - <title>A small example</title> - <p>A Hello World example that uses Erl Scheme would look like - this. Note that this example does not have a process running - and thus does not need a <c>start</c> parameter in the - configuration function. - </p> - <p><em>helloworld.erl:</em></p> - <pre> - -module(helloworld). - -export([config_data/0]). - -export([helloworld/2]). - - config_data()-> - {testtool, - [{web_data,{"TestTool","/testtool/helloworld/helloworld"}}, - {alias,{erl_alias,"/testtool",[helloworld]}}]}. - - helloworld(_Env,_Input)-> - [header(),html_header(),helloworld_body(),html_end()]. - - header() -> - header("text/html"). - - header(MimeType) -> - "Content-type: " ++ MimeType ++ "\r\n\r\n". - - html_header() -> - "<HTML> - <HEAD> - <TITLE>Hello world Example </TITLE> - </HEAD>\n". - - helloworld_body()-> - "<BODY>Hello World</BODY>". - - html_end()-> - "</HTML>". - </pre> - <p>To use this example with WebTool a *.tool file must be created - and added to a directory in the current path, e.g. the same - directory as the compiled <c>helloworld.beam</c>.</p> - <p><em>testtool.tool:</em></p> - <code type="none"> - {version,"1.2"}. - [{config_func, {helloworld,config_data,[]}}]. - </code> - <p>When <c>helloworld.erl</c> is compiled, start WebTool by - calling the function <c>webtool:start()</c> and point your - browser to <em>http://localhost:8888/</em>. Select WebTool in - the topmost frame and start TestTool from the web page. Click - on the link labeled <em>TestTool</em> in the topmost frame.</p> - </section> - </section> -</chapter> - diff --git a/lib/webtool/ebin/.gitignore b/lib/webtool/ebin/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/lib/webtool/ebin/.gitignore +++ /dev/null diff --git a/lib/webtool/info b/lib/webtool/info deleted file mode 100644 index 4d8dc6f2cb..0000000000 --- a/lib/webtool/info +++ /dev/null @@ -1,2 +0,0 @@ -group: tools -short: A tool that simplifying the use of web based Erlang tools diff --git a/lib/webtool/priv/Makefile b/lib/webtool/priv/Makefile deleted file mode 100644 index 4963767a4d..0000000000 --- a/lib/webtool/priv/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -# ``Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# The Initial Developer of the Original Code is Ericsson Utvecklings AB. -# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -# AB. All Rights Reserved.'' -# -# $Id$ -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../vsn.mk -VSN=$(WEBTOOL_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/webtool-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -WEBSERVER_CONFIG_FILES = root/conf/mime.types - -HTDOCS_FILES = root/doc/index.html \ - root/doc/tool_management.html \ - root/doc/start_info.html - -ifeq ($(findstring win32,$(TARGET)),win32) -WIN32_SCRIPTS= bin/start_webtool.bat -else -WIN32_SCRIPTS= -endif -SCRIPTS = bin/start_webtool $(WIN32_SCRIPTS) - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: - -clean: - -docs: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/priv" - $(INSTALL_DIR) "$(RELSYSDIR)/priv/root" - $(INSTALL_DIR) "$(RELSYSDIR)/priv/root/conf" - $(INSTALL_DIR) "$(RELSYSDIR)/priv/root/doc" - $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv/root/doc" - $(INSTALL_DATA) $(WEBSERVER_CONFIG_FILES) "$(RELSYSDIR)/priv/root/conf" - $(INSTALL_DIR) "$(RELSYSDIR)/priv/bin" - $(INSTALL_SCRIPT) $(SCRIPTS) "$(RELSYSDIR)/priv/bin" - -release_docs_spec: - - diff --git a/lib/webtool/priv/bin/start_webtool b/lib/webtool/priv/bin/start_webtool deleted file mode 100755 index e552fb5af0..0000000000 --- a/lib/webtool/priv/bin/start_webtool +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -erl -sname webtool -s webtool script_start $@ diff --git a/lib/webtool/priv/bin/start_webtool.bat b/lib/webtool/priv/bin/start_webtool.bat deleted file mode 100644 index cd16aa6200..0000000000 --- a/lib/webtool/priv/bin/start_webtool.bat +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF
-CALL erl -sname webtool -s webtool script_start %* -s erlang halt
\ No newline at end of file diff --git a/lib/webtool/priv/root/conf/mime.types b/lib/webtool/priv/root/conf/mime.types deleted file mode 100644 index 32f7cd853c..0000000000 --- a/lib/webtool/priv/root/conf/mime.types +++ /dev/null @@ -1,99 +0,0 @@ -# This is a comment. I love comments. - -application/activemessage -application/andrew-inset -application/applefile -application/atomicmail -application/dca-rft -application/dec-dx -application/mac-binhex40 hqx -application/mac-compactpro cpt -application/macwriteii -application/msword doc -application/news-message-id -application/news-transmission -application/octet-stream bin dms lha lzh exe class -application/oda oda -application/pdf pdf -application/postscript ai eps ps -application/powerpoint ppt -application/remote-printing -application/rtf rtf -application/slate -application/wita -application/wordperfect5.1 -application/x-bcpio bcpio -application/x-cdlink vcd -application/x-compress Z -application/x-cpio cpio -application/x-csh csh -application/x-director dcr dir dxr -application/x-dvi dvi -application/x-gtar gtar -application/x-gzip gz -application/x-hdf hdf -application/x-httpd-cgi cgi -application/x-koan skp skd skt skm -application/x-latex latex -application/x-mif mif -application/x-netcdf nc cdf -application/x-sh sh -application/x-shar shar -application/x-stuffit sit -application/x-sv4cpio sv4cpio -application/x-sv4crc sv4crc -application/x-tar tar -application/x-tcl tcl -application/x-tex tex -application/x-texinfo texinfo texi -application/x-troff t tr roff -application/x-troff-man man -application/x-troff-me me -application/x-troff-ms ms -application/x-ustar ustar -application/x-wais-source src -application/zip zip -audio/basic au snd -audio/mpeg mpga mp2 -audio/x-aiff aif aiff aifc -audio/x-pn-realaudio ram -audio/x-pn-realaudio-plugin rpm -audio/x-realaudio ra -audio/x-wav wav -chemical/x-pdb pdb xyz -image/gif gif -image/ief ief -image/jpeg jpeg jpg jpe -image/png png -image/tiff tiff tif -image/x-cmu-raster ras -image/x-portable-anymap pnm -image/x-portable-bitmap pbm -image/x-portable-graymap pgm -image/x-portable-pixmap ppm -image/x-rgb rgb -image/x-xbitmap xbm -image/x-xpixmap xpm -image/x-xwindowdump xwd -message/external-body -message/news -message/partial -message/rfc822 -multipart/alternative -multipart/appledouble -multipart/digest -multipart/mixed -multipart/parallel -text/html html htm -text/x-server-parsed-html shtml -text/plain txt -text/richtext rtx -text/tab-separated-values tsv -text/x-setext etx -text/x-sgml sgml sgm -video/mpeg mpeg mpg mpe -video/quicktime qt mov -video/x-msvideo avi -video/x-sgi-movie movie -x-conference/x-cooltalk ice -x-world/x-vrml wrl vrml diff --git a/lib/webtool/priv/root/doc/index.html b/lib/webtool/priv/root/doc/index.html deleted file mode 100644 index 9fbb143cc7..0000000000 --- a/lib/webtool/priv/root/doc/index.html +++ /dev/null @@ -1,11 +0,0 @@ -<HTML> -<HEAD> -<TITLE>Erlang WebTool</TITLE> -</HEAD> -<FRAMESET ROWS="60,*"> -<FRAME NAME="top1" SRC="webtool/webtool/started_tools"> -<FRAME NAME="app_frame" SRC="./start_info.html"> -</FRAMESET> -</HTML> - - diff --git a/lib/webtool/priv/root/doc/start_info.html b/lib/webtool/priv/root/doc/start_info.html deleted file mode 100644 index fcf44433f1..0000000000 --- a/lib/webtool/priv/root/doc/start_info.html +++ /dev/null @@ -1,28 +0,0 @@ -<HTML> -<HEAD> -</HEAD> -<BODY BGCOLOR="#FFFFFF"> -<TABLE WIDTH=100% HEIGHT=100%> -<TR VALIGN="middle"> -<TD ALIGN="center"> - -<TABLE WIDTH="60%"> -<TR> -<TD ALIGN="center"><FONT SIZE=6>Welcome <BR> to<BR> WebTool</FONT></TD> -</TR> - -<TR> -<TD><BR><BR><BR><BR> -</TD> -</TR> - -<TR> -<TD ALIGN="center">Click on the link WebTool on the top of the page, or <A HREF=tool_management.html>here</a> to start the Web based tools.</TD> -</TR> -</TABLE> - -</TD> -</TR> -</TABLE> -</BODY> -</HTML>
\ No newline at end of file diff --git a/lib/webtool/priv/root/doc/tool_management.html b/lib/webtool/priv/root/doc/tool_management.html deleted file mode 100644 index 19d9dbcb9e..0000000000 --- a/lib/webtool/priv/root/doc/tool_management.html +++ /dev/null @@ -1,9 +0,0 @@ -<HTML> -<HEAD> -<TITLE>Erlang WebTool </TITLE> -</HEAD> -<FRAMESET COLS="200,*"> -<FRAME NAME="left" SRC="/webtool/webtool/toolbar"> -<FRAME NAME="right" SRC="/webtool/webtool/start_tools"> -</FRAMESET> - diff --git a/lib/webtool/src/Makefile b/lib/webtool/src/Makefile deleted file mode 100644 index a5a8eaf5dc..0000000000 --- a/lib/webtool/src/Makefile +++ /dev/null @@ -1,98 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2001-2012. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions 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=$(WEBTOOL_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/webtool-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= webtool \ - webtool_sup - - - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) - -APP_FILE= webtool.app -APPUP_FILE= webtool.appup - -APP_SRC= $(APP_FILE).src -APPUP_SRC= $(APPUP_FILE).src - - -APP_TARGET= $(EBIN)/$(APP_FILE) -APPUP_TARGET= $(EBIN)/$(APPUP_FILE) - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += +warn_obsolete_guard - - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) - -clean: - rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) - rm -f core - -docs: - -# ---------------------------------------------------- -# Special Build Targets -# ---------------------------------------------------- - -$(APP_TARGET): $(APP_SRC) ../vsn.mk - $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ - -$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk - $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/src" - $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src" - $(INSTALL_DIR) "$(RELSYSDIR)/ebin" - $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \ - "$(RELSYSDIR)/ebin" - -release_docs_spec: - diff --git a/lib/webtool/src/webtool.appup.src b/lib/webtool/src/webtool.appup.src deleted file mode 100644 index 1394d0d6d5..0000000000 --- a/lib/webtool/src/webtool.appup.src +++ /dev/null @@ -1,22 +0,0 @@ -%% -*- erlang -*- -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2014. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -{"%VSN%", - [{<<".*">>,[{restart_application, webtool}]}], - [{<<".*">>,[{restart_application, webtool}]}] -}. diff --git a/lib/webtool/src/webtool.erl b/lib/webtool/src/webtool.erl deleted file mode 100644 index 80dad53f8f..0000000000 --- a/lib/webtool/src/webtool.erl +++ /dev/null @@ -1,1208 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(webtool). --behaviour(gen_server). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The general idea is: %% -%% %% -%% %% -%% 1. Scan through the path for *.tool files and find all the web %% -%% based tools. Query each tool for configuration data. %% -%% 2. Add Alias for Erlscript and html for each tool to %% -%% the webserver configuration data. %% -%% 3. Start the webserver. %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% API functions --export([start/0, start/2, stop/0]). - -%% Starting Webtool from a shell script --export([script_start/0, script_start/1]). - -%% Web api --export([started_tools/2, toolbar/2, start_tools/2, stop_tools/2]). - -%% API against other tools --export([is_localhost/0]). - -%% Debug export s --export([get_tools1/1]). --export([debug/1, stop_debug/0, debug_app/1]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). - --include_lib("kernel/include/file.hrl"). --include_lib("stdlib/include/ms_transform.hrl"). - --record(state,{priv_dir,app_data,supvis,web_data,started=[]}). - --define(MAX_NUMBER_OF_WEBTOOLS,256). --define(DEFAULT_PORT,8888).% must be >1024 or the user must be root on unix --define(DEFAULT_ADDR,{127,0,0,1}). - --define(WEBTOOL_ALIAS,{webtool,[{alias,{erl_alias,"/webtool",[webtool]}}]}). --define(HEADER,"Pragma:no-cache\r\n Content-type: text/html\r\n\r\n"). --define(HTML_HEADER,"<HTML>\r\n<HEAD>\r\n<TITLE>WebTool</TITLE>\r\n</HEAD>\r\n<BODY BGCOLOR=\"#FFFFFF\">\r\n"). --define(HTML_HEADER_RELOAD,"<HTML>\r\n<HEAD>\r\n<TITLE>WebTool - </TITLE>\r\n</HEAD>\r\n - <BODY BGCOLOR=\"#FFFFFF\" onLoad=reloadCompiledList()>\r\n"). - --define(HTML_END,"</BODY></HTML>"). - --define(SEND_URL_TIMEOUT,5000). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% For debugging only. %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Start tracing with -%% debug(Functions). -%% Functions = local | global | FunctionList -%% FunctionList = [Function] -%% Function = {FunctionName,Arity} | FunctionName | -%% {Module, FunctionName, Arity} | {Module,FunctionName} -debug(F) -> - ttb:tracer(all,[{file,"webtool.trc"}]), % tracing all nodes - ttb:p(all,[call,timestamp]), - MS = [{'_',[],[{return_trace},{message,{caller}}]}], - tp(F,MS), - ttb:ctp(?MODULE,stop_debug), % don't want tracing of the stop_debug func - ok. -tp(local,MS) -> % all functions - ttb:tpl(?MODULE,MS); -tp(global,MS) -> % all exported functions - ttb:tp(?MODULE,MS); -tp([{M,F,A}|T],MS) -> % Other module - ttb:tpl(M,F,A,MS), - tp(T,MS); -tp([{M,F}|T],MS) when is_atom(F) -> % Other module - ttb:tpl(M,F,MS), - tp(T,MS); -tp([{F,A}|T],MS) -> % function/arity - ttb:tpl(?MODULE,F,A,MS), - tp(T,MS); -tp([F|T],MS) -> % function - ttb:tpl(?MODULE,F,MS), - tp(T,MS); -tp([],_MS) -> - ok. -stop_debug() -> - ttb:stop([format]). - -debug_app(Mod) -> - ttb:tracer(all,[{file,"webtool_app.trc"},{handler,{fun out/4,true}}]), - ttb:p(all,[call,timestamp]), - MS = [{'_',[],[{return_trace},{message,{caller}}]}], - ttb:tp(Mod,MS), - ok. - -out(_,{trace_ts,Pid,call,MFA={M,F,A},{W,_,_},TS},_,S) - when W==webtool;W==mod_esi-> - io:format("~w: (~p)~ncall ~s~n", [TS,Pid,ffunc(MFA)]), - [{M,F,length(A)}|S]; -out(_,{trace_ts,Pid,return_from,MFA,R,TS},_,[MFA|S]) -> - io:format("~w: (~p)~nreturned from ~s -> ~p~n", [TS,Pid,ffunc(MFA),R]), - S; -out(_,_,_,_) -> - ok. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Functions called via script. %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -script_start() -> - usage(), - halt(). -script_start([App]) -> - DefaultBrowser = - case os:type() of - {win32,_} -> iexplore; - _ -> firefox - end, - script_start([App,DefaultBrowser]); -script_start([App,Browser]) -> - io:format("Starting webtool...\n"), - start(), - AvailableApps = get_applications(), - {OSType,_} = os:type(), - case lists:keysearch(App,1,AvailableApps) of - {value,{App,StartPage}} -> - io:format("Starting ~w...\n",[App]), - start_tools([],"app=" ++ atom_to_list(App)), - PortStr = integer_to_list(get_port()), - Url = case StartPage of - "/" ++ Page -> - "http://localhost:" ++ PortStr ++ "/" ++ Page; - _ -> - "http://localhost:" ++ PortStr ++ "/" ++ StartPage - end, - case Browser of - none -> - ok; - iexplore when OSType == win32-> - io:format("Starting internet explorer...\n"), - {ok,R} = win32reg:open(""), - Key="\\local_machine\\SOFTWARE\\Microsoft\\IE Setup\\Setup", - win32reg:change_key(R,Key), - {ok,Val} = win32reg:value(R,"Path"), - IExplore=filename:join(win32reg:expand(Val),"iexplore.exe"), - os:cmd("\"" ++ IExplore ++ "\" " ++ Url); - _ when OSType == win32 -> - io:format("Starting ~w...\n",[Browser]), - os:cmd("\"" ++ atom_to_list(Browser) ++ "\" " ++ Url); - B when B==firefox; B==mozilla -> - io:format("Sending URL to ~w...",[Browser]), - BStr = atom_to_list(Browser), - SendCmd = BStr ++ " -raise -remote \'openUrl(" ++ - Url ++ ")\'", - Port = open_port({spawn,SendCmd},[exit_status]), - receive - {Port,{exit_status,0}} -> - io:format("done\n"), - ok; - {Port,{exit_status,_Error}} -> - io:format(" not running, starting ~w...\n", - [Browser]), - os:cmd(BStr ++ " " ++ Url), - ok - after ?SEND_URL_TIMEOUT -> - io:format(" failed, starting ~w...\n",[Browser]), - erlang:port_close(Port), - os:cmd(BStr ++ " " ++ Url) - end; - _ -> - io:format("Starting ~w...\n",[Browser]), - os:cmd(atom_to_list(Browser) ++ " " ++ Url) - end, - ok; - false -> - stop(), - io:format("\n{error,{unknown_app,~p}}\n",[App]), - halt() - end. - -usage() -> - io:format("Starting webtool...\n"), - start(), - Apps = lists:map(fun({A,_}) -> A end,get_applications()), - io:format( - "\nUsage: start_webtool application [ browser ]\n" - "\nAvailable applications are: ~p\n" - "Default browser is \'iexplore\' (Internet Explorer) on Windows " - "or else \'firefox\'\n", - [Apps]), - stop(). - - -get_applications() -> - gen_server:call(web_tool,get_applications). - -get_port() -> - gen_server:call(web_tool,get_port). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Api functions to the genserver. %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%---------------------------------------------------------------------- -% -%---------------------------------------------------------------------- - -start()-> - start(standard_path,standard_data). - -start(Path,standard_data)-> - case get_standard_data() of - {error,Reason} -> - {error,Reason}; - Data -> - start(Path,Data) - end; - -start(standard_path,Data)-> - Path=get_path(), - start(Path,Data); - -start(Path,Port) when is_integer(Port)-> - Data = get_standard_data(Port), - start(Path,Data); - -start(Path,Data0)-> - Data = Data0 ++ rest_of_standard_data(), - gen_server:start({local,web_tool},webtool,{Path,Data},[]). - -stop()-> - gen_server:call(web_tool,stoppit). - -%---------------------------------------------------------------------- -%Web Api functions called by the web -%---------------------------------------------------------------------- -started_tools(Env,Input)-> - gen_server:call(web_tool,{started_tools,Env,Input}). - -toolbar(Env,Input)-> - gen_server:call(web_tool,{toolbar,Env,Input}). - -start_tools(Env,Input)-> - gen_server:call(web_tool,{start_tools,Env,Input}). - -stop_tools(Env,Input)-> - gen_server:call(web_tool,{stop_tools,Env,Input}). -%---------------------------------------------------------------------- -%Support API for other tools -%---------------------------------------------------------------------- - -is_localhost()-> - gen_server:call(web_tool,is_localhost). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%%The gen_server callback functions that builds the webbpages %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -handle_call(get_applications,_,State)-> - MS = ets:fun2ms(fun({Tool,{web_data,{_,Start}}}) -> {Tool,Start} end), - Tools = ets:select(State#state.app_data,MS), - {reply,Tools,State}; - -handle_call(get_port,_,State)-> - {value,{port,Port}}=lists:keysearch(port,1,State#state.web_data), - {reply,Port,State}; - -handle_call({started_tools,_Env,_Input},_,State)-> - {reply,started_tools_page(State),State}; - -handle_call({toolbar,_Env,_Input},_,State)-> - {reply,toolbar(),State}; - -handle_call({start_tools,Env,Input},_,State)-> - {NewState,Page}=start_tools_page(Env,Input,State), - {reply,Page,NewState}; - -handle_call({stop_tools,Env,Input},_,State)-> - {NewState,Page}=stop_tools_page(Env,Input,State), - {reply,Page,NewState}; - -handle_call(stoppit,_From,Data)-> - {stop,normal,ok,Data}; - -handle_call(is_localhost,_From,Data)-> - Result=case proplists:get_value(bind_address, Data#state.web_data) of - ?DEFAULT_ADDR -> - true; - _IpNumber -> - false - end, - {reply,Result,Data}. - - -handle_info(_Message,State)-> - {noreply,State}. - -handle_cast(_Request,State)-> - {noreply,State}. - -code_change(_,State,_)-> - {ok,State}. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% The other functions needed by the gen_server behaviour -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%---------------------------------------------------------------------- -% Start the gen_server -%---------------------------------------------------------------------- -init({Path,Config})-> - case filelib:is_dir(Path) of - true -> - {ok, Table} = get_tool_files_data(), - insert_app(?WEBTOOL_ALIAS, Table), - case webtool_sup:start_link() of - {ok, Pid} -> - case start_webserver(Table, Path, Config) of - {ok, _} -> - print_url(Config), - {ok,#state{priv_dir=Path, - app_data=Table, - supvis=Pid, - web_data=Config}}; - {error, Error} -> - {stop, {error, Error}} - end; - Error -> - {stop,Error} - end; - false -> - {stop, {error, error_dir}} - end. - -terminate(_Reason,Data)-> - %%shut down the webbserver - shutdown_server(Data), - %%Shutdown the different tools that are started with application:start - shutdown_apps(Data), - %%Shutdown the supervisor and its children will die - shutdown_supervisor(Data), - ok. - -print_url(ConfigData)-> - Server=proplists:get_value(server_name,ConfigData,"undefined"), - Port=proplists:get_value(port,ConfigData,"undefined"), - {A,B,C,D}=proplists:get_value(bind_address,ConfigData,"undefined"), - io:format("WebTool is available at http://~s:~w/~n",[Server,Port]), - io:format("Or http://~w.~w.~w.~w:~w/~n",[A,B,C,D,Port]). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% begin build the pages -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%---------------------------------------------------------------------- -%The page that shows the started tools -%---------------------------------------------------------------------- -started_tools_page(State)-> - [?HEADER,?HTML_HEADER,started_tools(State),?HTML_END]. - -toolbar()-> - [?HEADER,?HTML_HEADER,toolbar_page(),?HTML_END]. - - -start_tools_page(_Env,Input,State)-> - %%io:format("~n======= ~n ~p ~n============~n",[Input]), - case get_tools(Input) of - {tools,Tools}-> - %%io:format("~n======= ~n ~p ~n============~n",[Tools]), - {ok,NewState}=handle_apps(Tools,State,start), - {NewState,[?HEADER,?HTML_HEADER_RELOAD,reload_started_apps(), - show_unstarted_apps(NewState),?HTML_END]}; - _ -> - {State,[?HEADER,?HTML_HEADER,show_unstarted_apps(State),?HTML_END]} - end. - -stop_tools_page(_Env,Input,State)-> - case get_tools(Input) of - {tools,Tools}-> - {ok,NewState}=handle_apps(Tools,State,stop), - {NewState,[?HEADER,?HTML_HEADER_RELOAD,reload_started_apps(), - show_started_apps(NewState),?HTML_END]}; - _ -> - {State,[?HEADER,?HTML_HEADER,show_started_apps(State),?HTML_END]} - end. - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%% Functions that start and config the webserver -%% 1. Collect the config data -%% 2. Start webserver -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%---------------------------------------------------------------------- -% Start the webserver -%---------------------------------------------------------------------- -start_webserver(Data,Path,Config)-> - case get_conf_data(Data,Path,Config) of - {ok,Conf_data}-> - %%io:format("Conf_data: ~p~n",[Conf_data]), - start_server(Conf_data); - {error,Error} -> - {error,{error_server_conf_file,Error}} - end. - -start_server(Conf_data)-> - case inets:start(httpd, Conf_data, stand_alone) of - {ok,Pid}-> - {ok,Pid}; - Error-> - {error,{server_error,Error}} - end. - -%---------------------------------------------------------------------- -% Create config data for the webserver -%---------------------------------------------------------------------- -get_conf_data(Data,Path,Config)-> - Aliases=get_aliases(Data), - ServerRoot = filename:join([Path,"root"]), - MimeTypesFile = filename:join([ServerRoot,"conf","mime.types"]), - case httpd_conf:load_mime_types(MimeTypesFile) of - {ok,MimeTypes} -> - Config1 = Config ++ Aliases, - Config2 = [{server_root,ServerRoot}, - {document_root,filename:join([Path,"root/doc"])}, - {mime_types,MimeTypes} | - Config1], - {ok,Config2}; - Error -> - Error - end. - -%---------------------------------------------------------------------- -% Control the path for *.tools files -%---------------------------------------------------------------------- -get_tool_files_data()-> - Tools=get_tools1(code:get_path()), - %%io:format("Data : ~p ~n",[Tools]), - get_file_content(Tools). - -%---------------------------------------------------------------------- -%Control that the data in the file really is erlang terms -%---------------------------------------------------------------------- -get_file_content(Tools)-> - Get_data=fun({tool,ToolData}) -> - %%io:format("Data : ~p ~n",[ToolData]), - case proplists:get_value(config_func,ToolData) of - {M,F,A}-> - case catch apply(M,F,A) of - {'EXIT',_} -> - bad_data; - Data when is_tuple(Data) -> - Data; - _-> - bad_data - end; - _ -> - bad_data - end - end, - insert_file_content([X ||X<-lists:map(Get_data,Tools),X/=bad_data]). - -%---------------------------------------------------------------------- -%Insert the data from the file in to the ets:table -%---------------------------------------------------------------------- -insert_file_content(Content)-> - Table=ets:new(app_data,[bag]), - lists:foreach(fun(X)-> - insert_app(X,Table) - end,Content), - {ok,Table}. - -%---------------------------------------------------------------------- -%Control that we got a a tuple of a atom and a list if so add the -%elements in the list to the ets:table -%---------------------------------------------------------------------- -insert_app({Name,Key_val_list},Table) when is_list(Key_val_list),is_atom(Name)-> - %%io:format("ToolData: ~p: ~p~n",[Name,Key_val_list]), - lists:foreach( - fun({alias,{erl_alias,Alias,Mods}}) -> - Key_val = {erl_script_alias,{Alias,Mods}}, - %%io:format("Insert: ~p~n",[Key_val]), - ets:insert(Table,{Name,Key_val}); - (Key_val_pair)-> - %%io:format("Insert: ~p~n",[Key_val_pair]), - ets:insert(Table,{Name,Key_val_pair}) - end, - Key_val_list); - -insert_app(_,_)-> - ok. - -%---------------------------------------------------------------------- -% Select all the alias in the database -%---------------------------------------------------------------------- -get_aliases(Data)-> - MS = ets:fun2ms(fun({_,{erl_script_alias,Alias}}) -> - {erl_script_alias,Alias}; - ({_,{alias,Alias}}) -> - {alias,Alias} - end), - ets:select(Data,MS). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Helper functions %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -get_standard_data(Port)-> - [ - {port,Port}, - {bind_address,?DEFAULT_ADDR}, - {server_name,"localhost"} - ]. - -get_standard_data()-> - case get_free_port(?DEFAULT_PORT,?MAX_NUMBER_OF_WEBTOOLS) of - {error,Reason} -> {error,Reason}; - Port -> - [ - {port,Port}, - {bind_address,?DEFAULT_ADDR}, - {server_name,"localhost"} - ] - end. - -get_free_port(_Port,0) -> - {error,no_free_port_found}; -get_free_port(Port,N) -> - case gen_tcp:connect("localhost",Port,[]) of - {error, _Reason} -> - Port; - {ok,Sock} -> - gen_tcp:close(Sock), - get_free_port(Port+1,N-1) - end. - -rest_of_standard_data() -> - [ - %% Do not allow the server to be crashed by malformed http-request - {max_header_siz,1024}, - {max_header_action,reply414}, - %% Go on a straight ip-socket - {com_type,ip_comm}, - %% Do not change the order of these module names!! - {modules,[mod_alias, - mod_auth, - mod_esi, - mod_actions, - mod_cgi, - mod_include, - mod_dir, - mod_get, - mod_head, - mod_log, - mod_disk_log]}, - {directory_index,["index.html"]}, - {default_type,"text/plain"} - ]. - - -get_path()-> - code:priv_dir(webtool). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% These functions is used to shutdown the webserver -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%---------------------------------------------------------------------- -% Shut down the webbserver -%---------------------------------------------------------------------- -shutdown_server(State)-> - {Addr,Port} = get_addr_and_port(State#state.web_data), - inets:stop(httpd,{Addr,Port}). - -get_addr_and_port(Config) -> - Addr = proplists:get_value(bind_address,Config,?DEFAULT_ADDR), - Port = proplists:get_value(port,Config,?DEFAULT_PORT), - {Addr,Port}. - -%---------------------------------------------------------------------- -% Select all apps in the table and close them -%---------------------------------------------------------------------- -shutdown_apps(State)-> - Data=State#state.app_data, - MS = ets:fun2ms(fun({_,{start,HowToStart}}) -> HowToStart end), - lists:foreach(fun(Start_app)-> - stop_app(Start_app) - end, - ets:select(Data,MS)). - -%---------------------------------------------------------------------- -%Shuts down the supervisor that supervises tools that is not -%Designed as applications -%---------------------------------------------------------------------- -shutdown_supervisor(State)-> - %io:format("~n==================~n"), - webtool_sup:stop(State#state.supvis). - %io:format("~n==================~n"). - -%---------------------------------------------------------------------- -%close the individual apps. -%---------------------------------------------------------------------- -stop_app({child,_Real_name})-> - ok; - -stop_app({app,Real_name})-> - application:stop(Real_name); - -stop_app({func,_Start,Stop})-> - case Stop of - {M,F,A} -> - catch apply(M,F,A); - _NoStop -> - ok - end. - - - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%% These functions creates the webpage where the user can select if -%% to start apps or to stop apps -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -toolbar_page()-> - "<TABLE> - <TR> - <TD> - <B>Select Action</B> - </TD> - </TR> - <TR> - <TD> - <A HREF=\"./start_tools\" TARGET=right> Start Tools</A> - </TD> - </TR> - <TR> - <TD> - <A HREF=\"./stop_tools\" TARGET=right> Stop Tools</A> - </TD> - </TR> - </TABLE>". -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%% These functions creates the webbpage that shows the started apps -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%---------------------------------------------------------------------- -% started_tools(State)->String (html table) -% State is a record of type state -%---------------------------------------------------------------------- -started_tools(State)-> - Names=get_started_apps(State#state.app_data,State#state.started), - "<TABLE BORDER=1 WIDTH=100%> - "++ make_rows(Names,[],0) ++" - </TABLE>". -%---------------------------------------------------------------------- -%get_started_apps(Data,Started)-> [{web_name,link}] -%selects the started apps from the ets table of apps. -%---------------------------------------------------------------------- - -get_started_apps(Data,Started)-> - SelectData=fun({Name,Link}) -> - {Name,Link} - end, - MS = lists:map(fun(A) -> {{A,{web_data,'$1'}},[],['$1']} end,Started), - - [{"WebTool","/tool_management.html"} | - [SelectData(X) || X <- ets:select(Data,MS)]]. - -%---------------------------------------------------------------------- -% make_rows(List,Result,Fields)-> String (The rows of a htmltable -% List a list of tupler discibed above -% Result an accumulator for the result -% Field, counter that counts the number of cols in each row. -%---------------------------------------------------------------------- -make_rows([],Result,Fields)-> - Result ++ fill_out(Fields); -make_rows([Data|Paths],Result,Field)when Field==0-> - make_rows(Paths,Result ++ "<TR>" ++ make_field(Data),Field+1); - -make_rows([Path|Paths],Result,Field)when Field==4-> - make_rows(Paths,Result ++ make_field(Path) ++ "</TR>",0); - -make_rows([Path|Paths],Result,Field)-> - make_rows(Paths,Result ++ make_field(Path),Field+1). - -%---------------------------------------------------------------------- -% make_fields(Path)-> String that is a field i a html table -% Path is a name url tuple {Name,url} -%---------------------------------------------------------------------- -make_field(Path)-> - "<TD WIDTH=20%>" ++ get_name(Path) ++ "</TD>". - - -%---------------------------------------------------------------------- -%get_name({Nae,Url})->String that represents a <A> tag in html. -%---------------------------------------------------------------------- -get_name({Name,Url})-> - "<A HREF=\"" ++ Url ++ "\" TARGET=app_frame>" ++ Name ++ "</A>". - - -%---------------------------------------------------------------------- -% fill_out(Nr)-> String, that represent Nr fields in a html-table. -%---------------------------------------------------------------------- -fill_out(Nr)when Nr==0-> - []; -fill_out(Nr)when Nr==4-> - "<TD WIDTH=\"20%\" > </TD></TR>"; - -fill_out(Nr)-> - "<TD WIDTH=\"20%\"> </TD>" ++ fill_out(Nr+1). - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%%These functions starts applicatons and builds the page showing tools -%%to start -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%---------------------------------------------------------------------- -%Controls whether the user selected a tool to start -%---------------------------------------------------------------------- -get_tools(Input)-> - case httpd:parse_query(Input) of - []-> - no_tools; - Tools-> - FormatData=fun({_Name,Data}) -> list_to_atom(Data) end, - SelectData= - fun({Name,_Data}) -> string:equal(Name,"app") end, - {tools,[FormatData(X)||X<-Tools,SelectData(X)]} - end. - -%---------------------------------------------------------------------- -% Selects the data to start the applications the user has ordered -% starting of -%---------------------------------------------------------------------- -handle_apps([],State,_Cmd)-> - {ok,State}; - -handle_apps([Tool|Tools],State,Cmd)-> - case ets:match_object(State#state.app_data,{Tool,{start,'_'}}) of - []-> - Started = case Cmd of - start -> - [Tool|State#state.started]; - stop -> - lists:delete(Tool,State#state.started) - end, - {ok,#state{priv_dir=State#state.priv_dir, - app_data=State#state.app_data, - supvis=State#state.supvis, - web_data=State#state.web_data, - started=Started}}; - ToStart -> - case handle_apps2(ToStart,State,Cmd) of - {ok,NewState}-> - handle_apps(Tools,NewState,Cmd); - _-> - handle_apps(Tools,State,Cmd) - end - end. - -%---------------------------------------------------------------------- -%execute every start or stop data about a tool. -%---------------------------------------------------------------------- -handle_apps2([{Name,Start_data}],State,Cmd)-> - case handle_app({Name,Start_data},State#state.app_data,State#state.supvis,Cmd) of - ok-> - Started = case Cmd of - start -> - [Name|State#state.started]; - stop -> - - lists:delete(Name,State#state.started) - end, - {ok,#state{priv_dir=State#state.priv_dir, - app_data=State#state.app_data, - supvis=State#state.supvis, - web_data=State#state.web_data, - started=Started}}; - _-> - error - end; - -handle_apps2([{Name,Start_data}|Rest],State,Cmd)-> - case handle_app({Name,Start_data},State#state.app_data,State#state.supvis,Cmd)of - ok-> - handle_apps2(Rest,State,Cmd); - _-> - error - end. - - -%---------------------------------------------------------------------- -% Handle start and stop of applications -%---------------------------------------------------------------------- - -handle_app({Name,{start,{func,Start,Stop}}},Data,_Pid,Cmd)-> - Action = case Cmd of - start -> - Start; - _ -> - Stop - end, - case Action of - {M,F,A} -> - case catch apply(M,F,A) of - {'EXIT',_} = Exit-> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not start application \'~p\'\n\n" - "~w:~w(~s) ->\n" - "~p\n\n", - [?LINE,Name,M,F,format_args(A),Exit]), - ets:delete(Data,Name); - _OK-> - ok - end; - _NoStart -> - ok - end; - - -handle_app({Name,{start,{child,ChildSpec}}},Data,Pid,Cmd)-> - case Cmd of - start -> - case catch supervisor:start_child(Pid,ChildSpec) of - {ok,_}-> - ok; - {ok,_,_}-> - ok; - {error,Reason}-> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not start application \'~p\'\n\n" - "supervisor:start_child(~p,~p) ->\n" - "~p\n\n", - [?LINE,Name,Pid,ChildSpec,{error,Reason}]), - ets:delete(Data,Name); - Error -> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not start application \'~p\'\n\n" - "supervisor:start_child(~p,~p) ->\n" - "~p\n\n", - [?LINE,Name,Pid,ChildSpec,Error]), - ets:delete(Data,Name) - end; - stop -> - case catch supervisor:terminate_child(websup,element(1,ChildSpec)) of - ok -> - supervisor:delete_child(websup,element(1,ChildSpec)); - _ -> - error - end - end; - - - -handle_app({Name,{start,{app,Real_name}}},Data,_Pid,Cmd)-> - case Cmd of - start -> - case application:start(Real_name,temporary) of - ok-> - io:write(Name), - ok; - {error,{already_started,_}}-> - %% Remove it from the database so we dont start - %% anything already started - ets:match_delete(Data,{Name,{start,{app,Real_name}}}), - ok; - {error,_Reason}=Error-> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not start application \'~p\'\n\n" - "application:start(~p,~p) ->\n" - "~p\n\n", - [?LINE,Name,Real_name,temporary,Error]), - ets:delete(Data,Name) - end; - - stop -> - application:stop(Real_name) - end; - -%---------------------------------------------------------------------- -% If the data is incorrect delete the app -%---------------------------------------------------------------------- -handle_app({Name,Incorrect},Data,_Pid,Cmd)-> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not ~w application \'~p\'\n\n" - "Incorrect data: ~p\n\n", - [?LINE,Cmd,Name,Incorrect]), - ets:delete(Data,Name). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% this functions creates the page that shows the unstarted tools %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -reload_started_apps()-> - "<script> - function reloadCompiledList() - { - parent.parent.top1.document.location.href=\"/webtool/webtool/started_tools\"; - } - </script>". - -show_unstarted_apps(State)-> - "<TABLE HEIGHT=100% WIDTH=100% BORDER=0> - <TR HEIGHT=80%><TD ALIGN=\"center\" VALIGN=\"middle\"> - <FORM NAME=\"stop_apps\" ACTION=\"/webtool/webtool/start_tools\" > - <TABLE BORDER=1 WIDTH=60%> - <TR BGCOLOR=\"#8899AA\"> - <TD ALIGN=CENTER COLSPAN=2><FONT SIZE=4>Available Tools<FONT></TD> - </TR> - <TR> - <TD WIDTH=50%> - <TABLE BORDER=0> - "++ list_available_apps(State)++" - <TR><TD COLSPAN=2> </TD></TR> - <TR> - <TD COLSPAN=2 ALIGN=\"center\"> - <INPUT TYPE=submit VALUE=\"Start\"> - </TD> - </TR> - </TABLE> - </TD> - <TD> - To Start a Tool: - <UL> - <LI>Select the - checkbox for each tool to - start.</LI> - <LI>Click on the - button marked <EM>Start</EM>.</LI></UL> - </TD> - </TR> - </TABLE> - </FORM> - </TD></TR> - <TR><TD> </TD></TR> - </TABLE>". - - - -list_available_apps(State)-> - MS = ets:fun2ms(fun({Tool,{web_data,{Name,_}}}) -> {Tool,Name} end), - Unstarted_apps= - lists:filter( - fun({Tool,_})-> - false==lists:member(Tool,State#state.started) - end, - ets:select(State#state.app_data,MS)), - case Unstarted_apps of - []-> - "<TR><TD>All tools are started</TD></TR>"; - _-> - list_apps(Unstarted_apps) - end. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% these functions creates the page that shows the started apps %% -%% the user can select to shutdown %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -show_started_apps(State)-> - "<TABLE HEIGHT=100% WIDTH=100% BORDER=0> - <TR HEIGHT=80%><TD ALIGN=\"center\" VALIGN=\"middle\"> - <FORM NAME=\"stop_apps\" ACTION=\"/webtool/webtool/stop_tools\" > - <TABLE BORDER=1 WIDTH=60%> - <TR BGCOLOR=\"#8899AA\"> - <TD ALIGN=CENTER COLSPAN=2><FONT SIZE=4>Started Tools<FONT></TD> - </TR> - <TR> - <TD WIDTH=50%> - <TABLE BORDER=0> - "++ list_started_apps(State)++" - <TR><TD COLSPAN=2> </TD></TR> - <TR> - <TD COLSPAN=2 ALIGN=\"center\"> - <INPUT TYPE=submit VALUE=\"Stop\"> - </TD> - </TR> - </TABLE> - </TD> - <TD> - Stop a Tool: - <UL> - <LI>Select the - checkbox for each tool to - stop.</LI> - <LI>Click on the - button marked <EM>Stop</EM>.</LI></UL> - </TD> - </TR> - </TABLE> - </FORM> - </TD></TR> - <TR><TD> </TD></TR> - </TABLE>". - -list_started_apps(State)-> - MS = lists:map(fun(A) -> {{A,{web_data,{'$1','_'}}},[],[{{A,'$1'}}]} end, - State#state.started), - Started_apps= ets:select(State#state.app_data,MS), - case Started_apps of - []-> - "<TR><TD>No tool is started yet.</TD></TR>"; - _-> - list_apps(Started_apps) - end. - - -list_apps(Apps) -> - lists:map(fun({Tool,Name})-> - "<TR><TD> - <INPUT TYPE=\"checkbox\" NAME=\"app\" VALUE=\"" - ++ atom_to_list(Tool) ++ "\"> - " ++ Name ++ " - </TD></TR>" - end, - Apps). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Collecting the data from the *.tool files %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%---------------------------------------- -% get_tools(Dirs) => [{M,F,A},{M,F,A}...{M,F,A}] -% Dirs - [string()] Directory names -% Calls get_tools2/2 recursively for a number of directories -% to retireve the configuration data for the web based tools. -%---------------------------------------- -get_tools1(Dirs)-> - get_tools1(Dirs,[]). - -get_tools1([Dir|Rest],Data) when is_list(Dir) -> - Tools=case filename:basename(Dir) of - %% Dir is an 'ebin' directory, check in '../priv' as well - "ebin" -> - [get_tools2(filename:join(filename:dirname(Dir),"priv")) | - get_tools2(Dir)]; - _ -> - get_tools2(Dir) - end, - get_tools1(Rest,[Tools|Data]); - -get_tools1([],Data) -> - lists:flatten(Data). - -%---------------------------------------- -% get_tools2(Directory) => DataList -% DataList : [WebTuple]|[] -% WebTuple: {tool,[{web,M,F,A}]} -% -%---------------------------------------- -get_tools2(Dir)-> - get_tools2(tool_files(Dir),[]). - -get_tools2([ToolFile|Rest],Data) -> - case get_tools3(ToolFile) of - {tool,WebData} -> - get_tools2(Rest,[{tool,WebData}|Data]); - {error,_Reason} -> - get_tools2(Rest,Data); - nodata -> - get_tools2(Rest,Data) - end; - -get_tools2([],Data) -> - Data. - -%---------------------------------------- -% get_tools3(ToolFile) => {ok,Tool}|{error,Reason}|nodata -% Tool: {tool,[KeyValTuple]} -% ToolFile - string() A .tool file -% Now we have the file get the data and sort it out -%---------------------------------------- -get_tools3(ToolFile) -> - case file:consult(ToolFile) of - {error,open} -> - {error,nofile}; - {error,read} -> - {error,format}; - {ok,[{version,"1.2"},ToolInfo]} when is_list(ToolInfo)-> - webdata(ToolInfo); - {ok,[{version,_Vsn},_Info]} -> - {error,old_version}; - {ok,_Other} -> - {error,format} - end. - - -%---------------------------------------------------------------------- -% webdata(TupleList)-> ToolTuple| nodata -% ToolTuple: {tool,[{config_func,{M,F,A}}]} -% -% There are a little unneccesary work in this format but it is extendable -%---------------------------------------------------------------------- -webdata(TupleList)-> - case proplists:get_value(config_func,TupleList,nodata) of - {M,F,A} -> - {tool,[{config_func,{M,F,A}}]}; - _ -> - nodata - end. - - -%============================================================================= -% Functions for getting *.tool configuration files -%============================================================================= - -%---------------------------------------- -% tool_files(Dir) => ToolFiles -% Dir - string() Directory name -% ToolFiles - [string()] -% Return the list of all files in Dir ending with .tool (appended to Dir) -%---------------------------------------- -tool_files(Dir) -> - case file:list_dir(Dir) of - {ok,Files} -> - filter_tool_files(Dir,Files); - {error,_Reason} -> - [] - end. - -%---------------------------------------- -% filter_tool_files(Dir,Files) => ToolFiles -% Dir - string() Directory name -% Files, ToolFiles - [string()] File names -% Filters out the files in Files ending with .tool and append them to Dir -%---------------------------------------- -filter_tool_files(_Dir,[]) -> - []; -filter_tool_files(Dir,[File|Rest]) -> - case filename:extension(File) of - ".tool" -> - [filename:join(Dir,File)|filter_tool_files(Dir,Rest)]; - _ -> - filter_tool_files(Dir,Rest) - end. - - -%%%----------------------------------------------------------------- -%%% format functions -ffunc({M,F,A}) when is_list(A) -> - io_lib:format("~w:~w(~s)\n",[M,F,format_args(A)]); -ffunc({M,F,A}) when is_integer(A) -> - io_lib:format("~w:~w/~w\n",[M,F,A]). - -format_args([]) -> - ""; -format_args(Args) -> - Str = lists:append(["~p"|lists:duplicate(length(Args)-1,",~p")]), - io_lib:format(Str,Args). diff --git a/lib/webtool/src/webtool_sup.erl b/lib/webtool/src/webtool_sup.erl deleted file mode 100644 index e4a05c53ae..0000000000 --- a/lib/webtool/src/webtool_sup.erl +++ /dev/null @@ -1,75 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(webtool_sup). - --behaviour(supervisor). - -%% External exports --export([start_link/0,stop/1]). - -%% supervisor callbacks --export([init/1]). - -%%%---------------------------------------------------------------------- -%%% API -%%%---------------------------------------------------------------------- -start_link() -> - supervisor:start_link({local,websup},webtool_sup, []). - -stop(Pid)-> - exit(Pid,normal). -%%%---------------------------------------------------------------------- -%%% Callback functions from supervisor -%%%---------------------------------------------------------------------- - -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, {SupFlags, [ChildSpec]}} | -%% ignore | -%% {error, Reason} -%%---------------------------------------------------------------------- -init(_StartArgs) -> - %%Child1 = - %%Child2 ={webcover_backend,{webcover_backend,start_link,[]},permanent,2000,worker,[webcover_backend]}, - %%{ok,{{simple_one_for_one,5,10},[Child1]}}. - {ok,{{one_for_one,100,10},[]}}. - -%%%---------------------------------------------------------------------- -%%% Internal functions -%%%---------------------------------------------------------------------- - - - - - - - - - - - - - - - - - - - diff --git a/lib/webtool/test/Makefile b/lib/webtool/test/Makefile deleted file mode 100644 index 93aa1c09eb..0000000000 --- a/lib/webtool/test/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= \ - webtool_SUITE - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) -INSTALL_PROGS= $(TARGET_FILES) - -EMAKEFILE=Emakefile - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/webtool_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) webtool.spec "$(RELSYSDIR)" - chmod -R u+w "$(RELSYSDIR)" - -release_docs_spec: diff --git a/lib/webtool/test/webtool.spec b/lib/webtool/test/webtool.spec deleted file mode 100644 index 134e6ed40c..0000000000 --- a/lib/webtool/test/webtool.spec +++ /dev/null @@ -1 +0,0 @@ -{suites,"../webtool_test",all}. diff --git a/lib/webtool/test/webtool_SUITE.erl b/lib/webtool/test/webtool_SUITE.erl deleted file mode 100644 index 9e2d9a2e0f..0000000000 --- a/lib/webtool/test/webtool_SUITE.erl +++ /dev/null @@ -1,51 +0,0 @@ -%% ``Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. -%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -%% AB. All Rights Reserved.'' -%% --module(webtool_SUITE). - --compile([export_all]). --include_lib("common_test/include/ct.hrl"). - -suite() -> - [{ct_hooks, [ts_install_cth]}]. - -all() -> - [app, appup]. - -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -app() -> - [{doc, "Test that the webtool app file is ok"}]. -app(Config) when is_list(Config) -> - ok = ?t:app_test(webtool). - -appup() -> - [{doc, "Test that the webtool appup file is ok"}]. -appup(Config) when is_list(Config) -> - ok = ?t:appup_test(webtool). diff --git a/lib/webtool/vsn.mk b/lib/webtool/vsn.mk deleted file mode 100644 index 4a701ae6e0..0000000000 --- a/lib/webtool/vsn.mk +++ /dev/null @@ -1 +0,0 @@ -WEBTOOL_VSN=0.9 diff --git a/lib/wx/api_gen/Makefile b/lib/wx/api_gen/Makefile index d605f3d8d8..3fa8f1feee 100644 --- a/lib/wx/api_gen/Makefile +++ b/lib/wx/api_gen/Makefile @@ -49,7 +49,7 @@ opt: $(WX) $(GL) $(WX): wxxml_generated $(COMPILER_T) wxapi.conf $(wildcard wx_extra/wx*.c_src) $(wildcard wx_extra/wx*.erl) erl -noshell -run wx_gen code && touch wx_code_generated -wxxml_generated: wx_doxygen.conf wx_extra/bugs.h wx_extra/wxe_evth.h +wxxml_generated: wx_doxygen.conf wx_extra/bugs.h wx_extra/wxe_evth.h wx_extra/added_func.h sed -e 's|@WXGTK_DIR@|$(WXGTK_DIR)|g' wx_doxygen.conf > wx_doxygen doxygen wx_doxygen && touch wxxml_generated diff --git a/lib/wx/api_gen/wx_extra/added_func.h b/lib/wx/api_gen/wx_extra/added_func.h new file mode 100644 index 0000000000..2323529368 --- /dev/null +++ b/lib/wx/api_gen/wx_extra/added_func.h @@ -0,0 +1,28 @@ +// Added 3.0 functionality + +class WXDLLIMPEXP_AUI wxAuiTabArt +{ +public: + virtual void SetColour(const wxColour& colour) = 0; + virtual void SetActiveColour(const wxColour& colour) = 0; +}; + +// Api to get data out of paneinfo +class WXDLLIMPEXP_AUI wxAuiPaneInfo +{ + public: + wxString GetName(); + wxString GetCaption(); + wxIcon GetIcon(); + + wxWindow* GetWindow(); + wxFrame* GetFrame(); + + int GetDirection(); + int GetLayer(); + int GetRow(); + int GetPosition(); + + wxPoint GetFloatingPosition(); + wxSize GetFloatingSize(); +}; diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl index 114b3e561e..5cf09e5eee 100644 --- a/lib/wx/api_gen/wx_gen.erl +++ b/lib/wx/api_gen/wx_gen.erl @@ -771,14 +771,19 @@ parse_type2([N="wxGridCellCoordsArray"|R],Info,Opts,T) -> parse_type2(R,Info,Opts,T#type{name=N,base={comp,"wxGridCellCoords", [{int,"R"},{int,"C"}]}, single=array}); +parse_type2([N="wxAuiPaneInfoArray"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={class,"wxAuiPaneInfo"}, + single=array}); + parse_type2([N="wxRect"|R],Info,Opts,T) -> parse_type2(R,Info,Opts,T#type{name=N,base={comp,N,[{int,"X"},{int,"Y"}, {int,"W"},{int,"H"}]}}); parse_type2([N="wxColour"|R],Info,Opts,T) -> parse_type2(R,Info,Opts,T#type{name=N, base={comp,N,[{int,"R"},{int,"G"},{int,"B"},{int,"A"}]}}); -parse_type2([N="wxColor"|R],Info,Opts,T) -> - parse_type2(R,Info,Opts,T#type{name="wxColour", +parse_type2(["wxColor"|R],Info,Opts,T) -> + N = "wxColour", + parse_type2(R,Info,Opts,T#type{name=N, base={comp,N,[{int,"R"},{int,"G"},{int,"B"},{int,"A"}]}}); parse_type2([N="wxPoint2DDouble"|R],Info,Opts,T) -> diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl index 2ce6295078..5649336b5d 100644 --- a/lib/wx/api_gen/wx_gen_cpp.erl +++ b/lib/wx/api_gen/wx_gen_cpp.erl @@ -235,7 +235,8 @@ gen_funcs(Defs) -> w("}} /* The End */~n~n~n"), UglySkipList = ["wxCaret", "wxCalendarDateAttr", - "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject" + "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject", + "wxAuiSimpleTabArt" ], w("bool WxeApp::delete_object(void *ptr, wxeRefData *refd) {~n", []), @@ -323,12 +324,8 @@ gen_method(CName, M=#method{name=N,params=Ps0,type=T,method_type=MT,id=MethodId put(current_func, N), put(bin_count,-1), ?WTC("gen_method"), - Endif = case lists:keysearch(deprecated, 1, FOpts) of - {value, {deprecated, IfDef}} -> - w("#if ~s~n", [IfDef]), - true; - _ -> false - end, + Endif1 = gen_if(deprecated, FOpts), + Endif2 = gen_if(test_if, FOpts), w("case ~s: { // ~s::~s~n", [wx_gen_erl:get_unique_name(MethodId),CName,N]), Ps1 = declare_variables(void, Ps0), {Ps2,Align} = decode_arguments(Ps1), @@ -347,10 +344,19 @@ gen_method(CName, M=#method{name=N,params=Ps0,type=T,method_type=MT,id=MethodId free_args(), build_return_vals(T,Ps3), w(" break;~n}~n", []), - Endif andalso w("#endif~n", []), + Endif1 andalso w("#endif~n", []), + Endif2 andalso w("#endif~n", []), erase(current_func), M. +gen_if(What, Opts) -> + case lists:keysearch(What, 1, Opts) of + {value, {What, IfDef}} -> + w("#if ~s~n", [IfDef]), + true; + _ -> false + end. + declare_variables(void,Ps) -> [declare_var(P) || P <- Ps]; declare_variables(T, Ps) -> @@ -1014,6 +1020,10 @@ build_ret(Name,_,#type{base={comp,_,_},single=array}) -> w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]), w(" rt.add(~s[i]);~n }~n",[Name]), w(" rt.endList(~s.GetCount());~n",[Name]); +build_ret(Name,_,#type{base={class,Class},single=array}) -> + w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]), + w(" rt.addRef(getRef((void *) &~s.Item(i), memenv), \"~s\");~n }~n",[Name, Class]), + w(" rt.endList(~s.GetCount());~n",[Name]); build_ret(Name,_,#type{name=List,single=list,base={class,Class}}) -> w(" int i=0;~n"), w(" for(~s::const_iterator it = ~s.begin(); it != ~s.end(); ++it) {~n", diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index 0d1fef6272..f076323bea 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -1246,7 +1246,8 @@ 'SetArtProvider','SetDockSizeConstraint','SetFlags','SetManagedWindow', 'ShowHint','UnInit','Update']}. -{class, wxAuiPaneInfo, root, [{ifdef, wxUSE_AUI}], +{class, wxAuiPaneInfo, root, + [{ifdef, wxUSE_AUI}], [ wxAuiPaneInfo,'~wxAuiPaneInfo', 'BestSize','Bottom','BottomDockable','Caption','CaptionVisible', @@ -1263,7 +1264,44 @@ 'MinSize','MinimizeButton','Movable','Name', 'PaneBorder','PinButton','Position','Resizable','Right', 'RightDockable','Row','SafeSet','SetFlag','Show','ToolbarPane', - 'Top','TopDockable','Window']}. + 'Top','TopDockable','Window', + %% Extended func + %% These are not initilized by default and thus cause crashes + %% {'GetName', + %% [{pre_hook, [{c, "#if 0\n"}]}, + %% {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n wxString Result = This->name"}]}]}, + %% {'GetCaption', + %% [{pre_hook, [{c, "#if 0\n"}]}, + %% {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n wxString Result = This->caption"}]}]}, + %% {'GetIcon', + %% [{pre_hook, [{c, "#if 0\n"}]}, + %% {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n wxIcon Result = This->icon"}]}]}, + {'GetWindow', + [{pre_hook, [{c, "#if 0\n"}]}, + {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n wxWindow* Result = This->window"}]}]}, + {'GetFrame', + [{pre_hook, [{c, "#if 0\n"}]}, + {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n wxFrame* Result = This->frame"}]}]}, + {'GetDirection', + [{pre_hook, [{c, "#if 0\n"}]}, + {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n int Result = This->dock_direction"}]}]}, + {'GetLayer', + [{pre_hook, [{c, "#if 0\n"}]}, + {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n int Result = This->dock_layer"}]}]}, + {'GetRow', + [{pre_hook, [{c, "#if 0\n"}]}, + {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n int Result = This->dock_row"}]}]}, + {'GetPosition', + [{pre_hook, [{c, "#if 0\n"}]}, + {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n int Result = This->dock_pos"}]}]}, + {'GetFloatingPosition', + [{pre_hook, [{c, "#if 0\n"}]}, + {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n wxPoint Result = This->floating_pos"}]}]}, + {'GetFloatingSize', + [{pre_hook, [{c, "#if 0\n"}]}, + {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n wxSize Result = This->floating_size"}]}]} + +]}. {class, wxAuiNotebook, wxControl, [{ifdef, wxUSE_AUI}], ['wxAuiNotebook','AddPage',%'AdvanceSelection', @@ -1282,15 +1320,22 @@ %'Clone','DrawBackground','DrawButton','DrawTab','GetBestTabCtrlSize', %'GetIndentSize','GetTabSize','SetFlags','SetMeasuringFont', %'SetNormalFont','SetSelectedFont','SetSizingInfo'%,'ShowWindowList' + 'SetFlags', 'SetMeasuringFont', 'SetNormalFont', 'SetSelectedFont', + {'SetColour', [{test_if, "wxCHECK_VERSION(3,0,0)"}]}, + {'SetActiveColour', [{test_if, "wxCHECK_VERSION(3,0,0)"}]} ]}. {class,wxAuiDockArt, root, [{ifdef, wxUSE_AUI}], [%% 'wxAuiDockArt','~wxAuiDockArt' %, %%'DrawBackground','DrawBorder','DrawCaption', %% Pure virtual funcs %%'DrawGripper','DrawPaneButton','DrawSash', - %%'GetColor','GetColour','GetFont','GetMetric','SetColor','SetColour','SetFont','SetMetric' + 'GetColour','GetFont','GetMetric','SetColour','SetFont','SetMetric' ]}. +{class,wxAuiSimpleTabArt, wxAuiTabArt, [{ifdef, wxUSE_AUI}], + [wxAuiSimpleTabArt]}. + + {class, wxMDIParentFrame, wxFrame, [], [ 'wxMDIParentFrame', @@ -1870,7 +1915,7 @@ ]}. -{class, wxAuiManagerEvent, wxEvent, +{class, wxAuiManagerEvent, wxEvent, [{acc, [{button, "GetButton()"}, {dc, "GetDC()"}, {pane, "GetPane()"}, @@ -1880,6 +1925,7 @@ wxEVT_AUI_PANE_CLOSE, wxEVT_AUI_PANE_MAXIMIZE, wxEVT_AUI_PANE_RESTORE, + {wxEVT_AUI_PANE_ACTIVATED, {test_if, "wxCHECK_VERSION(2,9,5)"}}, wxEVT_AUI_RENDER, wxEVT_AUI_FIND_MANAGER ]}], diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp index f6a5868b48..a532ee985d 100644 --- a/lib/wx/c_src/gen/wxe_events.cpp +++ b/lib/wx/c_src/gen/wxe_events.cpp @@ -54,255 +54,258 @@ void initEventTable() struct { int ev_type; int class_id; const char * ev_name;} event_types[] = { {wxEVT_NULL, 0, "null"}, - {wxEVT_COMMAND_BUTTON_CLICKED, 164, "command_button_clicked"}, - {wxEVT_COMMAND_CHECKBOX_CLICKED, 164, "command_checkbox_clicked"}, - {wxEVT_COMMAND_CHOICE_SELECTED, 164, "command_choice_selected"}, - {wxEVT_COMMAND_LISTBOX_SELECTED, 164, "command_listbox_selected"}, - {wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 164, "command_listbox_doubleclicked"}, - {wxEVT_COMMAND_TEXT_UPDATED, 164, "command_text_updated"}, - {wxEVT_COMMAND_TEXT_ENTER, 164, "command_text_enter"}, - {wxEVT_COMMAND_MENU_SELECTED, 164, "command_menu_selected"}, - {wxEVT_COMMAND_SLIDER_UPDATED, 164, "command_slider_updated"}, - {wxEVT_COMMAND_RADIOBOX_SELECTED, 164, "command_radiobox_selected"}, - {wxEVT_COMMAND_RADIOBUTTON_SELECTED, 164, "command_radiobutton_selected"}, - {wxEVT_COMMAND_SCROLLBAR_UPDATED, 164, "command_scrollbar_updated"}, - {wxEVT_COMMAND_VLBOX_SELECTED, 164, "command_vlbox_selected"}, - {wxEVT_COMMAND_COMBOBOX_SELECTED, 164, "command_combobox_selected"}, - {wxEVT_COMMAND_TOOL_RCLICKED, 164, "command_tool_rclicked"}, - {wxEVT_COMMAND_TOOL_ENTER, 164, "command_tool_enter"}, - {wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 164, "command_checklistbox_toggled"}, - {wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 164, "command_togglebutton_clicked"}, - {wxEVT_COMMAND_LEFT_CLICK, 164, "command_left_click"}, - {wxEVT_COMMAND_LEFT_DCLICK, 164, "command_left_dclick"}, - {wxEVT_COMMAND_RIGHT_CLICK, 164, "command_right_click"}, - {wxEVT_COMMAND_SET_FOCUS, 164, "command_set_focus"}, - {wxEVT_COMMAND_KILL_FOCUS, 164, "command_kill_focus"}, - {wxEVT_COMMAND_ENTER, 164, "command_enter"}, - {wxEVT_SCROLL_TOP, 165, "scroll_top"}, - {wxEVT_SCROLL_BOTTOM, 165, "scroll_bottom"}, - {wxEVT_SCROLL_LINEUP, 165, "scroll_lineup"}, - {wxEVT_SCROLL_LINEDOWN, 165, "scroll_linedown"}, - {wxEVT_SCROLL_PAGEUP, 165, "scroll_pageup"}, - {wxEVT_SCROLL_PAGEDOWN, 165, "scroll_pagedown"}, - {wxEVT_SCROLL_THUMBTRACK, 165, "scroll_thumbtrack"}, - {wxEVT_SCROLL_THUMBRELEASE, 165, "scroll_thumbrelease"}, - {wxEVT_SCROLL_CHANGED, 165, "scroll_changed"}, - {wxEVT_SCROLLWIN_TOP, 166, "scrollwin_top"}, - {wxEVT_SCROLLWIN_BOTTOM, 166, "scrollwin_bottom"}, - {wxEVT_SCROLLWIN_LINEUP, 166, "scrollwin_lineup"}, - {wxEVT_SCROLLWIN_LINEDOWN, 166, "scrollwin_linedown"}, - {wxEVT_SCROLLWIN_PAGEUP, 166, "scrollwin_pageup"}, - {wxEVT_SCROLLWIN_PAGEDOWN, 166, "scrollwin_pagedown"}, - {wxEVT_SCROLLWIN_THUMBTRACK, 166, "scrollwin_thumbtrack"}, - {wxEVT_SCROLLWIN_THUMBRELEASE, 166, "scrollwin_thumbrelease"}, - {wxEVT_LEFT_DOWN, 167, "left_down"}, - {wxEVT_LEFT_UP, 167, "left_up"}, - {wxEVT_MIDDLE_DOWN, 167, "middle_down"}, - {wxEVT_MIDDLE_UP, 167, "middle_up"}, - {wxEVT_RIGHT_DOWN, 167, "right_down"}, - {wxEVT_RIGHT_UP, 167, "right_up"}, - {wxEVT_MOTION, 167, "motion"}, - {wxEVT_ENTER_WINDOW, 167, "enter_window"}, - {wxEVT_LEAVE_WINDOW, 167, "leave_window"}, - {wxEVT_LEFT_DCLICK, 167, "left_dclick"}, - {wxEVT_MIDDLE_DCLICK, 167, "middle_dclick"}, - {wxEVT_RIGHT_DCLICK, 167, "right_dclick"}, - {wxEVT_MOUSEWHEEL, 167, "mousewheel"}, - {wxEVT_SET_CURSOR, 168, "set_cursor"}, - {wxEVT_CHAR, 169, "char"}, - {wxEVT_CHAR_HOOK, 169, "char_hook"}, - {wxEVT_KEY_DOWN, 169, "key_down"}, - {wxEVT_KEY_UP, 169, "key_up"}, - {wxEVT_SIZE, 170, "size"}, - {wxEVT_MOVE, 171, "move"}, - {wxEVT_PAINT, 172, "paint"}, - {wxEVT_ERASE_BACKGROUND, 173, "erase_background"}, - {wxEVT_SET_FOCUS, 174, "set_focus"}, - {wxEVT_KILL_FOCUS, 174, "kill_focus"}, - {wxEVT_CHILD_FOCUS, 175, "child_focus"}, - {wxEVT_MENU_OPEN, 176, "menu_open"}, - {wxEVT_MENU_CLOSE, 176, "menu_close"}, - {wxEVT_MENU_HIGHLIGHT, 176, "menu_highlight"}, - {wxEVT_CLOSE_WINDOW, 177, "close_window"}, - {wxEVT_END_SESSION, 177, "end_session"}, - {wxEVT_QUERY_END_SESSION, 177, "query_end_session"}, - {wxEVT_SHOW, 178, "show"}, - {wxEVT_ICONIZE, 179, "iconize"}, - {wxEVT_MAXIMIZE, 180, "maximize"}, - {wxEVT_JOY_BUTTON_DOWN, 181, "joy_button_down"}, - {wxEVT_JOY_BUTTON_UP, 181, "joy_button_up"}, - {wxEVT_JOY_MOVE, 181, "joy_move"}, - {wxEVT_JOY_ZMOVE, 181, "joy_zmove"}, - {wxEVT_UPDATE_UI, 182, "update_ui"}, - {wxEVT_SYS_COLOUR_CHANGED, 183, "sys_colour_changed"}, - {wxEVT_MOUSE_CAPTURE_CHANGED, 184, "mouse_capture_changed"}, - {wxEVT_DISPLAY_CHANGED, 185, "display_changed"}, - {wxEVT_PALETTE_CHANGED, 186, "palette_changed"}, - {wxEVT_QUERY_NEW_PALETTE, 187, "query_new_palette"}, - {wxEVT_NAVIGATION_KEY, 188, "navigation_key"}, - {wxEVT_CREATE, 189, "create"}, - {wxEVT_DESTROY, 190, "destroy"}, - {wxEVT_HELP, 191, "help"}, - {wxEVT_DETAILED_HELP, 191, "detailed_help"}, - {wxEVT_CONTEXT_MENU, 192, "context_menu"}, - {wxEVT_IDLE, 193, "idle"}, - {wxEVT_GRID_CELL_LEFT_CLICK, 194, "grid_cell_left_click"}, - {wxEVT_GRID_CELL_RIGHT_CLICK, 194, "grid_cell_right_click"}, - {wxEVT_GRID_CELL_LEFT_DCLICK, 194, "grid_cell_left_dclick"}, - {wxEVT_GRID_CELL_RIGHT_DCLICK, 194, "grid_cell_right_dclick"}, - {wxEVT_GRID_LABEL_LEFT_CLICK, 194, "grid_label_left_click"}, - {wxEVT_GRID_LABEL_RIGHT_CLICK, 194, "grid_label_right_click"}, - {wxEVT_GRID_LABEL_LEFT_DCLICK, 194, "grid_label_left_dclick"}, - {wxEVT_GRID_LABEL_RIGHT_DCLICK, 194, "grid_label_right_dclick"}, - {wxEVT_GRID_ROW_SIZE, 194, "grid_row_size"}, - {wxEVT_GRID_COL_SIZE, 194, "grid_col_size"}, - {wxEVT_GRID_RANGE_SELECT, 194, "grid_range_select"}, - {wxEVT_GRID_CELL_CHANGE, 194, "grid_cell_change"}, - {wxEVT_GRID_SELECT_CELL, 194, "grid_select_cell"}, - {wxEVT_GRID_EDITOR_SHOWN, 194, "grid_editor_shown"}, - {wxEVT_GRID_EDITOR_HIDDEN, 194, "grid_editor_hidden"}, - {wxEVT_GRID_EDITOR_CREATED, 194, "grid_editor_created"}, - {wxEVT_GRID_CELL_BEGIN_DRAG, 194, "grid_cell_begin_drag"}, - {wxEVT_SASH_DRAGGED, 196, "sash_dragged"}, - {wxEVT_COMMAND_LIST_BEGIN_DRAG, 197, "command_list_begin_drag"}, - {wxEVT_COMMAND_LIST_BEGIN_RDRAG, 197, "command_list_begin_rdrag"}, - {wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, 197, "command_list_begin_label_edit"}, - {wxEVT_COMMAND_LIST_END_LABEL_EDIT, 197, "command_list_end_label_edit"}, - {wxEVT_COMMAND_LIST_DELETE_ITEM, 197, "command_list_delete_item"}, - {wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, 197, "command_list_delete_all_items"}, - {wxEVT_COMMAND_LIST_KEY_DOWN, 197, "command_list_key_down"}, - {wxEVT_COMMAND_LIST_INSERT_ITEM, 197, "command_list_insert_item"}, - {wxEVT_COMMAND_LIST_COL_CLICK, 197, "command_list_col_click"}, - {wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, 197, "command_list_col_right_click"}, - {wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, 197, "command_list_col_begin_drag"}, - {wxEVT_COMMAND_LIST_COL_DRAGGING, 197, "command_list_col_dragging"}, - {wxEVT_COMMAND_LIST_COL_END_DRAG, 197, "command_list_col_end_drag"}, - {wxEVT_COMMAND_LIST_ITEM_SELECTED, 197, "command_list_item_selected"}, - {wxEVT_COMMAND_LIST_ITEM_DESELECTED, 197, "command_list_item_deselected"}, - {wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, 197, "command_list_item_right_click"}, - {wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 197, "command_list_item_middle_click"}, - {wxEVT_COMMAND_LIST_ITEM_ACTIVATED, 197, "command_list_item_activated"}, - {wxEVT_COMMAND_LIST_ITEM_FOCUSED, 197, "command_list_item_focused"}, - {wxEVT_COMMAND_LIST_CACHE_HINT, 197, "command_list_cache_hint"}, - {wxEVT_DATE_CHANGED, 198, "date_changed"}, - {wxEVT_CALENDAR_SEL_CHANGED, 199, "calendar_sel_changed"}, - {wxEVT_CALENDAR_DAY_CHANGED, 199, "calendar_day_changed"}, - {wxEVT_CALENDAR_MONTH_CHANGED, 199, "calendar_month_changed"}, - {wxEVT_CALENDAR_YEAR_CHANGED, 199, "calendar_year_changed"}, - {wxEVT_CALENDAR_DOUBLECLICKED, 199, "calendar_doubleclicked"}, - {wxEVT_CALENDAR_WEEKDAY_CLICKED, 199, "calendar_weekday_clicked"}, - {wxEVT_COMMAND_FILEPICKER_CHANGED, 200, "command_filepicker_changed"}, - {wxEVT_COMMAND_DIRPICKER_CHANGED, 200, "command_dirpicker_changed"}, - {wxEVT_COMMAND_COLOURPICKER_CHANGED, 201, "command_colourpicker_changed"}, - {wxEVT_COMMAND_FONTPICKER_CHANGED, 202, "command_fontpicker_changed"}, - {wxEVT_STC_CHANGE, 203, "stc_change"}, - {wxEVT_STC_STYLENEEDED, 203, "stc_styleneeded"}, - {wxEVT_STC_CHARADDED, 203, "stc_charadded"}, - {wxEVT_STC_SAVEPOINTREACHED, 203, "stc_savepointreached"}, - {wxEVT_STC_SAVEPOINTLEFT, 203, "stc_savepointleft"}, - {wxEVT_STC_ROMODIFYATTEMPT, 203, "stc_romodifyattempt"}, - {wxEVT_STC_KEY, 203, "stc_key"}, - {wxEVT_STC_DOUBLECLICK, 203, "stc_doubleclick"}, - {wxEVT_STC_UPDATEUI, 203, "stc_updateui"}, - {wxEVT_STC_MODIFIED, 203, "stc_modified"}, - {wxEVT_STC_MACRORECORD, 203, "stc_macrorecord"}, - {wxEVT_STC_MARGINCLICK, 203, "stc_marginclick"}, - {wxEVT_STC_NEEDSHOWN, 203, "stc_needshown"}, - {wxEVT_STC_PAINTED, 203, "stc_painted"}, - {wxEVT_STC_USERLISTSELECTION, 203, "stc_userlistselection"}, - {wxEVT_STC_URIDROPPED, 203, "stc_uridropped"}, - {wxEVT_STC_DWELLSTART, 203, "stc_dwellstart"}, - {wxEVT_STC_DWELLEND, 203, "stc_dwellend"}, - {wxEVT_STC_START_DRAG, 203, "stc_start_drag"}, - {wxEVT_STC_DRAG_OVER, 203, "stc_drag_over"}, - {wxEVT_STC_DO_DROP, 203, "stc_do_drop"}, - {wxEVT_STC_ZOOM, 203, "stc_zoom"}, - {wxEVT_STC_HOTSPOT_CLICK, 203, "stc_hotspot_click"}, - {wxEVT_STC_HOTSPOT_DCLICK, 203, "stc_hotspot_dclick"}, - {wxEVT_STC_CALLTIP_CLICK, 203, "stc_calltip_click"}, - {wxEVT_STC_AUTOCOMP_SELECTION, 203, "stc_autocomp_selection"}, - {wxEVT_COMMAND_TREE_BEGIN_DRAG, 209, "command_tree_begin_drag"}, - {wxEVT_COMMAND_TREE_BEGIN_RDRAG, 209, "command_tree_begin_rdrag"}, - {wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, 209, "command_tree_begin_label_edit"}, - {wxEVT_COMMAND_TREE_END_LABEL_EDIT, 209, "command_tree_end_label_edit"}, - {wxEVT_COMMAND_TREE_DELETE_ITEM, 209, "command_tree_delete_item"}, - {wxEVT_COMMAND_TREE_GET_INFO, 209, "command_tree_get_info"}, - {wxEVT_COMMAND_TREE_SET_INFO, 209, "command_tree_set_info"}, - {wxEVT_COMMAND_TREE_ITEM_EXPANDED, 209, "command_tree_item_expanded"}, - {wxEVT_COMMAND_TREE_ITEM_EXPANDING, 209, "command_tree_item_expanding"}, - {wxEVT_COMMAND_TREE_ITEM_COLLAPSED, 209, "command_tree_item_collapsed"}, - {wxEVT_COMMAND_TREE_ITEM_COLLAPSING, 209, "command_tree_item_collapsing"}, - {wxEVT_COMMAND_TREE_SEL_CHANGED, 209, "command_tree_sel_changed"}, - {wxEVT_COMMAND_TREE_SEL_CHANGING, 209, "command_tree_sel_changing"}, - {wxEVT_COMMAND_TREE_KEY_DOWN, 209, "command_tree_key_down"}, - {wxEVT_COMMAND_TREE_ITEM_ACTIVATED, 209, "command_tree_item_activated"}, - {wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, 209, "command_tree_item_right_click"}, - {wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 209, "command_tree_item_middle_click"}, - {wxEVT_COMMAND_TREE_END_DRAG, 209, "command_tree_end_drag"}, - {wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 209, "command_tree_state_image_click"}, - {wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 209, "command_tree_item_gettooltip"}, - {wxEVT_COMMAND_TREE_ITEM_MENU, 209, "command_tree_item_menu"}, - {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 210, "command_notebook_page_changed"}, - {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 210, "command_notebook_page_changing"}, - {wxEVT_COMMAND_TEXT_COPY, 216, "command_text_copy"}, - {wxEVT_COMMAND_TEXT_CUT, 216, "command_text_cut"}, - {wxEVT_COMMAND_TEXT_PASTE, 216, "command_text_paste"}, - {wxEVT_COMMAND_SPINCTRL_UPDATED, 217, "command_spinctrl_updated"}, - {wxEVT_SCROLL_LINEUP + wxEVT_USER_FIRST, 165, "spin_up"}, - {wxEVT_SCROLL_LINEDOWN + wxEVT_USER_FIRST, 165, "spin_down"}, - {wxEVT_SCROLL_THUMBTRACK + wxEVT_USER_FIRST, 165, "spin"}, - {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 219, "command_splitter_sash_pos_changed"}, - {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 219, "command_splitter_sash_pos_changing"}, - {wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 219, "command_splitter_doubleclicked"}, - {wxEVT_COMMAND_SPLITTER_UNSPLIT, 219, "command_splitter_unsplit"}, - {wxEVT_COMMAND_HTML_LINK_CLICKED, 221, "command_html_link_clicked"}, - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 224, "command_auinotebook_page_close"}, - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 224, "command_auinotebook_page_changed"}, - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 224, "command_auinotebook_page_changing"}, - {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 224, "command_auinotebook_button"}, - {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 224, "command_auinotebook_begin_drag"}, - {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 224, "command_auinotebook_end_drag"}, - {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 224, "command_auinotebook_drag_motion"}, - {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 224, "command_auinotebook_allow_dnd"}, + {wxEVT_COMMAND_BUTTON_CLICKED, 165, "command_button_clicked"}, + {wxEVT_COMMAND_CHECKBOX_CLICKED, 165, "command_checkbox_clicked"}, + {wxEVT_COMMAND_CHOICE_SELECTED, 165, "command_choice_selected"}, + {wxEVT_COMMAND_LISTBOX_SELECTED, 165, "command_listbox_selected"}, + {wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 165, "command_listbox_doubleclicked"}, + {wxEVT_COMMAND_TEXT_UPDATED, 165, "command_text_updated"}, + {wxEVT_COMMAND_TEXT_ENTER, 165, "command_text_enter"}, + {wxEVT_COMMAND_MENU_SELECTED, 165, "command_menu_selected"}, + {wxEVT_COMMAND_SLIDER_UPDATED, 165, "command_slider_updated"}, + {wxEVT_COMMAND_RADIOBOX_SELECTED, 165, "command_radiobox_selected"}, + {wxEVT_COMMAND_RADIOBUTTON_SELECTED, 165, "command_radiobutton_selected"}, + {wxEVT_COMMAND_SCROLLBAR_UPDATED, 165, "command_scrollbar_updated"}, + {wxEVT_COMMAND_VLBOX_SELECTED, 165, "command_vlbox_selected"}, + {wxEVT_COMMAND_COMBOBOX_SELECTED, 165, "command_combobox_selected"}, + {wxEVT_COMMAND_TOOL_RCLICKED, 165, "command_tool_rclicked"}, + {wxEVT_COMMAND_TOOL_ENTER, 165, "command_tool_enter"}, + {wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 165, "command_checklistbox_toggled"}, + {wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 165, "command_togglebutton_clicked"}, + {wxEVT_COMMAND_LEFT_CLICK, 165, "command_left_click"}, + {wxEVT_COMMAND_LEFT_DCLICK, 165, "command_left_dclick"}, + {wxEVT_COMMAND_RIGHT_CLICK, 165, "command_right_click"}, + {wxEVT_COMMAND_SET_FOCUS, 165, "command_set_focus"}, + {wxEVT_COMMAND_KILL_FOCUS, 165, "command_kill_focus"}, + {wxEVT_COMMAND_ENTER, 165, "command_enter"}, + {wxEVT_SCROLL_TOP, 166, "scroll_top"}, + {wxEVT_SCROLL_BOTTOM, 166, "scroll_bottom"}, + {wxEVT_SCROLL_LINEUP, 166, "scroll_lineup"}, + {wxEVT_SCROLL_LINEDOWN, 166, "scroll_linedown"}, + {wxEVT_SCROLL_PAGEUP, 166, "scroll_pageup"}, + {wxEVT_SCROLL_PAGEDOWN, 166, "scroll_pagedown"}, + {wxEVT_SCROLL_THUMBTRACK, 166, "scroll_thumbtrack"}, + {wxEVT_SCROLL_THUMBRELEASE, 166, "scroll_thumbrelease"}, + {wxEVT_SCROLL_CHANGED, 166, "scroll_changed"}, + {wxEVT_SCROLLWIN_TOP, 167, "scrollwin_top"}, + {wxEVT_SCROLLWIN_BOTTOM, 167, "scrollwin_bottom"}, + {wxEVT_SCROLLWIN_LINEUP, 167, "scrollwin_lineup"}, + {wxEVT_SCROLLWIN_LINEDOWN, 167, "scrollwin_linedown"}, + {wxEVT_SCROLLWIN_PAGEUP, 167, "scrollwin_pageup"}, + {wxEVT_SCROLLWIN_PAGEDOWN, 167, "scrollwin_pagedown"}, + {wxEVT_SCROLLWIN_THUMBTRACK, 167, "scrollwin_thumbtrack"}, + {wxEVT_SCROLLWIN_THUMBRELEASE, 167, "scrollwin_thumbrelease"}, + {wxEVT_LEFT_DOWN, 168, "left_down"}, + {wxEVT_LEFT_UP, 168, "left_up"}, + {wxEVT_MIDDLE_DOWN, 168, "middle_down"}, + {wxEVT_MIDDLE_UP, 168, "middle_up"}, + {wxEVT_RIGHT_DOWN, 168, "right_down"}, + {wxEVT_RIGHT_UP, 168, "right_up"}, + {wxEVT_MOTION, 168, "motion"}, + {wxEVT_ENTER_WINDOW, 168, "enter_window"}, + {wxEVT_LEAVE_WINDOW, 168, "leave_window"}, + {wxEVT_LEFT_DCLICK, 168, "left_dclick"}, + {wxEVT_MIDDLE_DCLICK, 168, "middle_dclick"}, + {wxEVT_RIGHT_DCLICK, 168, "right_dclick"}, + {wxEVT_MOUSEWHEEL, 168, "mousewheel"}, + {wxEVT_SET_CURSOR, 169, "set_cursor"}, + {wxEVT_CHAR, 170, "char"}, + {wxEVT_CHAR_HOOK, 170, "char_hook"}, + {wxEVT_KEY_DOWN, 170, "key_down"}, + {wxEVT_KEY_UP, 170, "key_up"}, + {wxEVT_SIZE, 171, "size"}, + {wxEVT_MOVE, 172, "move"}, + {wxEVT_PAINT, 173, "paint"}, + {wxEVT_ERASE_BACKGROUND, 174, "erase_background"}, + {wxEVT_SET_FOCUS, 175, "set_focus"}, + {wxEVT_KILL_FOCUS, 175, "kill_focus"}, + {wxEVT_CHILD_FOCUS, 176, "child_focus"}, + {wxEVT_MENU_OPEN, 177, "menu_open"}, + {wxEVT_MENU_CLOSE, 177, "menu_close"}, + {wxEVT_MENU_HIGHLIGHT, 177, "menu_highlight"}, + {wxEVT_CLOSE_WINDOW, 178, "close_window"}, + {wxEVT_END_SESSION, 178, "end_session"}, + {wxEVT_QUERY_END_SESSION, 178, "query_end_session"}, + {wxEVT_SHOW, 179, "show"}, + {wxEVT_ICONIZE, 180, "iconize"}, + {wxEVT_MAXIMIZE, 181, "maximize"}, + {wxEVT_JOY_BUTTON_DOWN, 182, "joy_button_down"}, + {wxEVT_JOY_BUTTON_UP, 182, "joy_button_up"}, + {wxEVT_JOY_MOVE, 182, "joy_move"}, + {wxEVT_JOY_ZMOVE, 182, "joy_zmove"}, + {wxEVT_UPDATE_UI, 183, "update_ui"}, + {wxEVT_SYS_COLOUR_CHANGED, 184, "sys_colour_changed"}, + {wxEVT_MOUSE_CAPTURE_CHANGED, 185, "mouse_capture_changed"}, + {wxEVT_DISPLAY_CHANGED, 186, "display_changed"}, + {wxEVT_PALETTE_CHANGED, 187, "palette_changed"}, + {wxEVT_QUERY_NEW_PALETTE, 188, "query_new_palette"}, + {wxEVT_NAVIGATION_KEY, 189, "navigation_key"}, + {wxEVT_CREATE, 190, "create"}, + {wxEVT_DESTROY, 191, "destroy"}, + {wxEVT_HELP, 192, "help"}, + {wxEVT_DETAILED_HELP, 192, "detailed_help"}, + {wxEVT_CONTEXT_MENU, 193, "context_menu"}, + {wxEVT_IDLE, 194, "idle"}, + {wxEVT_GRID_CELL_LEFT_CLICK, 195, "grid_cell_left_click"}, + {wxEVT_GRID_CELL_RIGHT_CLICK, 195, "grid_cell_right_click"}, + {wxEVT_GRID_CELL_LEFT_DCLICK, 195, "grid_cell_left_dclick"}, + {wxEVT_GRID_CELL_RIGHT_DCLICK, 195, "grid_cell_right_dclick"}, + {wxEVT_GRID_LABEL_LEFT_CLICK, 195, "grid_label_left_click"}, + {wxEVT_GRID_LABEL_RIGHT_CLICK, 195, "grid_label_right_click"}, + {wxEVT_GRID_LABEL_LEFT_DCLICK, 195, "grid_label_left_dclick"}, + {wxEVT_GRID_LABEL_RIGHT_DCLICK, 195, "grid_label_right_dclick"}, + {wxEVT_GRID_ROW_SIZE, 195, "grid_row_size"}, + {wxEVT_GRID_COL_SIZE, 195, "grid_col_size"}, + {wxEVT_GRID_RANGE_SELECT, 195, "grid_range_select"}, + {wxEVT_GRID_CELL_CHANGE, 195, "grid_cell_change"}, + {wxEVT_GRID_SELECT_CELL, 195, "grid_select_cell"}, + {wxEVT_GRID_EDITOR_SHOWN, 195, "grid_editor_shown"}, + {wxEVT_GRID_EDITOR_HIDDEN, 195, "grid_editor_hidden"}, + {wxEVT_GRID_EDITOR_CREATED, 195, "grid_editor_created"}, + {wxEVT_GRID_CELL_BEGIN_DRAG, 195, "grid_cell_begin_drag"}, + {wxEVT_SASH_DRAGGED, 197, "sash_dragged"}, + {wxEVT_COMMAND_LIST_BEGIN_DRAG, 198, "command_list_begin_drag"}, + {wxEVT_COMMAND_LIST_BEGIN_RDRAG, 198, "command_list_begin_rdrag"}, + {wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, 198, "command_list_begin_label_edit"}, + {wxEVT_COMMAND_LIST_END_LABEL_EDIT, 198, "command_list_end_label_edit"}, + {wxEVT_COMMAND_LIST_DELETE_ITEM, 198, "command_list_delete_item"}, + {wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, 198, "command_list_delete_all_items"}, + {wxEVT_COMMAND_LIST_KEY_DOWN, 198, "command_list_key_down"}, + {wxEVT_COMMAND_LIST_INSERT_ITEM, 198, "command_list_insert_item"}, + {wxEVT_COMMAND_LIST_COL_CLICK, 198, "command_list_col_click"}, + {wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, 198, "command_list_col_right_click"}, + {wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, 198, "command_list_col_begin_drag"}, + {wxEVT_COMMAND_LIST_COL_DRAGGING, 198, "command_list_col_dragging"}, + {wxEVT_COMMAND_LIST_COL_END_DRAG, 198, "command_list_col_end_drag"}, + {wxEVT_COMMAND_LIST_ITEM_SELECTED, 198, "command_list_item_selected"}, + {wxEVT_COMMAND_LIST_ITEM_DESELECTED, 198, "command_list_item_deselected"}, + {wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, 198, "command_list_item_right_click"}, + {wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 198, "command_list_item_middle_click"}, + {wxEVT_COMMAND_LIST_ITEM_ACTIVATED, 198, "command_list_item_activated"}, + {wxEVT_COMMAND_LIST_ITEM_FOCUSED, 198, "command_list_item_focused"}, + {wxEVT_COMMAND_LIST_CACHE_HINT, 198, "command_list_cache_hint"}, + {wxEVT_DATE_CHANGED, 199, "date_changed"}, + {wxEVT_CALENDAR_SEL_CHANGED, 200, "calendar_sel_changed"}, + {wxEVT_CALENDAR_DAY_CHANGED, 200, "calendar_day_changed"}, + {wxEVT_CALENDAR_MONTH_CHANGED, 200, "calendar_month_changed"}, + {wxEVT_CALENDAR_YEAR_CHANGED, 200, "calendar_year_changed"}, + {wxEVT_CALENDAR_DOUBLECLICKED, 200, "calendar_doubleclicked"}, + {wxEVT_CALENDAR_WEEKDAY_CLICKED, 200, "calendar_weekday_clicked"}, + {wxEVT_COMMAND_FILEPICKER_CHANGED, 201, "command_filepicker_changed"}, + {wxEVT_COMMAND_DIRPICKER_CHANGED, 201, "command_dirpicker_changed"}, + {wxEVT_COMMAND_COLOURPICKER_CHANGED, 202, "command_colourpicker_changed"}, + {wxEVT_COMMAND_FONTPICKER_CHANGED, 203, "command_fontpicker_changed"}, + {wxEVT_STC_CHANGE, 204, "stc_change"}, + {wxEVT_STC_STYLENEEDED, 204, "stc_styleneeded"}, + {wxEVT_STC_CHARADDED, 204, "stc_charadded"}, + {wxEVT_STC_SAVEPOINTREACHED, 204, "stc_savepointreached"}, + {wxEVT_STC_SAVEPOINTLEFT, 204, "stc_savepointleft"}, + {wxEVT_STC_ROMODIFYATTEMPT, 204, "stc_romodifyattempt"}, + {wxEVT_STC_KEY, 204, "stc_key"}, + {wxEVT_STC_DOUBLECLICK, 204, "stc_doubleclick"}, + {wxEVT_STC_UPDATEUI, 204, "stc_updateui"}, + {wxEVT_STC_MODIFIED, 204, "stc_modified"}, + {wxEVT_STC_MACRORECORD, 204, "stc_macrorecord"}, + {wxEVT_STC_MARGINCLICK, 204, "stc_marginclick"}, + {wxEVT_STC_NEEDSHOWN, 204, "stc_needshown"}, + {wxEVT_STC_PAINTED, 204, "stc_painted"}, + {wxEVT_STC_USERLISTSELECTION, 204, "stc_userlistselection"}, + {wxEVT_STC_URIDROPPED, 204, "stc_uridropped"}, + {wxEVT_STC_DWELLSTART, 204, "stc_dwellstart"}, + {wxEVT_STC_DWELLEND, 204, "stc_dwellend"}, + {wxEVT_STC_START_DRAG, 204, "stc_start_drag"}, + {wxEVT_STC_DRAG_OVER, 204, "stc_drag_over"}, + {wxEVT_STC_DO_DROP, 204, "stc_do_drop"}, + {wxEVT_STC_ZOOM, 204, "stc_zoom"}, + {wxEVT_STC_HOTSPOT_CLICK, 204, "stc_hotspot_click"}, + {wxEVT_STC_HOTSPOT_DCLICK, 204, "stc_hotspot_dclick"}, + {wxEVT_STC_CALLTIP_CLICK, 204, "stc_calltip_click"}, + {wxEVT_STC_AUTOCOMP_SELECTION, 204, "stc_autocomp_selection"}, + {wxEVT_COMMAND_TREE_BEGIN_DRAG, 210, "command_tree_begin_drag"}, + {wxEVT_COMMAND_TREE_BEGIN_RDRAG, 210, "command_tree_begin_rdrag"}, + {wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, 210, "command_tree_begin_label_edit"}, + {wxEVT_COMMAND_TREE_END_LABEL_EDIT, 210, "command_tree_end_label_edit"}, + {wxEVT_COMMAND_TREE_DELETE_ITEM, 210, "command_tree_delete_item"}, + {wxEVT_COMMAND_TREE_GET_INFO, 210, "command_tree_get_info"}, + {wxEVT_COMMAND_TREE_SET_INFO, 210, "command_tree_set_info"}, + {wxEVT_COMMAND_TREE_ITEM_EXPANDED, 210, "command_tree_item_expanded"}, + {wxEVT_COMMAND_TREE_ITEM_EXPANDING, 210, "command_tree_item_expanding"}, + {wxEVT_COMMAND_TREE_ITEM_COLLAPSED, 210, "command_tree_item_collapsed"}, + {wxEVT_COMMAND_TREE_ITEM_COLLAPSING, 210, "command_tree_item_collapsing"}, + {wxEVT_COMMAND_TREE_SEL_CHANGED, 210, "command_tree_sel_changed"}, + {wxEVT_COMMAND_TREE_SEL_CHANGING, 210, "command_tree_sel_changing"}, + {wxEVT_COMMAND_TREE_KEY_DOWN, 210, "command_tree_key_down"}, + {wxEVT_COMMAND_TREE_ITEM_ACTIVATED, 210, "command_tree_item_activated"}, + {wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, 210, "command_tree_item_right_click"}, + {wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 210, "command_tree_item_middle_click"}, + {wxEVT_COMMAND_TREE_END_DRAG, 210, "command_tree_end_drag"}, + {wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 210, "command_tree_state_image_click"}, + {wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 210, "command_tree_item_gettooltip"}, + {wxEVT_COMMAND_TREE_ITEM_MENU, 210, "command_tree_item_menu"}, + {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 211, "command_notebook_page_changed"}, + {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 211, "command_notebook_page_changing"}, + {wxEVT_COMMAND_TEXT_COPY, 217, "command_text_copy"}, + {wxEVT_COMMAND_TEXT_CUT, 217, "command_text_cut"}, + {wxEVT_COMMAND_TEXT_PASTE, 217, "command_text_paste"}, + {wxEVT_COMMAND_SPINCTRL_UPDATED, 218, "command_spinctrl_updated"}, + {wxEVT_SCROLL_LINEUP + wxEVT_USER_FIRST, 166, "spin_up"}, + {wxEVT_SCROLL_LINEDOWN + wxEVT_USER_FIRST, 166, "spin_down"}, + {wxEVT_SCROLL_THUMBTRACK + wxEVT_USER_FIRST, 166, "spin"}, + {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 220, "command_splitter_sash_pos_changed"}, + {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 220, "command_splitter_sash_pos_changing"}, + {wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 220, "command_splitter_doubleclicked"}, + {wxEVT_COMMAND_SPLITTER_UNSPLIT, 220, "command_splitter_unsplit"}, + {wxEVT_COMMAND_HTML_LINK_CLICKED, 222, "command_html_link_clicked"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 225, "command_auinotebook_page_close"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 225, "command_auinotebook_page_changed"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 225, "command_auinotebook_page_changing"}, + {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 225, "command_auinotebook_button"}, + {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 225, "command_auinotebook_begin_drag"}, + {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 225, "command_auinotebook_end_drag"}, + {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 225, "command_auinotebook_drag_motion"}, + {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 225, "command_auinotebook_allow_dnd"}, #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 224, "command_auinotebook_tab_middle_down"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 225, "command_auinotebook_tab_middle_down"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 224, "command_auinotebook_tab_middle_up"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 225, "command_auinotebook_tab_middle_up"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 224, "command_auinotebook_tab_right_down"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 225, "command_auinotebook_tab_right_down"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 224, "command_auinotebook_tab_right_up"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 225, "command_auinotebook_tab_right_up"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 224, "command_auinotebook_page_closed"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 225, "command_auinotebook_page_closed"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 224, "command_auinotebook_drag_done"}, + {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 225, "command_auinotebook_drag_done"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 224, "command_auinotebook_bg_dclick"}, + {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 225, "command_auinotebook_bg_dclick"}, #endif - {wxEVT_AUI_PANE_BUTTON, 225, "aui_pane_button"}, - {wxEVT_AUI_PANE_CLOSE, 225, "aui_pane_close"}, - {wxEVT_AUI_PANE_MAXIMIZE, 225, "aui_pane_maximize"}, - {wxEVT_AUI_PANE_RESTORE, 225, "aui_pane_restore"}, - {wxEVT_AUI_RENDER, 225, "aui_render"}, - {wxEVT_AUI_FIND_MANAGER, 225, "aui_find_manager"}, - {wxEVT_TASKBAR_MOVE, 228, "taskbar_move"}, - {wxEVT_TASKBAR_LEFT_DOWN, 228, "taskbar_left_down"}, - {wxEVT_TASKBAR_LEFT_UP, 228, "taskbar_left_up"}, - {wxEVT_TASKBAR_RIGHT_DOWN, 228, "taskbar_right_down"}, - {wxEVT_TASKBAR_RIGHT_UP, 228, "taskbar_right_up"}, - {wxEVT_TASKBAR_LEFT_DCLICK, 228, "taskbar_left_dclick"}, - {wxEVT_TASKBAR_RIGHT_DCLICK, 228, "taskbar_right_dclick"}, - {wxEVT_INIT_DIALOG, 229, "init_dialog"}, - {wxEVT_ACTIVATE, 231, "activate"}, - {wxEVT_ACTIVATE_APP, 231, "activate_app"}, - {wxEVT_HIBERNATE, 231, "hibernate"}, - {wxEVT_MOUSE_CAPTURE_LOST, 234, "mouse_capture_lost"}, + {wxEVT_AUI_PANE_BUTTON, 226, "aui_pane_button"}, + {wxEVT_AUI_PANE_CLOSE, 226, "aui_pane_close"}, + {wxEVT_AUI_PANE_MAXIMIZE, 226, "aui_pane_maximize"}, + {wxEVT_AUI_PANE_RESTORE, 226, "aui_pane_restore"}, +#if wxCHECK_VERSION(2,9,5) + {wxEVT_AUI_PANE_ACTIVATED, 226, "aui_pane_activated"}, +#endif + {wxEVT_AUI_RENDER, 226, "aui_render"}, + {wxEVT_AUI_FIND_MANAGER, 226, "aui_find_manager"}, + {wxEVT_TASKBAR_MOVE, 229, "taskbar_move"}, + {wxEVT_TASKBAR_LEFT_DOWN, 229, "taskbar_left_down"}, + {wxEVT_TASKBAR_LEFT_UP, 229, "taskbar_left_up"}, + {wxEVT_TASKBAR_RIGHT_DOWN, 229, "taskbar_right_down"}, + {wxEVT_TASKBAR_RIGHT_UP, 229, "taskbar_right_up"}, + {wxEVT_TASKBAR_LEFT_DCLICK, 229, "taskbar_left_dclick"}, + {wxEVT_TASKBAR_RIGHT_DCLICK, 229, "taskbar_right_dclick"}, + {wxEVT_INIT_DIALOG, 230, "init_dialog"}, + {wxEVT_ACTIVATE, 232, "activate"}, + {wxEVT_ACTIVATE_APP, 232, "activate_app"}, + {wxEVT_HIBERNATE, 232, "hibernate"}, + {wxEVT_MOUSE_CAPTURE_LOST, 235, "mouse_capture_lost"}, {-1, 0, } }; for(int i=0; event_types[i].ev_type != -1; i++) { @@ -345,7 +348,7 @@ bool sendevent(wxEvent *event, ErlDrvTermData port) rt.addRef(cb->obj, cb->class_name); rt.addExt2Term(cb->user_data); switch(Etype->cID) { -case 164: {// wxCommandEvent +case 165: {// wxCommandEvent wxCommandEvent * ev = (wxCommandEvent *) event; evClass = (char*)"wxCommandEvent"; rt.addAtom((char*)"wxCommand"); @@ -356,7 +359,7 @@ case 164: {// wxCommandEvent rt.addTupleCount(5); break; } -case 165: {// wxScrollEvent or wxSpinEvent +case 166: {// wxScrollEvent or wxSpinEvent if(event->IsKindOf(CLASSINFO(wxScrollEvent))) { wxScrollEvent * ev = (wxScrollEvent *) event; evClass = (char*)"wxScrollEvent"; @@ -376,7 +379,7 @@ case 165: {// wxScrollEvent or wxSpinEvent } break; } -case 166: {// wxScrollWinEvent +case 167: {// wxScrollWinEvent wxScrollWinEvent * ev = (wxScrollWinEvent *) event; evClass = (char*)"wxScrollWinEvent"; rt.addAtom((char*)"wxScrollWin"); @@ -386,7 +389,7 @@ case 166: {// wxScrollWinEvent rt.addTupleCount(4); break; } -case 167: {// wxMouseEvent +case 168: {// wxMouseEvent wxMouseEvent * ev = (wxMouseEvent *) event; evClass = (char*)"wxMouseEvent"; rt.addAtom((char*)"wxMouse"); @@ -410,7 +413,7 @@ case 167: {// wxMouseEvent rt.addTupleCount(14); break; } -case 168: {// wxSetCursorEvent +case 169: {// wxSetCursorEvent wxSetCursorEvent * ev = (wxSetCursorEvent *) event; wxCursor * GetCursor = new wxCursor(ev->GetCursor()); app->newPtr((void *) GetCursor,3, memenv); @@ -423,7 +426,7 @@ case 168: {// wxSetCursorEvent rt.addTupleCount(5); break; } -case 169: {// wxKeyEvent +case 170: {// wxKeyEvent wxKeyEvent * ev = (wxKeyEvent *) event; evClass = (char*)"wxKeyEvent"; rt.addAtom((char*)"wxKey"); @@ -450,7 +453,7 @@ case 169: {// wxKeyEvent rt.addTupleCount(13); break; } -case 170: {// wxSizeEvent +case 171: {// wxSizeEvent wxSizeEvent * ev = (wxSizeEvent *) event; evClass = (char*)"wxSizeEvent"; rt.addAtom((char*)"wxSize"); @@ -460,7 +463,7 @@ case 170: {// wxSizeEvent rt.addTupleCount(4); break; } -case 171: {// wxMoveEvent +case 172: {// wxMoveEvent wxMoveEvent * ev = (wxMoveEvent *) event; evClass = (char*)"wxMoveEvent"; rt.addAtom((char*)"wxMove"); @@ -470,14 +473,14 @@ case 171: {// wxMoveEvent rt.addTupleCount(4); break; } -case 172: {// wxPaintEvent +case 173: {// wxPaintEvent evClass = (char*)"wxPaintEvent"; rt.addAtom((char*)"wxPaint"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 173: {// wxEraseEvent +case 174: {// wxEraseEvent wxEraseEvent * ev = (wxEraseEvent *) event; wxDC * GetDC = ev->GetDC(); evClass = (char*)"wxEraseEvent"; @@ -487,7 +490,7 @@ case 173: {// wxEraseEvent rt.addTupleCount(3); break; } -case 174: {// wxFocusEvent +case 175: {// wxFocusEvent wxFocusEvent * ev = (wxFocusEvent *) event; wxWindow * GetWindow = ev->GetWindow(); evClass = (char*)"wxFocusEvent"; @@ -497,14 +500,14 @@ case 174: {// wxFocusEvent rt.addTupleCount(3); break; } -case 175: {// wxChildFocusEvent +case 176: {// wxChildFocusEvent evClass = (char*)"wxChildFocusEvent"; rt.addAtom((char*)"wxChildFocus"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 176: {// wxMenuEvent +case 177: {// wxMenuEvent wxMenuEvent * ev = (wxMenuEvent *) event; wxMenu * GetMenu = ev->GetMenu(); evClass = (char*)"wxMenuEvent"; @@ -515,14 +518,14 @@ case 176: {// wxMenuEvent rt.addTupleCount(4); break; } -case 177: {// wxCloseEvent +case 178: {// wxCloseEvent evClass = (char*)"wxCloseEvent"; rt.addAtom((char*)"wxClose"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 178: {// wxShowEvent +case 179: {// wxShowEvent wxShowEvent * ev = (wxShowEvent *) event; evClass = (char*)"wxShowEvent"; rt.addAtom((char*)"wxShow"); @@ -531,7 +534,7 @@ case 178: {// wxShowEvent rt.addTupleCount(3); break; } -case 179: {// wxIconizeEvent +case 180: {// wxIconizeEvent wxIconizeEvent * ev = (wxIconizeEvent *) event; evClass = (char*)"wxIconizeEvent"; rt.addAtom((char*)"wxIconize"); @@ -540,14 +543,14 @@ case 179: {// wxIconizeEvent rt.addTupleCount(3); break; } -case 180: {// wxMaximizeEvent +case 181: {// wxMaximizeEvent evClass = (char*)"wxMaximizeEvent"; rt.addAtom((char*)"wxMaximize"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 181: {// wxJoystickEvent +case 182: {// wxJoystickEvent wxJoystickEvent * ev = (wxJoystickEvent *) event; evClass = (char*)"wxJoystickEvent"; rt.addAtom((char*)"wxJoystick"); @@ -560,49 +563,49 @@ case 181: {// wxJoystickEvent rt.addTupleCount(7); break; } -case 182: {// wxUpdateUIEvent +case 183: {// wxUpdateUIEvent evClass = (char*)"wxUpdateUIEvent"; rt.addAtom((char*)"wxUpdateUI"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 183: {// wxSysColourChangedEvent +case 184: {// wxSysColourChangedEvent evClass = (char*)"wxSysColourChangedEvent"; rt.addAtom((char*)"wxSysColourChanged"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 184: {// wxMouseCaptureChangedEvent +case 185: {// wxMouseCaptureChangedEvent evClass = (char*)"wxMouseCaptureChangedEvent"; rt.addAtom((char*)"wxMouseCaptureChanged"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 185: {// wxDisplayChangedEvent +case 186: {// wxDisplayChangedEvent evClass = (char*)"wxDisplayChangedEvent"; rt.addAtom((char*)"wxDisplayChanged"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 186: {// wxPaletteChangedEvent +case 187: {// wxPaletteChangedEvent evClass = (char*)"wxPaletteChangedEvent"; rt.addAtom((char*)"wxPaletteChanged"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 187: {// wxQueryNewPaletteEvent +case 188: {// wxQueryNewPaletteEvent evClass = (char*)"wxQueryNewPaletteEvent"; rt.addAtom((char*)"wxQueryNewPalette"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 188: {// wxNavigationKeyEvent +case 189: {// wxNavigationKeyEvent wxNavigationKeyEvent * ev = (wxNavigationKeyEvent *) event; evClass = (char*)"wxNavigationKeyEvent"; rt.addAtom((char*)"wxNavigationKey"); @@ -612,28 +615,28 @@ case 188: {// wxNavigationKeyEvent rt.addTupleCount(4); break; } -case 189: {// wxWindowCreateEvent +case 190: {// wxWindowCreateEvent evClass = (char*)"wxWindowCreateEvent"; rt.addAtom((char*)"wxWindowCreate"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 190: {// wxWindowDestroyEvent +case 191: {// wxWindowDestroyEvent evClass = (char*)"wxWindowDestroyEvent"; rt.addAtom((char*)"wxWindowDestroy"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 191: {// wxHelpEvent +case 192: {// wxHelpEvent evClass = (char*)"wxHelpEvent"; rt.addAtom((char*)"wxHelp"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 192: {// wxContextMenuEvent +case 193: {// wxContextMenuEvent wxContextMenuEvent * ev = (wxContextMenuEvent *) event; evClass = (char*)"wxContextMenuEvent"; rt.addAtom((char*)"wxContextMenu"); @@ -642,14 +645,14 @@ case 192: {// wxContextMenuEvent rt.addTupleCount(3); break; } -case 193: {// wxIdleEvent +case 194: {// wxIdleEvent evClass = (char*)"wxIdleEvent"; rt.addAtom((char*)"wxIdle"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 194: {// wxGridEvent +case 195: {// wxGridEvent wxGridEvent * ev = (wxGridEvent *) event; evClass = (char*)"wxGridEvent"; rt.addAtom((char*)"wxGrid"); @@ -666,7 +669,7 @@ case 194: {// wxGridEvent rt.addTupleCount(11); break; } -case 196: {// wxSashEvent +case 197: {// wxSashEvent wxSashEvent * ev = (wxSashEvent *) event; evClass = (char*)"wxSashEvent"; rt.addAtom((char*)"wxSash"); @@ -677,7 +680,7 @@ case 196: {// wxSashEvent rt.addTupleCount(5); break; } -case 197: {// wxListEvent +case 198: {// wxListEvent wxListEvent * ev = (wxListEvent *) event; evClass = (char*)"wxListEvent"; rt.addAtom((char*)"wxList"); @@ -690,7 +693,7 @@ case 197: {// wxListEvent rt.addTupleCount(7); break; } -case 198: {// wxDateEvent +case 199: {// wxDateEvent wxDateEvent * ev = (wxDateEvent *) event; evClass = (char*)"wxDateEvent"; rt.addAtom((char*)"wxDate"); @@ -699,7 +702,7 @@ case 198: {// wxDateEvent rt.addTupleCount(3); break; } -case 199: {// wxCalendarEvent +case 200: {// wxCalendarEvent wxCalendarEvent * ev = (wxCalendarEvent *) event; evClass = (char*)"wxCalendarEvent"; rt.addAtom((char*)"wxCalendar"); @@ -709,7 +712,7 @@ case 199: {// wxCalendarEvent rt.addTupleCount(4); break; } -case 200: {// wxFileDirPickerEvent +case 201: {// wxFileDirPickerEvent wxFileDirPickerEvent * ev = (wxFileDirPickerEvent *) event; evClass = (char*)"wxFileDirPickerEvent"; rt.addAtom((char*)"wxFileDirPicker"); @@ -718,7 +721,7 @@ case 200: {// wxFileDirPickerEvent rt.addTupleCount(3); break; } -case 201: {// wxColourPickerEvent +case 202: {// wxColourPickerEvent wxColourPickerEvent * ev = (wxColourPickerEvent *) event; evClass = (char*)"wxColourPickerEvent"; rt.addAtom((char*)"wxColourPicker"); @@ -727,7 +730,7 @@ case 201: {// wxColourPickerEvent rt.addTupleCount(3); break; } -case 202: {// wxFontPickerEvent +case 203: {// wxFontPickerEvent wxFontPickerEvent * ev = (wxFontPickerEvent *) event; wxFont * GetFont = new wxFont(ev->GetFont()); app->newPtr((void *) GetFont,3, memenv); @@ -738,7 +741,7 @@ case 202: {// wxFontPickerEvent rt.addTupleCount(3); break; } -case 203: {// wxStyledTextEvent +case 204: {// wxStyledTextEvent wxStyledTextEvent * ev = (wxStyledTextEvent *) event; evClass = (char*)"wxStyledTextEvent"; rt.addAtom((char*)"wxStyledText"); @@ -766,7 +769,7 @@ case 203: {// wxStyledTextEvent rt.addTupleCount(22); break; } -case 209: {// wxTreeEvent +case 210: {// wxTreeEvent wxTreeEvent * ev = (wxTreeEvent *) event; evClass = (char*)"wxTreeEvent"; rt.addAtom((char*)"wxTree"); @@ -777,7 +780,7 @@ case 209: {// wxTreeEvent rt.addTupleCount(5); break; } -case 210: {// wxNotebookEvent +case 211: {// wxNotebookEvent wxNotebookEvent * ev = (wxNotebookEvent *) event; evClass = (char*)"wxNotebookEvent"; rt.addAtom((char*)"wxNotebook"); @@ -787,14 +790,14 @@ case 210: {// wxNotebookEvent rt.addTupleCount(4); break; } -case 216: {// wxClipboardTextEvent +case 217: {// wxClipboardTextEvent evClass = (char*)"wxClipboardTextEvent"; rt.addAtom((char*)"wxClipboardText"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 217: {// wxSpinEvent +case 218: {// wxSpinEvent wxSpinEvent * ev = (wxSpinEvent *) event; evClass = (char*)"wxSpinEvent"; rt.addAtom((char*)"wxSpin"); @@ -803,14 +806,14 @@ case 217: {// wxSpinEvent rt.addTupleCount(3); break; } -case 219: {// wxSplitterEvent +case 220: {// wxSplitterEvent evClass = (char*)"wxSplitterEvent"; rt.addAtom((char*)"wxSplitter"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 221: {// wxHtmlLinkEvent +case 222: {// wxHtmlLinkEvent wxHtmlLinkEvent * ev = (wxHtmlLinkEvent *) event; evClass = (char*)"wxHtmlLinkEvent"; rt.addAtom((char*)"wxHtmlLink"); @@ -819,7 +822,7 @@ case 221: {// wxHtmlLinkEvent rt.addTupleCount(3); break; } -case 224: {// wxAuiNotebookEvent +case 225: {// wxAuiNotebookEvent wxAuiNotebookEvent * ev = (wxAuiNotebookEvent *) event; wxAuiNotebook * GetDragSource = ev->GetDragSource(); evClass = (char*)"wxAuiNotebookEvent"; @@ -831,7 +834,7 @@ case 224: {// wxAuiNotebookEvent rt.addTupleCount(5); break; } -case 225: {// wxAuiManagerEvent +case 226: {// wxAuiManagerEvent wxAuiManagerEvent * ev = (wxAuiManagerEvent *) event; wxAuiManager * GetManager = ev->GetManager(); wxAuiPaneInfo * GetPane = ev->GetPane(); @@ -848,21 +851,21 @@ case 225: {// wxAuiManagerEvent rt.addTupleCount(8); break; } -case 228: {// wxTaskBarIconEvent +case 229: {// wxTaskBarIconEvent evClass = (char*)"wxTaskBarIconEvent"; rt.addAtom((char*)"wxTaskBarIcon"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 229: {// wxInitDialogEvent +case 230: {// wxInitDialogEvent evClass = (char*)"wxInitDialogEvent"; rt.addAtom((char*)"wxInitDialog"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 231: {// wxActivateEvent +case 232: {// wxActivateEvent wxActivateEvent * ev = (wxActivateEvent *) event; evClass = (char*)"wxActivateEvent"; rt.addAtom((char*)"wxActivate"); @@ -871,7 +874,7 @@ case 231: {// wxActivateEvent rt.addTupleCount(3); break; } -case 234: {// wxMouseCaptureLostEvent +case 235: {// wxMouseCaptureLostEvent evClass = (char*)"wxMouseCaptureLostEvent"; rt.addAtom((char*)"wxMouseCaptureLost"); rt.addAtom(Etype->eName); diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index b440de6cae..3211664499 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -23735,8 +23735,11 @@ case wxAuiManager_DetachPane: { // wxAuiManager::DetachPane case wxAuiManager_GetAllPanes: { // wxAuiManager::GetAllPanes wxAuiManager *This = (wxAuiManager *) getPtr(bp,memenv); bp += 4; if(!This) throw wxe_badarg(0); - wxAuiPaneInfoArray * Result = &This->GetAllPanes(); - rt.addRef(getRef((void *)Result,memenv), "wxAuiPaneInfoArray"); + wxAuiPaneInfoArray Result = This->GetAllPanes(); + for(unsigned int i=0; i < Result.GetCount(); i++) { + rt.addRef(getRef((void *) &Result.Item(i), memenv), "wxAuiPaneInfo"); + } + rt.endList(Result.GetCount()); break; } case wxAuiManager_GetArtProvider: { // wxAuiManager::GetArtProvider @@ -24595,6 +24598,102 @@ case wxAuiPaneInfo_Window: { // wxAuiPaneInfo::Window rt.addRef(getRef((void *)Result,memenv), "wxAuiPaneInfo"); break; } +case wxAuiPaneInfo_GetWindow: { // wxAuiPaneInfo::GetWindow + wxAuiPaneInfo *This = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4; + #if 0 +; + if(!This) throw wxe_badarg(0); + wxWindow * Result = (wxWindow*)This->GetWindow(); + #endif + if(!This) throw wxe_badarg(0); + wxWindow* Result = This->window; + rt.addRef(getRef((void *)Result,memenv), "wxWindow"); + break; +} +case wxAuiPaneInfo_GetFrame: { // wxAuiPaneInfo::GetFrame + wxAuiPaneInfo *This = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4; + #if 0 +; + if(!This) throw wxe_badarg(0); + wxFrame * Result = (wxFrame*)This->GetFrame(); + #endif + if(!This) throw wxe_badarg(0); + wxFrame* Result = This->frame; + rt.addRef(getRef((void *)Result,memenv), "wxFrame"); + break; +} +case wxAuiPaneInfo_GetDirection: { // wxAuiPaneInfo::GetDirection + wxAuiPaneInfo *This = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4; + #if 0 +; + if(!This) throw wxe_badarg(0); + int Result = This->GetDirection(); + #endif + if(!This) throw wxe_badarg(0); + int Result = This->dock_direction; + rt.addInt(Result); + break; +} +case wxAuiPaneInfo_GetLayer: { // wxAuiPaneInfo::GetLayer + wxAuiPaneInfo *This = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4; + #if 0 +; + if(!This) throw wxe_badarg(0); + int Result = This->GetLayer(); + #endif + if(!This) throw wxe_badarg(0); + int Result = This->dock_layer; + rt.addInt(Result); + break; +} +case wxAuiPaneInfo_GetRow: { // wxAuiPaneInfo::GetRow + wxAuiPaneInfo *This = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4; + #if 0 +; + if(!This) throw wxe_badarg(0); + int Result = This->GetRow(); + #endif + if(!This) throw wxe_badarg(0); + int Result = This->dock_row; + rt.addInt(Result); + break; +} +case wxAuiPaneInfo_GetPosition: { // wxAuiPaneInfo::GetPosition + wxAuiPaneInfo *This = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4; + #if 0 +; + if(!This) throw wxe_badarg(0); + int Result = This->GetPosition(); + #endif + if(!This) throw wxe_badarg(0); + int Result = This->dock_pos; + rt.addInt(Result); + break; +} +case wxAuiPaneInfo_GetFloatingPosition: { // wxAuiPaneInfo::GetFloatingPosition + wxAuiPaneInfo *This = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4; + #if 0 +; + if(!This) throw wxe_badarg(0); + wxPoint Result = This->GetFloatingPosition(); + #endif + if(!This) throw wxe_badarg(0); + wxPoint Result = This->floating_pos; + rt.add(Result); + break; +} +case wxAuiPaneInfo_GetFloatingSize: { // wxAuiPaneInfo::GetFloatingSize + wxAuiPaneInfo *This = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4; + #if 0 +; + if(!This) throw wxe_badarg(0); + wxSize Result = This->GetFloatingSize(); + #endif + if(!This) throw wxe_badarg(0); + wxSize Result = This->floating_size; + rt.add(Result); + break; +} #endif // wxUSE_AUI #if wxUSE_AUI case wxAuiNotebook_new_0: { // wxAuiNotebook::wxAuiNotebook @@ -24840,8 +24939,128 @@ case wxAuiNotebook_SetUniformBitmapSize: { // wxAuiNotebook::SetUniformBitmapSiz } #endif // wxUSE_AUI #if wxUSE_AUI +case wxAuiTabArt_SetFlags: { // wxAuiTabArt::SetFlags + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + unsigned int * flags = (unsigned int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + This->SetFlags(*flags); + break; +} +case wxAuiTabArt_SetMeasuringFont: { // wxAuiTabArt::SetMeasuringFont + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->SetMeasuringFont(*font); + break; +} +case wxAuiTabArt_SetNormalFont: { // wxAuiTabArt::SetNormalFont + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->SetNormalFont(*font); + break; +} +case wxAuiTabArt_SetSelectedFont: { // wxAuiTabArt::SetSelectedFont + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->SetSelectedFont(*font); + break; +} +#if wxCHECK_VERSION(3,0,0) +case wxAuiTabArt_SetColour: { // wxAuiTabArt::SetColour + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + int * colourR = (int *) bp; bp += 4; + int * colourG = (int *) bp; bp += 4; + int * colourB = (int *) bp; bp += 4; + int * colourA = (int *) bp; bp += 4; + wxColour colour = wxColour(*colourR,*colourG,*colourB,*colourA); + if(!This) throw wxe_badarg(0); + This->SetColour(colour); + break; +} +#endif +#if wxCHECK_VERSION(3,0,0) +case wxAuiTabArt_SetActiveColour: { // wxAuiTabArt::SetActiveColour + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + int * colourR = (int *) bp; bp += 4; + int * colourG = (int *) bp; bp += 4; + int * colourB = (int *) bp; bp += 4; + int * colourA = (int *) bp; bp += 4; + wxColour colour = wxColour(*colourR,*colourG,*colourB,*colourA); + if(!This) throw wxe_badarg(0); + This->SetActiveColour(colour); + break; +} +#endif +#endif // wxUSE_AUI +#if wxUSE_AUI +case wxAuiDockArt_GetColour: { // wxAuiDockArt::GetColour + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + wxColour Result = This->GetColour(*id); + rt.add(Result); + break; +} +case wxAuiDockArt_GetFont: { // wxAuiDockArt::GetFont + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + wxFont * Result = new wxFont(This->GetFont(*id)); newPtr((void *) Result,3, memenv);; + rt.addRef(getRef((void *)Result,memenv), "wxFont"); + break; +} +case wxAuiDockArt_GetMetric: { // wxAuiDockArt::GetMetric + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + int Result = This->GetMetric(*id); + rt.addInt(Result); + break; +} +case wxAuiDockArt_SetColour: { // wxAuiDockArt::SetColour + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + int * colourR = (int *) bp; bp += 4; + int * colourG = (int *) bp; bp += 4; + int * colourB = (int *) bp; bp += 4; + int * colourA = (int *) bp; bp += 4; + wxColour colour = wxColour(*colourR,*colourG,*colourB,*colourA); + if(!This) throw wxe_badarg(0); + This->SetColour(*id,colour); + break; +} +case wxAuiDockArt_SetFont: { // wxAuiDockArt::SetFont + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->SetFont(*id,*font); + break; +} +case wxAuiDockArt_SetMetric: { // wxAuiDockArt::SetMetric + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + int * new_val = (int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + This->SetMetric(*id,*new_val); + break; +} #endif // wxUSE_AUI #if wxUSE_AUI +case wxAuiSimpleTabArt_new: { // wxAuiSimpleTabArt::wxAuiSimpleTabArt + wxAuiSimpleTabArt * Result = new wxAuiSimpleTabArt(); + newPtr((void *) Result, 159, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxAuiSimpleTabArt"); + break; +} +case wxAuiSimpleTabArt_destroy: { // wxAuiSimpleTabArt::destroy + wxAuiSimpleTabArt *This = (wxAuiSimpleTabArt *) getPtr(bp,memenv); bp += 4; + if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This); + delete This;} + break; +} #endif // wxUSE_AUI case wxMDIParentFrame_new_0: { // wxMDIParentFrame::wxMDIParentFrame wxMDIParentFrame * Result = new EwxMDIParentFrame(); @@ -30473,7 +30692,7 @@ case wxNotebookEvent_SetSelection: { // wxNotebookEvent::SetSelection } case wxFileDataObject_new: { // wxFileDataObject::wxFileDataObject wxFileDataObject * Result = new wxFileDataObject(); - newPtr((void *) Result, 212, memenv); + newPtr((void *) Result, 213, memenv); rt.addRef(getRef((void *)Result,memenv), "wxFileDataObject"); break; } @@ -30509,7 +30728,7 @@ case wxTextDataObject_new: { // wxTextDataObject::wxTextDataObject } break; }}; wxTextDataObject * Result = new wxTextDataObject(text); - newPtr((void *) Result, 213, memenv); + newPtr((void *) Result, 214, memenv); rt.addRef(getRef((void *)Result,memenv), "wxTextDataObject"); break; } @@ -30545,7 +30764,7 @@ case wxTextDataObject_destroy: { // wxTextDataObject::destroy case wxBitmapDataObject_new_1_1: { // wxBitmapDataObject::wxBitmapDataObject wxBitmap *bitmap = (wxBitmap *) getPtr(bp,memenv); bp += 4; wxBitmapDataObject * Result = new wxBitmapDataObject(*bitmap); - newPtr((void *) Result, 214, memenv); + newPtr((void *) Result, 215, memenv); rt.addRef(getRef((void *)Result,memenv), "wxBitmapDataObject"); break; } @@ -30557,7 +30776,7 @@ bitmap = (wxBitmap *) getPtr(bp,memenv); bp += 4; } break; }}; wxBitmapDataObject * Result = new wxBitmapDataObject(*bitmap); - newPtr((void *) Result, 214, memenv); + newPtr((void *) Result, 215, memenv); rt.addRef(getRef((void *)Result,memenv), "wxBitmapDataObject"); break; } @@ -31390,7 +31609,7 @@ case wxAuiManagerEvent_CanVeto: { // wxAuiManagerEvent::CanVeto } case wxLogNull_new: { // wxLogNull::wxLogNull wxLogNull * Result = new wxLogNull(); - newPtr((void *) Result, 226, memenv); + newPtr((void *) Result, 227, memenv); rt.addRef(getRef((void *)Result,memenv), "wxLogNull"); break; } @@ -31439,7 +31658,7 @@ case wxTaskBarIcon_SetIcon: { // wxTaskBarIcon::SetIcon } case wxLocale_new_0: { // wxLocale::wxLocale wxLocale * Result = new EwxLocale(); - newPtr((void *) Result, 230, memenv); + newPtr((void *) Result, 231, memenv); rt.addRef(getRef((void *)Result,memenv), "wxLocale"); break; } @@ -31453,7 +31672,7 @@ case wxLocale_new_2: { // wxLocale::wxLocale } break; }}; wxLocale * Result = new EwxLocale(*language,flags); - newPtr((void *) Result, 230, memenv); + newPtr((void *) Result, 231, memenv); rt.addRef(getRef((void *)Result,memenv), "wxLocale"); break; } @@ -31780,11 +31999,12 @@ bool WxeApp::delete_object(void *ptr, wxeRefData *refd) { case 101: delete (wxListItemAttr *) ptr; break; case 103: delete (wxTextAttr *) ptr; break; case 155: delete (wxAuiPaneInfo *) ptr; break; - case 212: /* delete (wxFileDataObject *) ptr;These objects must be deleted by owner object */ break; - case 213: /* delete (wxTextDataObject *) ptr;These objects must be deleted by owner object */ break; - case 214: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break; - case 226: delete (wxLogNull *) ptr; break; - case 230: delete (EwxLocale *) ptr; return false; + case 159: /* delete (wxAuiSimpleTabArt *) ptr;These objects must be deleted by owner object */ break; + case 213: /* delete (wxFileDataObject *) ptr;These objects must be deleted by owner object */ break; + case 214: /* delete (wxTextDataObject *) ptr;These objects must be deleted by owner object */ break; + case 215: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break; + case 227: delete (wxLogNull *) ptr; break; + case 231: delete (EwxLocale *) ptr; return false; default: delete (wxObject *) ptr; return false; } return true; diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h index 50ceb01623..59f9c7054e 100644 --- a/lib/wx/c_src/gen/wxe_macros.h +++ b/lib/wx/c_src/gen/wxe_macros.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2008-2014. All Rights Reserved. + * Copyright Ericsson AB 2008-2015. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -2488,906 +2488,928 @@ #define wxAuiPaneInfo_Top 2650 #define wxAuiPaneInfo_TopDockable 2651 #define wxAuiPaneInfo_Window 2652 -#define wxAuiNotebook_new_0 2653 -#define wxAuiNotebook_new_2 2654 -#define wxAuiNotebook_AddPage 2655 -#define wxAuiNotebook_Create 2656 -#define wxAuiNotebook_DeletePage 2657 -#define wxAuiNotebook_GetArtProvider 2658 -#define wxAuiNotebook_GetPage 2659 -#define wxAuiNotebook_GetPageBitmap 2660 -#define wxAuiNotebook_GetPageCount 2661 -#define wxAuiNotebook_GetPageIndex 2662 -#define wxAuiNotebook_GetPageText 2663 -#define wxAuiNotebook_GetSelection 2664 -#define wxAuiNotebook_InsertPage 2665 -#define wxAuiNotebook_RemovePage 2666 -#define wxAuiNotebook_SetArtProvider 2667 -#define wxAuiNotebook_SetFont 2668 -#define wxAuiNotebook_SetPageBitmap 2669 -#define wxAuiNotebook_SetPageText 2670 -#define wxAuiNotebook_SetSelection 2671 -#define wxAuiNotebook_SetTabCtrlHeight 2672 -#define wxAuiNotebook_SetUniformBitmapSize 2673 -#define wxAuiNotebook_destroy 2674 -#define wxMDIParentFrame_new_0 2675 -#define wxMDIParentFrame_new_4 2676 -#define wxMDIParentFrame_destruct 2677 -#define wxMDIParentFrame_ActivateNext 2678 -#define wxMDIParentFrame_ActivatePrevious 2679 -#define wxMDIParentFrame_ArrangeIcons 2680 -#define wxMDIParentFrame_Cascade 2681 -#define wxMDIParentFrame_Create 2682 -#define wxMDIParentFrame_GetActiveChild 2683 -#define wxMDIParentFrame_GetClientWindow 2684 -#define wxMDIParentFrame_Tile 2685 -#define wxMDIChildFrame_new_0 2686 -#define wxMDIChildFrame_new_4 2687 -#define wxMDIChildFrame_destruct 2688 -#define wxMDIChildFrame_Activate 2689 -#define wxMDIChildFrame_Create 2690 -#define wxMDIChildFrame_Maximize 2691 -#define wxMDIChildFrame_Restore 2692 -#define wxMDIClientWindow_new_0 2693 -#define wxMDIClientWindow_new_2 2694 -#define wxMDIClientWindow_destruct 2695 -#define wxMDIClientWindow_CreateClient 2696 -#define wxLayoutAlgorithm_new 2697 -#define wxLayoutAlgorithm_LayoutFrame 2698 -#define wxLayoutAlgorithm_LayoutMDIFrame 2699 -#define wxLayoutAlgorithm_LayoutWindow 2700 -#define wxLayoutAlgorithm_destroy 2701 -#define wxEvent_GetId 2702 -#define wxEvent_GetSkipped 2703 -#define wxEvent_GetTimestamp 2704 -#define wxEvent_IsCommandEvent 2705 -#define wxEvent_ResumePropagation 2706 -#define wxEvent_ShouldPropagate 2707 -#define wxEvent_Skip 2708 -#define wxEvent_StopPropagation 2709 -#define wxCommandEvent_getClientData 2710 -#define wxCommandEvent_GetExtraLong 2711 -#define wxCommandEvent_GetInt 2712 -#define wxCommandEvent_GetSelection 2713 -#define wxCommandEvent_GetString 2714 -#define wxCommandEvent_IsChecked 2715 -#define wxCommandEvent_IsSelection 2716 -#define wxCommandEvent_SetInt 2717 -#define wxCommandEvent_SetString 2718 -#define wxScrollEvent_GetOrientation 2719 -#define wxScrollEvent_GetPosition 2720 -#define wxScrollWinEvent_GetOrientation 2721 -#define wxScrollWinEvent_GetPosition 2722 -#define wxMouseEvent_AltDown 2723 -#define wxMouseEvent_Button 2724 -#define wxMouseEvent_ButtonDClick 2725 -#define wxMouseEvent_ButtonDown 2726 -#define wxMouseEvent_ButtonUp 2727 -#define wxMouseEvent_CmdDown 2728 -#define wxMouseEvent_ControlDown 2729 -#define wxMouseEvent_Dragging 2730 -#define wxMouseEvent_Entering 2731 -#define wxMouseEvent_GetButton 2732 -#define wxMouseEvent_GetPosition 2735 -#define wxMouseEvent_GetLogicalPosition 2736 -#define wxMouseEvent_GetLinesPerAction 2737 -#define wxMouseEvent_GetWheelRotation 2738 -#define wxMouseEvent_GetWheelDelta 2739 -#define wxMouseEvent_GetX 2740 -#define wxMouseEvent_GetY 2741 -#define wxMouseEvent_IsButton 2742 -#define wxMouseEvent_IsPageScroll 2743 -#define wxMouseEvent_Leaving 2744 -#define wxMouseEvent_LeftDClick 2745 -#define wxMouseEvent_LeftDown 2746 -#define wxMouseEvent_LeftIsDown 2747 -#define wxMouseEvent_LeftUp 2748 -#define wxMouseEvent_MetaDown 2749 -#define wxMouseEvent_MiddleDClick 2750 -#define wxMouseEvent_MiddleDown 2751 -#define wxMouseEvent_MiddleIsDown 2752 -#define wxMouseEvent_MiddleUp 2753 -#define wxMouseEvent_Moving 2754 -#define wxMouseEvent_RightDClick 2755 -#define wxMouseEvent_RightDown 2756 -#define wxMouseEvent_RightIsDown 2757 -#define wxMouseEvent_RightUp 2758 -#define wxMouseEvent_ShiftDown 2759 -#define wxSetCursorEvent_GetCursor 2760 -#define wxSetCursorEvent_GetX 2761 -#define wxSetCursorEvent_GetY 2762 -#define wxSetCursorEvent_HasCursor 2763 -#define wxSetCursorEvent_SetCursor 2764 -#define wxKeyEvent_AltDown 2765 -#define wxKeyEvent_CmdDown 2766 -#define wxKeyEvent_ControlDown 2767 -#define wxKeyEvent_GetKeyCode 2768 -#define wxKeyEvent_GetModifiers 2769 -#define wxKeyEvent_GetPosition 2772 -#define wxKeyEvent_GetRawKeyCode 2773 -#define wxKeyEvent_GetRawKeyFlags 2774 -#define wxKeyEvent_GetUnicodeKey 2775 -#define wxKeyEvent_GetX 2776 -#define wxKeyEvent_GetY 2777 -#define wxKeyEvent_HasModifiers 2778 -#define wxKeyEvent_MetaDown 2779 -#define wxKeyEvent_ShiftDown 2780 -#define wxSizeEvent_GetSize 2781 -#define wxMoveEvent_GetPosition 2782 -#define wxEraseEvent_GetDC 2783 -#define wxFocusEvent_GetWindow 2784 -#define wxChildFocusEvent_GetWindow 2785 -#define wxMenuEvent_GetMenu 2786 -#define wxMenuEvent_GetMenuId 2787 -#define wxMenuEvent_IsPopup 2788 -#define wxCloseEvent_CanVeto 2789 -#define wxCloseEvent_GetLoggingOff 2790 -#define wxCloseEvent_SetCanVeto 2791 -#define wxCloseEvent_SetLoggingOff 2792 -#define wxCloseEvent_Veto 2793 -#define wxShowEvent_SetShow 2794 -#define wxShowEvent_GetShow 2795 -#define wxIconizeEvent_Iconized 2796 -#define wxJoystickEvent_ButtonDown 2797 -#define wxJoystickEvent_ButtonIsDown 2798 -#define wxJoystickEvent_ButtonUp 2799 -#define wxJoystickEvent_GetButtonChange 2800 -#define wxJoystickEvent_GetButtonState 2801 -#define wxJoystickEvent_GetJoystick 2802 -#define wxJoystickEvent_GetPosition 2803 -#define wxJoystickEvent_GetZPosition 2804 -#define wxJoystickEvent_IsButton 2805 -#define wxJoystickEvent_IsMove 2806 -#define wxJoystickEvent_IsZMove 2807 -#define wxUpdateUIEvent_CanUpdate 2808 -#define wxUpdateUIEvent_Check 2809 -#define wxUpdateUIEvent_Enable 2810 -#define wxUpdateUIEvent_Show 2811 -#define wxUpdateUIEvent_GetChecked 2812 -#define wxUpdateUIEvent_GetEnabled 2813 -#define wxUpdateUIEvent_GetShown 2814 -#define wxUpdateUIEvent_GetSetChecked 2815 -#define wxUpdateUIEvent_GetSetEnabled 2816 -#define wxUpdateUIEvent_GetSetShown 2817 -#define wxUpdateUIEvent_GetSetText 2818 -#define wxUpdateUIEvent_GetText 2819 -#define wxUpdateUIEvent_GetMode 2820 -#define wxUpdateUIEvent_GetUpdateInterval 2821 -#define wxUpdateUIEvent_ResetUpdateTime 2822 -#define wxUpdateUIEvent_SetMode 2823 -#define wxUpdateUIEvent_SetText 2824 -#define wxUpdateUIEvent_SetUpdateInterval 2825 -#define wxMouseCaptureChangedEvent_GetCapturedWindow 2826 -#define wxPaletteChangedEvent_SetChangedWindow 2827 -#define wxPaletteChangedEvent_GetChangedWindow 2828 -#define wxQueryNewPaletteEvent_SetPaletteRealized 2829 -#define wxQueryNewPaletteEvent_GetPaletteRealized 2830 -#define wxNavigationKeyEvent_GetDirection 2831 -#define wxNavigationKeyEvent_SetDirection 2832 -#define wxNavigationKeyEvent_IsWindowChange 2833 -#define wxNavigationKeyEvent_SetWindowChange 2834 -#define wxNavigationKeyEvent_IsFromTab 2835 -#define wxNavigationKeyEvent_SetFromTab 2836 -#define wxNavigationKeyEvent_GetCurrentFocus 2837 -#define wxNavigationKeyEvent_SetCurrentFocus 2838 -#define wxHelpEvent_GetOrigin 2839 -#define wxHelpEvent_GetPosition 2840 -#define wxHelpEvent_SetOrigin 2841 -#define wxHelpEvent_SetPosition 2842 -#define wxContextMenuEvent_GetPosition 2843 -#define wxContextMenuEvent_SetPosition 2844 -#define wxIdleEvent_CanSend 2845 -#define wxIdleEvent_GetMode 2846 -#define wxIdleEvent_RequestMore 2847 -#define wxIdleEvent_MoreRequested 2848 -#define wxIdleEvent_SetMode 2849 -#define wxGridEvent_AltDown 2850 -#define wxGridEvent_ControlDown 2851 -#define wxGridEvent_GetCol 2852 -#define wxGridEvent_GetPosition 2853 -#define wxGridEvent_GetRow 2854 -#define wxGridEvent_MetaDown 2855 -#define wxGridEvent_Selecting 2856 -#define wxGridEvent_ShiftDown 2857 -#define wxNotifyEvent_Allow 2858 -#define wxNotifyEvent_IsAllowed 2859 -#define wxNotifyEvent_Veto 2860 -#define wxSashEvent_GetEdge 2861 -#define wxSashEvent_GetDragRect 2862 -#define wxSashEvent_GetDragStatus 2863 -#define wxListEvent_GetCacheFrom 2864 -#define wxListEvent_GetCacheTo 2865 -#define wxListEvent_GetKeyCode 2866 -#define wxListEvent_GetIndex 2867 -#define wxListEvent_GetColumn 2868 -#define wxListEvent_GetPoint 2869 -#define wxListEvent_GetLabel 2870 -#define wxListEvent_GetText 2871 -#define wxListEvent_GetImage 2872 -#define wxListEvent_GetData 2873 -#define wxListEvent_GetMask 2874 -#define wxListEvent_GetItem 2875 -#define wxListEvent_IsEditCancelled 2876 -#define wxDateEvent_GetDate 2877 -#define wxCalendarEvent_GetWeekDay 2878 -#define wxFileDirPickerEvent_GetPath 2879 -#define wxColourPickerEvent_GetColour 2880 -#define wxFontPickerEvent_GetFont 2881 -#define wxStyledTextEvent_GetPosition 2882 -#define wxStyledTextEvent_GetKey 2883 -#define wxStyledTextEvent_GetModifiers 2884 -#define wxStyledTextEvent_GetModificationType 2885 -#define wxStyledTextEvent_GetText 2886 -#define wxStyledTextEvent_GetLength 2887 -#define wxStyledTextEvent_GetLinesAdded 2888 -#define wxStyledTextEvent_GetLine 2889 -#define wxStyledTextEvent_GetFoldLevelNow 2890 -#define wxStyledTextEvent_GetFoldLevelPrev 2891 -#define wxStyledTextEvent_GetMargin 2892 -#define wxStyledTextEvent_GetMessage 2893 -#define wxStyledTextEvent_GetWParam 2894 -#define wxStyledTextEvent_GetLParam 2895 -#define wxStyledTextEvent_GetListType 2896 -#define wxStyledTextEvent_GetX 2897 -#define wxStyledTextEvent_GetY 2898 -#define wxStyledTextEvent_GetDragText 2899 -#define wxStyledTextEvent_GetDragAllowMove 2900 -#define wxStyledTextEvent_GetDragResult 2901 -#define wxStyledTextEvent_GetShift 2902 -#define wxStyledTextEvent_GetControl 2903 -#define wxStyledTextEvent_GetAlt 2904 -#define utils_wxGetKeyState 2905 -#define utils_wxGetMousePosition 2906 -#define utils_wxGetMouseState 2907 -#define utils_wxSetDetectableAutoRepeat 2908 -#define utils_wxBell 2909 -#define utils_wxFindMenuItemId 2910 -#define utils_wxGenericFindWindowAtPoint 2911 -#define utils_wxFindWindowAtPoint 2912 -#define utils_wxBeginBusyCursor 2913 -#define utils_wxEndBusyCursor 2914 -#define utils_wxIsBusy 2915 -#define utils_wxShutdown 2916 -#define utils_wxShell 2917 -#define utils_wxLaunchDefaultBrowser 2918 -#define utils_wxGetEmailAddress 2919 -#define utils_wxGetUserId 2920 -#define utils_wxGetHomeDir 2921 -#define utils_wxNewId 2922 -#define utils_wxRegisterId 2923 -#define utils_wxGetCurrentId 2924 -#define utils_wxGetOsDescription 2925 -#define utils_wxIsPlatformLittleEndian 2926 -#define utils_wxIsPlatform64Bit 2927 -#define gdicmn_wxDisplaySize 2928 -#define gdicmn_wxSetCursor 2929 -#define wxPrintout_new 2930 -#define wxPrintout_destruct 2931 -#define wxPrintout_GetDC 2932 -#define wxPrintout_GetPageSizeMM 2933 -#define wxPrintout_GetPageSizePixels 2934 -#define wxPrintout_GetPaperRectPixels 2935 -#define wxPrintout_GetPPIPrinter 2936 -#define wxPrintout_GetPPIScreen 2937 -#define wxPrintout_GetTitle 2938 -#define wxPrintout_IsPreview 2939 -#define wxPrintout_FitThisSizeToPaper 2940 -#define wxPrintout_FitThisSizeToPage 2941 -#define wxPrintout_FitThisSizeToPageMargins 2942 -#define wxPrintout_MapScreenSizeToPaper 2943 -#define wxPrintout_MapScreenSizeToPage 2944 -#define wxPrintout_MapScreenSizeToPageMargins 2945 -#define wxPrintout_MapScreenSizeToDevice 2946 -#define wxPrintout_GetLogicalPaperRect 2947 -#define wxPrintout_GetLogicalPageRect 2948 -#define wxPrintout_GetLogicalPageMarginsRect 2949 -#define wxPrintout_SetLogicalOrigin 2950 -#define wxPrintout_OffsetLogicalOrigin 2951 -#define wxStyledTextCtrl_new_2 2952 -#define wxStyledTextCtrl_new_0 2953 -#define wxStyledTextCtrl_destruct 2954 -#define wxStyledTextCtrl_Create 2955 -#define wxStyledTextCtrl_AddText 2956 -#define wxStyledTextCtrl_AddStyledText 2957 -#define wxStyledTextCtrl_InsertText 2958 -#define wxStyledTextCtrl_ClearAll 2959 -#define wxStyledTextCtrl_ClearDocumentStyle 2960 -#define wxStyledTextCtrl_GetLength 2961 -#define wxStyledTextCtrl_GetCharAt 2962 -#define wxStyledTextCtrl_GetCurrentPos 2963 -#define wxStyledTextCtrl_GetAnchor 2964 -#define wxStyledTextCtrl_GetStyleAt 2965 -#define wxStyledTextCtrl_Redo 2966 -#define wxStyledTextCtrl_SetUndoCollection 2967 -#define wxStyledTextCtrl_SelectAll 2968 -#define wxStyledTextCtrl_SetSavePoint 2969 -#define wxStyledTextCtrl_GetStyledText 2970 -#define wxStyledTextCtrl_CanRedo 2971 -#define wxStyledTextCtrl_MarkerLineFromHandle 2972 -#define wxStyledTextCtrl_MarkerDeleteHandle 2973 -#define wxStyledTextCtrl_GetUndoCollection 2974 -#define wxStyledTextCtrl_GetViewWhiteSpace 2975 -#define wxStyledTextCtrl_SetViewWhiteSpace 2976 -#define wxStyledTextCtrl_PositionFromPoint 2977 -#define wxStyledTextCtrl_PositionFromPointClose 2978 -#define wxStyledTextCtrl_GotoLine 2979 -#define wxStyledTextCtrl_GotoPos 2980 -#define wxStyledTextCtrl_SetAnchor 2981 -#define wxStyledTextCtrl_GetCurLine 2982 -#define wxStyledTextCtrl_GetEndStyled 2983 -#define wxStyledTextCtrl_ConvertEOLs 2984 -#define wxStyledTextCtrl_GetEOLMode 2985 -#define wxStyledTextCtrl_SetEOLMode 2986 -#define wxStyledTextCtrl_StartStyling 2987 -#define wxStyledTextCtrl_SetStyling 2988 -#define wxStyledTextCtrl_GetBufferedDraw 2989 -#define wxStyledTextCtrl_SetBufferedDraw 2990 -#define wxStyledTextCtrl_SetTabWidth 2991 -#define wxStyledTextCtrl_GetTabWidth 2992 -#define wxStyledTextCtrl_SetCodePage 2993 -#define wxStyledTextCtrl_MarkerDefine 2994 -#define wxStyledTextCtrl_MarkerSetForeground 2995 -#define wxStyledTextCtrl_MarkerSetBackground 2996 -#define wxStyledTextCtrl_MarkerAdd 2997 -#define wxStyledTextCtrl_MarkerDelete 2998 -#define wxStyledTextCtrl_MarkerDeleteAll 2999 -#define wxStyledTextCtrl_MarkerGet 3000 -#define wxStyledTextCtrl_MarkerNext 3001 -#define wxStyledTextCtrl_MarkerPrevious 3002 -#define wxStyledTextCtrl_MarkerDefineBitmap 3003 -#define wxStyledTextCtrl_MarkerAddSet 3004 -#define wxStyledTextCtrl_MarkerSetAlpha 3005 -#define wxStyledTextCtrl_SetMarginType 3006 -#define wxStyledTextCtrl_GetMarginType 3007 -#define wxStyledTextCtrl_SetMarginWidth 3008 -#define wxStyledTextCtrl_GetMarginWidth 3009 -#define wxStyledTextCtrl_SetMarginMask 3010 -#define wxStyledTextCtrl_GetMarginMask 3011 -#define wxStyledTextCtrl_SetMarginSensitive 3012 -#define wxStyledTextCtrl_GetMarginSensitive 3013 -#define wxStyledTextCtrl_StyleClearAll 3014 -#define wxStyledTextCtrl_StyleSetForeground 3015 -#define wxStyledTextCtrl_StyleSetBackground 3016 -#define wxStyledTextCtrl_StyleSetBold 3017 -#define wxStyledTextCtrl_StyleSetItalic 3018 -#define wxStyledTextCtrl_StyleSetSize 3019 -#define wxStyledTextCtrl_StyleSetFaceName 3020 -#define wxStyledTextCtrl_StyleSetEOLFilled 3021 -#define wxStyledTextCtrl_StyleResetDefault 3022 -#define wxStyledTextCtrl_StyleSetUnderline 3023 -#define wxStyledTextCtrl_StyleSetCase 3024 -#define wxStyledTextCtrl_StyleSetHotSpot 3025 -#define wxStyledTextCtrl_SetSelForeground 3026 -#define wxStyledTextCtrl_SetSelBackground 3027 -#define wxStyledTextCtrl_GetSelAlpha 3028 -#define wxStyledTextCtrl_SetSelAlpha 3029 -#define wxStyledTextCtrl_SetCaretForeground 3030 -#define wxStyledTextCtrl_CmdKeyAssign 3031 -#define wxStyledTextCtrl_CmdKeyClear 3032 -#define wxStyledTextCtrl_CmdKeyClearAll 3033 -#define wxStyledTextCtrl_SetStyleBytes 3034 -#define wxStyledTextCtrl_StyleSetVisible 3035 -#define wxStyledTextCtrl_GetCaretPeriod 3036 -#define wxStyledTextCtrl_SetCaretPeriod 3037 -#define wxStyledTextCtrl_SetWordChars 3038 -#define wxStyledTextCtrl_BeginUndoAction 3039 -#define wxStyledTextCtrl_EndUndoAction 3040 -#define wxStyledTextCtrl_IndicatorSetStyle 3041 -#define wxStyledTextCtrl_IndicatorGetStyle 3042 -#define wxStyledTextCtrl_IndicatorSetForeground 3043 -#define wxStyledTextCtrl_IndicatorGetForeground 3044 -#define wxStyledTextCtrl_SetWhitespaceForeground 3045 -#define wxStyledTextCtrl_SetWhitespaceBackground 3046 -#define wxStyledTextCtrl_GetStyleBits 3047 -#define wxStyledTextCtrl_SetLineState 3048 -#define wxStyledTextCtrl_GetLineState 3049 -#define wxStyledTextCtrl_GetMaxLineState 3050 -#define wxStyledTextCtrl_GetCaretLineVisible 3051 -#define wxStyledTextCtrl_SetCaretLineVisible 3052 -#define wxStyledTextCtrl_GetCaretLineBackground 3053 -#define wxStyledTextCtrl_SetCaretLineBackground 3054 -#define wxStyledTextCtrl_AutoCompShow 3055 -#define wxStyledTextCtrl_AutoCompCancel 3056 -#define wxStyledTextCtrl_AutoCompActive 3057 -#define wxStyledTextCtrl_AutoCompPosStart 3058 -#define wxStyledTextCtrl_AutoCompComplete 3059 -#define wxStyledTextCtrl_AutoCompStops 3060 -#define wxStyledTextCtrl_AutoCompSetSeparator 3061 -#define wxStyledTextCtrl_AutoCompGetSeparator 3062 -#define wxStyledTextCtrl_AutoCompSelect 3063 -#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3064 -#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3065 -#define wxStyledTextCtrl_AutoCompSetFillUps 3066 -#define wxStyledTextCtrl_AutoCompSetChooseSingle 3067 -#define wxStyledTextCtrl_AutoCompGetChooseSingle 3068 -#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3069 -#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3070 -#define wxStyledTextCtrl_UserListShow 3071 -#define wxStyledTextCtrl_AutoCompSetAutoHide 3072 -#define wxStyledTextCtrl_AutoCompGetAutoHide 3073 -#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3074 -#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3075 -#define wxStyledTextCtrl_RegisterImage 3076 -#define wxStyledTextCtrl_ClearRegisteredImages 3077 -#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3078 -#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3079 -#define wxStyledTextCtrl_AutoCompSetMaxWidth 3080 -#define wxStyledTextCtrl_AutoCompGetMaxWidth 3081 -#define wxStyledTextCtrl_AutoCompSetMaxHeight 3082 -#define wxStyledTextCtrl_AutoCompGetMaxHeight 3083 -#define wxStyledTextCtrl_SetIndent 3084 -#define wxStyledTextCtrl_GetIndent 3085 -#define wxStyledTextCtrl_SetUseTabs 3086 -#define wxStyledTextCtrl_GetUseTabs 3087 -#define wxStyledTextCtrl_SetLineIndentation 3088 -#define wxStyledTextCtrl_GetLineIndentation 3089 -#define wxStyledTextCtrl_GetLineIndentPosition 3090 -#define wxStyledTextCtrl_GetColumn 3091 -#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3092 -#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3093 -#define wxStyledTextCtrl_SetIndentationGuides 3094 -#define wxStyledTextCtrl_GetIndentationGuides 3095 -#define wxStyledTextCtrl_SetHighlightGuide 3096 -#define wxStyledTextCtrl_GetHighlightGuide 3097 -#define wxStyledTextCtrl_GetLineEndPosition 3098 -#define wxStyledTextCtrl_GetCodePage 3099 -#define wxStyledTextCtrl_GetCaretForeground 3100 -#define wxStyledTextCtrl_GetReadOnly 3101 -#define wxStyledTextCtrl_SetCurrentPos 3102 -#define wxStyledTextCtrl_SetSelectionStart 3103 -#define wxStyledTextCtrl_GetSelectionStart 3104 -#define wxStyledTextCtrl_SetSelectionEnd 3105 -#define wxStyledTextCtrl_GetSelectionEnd 3106 -#define wxStyledTextCtrl_SetPrintMagnification 3107 -#define wxStyledTextCtrl_GetPrintMagnification 3108 -#define wxStyledTextCtrl_SetPrintColourMode 3109 -#define wxStyledTextCtrl_GetPrintColourMode 3110 -#define wxStyledTextCtrl_FindText 3111 -#define wxStyledTextCtrl_FormatRange 3112 -#define wxStyledTextCtrl_GetFirstVisibleLine 3113 -#define wxStyledTextCtrl_GetLine 3114 -#define wxStyledTextCtrl_GetLineCount 3115 -#define wxStyledTextCtrl_SetMarginLeft 3116 -#define wxStyledTextCtrl_GetMarginLeft 3117 -#define wxStyledTextCtrl_SetMarginRight 3118 -#define wxStyledTextCtrl_GetMarginRight 3119 -#define wxStyledTextCtrl_GetModify 3120 -#define wxStyledTextCtrl_SetSelection 3121 -#define wxStyledTextCtrl_GetSelectedText 3122 -#define wxStyledTextCtrl_GetTextRange 3123 -#define wxStyledTextCtrl_HideSelection 3124 -#define wxStyledTextCtrl_LineFromPosition 3125 -#define wxStyledTextCtrl_PositionFromLine 3126 -#define wxStyledTextCtrl_LineScroll 3127 -#define wxStyledTextCtrl_EnsureCaretVisible 3128 -#define wxStyledTextCtrl_ReplaceSelection 3129 -#define wxStyledTextCtrl_SetReadOnly 3130 -#define wxStyledTextCtrl_CanPaste 3131 -#define wxStyledTextCtrl_CanUndo 3132 -#define wxStyledTextCtrl_EmptyUndoBuffer 3133 -#define wxStyledTextCtrl_Undo 3134 -#define wxStyledTextCtrl_Cut 3135 -#define wxStyledTextCtrl_Copy 3136 -#define wxStyledTextCtrl_Paste 3137 -#define wxStyledTextCtrl_Clear 3138 -#define wxStyledTextCtrl_SetText 3139 -#define wxStyledTextCtrl_GetText 3140 -#define wxStyledTextCtrl_GetTextLength 3141 -#define wxStyledTextCtrl_GetOvertype 3142 -#define wxStyledTextCtrl_SetCaretWidth 3143 -#define wxStyledTextCtrl_GetCaretWidth 3144 -#define wxStyledTextCtrl_SetTargetStart 3145 -#define wxStyledTextCtrl_GetTargetStart 3146 -#define wxStyledTextCtrl_SetTargetEnd 3147 -#define wxStyledTextCtrl_GetTargetEnd 3148 -#define wxStyledTextCtrl_ReplaceTarget 3149 -#define wxStyledTextCtrl_SearchInTarget 3150 -#define wxStyledTextCtrl_SetSearchFlags 3151 -#define wxStyledTextCtrl_GetSearchFlags 3152 -#define wxStyledTextCtrl_CallTipShow 3153 -#define wxStyledTextCtrl_CallTipCancel 3154 -#define wxStyledTextCtrl_CallTipActive 3155 -#define wxStyledTextCtrl_CallTipPosAtStart 3156 -#define wxStyledTextCtrl_CallTipSetHighlight 3157 -#define wxStyledTextCtrl_CallTipSetBackground 3158 -#define wxStyledTextCtrl_CallTipSetForeground 3159 -#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3160 -#define wxStyledTextCtrl_CallTipUseStyle 3161 -#define wxStyledTextCtrl_VisibleFromDocLine 3162 -#define wxStyledTextCtrl_DocLineFromVisible 3163 -#define wxStyledTextCtrl_WrapCount 3164 -#define wxStyledTextCtrl_SetFoldLevel 3165 -#define wxStyledTextCtrl_GetFoldLevel 3166 -#define wxStyledTextCtrl_GetLastChild 3167 -#define wxStyledTextCtrl_GetFoldParent 3168 -#define wxStyledTextCtrl_ShowLines 3169 -#define wxStyledTextCtrl_HideLines 3170 -#define wxStyledTextCtrl_GetLineVisible 3171 -#define wxStyledTextCtrl_SetFoldExpanded 3172 -#define wxStyledTextCtrl_GetFoldExpanded 3173 -#define wxStyledTextCtrl_ToggleFold 3174 -#define wxStyledTextCtrl_EnsureVisible 3175 -#define wxStyledTextCtrl_SetFoldFlags 3176 -#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3177 -#define wxStyledTextCtrl_SetTabIndents 3178 -#define wxStyledTextCtrl_GetTabIndents 3179 -#define wxStyledTextCtrl_SetBackSpaceUnIndents 3180 -#define wxStyledTextCtrl_GetBackSpaceUnIndents 3181 -#define wxStyledTextCtrl_SetMouseDwellTime 3182 -#define wxStyledTextCtrl_GetMouseDwellTime 3183 -#define wxStyledTextCtrl_WordStartPosition 3184 -#define wxStyledTextCtrl_WordEndPosition 3185 -#define wxStyledTextCtrl_SetWrapMode 3186 -#define wxStyledTextCtrl_GetWrapMode 3187 -#define wxStyledTextCtrl_SetWrapVisualFlags 3188 -#define wxStyledTextCtrl_GetWrapVisualFlags 3189 -#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3190 -#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3191 -#define wxStyledTextCtrl_SetWrapStartIndent 3192 -#define wxStyledTextCtrl_GetWrapStartIndent 3193 -#define wxStyledTextCtrl_SetLayoutCache 3194 -#define wxStyledTextCtrl_GetLayoutCache 3195 -#define wxStyledTextCtrl_SetScrollWidth 3196 -#define wxStyledTextCtrl_GetScrollWidth 3197 -#define wxStyledTextCtrl_TextWidth 3198 -#define wxStyledTextCtrl_GetEndAtLastLine 3199 -#define wxStyledTextCtrl_TextHeight 3200 -#define wxStyledTextCtrl_SetUseVerticalScrollBar 3201 -#define wxStyledTextCtrl_GetUseVerticalScrollBar 3202 -#define wxStyledTextCtrl_AppendText 3203 -#define wxStyledTextCtrl_GetTwoPhaseDraw 3204 -#define wxStyledTextCtrl_SetTwoPhaseDraw 3205 -#define wxStyledTextCtrl_TargetFromSelection 3206 -#define wxStyledTextCtrl_LinesJoin 3207 -#define wxStyledTextCtrl_LinesSplit 3208 -#define wxStyledTextCtrl_SetFoldMarginColour 3209 -#define wxStyledTextCtrl_SetFoldMarginHiColour 3210 -#define wxStyledTextCtrl_LineDown 3211 -#define wxStyledTextCtrl_LineDownExtend 3212 -#define wxStyledTextCtrl_LineUp 3213 -#define wxStyledTextCtrl_LineUpExtend 3214 -#define wxStyledTextCtrl_CharLeft 3215 -#define wxStyledTextCtrl_CharLeftExtend 3216 -#define wxStyledTextCtrl_CharRight 3217 -#define wxStyledTextCtrl_CharRightExtend 3218 -#define wxStyledTextCtrl_WordLeft 3219 -#define wxStyledTextCtrl_WordLeftExtend 3220 -#define wxStyledTextCtrl_WordRight 3221 -#define wxStyledTextCtrl_WordRightExtend 3222 -#define wxStyledTextCtrl_Home 3223 -#define wxStyledTextCtrl_HomeExtend 3224 -#define wxStyledTextCtrl_LineEnd 3225 -#define wxStyledTextCtrl_LineEndExtend 3226 -#define wxStyledTextCtrl_DocumentStart 3227 -#define wxStyledTextCtrl_DocumentStartExtend 3228 -#define wxStyledTextCtrl_DocumentEnd 3229 -#define wxStyledTextCtrl_DocumentEndExtend 3230 -#define wxStyledTextCtrl_PageUp 3231 -#define wxStyledTextCtrl_PageUpExtend 3232 -#define wxStyledTextCtrl_PageDown 3233 -#define wxStyledTextCtrl_PageDownExtend 3234 -#define wxStyledTextCtrl_EditToggleOvertype 3235 -#define wxStyledTextCtrl_Cancel 3236 -#define wxStyledTextCtrl_DeleteBack 3237 -#define wxStyledTextCtrl_Tab 3238 -#define wxStyledTextCtrl_BackTab 3239 -#define wxStyledTextCtrl_NewLine 3240 -#define wxStyledTextCtrl_FormFeed 3241 -#define wxStyledTextCtrl_VCHome 3242 -#define wxStyledTextCtrl_VCHomeExtend 3243 -#define wxStyledTextCtrl_ZoomIn 3244 -#define wxStyledTextCtrl_ZoomOut 3245 -#define wxStyledTextCtrl_DelWordLeft 3246 -#define wxStyledTextCtrl_DelWordRight 3247 -#define wxStyledTextCtrl_LineCut 3248 -#define wxStyledTextCtrl_LineDelete 3249 -#define wxStyledTextCtrl_LineTranspose 3250 -#define wxStyledTextCtrl_LineDuplicate 3251 -#define wxStyledTextCtrl_LowerCase 3252 -#define wxStyledTextCtrl_UpperCase 3253 -#define wxStyledTextCtrl_LineScrollDown 3254 -#define wxStyledTextCtrl_LineScrollUp 3255 -#define wxStyledTextCtrl_DeleteBackNotLine 3256 -#define wxStyledTextCtrl_HomeDisplay 3257 -#define wxStyledTextCtrl_HomeDisplayExtend 3258 -#define wxStyledTextCtrl_LineEndDisplay 3259 -#define wxStyledTextCtrl_LineEndDisplayExtend 3260 -#define wxStyledTextCtrl_HomeWrapExtend 3261 -#define wxStyledTextCtrl_LineEndWrap 3262 -#define wxStyledTextCtrl_LineEndWrapExtend 3263 -#define wxStyledTextCtrl_VCHomeWrap 3264 -#define wxStyledTextCtrl_VCHomeWrapExtend 3265 -#define wxStyledTextCtrl_LineCopy 3266 -#define wxStyledTextCtrl_MoveCaretInsideView 3267 -#define wxStyledTextCtrl_LineLength 3268 -#define wxStyledTextCtrl_BraceHighlight 3269 -#define wxStyledTextCtrl_BraceBadLight 3270 -#define wxStyledTextCtrl_BraceMatch 3271 -#define wxStyledTextCtrl_GetViewEOL 3272 -#define wxStyledTextCtrl_SetViewEOL 3273 -#define wxStyledTextCtrl_SetModEventMask 3274 -#define wxStyledTextCtrl_GetEdgeColumn 3275 -#define wxStyledTextCtrl_SetEdgeColumn 3276 -#define wxStyledTextCtrl_SetEdgeMode 3277 -#define wxStyledTextCtrl_GetEdgeMode 3278 -#define wxStyledTextCtrl_GetEdgeColour 3279 -#define wxStyledTextCtrl_SetEdgeColour 3280 -#define wxStyledTextCtrl_SearchAnchor 3281 -#define wxStyledTextCtrl_SearchNext 3282 -#define wxStyledTextCtrl_SearchPrev 3283 -#define wxStyledTextCtrl_LinesOnScreen 3284 -#define wxStyledTextCtrl_UsePopUp 3285 -#define wxStyledTextCtrl_SelectionIsRectangle 3286 -#define wxStyledTextCtrl_SetZoom 3287 -#define wxStyledTextCtrl_GetZoom 3288 -#define wxStyledTextCtrl_GetModEventMask 3289 -#define wxStyledTextCtrl_SetSTCFocus 3290 -#define wxStyledTextCtrl_GetSTCFocus 3291 -#define wxStyledTextCtrl_SetStatus 3292 -#define wxStyledTextCtrl_GetStatus 3293 -#define wxStyledTextCtrl_SetMouseDownCaptures 3294 -#define wxStyledTextCtrl_GetMouseDownCaptures 3295 -#define wxStyledTextCtrl_SetSTCCursor 3296 -#define wxStyledTextCtrl_GetSTCCursor 3297 -#define wxStyledTextCtrl_SetControlCharSymbol 3298 -#define wxStyledTextCtrl_GetControlCharSymbol 3299 -#define wxStyledTextCtrl_WordPartLeft 3300 -#define wxStyledTextCtrl_WordPartLeftExtend 3301 -#define wxStyledTextCtrl_WordPartRight 3302 -#define wxStyledTextCtrl_WordPartRightExtend 3303 -#define wxStyledTextCtrl_SetVisiblePolicy 3304 -#define wxStyledTextCtrl_DelLineLeft 3305 -#define wxStyledTextCtrl_DelLineRight 3306 -#define wxStyledTextCtrl_GetXOffset 3307 -#define wxStyledTextCtrl_ChooseCaretX 3308 -#define wxStyledTextCtrl_SetXCaretPolicy 3309 -#define wxStyledTextCtrl_SetYCaretPolicy 3310 -#define wxStyledTextCtrl_GetPrintWrapMode 3311 -#define wxStyledTextCtrl_SetHotspotActiveForeground 3312 -#define wxStyledTextCtrl_SetHotspotActiveBackground 3313 -#define wxStyledTextCtrl_SetHotspotActiveUnderline 3314 -#define wxStyledTextCtrl_SetHotspotSingleLine 3315 -#define wxStyledTextCtrl_ParaDownExtend 3316 -#define wxStyledTextCtrl_ParaUp 3317 -#define wxStyledTextCtrl_ParaUpExtend 3318 -#define wxStyledTextCtrl_PositionBefore 3319 -#define wxStyledTextCtrl_PositionAfter 3320 -#define wxStyledTextCtrl_CopyRange 3321 -#define wxStyledTextCtrl_CopyText 3322 -#define wxStyledTextCtrl_SetSelectionMode 3323 -#define wxStyledTextCtrl_GetSelectionMode 3324 -#define wxStyledTextCtrl_LineDownRectExtend 3325 -#define wxStyledTextCtrl_LineUpRectExtend 3326 -#define wxStyledTextCtrl_CharLeftRectExtend 3327 -#define wxStyledTextCtrl_CharRightRectExtend 3328 -#define wxStyledTextCtrl_HomeRectExtend 3329 -#define wxStyledTextCtrl_VCHomeRectExtend 3330 -#define wxStyledTextCtrl_LineEndRectExtend 3331 -#define wxStyledTextCtrl_PageUpRectExtend 3332 -#define wxStyledTextCtrl_PageDownRectExtend 3333 -#define wxStyledTextCtrl_StutteredPageUp 3334 -#define wxStyledTextCtrl_StutteredPageUpExtend 3335 -#define wxStyledTextCtrl_StutteredPageDown 3336 -#define wxStyledTextCtrl_StutteredPageDownExtend 3337 -#define wxStyledTextCtrl_WordLeftEnd 3338 -#define wxStyledTextCtrl_WordLeftEndExtend 3339 -#define wxStyledTextCtrl_WordRightEnd 3340 -#define wxStyledTextCtrl_WordRightEndExtend 3341 -#define wxStyledTextCtrl_SetWhitespaceChars 3342 -#define wxStyledTextCtrl_SetCharsDefault 3343 -#define wxStyledTextCtrl_AutoCompGetCurrent 3344 -#define wxStyledTextCtrl_Allocate 3345 -#define wxStyledTextCtrl_FindColumn 3346 -#define wxStyledTextCtrl_GetCaretSticky 3347 -#define wxStyledTextCtrl_SetCaretSticky 3348 -#define wxStyledTextCtrl_ToggleCaretSticky 3349 -#define wxStyledTextCtrl_SetPasteConvertEndings 3350 -#define wxStyledTextCtrl_GetPasteConvertEndings 3351 -#define wxStyledTextCtrl_SelectionDuplicate 3352 -#define wxStyledTextCtrl_SetCaretLineBackAlpha 3353 -#define wxStyledTextCtrl_GetCaretLineBackAlpha 3354 -#define wxStyledTextCtrl_StartRecord 3355 -#define wxStyledTextCtrl_StopRecord 3356 -#define wxStyledTextCtrl_SetLexer 3357 -#define wxStyledTextCtrl_GetLexer 3358 -#define wxStyledTextCtrl_Colourise 3359 -#define wxStyledTextCtrl_SetProperty 3360 -#define wxStyledTextCtrl_SetKeyWords 3361 -#define wxStyledTextCtrl_SetLexerLanguage 3362 -#define wxStyledTextCtrl_GetProperty 3363 -#define wxStyledTextCtrl_GetStyleBitsNeeded 3364 -#define wxStyledTextCtrl_GetCurrentLine 3365 -#define wxStyledTextCtrl_StyleSetSpec 3366 -#define wxStyledTextCtrl_StyleSetFont 3367 -#define wxStyledTextCtrl_StyleSetFontAttr 3368 -#define wxStyledTextCtrl_StyleSetCharacterSet 3369 -#define wxStyledTextCtrl_StyleSetFontEncoding 3370 -#define wxStyledTextCtrl_CmdKeyExecute 3371 -#define wxStyledTextCtrl_SetMargins 3372 -#define wxStyledTextCtrl_GetSelection 3373 -#define wxStyledTextCtrl_PointFromPosition 3374 -#define wxStyledTextCtrl_ScrollToLine 3375 -#define wxStyledTextCtrl_ScrollToColumn 3376 -#define wxStyledTextCtrl_SetVScrollBar 3377 -#define wxStyledTextCtrl_SetHScrollBar 3378 -#define wxStyledTextCtrl_GetLastKeydownProcessed 3379 -#define wxStyledTextCtrl_SetLastKeydownProcessed 3380 -#define wxStyledTextCtrl_SaveFile 3381 -#define wxStyledTextCtrl_LoadFile 3382 -#define wxStyledTextCtrl_DoDragOver 3383 -#define wxStyledTextCtrl_DoDropText 3384 -#define wxStyledTextCtrl_GetUseAntiAliasing 3385 -#define wxStyledTextCtrl_AddTextRaw 3386 -#define wxStyledTextCtrl_InsertTextRaw 3387 -#define wxStyledTextCtrl_GetCurLineRaw 3388 -#define wxStyledTextCtrl_GetLineRaw 3389 -#define wxStyledTextCtrl_GetSelectedTextRaw 3390 -#define wxStyledTextCtrl_GetTextRangeRaw 3391 -#define wxStyledTextCtrl_SetTextRaw 3392 -#define wxStyledTextCtrl_GetTextRaw 3393 -#define wxStyledTextCtrl_AppendTextRaw 3394 -#define wxArtProvider_GetBitmap 3395 -#define wxArtProvider_GetIcon 3396 -#define wxTreeEvent_GetKeyCode 3397 -#define wxTreeEvent_GetItem 3398 -#define wxTreeEvent_GetKeyEvent 3399 -#define wxTreeEvent_GetLabel 3400 -#define wxTreeEvent_GetOldItem 3401 -#define wxTreeEvent_GetPoint 3402 -#define wxTreeEvent_IsEditCancelled 3403 -#define wxTreeEvent_SetToolTip 3404 -#define wxNotebookEvent_GetOldSelection 3405 -#define wxNotebookEvent_GetSelection 3406 -#define wxNotebookEvent_SetOldSelection 3407 -#define wxNotebookEvent_SetSelection 3408 -#define wxFileDataObject_new 3409 -#define wxFileDataObject_AddFile 3410 -#define wxFileDataObject_GetFilenames 3411 -#define wxFileDataObject_destroy 3412 -#define wxTextDataObject_new 3413 -#define wxTextDataObject_GetTextLength 3414 -#define wxTextDataObject_GetText 3415 -#define wxTextDataObject_SetText 3416 -#define wxTextDataObject_destroy 3417 -#define wxBitmapDataObject_new_1_1 3418 -#define wxBitmapDataObject_new_1_0 3419 -#define wxBitmapDataObject_GetBitmap 3420 -#define wxBitmapDataObject_SetBitmap 3421 -#define wxBitmapDataObject_destroy 3422 -#define wxClipboard_new 3424 -#define wxClipboard_destruct 3425 -#define wxClipboard_AddData 3426 -#define wxClipboard_Clear 3427 -#define wxClipboard_Close 3428 -#define wxClipboard_Flush 3429 -#define wxClipboard_GetData 3430 -#define wxClipboard_IsOpened 3431 -#define wxClipboard_Open 3432 -#define wxClipboard_SetData 3433 -#define wxClipboard_UsePrimarySelection 3435 -#define wxClipboard_IsSupported 3436 -#define wxClipboard_Get 3437 -#define wxSpinEvent_GetPosition 3438 -#define wxSpinEvent_SetPosition 3439 -#define wxSplitterWindow_new_0 3440 -#define wxSplitterWindow_new_2 3441 -#define wxSplitterWindow_destruct 3442 -#define wxSplitterWindow_Create 3443 -#define wxSplitterWindow_GetMinimumPaneSize 3444 -#define wxSplitterWindow_GetSashGravity 3445 -#define wxSplitterWindow_GetSashPosition 3446 -#define wxSplitterWindow_GetSplitMode 3447 -#define wxSplitterWindow_GetWindow1 3448 -#define wxSplitterWindow_GetWindow2 3449 -#define wxSplitterWindow_Initialize 3450 -#define wxSplitterWindow_IsSplit 3451 -#define wxSplitterWindow_ReplaceWindow 3452 -#define wxSplitterWindow_SetSashGravity 3453 -#define wxSplitterWindow_SetSashPosition 3454 -#define wxSplitterWindow_SetSashSize 3455 -#define wxSplitterWindow_SetMinimumPaneSize 3456 -#define wxSplitterWindow_SetSplitMode 3457 -#define wxSplitterWindow_SplitHorizontally 3458 -#define wxSplitterWindow_SplitVertically 3459 -#define wxSplitterWindow_Unsplit 3460 -#define wxSplitterWindow_UpdateSize 3461 -#define wxSplitterEvent_GetSashPosition 3462 -#define wxSplitterEvent_GetX 3463 -#define wxSplitterEvent_GetY 3464 -#define wxSplitterEvent_GetWindowBeingRemoved 3465 -#define wxSplitterEvent_SetSashPosition 3466 -#define wxHtmlWindow_new_0 3467 -#define wxHtmlWindow_new_2 3468 -#define wxHtmlWindow_AppendToPage 3469 -#define wxHtmlWindow_GetOpenedAnchor 3470 -#define wxHtmlWindow_GetOpenedPage 3471 -#define wxHtmlWindow_GetOpenedPageTitle 3472 -#define wxHtmlWindow_GetRelatedFrame 3473 -#define wxHtmlWindow_HistoryBack 3474 -#define wxHtmlWindow_HistoryCanBack 3475 -#define wxHtmlWindow_HistoryCanForward 3476 -#define wxHtmlWindow_HistoryClear 3477 -#define wxHtmlWindow_HistoryForward 3478 -#define wxHtmlWindow_LoadFile 3479 -#define wxHtmlWindow_LoadPage 3480 -#define wxHtmlWindow_SelectAll 3481 -#define wxHtmlWindow_SelectionToText 3482 -#define wxHtmlWindow_SelectLine 3483 -#define wxHtmlWindow_SelectWord 3484 -#define wxHtmlWindow_SetBorders 3485 -#define wxHtmlWindow_SetFonts 3486 -#define wxHtmlWindow_SetPage 3487 -#define wxHtmlWindow_SetRelatedFrame 3488 -#define wxHtmlWindow_SetRelatedStatusBar 3489 -#define wxHtmlWindow_ToText 3490 -#define wxHtmlWindow_destroy 3491 -#define wxHtmlLinkEvent_GetLinkInfo 3492 -#define wxSystemSettings_GetColour 3493 -#define wxSystemSettings_GetFont 3494 -#define wxSystemSettings_GetMetric 3495 -#define wxSystemSettings_GetScreenType 3496 -#define wxSystemOptions_GetOption 3497 -#define wxSystemOptions_GetOptionInt 3498 -#define wxSystemOptions_HasOption 3499 -#define wxSystemOptions_IsFalse 3500 -#define wxSystemOptions_SetOption_2_1 3501 -#define wxSystemOptions_SetOption_2_0 3502 -#define wxAuiNotebookEvent_SetSelection 3503 -#define wxAuiNotebookEvent_GetSelection 3504 -#define wxAuiNotebookEvent_SetOldSelection 3505 -#define wxAuiNotebookEvent_GetOldSelection 3506 -#define wxAuiNotebookEvent_SetDragSource 3507 -#define wxAuiNotebookEvent_GetDragSource 3508 -#define wxAuiManagerEvent_SetManager 3509 -#define wxAuiManagerEvent_GetManager 3510 -#define wxAuiManagerEvent_SetPane 3511 -#define wxAuiManagerEvent_GetPane 3512 -#define wxAuiManagerEvent_SetButton 3513 -#define wxAuiManagerEvent_GetButton 3514 -#define wxAuiManagerEvent_SetDC 3515 -#define wxAuiManagerEvent_GetDC 3516 -#define wxAuiManagerEvent_Veto 3517 -#define wxAuiManagerEvent_GetVeto 3518 -#define wxAuiManagerEvent_SetCanVeto 3519 -#define wxAuiManagerEvent_CanVeto 3520 -#define wxLogNull_new 3521 -#define wxLogNull_destroy 3522 -#define wxTaskBarIcon_new 3523 -#define wxTaskBarIcon_destruct 3524 -#define wxTaskBarIcon_PopupMenu 3525 -#define wxTaskBarIcon_RemoveIcon 3526 -#define wxTaskBarIcon_SetIcon 3527 -#define wxLocale_new_0 3528 -#define wxLocale_new_2 3530 -#define wxLocale_destruct 3531 -#define wxLocale_Init 3533 -#define wxLocale_AddCatalog_1 3534 -#define wxLocale_AddCatalog_3 3535 -#define wxLocale_AddCatalogLookupPathPrefix 3536 -#define wxLocale_GetCanonicalName 3537 -#define wxLocale_GetLanguage 3538 -#define wxLocale_GetLanguageName 3539 -#define wxLocale_GetLocale 3540 -#define wxLocale_GetName 3541 -#define wxLocale_GetString_2 3542 -#define wxLocale_GetString_4 3543 -#define wxLocale_GetHeaderValue 3544 -#define wxLocale_GetSysName 3545 -#define wxLocale_GetSystemEncoding 3546 -#define wxLocale_GetSystemEncodingName 3547 -#define wxLocale_GetSystemLanguage 3548 -#define wxLocale_IsLoaded 3549 -#define wxLocale_IsOk 3550 -#define wxActivateEvent_GetActive 3551 -#define wxPopupWindow_new_2 3553 -#define wxPopupWindow_new_0 3554 -#define wxPopupWindow_destruct 3556 -#define wxPopupWindow_Create 3557 -#define wxPopupWindow_Position 3558 -#define wxPopupTransientWindow_new_0 3559 -#define wxPopupTransientWindow_new_2 3560 -#define wxPopupTransientWindow_destruct 3561 -#define wxPopupTransientWindow_Popup 3562 -#define wxPopupTransientWindow_Dismiss 3563 +#define wxAuiPaneInfo_GetWindow 2653 +#define wxAuiPaneInfo_GetFrame 2654 +#define wxAuiPaneInfo_GetDirection 2655 +#define wxAuiPaneInfo_GetLayer 2656 +#define wxAuiPaneInfo_GetRow 2657 +#define wxAuiPaneInfo_GetPosition 2658 +#define wxAuiPaneInfo_GetFloatingPosition 2659 +#define wxAuiPaneInfo_GetFloatingSize 2660 +#define wxAuiNotebook_new_0 2661 +#define wxAuiNotebook_new_2 2662 +#define wxAuiNotebook_AddPage 2663 +#define wxAuiNotebook_Create 2664 +#define wxAuiNotebook_DeletePage 2665 +#define wxAuiNotebook_GetArtProvider 2666 +#define wxAuiNotebook_GetPage 2667 +#define wxAuiNotebook_GetPageBitmap 2668 +#define wxAuiNotebook_GetPageCount 2669 +#define wxAuiNotebook_GetPageIndex 2670 +#define wxAuiNotebook_GetPageText 2671 +#define wxAuiNotebook_GetSelection 2672 +#define wxAuiNotebook_InsertPage 2673 +#define wxAuiNotebook_RemovePage 2674 +#define wxAuiNotebook_SetArtProvider 2675 +#define wxAuiNotebook_SetFont 2676 +#define wxAuiNotebook_SetPageBitmap 2677 +#define wxAuiNotebook_SetPageText 2678 +#define wxAuiNotebook_SetSelection 2679 +#define wxAuiNotebook_SetTabCtrlHeight 2680 +#define wxAuiNotebook_SetUniformBitmapSize 2681 +#define wxAuiNotebook_destroy 2682 +#define wxAuiTabArt_SetFlags 2683 +#define wxAuiTabArt_SetMeasuringFont 2684 +#define wxAuiTabArt_SetNormalFont 2685 +#define wxAuiTabArt_SetSelectedFont 2686 +#define wxAuiTabArt_SetColour 2687 +#define wxAuiTabArt_SetActiveColour 2688 +#define wxAuiDockArt_GetColour 2689 +#define wxAuiDockArt_GetFont 2690 +#define wxAuiDockArt_GetMetric 2691 +#define wxAuiDockArt_SetColour 2692 +#define wxAuiDockArt_SetFont 2693 +#define wxAuiDockArt_SetMetric 2694 +#define wxAuiSimpleTabArt_new 2695 +#define wxAuiSimpleTabArt_destroy 2696 +#define wxMDIParentFrame_new_0 2697 +#define wxMDIParentFrame_new_4 2698 +#define wxMDIParentFrame_destruct 2699 +#define wxMDIParentFrame_ActivateNext 2700 +#define wxMDIParentFrame_ActivatePrevious 2701 +#define wxMDIParentFrame_ArrangeIcons 2702 +#define wxMDIParentFrame_Cascade 2703 +#define wxMDIParentFrame_Create 2704 +#define wxMDIParentFrame_GetActiveChild 2705 +#define wxMDIParentFrame_GetClientWindow 2706 +#define wxMDIParentFrame_Tile 2707 +#define wxMDIChildFrame_new_0 2708 +#define wxMDIChildFrame_new_4 2709 +#define wxMDIChildFrame_destruct 2710 +#define wxMDIChildFrame_Activate 2711 +#define wxMDIChildFrame_Create 2712 +#define wxMDIChildFrame_Maximize 2713 +#define wxMDIChildFrame_Restore 2714 +#define wxMDIClientWindow_new_0 2715 +#define wxMDIClientWindow_new_2 2716 +#define wxMDIClientWindow_destruct 2717 +#define wxMDIClientWindow_CreateClient 2718 +#define wxLayoutAlgorithm_new 2719 +#define wxLayoutAlgorithm_LayoutFrame 2720 +#define wxLayoutAlgorithm_LayoutMDIFrame 2721 +#define wxLayoutAlgorithm_LayoutWindow 2722 +#define wxLayoutAlgorithm_destroy 2723 +#define wxEvent_GetId 2724 +#define wxEvent_GetSkipped 2725 +#define wxEvent_GetTimestamp 2726 +#define wxEvent_IsCommandEvent 2727 +#define wxEvent_ResumePropagation 2728 +#define wxEvent_ShouldPropagate 2729 +#define wxEvent_Skip 2730 +#define wxEvent_StopPropagation 2731 +#define wxCommandEvent_getClientData 2732 +#define wxCommandEvent_GetExtraLong 2733 +#define wxCommandEvent_GetInt 2734 +#define wxCommandEvent_GetSelection 2735 +#define wxCommandEvent_GetString 2736 +#define wxCommandEvent_IsChecked 2737 +#define wxCommandEvent_IsSelection 2738 +#define wxCommandEvent_SetInt 2739 +#define wxCommandEvent_SetString 2740 +#define wxScrollEvent_GetOrientation 2741 +#define wxScrollEvent_GetPosition 2742 +#define wxScrollWinEvent_GetOrientation 2743 +#define wxScrollWinEvent_GetPosition 2744 +#define wxMouseEvent_AltDown 2745 +#define wxMouseEvent_Button 2746 +#define wxMouseEvent_ButtonDClick 2747 +#define wxMouseEvent_ButtonDown 2748 +#define wxMouseEvent_ButtonUp 2749 +#define wxMouseEvent_CmdDown 2750 +#define wxMouseEvent_ControlDown 2751 +#define wxMouseEvent_Dragging 2752 +#define wxMouseEvent_Entering 2753 +#define wxMouseEvent_GetButton 2754 +#define wxMouseEvent_GetPosition 2757 +#define wxMouseEvent_GetLogicalPosition 2758 +#define wxMouseEvent_GetLinesPerAction 2759 +#define wxMouseEvent_GetWheelRotation 2760 +#define wxMouseEvent_GetWheelDelta 2761 +#define wxMouseEvent_GetX 2762 +#define wxMouseEvent_GetY 2763 +#define wxMouseEvent_IsButton 2764 +#define wxMouseEvent_IsPageScroll 2765 +#define wxMouseEvent_Leaving 2766 +#define wxMouseEvent_LeftDClick 2767 +#define wxMouseEvent_LeftDown 2768 +#define wxMouseEvent_LeftIsDown 2769 +#define wxMouseEvent_LeftUp 2770 +#define wxMouseEvent_MetaDown 2771 +#define wxMouseEvent_MiddleDClick 2772 +#define wxMouseEvent_MiddleDown 2773 +#define wxMouseEvent_MiddleIsDown 2774 +#define wxMouseEvent_MiddleUp 2775 +#define wxMouseEvent_Moving 2776 +#define wxMouseEvent_RightDClick 2777 +#define wxMouseEvent_RightDown 2778 +#define wxMouseEvent_RightIsDown 2779 +#define wxMouseEvent_RightUp 2780 +#define wxMouseEvent_ShiftDown 2781 +#define wxSetCursorEvent_GetCursor 2782 +#define wxSetCursorEvent_GetX 2783 +#define wxSetCursorEvent_GetY 2784 +#define wxSetCursorEvent_HasCursor 2785 +#define wxSetCursorEvent_SetCursor 2786 +#define wxKeyEvent_AltDown 2787 +#define wxKeyEvent_CmdDown 2788 +#define wxKeyEvent_ControlDown 2789 +#define wxKeyEvent_GetKeyCode 2790 +#define wxKeyEvent_GetModifiers 2791 +#define wxKeyEvent_GetPosition 2794 +#define wxKeyEvent_GetRawKeyCode 2795 +#define wxKeyEvent_GetRawKeyFlags 2796 +#define wxKeyEvent_GetUnicodeKey 2797 +#define wxKeyEvent_GetX 2798 +#define wxKeyEvent_GetY 2799 +#define wxKeyEvent_HasModifiers 2800 +#define wxKeyEvent_MetaDown 2801 +#define wxKeyEvent_ShiftDown 2802 +#define wxSizeEvent_GetSize 2803 +#define wxMoveEvent_GetPosition 2804 +#define wxEraseEvent_GetDC 2805 +#define wxFocusEvent_GetWindow 2806 +#define wxChildFocusEvent_GetWindow 2807 +#define wxMenuEvent_GetMenu 2808 +#define wxMenuEvent_GetMenuId 2809 +#define wxMenuEvent_IsPopup 2810 +#define wxCloseEvent_CanVeto 2811 +#define wxCloseEvent_GetLoggingOff 2812 +#define wxCloseEvent_SetCanVeto 2813 +#define wxCloseEvent_SetLoggingOff 2814 +#define wxCloseEvent_Veto 2815 +#define wxShowEvent_SetShow 2816 +#define wxShowEvent_GetShow 2817 +#define wxIconizeEvent_Iconized 2818 +#define wxJoystickEvent_ButtonDown 2819 +#define wxJoystickEvent_ButtonIsDown 2820 +#define wxJoystickEvent_ButtonUp 2821 +#define wxJoystickEvent_GetButtonChange 2822 +#define wxJoystickEvent_GetButtonState 2823 +#define wxJoystickEvent_GetJoystick 2824 +#define wxJoystickEvent_GetPosition 2825 +#define wxJoystickEvent_GetZPosition 2826 +#define wxJoystickEvent_IsButton 2827 +#define wxJoystickEvent_IsMove 2828 +#define wxJoystickEvent_IsZMove 2829 +#define wxUpdateUIEvent_CanUpdate 2830 +#define wxUpdateUIEvent_Check 2831 +#define wxUpdateUIEvent_Enable 2832 +#define wxUpdateUIEvent_Show 2833 +#define wxUpdateUIEvent_GetChecked 2834 +#define wxUpdateUIEvent_GetEnabled 2835 +#define wxUpdateUIEvent_GetShown 2836 +#define wxUpdateUIEvent_GetSetChecked 2837 +#define wxUpdateUIEvent_GetSetEnabled 2838 +#define wxUpdateUIEvent_GetSetShown 2839 +#define wxUpdateUIEvent_GetSetText 2840 +#define wxUpdateUIEvent_GetText 2841 +#define wxUpdateUIEvent_GetMode 2842 +#define wxUpdateUIEvent_GetUpdateInterval 2843 +#define wxUpdateUIEvent_ResetUpdateTime 2844 +#define wxUpdateUIEvent_SetMode 2845 +#define wxUpdateUIEvent_SetText 2846 +#define wxUpdateUIEvent_SetUpdateInterval 2847 +#define wxMouseCaptureChangedEvent_GetCapturedWindow 2848 +#define wxPaletteChangedEvent_SetChangedWindow 2849 +#define wxPaletteChangedEvent_GetChangedWindow 2850 +#define wxQueryNewPaletteEvent_SetPaletteRealized 2851 +#define wxQueryNewPaletteEvent_GetPaletteRealized 2852 +#define wxNavigationKeyEvent_GetDirection 2853 +#define wxNavigationKeyEvent_SetDirection 2854 +#define wxNavigationKeyEvent_IsWindowChange 2855 +#define wxNavigationKeyEvent_SetWindowChange 2856 +#define wxNavigationKeyEvent_IsFromTab 2857 +#define wxNavigationKeyEvent_SetFromTab 2858 +#define wxNavigationKeyEvent_GetCurrentFocus 2859 +#define wxNavigationKeyEvent_SetCurrentFocus 2860 +#define wxHelpEvent_GetOrigin 2861 +#define wxHelpEvent_GetPosition 2862 +#define wxHelpEvent_SetOrigin 2863 +#define wxHelpEvent_SetPosition 2864 +#define wxContextMenuEvent_GetPosition 2865 +#define wxContextMenuEvent_SetPosition 2866 +#define wxIdleEvent_CanSend 2867 +#define wxIdleEvent_GetMode 2868 +#define wxIdleEvent_RequestMore 2869 +#define wxIdleEvent_MoreRequested 2870 +#define wxIdleEvent_SetMode 2871 +#define wxGridEvent_AltDown 2872 +#define wxGridEvent_ControlDown 2873 +#define wxGridEvent_GetCol 2874 +#define wxGridEvent_GetPosition 2875 +#define wxGridEvent_GetRow 2876 +#define wxGridEvent_MetaDown 2877 +#define wxGridEvent_Selecting 2878 +#define wxGridEvent_ShiftDown 2879 +#define wxNotifyEvent_Allow 2880 +#define wxNotifyEvent_IsAllowed 2881 +#define wxNotifyEvent_Veto 2882 +#define wxSashEvent_GetEdge 2883 +#define wxSashEvent_GetDragRect 2884 +#define wxSashEvent_GetDragStatus 2885 +#define wxListEvent_GetCacheFrom 2886 +#define wxListEvent_GetCacheTo 2887 +#define wxListEvent_GetKeyCode 2888 +#define wxListEvent_GetIndex 2889 +#define wxListEvent_GetColumn 2890 +#define wxListEvent_GetPoint 2891 +#define wxListEvent_GetLabel 2892 +#define wxListEvent_GetText 2893 +#define wxListEvent_GetImage 2894 +#define wxListEvent_GetData 2895 +#define wxListEvent_GetMask 2896 +#define wxListEvent_GetItem 2897 +#define wxListEvent_IsEditCancelled 2898 +#define wxDateEvent_GetDate 2899 +#define wxCalendarEvent_GetWeekDay 2900 +#define wxFileDirPickerEvent_GetPath 2901 +#define wxColourPickerEvent_GetColour 2902 +#define wxFontPickerEvent_GetFont 2903 +#define wxStyledTextEvent_GetPosition 2904 +#define wxStyledTextEvent_GetKey 2905 +#define wxStyledTextEvent_GetModifiers 2906 +#define wxStyledTextEvent_GetModificationType 2907 +#define wxStyledTextEvent_GetText 2908 +#define wxStyledTextEvent_GetLength 2909 +#define wxStyledTextEvent_GetLinesAdded 2910 +#define wxStyledTextEvent_GetLine 2911 +#define wxStyledTextEvent_GetFoldLevelNow 2912 +#define wxStyledTextEvent_GetFoldLevelPrev 2913 +#define wxStyledTextEvent_GetMargin 2914 +#define wxStyledTextEvent_GetMessage 2915 +#define wxStyledTextEvent_GetWParam 2916 +#define wxStyledTextEvent_GetLParam 2917 +#define wxStyledTextEvent_GetListType 2918 +#define wxStyledTextEvent_GetX 2919 +#define wxStyledTextEvent_GetY 2920 +#define wxStyledTextEvent_GetDragText 2921 +#define wxStyledTextEvent_GetDragAllowMove 2922 +#define wxStyledTextEvent_GetDragResult 2923 +#define wxStyledTextEvent_GetShift 2924 +#define wxStyledTextEvent_GetControl 2925 +#define wxStyledTextEvent_GetAlt 2926 +#define utils_wxGetKeyState 2927 +#define utils_wxGetMousePosition 2928 +#define utils_wxGetMouseState 2929 +#define utils_wxSetDetectableAutoRepeat 2930 +#define utils_wxBell 2931 +#define utils_wxFindMenuItemId 2932 +#define utils_wxGenericFindWindowAtPoint 2933 +#define utils_wxFindWindowAtPoint 2934 +#define utils_wxBeginBusyCursor 2935 +#define utils_wxEndBusyCursor 2936 +#define utils_wxIsBusy 2937 +#define utils_wxShutdown 2938 +#define utils_wxShell 2939 +#define utils_wxLaunchDefaultBrowser 2940 +#define utils_wxGetEmailAddress 2941 +#define utils_wxGetUserId 2942 +#define utils_wxGetHomeDir 2943 +#define utils_wxNewId 2944 +#define utils_wxRegisterId 2945 +#define utils_wxGetCurrentId 2946 +#define utils_wxGetOsDescription 2947 +#define utils_wxIsPlatformLittleEndian 2948 +#define utils_wxIsPlatform64Bit 2949 +#define gdicmn_wxDisplaySize 2950 +#define gdicmn_wxSetCursor 2951 +#define wxPrintout_new 2952 +#define wxPrintout_destruct 2953 +#define wxPrintout_GetDC 2954 +#define wxPrintout_GetPageSizeMM 2955 +#define wxPrintout_GetPageSizePixels 2956 +#define wxPrintout_GetPaperRectPixels 2957 +#define wxPrintout_GetPPIPrinter 2958 +#define wxPrintout_GetPPIScreen 2959 +#define wxPrintout_GetTitle 2960 +#define wxPrintout_IsPreview 2961 +#define wxPrintout_FitThisSizeToPaper 2962 +#define wxPrintout_FitThisSizeToPage 2963 +#define wxPrintout_FitThisSizeToPageMargins 2964 +#define wxPrintout_MapScreenSizeToPaper 2965 +#define wxPrintout_MapScreenSizeToPage 2966 +#define wxPrintout_MapScreenSizeToPageMargins 2967 +#define wxPrintout_MapScreenSizeToDevice 2968 +#define wxPrintout_GetLogicalPaperRect 2969 +#define wxPrintout_GetLogicalPageRect 2970 +#define wxPrintout_GetLogicalPageMarginsRect 2971 +#define wxPrintout_SetLogicalOrigin 2972 +#define wxPrintout_OffsetLogicalOrigin 2973 +#define wxStyledTextCtrl_new_2 2974 +#define wxStyledTextCtrl_new_0 2975 +#define wxStyledTextCtrl_destruct 2976 +#define wxStyledTextCtrl_Create 2977 +#define wxStyledTextCtrl_AddText 2978 +#define wxStyledTextCtrl_AddStyledText 2979 +#define wxStyledTextCtrl_InsertText 2980 +#define wxStyledTextCtrl_ClearAll 2981 +#define wxStyledTextCtrl_ClearDocumentStyle 2982 +#define wxStyledTextCtrl_GetLength 2983 +#define wxStyledTextCtrl_GetCharAt 2984 +#define wxStyledTextCtrl_GetCurrentPos 2985 +#define wxStyledTextCtrl_GetAnchor 2986 +#define wxStyledTextCtrl_GetStyleAt 2987 +#define wxStyledTextCtrl_Redo 2988 +#define wxStyledTextCtrl_SetUndoCollection 2989 +#define wxStyledTextCtrl_SelectAll 2990 +#define wxStyledTextCtrl_SetSavePoint 2991 +#define wxStyledTextCtrl_GetStyledText 2992 +#define wxStyledTextCtrl_CanRedo 2993 +#define wxStyledTextCtrl_MarkerLineFromHandle 2994 +#define wxStyledTextCtrl_MarkerDeleteHandle 2995 +#define wxStyledTextCtrl_GetUndoCollection 2996 +#define wxStyledTextCtrl_GetViewWhiteSpace 2997 +#define wxStyledTextCtrl_SetViewWhiteSpace 2998 +#define wxStyledTextCtrl_PositionFromPoint 2999 +#define wxStyledTextCtrl_PositionFromPointClose 3000 +#define wxStyledTextCtrl_GotoLine 3001 +#define wxStyledTextCtrl_GotoPos 3002 +#define wxStyledTextCtrl_SetAnchor 3003 +#define wxStyledTextCtrl_GetCurLine 3004 +#define wxStyledTextCtrl_GetEndStyled 3005 +#define wxStyledTextCtrl_ConvertEOLs 3006 +#define wxStyledTextCtrl_GetEOLMode 3007 +#define wxStyledTextCtrl_SetEOLMode 3008 +#define wxStyledTextCtrl_StartStyling 3009 +#define wxStyledTextCtrl_SetStyling 3010 +#define wxStyledTextCtrl_GetBufferedDraw 3011 +#define wxStyledTextCtrl_SetBufferedDraw 3012 +#define wxStyledTextCtrl_SetTabWidth 3013 +#define wxStyledTextCtrl_GetTabWidth 3014 +#define wxStyledTextCtrl_SetCodePage 3015 +#define wxStyledTextCtrl_MarkerDefine 3016 +#define wxStyledTextCtrl_MarkerSetForeground 3017 +#define wxStyledTextCtrl_MarkerSetBackground 3018 +#define wxStyledTextCtrl_MarkerAdd 3019 +#define wxStyledTextCtrl_MarkerDelete 3020 +#define wxStyledTextCtrl_MarkerDeleteAll 3021 +#define wxStyledTextCtrl_MarkerGet 3022 +#define wxStyledTextCtrl_MarkerNext 3023 +#define wxStyledTextCtrl_MarkerPrevious 3024 +#define wxStyledTextCtrl_MarkerDefineBitmap 3025 +#define wxStyledTextCtrl_MarkerAddSet 3026 +#define wxStyledTextCtrl_MarkerSetAlpha 3027 +#define wxStyledTextCtrl_SetMarginType 3028 +#define wxStyledTextCtrl_GetMarginType 3029 +#define wxStyledTextCtrl_SetMarginWidth 3030 +#define wxStyledTextCtrl_GetMarginWidth 3031 +#define wxStyledTextCtrl_SetMarginMask 3032 +#define wxStyledTextCtrl_GetMarginMask 3033 +#define wxStyledTextCtrl_SetMarginSensitive 3034 +#define wxStyledTextCtrl_GetMarginSensitive 3035 +#define wxStyledTextCtrl_StyleClearAll 3036 +#define wxStyledTextCtrl_StyleSetForeground 3037 +#define wxStyledTextCtrl_StyleSetBackground 3038 +#define wxStyledTextCtrl_StyleSetBold 3039 +#define wxStyledTextCtrl_StyleSetItalic 3040 +#define wxStyledTextCtrl_StyleSetSize 3041 +#define wxStyledTextCtrl_StyleSetFaceName 3042 +#define wxStyledTextCtrl_StyleSetEOLFilled 3043 +#define wxStyledTextCtrl_StyleResetDefault 3044 +#define wxStyledTextCtrl_StyleSetUnderline 3045 +#define wxStyledTextCtrl_StyleSetCase 3046 +#define wxStyledTextCtrl_StyleSetHotSpot 3047 +#define wxStyledTextCtrl_SetSelForeground 3048 +#define wxStyledTextCtrl_SetSelBackground 3049 +#define wxStyledTextCtrl_GetSelAlpha 3050 +#define wxStyledTextCtrl_SetSelAlpha 3051 +#define wxStyledTextCtrl_SetCaretForeground 3052 +#define wxStyledTextCtrl_CmdKeyAssign 3053 +#define wxStyledTextCtrl_CmdKeyClear 3054 +#define wxStyledTextCtrl_CmdKeyClearAll 3055 +#define wxStyledTextCtrl_SetStyleBytes 3056 +#define wxStyledTextCtrl_StyleSetVisible 3057 +#define wxStyledTextCtrl_GetCaretPeriod 3058 +#define wxStyledTextCtrl_SetCaretPeriod 3059 +#define wxStyledTextCtrl_SetWordChars 3060 +#define wxStyledTextCtrl_BeginUndoAction 3061 +#define wxStyledTextCtrl_EndUndoAction 3062 +#define wxStyledTextCtrl_IndicatorSetStyle 3063 +#define wxStyledTextCtrl_IndicatorGetStyle 3064 +#define wxStyledTextCtrl_IndicatorSetForeground 3065 +#define wxStyledTextCtrl_IndicatorGetForeground 3066 +#define wxStyledTextCtrl_SetWhitespaceForeground 3067 +#define wxStyledTextCtrl_SetWhitespaceBackground 3068 +#define wxStyledTextCtrl_GetStyleBits 3069 +#define wxStyledTextCtrl_SetLineState 3070 +#define wxStyledTextCtrl_GetLineState 3071 +#define wxStyledTextCtrl_GetMaxLineState 3072 +#define wxStyledTextCtrl_GetCaretLineVisible 3073 +#define wxStyledTextCtrl_SetCaretLineVisible 3074 +#define wxStyledTextCtrl_GetCaretLineBackground 3075 +#define wxStyledTextCtrl_SetCaretLineBackground 3076 +#define wxStyledTextCtrl_AutoCompShow 3077 +#define wxStyledTextCtrl_AutoCompCancel 3078 +#define wxStyledTextCtrl_AutoCompActive 3079 +#define wxStyledTextCtrl_AutoCompPosStart 3080 +#define wxStyledTextCtrl_AutoCompComplete 3081 +#define wxStyledTextCtrl_AutoCompStops 3082 +#define wxStyledTextCtrl_AutoCompSetSeparator 3083 +#define wxStyledTextCtrl_AutoCompGetSeparator 3084 +#define wxStyledTextCtrl_AutoCompSelect 3085 +#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3086 +#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3087 +#define wxStyledTextCtrl_AutoCompSetFillUps 3088 +#define wxStyledTextCtrl_AutoCompSetChooseSingle 3089 +#define wxStyledTextCtrl_AutoCompGetChooseSingle 3090 +#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3091 +#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3092 +#define wxStyledTextCtrl_UserListShow 3093 +#define wxStyledTextCtrl_AutoCompSetAutoHide 3094 +#define wxStyledTextCtrl_AutoCompGetAutoHide 3095 +#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3096 +#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3097 +#define wxStyledTextCtrl_RegisterImage 3098 +#define wxStyledTextCtrl_ClearRegisteredImages 3099 +#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3100 +#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3101 +#define wxStyledTextCtrl_AutoCompSetMaxWidth 3102 +#define wxStyledTextCtrl_AutoCompGetMaxWidth 3103 +#define wxStyledTextCtrl_AutoCompSetMaxHeight 3104 +#define wxStyledTextCtrl_AutoCompGetMaxHeight 3105 +#define wxStyledTextCtrl_SetIndent 3106 +#define wxStyledTextCtrl_GetIndent 3107 +#define wxStyledTextCtrl_SetUseTabs 3108 +#define wxStyledTextCtrl_GetUseTabs 3109 +#define wxStyledTextCtrl_SetLineIndentation 3110 +#define wxStyledTextCtrl_GetLineIndentation 3111 +#define wxStyledTextCtrl_GetLineIndentPosition 3112 +#define wxStyledTextCtrl_GetColumn 3113 +#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3114 +#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3115 +#define wxStyledTextCtrl_SetIndentationGuides 3116 +#define wxStyledTextCtrl_GetIndentationGuides 3117 +#define wxStyledTextCtrl_SetHighlightGuide 3118 +#define wxStyledTextCtrl_GetHighlightGuide 3119 +#define wxStyledTextCtrl_GetLineEndPosition 3120 +#define wxStyledTextCtrl_GetCodePage 3121 +#define wxStyledTextCtrl_GetCaretForeground 3122 +#define wxStyledTextCtrl_GetReadOnly 3123 +#define wxStyledTextCtrl_SetCurrentPos 3124 +#define wxStyledTextCtrl_SetSelectionStart 3125 +#define wxStyledTextCtrl_GetSelectionStart 3126 +#define wxStyledTextCtrl_SetSelectionEnd 3127 +#define wxStyledTextCtrl_GetSelectionEnd 3128 +#define wxStyledTextCtrl_SetPrintMagnification 3129 +#define wxStyledTextCtrl_GetPrintMagnification 3130 +#define wxStyledTextCtrl_SetPrintColourMode 3131 +#define wxStyledTextCtrl_GetPrintColourMode 3132 +#define wxStyledTextCtrl_FindText 3133 +#define wxStyledTextCtrl_FormatRange 3134 +#define wxStyledTextCtrl_GetFirstVisibleLine 3135 +#define wxStyledTextCtrl_GetLine 3136 +#define wxStyledTextCtrl_GetLineCount 3137 +#define wxStyledTextCtrl_SetMarginLeft 3138 +#define wxStyledTextCtrl_GetMarginLeft 3139 +#define wxStyledTextCtrl_SetMarginRight 3140 +#define wxStyledTextCtrl_GetMarginRight 3141 +#define wxStyledTextCtrl_GetModify 3142 +#define wxStyledTextCtrl_SetSelection 3143 +#define wxStyledTextCtrl_GetSelectedText 3144 +#define wxStyledTextCtrl_GetTextRange 3145 +#define wxStyledTextCtrl_HideSelection 3146 +#define wxStyledTextCtrl_LineFromPosition 3147 +#define wxStyledTextCtrl_PositionFromLine 3148 +#define wxStyledTextCtrl_LineScroll 3149 +#define wxStyledTextCtrl_EnsureCaretVisible 3150 +#define wxStyledTextCtrl_ReplaceSelection 3151 +#define wxStyledTextCtrl_SetReadOnly 3152 +#define wxStyledTextCtrl_CanPaste 3153 +#define wxStyledTextCtrl_CanUndo 3154 +#define wxStyledTextCtrl_EmptyUndoBuffer 3155 +#define wxStyledTextCtrl_Undo 3156 +#define wxStyledTextCtrl_Cut 3157 +#define wxStyledTextCtrl_Copy 3158 +#define wxStyledTextCtrl_Paste 3159 +#define wxStyledTextCtrl_Clear 3160 +#define wxStyledTextCtrl_SetText 3161 +#define wxStyledTextCtrl_GetText 3162 +#define wxStyledTextCtrl_GetTextLength 3163 +#define wxStyledTextCtrl_GetOvertype 3164 +#define wxStyledTextCtrl_SetCaretWidth 3165 +#define wxStyledTextCtrl_GetCaretWidth 3166 +#define wxStyledTextCtrl_SetTargetStart 3167 +#define wxStyledTextCtrl_GetTargetStart 3168 +#define wxStyledTextCtrl_SetTargetEnd 3169 +#define wxStyledTextCtrl_GetTargetEnd 3170 +#define wxStyledTextCtrl_ReplaceTarget 3171 +#define wxStyledTextCtrl_SearchInTarget 3172 +#define wxStyledTextCtrl_SetSearchFlags 3173 +#define wxStyledTextCtrl_GetSearchFlags 3174 +#define wxStyledTextCtrl_CallTipShow 3175 +#define wxStyledTextCtrl_CallTipCancel 3176 +#define wxStyledTextCtrl_CallTipActive 3177 +#define wxStyledTextCtrl_CallTipPosAtStart 3178 +#define wxStyledTextCtrl_CallTipSetHighlight 3179 +#define wxStyledTextCtrl_CallTipSetBackground 3180 +#define wxStyledTextCtrl_CallTipSetForeground 3181 +#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3182 +#define wxStyledTextCtrl_CallTipUseStyle 3183 +#define wxStyledTextCtrl_VisibleFromDocLine 3184 +#define wxStyledTextCtrl_DocLineFromVisible 3185 +#define wxStyledTextCtrl_WrapCount 3186 +#define wxStyledTextCtrl_SetFoldLevel 3187 +#define wxStyledTextCtrl_GetFoldLevel 3188 +#define wxStyledTextCtrl_GetLastChild 3189 +#define wxStyledTextCtrl_GetFoldParent 3190 +#define wxStyledTextCtrl_ShowLines 3191 +#define wxStyledTextCtrl_HideLines 3192 +#define wxStyledTextCtrl_GetLineVisible 3193 +#define wxStyledTextCtrl_SetFoldExpanded 3194 +#define wxStyledTextCtrl_GetFoldExpanded 3195 +#define wxStyledTextCtrl_ToggleFold 3196 +#define wxStyledTextCtrl_EnsureVisible 3197 +#define wxStyledTextCtrl_SetFoldFlags 3198 +#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3199 +#define wxStyledTextCtrl_SetTabIndents 3200 +#define wxStyledTextCtrl_GetTabIndents 3201 +#define wxStyledTextCtrl_SetBackSpaceUnIndents 3202 +#define wxStyledTextCtrl_GetBackSpaceUnIndents 3203 +#define wxStyledTextCtrl_SetMouseDwellTime 3204 +#define wxStyledTextCtrl_GetMouseDwellTime 3205 +#define wxStyledTextCtrl_WordStartPosition 3206 +#define wxStyledTextCtrl_WordEndPosition 3207 +#define wxStyledTextCtrl_SetWrapMode 3208 +#define wxStyledTextCtrl_GetWrapMode 3209 +#define wxStyledTextCtrl_SetWrapVisualFlags 3210 +#define wxStyledTextCtrl_GetWrapVisualFlags 3211 +#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3212 +#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3213 +#define wxStyledTextCtrl_SetWrapStartIndent 3214 +#define wxStyledTextCtrl_GetWrapStartIndent 3215 +#define wxStyledTextCtrl_SetLayoutCache 3216 +#define wxStyledTextCtrl_GetLayoutCache 3217 +#define wxStyledTextCtrl_SetScrollWidth 3218 +#define wxStyledTextCtrl_GetScrollWidth 3219 +#define wxStyledTextCtrl_TextWidth 3220 +#define wxStyledTextCtrl_GetEndAtLastLine 3221 +#define wxStyledTextCtrl_TextHeight 3222 +#define wxStyledTextCtrl_SetUseVerticalScrollBar 3223 +#define wxStyledTextCtrl_GetUseVerticalScrollBar 3224 +#define wxStyledTextCtrl_AppendText 3225 +#define wxStyledTextCtrl_GetTwoPhaseDraw 3226 +#define wxStyledTextCtrl_SetTwoPhaseDraw 3227 +#define wxStyledTextCtrl_TargetFromSelection 3228 +#define wxStyledTextCtrl_LinesJoin 3229 +#define wxStyledTextCtrl_LinesSplit 3230 +#define wxStyledTextCtrl_SetFoldMarginColour 3231 +#define wxStyledTextCtrl_SetFoldMarginHiColour 3232 +#define wxStyledTextCtrl_LineDown 3233 +#define wxStyledTextCtrl_LineDownExtend 3234 +#define wxStyledTextCtrl_LineUp 3235 +#define wxStyledTextCtrl_LineUpExtend 3236 +#define wxStyledTextCtrl_CharLeft 3237 +#define wxStyledTextCtrl_CharLeftExtend 3238 +#define wxStyledTextCtrl_CharRight 3239 +#define wxStyledTextCtrl_CharRightExtend 3240 +#define wxStyledTextCtrl_WordLeft 3241 +#define wxStyledTextCtrl_WordLeftExtend 3242 +#define wxStyledTextCtrl_WordRight 3243 +#define wxStyledTextCtrl_WordRightExtend 3244 +#define wxStyledTextCtrl_Home 3245 +#define wxStyledTextCtrl_HomeExtend 3246 +#define wxStyledTextCtrl_LineEnd 3247 +#define wxStyledTextCtrl_LineEndExtend 3248 +#define wxStyledTextCtrl_DocumentStart 3249 +#define wxStyledTextCtrl_DocumentStartExtend 3250 +#define wxStyledTextCtrl_DocumentEnd 3251 +#define wxStyledTextCtrl_DocumentEndExtend 3252 +#define wxStyledTextCtrl_PageUp 3253 +#define wxStyledTextCtrl_PageUpExtend 3254 +#define wxStyledTextCtrl_PageDown 3255 +#define wxStyledTextCtrl_PageDownExtend 3256 +#define wxStyledTextCtrl_EditToggleOvertype 3257 +#define wxStyledTextCtrl_Cancel 3258 +#define wxStyledTextCtrl_DeleteBack 3259 +#define wxStyledTextCtrl_Tab 3260 +#define wxStyledTextCtrl_BackTab 3261 +#define wxStyledTextCtrl_NewLine 3262 +#define wxStyledTextCtrl_FormFeed 3263 +#define wxStyledTextCtrl_VCHome 3264 +#define wxStyledTextCtrl_VCHomeExtend 3265 +#define wxStyledTextCtrl_ZoomIn 3266 +#define wxStyledTextCtrl_ZoomOut 3267 +#define wxStyledTextCtrl_DelWordLeft 3268 +#define wxStyledTextCtrl_DelWordRight 3269 +#define wxStyledTextCtrl_LineCut 3270 +#define wxStyledTextCtrl_LineDelete 3271 +#define wxStyledTextCtrl_LineTranspose 3272 +#define wxStyledTextCtrl_LineDuplicate 3273 +#define wxStyledTextCtrl_LowerCase 3274 +#define wxStyledTextCtrl_UpperCase 3275 +#define wxStyledTextCtrl_LineScrollDown 3276 +#define wxStyledTextCtrl_LineScrollUp 3277 +#define wxStyledTextCtrl_DeleteBackNotLine 3278 +#define wxStyledTextCtrl_HomeDisplay 3279 +#define wxStyledTextCtrl_HomeDisplayExtend 3280 +#define wxStyledTextCtrl_LineEndDisplay 3281 +#define wxStyledTextCtrl_LineEndDisplayExtend 3282 +#define wxStyledTextCtrl_HomeWrapExtend 3283 +#define wxStyledTextCtrl_LineEndWrap 3284 +#define wxStyledTextCtrl_LineEndWrapExtend 3285 +#define wxStyledTextCtrl_VCHomeWrap 3286 +#define wxStyledTextCtrl_VCHomeWrapExtend 3287 +#define wxStyledTextCtrl_LineCopy 3288 +#define wxStyledTextCtrl_MoveCaretInsideView 3289 +#define wxStyledTextCtrl_LineLength 3290 +#define wxStyledTextCtrl_BraceHighlight 3291 +#define wxStyledTextCtrl_BraceBadLight 3292 +#define wxStyledTextCtrl_BraceMatch 3293 +#define wxStyledTextCtrl_GetViewEOL 3294 +#define wxStyledTextCtrl_SetViewEOL 3295 +#define wxStyledTextCtrl_SetModEventMask 3296 +#define wxStyledTextCtrl_GetEdgeColumn 3297 +#define wxStyledTextCtrl_SetEdgeColumn 3298 +#define wxStyledTextCtrl_SetEdgeMode 3299 +#define wxStyledTextCtrl_GetEdgeMode 3300 +#define wxStyledTextCtrl_GetEdgeColour 3301 +#define wxStyledTextCtrl_SetEdgeColour 3302 +#define wxStyledTextCtrl_SearchAnchor 3303 +#define wxStyledTextCtrl_SearchNext 3304 +#define wxStyledTextCtrl_SearchPrev 3305 +#define wxStyledTextCtrl_LinesOnScreen 3306 +#define wxStyledTextCtrl_UsePopUp 3307 +#define wxStyledTextCtrl_SelectionIsRectangle 3308 +#define wxStyledTextCtrl_SetZoom 3309 +#define wxStyledTextCtrl_GetZoom 3310 +#define wxStyledTextCtrl_GetModEventMask 3311 +#define wxStyledTextCtrl_SetSTCFocus 3312 +#define wxStyledTextCtrl_GetSTCFocus 3313 +#define wxStyledTextCtrl_SetStatus 3314 +#define wxStyledTextCtrl_GetStatus 3315 +#define wxStyledTextCtrl_SetMouseDownCaptures 3316 +#define wxStyledTextCtrl_GetMouseDownCaptures 3317 +#define wxStyledTextCtrl_SetSTCCursor 3318 +#define wxStyledTextCtrl_GetSTCCursor 3319 +#define wxStyledTextCtrl_SetControlCharSymbol 3320 +#define wxStyledTextCtrl_GetControlCharSymbol 3321 +#define wxStyledTextCtrl_WordPartLeft 3322 +#define wxStyledTextCtrl_WordPartLeftExtend 3323 +#define wxStyledTextCtrl_WordPartRight 3324 +#define wxStyledTextCtrl_WordPartRightExtend 3325 +#define wxStyledTextCtrl_SetVisiblePolicy 3326 +#define wxStyledTextCtrl_DelLineLeft 3327 +#define wxStyledTextCtrl_DelLineRight 3328 +#define wxStyledTextCtrl_GetXOffset 3329 +#define wxStyledTextCtrl_ChooseCaretX 3330 +#define wxStyledTextCtrl_SetXCaretPolicy 3331 +#define wxStyledTextCtrl_SetYCaretPolicy 3332 +#define wxStyledTextCtrl_GetPrintWrapMode 3333 +#define wxStyledTextCtrl_SetHotspotActiveForeground 3334 +#define wxStyledTextCtrl_SetHotspotActiveBackground 3335 +#define wxStyledTextCtrl_SetHotspotActiveUnderline 3336 +#define wxStyledTextCtrl_SetHotspotSingleLine 3337 +#define wxStyledTextCtrl_ParaDownExtend 3338 +#define wxStyledTextCtrl_ParaUp 3339 +#define wxStyledTextCtrl_ParaUpExtend 3340 +#define wxStyledTextCtrl_PositionBefore 3341 +#define wxStyledTextCtrl_PositionAfter 3342 +#define wxStyledTextCtrl_CopyRange 3343 +#define wxStyledTextCtrl_CopyText 3344 +#define wxStyledTextCtrl_SetSelectionMode 3345 +#define wxStyledTextCtrl_GetSelectionMode 3346 +#define wxStyledTextCtrl_LineDownRectExtend 3347 +#define wxStyledTextCtrl_LineUpRectExtend 3348 +#define wxStyledTextCtrl_CharLeftRectExtend 3349 +#define wxStyledTextCtrl_CharRightRectExtend 3350 +#define wxStyledTextCtrl_HomeRectExtend 3351 +#define wxStyledTextCtrl_VCHomeRectExtend 3352 +#define wxStyledTextCtrl_LineEndRectExtend 3353 +#define wxStyledTextCtrl_PageUpRectExtend 3354 +#define wxStyledTextCtrl_PageDownRectExtend 3355 +#define wxStyledTextCtrl_StutteredPageUp 3356 +#define wxStyledTextCtrl_StutteredPageUpExtend 3357 +#define wxStyledTextCtrl_StutteredPageDown 3358 +#define wxStyledTextCtrl_StutteredPageDownExtend 3359 +#define wxStyledTextCtrl_WordLeftEnd 3360 +#define wxStyledTextCtrl_WordLeftEndExtend 3361 +#define wxStyledTextCtrl_WordRightEnd 3362 +#define wxStyledTextCtrl_WordRightEndExtend 3363 +#define wxStyledTextCtrl_SetWhitespaceChars 3364 +#define wxStyledTextCtrl_SetCharsDefault 3365 +#define wxStyledTextCtrl_AutoCompGetCurrent 3366 +#define wxStyledTextCtrl_Allocate 3367 +#define wxStyledTextCtrl_FindColumn 3368 +#define wxStyledTextCtrl_GetCaretSticky 3369 +#define wxStyledTextCtrl_SetCaretSticky 3370 +#define wxStyledTextCtrl_ToggleCaretSticky 3371 +#define wxStyledTextCtrl_SetPasteConvertEndings 3372 +#define wxStyledTextCtrl_GetPasteConvertEndings 3373 +#define wxStyledTextCtrl_SelectionDuplicate 3374 +#define wxStyledTextCtrl_SetCaretLineBackAlpha 3375 +#define wxStyledTextCtrl_GetCaretLineBackAlpha 3376 +#define wxStyledTextCtrl_StartRecord 3377 +#define wxStyledTextCtrl_StopRecord 3378 +#define wxStyledTextCtrl_SetLexer 3379 +#define wxStyledTextCtrl_GetLexer 3380 +#define wxStyledTextCtrl_Colourise 3381 +#define wxStyledTextCtrl_SetProperty 3382 +#define wxStyledTextCtrl_SetKeyWords 3383 +#define wxStyledTextCtrl_SetLexerLanguage 3384 +#define wxStyledTextCtrl_GetProperty 3385 +#define wxStyledTextCtrl_GetStyleBitsNeeded 3386 +#define wxStyledTextCtrl_GetCurrentLine 3387 +#define wxStyledTextCtrl_StyleSetSpec 3388 +#define wxStyledTextCtrl_StyleSetFont 3389 +#define wxStyledTextCtrl_StyleSetFontAttr 3390 +#define wxStyledTextCtrl_StyleSetCharacterSet 3391 +#define wxStyledTextCtrl_StyleSetFontEncoding 3392 +#define wxStyledTextCtrl_CmdKeyExecute 3393 +#define wxStyledTextCtrl_SetMargins 3394 +#define wxStyledTextCtrl_GetSelection 3395 +#define wxStyledTextCtrl_PointFromPosition 3396 +#define wxStyledTextCtrl_ScrollToLine 3397 +#define wxStyledTextCtrl_ScrollToColumn 3398 +#define wxStyledTextCtrl_SetVScrollBar 3399 +#define wxStyledTextCtrl_SetHScrollBar 3400 +#define wxStyledTextCtrl_GetLastKeydownProcessed 3401 +#define wxStyledTextCtrl_SetLastKeydownProcessed 3402 +#define wxStyledTextCtrl_SaveFile 3403 +#define wxStyledTextCtrl_LoadFile 3404 +#define wxStyledTextCtrl_DoDragOver 3405 +#define wxStyledTextCtrl_DoDropText 3406 +#define wxStyledTextCtrl_GetUseAntiAliasing 3407 +#define wxStyledTextCtrl_AddTextRaw 3408 +#define wxStyledTextCtrl_InsertTextRaw 3409 +#define wxStyledTextCtrl_GetCurLineRaw 3410 +#define wxStyledTextCtrl_GetLineRaw 3411 +#define wxStyledTextCtrl_GetSelectedTextRaw 3412 +#define wxStyledTextCtrl_GetTextRangeRaw 3413 +#define wxStyledTextCtrl_SetTextRaw 3414 +#define wxStyledTextCtrl_GetTextRaw 3415 +#define wxStyledTextCtrl_AppendTextRaw 3416 +#define wxArtProvider_GetBitmap 3417 +#define wxArtProvider_GetIcon 3418 +#define wxTreeEvent_GetKeyCode 3419 +#define wxTreeEvent_GetItem 3420 +#define wxTreeEvent_GetKeyEvent 3421 +#define wxTreeEvent_GetLabel 3422 +#define wxTreeEvent_GetOldItem 3423 +#define wxTreeEvent_GetPoint 3424 +#define wxTreeEvent_IsEditCancelled 3425 +#define wxTreeEvent_SetToolTip 3426 +#define wxNotebookEvent_GetOldSelection 3427 +#define wxNotebookEvent_GetSelection 3428 +#define wxNotebookEvent_SetOldSelection 3429 +#define wxNotebookEvent_SetSelection 3430 +#define wxFileDataObject_new 3431 +#define wxFileDataObject_AddFile 3432 +#define wxFileDataObject_GetFilenames 3433 +#define wxFileDataObject_destroy 3434 +#define wxTextDataObject_new 3435 +#define wxTextDataObject_GetTextLength 3436 +#define wxTextDataObject_GetText 3437 +#define wxTextDataObject_SetText 3438 +#define wxTextDataObject_destroy 3439 +#define wxBitmapDataObject_new_1_1 3440 +#define wxBitmapDataObject_new_1_0 3441 +#define wxBitmapDataObject_GetBitmap 3442 +#define wxBitmapDataObject_SetBitmap 3443 +#define wxBitmapDataObject_destroy 3444 +#define wxClipboard_new 3446 +#define wxClipboard_destruct 3447 +#define wxClipboard_AddData 3448 +#define wxClipboard_Clear 3449 +#define wxClipboard_Close 3450 +#define wxClipboard_Flush 3451 +#define wxClipboard_GetData 3452 +#define wxClipboard_IsOpened 3453 +#define wxClipboard_Open 3454 +#define wxClipboard_SetData 3455 +#define wxClipboard_UsePrimarySelection 3457 +#define wxClipboard_IsSupported 3458 +#define wxClipboard_Get 3459 +#define wxSpinEvent_GetPosition 3460 +#define wxSpinEvent_SetPosition 3461 +#define wxSplitterWindow_new_0 3462 +#define wxSplitterWindow_new_2 3463 +#define wxSplitterWindow_destruct 3464 +#define wxSplitterWindow_Create 3465 +#define wxSplitterWindow_GetMinimumPaneSize 3466 +#define wxSplitterWindow_GetSashGravity 3467 +#define wxSplitterWindow_GetSashPosition 3468 +#define wxSplitterWindow_GetSplitMode 3469 +#define wxSplitterWindow_GetWindow1 3470 +#define wxSplitterWindow_GetWindow2 3471 +#define wxSplitterWindow_Initialize 3472 +#define wxSplitterWindow_IsSplit 3473 +#define wxSplitterWindow_ReplaceWindow 3474 +#define wxSplitterWindow_SetSashGravity 3475 +#define wxSplitterWindow_SetSashPosition 3476 +#define wxSplitterWindow_SetSashSize 3477 +#define wxSplitterWindow_SetMinimumPaneSize 3478 +#define wxSplitterWindow_SetSplitMode 3479 +#define wxSplitterWindow_SplitHorizontally 3480 +#define wxSplitterWindow_SplitVertically 3481 +#define wxSplitterWindow_Unsplit 3482 +#define wxSplitterWindow_UpdateSize 3483 +#define wxSplitterEvent_GetSashPosition 3484 +#define wxSplitterEvent_GetX 3485 +#define wxSplitterEvent_GetY 3486 +#define wxSplitterEvent_GetWindowBeingRemoved 3487 +#define wxSplitterEvent_SetSashPosition 3488 +#define wxHtmlWindow_new_0 3489 +#define wxHtmlWindow_new_2 3490 +#define wxHtmlWindow_AppendToPage 3491 +#define wxHtmlWindow_GetOpenedAnchor 3492 +#define wxHtmlWindow_GetOpenedPage 3493 +#define wxHtmlWindow_GetOpenedPageTitle 3494 +#define wxHtmlWindow_GetRelatedFrame 3495 +#define wxHtmlWindow_HistoryBack 3496 +#define wxHtmlWindow_HistoryCanBack 3497 +#define wxHtmlWindow_HistoryCanForward 3498 +#define wxHtmlWindow_HistoryClear 3499 +#define wxHtmlWindow_HistoryForward 3500 +#define wxHtmlWindow_LoadFile 3501 +#define wxHtmlWindow_LoadPage 3502 +#define wxHtmlWindow_SelectAll 3503 +#define wxHtmlWindow_SelectionToText 3504 +#define wxHtmlWindow_SelectLine 3505 +#define wxHtmlWindow_SelectWord 3506 +#define wxHtmlWindow_SetBorders 3507 +#define wxHtmlWindow_SetFonts 3508 +#define wxHtmlWindow_SetPage 3509 +#define wxHtmlWindow_SetRelatedFrame 3510 +#define wxHtmlWindow_SetRelatedStatusBar 3511 +#define wxHtmlWindow_ToText 3512 +#define wxHtmlWindow_destroy 3513 +#define wxHtmlLinkEvent_GetLinkInfo 3514 +#define wxSystemSettings_GetColour 3515 +#define wxSystemSettings_GetFont 3516 +#define wxSystemSettings_GetMetric 3517 +#define wxSystemSettings_GetScreenType 3518 +#define wxSystemOptions_GetOption 3519 +#define wxSystemOptions_GetOptionInt 3520 +#define wxSystemOptions_HasOption 3521 +#define wxSystemOptions_IsFalse 3522 +#define wxSystemOptions_SetOption_2_1 3523 +#define wxSystemOptions_SetOption_2_0 3524 +#define wxAuiNotebookEvent_SetSelection 3525 +#define wxAuiNotebookEvent_GetSelection 3526 +#define wxAuiNotebookEvent_SetOldSelection 3527 +#define wxAuiNotebookEvent_GetOldSelection 3528 +#define wxAuiNotebookEvent_SetDragSource 3529 +#define wxAuiNotebookEvent_GetDragSource 3530 +#define wxAuiManagerEvent_SetManager 3531 +#define wxAuiManagerEvent_GetManager 3532 +#define wxAuiManagerEvent_SetPane 3533 +#define wxAuiManagerEvent_GetPane 3534 +#define wxAuiManagerEvent_SetButton 3535 +#define wxAuiManagerEvent_GetButton 3536 +#define wxAuiManagerEvent_SetDC 3537 +#define wxAuiManagerEvent_GetDC 3538 +#define wxAuiManagerEvent_Veto 3539 +#define wxAuiManagerEvent_GetVeto 3540 +#define wxAuiManagerEvent_SetCanVeto 3541 +#define wxAuiManagerEvent_CanVeto 3542 +#define wxLogNull_new 3543 +#define wxLogNull_destroy 3544 +#define wxTaskBarIcon_new 3545 +#define wxTaskBarIcon_destruct 3546 +#define wxTaskBarIcon_PopupMenu 3547 +#define wxTaskBarIcon_RemoveIcon 3548 +#define wxTaskBarIcon_SetIcon 3549 +#define wxLocale_new_0 3550 +#define wxLocale_new_2 3552 +#define wxLocale_destruct 3553 +#define wxLocale_Init 3555 +#define wxLocale_AddCatalog_1 3556 +#define wxLocale_AddCatalog_3 3557 +#define wxLocale_AddCatalogLookupPathPrefix 3558 +#define wxLocale_GetCanonicalName 3559 +#define wxLocale_GetLanguage 3560 +#define wxLocale_GetLanguageName 3561 +#define wxLocale_GetLocale 3562 +#define wxLocale_GetName 3563 +#define wxLocale_GetString_2 3564 +#define wxLocale_GetString_4 3565 +#define wxLocale_GetHeaderValue 3566 +#define wxLocale_GetSysName 3567 +#define wxLocale_GetSystemEncoding 3568 +#define wxLocale_GetSystemEncodingName 3569 +#define wxLocale_GetSystemLanguage 3570 +#define wxLocale_IsLoaded 3571 +#define wxLocale_IsOk 3572 +#define wxActivateEvent_GetActive 3573 +#define wxPopupWindow_new_2 3575 +#define wxPopupWindow_new_0 3576 +#define wxPopupWindow_destruct 3578 +#define wxPopupWindow_Create 3579 +#define wxPopupWindow_Position 3580 +#define wxPopupTransientWindow_new_0 3581 +#define wxPopupTransientWindow_new_2 3582 +#define wxPopupTransientWindow_destruct 3583 +#define wxPopupTransientWindow_Popup 3584 +#define wxPopupTransientWindow_Dismiss 3585 diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml index 0f00309f1b..6a0dd898e3 100644 --- a/lib/wx/doc/src/notes.xml +++ b/lib/wx/doc/src/notes.xml @@ -32,6 +32,21 @@ <p>This document describes the changes made to the wxErlang application.</p> +<section><title>Wx 1.5</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Extend AUI functionality.</p> + <p> + Own Id: OTP-12961</p> + </item> + </list> + </section> + +</section> + <section><title>Wx 1.4</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/wx/examples/demo/ex_aui.erl b/lib/wx/examples/demo/ex_aui.erl index e0841da670..7fbf841d16 100644 --- a/lib/wx/examples/demo/ex_aui.erl +++ b/lib/wx/examples/demo/ex_aui.erl @@ -47,40 +47,54 @@ init(Config) -> -define(pi, wxAuiPaneInfo). do_init(Config) -> - Parent = proplists:get_value(parent, Config), + Parent = proplists:get_value(parent, Config), Panel = wxPanel:new(Parent, []), %% Setup sizers MainSizer = wxBoxSizer:new(?wxVERTICAL), Manager = wxAuiManager:new([{managed_wnd, Panel}]), - - Pane = ?pi:new(), - ?pi:closeButton(Pane), - ?pi:right(Pane), - ?pi:dockable(Pane, [{b, true}]), - ?pi:floatingSize(Pane, 300,200), - ?pi:minSize(Pane, {50,50}), - ?pi:paneBorder(Pane), - ?pi:floatable(Pane, [{b, true}]), - - create_pane(Panel, Manager, Pane), - create_pane(Panel, Manager, - ?pi:caption(?pi:top(?pi:new(Pane)), "One")), - create_pane(Panel, Manager, - ?pi:caption(?pi:left(?pi:new(Pane)), "two")), - create_pane(Panel, Manager, - ?pi:caption(?pi:bottom(?pi:new(Pane)), "Three")), - Pane2 = wxAuiPaneInfo:new(Pane), - ?pi:centrePane(Pane2), - create_notebook(Panel, Manager, ?pi:new(Pane2)), - - wxPanel:setSizer(Panel, MainSizer), - - wxAuiManager:connect(Manager, aui_pane_button, [{skip,true}]), - wxAuiManager:connect(Manager, aui_pane_maximize, [{skip,true}]), - wxAuiManager:update(Manager), - process_flag(trap_exit, true), - {Panel, #state{parent=Panel, config=Config, aui=Manager}}. + try + Art = wxAuiManager:getArtProvider(Manager), + wxAuiDockArt:setColour(Art, ?wxAUI_DOCKART_BACKGROUND_COLOUR, {200, 100, 100}), + wxAuiDockArt:setColour(Art, ?wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR, {200, 100, 100}), + wxAuiDockArt:setColour(Art, ?wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR, {100, 200, 100}), + + + Pane = ?pi:new(), + ?pi:closeButton(Pane), + ?pi:right(Pane), + ?pi:dockable(Pane, [{b, true}]), + ?pi:floatingSize(Pane, 300,200), + ?pi:minSize(Pane, {50,50}), + ?pi:paneBorder(Pane), + ?pi:floatable(Pane, [{b, true}]), + + create_pane(Panel, Manager, Pane), + create_pane(Panel, Manager, + ?pi:caption(?pi:top(?pi:new(Pane)), "One")), + create_pane(Panel, Manager, + ?pi:caption(?pi:left(?pi:new(Pane)), "two")), + create_pane(Panel, Manager, + ?pi:caption(?pi:bottom(?pi:new(Pane)), "Three")), + Pane2 = wxAuiPaneInfo:new(Pane), + ?pi:centrePane(Pane2), + create_notebook(Panel, Manager, ?pi:new(Pane2)), + + wxPanel:setSizer(Panel, MainSizer), + + wxAuiManager:connect(Manager, aui_pane_button, [{skip,true}]), + wxAuiManager:connect(Manager, aui_pane_maximize, [{skip,true}]), + wxAuiManager:update(Manager), + process_flag(trap_exit, true), + {Panel, #state{parent=Panel, config=Config, aui=Manager}} + catch Class:Reason -> + ST = erlang:get_stacktrace(), + io:format("AUI Crashed ~p ~p~n",[Reason, ST]), + wxAuiManager:unInit(Manager), + wxAuiManager:destroy(Manager), + wxPanel:destroy(Panel), + erlang:raise(Class, Reason, ST) + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Callbacks handled as normal gen_server callbacks @@ -163,6 +177,15 @@ create_notebook(Parent, Manager, Pane) -> Notebook = wxAuiNotebook:new(Parent, [{style, Style}]), + Art = wxAuiSimpleTabArt:new(), + case ?wxMAJOR_VERSION > 2 of + true -> + wxAuiSimpleTabArt:setColour(Art, {200, 0, 0}), + wxAuiSimpleTabArt:setActiveColour(Art, {0, 0, 200}); + false -> ignore + end, + ok = wxAuiNotebook:setArtProvider(Notebook, Art), + Tab1 = wxPanel:new(Notebook, []), wxPanel:setBackgroundColour(Tab1, ?wxBLACK), wxButton:new(Tab1, ?wxID_ANY, [{label,"New tab"}]), diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl index 69ca13aca1..1bc00ca235 100644 --- a/lib/wx/include/wx.hrl +++ b/lib/wx/include/wx.hrl @@ -295,7 +295,7 @@ veto_flag :: boolean(), canveto_flag :: boolean(), dc :: wxDC:wxDC()}). --type wxAuiManagerEventType() :: aui_pane_button | aui_pane_close | aui_pane_maximize | aui_pane_restore | aui_render | aui_find_manager. +-type wxAuiManagerEventType() :: aui_pane_button | aui_pane_close | aui_pane_maximize | aui_pane_restore | aui_pane_activated | aui_render | aui_find_manager. -type wxAuiManager() :: #wxAuiManager{}. %% Callback event: {@link wxAuiManagerEvent} -record(wxInitDialog, {type :: wxInitDialogEventType()}). %% Callback event: {@link wxInitDialogEvent} diff --git a/lib/wx/src/gen/wxAuiDockArt.erl b/lib/wx/src/gen/wxAuiDockArt.erl index 499fbd9a23..4149b1d424 100644 --- a/lib/wx/src/gen/wxAuiDockArt.erl +++ b/lib/wx/src/gen/wxAuiDockArt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ -module(wxAuiDockArt). -include("wxe.hrl"). --export([]). +-export([getColour/2,getFont/2,getMetric/2,setColour/3,setFont/3,setMetric/3]). %% inherited exports -export([parent_class/1]). @@ -35,3 +35,58 @@ parent_class(_Class) -> erlang:error({badtype, ?MODULE}). -type wxAuiDockArt() :: wx:wx_object(). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauidockart.html#wxauidockartgetcolour">external documentation</a>. +-spec getColour(This, Id) -> wx:wx_colour4() when + This::wxAuiDockArt(), Id::integer(). +getColour(#wx_ref{type=ThisT,ref=ThisRef},Id) + when is_integer(Id) -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:call(?wxAuiDockArt_GetColour, + <<ThisRef:32/?UI,Id:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauidockart.html#wxauidockartgetfont">external documentation</a>. +-spec getFont(This, Id) -> wxFont:wxFont() when + This::wxAuiDockArt(), Id::integer(). +getFont(#wx_ref{type=ThisT,ref=ThisRef},Id) + when is_integer(Id) -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:call(?wxAuiDockArt_GetFont, + <<ThisRef:32/?UI,Id:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauidockart.html#wxauidockartgetmetric">external documentation</a>. +-spec getMetric(This, Id) -> integer() when + This::wxAuiDockArt(), Id::integer(). +getMetric(#wx_ref{type=ThisT,ref=ThisRef},Id) + when is_integer(Id) -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:call(?wxAuiDockArt_GetMetric, + <<ThisRef:32/?UI,Id:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauidockart.html#wxauidockartsetcolour">external documentation</a>. +-spec setColour(This, Id, Colour) -> ok when + This::wxAuiDockArt(), Id::integer(), Colour::wx:wx_colour(). +setColour(#wx_ref{type=ThisT,ref=ThisRef},Id,Colour) + when is_integer(Id),tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:cast(?wxAuiDockArt_SetColour, + <<ThisRef:32/?UI,Id:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauidockart.html#wxauidockartsetfont">external documentation</a>. +-spec setFont(This, Id, Font) -> ok when + This::wxAuiDockArt(), Id::integer(), Font::wxFont:wxFont(). +setFont(#wx_ref{type=ThisT,ref=ThisRef},Id,#wx_ref{type=FontT,ref=FontRef}) + when is_integer(Id) -> + ?CLASS(ThisT,wxAuiDockArt), + ?CLASS(FontT,wxFont), + wxe_util:cast(?wxAuiDockArt_SetFont, + <<ThisRef:32/?UI,Id:32/?UI,FontRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauidockart.html#wxauidockartsetmetric">external documentation</a>. +-spec setMetric(This, Id, New_val) -> ok when + This::wxAuiDockArt(), Id::integer(), New_val::integer(). +setMetric(#wx_ref{type=ThisT,ref=ThisRef},Id,New_val) + when is_integer(Id),is_integer(New_val) -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:cast(?wxAuiDockArt_SetMetric, + <<ThisRef:32/?UI,Id:32/?UI,New_val:32/?UI>>). + diff --git a/lib/wx/src/gen/wxAuiManager.erl b/lib/wx/src/gen/wxAuiManager.erl index 5a945f59e8..bf22e3091d 100644 --- a/lib/wx/src/gen/wxAuiManager.erl +++ b/lib/wx/src/gen/wxAuiManager.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -120,7 +120,7 @@ detachPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) <<ThisRef:32/?UI,WindowRef:32/?UI>>). %% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauimanager.html#wxauimanagergetallpanes">external documentation</a>. --spec getAllPanes(This) -> wx:wx_object() when +-spec getAllPanes(This) -> [wxAuiPaneInfo:wxAuiPaneInfo()] when This::wxAuiManager(). getAllPanes(#wx_ref{type=ThisT,ref=ThisRef}) -> ?CLASS(ThisT,wxAuiManager), diff --git a/lib/wx/src/gen/wxAuiManagerEvent.erl b/lib/wx/src/gen/wxAuiManagerEvent.erl index 51ad211e10..88e4433f24 100644 --- a/lib/wx/src/gen/wxAuiManagerEvent.erl +++ b/lib/wx/src/gen/wxAuiManagerEvent.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2013. All Rights Reserved. +%% Copyright Ericsson AB 2009-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ %% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauimanagerevent.html">wxAuiManagerEvent</a>. %% <dl><dt>Use {@link wxEvtHandler:connect/3.} with EventType:</dt> -%% <dd><em>aui_pane_button</em>, <em>aui_pane_close</em>, <em>aui_pane_maximize</em>, <em>aui_pane_restore</em>, <em>aui_render</em>, <em>aui_find_manager</em></dd></dl> +%% <dd><em>aui_pane_button</em>, <em>aui_pane_close</em>, <em>aui_pane_maximize</em>, <em>aui_pane_restore</em>, <em>aui_pane_activated</em>, <em>aui_render</em>, <em>aui_find_manager</em></dd></dl> %% See also the message variant {@link wxEvtHandler:wxAuiManager(). #wxAuiManager{}} event record type. %% %% <p>This class is derived (and can use functions) from: diff --git a/lib/wx/src/gen/wxAuiPaneInfo.erl b/lib/wx/src/gen/wxAuiPaneInfo.erl index 2b31df09fe..1f15e9cd39 100644 --- a/lib/wx/src/gen/wxAuiPaneInfo.erl +++ b/lib/wx/src/gen/wxAuiPaneInfo.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -30,17 +30,19 @@ closeButton/2,defaultPane/1,destroy/1,destroyOnClose/1,destroyOnClose/2, direction/2,dock/1,dockable/1,dockable/2,fixed/1,float/1,floatable/1, floatable/2,floatingPosition/2,floatingPosition/3,floatingSize/2, - floatingSize/3,gripper/1,gripper/2,gripperTop/1,gripperTop/2,hasBorder/1, - hasCaption/1,hasCloseButton/1,hasFlag/2,hasGripper/1,hasGripperTop/1, - hasMaximizeButton/1,hasMinimizeButton/1,hasPinButton/1,hide/1,isBottomDockable/1, - isDocked/1,isFixed/1,isFloatable/1,isFloating/1,isLeftDockable/1,isMovable/1, - isOk/1,isResizable/1,isRightDockable/1,isShown/1,isToolbar/1,isTopDockable/1, - layer/2,left/1,leftDockable/1,leftDockable/2,maxSize/2,maxSize/3,maximizeButton/1, - maximizeButton/2,minSize/2,minSize/3,minimizeButton/1,minimizeButton/2, - movable/1,movable/2,name/2,new/0,new/1,paneBorder/1,paneBorder/2,pinButton/1, - pinButton/2,position/2,resizable/1,resizable/2,right/1,rightDockable/1, - rightDockable/2,row/2,safeSet/2,setFlag/3,show/1,show/2,toolbarPane/1, - top/1,topDockable/1,topDockable/2,window/2]). + floatingSize/3,getDirection/1,getFloatingPosition/1,getFloatingSize/1, + getFrame/1,getLayer/1,getPosition/1,getRow/1,getWindow/1,gripper/1, + gripper/2,gripperTop/1,gripperTop/2,hasBorder/1,hasCaption/1,hasCloseButton/1, + hasFlag/2,hasGripper/1,hasGripperTop/1,hasMaximizeButton/1,hasMinimizeButton/1, + hasPinButton/1,hide/1,isBottomDockable/1,isDocked/1,isFixed/1,isFloatable/1, + isFloating/1,isLeftDockable/1,isMovable/1,isOk/1,isResizable/1,isRightDockable/1, + isShown/1,isToolbar/1,isTopDockable/1,layer/2,left/1,leftDockable/1, + leftDockable/2,maxSize/2,maxSize/3,maximizeButton/1,maximizeButton/2, + minSize/2,minSize/3,minimizeButton/1,minimizeButton/2,movable/1,movable/2, + name/2,new/0,new/1,paneBorder/1,paneBorder/2,pinButton/1,pinButton/2, + position/2,resizable/1,resizable/2,right/1,rightDockable/1,rightDockable/2, + row/2,safeSet/2,setFlag/3,show/1,show/2,toolbarPane/1,top/1,topDockable/1, + topDockable/2,window/2]). %% inherited exports -export([parent_class/1]). @@ -888,6 +890,70 @@ window(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WT,ref=WRef}) -> wxe_util:call(?wxAuiPaneInfo_Window, <<ThisRef:32/?UI,WRef:32/?UI>>). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauipaneinfo.html#wxauipaneinfogetwindow">external documentation</a>. +-spec getWindow(This) -> wxWindow:wxWindow() when + This::wxAuiPaneInfo(). +getWindow(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxAuiPaneInfo), + wxe_util:call(?wxAuiPaneInfo_GetWindow, + <<ThisRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauipaneinfo.html#wxauipaneinfogetframe">external documentation</a>. +-spec getFrame(This) -> wxFrame:wxFrame() when + This::wxAuiPaneInfo(). +getFrame(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxAuiPaneInfo), + wxe_util:call(?wxAuiPaneInfo_GetFrame, + <<ThisRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauipaneinfo.html#wxauipaneinfogetdirection">external documentation</a>. +-spec getDirection(This) -> integer() when + This::wxAuiPaneInfo(). +getDirection(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxAuiPaneInfo), + wxe_util:call(?wxAuiPaneInfo_GetDirection, + <<ThisRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauipaneinfo.html#wxauipaneinfogetlayer">external documentation</a>. +-spec getLayer(This) -> integer() when + This::wxAuiPaneInfo(). +getLayer(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxAuiPaneInfo), + wxe_util:call(?wxAuiPaneInfo_GetLayer, + <<ThisRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauipaneinfo.html#wxauipaneinfogetrow">external documentation</a>. +-spec getRow(This) -> integer() when + This::wxAuiPaneInfo(). +getRow(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxAuiPaneInfo), + wxe_util:call(?wxAuiPaneInfo_GetRow, + <<ThisRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauipaneinfo.html#wxauipaneinfogetposition">external documentation</a>. +-spec getPosition(This) -> integer() when + This::wxAuiPaneInfo(). +getPosition(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxAuiPaneInfo), + wxe_util:call(?wxAuiPaneInfo_GetPosition, + <<ThisRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauipaneinfo.html#wxauipaneinfogetfloatingposition">external documentation</a>. +-spec getFloatingPosition(This) -> {X::integer(), Y::integer()} when + This::wxAuiPaneInfo(). +getFloatingPosition(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxAuiPaneInfo), + wxe_util:call(?wxAuiPaneInfo_GetFloatingPosition, + <<ThisRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauipaneinfo.html#wxauipaneinfogetfloatingsize">external documentation</a>. +-spec getFloatingSize(This) -> {W::integer(), H::integer()} when + This::wxAuiPaneInfo(). +getFloatingSize(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxAuiPaneInfo), + wxe_util:call(?wxAuiPaneInfo_GetFloatingSize, + <<ThisRef:32/?UI>>). + %% @doc Destroys this object, do not use object again -spec destroy(This::wxAuiPaneInfo()) -> ok. destroy(Obj=#wx_ref{type=Type}) -> diff --git a/lib/wx/src/gen/wxAuiSimpleTabArt.erl b/lib/wx/src/gen/wxAuiSimpleTabArt.erl new file mode 100644 index 0000000000..57d12e2eb4 --- /dev/null +++ b/lib/wx/src/gen/wxAuiSimpleTabArt.erl @@ -0,0 +1,67 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauisimpletabart.html">wxAuiSimpleTabArt</a>. +%% <p>This class is derived (and can use functions) from: +%% <br />{@link wxAuiTabArt} +%% </p> +%% @type wxAuiSimpleTabArt(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxAuiSimpleTabArt). +-include("wxe.hrl"). +-export([destroy/1,new/0]). + +%% inherited exports +-export([parent_class/1,setActiveColour/2,setColour/2,setFlags/2,setMeasuringFont/2, + setNormalFont/2,setSelectedFont/2]). + +-export_type([wxAuiSimpleTabArt/0]). +%% @hidden +parent_class(wxAuiTabArt) -> true; +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxAuiSimpleTabArt() :: wx:wx_object(). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauisimpletabart.html#wxauisimpletabartwxauisimpletabart">external documentation</a>. +-spec new() -> wxAuiSimpleTabArt(). +new() -> + wxe_util:construct(?wxAuiSimpleTabArt_new, + <<>>). + +%% @doc Destroys this object, do not use object again +-spec destroy(This::wxAuiSimpleTabArt()) -> ok. +destroy(Obj=#wx_ref{type=Type}) -> + ?CLASS(Type,wxAuiSimpleTabArt), + wxe_util:destroy(?wxAuiSimpleTabArt_destroy,Obj), + ok. + %% From wxAuiTabArt +%% @hidden +setActiveColour(This,Colour) -> wxAuiTabArt:setActiveColour(This,Colour). +%% @hidden +setColour(This,Colour) -> wxAuiTabArt:setColour(This,Colour). +%% @hidden +setSelectedFont(This,Font) -> wxAuiTabArt:setSelectedFont(This,Font). +%% @hidden +setNormalFont(This,Font) -> wxAuiTabArt:setNormalFont(This,Font). +%% @hidden +setMeasuringFont(This,Font) -> wxAuiTabArt:setMeasuringFont(This,Font). +%% @hidden +setFlags(This,Flags) -> wxAuiTabArt:setFlags(This,Flags). diff --git a/lib/wx/src/gen/wxAuiTabArt.erl b/lib/wx/src/gen/wxAuiTabArt.erl index 0386ef9dce..80924c0269 100644 --- a/lib/wx/src/gen/wxAuiTabArt.erl +++ b/lib/wx/src/gen/wxAuiTabArt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,8 @@ -module(wxAuiTabArt). -include("wxe.hrl"). --export([]). +-export([setActiveColour/2,setColour/2,setFlags/2,setMeasuringFont/2,setNormalFont/2, + setSelectedFont/2]). %% inherited exports -export([parent_class/1]). @@ -35,3 +36,57 @@ parent_class(_Class) -> erlang:error({badtype, ?MODULE}). -type wxAuiTabArt() :: wx:wx_object(). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauitabart.html#wxauitabartsetflags">external documentation</a>. +-spec setFlags(This, Flags) -> ok when + This::wxAuiTabArt(), Flags::integer(). +setFlags(#wx_ref{type=ThisT,ref=ThisRef},Flags) + when is_integer(Flags) -> + ?CLASS(ThisT,wxAuiTabArt), + wxe_util:cast(?wxAuiTabArt_SetFlags, + <<ThisRef:32/?UI,Flags:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauitabart.html#wxauitabartsetmeasuringfont">external documentation</a>. +-spec setMeasuringFont(This, Font) -> ok when + This::wxAuiTabArt(), Font::wxFont:wxFont(). +setMeasuringFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) -> + ?CLASS(ThisT,wxAuiTabArt), + ?CLASS(FontT,wxFont), + wxe_util:cast(?wxAuiTabArt_SetMeasuringFont, + <<ThisRef:32/?UI,FontRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauitabart.html#wxauitabartsetnormalfont">external documentation</a>. +-spec setNormalFont(This, Font) -> ok when + This::wxAuiTabArt(), Font::wxFont:wxFont(). +setNormalFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) -> + ?CLASS(ThisT,wxAuiTabArt), + ?CLASS(FontT,wxFont), + wxe_util:cast(?wxAuiTabArt_SetNormalFont, + <<ThisRef:32/?UI,FontRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauitabart.html#wxauitabartsetselectedfont">external documentation</a>. +-spec setSelectedFont(This, Font) -> ok when + This::wxAuiTabArt(), Font::wxFont:wxFont(). +setSelectedFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) -> + ?CLASS(ThisT,wxAuiTabArt), + ?CLASS(FontT,wxFont), + wxe_util:cast(?wxAuiTabArt_SetSelectedFont, + <<ThisRef:32/?UI,FontRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauitabart.html#wxauitabartsetcolour">external documentation</a>. +-spec setColour(This, Colour) -> ok when + This::wxAuiTabArt(), Colour::wx:wx_colour(). +setColour(#wx_ref{type=ThisT,ref=ThisRef},Colour) + when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 -> + ?CLASS(ThisT,wxAuiTabArt), + wxe_util:cast(?wxAuiTabArt_SetColour, + <<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxauitabart.html#wxauitabartsetactivecolour">external documentation</a>. +-spec setActiveColour(This, Colour) -> ok when + This::wxAuiTabArt(), Colour::wx:wx_colour(). +setActiveColour(#wx_ref{type=ThisT,ref=ThisRef},Colour) + when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 -> + ?CLASS(ThisT,wxAuiTabArt), + wxe_util:cast(?wxAuiTabArt_SetActiveColour, + <<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>). + diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl index 58fbe8d061..2cb73c0fed 100644 --- a/lib/wx/src/gen/wxe_debug.hrl +++ b/lib/wx/src/gen/wxe_debug.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2014. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -2440,907 +2440,929 @@ wxdebug_table() -> {2650, {wxAuiPaneInfo, top, 0}}, {2651, {wxAuiPaneInfo, topDockable, 1}}, {2652, {wxAuiPaneInfo, window, 1}}, - {2653, {wxAuiNotebook, new_0, 0}}, - {2654, {wxAuiNotebook, new_2, 2}}, - {2655, {wxAuiNotebook, addPage, 3}}, - {2656, {wxAuiNotebook, create, 2}}, - {2657, {wxAuiNotebook, deletePage, 1}}, - {2658, {wxAuiNotebook, getArtProvider, 0}}, - {2659, {wxAuiNotebook, getPage, 1}}, - {2660, {wxAuiNotebook, getPageBitmap, 1}}, - {2661, {wxAuiNotebook, getPageCount, 0}}, - {2662, {wxAuiNotebook, getPageIndex, 1}}, - {2663, {wxAuiNotebook, getPageText, 1}}, - {2664, {wxAuiNotebook, getSelection, 0}}, - {2665, {wxAuiNotebook, insertPage, 4}}, - {2666, {wxAuiNotebook, removePage, 1}}, - {2667, {wxAuiNotebook, setArtProvider, 1}}, - {2668, {wxAuiNotebook, setFont, 1}}, - {2669, {wxAuiNotebook, setPageBitmap, 2}}, - {2670, {wxAuiNotebook, setPageText, 2}}, - {2671, {wxAuiNotebook, setSelection, 1}}, - {2672, {wxAuiNotebook, setTabCtrlHeight, 1}}, - {2673, {wxAuiNotebook, setUniformBitmapSize, 1}}, - {2674, {wxAuiNotebook, 'Destroy', undefined}}, - {2675, {wxMDIParentFrame, new_0, 0}}, - {2676, {wxMDIParentFrame, new_4, 4}}, - {2677, {wxMDIParentFrame, destruct, 0}}, - {2678, {wxMDIParentFrame, activateNext, 0}}, - {2679, {wxMDIParentFrame, activatePrevious, 0}}, - {2680, {wxMDIParentFrame, arrangeIcons, 0}}, - {2681, {wxMDIParentFrame, cascade, 0}}, - {2682, {wxMDIParentFrame, create, 4}}, - {2683, {wxMDIParentFrame, getActiveChild, 0}}, - {2684, {wxMDIParentFrame, getClientWindow, 0}}, - {2685, {wxMDIParentFrame, tile, 1}}, - {2686, {wxMDIChildFrame, new_0, 0}}, - {2687, {wxMDIChildFrame, new_4, 4}}, - {2688, {wxMDIChildFrame, destruct, 0}}, - {2689, {wxMDIChildFrame, activate, 0}}, - {2690, {wxMDIChildFrame, create, 4}}, - {2691, {wxMDIChildFrame, maximize, 1}}, - {2692, {wxMDIChildFrame, restore, 0}}, - {2693, {wxMDIClientWindow, new_0, 0}}, - {2694, {wxMDIClientWindow, new_2, 2}}, - {2695, {wxMDIClientWindow, destruct, 0}}, - {2696, {wxMDIClientWindow, createClient, 2}}, - {2697, {wxLayoutAlgorithm, new, 0}}, - {2698, {wxLayoutAlgorithm, layoutFrame, 2}}, - {2699, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, - {2700, {wxLayoutAlgorithm, layoutWindow, 2}}, - {2701, {wxLayoutAlgorithm, 'Destroy', undefined}}, - {2702, {wxEvent, getId, 0}}, - {2703, {wxEvent, getSkipped, 0}}, - {2704, {wxEvent, getTimestamp, 0}}, - {2705, {wxEvent, isCommandEvent, 0}}, - {2706, {wxEvent, resumePropagation, 1}}, - {2707, {wxEvent, shouldPropagate, 0}}, - {2708, {wxEvent, skip, 1}}, - {2709, {wxEvent, stopPropagation, 0}}, - {2710, {wxCommandEvent, getClientData, 0}}, - {2711, {wxCommandEvent, getExtraLong, 0}}, - {2712, {wxCommandEvent, getInt, 0}}, - {2713, {wxCommandEvent, getSelection, 0}}, - {2714, {wxCommandEvent, getString, 0}}, - {2715, {wxCommandEvent, isChecked, 0}}, - {2716, {wxCommandEvent, isSelection, 0}}, - {2717, {wxCommandEvent, setInt, 1}}, - {2718, {wxCommandEvent, setString, 1}}, - {2719, {wxScrollEvent, getOrientation, 0}}, - {2720, {wxScrollEvent, getPosition, 0}}, - {2721, {wxScrollWinEvent, getOrientation, 0}}, - {2722, {wxScrollWinEvent, getPosition, 0}}, - {2723, {wxMouseEvent, altDown, 0}}, - {2724, {wxMouseEvent, button, 1}}, - {2725, {wxMouseEvent, buttonDClick, 1}}, - {2726, {wxMouseEvent, buttonDown, 1}}, - {2727, {wxMouseEvent, buttonUp, 1}}, - {2728, {wxMouseEvent, cmdDown, 0}}, - {2729, {wxMouseEvent, controlDown, 0}}, - {2730, {wxMouseEvent, dragging, 0}}, - {2731, {wxMouseEvent, entering, 0}}, - {2732, {wxMouseEvent, getButton, 0}}, - {2735, {wxMouseEvent, getPosition, 0}}, - {2736, {wxMouseEvent, getLogicalPosition, 1}}, - {2737, {wxMouseEvent, getLinesPerAction, 0}}, - {2738, {wxMouseEvent, getWheelRotation, 0}}, - {2739, {wxMouseEvent, getWheelDelta, 0}}, - {2740, {wxMouseEvent, getX, 0}}, - {2741, {wxMouseEvent, getY, 0}}, - {2742, {wxMouseEvent, isButton, 0}}, - {2743, {wxMouseEvent, isPageScroll, 0}}, - {2744, {wxMouseEvent, leaving, 0}}, - {2745, {wxMouseEvent, leftDClick, 0}}, - {2746, {wxMouseEvent, leftDown, 0}}, - {2747, {wxMouseEvent, leftIsDown, 0}}, - {2748, {wxMouseEvent, leftUp, 0}}, - {2749, {wxMouseEvent, metaDown, 0}}, - {2750, {wxMouseEvent, middleDClick, 0}}, - {2751, {wxMouseEvent, middleDown, 0}}, - {2752, {wxMouseEvent, middleIsDown, 0}}, - {2753, {wxMouseEvent, middleUp, 0}}, - {2754, {wxMouseEvent, moving, 0}}, - {2755, {wxMouseEvent, rightDClick, 0}}, - {2756, {wxMouseEvent, rightDown, 0}}, - {2757, {wxMouseEvent, rightIsDown, 0}}, - {2758, {wxMouseEvent, rightUp, 0}}, - {2759, {wxMouseEvent, shiftDown, 0}}, - {2760, {wxSetCursorEvent, getCursor, 0}}, - {2761, {wxSetCursorEvent, getX, 0}}, - {2762, {wxSetCursorEvent, getY, 0}}, - {2763, {wxSetCursorEvent, hasCursor, 0}}, - {2764, {wxSetCursorEvent, setCursor, 1}}, - {2765, {wxKeyEvent, altDown, 0}}, - {2766, {wxKeyEvent, cmdDown, 0}}, - {2767, {wxKeyEvent, controlDown, 0}}, - {2768, {wxKeyEvent, getKeyCode, 0}}, - {2769, {wxKeyEvent, getModifiers, 0}}, - {2772, {wxKeyEvent, getPosition, 0}}, - {2773, {wxKeyEvent, getRawKeyCode, 0}}, - {2774, {wxKeyEvent, getRawKeyFlags, 0}}, - {2775, {wxKeyEvent, getUnicodeKey, 0}}, - {2776, {wxKeyEvent, getX, 0}}, - {2777, {wxKeyEvent, getY, 0}}, - {2778, {wxKeyEvent, hasModifiers, 0}}, - {2779, {wxKeyEvent, metaDown, 0}}, - {2780, {wxKeyEvent, shiftDown, 0}}, - {2781, {wxSizeEvent, getSize, 0}}, - {2782, {wxMoveEvent, getPosition, 0}}, - {2783, {wxEraseEvent, getDC, 0}}, - {2784, {wxFocusEvent, getWindow, 0}}, - {2785, {wxChildFocusEvent, getWindow, 0}}, - {2786, {wxMenuEvent, getMenu, 0}}, - {2787, {wxMenuEvent, getMenuId, 0}}, - {2788, {wxMenuEvent, isPopup, 0}}, - {2789, {wxCloseEvent, canVeto, 0}}, - {2790, {wxCloseEvent, getLoggingOff, 0}}, - {2791, {wxCloseEvent, setCanVeto, 1}}, - {2792, {wxCloseEvent, setLoggingOff, 1}}, - {2793, {wxCloseEvent, veto, 1}}, - {2794, {wxShowEvent, setShow, 1}}, - {2795, {wxShowEvent, getShow, 0}}, - {2796, {wxIconizeEvent, iconized, 0}}, - {2797, {wxJoystickEvent, buttonDown, 1}}, - {2798, {wxJoystickEvent, buttonIsDown, 1}}, - {2799, {wxJoystickEvent, buttonUp, 1}}, - {2800, {wxJoystickEvent, getButtonChange, 0}}, - {2801, {wxJoystickEvent, getButtonState, 0}}, - {2802, {wxJoystickEvent, getJoystick, 0}}, - {2803, {wxJoystickEvent, getPosition, 0}}, - {2804, {wxJoystickEvent, getZPosition, 0}}, - {2805, {wxJoystickEvent, isButton, 0}}, - {2806, {wxJoystickEvent, isMove, 0}}, - {2807, {wxJoystickEvent, isZMove, 0}}, - {2808, {wxUpdateUIEvent, canUpdate, 1}}, - {2809, {wxUpdateUIEvent, check, 1}}, - {2810, {wxUpdateUIEvent, enable, 1}}, - {2811, {wxUpdateUIEvent, show, 1}}, - {2812, {wxUpdateUIEvent, getChecked, 0}}, - {2813, {wxUpdateUIEvent, getEnabled, 0}}, - {2814, {wxUpdateUIEvent, getShown, 0}}, - {2815, {wxUpdateUIEvent, getSetChecked, 0}}, - {2816, {wxUpdateUIEvent, getSetEnabled, 0}}, - {2817, {wxUpdateUIEvent, getSetShown, 0}}, - {2818, {wxUpdateUIEvent, getSetText, 0}}, - {2819, {wxUpdateUIEvent, getText, 0}}, - {2820, {wxUpdateUIEvent, getMode, 0}}, - {2821, {wxUpdateUIEvent, getUpdateInterval, 0}}, - {2822, {wxUpdateUIEvent, resetUpdateTime, 0}}, - {2823, {wxUpdateUIEvent, setMode, 1}}, - {2824, {wxUpdateUIEvent, setText, 1}}, - {2825, {wxUpdateUIEvent, setUpdateInterval, 1}}, - {2826, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, - {2827, {wxPaletteChangedEvent, setChangedWindow, 1}}, - {2828, {wxPaletteChangedEvent, getChangedWindow, 0}}, - {2829, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, - {2830, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, - {2831, {wxNavigationKeyEvent, getDirection, 0}}, - {2832, {wxNavigationKeyEvent, setDirection, 1}}, - {2833, {wxNavigationKeyEvent, isWindowChange, 0}}, - {2834, {wxNavigationKeyEvent, setWindowChange, 1}}, - {2835, {wxNavigationKeyEvent, isFromTab, 0}}, - {2836, {wxNavigationKeyEvent, setFromTab, 1}}, - {2837, {wxNavigationKeyEvent, getCurrentFocus, 0}}, - {2838, {wxNavigationKeyEvent, setCurrentFocus, 1}}, - {2839, {wxHelpEvent, getOrigin, 0}}, - {2840, {wxHelpEvent, getPosition, 0}}, - {2841, {wxHelpEvent, setOrigin, 1}}, - {2842, {wxHelpEvent, setPosition, 1}}, - {2843, {wxContextMenuEvent, getPosition, 0}}, - {2844, {wxContextMenuEvent, setPosition, 1}}, - {2845, {wxIdleEvent, canSend, 1}}, - {2846, {wxIdleEvent, getMode, 0}}, - {2847, {wxIdleEvent, requestMore, 1}}, - {2848, {wxIdleEvent, moreRequested, 0}}, - {2849, {wxIdleEvent, setMode, 1}}, - {2850, {wxGridEvent, altDown, 0}}, - {2851, {wxGridEvent, controlDown, 0}}, - {2852, {wxGridEvent, getCol, 0}}, - {2853, {wxGridEvent, getPosition, 0}}, - {2854, {wxGridEvent, getRow, 0}}, - {2855, {wxGridEvent, metaDown, 0}}, - {2856, {wxGridEvent, selecting, 0}}, - {2857, {wxGridEvent, shiftDown, 0}}, - {2858, {wxNotifyEvent, allow, 0}}, - {2859, {wxNotifyEvent, isAllowed, 0}}, - {2860, {wxNotifyEvent, veto, 0}}, - {2861, {wxSashEvent, getEdge, 0}}, - {2862, {wxSashEvent, getDragRect, 0}}, - {2863, {wxSashEvent, getDragStatus, 0}}, - {2864, {wxListEvent, getCacheFrom, 0}}, - {2865, {wxListEvent, getCacheTo, 0}}, - {2866, {wxListEvent, getKeyCode, 0}}, - {2867, {wxListEvent, getIndex, 0}}, - {2868, {wxListEvent, getColumn, 0}}, - {2869, {wxListEvent, getPoint, 0}}, - {2870, {wxListEvent, getLabel, 0}}, - {2871, {wxListEvent, getText, 0}}, - {2872, {wxListEvent, getImage, 0}}, - {2873, {wxListEvent, getData, 0}}, - {2874, {wxListEvent, getMask, 0}}, - {2875, {wxListEvent, getItem, 0}}, - {2876, {wxListEvent, isEditCancelled, 0}}, - {2877, {wxDateEvent, getDate, 0}}, - {2878, {wxCalendarEvent, getWeekDay, 0}}, - {2879, {wxFileDirPickerEvent, getPath, 0}}, - {2880, {wxColourPickerEvent, getColour, 0}}, - {2881, {wxFontPickerEvent, getFont, 0}}, - {2882, {wxStyledTextEvent, getPosition, 0}}, - {2883, {wxStyledTextEvent, getKey, 0}}, - {2884, {wxStyledTextEvent, getModifiers, 0}}, - {2885, {wxStyledTextEvent, getModificationType, 0}}, - {2886, {wxStyledTextEvent, getText, 0}}, - {2887, {wxStyledTextEvent, getLength, 0}}, - {2888, {wxStyledTextEvent, getLinesAdded, 0}}, - {2889, {wxStyledTextEvent, getLine, 0}}, - {2890, {wxStyledTextEvent, getFoldLevelNow, 0}}, - {2891, {wxStyledTextEvent, getFoldLevelPrev, 0}}, - {2892, {wxStyledTextEvent, getMargin, 0}}, - {2893, {wxStyledTextEvent, getMessage, 0}}, - {2894, {wxStyledTextEvent, getWParam, 0}}, - {2895, {wxStyledTextEvent, getLParam, 0}}, - {2896, {wxStyledTextEvent, getListType, 0}}, - {2897, {wxStyledTextEvent, getX, 0}}, - {2898, {wxStyledTextEvent, getY, 0}}, - {2899, {wxStyledTextEvent, getDragText, 0}}, - {2900, {wxStyledTextEvent, getDragAllowMove, 0}}, - {2901, {wxStyledTextEvent, getDragResult, 0}}, - {2902, {wxStyledTextEvent, getShift, 0}}, - {2903, {wxStyledTextEvent, getControl, 0}}, - {2904, {wxStyledTextEvent, getAlt, 0}}, - {2905, {utils, getKeyState, 1}}, - {2906, {utils, getMousePosition, 2}}, - {2907, {utils, getMouseState, 0}}, - {2908, {utils, setDetectableAutoRepeat, 1}}, - {2909, {utils, bell, 0}}, - {2910, {utils, findMenuItemId, 3}}, - {2911, {utils, genericFindWindowAtPoint, 1}}, - {2912, {utils, findWindowAtPoint, 1}}, - {2913, {utils, beginBusyCursor, 1}}, - {2914, {utils, endBusyCursor, 0}}, - {2915, {utils, isBusy, 0}}, - {2916, {utils, shutdown, 1}}, - {2917, {utils, shell, 1}}, - {2918, {utils, launchDefaultBrowser, 2}}, - {2919, {utils, getEmailAddress, 0}}, - {2920, {utils, getUserId, 0}}, - {2921, {utils, getHomeDir, 0}}, - {2922, {utils, newId, 0}}, - {2923, {utils, registerId, 1}}, - {2924, {utils, getCurrentId, 0}}, - {2925, {utils, getOsDescription, 0}}, - {2926, {utils, isPlatformLittleEndian, 0}}, - {2927, {utils, isPlatform64Bit, 0}}, - {2928, {gdicmn, displaySize, 2}}, - {2929, {gdicmn, setCursor, 1}}, - {2930, {wxPrintout, new, 1}}, - {2931, {wxPrintout, destruct, 0}}, - {2932, {wxPrintout, getDC, 0}}, - {2933, {wxPrintout, getPageSizeMM, 2}}, - {2934, {wxPrintout, getPageSizePixels, 2}}, - {2935, {wxPrintout, getPaperRectPixels, 0}}, - {2936, {wxPrintout, getPPIPrinter, 2}}, - {2937, {wxPrintout, getPPIScreen, 2}}, - {2938, {wxPrintout, getTitle, 0}}, - {2939, {wxPrintout, isPreview, 0}}, - {2940, {wxPrintout, fitThisSizeToPaper, 1}}, - {2941, {wxPrintout, fitThisSizeToPage, 1}}, - {2942, {wxPrintout, fitThisSizeToPageMargins, 2}}, - {2943, {wxPrintout, mapScreenSizeToPaper, 0}}, - {2944, {wxPrintout, mapScreenSizeToPage, 0}}, - {2945, {wxPrintout, mapScreenSizeToPageMargins, 1}}, - {2946, {wxPrintout, mapScreenSizeToDevice, 0}}, - {2947, {wxPrintout, getLogicalPaperRect, 0}}, - {2948, {wxPrintout, getLogicalPageRect, 0}}, - {2949, {wxPrintout, getLogicalPageMarginsRect, 1}}, - {2950, {wxPrintout, setLogicalOrigin, 2}}, - {2951, {wxPrintout, offsetLogicalOrigin, 2}}, - {2952, {wxStyledTextCtrl, new_2, 2}}, - {2953, {wxStyledTextCtrl, new_0, 0}}, - {2954, {wxStyledTextCtrl, destruct, 0}}, - {2955, {wxStyledTextCtrl, create, 2}}, - {2956, {wxStyledTextCtrl, addText, 1}}, - {2957, {wxStyledTextCtrl, addStyledText, 1}}, - {2958, {wxStyledTextCtrl, insertText, 2}}, - {2959, {wxStyledTextCtrl, clearAll, 0}}, - {2960, {wxStyledTextCtrl, clearDocumentStyle, 0}}, - {2961, {wxStyledTextCtrl, getLength, 0}}, - {2962, {wxStyledTextCtrl, getCharAt, 1}}, - {2963, {wxStyledTextCtrl, getCurrentPos, 0}}, - {2964, {wxStyledTextCtrl, getAnchor, 0}}, - {2965, {wxStyledTextCtrl, getStyleAt, 1}}, - {2966, {wxStyledTextCtrl, redo, 0}}, - {2967, {wxStyledTextCtrl, setUndoCollection, 1}}, - {2968, {wxStyledTextCtrl, selectAll, 0}}, - {2969, {wxStyledTextCtrl, setSavePoint, 0}}, - {2970, {wxStyledTextCtrl, getStyledText, 2}}, - {2971, {wxStyledTextCtrl, canRedo, 0}}, - {2972, {wxStyledTextCtrl, markerLineFromHandle, 1}}, - {2973, {wxStyledTextCtrl, markerDeleteHandle, 1}}, - {2974, {wxStyledTextCtrl, getUndoCollection, 0}}, - {2975, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, - {2976, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, - {2977, {wxStyledTextCtrl, positionFromPoint, 1}}, - {2978, {wxStyledTextCtrl, positionFromPointClose, 2}}, - {2979, {wxStyledTextCtrl, gotoLine, 1}}, - {2980, {wxStyledTextCtrl, gotoPos, 1}}, - {2981, {wxStyledTextCtrl, setAnchor, 1}}, - {2982, {wxStyledTextCtrl, getCurLine, 1}}, - {2983, {wxStyledTextCtrl, getEndStyled, 0}}, - {2984, {wxStyledTextCtrl, convertEOLs, 1}}, - {2985, {wxStyledTextCtrl, getEOLMode, 0}}, - {2986, {wxStyledTextCtrl, setEOLMode, 1}}, - {2987, {wxStyledTextCtrl, startStyling, 2}}, - {2988, {wxStyledTextCtrl, setStyling, 2}}, - {2989, {wxStyledTextCtrl, getBufferedDraw, 0}}, - {2990, {wxStyledTextCtrl, setBufferedDraw, 1}}, - {2991, {wxStyledTextCtrl, setTabWidth, 1}}, - {2992, {wxStyledTextCtrl, getTabWidth, 0}}, - {2993, {wxStyledTextCtrl, setCodePage, 1}}, - {2994, {wxStyledTextCtrl, markerDefine, 3}}, - {2995, {wxStyledTextCtrl, markerSetForeground, 2}}, - {2996, {wxStyledTextCtrl, markerSetBackground, 2}}, - {2997, {wxStyledTextCtrl, markerAdd, 2}}, - {2998, {wxStyledTextCtrl, markerDelete, 2}}, - {2999, {wxStyledTextCtrl, markerDeleteAll, 1}}, - {3000, {wxStyledTextCtrl, markerGet, 1}}, - {3001, {wxStyledTextCtrl, markerNext, 2}}, - {3002, {wxStyledTextCtrl, markerPrevious, 2}}, - {3003, {wxStyledTextCtrl, markerDefineBitmap, 2}}, - {3004, {wxStyledTextCtrl, markerAddSet, 2}}, - {3005, {wxStyledTextCtrl, markerSetAlpha, 2}}, - {3006, {wxStyledTextCtrl, setMarginType, 2}}, - {3007, {wxStyledTextCtrl, getMarginType, 1}}, - {3008, {wxStyledTextCtrl, setMarginWidth, 2}}, - {3009, {wxStyledTextCtrl, getMarginWidth, 1}}, - {3010, {wxStyledTextCtrl, setMarginMask, 2}}, - {3011, {wxStyledTextCtrl, getMarginMask, 1}}, - {3012, {wxStyledTextCtrl, setMarginSensitive, 2}}, - {3013, {wxStyledTextCtrl, getMarginSensitive, 1}}, - {3014, {wxStyledTextCtrl, styleClearAll, 0}}, - {3015, {wxStyledTextCtrl, styleSetForeground, 2}}, - {3016, {wxStyledTextCtrl, styleSetBackground, 2}}, - {3017, {wxStyledTextCtrl, styleSetBold, 2}}, - {3018, {wxStyledTextCtrl, styleSetItalic, 2}}, - {3019, {wxStyledTextCtrl, styleSetSize, 2}}, - {3020, {wxStyledTextCtrl, styleSetFaceName, 2}}, - {3021, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, - {3022, {wxStyledTextCtrl, styleResetDefault, 0}}, - {3023, {wxStyledTextCtrl, styleSetUnderline, 2}}, - {3024, {wxStyledTextCtrl, styleSetCase, 2}}, - {3025, {wxStyledTextCtrl, styleSetHotSpot, 2}}, - {3026, {wxStyledTextCtrl, setSelForeground, 2}}, - {3027, {wxStyledTextCtrl, setSelBackground, 2}}, - {3028, {wxStyledTextCtrl, getSelAlpha, 0}}, - {3029, {wxStyledTextCtrl, setSelAlpha, 1}}, - {3030, {wxStyledTextCtrl, setCaretForeground, 1}}, - {3031, {wxStyledTextCtrl, cmdKeyAssign, 3}}, - {3032, {wxStyledTextCtrl, cmdKeyClear, 2}}, - {3033, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, - {3034, {wxStyledTextCtrl, setStyleBytes, 2}}, - {3035, {wxStyledTextCtrl, styleSetVisible, 2}}, - {3036, {wxStyledTextCtrl, getCaretPeriod, 0}}, - {3037, {wxStyledTextCtrl, setCaretPeriod, 1}}, - {3038, {wxStyledTextCtrl, setWordChars, 1}}, - {3039, {wxStyledTextCtrl, beginUndoAction, 0}}, - {3040, {wxStyledTextCtrl, endUndoAction, 0}}, - {3041, {wxStyledTextCtrl, indicatorSetStyle, 2}}, - {3042, {wxStyledTextCtrl, indicatorGetStyle, 1}}, - {3043, {wxStyledTextCtrl, indicatorSetForeground, 2}}, - {3044, {wxStyledTextCtrl, indicatorGetForeground, 1}}, - {3045, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, - {3046, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, - {3047, {wxStyledTextCtrl, getStyleBits, 0}}, - {3048, {wxStyledTextCtrl, setLineState, 2}}, - {3049, {wxStyledTextCtrl, getLineState, 1}}, - {3050, {wxStyledTextCtrl, getMaxLineState, 0}}, - {3051, {wxStyledTextCtrl, getCaretLineVisible, 0}}, - {3052, {wxStyledTextCtrl, setCaretLineVisible, 1}}, - {3053, {wxStyledTextCtrl, getCaretLineBackground, 0}}, - {3054, {wxStyledTextCtrl, setCaretLineBackground, 1}}, - {3055, {wxStyledTextCtrl, autoCompShow, 2}}, - {3056, {wxStyledTextCtrl, autoCompCancel, 0}}, - {3057, {wxStyledTextCtrl, autoCompActive, 0}}, - {3058, {wxStyledTextCtrl, autoCompPosStart, 0}}, - {3059, {wxStyledTextCtrl, autoCompComplete, 0}}, - {3060, {wxStyledTextCtrl, autoCompStops, 1}}, - {3061, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, - {3062, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, - {3063, {wxStyledTextCtrl, autoCompSelect, 1}}, - {3064, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, - {3065, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, - {3066, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, - {3067, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, - {3068, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, - {3069, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, - {3070, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, - {3071, {wxStyledTextCtrl, userListShow, 2}}, - {3072, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, - {3073, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, - {3074, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, - {3075, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, - {3076, {wxStyledTextCtrl, registerImage, 2}}, - {3077, {wxStyledTextCtrl, clearRegisteredImages, 0}}, - {3078, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, - {3079, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, - {3080, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, - {3081, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, - {3082, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, - {3083, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, - {3084, {wxStyledTextCtrl, setIndent, 1}}, - {3085, {wxStyledTextCtrl, getIndent, 0}}, - {3086, {wxStyledTextCtrl, setUseTabs, 1}}, - {3087, {wxStyledTextCtrl, getUseTabs, 0}}, - {3088, {wxStyledTextCtrl, setLineIndentation, 2}}, - {3089, {wxStyledTextCtrl, getLineIndentation, 1}}, - {3090, {wxStyledTextCtrl, getLineIndentPosition, 1}}, - {3091, {wxStyledTextCtrl, getColumn, 1}}, - {3092, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, - {3093, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, - {3094, {wxStyledTextCtrl, setIndentationGuides, 1}}, - {3095, {wxStyledTextCtrl, getIndentationGuides, 0}}, - {3096, {wxStyledTextCtrl, setHighlightGuide, 1}}, - {3097, {wxStyledTextCtrl, getHighlightGuide, 0}}, - {3098, {wxStyledTextCtrl, getLineEndPosition, 1}}, - {3099, {wxStyledTextCtrl, getCodePage, 0}}, - {3100, {wxStyledTextCtrl, getCaretForeground, 0}}, - {3101, {wxStyledTextCtrl, getReadOnly, 0}}, - {3102, {wxStyledTextCtrl, setCurrentPos, 1}}, - {3103, {wxStyledTextCtrl, setSelectionStart, 1}}, - {3104, {wxStyledTextCtrl, getSelectionStart, 0}}, - {3105, {wxStyledTextCtrl, setSelectionEnd, 1}}, - {3106, {wxStyledTextCtrl, getSelectionEnd, 0}}, - {3107, {wxStyledTextCtrl, setPrintMagnification, 1}}, - {3108, {wxStyledTextCtrl, getPrintMagnification, 0}}, - {3109, {wxStyledTextCtrl, setPrintColourMode, 1}}, - {3110, {wxStyledTextCtrl, getPrintColourMode, 0}}, - {3111, {wxStyledTextCtrl, findText, 4}}, - {3112, {wxStyledTextCtrl, formatRange, 7}}, - {3113, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, - {3114, {wxStyledTextCtrl, getLine, 1}}, - {3115, {wxStyledTextCtrl, getLineCount, 0}}, - {3116, {wxStyledTextCtrl, setMarginLeft, 1}}, - {3117, {wxStyledTextCtrl, getMarginLeft, 0}}, - {3118, {wxStyledTextCtrl, setMarginRight, 1}}, - {3119, {wxStyledTextCtrl, getMarginRight, 0}}, - {3120, {wxStyledTextCtrl, getModify, 0}}, - {3121, {wxStyledTextCtrl, setSelection, 2}}, - {3122, {wxStyledTextCtrl, getSelectedText, 0}}, - {3123, {wxStyledTextCtrl, getTextRange, 2}}, - {3124, {wxStyledTextCtrl, hideSelection, 1}}, - {3125, {wxStyledTextCtrl, lineFromPosition, 1}}, - {3126, {wxStyledTextCtrl, positionFromLine, 1}}, - {3127, {wxStyledTextCtrl, lineScroll, 2}}, - {3128, {wxStyledTextCtrl, ensureCaretVisible, 0}}, - {3129, {wxStyledTextCtrl, replaceSelection, 1}}, - {3130, {wxStyledTextCtrl, setReadOnly, 1}}, - {3131, {wxStyledTextCtrl, canPaste, 0}}, - {3132, {wxStyledTextCtrl, canUndo, 0}}, - {3133, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, - {3134, {wxStyledTextCtrl, undo, 0}}, - {3135, {wxStyledTextCtrl, cut, 0}}, - {3136, {wxStyledTextCtrl, copy, 0}}, - {3137, {wxStyledTextCtrl, paste, 0}}, - {3138, {wxStyledTextCtrl, clear, 0}}, - {3139, {wxStyledTextCtrl, setText, 1}}, - {3140, {wxStyledTextCtrl, getText, 0}}, - {3141, {wxStyledTextCtrl, getTextLength, 0}}, - {3142, {wxStyledTextCtrl, getOvertype, 0}}, - {3143, {wxStyledTextCtrl, setCaretWidth, 1}}, - {3144, {wxStyledTextCtrl, getCaretWidth, 0}}, - {3145, {wxStyledTextCtrl, setTargetStart, 1}}, - {3146, {wxStyledTextCtrl, getTargetStart, 0}}, - {3147, {wxStyledTextCtrl, setTargetEnd, 1}}, - {3148, {wxStyledTextCtrl, getTargetEnd, 0}}, - {3149, {wxStyledTextCtrl, replaceTarget, 1}}, - {3150, {wxStyledTextCtrl, searchInTarget, 1}}, - {3151, {wxStyledTextCtrl, setSearchFlags, 1}}, - {3152, {wxStyledTextCtrl, getSearchFlags, 0}}, - {3153, {wxStyledTextCtrl, callTipShow, 2}}, - {3154, {wxStyledTextCtrl, callTipCancel, 0}}, - {3155, {wxStyledTextCtrl, callTipActive, 0}}, - {3156, {wxStyledTextCtrl, callTipPosAtStart, 0}}, - {3157, {wxStyledTextCtrl, callTipSetHighlight, 2}}, - {3158, {wxStyledTextCtrl, callTipSetBackground, 1}}, - {3159, {wxStyledTextCtrl, callTipSetForeground, 1}}, - {3160, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, - {3161, {wxStyledTextCtrl, callTipUseStyle, 1}}, - {3162, {wxStyledTextCtrl, visibleFromDocLine, 1}}, - {3163, {wxStyledTextCtrl, docLineFromVisible, 1}}, - {3164, {wxStyledTextCtrl, wrapCount, 1}}, - {3165, {wxStyledTextCtrl, setFoldLevel, 2}}, - {3166, {wxStyledTextCtrl, getFoldLevel, 1}}, - {3167, {wxStyledTextCtrl, getLastChild, 2}}, - {3168, {wxStyledTextCtrl, getFoldParent, 1}}, - {3169, {wxStyledTextCtrl, showLines, 2}}, - {3170, {wxStyledTextCtrl, hideLines, 2}}, - {3171, {wxStyledTextCtrl, getLineVisible, 1}}, - {3172, {wxStyledTextCtrl, setFoldExpanded, 2}}, - {3173, {wxStyledTextCtrl, getFoldExpanded, 1}}, - {3174, {wxStyledTextCtrl, toggleFold, 1}}, - {3175, {wxStyledTextCtrl, ensureVisible, 1}}, - {3176, {wxStyledTextCtrl, setFoldFlags, 1}}, - {3177, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, - {3178, {wxStyledTextCtrl, setTabIndents, 1}}, - {3179, {wxStyledTextCtrl, getTabIndents, 0}}, - {3180, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, - {3181, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, - {3182, {wxStyledTextCtrl, setMouseDwellTime, 1}}, - {3183, {wxStyledTextCtrl, getMouseDwellTime, 0}}, - {3184, {wxStyledTextCtrl, wordStartPosition, 2}}, - {3185, {wxStyledTextCtrl, wordEndPosition, 2}}, - {3186, {wxStyledTextCtrl, setWrapMode, 1}}, - {3187, {wxStyledTextCtrl, getWrapMode, 0}}, - {3188, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, - {3189, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, - {3190, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, - {3191, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, - {3192, {wxStyledTextCtrl, setWrapStartIndent, 1}}, - {3193, {wxStyledTextCtrl, getWrapStartIndent, 0}}, - {3194, {wxStyledTextCtrl, setLayoutCache, 1}}, - {3195, {wxStyledTextCtrl, getLayoutCache, 0}}, - {3196, {wxStyledTextCtrl, setScrollWidth, 1}}, - {3197, {wxStyledTextCtrl, getScrollWidth, 0}}, - {3198, {wxStyledTextCtrl, textWidth, 2}}, - {3199, {wxStyledTextCtrl, getEndAtLastLine, 0}}, - {3200, {wxStyledTextCtrl, textHeight, 1}}, - {3201, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, - {3202, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, - {3203, {wxStyledTextCtrl, appendText, 1}}, - {3204, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, - {3205, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, - {3206, {wxStyledTextCtrl, targetFromSelection, 0}}, - {3207, {wxStyledTextCtrl, linesJoin, 0}}, - {3208, {wxStyledTextCtrl, linesSplit, 1}}, - {3209, {wxStyledTextCtrl, setFoldMarginColour, 2}}, - {3210, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, - {3211, {wxStyledTextCtrl, lineDown, 0}}, - {3212, {wxStyledTextCtrl, lineDownExtend, 0}}, - {3213, {wxStyledTextCtrl, lineUp, 0}}, - {3214, {wxStyledTextCtrl, lineUpExtend, 0}}, - {3215, {wxStyledTextCtrl, charLeft, 0}}, - {3216, {wxStyledTextCtrl, charLeftExtend, 0}}, - {3217, {wxStyledTextCtrl, charRight, 0}}, - {3218, {wxStyledTextCtrl, charRightExtend, 0}}, - {3219, {wxStyledTextCtrl, wordLeft, 0}}, - {3220, {wxStyledTextCtrl, wordLeftExtend, 0}}, - {3221, {wxStyledTextCtrl, wordRight, 0}}, - {3222, {wxStyledTextCtrl, wordRightExtend, 0}}, - {3223, {wxStyledTextCtrl, home, 0}}, - {3224, {wxStyledTextCtrl, homeExtend, 0}}, - {3225, {wxStyledTextCtrl, lineEnd, 0}}, - {3226, {wxStyledTextCtrl, lineEndExtend, 0}}, - {3227, {wxStyledTextCtrl, documentStart, 0}}, - {3228, {wxStyledTextCtrl, documentStartExtend, 0}}, - {3229, {wxStyledTextCtrl, documentEnd, 0}}, - {3230, {wxStyledTextCtrl, documentEndExtend, 0}}, - {3231, {wxStyledTextCtrl, pageUp, 0}}, - {3232, {wxStyledTextCtrl, pageUpExtend, 0}}, - {3233, {wxStyledTextCtrl, pageDown, 0}}, - {3234, {wxStyledTextCtrl, pageDownExtend, 0}}, - {3235, {wxStyledTextCtrl, editToggleOvertype, 0}}, - {3236, {wxStyledTextCtrl, cancel, 0}}, - {3237, {wxStyledTextCtrl, deleteBack, 0}}, - {3238, {wxStyledTextCtrl, tab, 0}}, - {3239, {wxStyledTextCtrl, backTab, 0}}, - {3240, {wxStyledTextCtrl, newLine, 0}}, - {3241, {wxStyledTextCtrl, formFeed, 0}}, - {3242, {wxStyledTextCtrl, vCHome, 0}}, - {3243, {wxStyledTextCtrl, vCHomeExtend, 0}}, - {3244, {wxStyledTextCtrl, zoomIn, 0}}, - {3245, {wxStyledTextCtrl, zoomOut, 0}}, - {3246, {wxStyledTextCtrl, delWordLeft, 0}}, - {3247, {wxStyledTextCtrl, delWordRight, 0}}, - {3248, {wxStyledTextCtrl, lineCut, 0}}, - {3249, {wxStyledTextCtrl, lineDelete, 0}}, - {3250, {wxStyledTextCtrl, lineTranspose, 0}}, - {3251, {wxStyledTextCtrl, lineDuplicate, 0}}, - {3252, {wxStyledTextCtrl, lowerCase, 0}}, - {3253, {wxStyledTextCtrl, upperCase, 0}}, - {3254, {wxStyledTextCtrl, lineScrollDown, 0}}, - {3255, {wxStyledTextCtrl, lineScrollUp, 0}}, - {3256, {wxStyledTextCtrl, deleteBackNotLine, 0}}, - {3257, {wxStyledTextCtrl, homeDisplay, 0}}, - {3258, {wxStyledTextCtrl, homeDisplayExtend, 0}}, - {3259, {wxStyledTextCtrl, lineEndDisplay, 0}}, - {3260, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, - {3261, {wxStyledTextCtrl, homeWrapExtend, 0}}, - {3262, {wxStyledTextCtrl, lineEndWrap, 0}}, - {3263, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, - {3264, {wxStyledTextCtrl, vCHomeWrap, 0}}, - {3265, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, - {3266, {wxStyledTextCtrl, lineCopy, 0}}, - {3267, {wxStyledTextCtrl, moveCaretInsideView, 0}}, - {3268, {wxStyledTextCtrl, lineLength, 1}}, - {3269, {wxStyledTextCtrl, braceHighlight, 2}}, - {3270, {wxStyledTextCtrl, braceBadLight, 1}}, - {3271, {wxStyledTextCtrl, braceMatch, 1}}, - {3272, {wxStyledTextCtrl, getViewEOL, 0}}, - {3273, {wxStyledTextCtrl, setViewEOL, 1}}, - {3274, {wxStyledTextCtrl, setModEventMask, 1}}, - {3275, {wxStyledTextCtrl, getEdgeColumn, 0}}, - {3276, {wxStyledTextCtrl, setEdgeColumn, 1}}, - {3277, {wxStyledTextCtrl, setEdgeMode, 1}}, - {3278, {wxStyledTextCtrl, getEdgeMode, 0}}, - {3279, {wxStyledTextCtrl, getEdgeColour, 0}}, - {3280, {wxStyledTextCtrl, setEdgeColour, 1}}, - {3281, {wxStyledTextCtrl, searchAnchor, 0}}, - {3282, {wxStyledTextCtrl, searchNext, 2}}, - {3283, {wxStyledTextCtrl, searchPrev, 2}}, - {3284, {wxStyledTextCtrl, linesOnScreen, 0}}, - {3285, {wxStyledTextCtrl, usePopUp, 1}}, - {3286, {wxStyledTextCtrl, selectionIsRectangle, 0}}, - {3287, {wxStyledTextCtrl, setZoom, 1}}, - {3288, {wxStyledTextCtrl, getZoom, 0}}, - {3289, {wxStyledTextCtrl, getModEventMask, 0}}, - {3290, {wxStyledTextCtrl, setSTCFocus, 1}}, - {3291, {wxStyledTextCtrl, getSTCFocus, 0}}, - {3292, {wxStyledTextCtrl, setStatus, 1}}, - {3293, {wxStyledTextCtrl, getStatus, 0}}, - {3294, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, - {3295, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, - {3296, {wxStyledTextCtrl, setSTCCursor, 1}}, - {3297, {wxStyledTextCtrl, getSTCCursor, 0}}, - {3298, {wxStyledTextCtrl, setControlCharSymbol, 1}}, - {3299, {wxStyledTextCtrl, getControlCharSymbol, 0}}, - {3300, {wxStyledTextCtrl, wordPartLeft, 0}}, - {3301, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, - {3302, {wxStyledTextCtrl, wordPartRight, 0}}, - {3303, {wxStyledTextCtrl, wordPartRightExtend, 0}}, - {3304, {wxStyledTextCtrl, setVisiblePolicy, 2}}, - {3305, {wxStyledTextCtrl, delLineLeft, 0}}, - {3306, {wxStyledTextCtrl, delLineRight, 0}}, - {3307, {wxStyledTextCtrl, getXOffset, 0}}, - {3308, {wxStyledTextCtrl, chooseCaretX, 0}}, - {3309, {wxStyledTextCtrl, setXCaretPolicy, 2}}, - {3310, {wxStyledTextCtrl, setYCaretPolicy, 2}}, - {3311, {wxStyledTextCtrl, getPrintWrapMode, 0}}, - {3312, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, - {3313, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, - {3314, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, - {3315, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, - {3316, {wxStyledTextCtrl, paraDownExtend, 0}}, - {3317, {wxStyledTextCtrl, paraUp, 0}}, - {3318, {wxStyledTextCtrl, paraUpExtend, 0}}, - {3319, {wxStyledTextCtrl, positionBefore, 1}}, - {3320, {wxStyledTextCtrl, positionAfter, 1}}, - {3321, {wxStyledTextCtrl, copyRange, 2}}, - {3322, {wxStyledTextCtrl, copyText, 2}}, - {3323, {wxStyledTextCtrl, setSelectionMode, 1}}, - {3324, {wxStyledTextCtrl, getSelectionMode, 0}}, - {3325, {wxStyledTextCtrl, lineDownRectExtend, 0}}, - {3326, {wxStyledTextCtrl, lineUpRectExtend, 0}}, - {3327, {wxStyledTextCtrl, charLeftRectExtend, 0}}, - {3328, {wxStyledTextCtrl, charRightRectExtend, 0}}, - {3329, {wxStyledTextCtrl, homeRectExtend, 0}}, - {3330, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, - {3331, {wxStyledTextCtrl, lineEndRectExtend, 0}}, - {3332, {wxStyledTextCtrl, pageUpRectExtend, 0}}, - {3333, {wxStyledTextCtrl, pageDownRectExtend, 0}}, - {3334, {wxStyledTextCtrl, stutteredPageUp, 0}}, - {3335, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, - {3336, {wxStyledTextCtrl, stutteredPageDown, 0}}, - {3337, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, - {3338, {wxStyledTextCtrl, wordLeftEnd, 0}}, - {3339, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, - {3340, {wxStyledTextCtrl, wordRightEnd, 0}}, - {3341, {wxStyledTextCtrl, wordRightEndExtend, 0}}, - {3342, {wxStyledTextCtrl, setWhitespaceChars, 1}}, - {3343, {wxStyledTextCtrl, setCharsDefault, 0}}, - {3344, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, - {3345, {wxStyledTextCtrl, allocate, 1}}, - {3346, {wxStyledTextCtrl, findColumn, 2}}, - {3347, {wxStyledTextCtrl, getCaretSticky, 0}}, - {3348, {wxStyledTextCtrl, setCaretSticky, 1}}, - {3349, {wxStyledTextCtrl, toggleCaretSticky, 0}}, - {3350, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, - {3351, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, - {3352, {wxStyledTextCtrl, selectionDuplicate, 0}}, - {3353, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, - {3354, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, - {3355, {wxStyledTextCtrl, startRecord, 0}}, - {3356, {wxStyledTextCtrl, stopRecord, 0}}, - {3357, {wxStyledTextCtrl, setLexer, 1}}, - {3358, {wxStyledTextCtrl, getLexer, 0}}, - {3359, {wxStyledTextCtrl, colourise, 2}}, - {3360, {wxStyledTextCtrl, setProperty, 2}}, - {3361, {wxStyledTextCtrl, setKeyWords, 2}}, - {3362, {wxStyledTextCtrl, setLexerLanguage, 1}}, - {3363, {wxStyledTextCtrl, getProperty, 1}}, - {3364, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, - {3365, {wxStyledTextCtrl, getCurrentLine, 0}}, - {3366, {wxStyledTextCtrl, styleSetSpec, 2}}, - {3367, {wxStyledTextCtrl, styleSetFont, 2}}, - {3368, {wxStyledTextCtrl, styleSetFontAttr, 7}}, - {3369, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, - {3370, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, - {3371, {wxStyledTextCtrl, cmdKeyExecute, 1}}, - {3372, {wxStyledTextCtrl, setMargins, 2}}, - {3373, {wxStyledTextCtrl, getSelection, 2}}, - {3374, {wxStyledTextCtrl, pointFromPosition, 1}}, - {3375, {wxStyledTextCtrl, scrollToLine, 1}}, - {3376, {wxStyledTextCtrl, scrollToColumn, 1}}, - {3377, {wxStyledTextCtrl, setVScrollBar, 1}}, - {3378, {wxStyledTextCtrl, setHScrollBar, 1}}, - {3379, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, - {3380, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, - {3381, {wxStyledTextCtrl, saveFile, 1}}, - {3382, {wxStyledTextCtrl, loadFile, 1}}, - {3383, {wxStyledTextCtrl, doDragOver, 3}}, - {3384, {wxStyledTextCtrl, doDropText, 3}}, - {3385, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, - {3386, {wxStyledTextCtrl, addTextRaw, 1}}, - {3387, {wxStyledTextCtrl, insertTextRaw, 2}}, - {3388, {wxStyledTextCtrl, getCurLineRaw, 1}}, - {3389, {wxStyledTextCtrl, getLineRaw, 1}}, - {3390, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, - {3391, {wxStyledTextCtrl, getTextRangeRaw, 2}}, - {3392, {wxStyledTextCtrl, setTextRaw, 1}}, - {3393, {wxStyledTextCtrl, getTextRaw, 0}}, - {3394, {wxStyledTextCtrl, appendTextRaw, 1}}, - {3395, {wxArtProvider, getBitmap, 2}}, - {3396, {wxArtProvider, getIcon, 2}}, - {3397, {wxTreeEvent, getKeyCode, 0}}, - {3398, {wxTreeEvent, getItem, 0}}, - {3399, {wxTreeEvent, getKeyEvent, 0}}, - {3400, {wxTreeEvent, getLabel, 0}}, - {3401, {wxTreeEvent, getOldItem, 0}}, - {3402, {wxTreeEvent, getPoint, 0}}, - {3403, {wxTreeEvent, isEditCancelled, 0}}, - {3404, {wxTreeEvent, setToolTip, 1}}, - {3405, {wxNotebookEvent, getOldSelection, 0}}, - {3406, {wxNotebookEvent, getSelection, 0}}, - {3407, {wxNotebookEvent, setOldSelection, 1}}, - {3408, {wxNotebookEvent, setSelection, 1}}, - {3409, {wxFileDataObject, new, 0}}, - {3410, {wxFileDataObject, addFile, 1}}, - {3411, {wxFileDataObject, getFilenames, 0}}, - {3412, {wxFileDataObject, 'Destroy', undefined}}, - {3413, {wxTextDataObject, new, 1}}, - {3414, {wxTextDataObject, getTextLength, 0}}, - {3415, {wxTextDataObject, getText, 0}}, - {3416, {wxTextDataObject, setText, 1}}, - {3417, {wxTextDataObject, 'Destroy', undefined}}, - {3418, {wxBitmapDataObject, new_1_1, 1}}, - {3419, {wxBitmapDataObject, new_1_0, 1}}, - {3420, {wxBitmapDataObject, getBitmap, 0}}, - {3421, {wxBitmapDataObject, setBitmap, 1}}, - {3422, {wxBitmapDataObject, 'Destroy', undefined}}, - {3424, {wxClipboard, new, 0}}, - {3425, {wxClipboard, destruct, 0}}, - {3426, {wxClipboard, addData, 1}}, - {3427, {wxClipboard, clear, 0}}, - {3428, {wxClipboard, close, 0}}, - {3429, {wxClipboard, flush, 0}}, - {3430, {wxClipboard, getData, 1}}, - {3431, {wxClipboard, isOpened, 0}}, - {3432, {wxClipboard, open, 0}}, - {3433, {wxClipboard, setData, 1}}, - {3435, {wxClipboard, usePrimarySelection, 1}}, - {3436, {wxClipboard, isSupported, 1}}, - {3437, {wxClipboard, get, 0}}, - {3438, {wxSpinEvent, getPosition, 0}}, - {3439, {wxSpinEvent, setPosition, 1}}, - {3440, {wxSplitterWindow, new_0, 0}}, - {3441, {wxSplitterWindow, new_2, 2}}, - {3442, {wxSplitterWindow, destruct, 0}}, - {3443, {wxSplitterWindow, create, 2}}, - {3444, {wxSplitterWindow, getMinimumPaneSize, 0}}, - {3445, {wxSplitterWindow, getSashGravity, 0}}, - {3446, {wxSplitterWindow, getSashPosition, 0}}, - {3447, {wxSplitterWindow, getSplitMode, 0}}, - {3448, {wxSplitterWindow, getWindow1, 0}}, - {3449, {wxSplitterWindow, getWindow2, 0}}, - {3450, {wxSplitterWindow, initialize, 1}}, - {3451, {wxSplitterWindow, isSplit, 0}}, - {3452, {wxSplitterWindow, replaceWindow, 2}}, - {3453, {wxSplitterWindow, setSashGravity, 1}}, - {3454, {wxSplitterWindow, setSashPosition, 2}}, - {3455, {wxSplitterWindow, setSashSize, 1}}, - {3456, {wxSplitterWindow, setMinimumPaneSize, 1}}, - {3457, {wxSplitterWindow, setSplitMode, 1}}, - {3458, {wxSplitterWindow, splitHorizontally, 3}}, - {3459, {wxSplitterWindow, splitVertically, 3}}, - {3460, {wxSplitterWindow, unsplit, 1}}, - {3461, {wxSplitterWindow, updateSize, 0}}, - {3462, {wxSplitterEvent, getSashPosition, 0}}, - {3463, {wxSplitterEvent, getX, 0}}, - {3464, {wxSplitterEvent, getY, 0}}, - {3465, {wxSplitterEvent, getWindowBeingRemoved, 0}}, - {3466, {wxSplitterEvent, setSashPosition, 1}}, - {3467, {wxHtmlWindow, new_0, 0}}, - {3468, {wxHtmlWindow, new_2, 2}}, - {3469, {wxHtmlWindow, appendToPage, 1}}, - {3470, {wxHtmlWindow, getOpenedAnchor, 0}}, - {3471, {wxHtmlWindow, getOpenedPage, 0}}, - {3472, {wxHtmlWindow, getOpenedPageTitle, 0}}, - {3473, {wxHtmlWindow, getRelatedFrame, 0}}, - {3474, {wxHtmlWindow, historyBack, 0}}, - {3475, {wxHtmlWindow, historyCanBack, 0}}, - {3476, {wxHtmlWindow, historyCanForward, 0}}, - {3477, {wxHtmlWindow, historyClear, 0}}, - {3478, {wxHtmlWindow, historyForward, 0}}, - {3479, {wxHtmlWindow, loadFile, 1}}, - {3480, {wxHtmlWindow, loadPage, 1}}, - {3481, {wxHtmlWindow, selectAll, 0}}, - {3482, {wxHtmlWindow, selectionToText, 0}}, - {3483, {wxHtmlWindow, selectLine, 1}}, - {3484, {wxHtmlWindow, selectWord, 1}}, - {3485, {wxHtmlWindow, setBorders, 1}}, - {3486, {wxHtmlWindow, setFonts, 3}}, - {3487, {wxHtmlWindow, setPage, 1}}, - {3488, {wxHtmlWindow, setRelatedFrame, 2}}, - {3489, {wxHtmlWindow, setRelatedStatusBar, 1}}, - {3490, {wxHtmlWindow, toText, 0}}, - {3491, {wxHtmlWindow, 'Destroy', undefined}}, - {3492, {wxHtmlLinkEvent, getLinkInfo, 0}}, - {3493, {wxSystemSettings, getColour, 1}}, - {3494, {wxSystemSettings, getFont, 1}}, - {3495, {wxSystemSettings, getMetric, 2}}, - {3496, {wxSystemSettings, getScreenType, 0}}, - {3497, {wxSystemOptions, getOption, 1}}, - {3498, {wxSystemOptions, getOptionInt, 1}}, - {3499, {wxSystemOptions, hasOption, 1}}, - {3500, {wxSystemOptions, isFalse, 1}}, - {3501, {wxSystemOptions, setOption_2_1, 2}}, - {3502, {wxSystemOptions, setOption_2_0, 2}}, - {3503, {wxAuiNotebookEvent, setSelection, 1}}, - {3504, {wxAuiNotebookEvent, getSelection, 0}}, - {3505, {wxAuiNotebookEvent, setOldSelection, 1}}, - {3506, {wxAuiNotebookEvent, getOldSelection, 0}}, - {3507, {wxAuiNotebookEvent, setDragSource, 1}}, - {3508, {wxAuiNotebookEvent, getDragSource, 0}}, - {3509, {wxAuiManagerEvent, setManager, 1}}, - {3510, {wxAuiManagerEvent, getManager, 0}}, - {3511, {wxAuiManagerEvent, setPane, 1}}, - {3512, {wxAuiManagerEvent, getPane, 0}}, - {3513, {wxAuiManagerEvent, setButton, 1}}, - {3514, {wxAuiManagerEvent, getButton, 0}}, - {3515, {wxAuiManagerEvent, setDC, 1}}, - {3516, {wxAuiManagerEvent, getDC, 0}}, - {3517, {wxAuiManagerEvent, veto, 1}}, - {3518, {wxAuiManagerEvent, getVeto, 0}}, - {3519, {wxAuiManagerEvent, setCanVeto, 1}}, - {3520, {wxAuiManagerEvent, canVeto, 0}}, - {3521, {wxLogNull, new, 0}}, - {3522, {wxLogNull, 'Destroy', undefined}}, - {3523, {wxTaskBarIcon, new, 0}}, - {3524, {wxTaskBarIcon, destruct, 0}}, - {3525, {wxTaskBarIcon, popupMenu, 1}}, - {3526, {wxTaskBarIcon, removeIcon, 0}}, - {3527, {wxTaskBarIcon, setIcon, 2}}, - {3528, {wxLocale, new_0, 0}}, - {3530, {wxLocale, new_2, 2}}, - {3531, {wxLocale, destruct, 0}}, - {3533, {wxLocale, init, 1}}, - {3534, {wxLocale, addCatalog_1, 1}}, - {3535, {wxLocale, addCatalog_3, 3}}, - {3536, {wxLocale, addCatalogLookupPathPrefix, 1}}, - {3537, {wxLocale, getCanonicalName, 0}}, - {3538, {wxLocale, getLanguage, 0}}, - {3539, {wxLocale, getLanguageName, 1}}, - {3540, {wxLocale, getLocale, 0}}, - {3541, {wxLocale, getName, 0}}, - {3542, {wxLocale, getString_2, 2}}, - {3543, {wxLocale, getString_4, 4}}, - {3544, {wxLocale, getHeaderValue, 2}}, - {3545, {wxLocale, getSysName, 0}}, - {3546, {wxLocale, getSystemEncoding, 0}}, - {3547, {wxLocale, getSystemEncodingName, 0}}, - {3548, {wxLocale, getSystemLanguage, 0}}, - {3549, {wxLocale, isLoaded, 1}}, - {3550, {wxLocale, isOk, 0}}, - {3551, {wxActivateEvent, getActive, 0}}, - {3553, {wxPopupWindow, new_2, 2}}, - {3554, {wxPopupWindow, new_0, 0}}, - {3556, {wxPopupWindow, destruct, 0}}, - {3557, {wxPopupWindow, create, 2}}, - {3558, {wxPopupWindow, position, 2}}, - {3559, {wxPopupTransientWindow, new_0, 0}}, - {3560, {wxPopupTransientWindow, new_2, 2}}, - {3561, {wxPopupTransientWindow, destruct, 0}}, - {3562, {wxPopupTransientWindow, popup, 1}}, - {3563, {wxPopupTransientWindow, dismiss, 0}}, + {2653, {wxAuiPaneInfo, getWindow, 0}}, + {2654, {wxAuiPaneInfo, getFrame, 0}}, + {2655, {wxAuiPaneInfo, getDirection, 0}}, + {2656, {wxAuiPaneInfo, getLayer, 0}}, + {2657, {wxAuiPaneInfo, getRow, 0}}, + {2658, {wxAuiPaneInfo, getPosition, 0}}, + {2659, {wxAuiPaneInfo, getFloatingPosition, 0}}, + {2660, {wxAuiPaneInfo, getFloatingSize, 0}}, + {2661, {wxAuiNotebook, new_0, 0}}, + {2662, {wxAuiNotebook, new_2, 2}}, + {2663, {wxAuiNotebook, addPage, 3}}, + {2664, {wxAuiNotebook, create, 2}}, + {2665, {wxAuiNotebook, deletePage, 1}}, + {2666, {wxAuiNotebook, getArtProvider, 0}}, + {2667, {wxAuiNotebook, getPage, 1}}, + {2668, {wxAuiNotebook, getPageBitmap, 1}}, + {2669, {wxAuiNotebook, getPageCount, 0}}, + {2670, {wxAuiNotebook, getPageIndex, 1}}, + {2671, {wxAuiNotebook, getPageText, 1}}, + {2672, {wxAuiNotebook, getSelection, 0}}, + {2673, {wxAuiNotebook, insertPage, 4}}, + {2674, {wxAuiNotebook, removePage, 1}}, + {2675, {wxAuiNotebook, setArtProvider, 1}}, + {2676, {wxAuiNotebook, setFont, 1}}, + {2677, {wxAuiNotebook, setPageBitmap, 2}}, + {2678, {wxAuiNotebook, setPageText, 2}}, + {2679, {wxAuiNotebook, setSelection, 1}}, + {2680, {wxAuiNotebook, setTabCtrlHeight, 1}}, + {2681, {wxAuiNotebook, setUniformBitmapSize, 1}}, + {2682, {wxAuiNotebook, 'Destroy', undefined}}, + {2683, {wxAuiTabArt, setFlags, 1}}, + {2684, {wxAuiTabArt, setMeasuringFont, 1}}, + {2685, {wxAuiTabArt, setNormalFont, 1}}, + {2686, {wxAuiTabArt, setSelectedFont, 1}}, + {2687, {wxAuiTabArt, setColour, 1}}, + {2688, {wxAuiTabArt, setActiveColour, 1}}, + {2689, {wxAuiDockArt, getColour, 1}}, + {2690, {wxAuiDockArt, getFont, 1}}, + {2691, {wxAuiDockArt, getMetric, 1}}, + {2692, {wxAuiDockArt, setColour, 2}}, + {2693, {wxAuiDockArt, setFont, 2}}, + {2694, {wxAuiDockArt, setMetric, 2}}, + {2695, {wxAuiSimpleTabArt, new, 0}}, + {2696, {wxAuiSimpleTabArt, 'Destroy', undefined}}, + {2697, {wxMDIParentFrame, new_0, 0}}, + {2698, {wxMDIParentFrame, new_4, 4}}, + {2699, {wxMDIParentFrame, destruct, 0}}, + {2700, {wxMDIParentFrame, activateNext, 0}}, + {2701, {wxMDIParentFrame, activatePrevious, 0}}, + {2702, {wxMDIParentFrame, arrangeIcons, 0}}, + {2703, {wxMDIParentFrame, cascade, 0}}, + {2704, {wxMDIParentFrame, create, 4}}, + {2705, {wxMDIParentFrame, getActiveChild, 0}}, + {2706, {wxMDIParentFrame, getClientWindow, 0}}, + {2707, {wxMDIParentFrame, tile, 1}}, + {2708, {wxMDIChildFrame, new_0, 0}}, + {2709, {wxMDIChildFrame, new_4, 4}}, + {2710, {wxMDIChildFrame, destruct, 0}}, + {2711, {wxMDIChildFrame, activate, 0}}, + {2712, {wxMDIChildFrame, create, 4}}, + {2713, {wxMDIChildFrame, maximize, 1}}, + {2714, {wxMDIChildFrame, restore, 0}}, + {2715, {wxMDIClientWindow, new_0, 0}}, + {2716, {wxMDIClientWindow, new_2, 2}}, + {2717, {wxMDIClientWindow, destruct, 0}}, + {2718, {wxMDIClientWindow, createClient, 2}}, + {2719, {wxLayoutAlgorithm, new, 0}}, + {2720, {wxLayoutAlgorithm, layoutFrame, 2}}, + {2721, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, + {2722, {wxLayoutAlgorithm, layoutWindow, 2}}, + {2723, {wxLayoutAlgorithm, 'Destroy', undefined}}, + {2724, {wxEvent, getId, 0}}, + {2725, {wxEvent, getSkipped, 0}}, + {2726, {wxEvent, getTimestamp, 0}}, + {2727, {wxEvent, isCommandEvent, 0}}, + {2728, {wxEvent, resumePropagation, 1}}, + {2729, {wxEvent, shouldPropagate, 0}}, + {2730, {wxEvent, skip, 1}}, + {2731, {wxEvent, stopPropagation, 0}}, + {2732, {wxCommandEvent, getClientData, 0}}, + {2733, {wxCommandEvent, getExtraLong, 0}}, + {2734, {wxCommandEvent, getInt, 0}}, + {2735, {wxCommandEvent, getSelection, 0}}, + {2736, {wxCommandEvent, getString, 0}}, + {2737, {wxCommandEvent, isChecked, 0}}, + {2738, {wxCommandEvent, isSelection, 0}}, + {2739, {wxCommandEvent, setInt, 1}}, + {2740, {wxCommandEvent, setString, 1}}, + {2741, {wxScrollEvent, getOrientation, 0}}, + {2742, {wxScrollEvent, getPosition, 0}}, + {2743, {wxScrollWinEvent, getOrientation, 0}}, + {2744, {wxScrollWinEvent, getPosition, 0}}, + {2745, {wxMouseEvent, altDown, 0}}, + {2746, {wxMouseEvent, button, 1}}, + {2747, {wxMouseEvent, buttonDClick, 1}}, + {2748, {wxMouseEvent, buttonDown, 1}}, + {2749, {wxMouseEvent, buttonUp, 1}}, + {2750, {wxMouseEvent, cmdDown, 0}}, + {2751, {wxMouseEvent, controlDown, 0}}, + {2752, {wxMouseEvent, dragging, 0}}, + {2753, {wxMouseEvent, entering, 0}}, + {2754, {wxMouseEvent, getButton, 0}}, + {2757, {wxMouseEvent, getPosition, 0}}, + {2758, {wxMouseEvent, getLogicalPosition, 1}}, + {2759, {wxMouseEvent, getLinesPerAction, 0}}, + {2760, {wxMouseEvent, getWheelRotation, 0}}, + {2761, {wxMouseEvent, getWheelDelta, 0}}, + {2762, {wxMouseEvent, getX, 0}}, + {2763, {wxMouseEvent, getY, 0}}, + {2764, {wxMouseEvent, isButton, 0}}, + {2765, {wxMouseEvent, isPageScroll, 0}}, + {2766, {wxMouseEvent, leaving, 0}}, + {2767, {wxMouseEvent, leftDClick, 0}}, + {2768, {wxMouseEvent, leftDown, 0}}, + {2769, {wxMouseEvent, leftIsDown, 0}}, + {2770, {wxMouseEvent, leftUp, 0}}, + {2771, {wxMouseEvent, metaDown, 0}}, + {2772, {wxMouseEvent, middleDClick, 0}}, + {2773, {wxMouseEvent, middleDown, 0}}, + {2774, {wxMouseEvent, middleIsDown, 0}}, + {2775, {wxMouseEvent, middleUp, 0}}, + {2776, {wxMouseEvent, moving, 0}}, + {2777, {wxMouseEvent, rightDClick, 0}}, + {2778, {wxMouseEvent, rightDown, 0}}, + {2779, {wxMouseEvent, rightIsDown, 0}}, + {2780, {wxMouseEvent, rightUp, 0}}, + {2781, {wxMouseEvent, shiftDown, 0}}, + {2782, {wxSetCursorEvent, getCursor, 0}}, + {2783, {wxSetCursorEvent, getX, 0}}, + {2784, {wxSetCursorEvent, getY, 0}}, + {2785, {wxSetCursorEvent, hasCursor, 0}}, + {2786, {wxSetCursorEvent, setCursor, 1}}, + {2787, {wxKeyEvent, altDown, 0}}, + {2788, {wxKeyEvent, cmdDown, 0}}, + {2789, {wxKeyEvent, controlDown, 0}}, + {2790, {wxKeyEvent, getKeyCode, 0}}, + {2791, {wxKeyEvent, getModifiers, 0}}, + {2794, {wxKeyEvent, getPosition, 0}}, + {2795, {wxKeyEvent, getRawKeyCode, 0}}, + {2796, {wxKeyEvent, getRawKeyFlags, 0}}, + {2797, {wxKeyEvent, getUnicodeKey, 0}}, + {2798, {wxKeyEvent, getX, 0}}, + {2799, {wxKeyEvent, getY, 0}}, + {2800, {wxKeyEvent, hasModifiers, 0}}, + {2801, {wxKeyEvent, metaDown, 0}}, + {2802, {wxKeyEvent, shiftDown, 0}}, + {2803, {wxSizeEvent, getSize, 0}}, + {2804, {wxMoveEvent, getPosition, 0}}, + {2805, {wxEraseEvent, getDC, 0}}, + {2806, {wxFocusEvent, getWindow, 0}}, + {2807, {wxChildFocusEvent, getWindow, 0}}, + {2808, {wxMenuEvent, getMenu, 0}}, + {2809, {wxMenuEvent, getMenuId, 0}}, + {2810, {wxMenuEvent, isPopup, 0}}, + {2811, {wxCloseEvent, canVeto, 0}}, + {2812, {wxCloseEvent, getLoggingOff, 0}}, + {2813, {wxCloseEvent, setCanVeto, 1}}, + {2814, {wxCloseEvent, setLoggingOff, 1}}, + {2815, {wxCloseEvent, veto, 1}}, + {2816, {wxShowEvent, setShow, 1}}, + {2817, {wxShowEvent, getShow, 0}}, + {2818, {wxIconizeEvent, iconized, 0}}, + {2819, {wxJoystickEvent, buttonDown, 1}}, + {2820, {wxJoystickEvent, buttonIsDown, 1}}, + {2821, {wxJoystickEvent, buttonUp, 1}}, + {2822, {wxJoystickEvent, getButtonChange, 0}}, + {2823, {wxJoystickEvent, getButtonState, 0}}, + {2824, {wxJoystickEvent, getJoystick, 0}}, + {2825, {wxJoystickEvent, getPosition, 0}}, + {2826, {wxJoystickEvent, getZPosition, 0}}, + {2827, {wxJoystickEvent, isButton, 0}}, + {2828, {wxJoystickEvent, isMove, 0}}, + {2829, {wxJoystickEvent, isZMove, 0}}, + {2830, {wxUpdateUIEvent, canUpdate, 1}}, + {2831, {wxUpdateUIEvent, check, 1}}, + {2832, {wxUpdateUIEvent, enable, 1}}, + {2833, {wxUpdateUIEvent, show, 1}}, + {2834, {wxUpdateUIEvent, getChecked, 0}}, + {2835, {wxUpdateUIEvent, getEnabled, 0}}, + {2836, {wxUpdateUIEvent, getShown, 0}}, + {2837, {wxUpdateUIEvent, getSetChecked, 0}}, + {2838, {wxUpdateUIEvent, getSetEnabled, 0}}, + {2839, {wxUpdateUIEvent, getSetShown, 0}}, + {2840, {wxUpdateUIEvent, getSetText, 0}}, + {2841, {wxUpdateUIEvent, getText, 0}}, + {2842, {wxUpdateUIEvent, getMode, 0}}, + {2843, {wxUpdateUIEvent, getUpdateInterval, 0}}, + {2844, {wxUpdateUIEvent, resetUpdateTime, 0}}, + {2845, {wxUpdateUIEvent, setMode, 1}}, + {2846, {wxUpdateUIEvent, setText, 1}}, + {2847, {wxUpdateUIEvent, setUpdateInterval, 1}}, + {2848, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, + {2849, {wxPaletteChangedEvent, setChangedWindow, 1}}, + {2850, {wxPaletteChangedEvent, getChangedWindow, 0}}, + {2851, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, + {2852, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, + {2853, {wxNavigationKeyEvent, getDirection, 0}}, + {2854, {wxNavigationKeyEvent, setDirection, 1}}, + {2855, {wxNavigationKeyEvent, isWindowChange, 0}}, + {2856, {wxNavigationKeyEvent, setWindowChange, 1}}, + {2857, {wxNavigationKeyEvent, isFromTab, 0}}, + {2858, {wxNavigationKeyEvent, setFromTab, 1}}, + {2859, {wxNavigationKeyEvent, getCurrentFocus, 0}}, + {2860, {wxNavigationKeyEvent, setCurrentFocus, 1}}, + {2861, {wxHelpEvent, getOrigin, 0}}, + {2862, {wxHelpEvent, getPosition, 0}}, + {2863, {wxHelpEvent, setOrigin, 1}}, + {2864, {wxHelpEvent, setPosition, 1}}, + {2865, {wxContextMenuEvent, getPosition, 0}}, + {2866, {wxContextMenuEvent, setPosition, 1}}, + {2867, {wxIdleEvent, canSend, 1}}, + {2868, {wxIdleEvent, getMode, 0}}, + {2869, {wxIdleEvent, requestMore, 1}}, + {2870, {wxIdleEvent, moreRequested, 0}}, + {2871, {wxIdleEvent, setMode, 1}}, + {2872, {wxGridEvent, altDown, 0}}, + {2873, {wxGridEvent, controlDown, 0}}, + {2874, {wxGridEvent, getCol, 0}}, + {2875, {wxGridEvent, getPosition, 0}}, + {2876, {wxGridEvent, getRow, 0}}, + {2877, {wxGridEvent, metaDown, 0}}, + {2878, {wxGridEvent, selecting, 0}}, + {2879, {wxGridEvent, shiftDown, 0}}, + {2880, {wxNotifyEvent, allow, 0}}, + {2881, {wxNotifyEvent, isAllowed, 0}}, + {2882, {wxNotifyEvent, veto, 0}}, + {2883, {wxSashEvent, getEdge, 0}}, + {2884, {wxSashEvent, getDragRect, 0}}, + {2885, {wxSashEvent, getDragStatus, 0}}, + {2886, {wxListEvent, getCacheFrom, 0}}, + {2887, {wxListEvent, getCacheTo, 0}}, + {2888, {wxListEvent, getKeyCode, 0}}, + {2889, {wxListEvent, getIndex, 0}}, + {2890, {wxListEvent, getColumn, 0}}, + {2891, {wxListEvent, getPoint, 0}}, + {2892, {wxListEvent, getLabel, 0}}, + {2893, {wxListEvent, getText, 0}}, + {2894, {wxListEvent, getImage, 0}}, + {2895, {wxListEvent, getData, 0}}, + {2896, {wxListEvent, getMask, 0}}, + {2897, {wxListEvent, getItem, 0}}, + {2898, {wxListEvent, isEditCancelled, 0}}, + {2899, {wxDateEvent, getDate, 0}}, + {2900, {wxCalendarEvent, getWeekDay, 0}}, + {2901, {wxFileDirPickerEvent, getPath, 0}}, + {2902, {wxColourPickerEvent, getColour, 0}}, + {2903, {wxFontPickerEvent, getFont, 0}}, + {2904, {wxStyledTextEvent, getPosition, 0}}, + {2905, {wxStyledTextEvent, getKey, 0}}, + {2906, {wxStyledTextEvent, getModifiers, 0}}, + {2907, {wxStyledTextEvent, getModificationType, 0}}, + {2908, {wxStyledTextEvent, getText, 0}}, + {2909, {wxStyledTextEvent, getLength, 0}}, + {2910, {wxStyledTextEvent, getLinesAdded, 0}}, + {2911, {wxStyledTextEvent, getLine, 0}}, + {2912, {wxStyledTextEvent, getFoldLevelNow, 0}}, + {2913, {wxStyledTextEvent, getFoldLevelPrev, 0}}, + {2914, {wxStyledTextEvent, getMargin, 0}}, + {2915, {wxStyledTextEvent, getMessage, 0}}, + {2916, {wxStyledTextEvent, getWParam, 0}}, + {2917, {wxStyledTextEvent, getLParam, 0}}, + {2918, {wxStyledTextEvent, getListType, 0}}, + {2919, {wxStyledTextEvent, getX, 0}}, + {2920, {wxStyledTextEvent, getY, 0}}, + {2921, {wxStyledTextEvent, getDragText, 0}}, + {2922, {wxStyledTextEvent, getDragAllowMove, 0}}, + {2923, {wxStyledTextEvent, getDragResult, 0}}, + {2924, {wxStyledTextEvent, getShift, 0}}, + {2925, {wxStyledTextEvent, getControl, 0}}, + {2926, {wxStyledTextEvent, getAlt, 0}}, + {2927, {utils, getKeyState, 1}}, + {2928, {utils, getMousePosition, 2}}, + {2929, {utils, getMouseState, 0}}, + {2930, {utils, setDetectableAutoRepeat, 1}}, + {2931, {utils, bell, 0}}, + {2932, {utils, findMenuItemId, 3}}, + {2933, {utils, genericFindWindowAtPoint, 1}}, + {2934, {utils, findWindowAtPoint, 1}}, + {2935, {utils, beginBusyCursor, 1}}, + {2936, {utils, endBusyCursor, 0}}, + {2937, {utils, isBusy, 0}}, + {2938, {utils, shutdown, 1}}, + {2939, {utils, shell, 1}}, + {2940, {utils, launchDefaultBrowser, 2}}, + {2941, {utils, getEmailAddress, 0}}, + {2942, {utils, getUserId, 0}}, + {2943, {utils, getHomeDir, 0}}, + {2944, {utils, newId, 0}}, + {2945, {utils, registerId, 1}}, + {2946, {utils, getCurrentId, 0}}, + {2947, {utils, getOsDescription, 0}}, + {2948, {utils, isPlatformLittleEndian, 0}}, + {2949, {utils, isPlatform64Bit, 0}}, + {2950, {gdicmn, displaySize, 2}}, + {2951, {gdicmn, setCursor, 1}}, + {2952, {wxPrintout, new, 1}}, + {2953, {wxPrintout, destruct, 0}}, + {2954, {wxPrintout, getDC, 0}}, + {2955, {wxPrintout, getPageSizeMM, 2}}, + {2956, {wxPrintout, getPageSizePixels, 2}}, + {2957, {wxPrintout, getPaperRectPixels, 0}}, + {2958, {wxPrintout, getPPIPrinter, 2}}, + {2959, {wxPrintout, getPPIScreen, 2}}, + {2960, {wxPrintout, getTitle, 0}}, + {2961, {wxPrintout, isPreview, 0}}, + {2962, {wxPrintout, fitThisSizeToPaper, 1}}, + {2963, {wxPrintout, fitThisSizeToPage, 1}}, + {2964, {wxPrintout, fitThisSizeToPageMargins, 2}}, + {2965, {wxPrintout, mapScreenSizeToPaper, 0}}, + {2966, {wxPrintout, mapScreenSizeToPage, 0}}, + {2967, {wxPrintout, mapScreenSizeToPageMargins, 1}}, + {2968, {wxPrintout, mapScreenSizeToDevice, 0}}, + {2969, {wxPrintout, getLogicalPaperRect, 0}}, + {2970, {wxPrintout, getLogicalPageRect, 0}}, + {2971, {wxPrintout, getLogicalPageMarginsRect, 1}}, + {2972, {wxPrintout, setLogicalOrigin, 2}}, + {2973, {wxPrintout, offsetLogicalOrigin, 2}}, + {2974, {wxStyledTextCtrl, new_2, 2}}, + {2975, {wxStyledTextCtrl, new_0, 0}}, + {2976, {wxStyledTextCtrl, destruct, 0}}, + {2977, {wxStyledTextCtrl, create, 2}}, + {2978, {wxStyledTextCtrl, addText, 1}}, + {2979, {wxStyledTextCtrl, addStyledText, 1}}, + {2980, {wxStyledTextCtrl, insertText, 2}}, + {2981, {wxStyledTextCtrl, clearAll, 0}}, + {2982, {wxStyledTextCtrl, clearDocumentStyle, 0}}, + {2983, {wxStyledTextCtrl, getLength, 0}}, + {2984, {wxStyledTextCtrl, getCharAt, 1}}, + {2985, {wxStyledTextCtrl, getCurrentPos, 0}}, + {2986, {wxStyledTextCtrl, getAnchor, 0}}, + {2987, {wxStyledTextCtrl, getStyleAt, 1}}, + {2988, {wxStyledTextCtrl, redo, 0}}, + {2989, {wxStyledTextCtrl, setUndoCollection, 1}}, + {2990, {wxStyledTextCtrl, selectAll, 0}}, + {2991, {wxStyledTextCtrl, setSavePoint, 0}}, + {2992, {wxStyledTextCtrl, getStyledText, 2}}, + {2993, {wxStyledTextCtrl, canRedo, 0}}, + {2994, {wxStyledTextCtrl, markerLineFromHandle, 1}}, + {2995, {wxStyledTextCtrl, markerDeleteHandle, 1}}, + {2996, {wxStyledTextCtrl, getUndoCollection, 0}}, + {2997, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, + {2998, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, + {2999, {wxStyledTextCtrl, positionFromPoint, 1}}, + {3000, {wxStyledTextCtrl, positionFromPointClose, 2}}, + {3001, {wxStyledTextCtrl, gotoLine, 1}}, + {3002, {wxStyledTextCtrl, gotoPos, 1}}, + {3003, {wxStyledTextCtrl, setAnchor, 1}}, + {3004, {wxStyledTextCtrl, getCurLine, 1}}, + {3005, {wxStyledTextCtrl, getEndStyled, 0}}, + {3006, {wxStyledTextCtrl, convertEOLs, 1}}, + {3007, {wxStyledTextCtrl, getEOLMode, 0}}, + {3008, {wxStyledTextCtrl, setEOLMode, 1}}, + {3009, {wxStyledTextCtrl, startStyling, 2}}, + {3010, {wxStyledTextCtrl, setStyling, 2}}, + {3011, {wxStyledTextCtrl, getBufferedDraw, 0}}, + {3012, {wxStyledTextCtrl, setBufferedDraw, 1}}, + {3013, {wxStyledTextCtrl, setTabWidth, 1}}, + {3014, {wxStyledTextCtrl, getTabWidth, 0}}, + {3015, {wxStyledTextCtrl, setCodePage, 1}}, + {3016, {wxStyledTextCtrl, markerDefine, 3}}, + {3017, {wxStyledTextCtrl, markerSetForeground, 2}}, + {3018, {wxStyledTextCtrl, markerSetBackground, 2}}, + {3019, {wxStyledTextCtrl, markerAdd, 2}}, + {3020, {wxStyledTextCtrl, markerDelete, 2}}, + {3021, {wxStyledTextCtrl, markerDeleteAll, 1}}, + {3022, {wxStyledTextCtrl, markerGet, 1}}, + {3023, {wxStyledTextCtrl, markerNext, 2}}, + {3024, {wxStyledTextCtrl, markerPrevious, 2}}, + {3025, {wxStyledTextCtrl, markerDefineBitmap, 2}}, + {3026, {wxStyledTextCtrl, markerAddSet, 2}}, + {3027, {wxStyledTextCtrl, markerSetAlpha, 2}}, + {3028, {wxStyledTextCtrl, setMarginType, 2}}, + {3029, {wxStyledTextCtrl, getMarginType, 1}}, + {3030, {wxStyledTextCtrl, setMarginWidth, 2}}, + {3031, {wxStyledTextCtrl, getMarginWidth, 1}}, + {3032, {wxStyledTextCtrl, setMarginMask, 2}}, + {3033, {wxStyledTextCtrl, getMarginMask, 1}}, + {3034, {wxStyledTextCtrl, setMarginSensitive, 2}}, + {3035, {wxStyledTextCtrl, getMarginSensitive, 1}}, + {3036, {wxStyledTextCtrl, styleClearAll, 0}}, + {3037, {wxStyledTextCtrl, styleSetForeground, 2}}, + {3038, {wxStyledTextCtrl, styleSetBackground, 2}}, + {3039, {wxStyledTextCtrl, styleSetBold, 2}}, + {3040, {wxStyledTextCtrl, styleSetItalic, 2}}, + {3041, {wxStyledTextCtrl, styleSetSize, 2}}, + {3042, {wxStyledTextCtrl, styleSetFaceName, 2}}, + {3043, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, + {3044, {wxStyledTextCtrl, styleResetDefault, 0}}, + {3045, {wxStyledTextCtrl, styleSetUnderline, 2}}, + {3046, {wxStyledTextCtrl, styleSetCase, 2}}, + {3047, {wxStyledTextCtrl, styleSetHotSpot, 2}}, + {3048, {wxStyledTextCtrl, setSelForeground, 2}}, + {3049, {wxStyledTextCtrl, setSelBackground, 2}}, + {3050, {wxStyledTextCtrl, getSelAlpha, 0}}, + {3051, {wxStyledTextCtrl, setSelAlpha, 1}}, + {3052, {wxStyledTextCtrl, setCaretForeground, 1}}, + {3053, {wxStyledTextCtrl, cmdKeyAssign, 3}}, + {3054, {wxStyledTextCtrl, cmdKeyClear, 2}}, + {3055, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, + {3056, {wxStyledTextCtrl, setStyleBytes, 2}}, + {3057, {wxStyledTextCtrl, styleSetVisible, 2}}, + {3058, {wxStyledTextCtrl, getCaretPeriod, 0}}, + {3059, {wxStyledTextCtrl, setCaretPeriod, 1}}, + {3060, {wxStyledTextCtrl, setWordChars, 1}}, + {3061, {wxStyledTextCtrl, beginUndoAction, 0}}, + {3062, {wxStyledTextCtrl, endUndoAction, 0}}, + {3063, {wxStyledTextCtrl, indicatorSetStyle, 2}}, + {3064, {wxStyledTextCtrl, indicatorGetStyle, 1}}, + {3065, {wxStyledTextCtrl, indicatorSetForeground, 2}}, + {3066, {wxStyledTextCtrl, indicatorGetForeground, 1}}, + {3067, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, + {3068, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, + {3069, {wxStyledTextCtrl, getStyleBits, 0}}, + {3070, {wxStyledTextCtrl, setLineState, 2}}, + {3071, {wxStyledTextCtrl, getLineState, 1}}, + {3072, {wxStyledTextCtrl, getMaxLineState, 0}}, + {3073, {wxStyledTextCtrl, getCaretLineVisible, 0}}, + {3074, {wxStyledTextCtrl, setCaretLineVisible, 1}}, + {3075, {wxStyledTextCtrl, getCaretLineBackground, 0}}, + {3076, {wxStyledTextCtrl, setCaretLineBackground, 1}}, + {3077, {wxStyledTextCtrl, autoCompShow, 2}}, + {3078, {wxStyledTextCtrl, autoCompCancel, 0}}, + {3079, {wxStyledTextCtrl, autoCompActive, 0}}, + {3080, {wxStyledTextCtrl, autoCompPosStart, 0}}, + {3081, {wxStyledTextCtrl, autoCompComplete, 0}}, + {3082, {wxStyledTextCtrl, autoCompStops, 1}}, + {3083, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, + {3084, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, + {3085, {wxStyledTextCtrl, autoCompSelect, 1}}, + {3086, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, + {3087, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, + {3088, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, + {3089, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, + {3090, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, + {3091, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, + {3092, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, + {3093, {wxStyledTextCtrl, userListShow, 2}}, + {3094, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, + {3095, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, + {3096, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, + {3097, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, + {3098, {wxStyledTextCtrl, registerImage, 2}}, + {3099, {wxStyledTextCtrl, clearRegisteredImages, 0}}, + {3100, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, + {3101, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, + {3102, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, + {3103, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, + {3104, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, + {3105, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, + {3106, {wxStyledTextCtrl, setIndent, 1}}, + {3107, {wxStyledTextCtrl, getIndent, 0}}, + {3108, {wxStyledTextCtrl, setUseTabs, 1}}, + {3109, {wxStyledTextCtrl, getUseTabs, 0}}, + {3110, {wxStyledTextCtrl, setLineIndentation, 2}}, + {3111, {wxStyledTextCtrl, getLineIndentation, 1}}, + {3112, {wxStyledTextCtrl, getLineIndentPosition, 1}}, + {3113, {wxStyledTextCtrl, getColumn, 1}}, + {3114, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, + {3115, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, + {3116, {wxStyledTextCtrl, setIndentationGuides, 1}}, + {3117, {wxStyledTextCtrl, getIndentationGuides, 0}}, + {3118, {wxStyledTextCtrl, setHighlightGuide, 1}}, + {3119, {wxStyledTextCtrl, getHighlightGuide, 0}}, + {3120, {wxStyledTextCtrl, getLineEndPosition, 1}}, + {3121, {wxStyledTextCtrl, getCodePage, 0}}, + {3122, {wxStyledTextCtrl, getCaretForeground, 0}}, + {3123, {wxStyledTextCtrl, getReadOnly, 0}}, + {3124, {wxStyledTextCtrl, setCurrentPos, 1}}, + {3125, {wxStyledTextCtrl, setSelectionStart, 1}}, + {3126, {wxStyledTextCtrl, getSelectionStart, 0}}, + {3127, {wxStyledTextCtrl, setSelectionEnd, 1}}, + {3128, {wxStyledTextCtrl, getSelectionEnd, 0}}, + {3129, {wxStyledTextCtrl, setPrintMagnification, 1}}, + {3130, {wxStyledTextCtrl, getPrintMagnification, 0}}, + {3131, {wxStyledTextCtrl, setPrintColourMode, 1}}, + {3132, {wxStyledTextCtrl, getPrintColourMode, 0}}, + {3133, {wxStyledTextCtrl, findText, 4}}, + {3134, {wxStyledTextCtrl, formatRange, 7}}, + {3135, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, + {3136, {wxStyledTextCtrl, getLine, 1}}, + {3137, {wxStyledTextCtrl, getLineCount, 0}}, + {3138, {wxStyledTextCtrl, setMarginLeft, 1}}, + {3139, {wxStyledTextCtrl, getMarginLeft, 0}}, + {3140, {wxStyledTextCtrl, setMarginRight, 1}}, + {3141, {wxStyledTextCtrl, getMarginRight, 0}}, + {3142, {wxStyledTextCtrl, getModify, 0}}, + {3143, {wxStyledTextCtrl, setSelection, 2}}, + {3144, {wxStyledTextCtrl, getSelectedText, 0}}, + {3145, {wxStyledTextCtrl, getTextRange, 2}}, + {3146, {wxStyledTextCtrl, hideSelection, 1}}, + {3147, {wxStyledTextCtrl, lineFromPosition, 1}}, + {3148, {wxStyledTextCtrl, positionFromLine, 1}}, + {3149, {wxStyledTextCtrl, lineScroll, 2}}, + {3150, {wxStyledTextCtrl, ensureCaretVisible, 0}}, + {3151, {wxStyledTextCtrl, replaceSelection, 1}}, + {3152, {wxStyledTextCtrl, setReadOnly, 1}}, + {3153, {wxStyledTextCtrl, canPaste, 0}}, + {3154, {wxStyledTextCtrl, canUndo, 0}}, + {3155, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, + {3156, {wxStyledTextCtrl, undo, 0}}, + {3157, {wxStyledTextCtrl, cut, 0}}, + {3158, {wxStyledTextCtrl, copy, 0}}, + {3159, {wxStyledTextCtrl, paste, 0}}, + {3160, {wxStyledTextCtrl, clear, 0}}, + {3161, {wxStyledTextCtrl, setText, 1}}, + {3162, {wxStyledTextCtrl, getText, 0}}, + {3163, {wxStyledTextCtrl, getTextLength, 0}}, + {3164, {wxStyledTextCtrl, getOvertype, 0}}, + {3165, {wxStyledTextCtrl, setCaretWidth, 1}}, + {3166, {wxStyledTextCtrl, getCaretWidth, 0}}, + {3167, {wxStyledTextCtrl, setTargetStart, 1}}, + {3168, {wxStyledTextCtrl, getTargetStart, 0}}, + {3169, {wxStyledTextCtrl, setTargetEnd, 1}}, + {3170, {wxStyledTextCtrl, getTargetEnd, 0}}, + {3171, {wxStyledTextCtrl, replaceTarget, 1}}, + {3172, {wxStyledTextCtrl, searchInTarget, 1}}, + {3173, {wxStyledTextCtrl, setSearchFlags, 1}}, + {3174, {wxStyledTextCtrl, getSearchFlags, 0}}, + {3175, {wxStyledTextCtrl, callTipShow, 2}}, + {3176, {wxStyledTextCtrl, callTipCancel, 0}}, + {3177, {wxStyledTextCtrl, callTipActive, 0}}, + {3178, {wxStyledTextCtrl, callTipPosAtStart, 0}}, + {3179, {wxStyledTextCtrl, callTipSetHighlight, 2}}, + {3180, {wxStyledTextCtrl, callTipSetBackground, 1}}, + {3181, {wxStyledTextCtrl, callTipSetForeground, 1}}, + {3182, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, + {3183, {wxStyledTextCtrl, callTipUseStyle, 1}}, + {3184, {wxStyledTextCtrl, visibleFromDocLine, 1}}, + {3185, {wxStyledTextCtrl, docLineFromVisible, 1}}, + {3186, {wxStyledTextCtrl, wrapCount, 1}}, + {3187, {wxStyledTextCtrl, setFoldLevel, 2}}, + {3188, {wxStyledTextCtrl, getFoldLevel, 1}}, + {3189, {wxStyledTextCtrl, getLastChild, 2}}, + {3190, {wxStyledTextCtrl, getFoldParent, 1}}, + {3191, {wxStyledTextCtrl, showLines, 2}}, + {3192, {wxStyledTextCtrl, hideLines, 2}}, + {3193, {wxStyledTextCtrl, getLineVisible, 1}}, + {3194, {wxStyledTextCtrl, setFoldExpanded, 2}}, + {3195, {wxStyledTextCtrl, getFoldExpanded, 1}}, + {3196, {wxStyledTextCtrl, toggleFold, 1}}, + {3197, {wxStyledTextCtrl, ensureVisible, 1}}, + {3198, {wxStyledTextCtrl, setFoldFlags, 1}}, + {3199, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, + {3200, {wxStyledTextCtrl, setTabIndents, 1}}, + {3201, {wxStyledTextCtrl, getTabIndents, 0}}, + {3202, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, + {3203, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, + {3204, {wxStyledTextCtrl, setMouseDwellTime, 1}}, + {3205, {wxStyledTextCtrl, getMouseDwellTime, 0}}, + {3206, {wxStyledTextCtrl, wordStartPosition, 2}}, + {3207, {wxStyledTextCtrl, wordEndPosition, 2}}, + {3208, {wxStyledTextCtrl, setWrapMode, 1}}, + {3209, {wxStyledTextCtrl, getWrapMode, 0}}, + {3210, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, + {3211, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, + {3212, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, + {3213, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, + {3214, {wxStyledTextCtrl, setWrapStartIndent, 1}}, + {3215, {wxStyledTextCtrl, getWrapStartIndent, 0}}, + {3216, {wxStyledTextCtrl, setLayoutCache, 1}}, + {3217, {wxStyledTextCtrl, getLayoutCache, 0}}, + {3218, {wxStyledTextCtrl, setScrollWidth, 1}}, + {3219, {wxStyledTextCtrl, getScrollWidth, 0}}, + {3220, {wxStyledTextCtrl, textWidth, 2}}, + {3221, {wxStyledTextCtrl, getEndAtLastLine, 0}}, + {3222, {wxStyledTextCtrl, textHeight, 1}}, + {3223, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, + {3224, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, + {3225, {wxStyledTextCtrl, appendText, 1}}, + {3226, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, + {3227, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, + {3228, {wxStyledTextCtrl, targetFromSelection, 0}}, + {3229, {wxStyledTextCtrl, linesJoin, 0}}, + {3230, {wxStyledTextCtrl, linesSplit, 1}}, + {3231, {wxStyledTextCtrl, setFoldMarginColour, 2}}, + {3232, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, + {3233, {wxStyledTextCtrl, lineDown, 0}}, + {3234, {wxStyledTextCtrl, lineDownExtend, 0}}, + {3235, {wxStyledTextCtrl, lineUp, 0}}, + {3236, {wxStyledTextCtrl, lineUpExtend, 0}}, + {3237, {wxStyledTextCtrl, charLeft, 0}}, + {3238, {wxStyledTextCtrl, charLeftExtend, 0}}, + {3239, {wxStyledTextCtrl, charRight, 0}}, + {3240, {wxStyledTextCtrl, charRightExtend, 0}}, + {3241, {wxStyledTextCtrl, wordLeft, 0}}, + {3242, {wxStyledTextCtrl, wordLeftExtend, 0}}, + {3243, {wxStyledTextCtrl, wordRight, 0}}, + {3244, {wxStyledTextCtrl, wordRightExtend, 0}}, + {3245, {wxStyledTextCtrl, home, 0}}, + {3246, {wxStyledTextCtrl, homeExtend, 0}}, + {3247, {wxStyledTextCtrl, lineEnd, 0}}, + {3248, {wxStyledTextCtrl, lineEndExtend, 0}}, + {3249, {wxStyledTextCtrl, documentStart, 0}}, + {3250, {wxStyledTextCtrl, documentStartExtend, 0}}, + {3251, {wxStyledTextCtrl, documentEnd, 0}}, + {3252, {wxStyledTextCtrl, documentEndExtend, 0}}, + {3253, {wxStyledTextCtrl, pageUp, 0}}, + {3254, {wxStyledTextCtrl, pageUpExtend, 0}}, + {3255, {wxStyledTextCtrl, pageDown, 0}}, + {3256, {wxStyledTextCtrl, pageDownExtend, 0}}, + {3257, {wxStyledTextCtrl, editToggleOvertype, 0}}, + {3258, {wxStyledTextCtrl, cancel, 0}}, + {3259, {wxStyledTextCtrl, deleteBack, 0}}, + {3260, {wxStyledTextCtrl, tab, 0}}, + {3261, {wxStyledTextCtrl, backTab, 0}}, + {3262, {wxStyledTextCtrl, newLine, 0}}, + {3263, {wxStyledTextCtrl, formFeed, 0}}, + {3264, {wxStyledTextCtrl, vCHome, 0}}, + {3265, {wxStyledTextCtrl, vCHomeExtend, 0}}, + {3266, {wxStyledTextCtrl, zoomIn, 0}}, + {3267, {wxStyledTextCtrl, zoomOut, 0}}, + {3268, {wxStyledTextCtrl, delWordLeft, 0}}, + {3269, {wxStyledTextCtrl, delWordRight, 0}}, + {3270, {wxStyledTextCtrl, lineCut, 0}}, + {3271, {wxStyledTextCtrl, lineDelete, 0}}, + {3272, {wxStyledTextCtrl, lineTranspose, 0}}, + {3273, {wxStyledTextCtrl, lineDuplicate, 0}}, + {3274, {wxStyledTextCtrl, lowerCase, 0}}, + {3275, {wxStyledTextCtrl, upperCase, 0}}, + {3276, {wxStyledTextCtrl, lineScrollDown, 0}}, + {3277, {wxStyledTextCtrl, lineScrollUp, 0}}, + {3278, {wxStyledTextCtrl, deleteBackNotLine, 0}}, + {3279, {wxStyledTextCtrl, homeDisplay, 0}}, + {3280, {wxStyledTextCtrl, homeDisplayExtend, 0}}, + {3281, {wxStyledTextCtrl, lineEndDisplay, 0}}, + {3282, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, + {3283, {wxStyledTextCtrl, homeWrapExtend, 0}}, + {3284, {wxStyledTextCtrl, lineEndWrap, 0}}, + {3285, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, + {3286, {wxStyledTextCtrl, vCHomeWrap, 0}}, + {3287, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, + {3288, {wxStyledTextCtrl, lineCopy, 0}}, + {3289, {wxStyledTextCtrl, moveCaretInsideView, 0}}, + {3290, {wxStyledTextCtrl, lineLength, 1}}, + {3291, {wxStyledTextCtrl, braceHighlight, 2}}, + {3292, {wxStyledTextCtrl, braceBadLight, 1}}, + {3293, {wxStyledTextCtrl, braceMatch, 1}}, + {3294, {wxStyledTextCtrl, getViewEOL, 0}}, + {3295, {wxStyledTextCtrl, setViewEOL, 1}}, + {3296, {wxStyledTextCtrl, setModEventMask, 1}}, + {3297, {wxStyledTextCtrl, getEdgeColumn, 0}}, + {3298, {wxStyledTextCtrl, setEdgeColumn, 1}}, + {3299, {wxStyledTextCtrl, setEdgeMode, 1}}, + {3300, {wxStyledTextCtrl, getEdgeMode, 0}}, + {3301, {wxStyledTextCtrl, getEdgeColour, 0}}, + {3302, {wxStyledTextCtrl, setEdgeColour, 1}}, + {3303, {wxStyledTextCtrl, searchAnchor, 0}}, + {3304, {wxStyledTextCtrl, searchNext, 2}}, + {3305, {wxStyledTextCtrl, searchPrev, 2}}, + {3306, {wxStyledTextCtrl, linesOnScreen, 0}}, + {3307, {wxStyledTextCtrl, usePopUp, 1}}, + {3308, {wxStyledTextCtrl, selectionIsRectangle, 0}}, + {3309, {wxStyledTextCtrl, setZoom, 1}}, + {3310, {wxStyledTextCtrl, getZoom, 0}}, + {3311, {wxStyledTextCtrl, getModEventMask, 0}}, + {3312, {wxStyledTextCtrl, setSTCFocus, 1}}, + {3313, {wxStyledTextCtrl, getSTCFocus, 0}}, + {3314, {wxStyledTextCtrl, setStatus, 1}}, + {3315, {wxStyledTextCtrl, getStatus, 0}}, + {3316, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, + {3317, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, + {3318, {wxStyledTextCtrl, setSTCCursor, 1}}, + {3319, {wxStyledTextCtrl, getSTCCursor, 0}}, + {3320, {wxStyledTextCtrl, setControlCharSymbol, 1}}, + {3321, {wxStyledTextCtrl, getControlCharSymbol, 0}}, + {3322, {wxStyledTextCtrl, wordPartLeft, 0}}, + {3323, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, + {3324, {wxStyledTextCtrl, wordPartRight, 0}}, + {3325, {wxStyledTextCtrl, wordPartRightExtend, 0}}, + {3326, {wxStyledTextCtrl, setVisiblePolicy, 2}}, + {3327, {wxStyledTextCtrl, delLineLeft, 0}}, + {3328, {wxStyledTextCtrl, delLineRight, 0}}, + {3329, {wxStyledTextCtrl, getXOffset, 0}}, + {3330, {wxStyledTextCtrl, chooseCaretX, 0}}, + {3331, {wxStyledTextCtrl, setXCaretPolicy, 2}}, + {3332, {wxStyledTextCtrl, setYCaretPolicy, 2}}, + {3333, {wxStyledTextCtrl, getPrintWrapMode, 0}}, + {3334, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, + {3335, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, + {3336, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, + {3337, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, + {3338, {wxStyledTextCtrl, paraDownExtend, 0}}, + {3339, {wxStyledTextCtrl, paraUp, 0}}, + {3340, {wxStyledTextCtrl, paraUpExtend, 0}}, + {3341, {wxStyledTextCtrl, positionBefore, 1}}, + {3342, {wxStyledTextCtrl, positionAfter, 1}}, + {3343, {wxStyledTextCtrl, copyRange, 2}}, + {3344, {wxStyledTextCtrl, copyText, 2}}, + {3345, {wxStyledTextCtrl, setSelectionMode, 1}}, + {3346, {wxStyledTextCtrl, getSelectionMode, 0}}, + {3347, {wxStyledTextCtrl, lineDownRectExtend, 0}}, + {3348, {wxStyledTextCtrl, lineUpRectExtend, 0}}, + {3349, {wxStyledTextCtrl, charLeftRectExtend, 0}}, + {3350, {wxStyledTextCtrl, charRightRectExtend, 0}}, + {3351, {wxStyledTextCtrl, homeRectExtend, 0}}, + {3352, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, + {3353, {wxStyledTextCtrl, lineEndRectExtend, 0}}, + {3354, {wxStyledTextCtrl, pageUpRectExtend, 0}}, + {3355, {wxStyledTextCtrl, pageDownRectExtend, 0}}, + {3356, {wxStyledTextCtrl, stutteredPageUp, 0}}, + {3357, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, + {3358, {wxStyledTextCtrl, stutteredPageDown, 0}}, + {3359, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, + {3360, {wxStyledTextCtrl, wordLeftEnd, 0}}, + {3361, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, + {3362, {wxStyledTextCtrl, wordRightEnd, 0}}, + {3363, {wxStyledTextCtrl, wordRightEndExtend, 0}}, + {3364, {wxStyledTextCtrl, setWhitespaceChars, 1}}, + {3365, {wxStyledTextCtrl, setCharsDefault, 0}}, + {3366, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, + {3367, {wxStyledTextCtrl, allocate, 1}}, + {3368, {wxStyledTextCtrl, findColumn, 2}}, + {3369, {wxStyledTextCtrl, getCaretSticky, 0}}, + {3370, {wxStyledTextCtrl, setCaretSticky, 1}}, + {3371, {wxStyledTextCtrl, toggleCaretSticky, 0}}, + {3372, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, + {3373, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, + {3374, {wxStyledTextCtrl, selectionDuplicate, 0}}, + {3375, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, + {3376, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, + {3377, {wxStyledTextCtrl, startRecord, 0}}, + {3378, {wxStyledTextCtrl, stopRecord, 0}}, + {3379, {wxStyledTextCtrl, setLexer, 1}}, + {3380, {wxStyledTextCtrl, getLexer, 0}}, + {3381, {wxStyledTextCtrl, colourise, 2}}, + {3382, {wxStyledTextCtrl, setProperty, 2}}, + {3383, {wxStyledTextCtrl, setKeyWords, 2}}, + {3384, {wxStyledTextCtrl, setLexerLanguage, 1}}, + {3385, {wxStyledTextCtrl, getProperty, 1}}, + {3386, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, + {3387, {wxStyledTextCtrl, getCurrentLine, 0}}, + {3388, {wxStyledTextCtrl, styleSetSpec, 2}}, + {3389, {wxStyledTextCtrl, styleSetFont, 2}}, + {3390, {wxStyledTextCtrl, styleSetFontAttr, 7}}, + {3391, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, + {3392, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, + {3393, {wxStyledTextCtrl, cmdKeyExecute, 1}}, + {3394, {wxStyledTextCtrl, setMargins, 2}}, + {3395, {wxStyledTextCtrl, getSelection, 2}}, + {3396, {wxStyledTextCtrl, pointFromPosition, 1}}, + {3397, {wxStyledTextCtrl, scrollToLine, 1}}, + {3398, {wxStyledTextCtrl, scrollToColumn, 1}}, + {3399, {wxStyledTextCtrl, setVScrollBar, 1}}, + {3400, {wxStyledTextCtrl, setHScrollBar, 1}}, + {3401, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, + {3402, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, + {3403, {wxStyledTextCtrl, saveFile, 1}}, + {3404, {wxStyledTextCtrl, loadFile, 1}}, + {3405, {wxStyledTextCtrl, doDragOver, 3}}, + {3406, {wxStyledTextCtrl, doDropText, 3}}, + {3407, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, + {3408, {wxStyledTextCtrl, addTextRaw, 1}}, + {3409, {wxStyledTextCtrl, insertTextRaw, 2}}, + {3410, {wxStyledTextCtrl, getCurLineRaw, 1}}, + {3411, {wxStyledTextCtrl, getLineRaw, 1}}, + {3412, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, + {3413, {wxStyledTextCtrl, getTextRangeRaw, 2}}, + {3414, {wxStyledTextCtrl, setTextRaw, 1}}, + {3415, {wxStyledTextCtrl, getTextRaw, 0}}, + {3416, {wxStyledTextCtrl, appendTextRaw, 1}}, + {3417, {wxArtProvider, getBitmap, 2}}, + {3418, {wxArtProvider, getIcon, 2}}, + {3419, {wxTreeEvent, getKeyCode, 0}}, + {3420, {wxTreeEvent, getItem, 0}}, + {3421, {wxTreeEvent, getKeyEvent, 0}}, + {3422, {wxTreeEvent, getLabel, 0}}, + {3423, {wxTreeEvent, getOldItem, 0}}, + {3424, {wxTreeEvent, getPoint, 0}}, + {3425, {wxTreeEvent, isEditCancelled, 0}}, + {3426, {wxTreeEvent, setToolTip, 1}}, + {3427, {wxNotebookEvent, getOldSelection, 0}}, + {3428, {wxNotebookEvent, getSelection, 0}}, + {3429, {wxNotebookEvent, setOldSelection, 1}}, + {3430, {wxNotebookEvent, setSelection, 1}}, + {3431, {wxFileDataObject, new, 0}}, + {3432, {wxFileDataObject, addFile, 1}}, + {3433, {wxFileDataObject, getFilenames, 0}}, + {3434, {wxFileDataObject, 'Destroy', undefined}}, + {3435, {wxTextDataObject, new, 1}}, + {3436, {wxTextDataObject, getTextLength, 0}}, + {3437, {wxTextDataObject, getText, 0}}, + {3438, {wxTextDataObject, setText, 1}}, + {3439, {wxTextDataObject, 'Destroy', undefined}}, + {3440, {wxBitmapDataObject, new_1_1, 1}}, + {3441, {wxBitmapDataObject, new_1_0, 1}}, + {3442, {wxBitmapDataObject, getBitmap, 0}}, + {3443, {wxBitmapDataObject, setBitmap, 1}}, + {3444, {wxBitmapDataObject, 'Destroy', undefined}}, + {3446, {wxClipboard, new, 0}}, + {3447, {wxClipboard, destruct, 0}}, + {3448, {wxClipboard, addData, 1}}, + {3449, {wxClipboard, clear, 0}}, + {3450, {wxClipboard, close, 0}}, + {3451, {wxClipboard, flush, 0}}, + {3452, {wxClipboard, getData, 1}}, + {3453, {wxClipboard, isOpened, 0}}, + {3454, {wxClipboard, open, 0}}, + {3455, {wxClipboard, setData, 1}}, + {3457, {wxClipboard, usePrimarySelection, 1}}, + {3458, {wxClipboard, isSupported, 1}}, + {3459, {wxClipboard, get, 0}}, + {3460, {wxSpinEvent, getPosition, 0}}, + {3461, {wxSpinEvent, setPosition, 1}}, + {3462, {wxSplitterWindow, new_0, 0}}, + {3463, {wxSplitterWindow, new_2, 2}}, + {3464, {wxSplitterWindow, destruct, 0}}, + {3465, {wxSplitterWindow, create, 2}}, + {3466, {wxSplitterWindow, getMinimumPaneSize, 0}}, + {3467, {wxSplitterWindow, getSashGravity, 0}}, + {3468, {wxSplitterWindow, getSashPosition, 0}}, + {3469, {wxSplitterWindow, getSplitMode, 0}}, + {3470, {wxSplitterWindow, getWindow1, 0}}, + {3471, {wxSplitterWindow, getWindow2, 0}}, + {3472, {wxSplitterWindow, initialize, 1}}, + {3473, {wxSplitterWindow, isSplit, 0}}, + {3474, {wxSplitterWindow, replaceWindow, 2}}, + {3475, {wxSplitterWindow, setSashGravity, 1}}, + {3476, {wxSplitterWindow, setSashPosition, 2}}, + {3477, {wxSplitterWindow, setSashSize, 1}}, + {3478, {wxSplitterWindow, setMinimumPaneSize, 1}}, + {3479, {wxSplitterWindow, setSplitMode, 1}}, + {3480, {wxSplitterWindow, splitHorizontally, 3}}, + {3481, {wxSplitterWindow, splitVertically, 3}}, + {3482, {wxSplitterWindow, unsplit, 1}}, + {3483, {wxSplitterWindow, updateSize, 0}}, + {3484, {wxSplitterEvent, getSashPosition, 0}}, + {3485, {wxSplitterEvent, getX, 0}}, + {3486, {wxSplitterEvent, getY, 0}}, + {3487, {wxSplitterEvent, getWindowBeingRemoved, 0}}, + {3488, {wxSplitterEvent, setSashPosition, 1}}, + {3489, {wxHtmlWindow, new_0, 0}}, + {3490, {wxHtmlWindow, new_2, 2}}, + {3491, {wxHtmlWindow, appendToPage, 1}}, + {3492, {wxHtmlWindow, getOpenedAnchor, 0}}, + {3493, {wxHtmlWindow, getOpenedPage, 0}}, + {3494, {wxHtmlWindow, getOpenedPageTitle, 0}}, + {3495, {wxHtmlWindow, getRelatedFrame, 0}}, + {3496, {wxHtmlWindow, historyBack, 0}}, + {3497, {wxHtmlWindow, historyCanBack, 0}}, + {3498, {wxHtmlWindow, historyCanForward, 0}}, + {3499, {wxHtmlWindow, historyClear, 0}}, + {3500, {wxHtmlWindow, historyForward, 0}}, + {3501, {wxHtmlWindow, loadFile, 1}}, + {3502, {wxHtmlWindow, loadPage, 1}}, + {3503, {wxHtmlWindow, selectAll, 0}}, + {3504, {wxHtmlWindow, selectionToText, 0}}, + {3505, {wxHtmlWindow, selectLine, 1}}, + {3506, {wxHtmlWindow, selectWord, 1}}, + {3507, {wxHtmlWindow, setBorders, 1}}, + {3508, {wxHtmlWindow, setFonts, 3}}, + {3509, {wxHtmlWindow, setPage, 1}}, + {3510, {wxHtmlWindow, setRelatedFrame, 2}}, + {3511, {wxHtmlWindow, setRelatedStatusBar, 1}}, + {3512, {wxHtmlWindow, toText, 0}}, + {3513, {wxHtmlWindow, 'Destroy', undefined}}, + {3514, {wxHtmlLinkEvent, getLinkInfo, 0}}, + {3515, {wxSystemSettings, getColour, 1}}, + {3516, {wxSystemSettings, getFont, 1}}, + {3517, {wxSystemSettings, getMetric, 2}}, + {3518, {wxSystemSettings, getScreenType, 0}}, + {3519, {wxSystemOptions, getOption, 1}}, + {3520, {wxSystemOptions, getOptionInt, 1}}, + {3521, {wxSystemOptions, hasOption, 1}}, + {3522, {wxSystemOptions, isFalse, 1}}, + {3523, {wxSystemOptions, setOption_2_1, 2}}, + {3524, {wxSystemOptions, setOption_2_0, 2}}, + {3525, {wxAuiNotebookEvent, setSelection, 1}}, + {3526, {wxAuiNotebookEvent, getSelection, 0}}, + {3527, {wxAuiNotebookEvent, setOldSelection, 1}}, + {3528, {wxAuiNotebookEvent, getOldSelection, 0}}, + {3529, {wxAuiNotebookEvent, setDragSource, 1}}, + {3530, {wxAuiNotebookEvent, getDragSource, 0}}, + {3531, {wxAuiManagerEvent, setManager, 1}}, + {3532, {wxAuiManagerEvent, getManager, 0}}, + {3533, {wxAuiManagerEvent, setPane, 1}}, + {3534, {wxAuiManagerEvent, getPane, 0}}, + {3535, {wxAuiManagerEvent, setButton, 1}}, + {3536, {wxAuiManagerEvent, getButton, 0}}, + {3537, {wxAuiManagerEvent, setDC, 1}}, + {3538, {wxAuiManagerEvent, getDC, 0}}, + {3539, {wxAuiManagerEvent, veto, 1}}, + {3540, {wxAuiManagerEvent, getVeto, 0}}, + {3541, {wxAuiManagerEvent, setCanVeto, 1}}, + {3542, {wxAuiManagerEvent, canVeto, 0}}, + {3543, {wxLogNull, new, 0}}, + {3544, {wxLogNull, 'Destroy', undefined}}, + {3545, {wxTaskBarIcon, new, 0}}, + {3546, {wxTaskBarIcon, destruct, 0}}, + {3547, {wxTaskBarIcon, popupMenu, 1}}, + {3548, {wxTaskBarIcon, removeIcon, 0}}, + {3549, {wxTaskBarIcon, setIcon, 2}}, + {3550, {wxLocale, new_0, 0}}, + {3552, {wxLocale, new_2, 2}}, + {3553, {wxLocale, destruct, 0}}, + {3555, {wxLocale, init, 1}}, + {3556, {wxLocale, addCatalog_1, 1}}, + {3557, {wxLocale, addCatalog_3, 3}}, + {3558, {wxLocale, addCatalogLookupPathPrefix, 1}}, + {3559, {wxLocale, getCanonicalName, 0}}, + {3560, {wxLocale, getLanguage, 0}}, + {3561, {wxLocale, getLanguageName, 1}}, + {3562, {wxLocale, getLocale, 0}}, + {3563, {wxLocale, getName, 0}}, + {3564, {wxLocale, getString_2, 2}}, + {3565, {wxLocale, getString_4, 4}}, + {3566, {wxLocale, getHeaderValue, 2}}, + {3567, {wxLocale, getSysName, 0}}, + {3568, {wxLocale, getSystemEncoding, 0}}, + {3569, {wxLocale, getSystemEncodingName, 0}}, + {3570, {wxLocale, getSystemLanguage, 0}}, + {3571, {wxLocale, isLoaded, 1}}, + {3572, {wxLocale, isOk, 0}}, + {3573, {wxActivateEvent, getActive, 0}}, + {3575, {wxPopupWindow, new_2, 2}}, + {3576, {wxPopupWindow, new_0, 0}}, + {3578, {wxPopupWindow, destruct, 0}}, + {3579, {wxPopupWindow, create, 2}}, + {3580, {wxPopupWindow, position, 2}}, + {3581, {wxPopupTransientWindow, new_0, 0}}, + {3582, {wxPopupTransientWindow, new_2, 2}}, + {3583, {wxPopupTransientWindow, destruct, 0}}, + {3584, {wxPopupTransientWindow, popup, 1}}, + {3585, {wxPopupTransientWindow, dismiss, 0}}, {-1, {mod, func, -1}} ]. diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl index faab72184d..d8c2ba9171 100644 --- a/lib/wx/src/gen/wxe_funcs.hrl +++ b/lib/wx/src/gen/wxe_funcs.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2014. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -2437,904 +2437,926 @@ -define(wxAuiPaneInfo_Top, 2650). -define(wxAuiPaneInfo_TopDockable, 2651). -define(wxAuiPaneInfo_Window, 2652). --define(wxAuiNotebook_new_0, 2653). --define(wxAuiNotebook_new_2, 2654). --define(wxAuiNotebook_AddPage, 2655). --define(wxAuiNotebook_Create, 2656). --define(wxAuiNotebook_DeletePage, 2657). --define(wxAuiNotebook_GetArtProvider, 2658). --define(wxAuiNotebook_GetPage, 2659). --define(wxAuiNotebook_GetPageBitmap, 2660). --define(wxAuiNotebook_GetPageCount, 2661). --define(wxAuiNotebook_GetPageIndex, 2662). --define(wxAuiNotebook_GetPageText, 2663). --define(wxAuiNotebook_GetSelection, 2664). --define(wxAuiNotebook_InsertPage, 2665). --define(wxAuiNotebook_RemovePage, 2666). --define(wxAuiNotebook_SetArtProvider, 2667). --define(wxAuiNotebook_SetFont, 2668). --define(wxAuiNotebook_SetPageBitmap, 2669). --define(wxAuiNotebook_SetPageText, 2670). --define(wxAuiNotebook_SetSelection, 2671). --define(wxAuiNotebook_SetTabCtrlHeight, 2672). --define(wxAuiNotebook_SetUniformBitmapSize, 2673). --define(wxAuiNotebook_destroy, 2674). --define(wxMDIParentFrame_new_0, 2675). --define(wxMDIParentFrame_new_4, 2676). --define(wxMDIParentFrame_destruct, 2677). --define(wxMDIParentFrame_ActivateNext, 2678). --define(wxMDIParentFrame_ActivatePrevious, 2679). --define(wxMDIParentFrame_ArrangeIcons, 2680). --define(wxMDIParentFrame_Cascade, 2681). --define(wxMDIParentFrame_Create, 2682). --define(wxMDIParentFrame_GetActiveChild, 2683). --define(wxMDIParentFrame_GetClientWindow, 2684). --define(wxMDIParentFrame_Tile, 2685). --define(wxMDIChildFrame_new_0, 2686). --define(wxMDIChildFrame_new_4, 2687). --define(wxMDIChildFrame_destruct, 2688). --define(wxMDIChildFrame_Activate, 2689). --define(wxMDIChildFrame_Create, 2690). --define(wxMDIChildFrame_Maximize, 2691). --define(wxMDIChildFrame_Restore, 2692). --define(wxMDIClientWindow_new_0, 2693). --define(wxMDIClientWindow_new_2, 2694). --define(wxMDIClientWindow_destruct, 2695). --define(wxMDIClientWindow_CreateClient, 2696). --define(wxLayoutAlgorithm_new, 2697). --define(wxLayoutAlgorithm_LayoutFrame, 2698). --define(wxLayoutAlgorithm_LayoutMDIFrame, 2699). --define(wxLayoutAlgorithm_LayoutWindow, 2700). --define(wxLayoutAlgorithm_destroy, 2701). --define(wxEvent_GetId, 2702). --define(wxEvent_GetSkipped, 2703). --define(wxEvent_GetTimestamp, 2704). --define(wxEvent_IsCommandEvent, 2705). --define(wxEvent_ResumePropagation, 2706). --define(wxEvent_ShouldPropagate, 2707). --define(wxEvent_Skip, 2708). --define(wxEvent_StopPropagation, 2709). --define(wxCommandEvent_getClientData, 2710). --define(wxCommandEvent_GetExtraLong, 2711). --define(wxCommandEvent_GetInt, 2712). --define(wxCommandEvent_GetSelection, 2713). --define(wxCommandEvent_GetString, 2714). --define(wxCommandEvent_IsChecked, 2715). --define(wxCommandEvent_IsSelection, 2716). --define(wxCommandEvent_SetInt, 2717). --define(wxCommandEvent_SetString, 2718). --define(wxScrollEvent_GetOrientation, 2719). --define(wxScrollEvent_GetPosition, 2720). --define(wxScrollWinEvent_GetOrientation, 2721). --define(wxScrollWinEvent_GetPosition, 2722). --define(wxMouseEvent_AltDown, 2723). --define(wxMouseEvent_Button, 2724). --define(wxMouseEvent_ButtonDClick, 2725). --define(wxMouseEvent_ButtonDown, 2726). --define(wxMouseEvent_ButtonUp, 2727). --define(wxMouseEvent_CmdDown, 2728). --define(wxMouseEvent_ControlDown, 2729). --define(wxMouseEvent_Dragging, 2730). --define(wxMouseEvent_Entering, 2731). --define(wxMouseEvent_GetButton, 2732). --define(wxMouseEvent_GetPosition, 2735). --define(wxMouseEvent_GetLogicalPosition, 2736). --define(wxMouseEvent_GetLinesPerAction, 2737). --define(wxMouseEvent_GetWheelRotation, 2738). --define(wxMouseEvent_GetWheelDelta, 2739). --define(wxMouseEvent_GetX, 2740). --define(wxMouseEvent_GetY, 2741). --define(wxMouseEvent_IsButton, 2742). --define(wxMouseEvent_IsPageScroll, 2743). --define(wxMouseEvent_Leaving, 2744). --define(wxMouseEvent_LeftDClick, 2745). --define(wxMouseEvent_LeftDown, 2746). --define(wxMouseEvent_LeftIsDown, 2747). --define(wxMouseEvent_LeftUp, 2748). --define(wxMouseEvent_MetaDown, 2749). --define(wxMouseEvent_MiddleDClick, 2750). --define(wxMouseEvent_MiddleDown, 2751). --define(wxMouseEvent_MiddleIsDown, 2752). --define(wxMouseEvent_MiddleUp, 2753). --define(wxMouseEvent_Moving, 2754). --define(wxMouseEvent_RightDClick, 2755). --define(wxMouseEvent_RightDown, 2756). --define(wxMouseEvent_RightIsDown, 2757). --define(wxMouseEvent_RightUp, 2758). --define(wxMouseEvent_ShiftDown, 2759). --define(wxSetCursorEvent_GetCursor, 2760). --define(wxSetCursorEvent_GetX, 2761). --define(wxSetCursorEvent_GetY, 2762). --define(wxSetCursorEvent_HasCursor, 2763). --define(wxSetCursorEvent_SetCursor, 2764). --define(wxKeyEvent_AltDown, 2765). --define(wxKeyEvent_CmdDown, 2766). --define(wxKeyEvent_ControlDown, 2767). --define(wxKeyEvent_GetKeyCode, 2768). --define(wxKeyEvent_GetModifiers, 2769). --define(wxKeyEvent_GetPosition, 2772). --define(wxKeyEvent_GetRawKeyCode, 2773). --define(wxKeyEvent_GetRawKeyFlags, 2774). --define(wxKeyEvent_GetUnicodeKey, 2775). --define(wxKeyEvent_GetX, 2776). --define(wxKeyEvent_GetY, 2777). --define(wxKeyEvent_HasModifiers, 2778). --define(wxKeyEvent_MetaDown, 2779). --define(wxKeyEvent_ShiftDown, 2780). --define(wxSizeEvent_GetSize, 2781). --define(wxMoveEvent_GetPosition, 2782). --define(wxEraseEvent_GetDC, 2783). --define(wxFocusEvent_GetWindow, 2784). --define(wxChildFocusEvent_GetWindow, 2785). --define(wxMenuEvent_GetMenu, 2786). --define(wxMenuEvent_GetMenuId, 2787). --define(wxMenuEvent_IsPopup, 2788). --define(wxCloseEvent_CanVeto, 2789). --define(wxCloseEvent_GetLoggingOff, 2790). --define(wxCloseEvent_SetCanVeto, 2791). --define(wxCloseEvent_SetLoggingOff, 2792). --define(wxCloseEvent_Veto, 2793). --define(wxShowEvent_SetShow, 2794). --define(wxShowEvent_GetShow, 2795). --define(wxIconizeEvent_Iconized, 2796). --define(wxJoystickEvent_ButtonDown, 2797). --define(wxJoystickEvent_ButtonIsDown, 2798). --define(wxJoystickEvent_ButtonUp, 2799). --define(wxJoystickEvent_GetButtonChange, 2800). --define(wxJoystickEvent_GetButtonState, 2801). --define(wxJoystickEvent_GetJoystick, 2802). --define(wxJoystickEvent_GetPosition, 2803). --define(wxJoystickEvent_GetZPosition, 2804). --define(wxJoystickEvent_IsButton, 2805). --define(wxJoystickEvent_IsMove, 2806). --define(wxJoystickEvent_IsZMove, 2807). --define(wxUpdateUIEvent_CanUpdate, 2808). --define(wxUpdateUIEvent_Check, 2809). --define(wxUpdateUIEvent_Enable, 2810). --define(wxUpdateUIEvent_Show, 2811). --define(wxUpdateUIEvent_GetChecked, 2812). --define(wxUpdateUIEvent_GetEnabled, 2813). --define(wxUpdateUIEvent_GetShown, 2814). --define(wxUpdateUIEvent_GetSetChecked, 2815). --define(wxUpdateUIEvent_GetSetEnabled, 2816). --define(wxUpdateUIEvent_GetSetShown, 2817). --define(wxUpdateUIEvent_GetSetText, 2818). --define(wxUpdateUIEvent_GetText, 2819). --define(wxUpdateUIEvent_GetMode, 2820). --define(wxUpdateUIEvent_GetUpdateInterval, 2821). --define(wxUpdateUIEvent_ResetUpdateTime, 2822). --define(wxUpdateUIEvent_SetMode, 2823). --define(wxUpdateUIEvent_SetText, 2824). --define(wxUpdateUIEvent_SetUpdateInterval, 2825). --define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2826). --define(wxPaletteChangedEvent_SetChangedWindow, 2827). --define(wxPaletteChangedEvent_GetChangedWindow, 2828). --define(wxQueryNewPaletteEvent_SetPaletteRealized, 2829). --define(wxQueryNewPaletteEvent_GetPaletteRealized, 2830). --define(wxNavigationKeyEvent_GetDirection, 2831). --define(wxNavigationKeyEvent_SetDirection, 2832). --define(wxNavigationKeyEvent_IsWindowChange, 2833). --define(wxNavigationKeyEvent_SetWindowChange, 2834). --define(wxNavigationKeyEvent_IsFromTab, 2835). --define(wxNavigationKeyEvent_SetFromTab, 2836). --define(wxNavigationKeyEvent_GetCurrentFocus, 2837). --define(wxNavigationKeyEvent_SetCurrentFocus, 2838). --define(wxHelpEvent_GetOrigin, 2839). --define(wxHelpEvent_GetPosition, 2840). --define(wxHelpEvent_SetOrigin, 2841). --define(wxHelpEvent_SetPosition, 2842). --define(wxContextMenuEvent_GetPosition, 2843). --define(wxContextMenuEvent_SetPosition, 2844). --define(wxIdleEvent_CanSend, 2845). --define(wxIdleEvent_GetMode, 2846). --define(wxIdleEvent_RequestMore, 2847). --define(wxIdleEvent_MoreRequested, 2848). --define(wxIdleEvent_SetMode, 2849). --define(wxGridEvent_AltDown, 2850). --define(wxGridEvent_ControlDown, 2851). --define(wxGridEvent_GetCol, 2852). --define(wxGridEvent_GetPosition, 2853). --define(wxGridEvent_GetRow, 2854). --define(wxGridEvent_MetaDown, 2855). --define(wxGridEvent_Selecting, 2856). --define(wxGridEvent_ShiftDown, 2857). --define(wxNotifyEvent_Allow, 2858). --define(wxNotifyEvent_IsAllowed, 2859). --define(wxNotifyEvent_Veto, 2860). --define(wxSashEvent_GetEdge, 2861). --define(wxSashEvent_GetDragRect, 2862). --define(wxSashEvent_GetDragStatus, 2863). --define(wxListEvent_GetCacheFrom, 2864). --define(wxListEvent_GetCacheTo, 2865). --define(wxListEvent_GetKeyCode, 2866). --define(wxListEvent_GetIndex, 2867). --define(wxListEvent_GetColumn, 2868). --define(wxListEvent_GetPoint, 2869). --define(wxListEvent_GetLabel, 2870). --define(wxListEvent_GetText, 2871). --define(wxListEvent_GetImage, 2872). --define(wxListEvent_GetData, 2873). --define(wxListEvent_GetMask, 2874). --define(wxListEvent_GetItem, 2875). --define(wxListEvent_IsEditCancelled, 2876). --define(wxDateEvent_GetDate, 2877). --define(wxCalendarEvent_GetWeekDay, 2878). --define(wxFileDirPickerEvent_GetPath, 2879). --define(wxColourPickerEvent_GetColour, 2880). --define(wxFontPickerEvent_GetFont, 2881). --define(wxStyledTextEvent_GetPosition, 2882). --define(wxStyledTextEvent_GetKey, 2883). --define(wxStyledTextEvent_GetModifiers, 2884). --define(wxStyledTextEvent_GetModificationType, 2885). --define(wxStyledTextEvent_GetText, 2886). --define(wxStyledTextEvent_GetLength, 2887). --define(wxStyledTextEvent_GetLinesAdded, 2888). --define(wxStyledTextEvent_GetLine, 2889). --define(wxStyledTextEvent_GetFoldLevelNow, 2890). --define(wxStyledTextEvent_GetFoldLevelPrev, 2891). --define(wxStyledTextEvent_GetMargin, 2892). --define(wxStyledTextEvent_GetMessage, 2893). --define(wxStyledTextEvent_GetWParam, 2894). --define(wxStyledTextEvent_GetLParam, 2895). --define(wxStyledTextEvent_GetListType, 2896). --define(wxStyledTextEvent_GetX, 2897). --define(wxStyledTextEvent_GetY, 2898). --define(wxStyledTextEvent_GetDragText, 2899). --define(wxStyledTextEvent_GetDragAllowMove, 2900). --define(wxStyledTextEvent_GetDragResult, 2901). --define(wxStyledTextEvent_GetShift, 2902). --define(wxStyledTextEvent_GetControl, 2903). --define(wxStyledTextEvent_GetAlt, 2904). --define(utils_wxGetKeyState, 2905). --define(utils_wxGetMousePosition, 2906). --define(utils_wxGetMouseState, 2907). --define(utils_wxSetDetectableAutoRepeat, 2908). --define(utils_wxBell, 2909). --define(utils_wxFindMenuItemId, 2910). --define(utils_wxGenericFindWindowAtPoint, 2911). --define(utils_wxFindWindowAtPoint, 2912). --define(utils_wxBeginBusyCursor, 2913). --define(utils_wxEndBusyCursor, 2914). --define(utils_wxIsBusy, 2915). --define(utils_wxShutdown, 2916). --define(utils_wxShell, 2917). --define(utils_wxLaunchDefaultBrowser, 2918). --define(utils_wxGetEmailAddress, 2919). --define(utils_wxGetUserId, 2920). --define(utils_wxGetHomeDir, 2921). --define(utils_wxNewId, 2922). --define(utils_wxRegisterId, 2923). --define(utils_wxGetCurrentId, 2924). --define(utils_wxGetOsDescription, 2925). --define(utils_wxIsPlatformLittleEndian, 2926). --define(utils_wxIsPlatform64Bit, 2927). --define(gdicmn_wxDisplaySize, 2928). --define(gdicmn_wxSetCursor, 2929). --define(wxPrintout_new, 2930). --define(wxPrintout_destruct, 2931). --define(wxPrintout_GetDC, 2932). --define(wxPrintout_GetPageSizeMM, 2933). --define(wxPrintout_GetPageSizePixels, 2934). --define(wxPrintout_GetPaperRectPixels, 2935). --define(wxPrintout_GetPPIPrinter, 2936). --define(wxPrintout_GetPPIScreen, 2937). --define(wxPrintout_GetTitle, 2938). --define(wxPrintout_IsPreview, 2939). --define(wxPrintout_FitThisSizeToPaper, 2940). --define(wxPrintout_FitThisSizeToPage, 2941). --define(wxPrintout_FitThisSizeToPageMargins, 2942). --define(wxPrintout_MapScreenSizeToPaper, 2943). --define(wxPrintout_MapScreenSizeToPage, 2944). --define(wxPrintout_MapScreenSizeToPageMargins, 2945). --define(wxPrintout_MapScreenSizeToDevice, 2946). --define(wxPrintout_GetLogicalPaperRect, 2947). --define(wxPrintout_GetLogicalPageRect, 2948). --define(wxPrintout_GetLogicalPageMarginsRect, 2949). --define(wxPrintout_SetLogicalOrigin, 2950). --define(wxPrintout_OffsetLogicalOrigin, 2951). --define(wxStyledTextCtrl_new_2, 2952). --define(wxStyledTextCtrl_new_0, 2953). --define(wxStyledTextCtrl_destruct, 2954). --define(wxStyledTextCtrl_Create, 2955). --define(wxStyledTextCtrl_AddText, 2956). --define(wxStyledTextCtrl_AddStyledText, 2957). --define(wxStyledTextCtrl_InsertText, 2958). --define(wxStyledTextCtrl_ClearAll, 2959). --define(wxStyledTextCtrl_ClearDocumentStyle, 2960). --define(wxStyledTextCtrl_GetLength, 2961). --define(wxStyledTextCtrl_GetCharAt, 2962). --define(wxStyledTextCtrl_GetCurrentPos, 2963). --define(wxStyledTextCtrl_GetAnchor, 2964). --define(wxStyledTextCtrl_GetStyleAt, 2965). --define(wxStyledTextCtrl_Redo, 2966). --define(wxStyledTextCtrl_SetUndoCollection, 2967). --define(wxStyledTextCtrl_SelectAll, 2968). --define(wxStyledTextCtrl_SetSavePoint, 2969). --define(wxStyledTextCtrl_GetStyledText, 2970). --define(wxStyledTextCtrl_CanRedo, 2971). --define(wxStyledTextCtrl_MarkerLineFromHandle, 2972). --define(wxStyledTextCtrl_MarkerDeleteHandle, 2973). --define(wxStyledTextCtrl_GetUndoCollection, 2974). --define(wxStyledTextCtrl_GetViewWhiteSpace, 2975). --define(wxStyledTextCtrl_SetViewWhiteSpace, 2976). --define(wxStyledTextCtrl_PositionFromPoint, 2977). --define(wxStyledTextCtrl_PositionFromPointClose, 2978). --define(wxStyledTextCtrl_GotoLine, 2979). --define(wxStyledTextCtrl_GotoPos, 2980). --define(wxStyledTextCtrl_SetAnchor, 2981). --define(wxStyledTextCtrl_GetCurLine, 2982). --define(wxStyledTextCtrl_GetEndStyled, 2983). --define(wxStyledTextCtrl_ConvertEOLs, 2984). --define(wxStyledTextCtrl_GetEOLMode, 2985). --define(wxStyledTextCtrl_SetEOLMode, 2986). --define(wxStyledTextCtrl_StartStyling, 2987). --define(wxStyledTextCtrl_SetStyling, 2988). --define(wxStyledTextCtrl_GetBufferedDraw, 2989). --define(wxStyledTextCtrl_SetBufferedDraw, 2990). --define(wxStyledTextCtrl_SetTabWidth, 2991). --define(wxStyledTextCtrl_GetTabWidth, 2992). --define(wxStyledTextCtrl_SetCodePage, 2993). --define(wxStyledTextCtrl_MarkerDefine, 2994). --define(wxStyledTextCtrl_MarkerSetForeground, 2995). --define(wxStyledTextCtrl_MarkerSetBackground, 2996). --define(wxStyledTextCtrl_MarkerAdd, 2997). --define(wxStyledTextCtrl_MarkerDelete, 2998). --define(wxStyledTextCtrl_MarkerDeleteAll, 2999). --define(wxStyledTextCtrl_MarkerGet, 3000). --define(wxStyledTextCtrl_MarkerNext, 3001). --define(wxStyledTextCtrl_MarkerPrevious, 3002). --define(wxStyledTextCtrl_MarkerDefineBitmap, 3003). --define(wxStyledTextCtrl_MarkerAddSet, 3004). --define(wxStyledTextCtrl_MarkerSetAlpha, 3005). --define(wxStyledTextCtrl_SetMarginType, 3006). --define(wxStyledTextCtrl_GetMarginType, 3007). --define(wxStyledTextCtrl_SetMarginWidth, 3008). --define(wxStyledTextCtrl_GetMarginWidth, 3009). --define(wxStyledTextCtrl_SetMarginMask, 3010). --define(wxStyledTextCtrl_GetMarginMask, 3011). --define(wxStyledTextCtrl_SetMarginSensitive, 3012). --define(wxStyledTextCtrl_GetMarginSensitive, 3013). --define(wxStyledTextCtrl_StyleClearAll, 3014). --define(wxStyledTextCtrl_StyleSetForeground, 3015). --define(wxStyledTextCtrl_StyleSetBackground, 3016). --define(wxStyledTextCtrl_StyleSetBold, 3017). --define(wxStyledTextCtrl_StyleSetItalic, 3018). --define(wxStyledTextCtrl_StyleSetSize, 3019). --define(wxStyledTextCtrl_StyleSetFaceName, 3020). --define(wxStyledTextCtrl_StyleSetEOLFilled, 3021). --define(wxStyledTextCtrl_StyleResetDefault, 3022). --define(wxStyledTextCtrl_StyleSetUnderline, 3023). --define(wxStyledTextCtrl_StyleSetCase, 3024). --define(wxStyledTextCtrl_StyleSetHotSpot, 3025). --define(wxStyledTextCtrl_SetSelForeground, 3026). --define(wxStyledTextCtrl_SetSelBackground, 3027). --define(wxStyledTextCtrl_GetSelAlpha, 3028). --define(wxStyledTextCtrl_SetSelAlpha, 3029). --define(wxStyledTextCtrl_SetCaretForeground, 3030). --define(wxStyledTextCtrl_CmdKeyAssign, 3031). --define(wxStyledTextCtrl_CmdKeyClear, 3032). --define(wxStyledTextCtrl_CmdKeyClearAll, 3033). --define(wxStyledTextCtrl_SetStyleBytes, 3034). --define(wxStyledTextCtrl_StyleSetVisible, 3035). --define(wxStyledTextCtrl_GetCaretPeriod, 3036). --define(wxStyledTextCtrl_SetCaretPeriod, 3037). --define(wxStyledTextCtrl_SetWordChars, 3038). --define(wxStyledTextCtrl_BeginUndoAction, 3039). --define(wxStyledTextCtrl_EndUndoAction, 3040). --define(wxStyledTextCtrl_IndicatorSetStyle, 3041). --define(wxStyledTextCtrl_IndicatorGetStyle, 3042). --define(wxStyledTextCtrl_IndicatorSetForeground, 3043). --define(wxStyledTextCtrl_IndicatorGetForeground, 3044). --define(wxStyledTextCtrl_SetWhitespaceForeground, 3045). --define(wxStyledTextCtrl_SetWhitespaceBackground, 3046). --define(wxStyledTextCtrl_GetStyleBits, 3047). --define(wxStyledTextCtrl_SetLineState, 3048). --define(wxStyledTextCtrl_GetLineState, 3049). --define(wxStyledTextCtrl_GetMaxLineState, 3050). --define(wxStyledTextCtrl_GetCaretLineVisible, 3051). --define(wxStyledTextCtrl_SetCaretLineVisible, 3052). --define(wxStyledTextCtrl_GetCaretLineBackground, 3053). --define(wxStyledTextCtrl_SetCaretLineBackground, 3054). --define(wxStyledTextCtrl_AutoCompShow, 3055). --define(wxStyledTextCtrl_AutoCompCancel, 3056). --define(wxStyledTextCtrl_AutoCompActive, 3057). --define(wxStyledTextCtrl_AutoCompPosStart, 3058). --define(wxStyledTextCtrl_AutoCompComplete, 3059). --define(wxStyledTextCtrl_AutoCompStops, 3060). --define(wxStyledTextCtrl_AutoCompSetSeparator, 3061). --define(wxStyledTextCtrl_AutoCompGetSeparator, 3062). --define(wxStyledTextCtrl_AutoCompSelect, 3063). --define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3064). --define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3065). --define(wxStyledTextCtrl_AutoCompSetFillUps, 3066). --define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3067). --define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3068). --define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3069). --define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3070). --define(wxStyledTextCtrl_UserListShow, 3071). --define(wxStyledTextCtrl_AutoCompSetAutoHide, 3072). --define(wxStyledTextCtrl_AutoCompGetAutoHide, 3073). --define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3074). --define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3075). --define(wxStyledTextCtrl_RegisterImage, 3076). --define(wxStyledTextCtrl_ClearRegisteredImages, 3077). --define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3078). --define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3079). --define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3080). --define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3081). --define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3082). --define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3083). --define(wxStyledTextCtrl_SetIndent, 3084). --define(wxStyledTextCtrl_GetIndent, 3085). --define(wxStyledTextCtrl_SetUseTabs, 3086). --define(wxStyledTextCtrl_GetUseTabs, 3087). --define(wxStyledTextCtrl_SetLineIndentation, 3088). --define(wxStyledTextCtrl_GetLineIndentation, 3089). --define(wxStyledTextCtrl_GetLineIndentPosition, 3090). --define(wxStyledTextCtrl_GetColumn, 3091). --define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3092). --define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3093). --define(wxStyledTextCtrl_SetIndentationGuides, 3094). --define(wxStyledTextCtrl_GetIndentationGuides, 3095). --define(wxStyledTextCtrl_SetHighlightGuide, 3096). --define(wxStyledTextCtrl_GetHighlightGuide, 3097). --define(wxStyledTextCtrl_GetLineEndPosition, 3098). --define(wxStyledTextCtrl_GetCodePage, 3099). --define(wxStyledTextCtrl_GetCaretForeground, 3100). --define(wxStyledTextCtrl_GetReadOnly, 3101). --define(wxStyledTextCtrl_SetCurrentPos, 3102). --define(wxStyledTextCtrl_SetSelectionStart, 3103). --define(wxStyledTextCtrl_GetSelectionStart, 3104). --define(wxStyledTextCtrl_SetSelectionEnd, 3105). --define(wxStyledTextCtrl_GetSelectionEnd, 3106). --define(wxStyledTextCtrl_SetPrintMagnification, 3107). --define(wxStyledTextCtrl_GetPrintMagnification, 3108). --define(wxStyledTextCtrl_SetPrintColourMode, 3109). --define(wxStyledTextCtrl_GetPrintColourMode, 3110). --define(wxStyledTextCtrl_FindText, 3111). --define(wxStyledTextCtrl_FormatRange, 3112). --define(wxStyledTextCtrl_GetFirstVisibleLine, 3113). --define(wxStyledTextCtrl_GetLine, 3114). --define(wxStyledTextCtrl_GetLineCount, 3115). --define(wxStyledTextCtrl_SetMarginLeft, 3116). --define(wxStyledTextCtrl_GetMarginLeft, 3117). --define(wxStyledTextCtrl_SetMarginRight, 3118). --define(wxStyledTextCtrl_GetMarginRight, 3119). --define(wxStyledTextCtrl_GetModify, 3120). --define(wxStyledTextCtrl_SetSelection, 3121). --define(wxStyledTextCtrl_GetSelectedText, 3122). --define(wxStyledTextCtrl_GetTextRange, 3123). --define(wxStyledTextCtrl_HideSelection, 3124). --define(wxStyledTextCtrl_LineFromPosition, 3125). --define(wxStyledTextCtrl_PositionFromLine, 3126). --define(wxStyledTextCtrl_LineScroll, 3127). --define(wxStyledTextCtrl_EnsureCaretVisible, 3128). --define(wxStyledTextCtrl_ReplaceSelection, 3129). --define(wxStyledTextCtrl_SetReadOnly, 3130). --define(wxStyledTextCtrl_CanPaste, 3131). --define(wxStyledTextCtrl_CanUndo, 3132). --define(wxStyledTextCtrl_EmptyUndoBuffer, 3133). --define(wxStyledTextCtrl_Undo, 3134). --define(wxStyledTextCtrl_Cut, 3135). --define(wxStyledTextCtrl_Copy, 3136). --define(wxStyledTextCtrl_Paste, 3137). --define(wxStyledTextCtrl_Clear, 3138). --define(wxStyledTextCtrl_SetText, 3139). --define(wxStyledTextCtrl_GetText, 3140). --define(wxStyledTextCtrl_GetTextLength, 3141). --define(wxStyledTextCtrl_GetOvertype, 3142). --define(wxStyledTextCtrl_SetCaretWidth, 3143). --define(wxStyledTextCtrl_GetCaretWidth, 3144). --define(wxStyledTextCtrl_SetTargetStart, 3145). --define(wxStyledTextCtrl_GetTargetStart, 3146). --define(wxStyledTextCtrl_SetTargetEnd, 3147). --define(wxStyledTextCtrl_GetTargetEnd, 3148). --define(wxStyledTextCtrl_ReplaceTarget, 3149). --define(wxStyledTextCtrl_SearchInTarget, 3150). --define(wxStyledTextCtrl_SetSearchFlags, 3151). --define(wxStyledTextCtrl_GetSearchFlags, 3152). --define(wxStyledTextCtrl_CallTipShow, 3153). --define(wxStyledTextCtrl_CallTipCancel, 3154). --define(wxStyledTextCtrl_CallTipActive, 3155). --define(wxStyledTextCtrl_CallTipPosAtStart, 3156). --define(wxStyledTextCtrl_CallTipSetHighlight, 3157). --define(wxStyledTextCtrl_CallTipSetBackground, 3158). --define(wxStyledTextCtrl_CallTipSetForeground, 3159). --define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3160). --define(wxStyledTextCtrl_CallTipUseStyle, 3161). --define(wxStyledTextCtrl_VisibleFromDocLine, 3162). --define(wxStyledTextCtrl_DocLineFromVisible, 3163). --define(wxStyledTextCtrl_WrapCount, 3164). --define(wxStyledTextCtrl_SetFoldLevel, 3165). --define(wxStyledTextCtrl_GetFoldLevel, 3166). --define(wxStyledTextCtrl_GetLastChild, 3167). --define(wxStyledTextCtrl_GetFoldParent, 3168). --define(wxStyledTextCtrl_ShowLines, 3169). --define(wxStyledTextCtrl_HideLines, 3170). --define(wxStyledTextCtrl_GetLineVisible, 3171). --define(wxStyledTextCtrl_SetFoldExpanded, 3172). --define(wxStyledTextCtrl_GetFoldExpanded, 3173). --define(wxStyledTextCtrl_ToggleFold, 3174). --define(wxStyledTextCtrl_EnsureVisible, 3175). --define(wxStyledTextCtrl_SetFoldFlags, 3176). --define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3177). --define(wxStyledTextCtrl_SetTabIndents, 3178). --define(wxStyledTextCtrl_GetTabIndents, 3179). --define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3180). --define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3181). --define(wxStyledTextCtrl_SetMouseDwellTime, 3182). --define(wxStyledTextCtrl_GetMouseDwellTime, 3183). --define(wxStyledTextCtrl_WordStartPosition, 3184). --define(wxStyledTextCtrl_WordEndPosition, 3185). --define(wxStyledTextCtrl_SetWrapMode, 3186). --define(wxStyledTextCtrl_GetWrapMode, 3187). --define(wxStyledTextCtrl_SetWrapVisualFlags, 3188). --define(wxStyledTextCtrl_GetWrapVisualFlags, 3189). --define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3190). --define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3191). --define(wxStyledTextCtrl_SetWrapStartIndent, 3192). --define(wxStyledTextCtrl_GetWrapStartIndent, 3193). --define(wxStyledTextCtrl_SetLayoutCache, 3194). --define(wxStyledTextCtrl_GetLayoutCache, 3195). --define(wxStyledTextCtrl_SetScrollWidth, 3196). --define(wxStyledTextCtrl_GetScrollWidth, 3197). --define(wxStyledTextCtrl_TextWidth, 3198). --define(wxStyledTextCtrl_GetEndAtLastLine, 3199). --define(wxStyledTextCtrl_TextHeight, 3200). --define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3201). --define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3202). --define(wxStyledTextCtrl_AppendText, 3203). --define(wxStyledTextCtrl_GetTwoPhaseDraw, 3204). --define(wxStyledTextCtrl_SetTwoPhaseDraw, 3205). --define(wxStyledTextCtrl_TargetFromSelection, 3206). --define(wxStyledTextCtrl_LinesJoin, 3207). --define(wxStyledTextCtrl_LinesSplit, 3208). --define(wxStyledTextCtrl_SetFoldMarginColour, 3209). --define(wxStyledTextCtrl_SetFoldMarginHiColour, 3210). --define(wxStyledTextCtrl_LineDown, 3211). --define(wxStyledTextCtrl_LineDownExtend, 3212). --define(wxStyledTextCtrl_LineUp, 3213). --define(wxStyledTextCtrl_LineUpExtend, 3214). --define(wxStyledTextCtrl_CharLeft, 3215). --define(wxStyledTextCtrl_CharLeftExtend, 3216). --define(wxStyledTextCtrl_CharRight, 3217). --define(wxStyledTextCtrl_CharRightExtend, 3218). --define(wxStyledTextCtrl_WordLeft, 3219). --define(wxStyledTextCtrl_WordLeftExtend, 3220). --define(wxStyledTextCtrl_WordRight, 3221). --define(wxStyledTextCtrl_WordRightExtend, 3222). --define(wxStyledTextCtrl_Home, 3223). --define(wxStyledTextCtrl_HomeExtend, 3224). --define(wxStyledTextCtrl_LineEnd, 3225). --define(wxStyledTextCtrl_LineEndExtend, 3226). --define(wxStyledTextCtrl_DocumentStart, 3227). --define(wxStyledTextCtrl_DocumentStartExtend, 3228). --define(wxStyledTextCtrl_DocumentEnd, 3229). --define(wxStyledTextCtrl_DocumentEndExtend, 3230). --define(wxStyledTextCtrl_PageUp, 3231). --define(wxStyledTextCtrl_PageUpExtend, 3232). --define(wxStyledTextCtrl_PageDown, 3233). --define(wxStyledTextCtrl_PageDownExtend, 3234). --define(wxStyledTextCtrl_EditToggleOvertype, 3235). --define(wxStyledTextCtrl_Cancel, 3236). --define(wxStyledTextCtrl_DeleteBack, 3237). --define(wxStyledTextCtrl_Tab, 3238). --define(wxStyledTextCtrl_BackTab, 3239). --define(wxStyledTextCtrl_NewLine, 3240). --define(wxStyledTextCtrl_FormFeed, 3241). --define(wxStyledTextCtrl_VCHome, 3242). --define(wxStyledTextCtrl_VCHomeExtend, 3243). --define(wxStyledTextCtrl_ZoomIn, 3244). --define(wxStyledTextCtrl_ZoomOut, 3245). --define(wxStyledTextCtrl_DelWordLeft, 3246). --define(wxStyledTextCtrl_DelWordRight, 3247). --define(wxStyledTextCtrl_LineCut, 3248). --define(wxStyledTextCtrl_LineDelete, 3249). --define(wxStyledTextCtrl_LineTranspose, 3250). --define(wxStyledTextCtrl_LineDuplicate, 3251). --define(wxStyledTextCtrl_LowerCase, 3252). --define(wxStyledTextCtrl_UpperCase, 3253). --define(wxStyledTextCtrl_LineScrollDown, 3254). --define(wxStyledTextCtrl_LineScrollUp, 3255). --define(wxStyledTextCtrl_DeleteBackNotLine, 3256). --define(wxStyledTextCtrl_HomeDisplay, 3257). --define(wxStyledTextCtrl_HomeDisplayExtend, 3258). --define(wxStyledTextCtrl_LineEndDisplay, 3259). --define(wxStyledTextCtrl_LineEndDisplayExtend, 3260). --define(wxStyledTextCtrl_HomeWrapExtend, 3261). --define(wxStyledTextCtrl_LineEndWrap, 3262). --define(wxStyledTextCtrl_LineEndWrapExtend, 3263). --define(wxStyledTextCtrl_VCHomeWrap, 3264). --define(wxStyledTextCtrl_VCHomeWrapExtend, 3265). --define(wxStyledTextCtrl_LineCopy, 3266). --define(wxStyledTextCtrl_MoveCaretInsideView, 3267). --define(wxStyledTextCtrl_LineLength, 3268). --define(wxStyledTextCtrl_BraceHighlight, 3269). --define(wxStyledTextCtrl_BraceBadLight, 3270). --define(wxStyledTextCtrl_BraceMatch, 3271). --define(wxStyledTextCtrl_GetViewEOL, 3272). --define(wxStyledTextCtrl_SetViewEOL, 3273). --define(wxStyledTextCtrl_SetModEventMask, 3274). --define(wxStyledTextCtrl_GetEdgeColumn, 3275). --define(wxStyledTextCtrl_SetEdgeColumn, 3276). --define(wxStyledTextCtrl_SetEdgeMode, 3277). --define(wxStyledTextCtrl_GetEdgeMode, 3278). --define(wxStyledTextCtrl_GetEdgeColour, 3279). --define(wxStyledTextCtrl_SetEdgeColour, 3280). --define(wxStyledTextCtrl_SearchAnchor, 3281). --define(wxStyledTextCtrl_SearchNext, 3282). --define(wxStyledTextCtrl_SearchPrev, 3283). --define(wxStyledTextCtrl_LinesOnScreen, 3284). --define(wxStyledTextCtrl_UsePopUp, 3285). --define(wxStyledTextCtrl_SelectionIsRectangle, 3286). --define(wxStyledTextCtrl_SetZoom, 3287). --define(wxStyledTextCtrl_GetZoom, 3288). --define(wxStyledTextCtrl_GetModEventMask, 3289). --define(wxStyledTextCtrl_SetSTCFocus, 3290). --define(wxStyledTextCtrl_GetSTCFocus, 3291). --define(wxStyledTextCtrl_SetStatus, 3292). --define(wxStyledTextCtrl_GetStatus, 3293). --define(wxStyledTextCtrl_SetMouseDownCaptures, 3294). --define(wxStyledTextCtrl_GetMouseDownCaptures, 3295). --define(wxStyledTextCtrl_SetSTCCursor, 3296). --define(wxStyledTextCtrl_GetSTCCursor, 3297). --define(wxStyledTextCtrl_SetControlCharSymbol, 3298). --define(wxStyledTextCtrl_GetControlCharSymbol, 3299). --define(wxStyledTextCtrl_WordPartLeft, 3300). --define(wxStyledTextCtrl_WordPartLeftExtend, 3301). --define(wxStyledTextCtrl_WordPartRight, 3302). --define(wxStyledTextCtrl_WordPartRightExtend, 3303). --define(wxStyledTextCtrl_SetVisiblePolicy, 3304). --define(wxStyledTextCtrl_DelLineLeft, 3305). --define(wxStyledTextCtrl_DelLineRight, 3306). --define(wxStyledTextCtrl_GetXOffset, 3307). --define(wxStyledTextCtrl_ChooseCaretX, 3308). --define(wxStyledTextCtrl_SetXCaretPolicy, 3309). --define(wxStyledTextCtrl_SetYCaretPolicy, 3310). --define(wxStyledTextCtrl_GetPrintWrapMode, 3311). --define(wxStyledTextCtrl_SetHotspotActiveForeground, 3312). --define(wxStyledTextCtrl_SetHotspotActiveBackground, 3313). --define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3314). --define(wxStyledTextCtrl_SetHotspotSingleLine, 3315). --define(wxStyledTextCtrl_ParaDownExtend, 3316). --define(wxStyledTextCtrl_ParaUp, 3317). --define(wxStyledTextCtrl_ParaUpExtend, 3318). --define(wxStyledTextCtrl_PositionBefore, 3319). --define(wxStyledTextCtrl_PositionAfter, 3320). --define(wxStyledTextCtrl_CopyRange, 3321). --define(wxStyledTextCtrl_CopyText, 3322). --define(wxStyledTextCtrl_SetSelectionMode, 3323). --define(wxStyledTextCtrl_GetSelectionMode, 3324). --define(wxStyledTextCtrl_LineDownRectExtend, 3325). --define(wxStyledTextCtrl_LineUpRectExtend, 3326). --define(wxStyledTextCtrl_CharLeftRectExtend, 3327). --define(wxStyledTextCtrl_CharRightRectExtend, 3328). --define(wxStyledTextCtrl_HomeRectExtend, 3329). --define(wxStyledTextCtrl_VCHomeRectExtend, 3330). --define(wxStyledTextCtrl_LineEndRectExtend, 3331). --define(wxStyledTextCtrl_PageUpRectExtend, 3332). --define(wxStyledTextCtrl_PageDownRectExtend, 3333). --define(wxStyledTextCtrl_StutteredPageUp, 3334). --define(wxStyledTextCtrl_StutteredPageUpExtend, 3335). --define(wxStyledTextCtrl_StutteredPageDown, 3336). --define(wxStyledTextCtrl_StutteredPageDownExtend, 3337). --define(wxStyledTextCtrl_WordLeftEnd, 3338). --define(wxStyledTextCtrl_WordLeftEndExtend, 3339). --define(wxStyledTextCtrl_WordRightEnd, 3340). --define(wxStyledTextCtrl_WordRightEndExtend, 3341). --define(wxStyledTextCtrl_SetWhitespaceChars, 3342). --define(wxStyledTextCtrl_SetCharsDefault, 3343). --define(wxStyledTextCtrl_AutoCompGetCurrent, 3344). --define(wxStyledTextCtrl_Allocate, 3345). --define(wxStyledTextCtrl_FindColumn, 3346). --define(wxStyledTextCtrl_GetCaretSticky, 3347). --define(wxStyledTextCtrl_SetCaretSticky, 3348). --define(wxStyledTextCtrl_ToggleCaretSticky, 3349). --define(wxStyledTextCtrl_SetPasteConvertEndings, 3350). --define(wxStyledTextCtrl_GetPasteConvertEndings, 3351). --define(wxStyledTextCtrl_SelectionDuplicate, 3352). --define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3353). --define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3354). --define(wxStyledTextCtrl_StartRecord, 3355). --define(wxStyledTextCtrl_StopRecord, 3356). --define(wxStyledTextCtrl_SetLexer, 3357). --define(wxStyledTextCtrl_GetLexer, 3358). --define(wxStyledTextCtrl_Colourise, 3359). --define(wxStyledTextCtrl_SetProperty, 3360). --define(wxStyledTextCtrl_SetKeyWords, 3361). --define(wxStyledTextCtrl_SetLexerLanguage, 3362). --define(wxStyledTextCtrl_GetProperty, 3363). --define(wxStyledTextCtrl_GetStyleBitsNeeded, 3364). --define(wxStyledTextCtrl_GetCurrentLine, 3365). --define(wxStyledTextCtrl_StyleSetSpec, 3366). --define(wxStyledTextCtrl_StyleSetFont, 3367). --define(wxStyledTextCtrl_StyleSetFontAttr, 3368). --define(wxStyledTextCtrl_StyleSetCharacterSet, 3369). --define(wxStyledTextCtrl_StyleSetFontEncoding, 3370). --define(wxStyledTextCtrl_CmdKeyExecute, 3371). --define(wxStyledTextCtrl_SetMargins, 3372). --define(wxStyledTextCtrl_GetSelection, 3373). --define(wxStyledTextCtrl_PointFromPosition, 3374). --define(wxStyledTextCtrl_ScrollToLine, 3375). --define(wxStyledTextCtrl_ScrollToColumn, 3376). --define(wxStyledTextCtrl_SetVScrollBar, 3377). --define(wxStyledTextCtrl_SetHScrollBar, 3378). --define(wxStyledTextCtrl_GetLastKeydownProcessed, 3379). --define(wxStyledTextCtrl_SetLastKeydownProcessed, 3380). --define(wxStyledTextCtrl_SaveFile, 3381). --define(wxStyledTextCtrl_LoadFile, 3382). --define(wxStyledTextCtrl_DoDragOver, 3383). --define(wxStyledTextCtrl_DoDropText, 3384). --define(wxStyledTextCtrl_GetUseAntiAliasing, 3385). --define(wxStyledTextCtrl_AddTextRaw, 3386). --define(wxStyledTextCtrl_InsertTextRaw, 3387). --define(wxStyledTextCtrl_GetCurLineRaw, 3388). --define(wxStyledTextCtrl_GetLineRaw, 3389). --define(wxStyledTextCtrl_GetSelectedTextRaw, 3390). --define(wxStyledTextCtrl_GetTextRangeRaw, 3391). --define(wxStyledTextCtrl_SetTextRaw, 3392). --define(wxStyledTextCtrl_GetTextRaw, 3393). --define(wxStyledTextCtrl_AppendTextRaw, 3394). --define(wxArtProvider_GetBitmap, 3395). --define(wxArtProvider_GetIcon, 3396). --define(wxTreeEvent_GetKeyCode, 3397). --define(wxTreeEvent_GetItem, 3398). --define(wxTreeEvent_GetKeyEvent, 3399). --define(wxTreeEvent_GetLabel, 3400). --define(wxTreeEvent_GetOldItem, 3401). --define(wxTreeEvent_GetPoint, 3402). --define(wxTreeEvent_IsEditCancelled, 3403). --define(wxTreeEvent_SetToolTip, 3404). --define(wxNotebookEvent_GetOldSelection, 3405). --define(wxNotebookEvent_GetSelection, 3406). --define(wxNotebookEvent_SetOldSelection, 3407). --define(wxNotebookEvent_SetSelection, 3408). --define(wxFileDataObject_new, 3409). --define(wxFileDataObject_AddFile, 3410). --define(wxFileDataObject_GetFilenames, 3411). --define(wxFileDataObject_destroy, 3412). --define(wxTextDataObject_new, 3413). --define(wxTextDataObject_GetTextLength, 3414). --define(wxTextDataObject_GetText, 3415). --define(wxTextDataObject_SetText, 3416). --define(wxTextDataObject_destroy, 3417). --define(wxBitmapDataObject_new_1_1, 3418). --define(wxBitmapDataObject_new_1_0, 3419). --define(wxBitmapDataObject_GetBitmap, 3420). --define(wxBitmapDataObject_SetBitmap, 3421). --define(wxBitmapDataObject_destroy, 3422). --define(wxClipboard_new, 3424). --define(wxClipboard_destruct, 3425). --define(wxClipboard_AddData, 3426). --define(wxClipboard_Clear, 3427). --define(wxClipboard_Close, 3428). --define(wxClipboard_Flush, 3429). --define(wxClipboard_GetData, 3430). --define(wxClipboard_IsOpened, 3431). --define(wxClipboard_Open, 3432). --define(wxClipboard_SetData, 3433). --define(wxClipboard_UsePrimarySelection, 3435). --define(wxClipboard_IsSupported, 3436). --define(wxClipboard_Get, 3437). --define(wxSpinEvent_GetPosition, 3438). --define(wxSpinEvent_SetPosition, 3439). --define(wxSplitterWindow_new_0, 3440). --define(wxSplitterWindow_new_2, 3441). --define(wxSplitterWindow_destruct, 3442). --define(wxSplitterWindow_Create, 3443). --define(wxSplitterWindow_GetMinimumPaneSize, 3444). --define(wxSplitterWindow_GetSashGravity, 3445). --define(wxSplitterWindow_GetSashPosition, 3446). --define(wxSplitterWindow_GetSplitMode, 3447). --define(wxSplitterWindow_GetWindow1, 3448). --define(wxSplitterWindow_GetWindow2, 3449). --define(wxSplitterWindow_Initialize, 3450). --define(wxSplitterWindow_IsSplit, 3451). --define(wxSplitterWindow_ReplaceWindow, 3452). --define(wxSplitterWindow_SetSashGravity, 3453). --define(wxSplitterWindow_SetSashPosition, 3454). --define(wxSplitterWindow_SetSashSize, 3455). --define(wxSplitterWindow_SetMinimumPaneSize, 3456). --define(wxSplitterWindow_SetSplitMode, 3457). --define(wxSplitterWindow_SplitHorizontally, 3458). --define(wxSplitterWindow_SplitVertically, 3459). --define(wxSplitterWindow_Unsplit, 3460). --define(wxSplitterWindow_UpdateSize, 3461). --define(wxSplitterEvent_GetSashPosition, 3462). --define(wxSplitterEvent_GetX, 3463). --define(wxSplitterEvent_GetY, 3464). --define(wxSplitterEvent_GetWindowBeingRemoved, 3465). --define(wxSplitterEvent_SetSashPosition, 3466). --define(wxHtmlWindow_new_0, 3467). --define(wxHtmlWindow_new_2, 3468). --define(wxHtmlWindow_AppendToPage, 3469). --define(wxHtmlWindow_GetOpenedAnchor, 3470). --define(wxHtmlWindow_GetOpenedPage, 3471). --define(wxHtmlWindow_GetOpenedPageTitle, 3472). --define(wxHtmlWindow_GetRelatedFrame, 3473). --define(wxHtmlWindow_HistoryBack, 3474). --define(wxHtmlWindow_HistoryCanBack, 3475). --define(wxHtmlWindow_HistoryCanForward, 3476). --define(wxHtmlWindow_HistoryClear, 3477). --define(wxHtmlWindow_HistoryForward, 3478). --define(wxHtmlWindow_LoadFile, 3479). --define(wxHtmlWindow_LoadPage, 3480). --define(wxHtmlWindow_SelectAll, 3481). --define(wxHtmlWindow_SelectionToText, 3482). --define(wxHtmlWindow_SelectLine, 3483). --define(wxHtmlWindow_SelectWord, 3484). --define(wxHtmlWindow_SetBorders, 3485). --define(wxHtmlWindow_SetFonts, 3486). --define(wxHtmlWindow_SetPage, 3487). --define(wxHtmlWindow_SetRelatedFrame, 3488). --define(wxHtmlWindow_SetRelatedStatusBar, 3489). --define(wxHtmlWindow_ToText, 3490). --define(wxHtmlWindow_destroy, 3491). --define(wxHtmlLinkEvent_GetLinkInfo, 3492). --define(wxSystemSettings_GetColour, 3493). --define(wxSystemSettings_GetFont, 3494). --define(wxSystemSettings_GetMetric, 3495). --define(wxSystemSettings_GetScreenType, 3496). --define(wxSystemOptions_GetOption, 3497). --define(wxSystemOptions_GetOptionInt, 3498). --define(wxSystemOptions_HasOption, 3499). --define(wxSystemOptions_IsFalse, 3500). --define(wxSystemOptions_SetOption_2_1, 3501). --define(wxSystemOptions_SetOption_2_0, 3502). --define(wxAuiNotebookEvent_SetSelection, 3503). --define(wxAuiNotebookEvent_GetSelection, 3504). --define(wxAuiNotebookEvent_SetOldSelection, 3505). --define(wxAuiNotebookEvent_GetOldSelection, 3506). --define(wxAuiNotebookEvent_SetDragSource, 3507). --define(wxAuiNotebookEvent_GetDragSource, 3508). --define(wxAuiManagerEvent_SetManager, 3509). --define(wxAuiManagerEvent_GetManager, 3510). --define(wxAuiManagerEvent_SetPane, 3511). --define(wxAuiManagerEvent_GetPane, 3512). --define(wxAuiManagerEvent_SetButton, 3513). --define(wxAuiManagerEvent_GetButton, 3514). --define(wxAuiManagerEvent_SetDC, 3515). --define(wxAuiManagerEvent_GetDC, 3516). --define(wxAuiManagerEvent_Veto, 3517). --define(wxAuiManagerEvent_GetVeto, 3518). --define(wxAuiManagerEvent_SetCanVeto, 3519). --define(wxAuiManagerEvent_CanVeto, 3520). --define(wxLogNull_new, 3521). --define(wxLogNull_destroy, 3522). --define(wxTaskBarIcon_new, 3523). --define(wxTaskBarIcon_destruct, 3524). --define(wxTaskBarIcon_PopupMenu, 3525). --define(wxTaskBarIcon_RemoveIcon, 3526). --define(wxTaskBarIcon_SetIcon, 3527). --define(wxLocale_new_0, 3528). --define(wxLocale_new_2, 3530). --define(wxLocale_destruct, 3531). --define(wxLocale_Init, 3533). --define(wxLocale_AddCatalog_1, 3534). --define(wxLocale_AddCatalog_3, 3535). --define(wxLocale_AddCatalogLookupPathPrefix, 3536). --define(wxLocale_GetCanonicalName, 3537). --define(wxLocale_GetLanguage, 3538). --define(wxLocale_GetLanguageName, 3539). --define(wxLocale_GetLocale, 3540). --define(wxLocale_GetName, 3541). --define(wxLocale_GetString_2, 3542). --define(wxLocale_GetString_4, 3543). --define(wxLocale_GetHeaderValue, 3544). --define(wxLocale_GetSysName, 3545). --define(wxLocale_GetSystemEncoding, 3546). --define(wxLocale_GetSystemEncodingName, 3547). --define(wxLocale_GetSystemLanguage, 3548). --define(wxLocale_IsLoaded, 3549). --define(wxLocale_IsOk, 3550). --define(wxActivateEvent_GetActive, 3551). --define(wxPopupWindow_new_2, 3553). --define(wxPopupWindow_new_0, 3554). --define(wxPopupWindow_destruct, 3556). --define(wxPopupWindow_Create, 3557). --define(wxPopupWindow_Position, 3558). --define(wxPopupTransientWindow_new_0, 3559). --define(wxPopupTransientWindow_new_2, 3560). --define(wxPopupTransientWindow_destruct, 3561). --define(wxPopupTransientWindow_Popup, 3562). --define(wxPopupTransientWindow_Dismiss, 3563). +-define(wxAuiPaneInfo_GetWindow, 2653). +-define(wxAuiPaneInfo_GetFrame, 2654). +-define(wxAuiPaneInfo_GetDirection, 2655). +-define(wxAuiPaneInfo_GetLayer, 2656). +-define(wxAuiPaneInfo_GetRow, 2657). +-define(wxAuiPaneInfo_GetPosition, 2658). +-define(wxAuiPaneInfo_GetFloatingPosition, 2659). +-define(wxAuiPaneInfo_GetFloatingSize, 2660). +-define(wxAuiNotebook_new_0, 2661). +-define(wxAuiNotebook_new_2, 2662). +-define(wxAuiNotebook_AddPage, 2663). +-define(wxAuiNotebook_Create, 2664). +-define(wxAuiNotebook_DeletePage, 2665). +-define(wxAuiNotebook_GetArtProvider, 2666). +-define(wxAuiNotebook_GetPage, 2667). +-define(wxAuiNotebook_GetPageBitmap, 2668). +-define(wxAuiNotebook_GetPageCount, 2669). +-define(wxAuiNotebook_GetPageIndex, 2670). +-define(wxAuiNotebook_GetPageText, 2671). +-define(wxAuiNotebook_GetSelection, 2672). +-define(wxAuiNotebook_InsertPage, 2673). +-define(wxAuiNotebook_RemovePage, 2674). +-define(wxAuiNotebook_SetArtProvider, 2675). +-define(wxAuiNotebook_SetFont, 2676). +-define(wxAuiNotebook_SetPageBitmap, 2677). +-define(wxAuiNotebook_SetPageText, 2678). +-define(wxAuiNotebook_SetSelection, 2679). +-define(wxAuiNotebook_SetTabCtrlHeight, 2680). +-define(wxAuiNotebook_SetUniformBitmapSize, 2681). +-define(wxAuiNotebook_destroy, 2682). +-define(wxAuiTabArt_SetFlags, 2683). +-define(wxAuiTabArt_SetMeasuringFont, 2684). +-define(wxAuiTabArt_SetNormalFont, 2685). +-define(wxAuiTabArt_SetSelectedFont, 2686). +-define(wxAuiTabArt_SetColour, 2687). +-define(wxAuiTabArt_SetActiveColour, 2688). +-define(wxAuiDockArt_GetColour, 2689). +-define(wxAuiDockArt_GetFont, 2690). +-define(wxAuiDockArt_GetMetric, 2691). +-define(wxAuiDockArt_SetColour, 2692). +-define(wxAuiDockArt_SetFont, 2693). +-define(wxAuiDockArt_SetMetric, 2694). +-define(wxAuiSimpleTabArt_new, 2695). +-define(wxAuiSimpleTabArt_destroy, 2696). +-define(wxMDIParentFrame_new_0, 2697). +-define(wxMDIParentFrame_new_4, 2698). +-define(wxMDIParentFrame_destruct, 2699). +-define(wxMDIParentFrame_ActivateNext, 2700). +-define(wxMDIParentFrame_ActivatePrevious, 2701). +-define(wxMDIParentFrame_ArrangeIcons, 2702). +-define(wxMDIParentFrame_Cascade, 2703). +-define(wxMDIParentFrame_Create, 2704). +-define(wxMDIParentFrame_GetActiveChild, 2705). +-define(wxMDIParentFrame_GetClientWindow, 2706). +-define(wxMDIParentFrame_Tile, 2707). +-define(wxMDIChildFrame_new_0, 2708). +-define(wxMDIChildFrame_new_4, 2709). +-define(wxMDIChildFrame_destruct, 2710). +-define(wxMDIChildFrame_Activate, 2711). +-define(wxMDIChildFrame_Create, 2712). +-define(wxMDIChildFrame_Maximize, 2713). +-define(wxMDIChildFrame_Restore, 2714). +-define(wxMDIClientWindow_new_0, 2715). +-define(wxMDIClientWindow_new_2, 2716). +-define(wxMDIClientWindow_destruct, 2717). +-define(wxMDIClientWindow_CreateClient, 2718). +-define(wxLayoutAlgorithm_new, 2719). +-define(wxLayoutAlgorithm_LayoutFrame, 2720). +-define(wxLayoutAlgorithm_LayoutMDIFrame, 2721). +-define(wxLayoutAlgorithm_LayoutWindow, 2722). +-define(wxLayoutAlgorithm_destroy, 2723). +-define(wxEvent_GetId, 2724). +-define(wxEvent_GetSkipped, 2725). +-define(wxEvent_GetTimestamp, 2726). +-define(wxEvent_IsCommandEvent, 2727). +-define(wxEvent_ResumePropagation, 2728). +-define(wxEvent_ShouldPropagate, 2729). +-define(wxEvent_Skip, 2730). +-define(wxEvent_StopPropagation, 2731). +-define(wxCommandEvent_getClientData, 2732). +-define(wxCommandEvent_GetExtraLong, 2733). +-define(wxCommandEvent_GetInt, 2734). +-define(wxCommandEvent_GetSelection, 2735). +-define(wxCommandEvent_GetString, 2736). +-define(wxCommandEvent_IsChecked, 2737). +-define(wxCommandEvent_IsSelection, 2738). +-define(wxCommandEvent_SetInt, 2739). +-define(wxCommandEvent_SetString, 2740). +-define(wxScrollEvent_GetOrientation, 2741). +-define(wxScrollEvent_GetPosition, 2742). +-define(wxScrollWinEvent_GetOrientation, 2743). +-define(wxScrollWinEvent_GetPosition, 2744). +-define(wxMouseEvent_AltDown, 2745). +-define(wxMouseEvent_Button, 2746). +-define(wxMouseEvent_ButtonDClick, 2747). +-define(wxMouseEvent_ButtonDown, 2748). +-define(wxMouseEvent_ButtonUp, 2749). +-define(wxMouseEvent_CmdDown, 2750). +-define(wxMouseEvent_ControlDown, 2751). +-define(wxMouseEvent_Dragging, 2752). +-define(wxMouseEvent_Entering, 2753). +-define(wxMouseEvent_GetButton, 2754). +-define(wxMouseEvent_GetPosition, 2757). +-define(wxMouseEvent_GetLogicalPosition, 2758). +-define(wxMouseEvent_GetLinesPerAction, 2759). +-define(wxMouseEvent_GetWheelRotation, 2760). +-define(wxMouseEvent_GetWheelDelta, 2761). +-define(wxMouseEvent_GetX, 2762). +-define(wxMouseEvent_GetY, 2763). +-define(wxMouseEvent_IsButton, 2764). +-define(wxMouseEvent_IsPageScroll, 2765). +-define(wxMouseEvent_Leaving, 2766). +-define(wxMouseEvent_LeftDClick, 2767). +-define(wxMouseEvent_LeftDown, 2768). +-define(wxMouseEvent_LeftIsDown, 2769). +-define(wxMouseEvent_LeftUp, 2770). +-define(wxMouseEvent_MetaDown, 2771). +-define(wxMouseEvent_MiddleDClick, 2772). +-define(wxMouseEvent_MiddleDown, 2773). +-define(wxMouseEvent_MiddleIsDown, 2774). +-define(wxMouseEvent_MiddleUp, 2775). +-define(wxMouseEvent_Moving, 2776). +-define(wxMouseEvent_RightDClick, 2777). +-define(wxMouseEvent_RightDown, 2778). +-define(wxMouseEvent_RightIsDown, 2779). +-define(wxMouseEvent_RightUp, 2780). +-define(wxMouseEvent_ShiftDown, 2781). +-define(wxSetCursorEvent_GetCursor, 2782). +-define(wxSetCursorEvent_GetX, 2783). +-define(wxSetCursorEvent_GetY, 2784). +-define(wxSetCursorEvent_HasCursor, 2785). +-define(wxSetCursorEvent_SetCursor, 2786). +-define(wxKeyEvent_AltDown, 2787). +-define(wxKeyEvent_CmdDown, 2788). +-define(wxKeyEvent_ControlDown, 2789). +-define(wxKeyEvent_GetKeyCode, 2790). +-define(wxKeyEvent_GetModifiers, 2791). +-define(wxKeyEvent_GetPosition, 2794). +-define(wxKeyEvent_GetRawKeyCode, 2795). +-define(wxKeyEvent_GetRawKeyFlags, 2796). +-define(wxKeyEvent_GetUnicodeKey, 2797). +-define(wxKeyEvent_GetX, 2798). +-define(wxKeyEvent_GetY, 2799). +-define(wxKeyEvent_HasModifiers, 2800). +-define(wxKeyEvent_MetaDown, 2801). +-define(wxKeyEvent_ShiftDown, 2802). +-define(wxSizeEvent_GetSize, 2803). +-define(wxMoveEvent_GetPosition, 2804). +-define(wxEraseEvent_GetDC, 2805). +-define(wxFocusEvent_GetWindow, 2806). +-define(wxChildFocusEvent_GetWindow, 2807). +-define(wxMenuEvent_GetMenu, 2808). +-define(wxMenuEvent_GetMenuId, 2809). +-define(wxMenuEvent_IsPopup, 2810). +-define(wxCloseEvent_CanVeto, 2811). +-define(wxCloseEvent_GetLoggingOff, 2812). +-define(wxCloseEvent_SetCanVeto, 2813). +-define(wxCloseEvent_SetLoggingOff, 2814). +-define(wxCloseEvent_Veto, 2815). +-define(wxShowEvent_SetShow, 2816). +-define(wxShowEvent_GetShow, 2817). +-define(wxIconizeEvent_Iconized, 2818). +-define(wxJoystickEvent_ButtonDown, 2819). +-define(wxJoystickEvent_ButtonIsDown, 2820). +-define(wxJoystickEvent_ButtonUp, 2821). +-define(wxJoystickEvent_GetButtonChange, 2822). +-define(wxJoystickEvent_GetButtonState, 2823). +-define(wxJoystickEvent_GetJoystick, 2824). +-define(wxJoystickEvent_GetPosition, 2825). +-define(wxJoystickEvent_GetZPosition, 2826). +-define(wxJoystickEvent_IsButton, 2827). +-define(wxJoystickEvent_IsMove, 2828). +-define(wxJoystickEvent_IsZMove, 2829). +-define(wxUpdateUIEvent_CanUpdate, 2830). +-define(wxUpdateUIEvent_Check, 2831). +-define(wxUpdateUIEvent_Enable, 2832). +-define(wxUpdateUIEvent_Show, 2833). +-define(wxUpdateUIEvent_GetChecked, 2834). +-define(wxUpdateUIEvent_GetEnabled, 2835). +-define(wxUpdateUIEvent_GetShown, 2836). +-define(wxUpdateUIEvent_GetSetChecked, 2837). +-define(wxUpdateUIEvent_GetSetEnabled, 2838). +-define(wxUpdateUIEvent_GetSetShown, 2839). +-define(wxUpdateUIEvent_GetSetText, 2840). +-define(wxUpdateUIEvent_GetText, 2841). +-define(wxUpdateUIEvent_GetMode, 2842). +-define(wxUpdateUIEvent_GetUpdateInterval, 2843). +-define(wxUpdateUIEvent_ResetUpdateTime, 2844). +-define(wxUpdateUIEvent_SetMode, 2845). +-define(wxUpdateUIEvent_SetText, 2846). +-define(wxUpdateUIEvent_SetUpdateInterval, 2847). +-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2848). +-define(wxPaletteChangedEvent_SetChangedWindow, 2849). +-define(wxPaletteChangedEvent_GetChangedWindow, 2850). +-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2851). +-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2852). +-define(wxNavigationKeyEvent_GetDirection, 2853). +-define(wxNavigationKeyEvent_SetDirection, 2854). +-define(wxNavigationKeyEvent_IsWindowChange, 2855). +-define(wxNavigationKeyEvent_SetWindowChange, 2856). +-define(wxNavigationKeyEvent_IsFromTab, 2857). +-define(wxNavigationKeyEvent_SetFromTab, 2858). +-define(wxNavigationKeyEvent_GetCurrentFocus, 2859). +-define(wxNavigationKeyEvent_SetCurrentFocus, 2860). +-define(wxHelpEvent_GetOrigin, 2861). +-define(wxHelpEvent_GetPosition, 2862). +-define(wxHelpEvent_SetOrigin, 2863). +-define(wxHelpEvent_SetPosition, 2864). +-define(wxContextMenuEvent_GetPosition, 2865). +-define(wxContextMenuEvent_SetPosition, 2866). +-define(wxIdleEvent_CanSend, 2867). +-define(wxIdleEvent_GetMode, 2868). +-define(wxIdleEvent_RequestMore, 2869). +-define(wxIdleEvent_MoreRequested, 2870). +-define(wxIdleEvent_SetMode, 2871). +-define(wxGridEvent_AltDown, 2872). +-define(wxGridEvent_ControlDown, 2873). +-define(wxGridEvent_GetCol, 2874). +-define(wxGridEvent_GetPosition, 2875). +-define(wxGridEvent_GetRow, 2876). +-define(wxGridEvent_MetaDown, 2877). +-define(wxGridEvent_Selecting, 2878). +-define(wxGridEvent_ShiftDown, 2879). +-define(wxNotifyEvent_Allow, 2880). +-define(wxNotifyEvent_IsAllowed, 2881). +-define(wxNotifyEvent_Veto, 2882). +-define(wxSashEvent_GetEdge, 2883). +-define(wxSashEvent_GetDragRect, 2884). +-define(wxSashEvent_GetDragStatus, 2885). +-define(wxListEvent_GetCacheFrom, 2886). +-define(wxListEvent_GetCacheTo, 2887). +-define(wxListEvent_GetKeyCode, 2888). +-define(wxListEvent_GetIndex, 2889). +-define(wxListEvent_GetColumn, 2890). +-define(wxListEvent_GetPoint, 2891). +-define(wxListEvent_GetLabel, 2892). +-define(wxListEvent_GetText, 2893). +-define(wxListEvent_GetImage, 2894). +-define(wxListEvent_GetData, 2895). +-define(wxListEvent_GetMask, 2896). +-define(wxListEvent_GetItem, 2897). +-define(wxListEvent_IsEditCancelled, 2898). +-define(wxDateEvent_GetDate, 2899). +-define(wxCalendarEvent_GetWeekDay, 2900). +-define(wxFileDirPickerEvent_GetPath, 2901). +-define(wxColourPickerEvent_GetColour, 2902). +-define(wxFontPickerEvent_GetFont, 2903). +-define(wxStyledTextEvent_GetPosition, 2904). +-define(wxStyledTextEvent_GetKey, 2905). +-define(wxStyledTextEvent_GetModifiers, 2906). +-define(wxStyledTextEvent_GetModificationType, 2907). +-define(wxStyledTextEvent_GetText, 2908). +-define(wxStyledTextEvent_GetLength, 2909). +-define(wxStyledTextEvent_GetLinesAdded, 2910). +-define(wxStyledTextEvent_GetLine, 2911). +-define(wxStyledTextEvent_GetFoldLevelNow, 2912). +-define(wxStyledTextEvent_GetFoldLevelPrev, 2913). +-define(wxStyledTextEvent_GetMargin, 2914). +-define(wxStyledTextEvent_GetMessage, 2915). +-define(wxStyledTextEvent_GetWParam, 2916). +-define(wxStyledTextEvent_GetLParam, 2917). +-define(wxStyledTextEvent_GetListType, 2918). +-define(wxStyledTextEvent_GetX, 2919). +-define(wxStyledTextEvent_GetY, 2920). +-define(wxStyledTextEvent_GetDragText, 2921). +-define(wxStyledTextEvent_GetDragAllowMove, 2922). +-define(wxStyledTextEvent_GetDragResult, 2923). +-define(wxStyledTextEvent_GetShift, 2924). +-define(wxStyledTextEvent_GetControl, 2925). +-define(wxStyledTextEvent_GetAlt, 2926). +-define(utils_wxGetKeyState, 2927). +-define(utils_wxGetMousePosition, 2928). +-define(utils_wxGetMouseState, 2929). +-define(utils_wxSetDetectableAutoRepeat, 2930). +-define(utils_wxBell, 2931). +-define(utils_wxFindMenuItemId, 2932). +-define(utils_wxGenericFindWindowAtPoint, 2933). +-define(utils_wxFindWindowAtPoint, 2934). +-define(utils_wxBeginBusyCursor, 2935). +-define(utils_wxEndBusyCursor, 2936). +-define(utils_wxIsBusy, 2937). +-define(utils_wxShutdown, 2938). +-define(utils_wxShell, 2939). +-define(utils_wxLaunchDefaultBrowser, 2940). +-define(utils_wxGetEmailAddress, 2941). +-define(utils_wxGetUserId, 2942). +-define(utils_wxGetHomeDir, 2943). +-define(utils_wxNewId, 2944). +-define(utils_wxRegisterId, 2945). +-define(utils_wxGetCurrentId, 2946). +-define(utils_wxGetOsDescription, 2947). +-define(utils_wxIsPlatformLittleEndian, 2948). +-define(utils_wxIsPlatform64Bit, 2949). +-define(gdicmn_wxDisplaySize, 2950). +-define(gdicmn_wxSetCursor, 2951). +-define(wxPrintout_new, 2952). +-define(wxPrintout_destruct, 2953). +-define(wxPrintout_GetDC, 2954). +-define(wxPrintout_GetPageSizeMM, 2955). +-define(wxPrintout_GetPageSizePixels, 2956). +-define(wxPrintout_GetPaperRectPixels, 2957). +-define(wxPrintout_GetPPIPrinter, 2958). +-define(wxPrintout_GetPPIScreen, 2959). +-define(wxPrintout_GetTitle, 2960). +-define(wxPrintout_IsPreview, 2961). +-define(wxPrintout_FitThisSizeToPaper, 2962). +-define(wxPrintout_FitThisSizeToPage, 2963). +-define(wxPrintout_FitThisSizeToPageMargins, 2964). +-define(wxPrintout_MapScreenSizeToPaper, 2965). +-define(wxPrintout_MapScreenSizeToPage, 2966). +-define(wxPrintout_MapScreenSizeToPageMargins, 2967). +-define(wxPrintout_MapScreenSizeToDevice, 2968). +-define(wxPrintout_GetLogicalPaperRect, 2969). +-define(wxPrintout_GetLogicalPageRect, 2970). +-define(wxPrintout_GetLogicalPageMarginsRect, 2971). +-define(wxPrintout_SetLogicalOrigin, 2972). +-define(wxPrintout_OffsetLogicalOrigin, 2973). +-define(wxStyledTextCtrl_new_2, 2974). +-define(wxStyledTextCtrl_new_0, 2975). +-define(wxStyledTextCtrl_destruct, 2976). +-define(wxStyledTextCtrl_Create, 2977). +-define(wxStyledTextCtrl_AddText, 2978). +-define(wxStyledTextCtrl_AddStyledText, 2979). +-define(wxStyledTextCtrl_InsertText, 2980). +-define(wxStyledTextCtrl_ClearAll, 2981). +-define(wxStyledTextCtrl_ClearDocumentStyle, 2982). +-define(wxStyledTextCtrl_GetLength, 2983). +-define(wxStyledTextCtrl_GetCharAt, 2984). +-define(wxStyledTextCtrl_GetCurrentPos, 2985). +-define(wxStyledTextCtrl_GetAnchor, 2986). +-define(wxStyledTextCtrl_GetStyleAt, 2987). +-define(wxStyledTextCtrl_Redo, 2988). +-define(wxStyledTextCtrl_SetUndoCollection, 2989). +-define(wxStyledTextCtrl_SelectAll, 2990). +-define(wxStyledTextCtrl_SetSavePoint, 2991). +-define(wxStyledTextCtrl_GetStyledText, 2992). +-define(wxStyledTextCtrl_CanRedo, 2993). +-define(wxStyledTextCtrl_MarkerLineFromHandle, 2994). +-define(wxStyledTextCtrl_MarkerDeleteHandle, 2995). +-define(wxStyledTextCtrl_GetUndoCollection, 2996). +-define(wxStyledTextCtrl_GetViewWhiteSpace, 2997). +-define(wxStyledTextCtrl_SetViewWhiteSpace, 2998). +-define(wxStyledTextCtrl_PositionFromPoint, 2999). +-define(wxStyledTextCtrl_PositionFromPointClose, 3000). +-define(wxStyledTextCtrl_GotoLine, 3001). +-define(wxStyledTextCtrl_GotoPos, 3002). +-define(wxStyledTextCtrl_SetAnchor, 3003). +-define(wxStyledTextCtrl_GetCurLine, 3004). +-define(wxStyledTextCtrl_GetEndStyled, 3005). +-define(wxStyledTextCtrl_ConvertEOLs, 3006). +-define(wxStyledTextCtrl_GetEOLMode, 3007). +-define(wxStyledTextCtrl_SetEOLMode, 3008). +-define(wxStyledTextCtrl_StartStyling, 3009). +-define(wxStyledTextCtrl_SetStyling, 3010). +-define(wxStyledTextCtrl_GetBufferedDraw, 3011). +-define(wxStyledTextCtrl_SetBufferedDraw, 3012). +-define(wxStyledTextCtrl_SetTabWidth, 3013). +-define(wxStyledTextCtrl_GetTabWidth, 3014). +-define(wxStyledTextCtrl_SetCodePage, 3015). +-define(wxStyledTextCtrl_MarkerDefine, 3016). +-define(wxStyledTextCtrl_MarkerSetForeground, 3017). +-define(wxStyledTextCtrl_MarkerSetBackground, 3018). +-define(wxStyledTextCtrl_MarkerAdd, 3019). +-define(wxStyledTextCtrl_MarkerDelete, 3020). +-define(wxStyledTextCtrl_MarkerDeleteAll, 3021). +-define(wxStyledTextCtrl_MarkerGet, 3022). +-define(wxStyledTextCtrl_MarkerNext, 3023). +-define(wxStyledTextCtrl_MarkerPrevious, 3024). +-define(wxStyledTextCtrl_MarkerDefineBitmap, 3025). +-define(wxStyledTextCtrl_MarkerAddSet, 3026). +-define(wxStyledTextCtrl_MarkerSetAlpha, 3027). +-define(wxStyledTextCtrl_SetMarginType, 3028). +-define(wxStyledTextCtrl_GetMarginType, 3029). +-define(wxStyledTextCtrl_SetMarginWidth, 3030). +-define(wxStyledTextCtrl_GetMarginWidth, 3031). +-define(wxStyledTextCtrl_SetMarginMask, 3032). +-define(wxStyledTextCtrl_GetMarginMask, 3033). +-define(wxStyledTextCtrl_SetMarginSensitive, 3034). +-define(wxStyledTextCtrl_GetMarginSensitive, 3035). +-define(wxStyledTextCtrl_StyleClearAll, 3036). +-define(wxStyledTextCtrl_StyleSetForeground, 3037). +-define(wxStyledTextCtrl_StyleSetBackground, 3038). +-define(wxStyledTextCtrl_StyleSetBold, 3039). +-define(wxStyledTextCtrl_StyleSetItalic, 3040). +-define(wxStyledTextCtrl_StyleSetSize, 3041). +-define(wxStyledTextCtrl_StyleSetFaceName, 3042). +-define(wxStyledTextCtrl_StyleSetEOLFilled, 3043). +-define(wxStyledTextCtrl_StyleResetDefault, 3044). +-define(wxStyledTextCtrl_StyleSetUnderline, 3045). +-define(wxStyledTextCtrl_StyleSetCase, 3046). +-define(wxStyledTextCtrl_StyleSetHotSpot, 3047). +-define(wxStyledTextCtrl_SetSelForeground, 3048). +-define(wxStyledTextCtrl_SetSelBackground, 3049). +-define(wxStyledTextCtrl_GetSelAlpha, 3050). +-define(wxStyledTextCtrl_SetSelAlpha, 3051). +-define(wxStyledTextCtrl_SetCaretForeground, 3052). +-define(wxStyledTextCtrl_CmdKeyAssign, 3053). +-define(wxStyledTextCtrl_CmdKeyClear, 3054). +-define(wxStyledTextCtrl_CmdKeyClearAll, 3055). +-define(wxStyledTextCtrl_SetStyleBytes, 3056). +-define(wxStyledTextCtrl_StyleSetVisible, 3057). +-define(wxStyledTextCtrl_GetCaretPeriod, 3058). +-define(wxStyledTextCtrl_SetCaretPeriod, 3059). +-define(wxStyledTextCtrl_SetWordChars, 3060). +-define(wxStyledTextCtrl_BeginUndoAction, 3061). +-define(wxStyledTextCtrl_EndUndoAction, 3062). +-define(wxStyledTextCtrl_IndicatorSetStyle, 3063). +-define(wxStyledTextCtrl_IndicatorGetStyle, 3064). +-define(wxStyledTextCtrl_IndicatorSetForeground, 3065). +-define(wxStyledTextCtrl_IndicatorGetForeground, 3066). +-define(wxStyledTextCtrl_SetWhitespaceForeground, 3067). +-define(wxStyledTextCtrl_SetWhitespaceBackground, 3068). +-define(wxStyledTextCtrl_GetStyleBits, 3069). +-define(wxStyledTextCtrl_SetLineState, 3070). +-define(wxStyledTextCtrl_GetLineState, 3071). +-define(wxStyledTextCtrl_GetMaxLineState, 3072). +-define(wxStyledTextCtrl_GetCaretLineVisible, 3073). +-define(wxStyledTextCtrl_SetCaretLineVisible, 3074). +-define(wxStyledTextCtrl_GetCaretLineBackground, 3075). +-define(wxStyledTextCtrl_SetCaretLineBackground, 3076). +-define(wxStyledTextCtrl_AutoCompShow, 3077). +-define(wxStyledTextCtrl_AutoCompCancel, 3078). +-define(wxStyledTextCtrl_AutoCompActive, 3079). +-define(wxStyledTextCtrl_AutoCompPosStart, 3080). +-define(wxStyledTextCtrl_AutoCompComplete, 3081). +-define(wxStyledTextCtrl_AutoCompStops, 3082). +-define(wxStyledTextCtrl_AutoCompSetSeparator, 3083). +-define(wxStyledTextCtrl_AutoCompGetSeparator, 3084). +-define(wxStyledTextCtrl_AutoCompSelect, 3085). +-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3086). +-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3087). +-define(wxStyledTextCtrl_AutoCompSetFillUps, 3088). +-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3089). +-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3090). +-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3091). +-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3092). +-define(wxStyledTextCtrl_UserListShow, 3093). +-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3094). +-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3095). +-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3096). +-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3097). +-define(wxStyledTextCtrl_RegisterImage, 3098). +-define(wxStyledTextCtrl_ClearRegisteredImages, 3099). +-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3100). +-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3101). +-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3102). +-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3103). +-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3104). +-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3105). +-define(wxStyledTextCtrl_SetIndent, 3106). +-define(wxStyledTextCtrl_GetIndent, 3107). +-define(wxStyledTextCtrl_SetUseTabs, 3108). +-define(wxStyledTextCtrl_GetUseTabs, 3109). +-define(wxStyledTextCtrl_SetLineIndentation, 3110). +-define(wxStyledTextCtrl_GetLineIndentation, 3111). +-define(wxStyledTextCtrl_GetLineIndentPosition, 3112). +-define(wxStyledTextCtrl_GetColumn, 3113). +-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3114). +-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3115). +-define(wxStyledTextCtrl_SetIndentationGuides, 3116). +-define(wxStyledTextCtrl_GetIndentationGuides, 3117). +-define(wxStyledTextCtrl_SetHighlightGuide, 3118). +-define(wxStyledTextCtrl_GetHighlightGuide, 3119). +-define(wxStyledTextCtrl_GetLineEndPosition, 3120). +-define(wxStyledTextCtrl_GetCodePage, 3121). +-define(wxStyledTextCtrl_GetCaretForeground, 3122). +-define(wxStyledTextCtrl_GetReadOnly, 3123). +-define(wxStyledTextCtrl_SetCurrentPos, 3124). +-define(wxStyledTextCtrl_SetSelectionStart, 3125). +-define(wxStyledTextCtrl_GetSelectionStart, 3126). +-define(wxStyledTextCtrl_SetSelectionEnd, 3127). +-define(wxStyledTextCtrl_GetSelectionEnd, 3128). +-define(wxStyledTextCtrl_SetPrintMagnification, 3129). +-define(wxStyledTextCtrl_GetPrintMagnification, 3130). +-define(wxStyledTextCtrl_SetPrintColourMode, 3131). +-define(wxStyledTextCtrl_GetPrintColourMode, 3132). +-define(wxStyledTextCtrl_FindText, 3133). +-define(wxStyledTextCtrl_FormatRange, 3134). +-define(wxStyledTextCtrl_GetFirstVisibleLine, 3135). +-define(wxStyledTextCtrl_GetLine, 3136). +-define(wxStyledTextCtrl_GetLineCount, 3137). +-define(wxStyledTextCtrl_SetMarginLeft, 3138). +-define(wxStyledTextCtrl_GetMarginLeft, 3139). +-define(wxStyledTextCtrl_SetMarginRight, 3140). +-define(wxStyledTextCtrl_GetMarginRight, 3141). +-define(wxStyledTextCtrl_GetModify, 3142). +-define(wxStyledTextCtrl_SetSelection, 3143). +-define(wxStyledTextCtrl_GetSelectedText, 3144). +-define(wxStyledTextCtrl_GetTextRange, 3145). +-define(wxStyledTextCtrl_HideSelection, 3146). +-define(wxStyledTextCtrl_LineFromPosition, 3147). +-define(wxStyledTextCtrl_PositionFromLine, 3148). +-define(wxStyledTextCtrl_LineScroll, 3149). +-define(wxStyledTextCtrl_EnsureCaretVisible, 3150). +-define(wxStyledTextCtrl_ReplaceSelection, 3151). +-define(wxStyledTextCtrl_SetReadOnly, 3152). +-define(wxStyledTextCtrl_CanPaste, 3153). +-define(wxStyledTextCtrl_CanUndo, 3154). +-define(wxStyledTextCtrl_EmptyUndoBuffer, 3155). +-define(wxStyledTextCtrl_Undo, 3156). +-define(wxStyledTextCtrl_Cut, 3157). +-define(wxStyledTextCtrl_Copy, 3158). +-define(wxStyledTextCtrl_Paste, 3159). +-define(wxStyledTextCtrl_Clear, 3160). +-define(wxStyledTextCtrl_SetText, 3161). +-define(wxStyledTextCtrl_GetText, 3162). +-define(wxStyledTextCtrl_GetTextLength, 3163). +-define(wxStyledTextCtrl_GetOvertype, 3164). +-define(wxStyledTextCtrl_SetCaretWidth, 3165). +-define(wxStyledTextCtrl_GetCaretWidth, 3166). +-define(wxStyledTextCtrl_SetTargetStart, 3167). +-define(wxStyledTextCtrl_GetTargetStart, 3168). +-define(wxStyledTextCtrl_SetTargetEnd, 3169). +-define(wxStyledTextCtrl_GetTargetEnd, 3170). +-define(wxStyledTextCtrl_ReplaceTarget, 3171). +-define(wxStyledTextCtrl_SearchInTarget, 3172). +-define(wxStyledTextCtrl_SetSearchFlags, 3173). +-define(wxStyledTextCtrl_GetSearchFlags, 3174). +-define(wxStyledTextCtrl_CallTipShow, 3175). +-define(wxStyledTextCtrl_CallTipCancel, 3176). +-define(wxStyledTextCtrl_CallTipActive, 3177). +-define(wxStyledTextCtrl_CallTipPosAtStart, 3178). +-define(wxStyledTextCtrl_CallTipSetHighlight, 3179). +-define(wxStyledTextCtrl_CallTipSetBackground, 3180). +-define(wxStyledTextCtrl_CallTipSetForeground, 3181). +-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3182). +-define(wxStyledTextCtrl_CallTipUseStyle, 3183). +-define(wxStyledTextCtrl_VisibleFromDocLine, 3184). +-define(wxStyledTextCtrl_DocLineFromVisible, 3185). +-define(wxStyledTextCtrl_WrapCount, 3186). +-define(wxStyledTextCtrl_SetFoldLevel, 3187). +-define(wxStyledTextCtrl_GetFoldLevel, 3188). +-define(wxStyledTextCtrl_GetLastChild, 3189). +-define(wxStyledTextCtrl_GetFoldParent, 3190). +-define(wxStyledTextCtrl_ShowLines, 3191). +-define(wxStyledTextCtrl_HideLines, 3192). +-define(wxStyledTextCtrl_GetLineVisible, 3193). +-define(wxStyledTextCtrl_SetFoldExpanded, 3194). +-define(wxStyledTextCtrl_GetFoldExpanded, 3195). +-define(wxStyledTextCtrl_ToggleFold, 3196). +-define(wxStyledTextCtrl_EnsureVisible, 3197). +-define(wxStyledTextCtrl_SetFoldFlags, 3198). +-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3199). +-define(wxStyledTextCtrl_SetTabIndents, 3200). +-define(wxStyledTextCtrl_GetTabIndents, 3201). +-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3202). +-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3203). +-define(wxStyledTextCtrl_SetMouseDwellTime, 3204). +-define(wxStyledTextCtrl_GetMouseDwellTime, 3205). +-define(wxStyledTextCtrl_WordStartPosition, 3206). +-define(wxStyledTextCtrl_WordEndPosition, 3207). +-define(wxStyledTextCtrl_SetWrapMode, 3208). +-define(wxStyledTextCtrl_GetWrapMode, 3209). +-define(wxStyledTextCtrl_SetWrapVisualFlags, 3210). +-define(wxStyledTextCtrl_GetWrapVisualFlags, 3211). +-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3212). +-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3213). +-define(wxStyledTextCtrl_SetWrapStartIndent, 3214). +-define(wxStyledTextCtrl_GetWrapStartIndent, 3215). +-define(wxStyledTextCtrl_SetLayoutCache, 3216). +-define(wxStyledTextCtrl_GetLayoutCache, 3217). +-define(wxStyledTextCtrl_SetScrollWidth, 3218). +-define(wxStyledTextCtrl_GetScrollWidth, 3219). +-define(wxStyledTextCtrl_TextWidth, 3220). +-define(wxStyledTextCtrl_GetEndAtLastLine, 3221). +-define(wxStyledTextCtrl_TextHeight, 3222). +-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3223). +-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3224). +-define(wxStyledTextCtrl_AppendText, 3225). +-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3226). +-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3227). +-define(wxStyledTextCtrl_TargetFromSelection, 3228). +-define(wxStyledTextCtrl_LinesJoin, 3229). +-define(wxStyledTextCtrl_LinesSplit, 3230). +-define(wxStyledTextCtrl_SetFoldMarginColour, 3231). +-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3232). +-define(wxStyledTextCtrl_LineDown, 3233). +-define(wxStyledTextCtrl_LineDownExtend, 3234). +-define(wxStyledTextCtrl_LineUp, 3235). +-define(wxStyledTextCtrl_LineUpExtend, 3236). +-define(wxStyledTextCtrl_CharLeft, 3237). +-define(wxStyledTextCtrl_CharLeftExtend, 3238). +-define(wxStyledTextCtrl_CharRight, 3239). +-define(wxStyledTextCtrl_CharRightExtend, 3240). +-define(wxStyledTextCtrl_WordLeft, 3241). +-define(wxStyledTextCtrl_WordLeftExtend, 3242). +-define(wxStyledTextCtrl_WordRight, 3243). +-define(wxStyledTextCtrl_WordRightExtend, 3244). +-define(wxStyledTextCtrl_Home, 3245). +-define(wxStyledTextCtrl_HomeExtend, 3246). +-define(wxStyledTextCtrl_LineEnd, 3247). +-define(wxStyledTextCtrl_LineEndExtend, 3248). +-define(wxStyledTextCtrl_DocumentStart, 3249). +-define(wxStyledTextCtrl_DocumentStartExtend, 3250). +-define(wxStyledTextCtrl_DocumentEnd, 3251). +-define(wxStyledTextCtrl_DocumentEndExtend, 3252). +-define(wxStyledTextCtrl_PageUp, 3253). +-define(wxStyledTextCtrl_PageUpExtend, 3254). +-define(wxStyledTextCtrl_PageDown, 3255). +-define(wxStyledTextCtrl_PageDownExtend, 3256). +-define(wxStyledTextCtrl_EditToggleOvertype, 3257). +-define(wxStyledTextCtrl_Cancel, 3258). +-define(wxStyledTextCtrl_DeleteBack, 3259). +-define(wxStyledTextCtrl_Tab, 3260). +-define(wxStyledTextCtrl_BackTab, 3261). +-define(wxStyledTextCtrl_NewLine, 3262). +-define(wxStyledTextCtrl_FormFeed, 3263). +-define(wxStyledTextCtrl_VCHome, 3264). +-define(wxStyledTextCtrl_VCHomeExtend, 3265). +-define(wxStyledTextCtrl_ZoomIn, 3266). +-define(wxStyledTextCtrl_ZoomOut, 3267). +-define(wxStyledTextCtrl_DelWordLeft, 3268). +-define(wxStyledTextCtrl_DelWordRight, 3269). +-define(wxStyledTextCtrl_LineCut, 3270). +-define(wxStyledTextCtrl_LineDelete, 3271). +-define(wxStyledTextCtrl_LineTranspose, 3272). +-define(wxStyledTextCtrl_LineDuplicate, 3273). +-define(wxStyledTextCtrl_LowerCase, 3274). +-define(wxStyledTextCtrl_UpperCase, 3275). +-define(wxStyledTextCtrl_LineScrollDown, 3276). +-define(wxStyledTextCtrl_LineScrollUp, 3277). +-define(wxStyledTextCtrl_DeleteBackNotLine, 3278). +-define(wxStyledTextCtrl_HomeDisplay, 3279). +-define(wxStyledTextCtrl_HomeDisplayExtend, 3280). +-define(wxStyledTextCtrl_LineEndDisplay, 3281). +-define(wxStyledTextCtrl_LineEndDisplayExtend, 3282). +-define(wxStyledTextCtrl_HomeWrapExtend, 3283). +-define(wxStyledTextCtrl_LineEndWrap, 3284). +-define(wxStyledTextCtrl_LineEndWrapExtend, 3285). +-define(wxStyledTextCtrl_VCHomeWrap, 3286). +-define(wxStyledTextCtrl_VCHomeWrapExtend, 3287). +-define(wxStyledTextCtrl_LineCopy, 3288). +-define(wxStyledTextCtrl_MoveCaretInsideView, 3289). +-define(wxStyledTextCtrl_LineLength, 3290). +-define(wxStyledTextCtrl_BraceHighlight, 3291). +-define(wxStyledTextCtrl_BraceBadLight, 3292). +-define(wxStyledTextCtrl_BraceMatch, 3293). +-define(wxStyledTextCtrl_GetViewEOL, 3294). +-define(wxStyledTextCtrl_SetViewEOL, 3295). +-define(wxStyledTextCtrl_SetModEventMask, 3296). +-define(wxStyledTextCtrl_GetEdgeColumn, 3297). +-define(wxStyledTextCtrl_SetEdgeColumn, 3298). +-define(wxStyledTextCtrl_SetEdgeMode, 3299). +-define(wxStyledTextCtrl_GetEdgeMode, 3300). +-define(wxStyledTextCtrl_GetEdgeColour, 3301). +-define(wxStyledTextCtrl_SetEdgeColour, 3302). +-define(wxStyledTextCtrl_SearchAnchor, 3303). +-define(wxStyledTextCtrl_SearchNext, 3304). +-define(wxStyledTextCtrl_SearchPrev, 3305). +-define(wxStyledTextCtrl_LinesOnScreen, 3306). +-define(wxStyledTextCtrl_UsePopUp, 3307). +-define(wxStyledTextCtrl_SelectionIsRectangle, 3308). +-define(wxStyledTextCtrl_SetZoom, 3309). +-define(wxStyledTextCtrl_GetZoom, 3310). +-define(wxStyledTextCtrl_GetModEventMask, 3311). +-define(wxStyledTextCtrl_SetSTCFocus, 3312). +-define(wxStyledTextCtrl_GetSTCFocus, 3313). +-define(wxStyledTextCtrl_SetStatus, 3314). +-define(wxStyledTextCtrl_GetStatus, 3315). +-define(wxStyledTextCtrl_SetMouseDownCaptures, 3316). +-define(wxStyledTextCtrl_GetMouseDownCaptures, 3317). +-define(wxStyledTextCtrl_SetSTCCursor, 3318). +-define(wxStyledTextCtrl_GetSTCCursor, 3319). +-define(wxStyledTextCtrl_SetControlCharSymbol, 3320). +-define(wxStyledTextCtrl_GetControlCharSymbol, 3321). +-define(wxStyledTextCtrl_WordPartLeft, 3322). +-define(wxStyledTextCtrl_WordPartLeftExtend, 3323). +-define(wxStyledTextCtrl_WordPartRight, 3324). +-define(wxStyledTextCtrl_WordPartRightExtend, 3325). +-define(wxStyledTextCtrl_SetVisiblePolicy, 3326). +-define(wxStyledTextCtrl_DelLineLeft, 3327). +-define(wxStyledTextCtrl_DelLineRight, 3328). +-define(wxStyledTextCtrl_GetXOffset, 3329). +-define(wxStyledTextCtrl_ChooseCaretX, 3330). +-define(wxStyledTextCtrl_SetXCaretPolicy, 3331). +-define(wxStyledTextCtrl_SetYCaretPolicy, 3332). +-define(wxStyledTextCtrl_GetPrintWrapMode, 3333). +-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3334). +-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3335). +-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3336). +-define(wxStyledTextCtrl_SetHotspotSingleLine, 3337). +-define(wxStyledTextCtrl_ParaDownExtend, 3338). +-define(wxStyledTextCtrl_ParaUp, 3339). +-define(wxStyledTextCtrl_ParaUpExtend, 3340). +-define(wxStyledTextCtrl_PositionBefore, 3341). +-define(wxStyledTextCtrl_PositionAfter, 3342). +-define(wxStyledTextCtrl_CopyRange, 3343). +-define(wxStyledTextCtrl_CopyText, 3344). +-define(wxStyledTextCtrl_SetSelectionMode, 3345). +-define(wxStyledTextCtrl_GetSelectionMode, 3346). +-define(wxStyledTextCtrl_LineDownRectExtend, 3347). +-define(wxStyledTextCtrl_LineUpRectExtend, 3348). +-define(wxStyledTextCtrl_CharLeftRectExtend, 3349). +-define(wxStyledTextCtrl_CharRightRectExtend, 3350). +-define(wxStyledTextCtrl_HomeRectExtend, 3351). +-define(wxStyledTextCtrl_VCHomeRectExtend, 3352). +-define(wxStyledTextCtrl_LineEndRectExtend, 3353). +-define(wxStyledTextCtrl_PageUpRectExtend, 3354). +-define(wxStyledTextCtrl_PageDownRectExtend, 3355). +-define(wxStyledTextCtrl_StutteredPageUp, 3356). +-define(wxStyledTextCtrl_StutteredPageUpExtend, 3357). +-define(wxStyledTextCtrl_StutteredPageDown, 3358). +-define(wxStyledTextCtrl_StutteredPageDownExtend, 3359). +-define(wxStyledTextCtrl_WordLeftEnd, 3360). +-define(wxStyledTextCtrl_WordLeftEndExtend, 3361). +-define(wxStyledTextCtrl_WordRightEnd, 3362). +-define(wxStyledTextCtrl_WordRightEndExtend, 3363). +-define(wxStyledTextCtrl_SetWhitespaceChars, 3364). +-define(wxStyledTextCtrl_SetCharsDefault, 3365). +-define(wxStyledTextCtrl_AutoCompGetCurrent, 3366). +-define(wxStyledTextCtrl_Allocate, 3367). +-define(wxStyledTextCtrl_FindColumn, 3368). +-define(wxStyledTextCtrl_GetCaretSticky, 3369). +-define(wxStyledTextCtrl_SetCaretSticky, 3370). +-define(wxStyledTextCtrl_ToggleCaretSticky, 3371). +-define(wxStyledTextCtrl_SetPasteConvertEndings, 3372). +-define(wxStyledTextCtrl_GetPasteConvertEndings, 3373). +-define(wxStyledTextCtrl_SelectionDuplicate, 3374). +-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3375). +-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3376). +-define(wxStyledTextCtrl_StartRecord, 3377). +-define(wxStyledTextCtrl_StopRecord, 3378). +-define(wxStyledTextCtrl_SetLexer, 3379). +-define(wxStyledTextCtrl_GetLexer, 3380). +-define(wxStyledTextCtrl_Colourise, 3381). +-define(wxStyledTextCtrl_SetProperty, 3382). +-define(wxStyledTextCtrl_SetKeyWords, 3383). +-define(wxStyledTextCtrl_SetLexerLanguage, 3384). +-define(wxStyledTextCtrl_GetProperty, 3385). +-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3386). +-define(wxStyledTextCtrl_GetCurrentLine, 3387). +-define(wxStyledTextCtrl_StyleSetSpec, 3388). +-define(wxStyledTextCtrl_StyleSetFont, 3389). +-define(wxStyledTextCtrl_StyleSetFontAttr, 3390). +-define(wxStyledTextCtrl_StyleSetCharacterSet, 3391). +-define(wxStyledTextCtrl_StyleSetFontEncoding, 3392). +-define(wxStyledTextCtrl_CmdKeyExecute, 3393). +-define(wxStyledTextCtrl_SetMargins, 3394). +-define(wxStyledTextCtrl_GetSelection, 3395). +-define(wxStyledTextCtrl_PointFromPosition, 3396). +-define(wxStyledTextCtrl_ScrollToLine, 3397). +-define(wxStyledTextCtrl_ScrollToColumn, 3398). +-define(wxStyledTextCtrl_SetVScrollBar, 3399). +-define(wxStyledTextCtrl_SetHScrollBar, 3400). +-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3401). +-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3402). +-define(wxStyledTextCtrl_SaveFile, 3403). +-define(wxStyledTextCtrl_LoadFile, 3404). +-define(wxStyledTextCtrl_DoDragOver, 3405). +-define(wxStyledTextCtrl_DoDropText, 3406). +-define(wxStyledTextCtrl_GetUseAntiAliasing, 3407). +-define(wxStyledTextCtrl_AddTextRaw, 3408). +-define(wxStyledTextCtrl_InsertTextRaw, 3409). +-define(wxStyledTextCtrl_GetCurLineRaw, 3410). +-define(wxStyledTextCtrl_GetLineRaw, 3411). +-define(wxStyledTextCtrl_GetSelectedTextRaw, 3412). +-define(wxStyledTextCtrl_GetTextRangeRaw, 3413). +-define(wxStyledTextCtrl_SetTextRaw, 3414). +-define(wxStyledTextCtrl_GetTextRaw, 3415). +-define(wxStyledTextCtrl_AppendTextRaw, 3416). +-define(wxArtProvider_GetBitmap, 3417). +-define(wxArtProvider_GetIcon, 3418). +-define(wxTreeEvent_GetKeyCode, 3419). +-define(wxTreeEvent_GetItem, 3420). +-define(wxTreeEvent_GetKeyEvent, 3421). +-define(wxTreeEvent_GetLabel, 3422). +-define(wxTreeEvent_GetOldItem, 3423). +-define(wxTreeEvent_GetPoint, 3424). +-define(wxTreeEvent_IsEditCancelled, 3425). +-define(wxTreeEvent_SetToolTip, 3426). +-define(wxNotebookEvent_GetOldSelection, 3427). +-define(wxNotebookEvent_GetSelection, 3428). +-define(wxNotebookEvent_SetOldSelection, 3429). +-define(wxNotebookEvent_SetSelection, 3430). +-define(wxFileDataObject_new, 3431). +-define(wxFileDataObject_AddFile, 3432). +-define(wxFileDataObject_GetFilenames, 3433). +-define(wxFileDataObject_destroy, 3434). +-define(wxTextDataObject_new, 3435). +-define(wxTextDataObject_GetTextLength, 3436). +-define(wxTextDataObject_GetText, 3437). +-define(wxTextDataObject_SetText, 3438). +-define(wxTextDataObject_destroy, 3439). +-define(wxBitmapDataObject_new_1_1, 3440). +-define(wxBitmapDataObject_new_1_0, 3441). +-define(wxBitmapDataObject_GetBitmap, 3442). +-define(wxBitmapDataObject_SetBitmap, 3443). +-define(wxBitmapDataObject_destroy, 3444). +-define(wxClipboard_new, 3446). +-define(wxClipboard_destruct, 3447). +-define(wxClipboard_AddData, 3448). +-define(wxClipboard_Clear, 3449). +-define(wxClipboard_Close, 3450). +-define(wxClipboard_Flush, 3451). +-define(wxClipboard_GetData, 3452). +-define(wxClipboard_IsOpened, 3453). +-define(wxClipboard_Open, 3454). +-define(wxClipboard_SetData, 3455). +-define(wxClipboard_UsePrimarySelection, 3457). +-define(wxClipboard_IsSupported, 3458). +-define(wxClipboard_Get, 3459). +-define(wxSpinEvent_GetPosition, 3460). +-define(wxSpinEvent_SetPosition, 3461). +-define(wxSplitterWindow_new_0, 3462). +-define(wxSplitterWindow_new_2, 3463). +-define(wxSplitterWindow_destruct, 3464). +-define(wxSplitterWindow_Create, 3465). +-define(wxSplitterWindow_GetMinimumPaneSize, 3466). +-define(wxSplitterWindow_GetSashGravity, 3467). +-define(wxSplitterWindow_GetSashPosition, 3468). +-define(wxSplitterWindow_GetSplitMode, 3469). +-define(wxSplitterWindow_GetWindow1, 3470). +-define(wxSplitterWindow_GetWindow2, 3471). +-define(wxSplitterWindow_Initialize, 3472). +-define(wxSplitterWindow_IsSplit, 3473). +-define(wxSplitterWindow_ReplaceWindow, 3474). +-define(wxSplitterWindow_SetSashGravity, 3475). +-define(wxSplitterWindow_SetSashPosition, 3476). +-define(wxSplitterWindow_SetSashSize, 3477). +-define(wxSplitterWindow_SetMinimumPaneSize, 3478). +-define(wxSplitterWindow_SetSplitMode, 3479). +-define(wxSplitterWindow_SplitHorizontally, 3480). +-define(wxSplitterWindow_SplitVertically, 3481). +-define(wxSplitterWindow_Unsplit, 3482). +-define(wxSplitterWindow_UpdateSize, 3483). +-define(wxSplitterEvent_GetSashPosition, 3484). +-define(wxSplitterEvent_GetX, 3485). +-define(wxSplitterEvent_GetY, 3486). +-define(wxSplitterEvent_GetWindowBeingRemoved, 3487). +-define(wxSplitterEvent_SetSashPosition, 3488). +-define(wxHtmlWindow_new_0, 3489). +-define(wxHtmlWindow_new_2, 3490). +-define(wxHtmlWindow_AppendToPage, 3491). +-define(wxHtmlWindow_GetOpenedAnchor, 3492). +-define(wxHtmlWindow_GetOpenedPage, 3493). +-define(wxHtmlWindow_GetOpenedPageTitle, 3494). +-define(wxHtmlWindow_GetRelatedFrame, 3495). +-define(wxHtmlWindow_HistoryBack, 3496). +-define(wxHtmlWindow_HistoryCanBack, 3497). +-define(wxHtmlWindow_HistoryCanForward, 3498). +-define(wxHtmlWindow_HistoryClear, 3499). +-define(wxHtmlWindow_HistoryForward, 3500). +-define(wxHtmlWindow_LoadFile, 3501). +-define(wxHtmlWindow_LoadPage, 3502). +-define(wxHtmlWindow_SelectAll, 3503). +-define(wxHtmlWindow_SelectionToText, 3504). +-define(wxHtmlWindow_SelectLine, 3505). +-define(wxHtmlWindow_SelectWord, 3506). +-define(wxHtmlWindow_SetBorders, 3507). +-define(wxHtmlWindow_SetFonts, 3508). +-define(wxHtmlWindow_SetPage, 3509). +-define(wxHtmlWindow_SetRelatedFrame, 3510). +-define(wxHtmlWindow_SetRelatedStatusBar, 3511). +-define(wxHtmlWindow_ToText, 3512). +-define(wxHtmlWindow_destroy, 3513). +-define(wxHtmlLinkEvent_GetLinkInfo, 3514). +-define(wxSystemSettings_GetColour, 3515). +-define(wxSystemSettings_GetFont, 3516). +-define(wxSystemSettings_GetMetric, 3517). +-define(wxSystemSettings_GetScreenType, 3518). +-define(wxSystemOptions_GetOption, 3519). +-define(wxSystemOptions_GetOptionInt, 3520). +-define(wxSystemOptions_HasOption, 3521). +-define(wxSystemOptions_IsFalse, 3522). +-define(wxSystemOptions_SetOption_2_1, 3523). +-define(wxSystemOptions_SetOption_2_0, 3524). +-define(wxAuiNotebookEvent_SetSelection, 3525). +-define(wxAuiNotebookEvent_GetSelection, 3526). +-define(wxAuiNotebookEvent_SetOldSelection, 3527). +-define(wxAuiNotebookEvent_GetOldSelection, 3528). +-define(wxAuiNotebookEvent_SetDragSource, 3529). +-define(wxAuiNotebookEvent_GetDragSource, 3530). +-define(wxAuiManagerEvent_SetManager, 3531). +-define(wxAuiManagerEvent_GetManager, 3532). +-define(wxAuiManagerEvent_SetPane, 3533). +-define(wxAuiManagerEvent_GetPane, 3534). +-define(wxAuiManagerEvent_SetButton, 3535). +-define(wxAuiManagerEvent_GetButton, 3536). +-define(wxAuiManagerEvent_SetDC, 3537). +-define(wxAuiManagerEvent_GetDC, 3538). +-define(wxAuiManagerEvent_Veto, 3539). +-define(wxAuiManagerEvent_GetVeto, 3540). +-define(wxAuiManagerEvent_SetCanVeto, 3541). +-define(wxAuiManagerEvent_CanVeto, 3542). +-define(wxLogNull_new, 3543). +-define(wxLogNull_destroy, 3544). +-define(wxTaskBarIcon_new, 3545). +-define(wxTaskBarIcon_destruct, 3546). +-define(wxTaskBarIcon_PopupMenu, 3547). +-define(wxTaskBarIcon_RemoveIcon, 3548). +-define(wxTaskBarIcon_SetIcon, 3549). +-define(wxLocale_new_0, 3550). +-define(wxLocale_new_2, 3552). +-define(wxLocale_destruct, 3553). +-define(wxLocale_Init, 3555). +-define(wxLocale_AddCatalog_1, 3556). +-define(wxLocale_AddCatalog_3, 3557). +-define(wxLocale_AddCatalogLookupPathPrefix, 3558). +-define(wxLocale_GetCanonicalName, 3559). +-define(wxLocale_GetLanguage, 3560). +-define(wxLocale_GetLanguageName, 3561). +-define(wxLocale_GetLocale, 3562). +-define(wxLocale_GetName, 3563). +-define(wxLocale_GetString_2, 3564). +-define(wxLocale_GetString_4, 3565). +-define(wxLocale_GetHeaderValue, 3566). +-define(wxLocale_GetSysName, 3567). +-define(wxLocale_GetSystemEncoding, 3568). +-define(wxLocale_GetSystemEncodingName, 3569). +-define(wxLocale_GetSystemLanguage, 3570). +-define(wxLocale_IsLoaded, 3571). +-define(wxLocale_IsOk, 3572). +-define(wxActivateEvent_GetActive, 3573). +-define(wxPopupWindow_new_2, 3575). +-define(wxPopupWindow_new_0, 3576). +-define(wxPopupWindow_destruct, 3578). +-define(wxPopupWindow_Create, 3579). +-define(wxPopupWindow_Position, 3580). +-define(wxPopupTransientWindow_new_0, 3581). +-define(wxPopupTransientWindow_new_2, 3582). +-define(wxPopupTransientWindow_destruct, 3583). +-define(wxPopupTransientWindow_Popup, 3584). +-define(wxPopupTransientWindow_Dismiss, 3585). diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk index 09fb9f384c..7608bb3014 100644 --- a/lib/wx/vsn.mk +++ b/lib/wx/vsn.mk @@ -1 +1 @@ -WX_VSN = 1.4 +WX_VSN = 1.5 diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl index 847161e844..3038a54ee6 100644 --- a/lib/xmerl/src/xmerl_xsd.erl +++ b/lib/xmerl/src/xmerl_xsd.erl @@ -4888,7 +4888,6 @@ mk_EII_Att_QName(AttName,XMLEl,S) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% create_tables(S=#xsd_state{table=undefined}) -> Tid=ets:new(xmerl_schema_tab,[]), - initial_tab_data(Tid), S#xsd_state{table=Tid}; create_tables(S) -> S. @@ -5617,131 +5616,5 @@ format_error(Err) -> %% {shema_el_pathname(SchemaE,Env), %% xml_el_pathname(E)}. -initial_tab_data(Tab) -> - ets:insert(Tab, - binary_to_term( - <<131,108,0,0,0,9,104,2,104,2,100,0,9,97,116,116,114,105,98,117,116, - 101,104,3,100,0,5,115,112,97,99,101,106,100,0,36,104,116,116,112,58, - 47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57, - 56,47,110,97,109,101,115,112,97,99,101,104,9,100,0,16,115,99,104,101, - 109,97,95,97,116,116,114,105,98,117,116,101,104,3,100,0,5,115,112,97, - 99,101,106,100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51, - 46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112, - 97,99,101,108,0,0,0,1,104,2,100,0,10,115,105,109,112,108,101,84,121, - 112,101,104,3,100,0,15,95,120,109,101,114,108,95,110,111,95,110,97, - 109,101,95,108,0,0,0,1,100,0,5,115,112,97,99,101,106,106,106,100,0,5, - 102,97,108,115,101,106,100,0,8,111,112,116,105,111,110,97,108,100,0,9, - 117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105, - 110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,2, - 100,0,6,115,99,104,101,109,97,107,0,7,120,109,108,46,120,115,100,104, - 7,100,0,6,115,99,104,101,109,97,100,0,11,117,110,113,117,97,108,105, - 102,105,101,100,100,0,11,117,110,113,117,97,108,105,102,105,101,100, - 100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114, - 103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99,101, - 106,106,106,104,2,104,2,100,0,9,97,116,116,114,105,98,117,116,101, - 104,3,100,0,4,98,97,115,101,106,100,0,36,104,116,116,112,58,47,47, - 119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47, - 110,97,109,101,115,112,97,99,101,104,9,100,0,16,115,99,104,101,109, - 97,95,97,116,116,114,105,98,117,116,101,104,3,100,0,4,98,97,115,101, - 106,100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111, - 114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99, - 101,108,0,0,0,1,104,2,100,0,10,115,105,109,112,108,101,84,121,112,101, - 104,3,100,0,6,97,110,121,85,82,73,106,100,0,32,104,116,116,112,58,47, - 47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83, - 99,104,101,109,97,106,100,0,5,102,97,108,115,101,106,100,0,8,111,112, - 116,105,111,110,97,108,100,0,9,117,110,100,101,102,105,110,101,100, - 100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101, - 102,105,110,101,100,104,2,104,2,100,0,14,97,116,116,114,105,98,117, - 116,101,71,114,111,117,112,104,3,100,0,12,115,112,101,99,105,97,108, - 65,116,116,114,115,106,100,0,36,104,116,116,112,58,47,47,119,119,119, - 46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101, - 115,112,97,99,101,104,5,100,0,22,115,99,104,101,109,97,95,97,116,116, - 114,105,98,117,116,101,95,103,114,111,117,112,104,3,100,0,12,115,112, - 101,99,105,97,108,65,116,116,114,115,106,100,0,36,104,116,116,112,58, - 47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57, - 56,47,110,97,109,101,115,112,97,99,101,100,0,9,117,110,100,101,102, - 105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,108,0,0, - 0,3,104,2,100,0,9,97,116,116,114,105,98,117,116,101,104,3,100,0,4,98, - 97,115,101,106,106,104,2,100,0,9,97,116,116,114,105,98,117,116,101, - 104,3,100,0,4,108,97,110,103,106,106,104,2,100,0,9,97,116,116,114, - 105,98,117,116,101,104,3,100,0,5,115,112,97,99,101,106,106,106,104, - 2,104,2,100,0,10,115,105,109,112,108,101,84,121,112,101,104,3,100,0, - 15,95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108,0,0,0, - 1,100,0,5,115,112,97,99,101,106,106,104,9,100,0,18,115,99,104,101, - 109,97,95,115,105,109,112,108,101,95,116,121,112,101,104,3,100,0,15, - 95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108,0,0,0,1, - 100,0,5,115,112,97,99,101,106,106,108,0,0,0,1,100,0,5,115,112,97,99, - 101,106,104,3,100,0,6,78,67,78,97,109,101,106,100,0,32,104,116,116, - 112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,49,47, - 88,77,76,83,99,104,101,109,97,100,0,5,102,97,108,115,101,106,108,0,0, - 0,1,104,2,100,0,11,101,110,117,109,101,114,97,116,105,111,110,108,0,0, - 0,2,107,0,7,100,101,102,97,117,108,116,107,0,8,112,114,101,115,101, - 114,118,101,106,106,100,0,6,97,116,111,109,105,99,108,0,0,0,1,104,2, - 100,0,11,114,101,115,116,114,105,99,116,105,111,110,104,2,104,3,100, - 0,6,78,67,78,97,109,101,106,100,0,32,104,116,116,112,58,47,47,119, - 119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83,99, - 104,101,109,97,108,0,0,0,2,104,2,100,0,11,101,110,117,109,101,114, - 97,116,105,111,110,107,0,7,100,101,102,97,117,108,116,104,2,100,0, - 11,101,110,117,109,101,114,97,116,105,111,110,107,0,8,112,114,101, - 115,101,114,118,101,106,106,104,2,104,2,100,0,10,115,105,109,112, - 108,101,84,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95,110, - 111,95,110,97,109,101,95,108,0,0,0,1,100,0,4,108,97,110,103,106,106, - 104,9,100,0,18,115,99,104,101,109,97,95,115,105,109,112,108,101,95, - 116,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95,110,111,95, - 110,97,109,101,95,108,0,0,0,1,100,0,4,108,97,110,103,106,106,108,0,0, - 0,1,100,0,4,108,97,110,103,106,100,0,9,117,110,100,101,102,105,110, - 101,100,100,0,5,102,97,108,115,101,106,106,100,0,6,97,116,111,109, - 105,99,108,0,0,0,1,104,2,100,0,5,117,110,105,111,110,108,0,0,0,2,104, - 2,100,0,10,115,105,109,112,108,101,84,121,112,101,104,3,100,0,8,108, - 97,110,103,117,97,103,101,106,100,0,32,104,116,116,112,58,47,47,119, - 119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83,99,104, - 101,109,97,104,2,100,0,10,115,105,109,112,108,101,84,121,112,101,104, - 3,100,0,15,95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108, - 0,0,0,2,100,0,15,95,120,109,101,114,108,95,110,111,95,110,97,109,101, - 95,100,0,4,108,97,110,103,106,106,106,106,104,2,104,2,100,0,9,97,116, - 116,114,105,98,117,116,101,104,3,100,0,2,105,100,106,100,0,36,104,116, - 116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47, - 49,57,57,56,47,110,97,109,101,115,112,97,99,101,104,9,100,0,16,115,99, - 104,101,109,97,95,97,116,116,114,105,98,117,116,101,104,3,100,0,2,105, - 100,106,100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51,46, - 111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97, - 99,101,108,0,0,0,1,104,2,100,0,10,115,105,109,112,108,101,84,121,112, - 101,104,3,100,0,2,73,68,106,100,0,32,104,116,116,112,58,47,47,119,119, - 119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83,99,104,101, - 109,97,106,100,0,5,102,97,108,115,101,106,100,0,8,111,112,116,105,111, - 110,97,108,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117, - 110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110, - 101,100,104,2,104,2,100,0,9,97,116,116,114,105,98,117,116,101,104,3, - 100,0,4,108,97,110,103,106,100,0,36,104,116,116,112,58,47,47,119,119, - 119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109, - 101,115,112,97,99,101,104,9,100,0,16,115,99,104,101,109,97,95,97,116, - 116,114,105,98,117,116,101,104,3,100,0,4,108,97,110,103,106,100,0,36, - 104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,88, - 77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99,101,108,0,0,0,1, - 104,2,100,0,10,115,105,109,112,108,101,84,121,112,101,104,3,100,0,15, - 95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108,0,0,0,1, - 100,0,4,108,97,110,103,106,106,106,100,0,5,102,97,108,115,101,106, - 100,0,8,111,112,116,105,111,110,97,108,100,0,9,117,110,100,101,102, - 105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9, - 117,110,100,101,102,105,110,101,100,104,2,104,2,100,0,10,115,105,109, - 112,108,101,84,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95, - 110,111,95,110,97,109,101,95,108,0,0,0,2,100,0,15,95,120,109,101,114, - 108,95,110,111,95,110,97,109,101,95,100,0,4,108,97,110,103,106,106, - 104,9,100,0,18,115,99,104,101,109,97,95,115,105,109,112,108,101,95, - 116,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95,110,111,95, - 110,97,109,101,95,108,0,0,0,2,100,0,15,95,120,109,101,114,108,95,110, - 111,95,110,97,109,101,95,100,0,4,108,97,110,103,106,106,108,0,0,0,2, - 100,0,15,95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,100, - 0,4,108,97,110,103,106,104,3,100,0,6,115,116,114,105,110,103,106,100, - 0,32,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47, - 50,48,48,49,47,88,77,76,83,99,104,101,109,97,100,0,5,102,97,108,115, - 101,106,108,0,0,0,1,104,2,100,0,11,101,110,117,109,101,114,97,116,105, - 111,110,108,0,0,0,1,106,106,106,100,0,6,97,116,111,109,105,99,108,0,0, - 0,1,104,2,100,0,11,114,101,115,116,114,105,99,116,105,111,110,104,2, - 104,3,100,0,6,115,116,114,105,110,103,106,100,0,32,104,116,116,112,58, - 47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76, - 83,99,104,101,109,97,108,0,0,0,1,104,2,100,0,11,101,110,117,109,101, - 114,97,116,105,111,110,106,106,106,106>>)). - default_namespace_by_convention() -> [{xml,'http://www.w3.org/XML/1998/namespace'}]. diff --git a/lib/xmerl/test/xmerl_xsd_SUITE.erl b/lib/xmerl/test/xmerl_xsd_SUITE.erl index 101fbcd50f..92c8287782 100644 --- a/lib/xmerl/test/xmerl_xsd_SUITE.erl +++ b/lib/xmerl/test/xmerl_xsd_SUITE.erl @@ -41,7 +41,8 @@ groups() -> [{group, primitive_datatypes}, {group, derived_datatypes}]}, {validation_tests, [], - [{group, xmlSchemaPrimerExamples}, + [{group, xmlXsdAndExample}, + {group, xmlSchemaPrimerExamples}, {group, miscXMLexamples}]}, {primitive_datatypes, [], [string, boolean, decimal, float, double, duration, @@ -55,6 +56,8 @@ groups() -> negativeInteger, long, int, short, byte, nonNegativeInteger, unsignedLong, unsignedInt, unsignedShort, unsignedByte, positiveInteger]}, + {xmlXsdAndExample, [], + [xml_xsd, xml_lang_attr]}, {xmlSchemaPrimerExamples, [], [po, po1, po2, ipo, ipo_redefine, '4Q99']}, {miscXMLexamples, [], @@ -863,6 +866,19 @@ compare_duration(_Config) -> ?line indefinite = xmerl_xsd_type:compare_durations("P5M","P153D"), ?line lt = xmerl_xsd_type:compare_durations("P5M","P154D"). +xml_xsd(suite) -> []; +xml_xsd(Config) -> + DataDir = ?config(data_dir, Config), + Options = [{fetch_path, [DataDir]}], + {ok, _} = xmerl_xsd:process_schema("xml.xsd", Options). + +xml_lang_attr(suite) -> []; +xml_lang_attr(Config) -> + DataDir = ?config(data_dir, Config), + {Element, _} = xmerl_scan:file(filename:join([DataDir, "book.xml"])), + Options = [{fetch_path, [DataDir]}], + {ok, Schema} = xmerl_xsd:process_schema("book.xsd", Options), + {Element, _} = xmerl_xsd:validate(Element, Schema). po(suite) -> []; po(Config) -> diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml new file mode 100644 index 0000000000..17d7ceffee --- /dev/null +++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<book title="Title" xml:lang="EN"> + <author>Author1</author> + <author>Author2</author> +</book> diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd new file mode 100644 index 0000000000..830951ec1b --- /dev/null +++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/> + <xs:element name="book"> + <xs:complexType> + <xs:sequence> + <xs:element name="author" type="xs:string" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="title" type="xs:string"/> + <xs:attribute ref="xml:lang"/> + </xs:complexType> + </xs:element> +</xs:schema> diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd new file mode 100644 index 0000000000..aea7d0db0a --- /dev/null +++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd @@ -0,0 +1,287 @@ +<?xml version='1.0'?> +<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?> +<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns ="http://www.w3.org/1999/xhtml" + xml:lang="en"> + + <xs:annotation> + <xs:documentation> + <div> + <h1>About the XML namespace</h1> + + <div class="bodytext"> + <p> + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. + </p> + <p> + See <a href="http://www.w3.org/XML/1998/namespace.html"> + http://www.w3.org/XML/1998/namespace.html</a> and + <a href="http://www.w3.org/TR/REC-xml"> + http://www.w3.org/TR/REC-xml</a> for information + about this namespace. + </p> + <p> + Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. + </p> + <p> + See further below in this document for more information about <a + href="#usage">how to refer to this schema document from your own + XSD schema documents</a> and about <a href="#nsversioning">the + namespace-versioning policy governing this schema document</a>. + </p> + </div> + </div> + </xs:documentation> + </xs:annotation> + + <xs:attribute name="lang"> + <xs:annotation> + <xs:documentation> + <div> + + <h3>lang (as an attribute name)</h3> + <p> + denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.</p> + + </div> + <div> + <h4>Notes</h4> + <p> + Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. + </p> + <p> + See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt"> + http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a> + and the IANA language subtag registry at + <a href="http://www.iana.org/assignments/language-subtag-registry"> + http://www.iana.org/assignments/language-subtag-registry</a> + for further information. + </p> + <p> + The union allows for the 'un-declaration' of xml:lang with + the empty string. + </p> + </div> + </xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:union memberTypes="xs:language"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value=""/> + </xs:restriction> + </xs:simpleType> + </xs:union> + </xs:simpleType> + </xs:attribute> + + <xs:attribute name="space"> + <xs:annotation> + <xs:documentation> + <div> + + <h3>space (as an attribute name)</h3> + <p> + denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.</p> + + </div> + </xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:NCName"> + <xs:enumeration value="default"/> + <xs:enumeration value="preserve"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + + <xs:attribute name="base" type="xs:anyURI"> <xs:annotation> + <xs:documentation> + <div> + + <h3>base (as an attribute name)</h3> + <p> + denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.</p> + + <p> + See <a + href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a> + for information about this attribute. + </p> + </div> + </xs:documentation> + </xs:annotation> + </xs:attribute> + + <xs:attribute name="id" type="xs:ID"> + <xs:annotation> + <xs:documentation> + <div> + + <h3>id (as an attribute name)</h3> + <p> + denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.</p> + + <p> + See <a + href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a> + for information about this attribute. + </p> + </div> + </xs:documentation> + </xs:annotation> + </xs:attribute> + + <xs:attributeGroup name="specialAttrs"> + <xs:attribute ref="xml:base"/> + <xs:attribute ref="xml:lang"/> + <xs:attribute ref="xml:space"/> + <xs:attribute ref="xml:id"/> + </xs:attributeGroup> + + <xs:annotation> + <xs:documentation> + <div> + + <h3>Father (in any context at all)</h3> + + <div class="bodytext"> + <p> + denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: + </p> + <blockquote> + <p> + In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". + </p> + </blockquote> + </div> + </div> + </xs:documentation> + </xs:annotation> + + <xs:annotation> + <xs:documentation> + <div xml:id="usage" id="usage"> + <h2><a name="usage">About this schema document</a></h2> + + <div class="bodytext"> + <p> + This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow <code>xml:base</code>, + <code>xml:lang</code>, <code>xml:space</code> or + <code>xml:id</code> attributes on elements they define. + </p> + <p> + To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: + </p> + <pre> + <schema . . .> + . . . + <import namespace="http://www.w3.org/XML/1998/namespace" + schemaLocation="http://www.w3.org/2001/xml.xsd"/> + </pre> + <p> + or + </p> + <pre> + <import namespace="http://www.w3.org/XML/1998/namespace" + schemaLocation="http://www.w3.org/2009/01/xml.xsd"/> + </pre> + <p> + Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. + </p> + <pre> + <type . . .> + . . . + <attributeGroup ref="xml:specialAttrs"/> + </pre> + <p> + will define a type which will schema-validate an instance element + with any of those attributes. + </p> + </div> + </div> + </xs:documentation> + </xs:annotation> + + <xs:annotation> + <xs:documentation> + <div id="nsversioning" xml:id="nsversioning"> + <h2><a name="nsversioning">Versioning policy for this schema document</a></h2> + <div class="bodytext"> + <p> + In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + <a href="http://www.w3.org/2009/01/xml.xsd"> + http://www.w3.org/2009/01/xml.xsd</a>. + </p> + <p> + At the date of issue it can also be found at + <a href="http://www.w3.org/2001/xml.xsd"> + http://www.w3.org/2001/xml.xsd</a>. + </p> + <p> + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at <a href="http://www.w3.org/2001/xml.xsd"> + http://www.w3.org/2001/xml.xsd + </a> + will change accordingly; the version at + <a href="http://www.w3.org/2009/01/xml.xsd"> + http://www.w3.org/2009/01/xml.xsd + </a> + will not change. + </p> + <p> + Previous dated (and unchanging) versions of this schema + document are at: + </p> + <ul> + <li><a href="http://www.w3.org/2009/01/xml.xsd"> + http://www.w3.org/2009/01/xml.xsd</a></li> + <li><a href="http://www.w3.org/2007/08/xml.xsd"> + http://www.w3.org/2007/08/xml.xsd</a></li> + <li><a href="http://www.w3.org/2004/10/xml.xsd"> + http://www.w3.org/2004/10/xml.xsd</a></li> + <li><a href="http://www.w3.org/2001/03/xml.xsd"> + http://www.w3.org/2001/03/xml.xsd</a></li> + </ul> + </div> + </div> + </xs:documentation> + </xs:annotation> + +</xs:schema> + |