diff options
30 files changed, 817 insertions, 190 deletions
diff --git a/configure.in b/configure.in index 9c815414da..eb29b13bcc 100644 --- a/configure.in +++ b/configure.in @@ -386,10 +386,18 @@ if test -f "erts/doc/CONF_INFO"; then echo '*********************************************************************' echo printf "%-15s: \n" documentation; + havexsltproc="yes" for cmd in `cat erts/doc/CONF_INFO`; do echo " $cmd is missing." + if test $cmd = "xsltproc"; then + havexsltproc="no" + fi done - echo ' The documentation can not be built.' + if test $havexsltproc = "no"; then + echo ' The documentation can not be built.' + else + echo ' Using fakefop to generate placeholder PDF files.' + fi echo echo '*********************************************************************' fi diff --git a/erts/configure.in b/erts/configure.in index 6278af3a2e..e5202b75cb 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -821,13 +821,14 @@ fi AC_CHECK_PROGS(XSLTPROC, xsltproc) if test -z "$XSLTPROC"; then echo "xsltproc" >> doc/CONF_INFO - AC_MSG_WARN([No 'xsltproc' command found: the documentation can not be built]) + AC_MSG_WARN([No 'xsltproc' command found: the documentation cannot be built]) fi AC_CHECK_PROGS(FOP, fop) if test -z "$FOP"; then + FOP="$ERL_TOP/make/fakefop" echo "fop" >> doc/CONF_INFO - AC_MSG_WARN([No 'fop' command found: the documentation can not be built]) + AC_MSG_WARN([No 'fop' command found: going to generate placeholder PDF files]) fi dnl diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile index 405cf5f47b..6578923fe1 100644 --- a/erts/doc/src/Makefile +++ b/erts/doc/src/Makefile @@ -1,19 +1,19 @@ # # %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 1997-2010. All Rights Reserved. +# # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in # compliance with the License. You should have received a copy of the # Erlang Public License along with this software. If not, it can be # retrieved online at http://www.erlang.org/. -# +# # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. -# +# # %CopyrightEnd% # include $(ERL_TOP)/make/target.mk diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c index d93c031db2..dbe864f941 100644 --- a/erts/emulator/beam/break.c +++ b/erts/emulator/beam/break.c @@ -327,7 +327,7 @@ print_process_info(int to, void *to_arg, Process *p) (unsigned)(OLD_HEND(p) - OLD_HEAP(p)) ); erts_print(to, to_arg, "Heap unused: %bpu\n", (p->hend - p->htop)); erts_print(to, to_arg, "OldHeap unused: %bpu\n", - (OLD_HEAP(p) == NULL) ? 0 : (OLD_HEND(p) - OLD_HEAP(p)) ); + (OLD_HEAP(p) == NULL) ? 0 : (OLD_HEND(p) - OLD_HTOP(p)) ); if (garbing) { print_garb_info(to, to_arg, p); diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml index 8a0ae52c39..265f8735c2 100644 --- a/lib/asn1/doc/src/asn1ct.xml +++ b/lib/asn1/doc/src/asn1ct.xml @@ -53,7 +53,7 @@ <v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string | noobj | {n2n,EnumTypeName} |{outdir,Dir} | {i,IncludeDir} | optimize | driver | asn1config | undec_rest | {inline,OutputName} | inline | - {macro_name_prefix, Prefix} | {record_name_prefix, Prefix}</v> + {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose</v> <v>OldOption = ber | per</v> <v>Reason = term()</v> <v>Prefix = string()</v> @@ -284,6 +284,11 @@ Binary = binary() <c>Prefix</c>. This is useful when multiple protocols that contains records with identical names are included in a single module.</p> </item> + <tag><c>verbose</c></tag> + <item> + <p>Causes more verbose information from the compiler + describing what it is doing.</p> + </item> </taglist> <p>Any additional option that is applied will be passed to the final step when the generated .erl file is compiled. diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index e6fd3663dd..1859428c49 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -39,7 +39,7 @@ add_tobe_refed_func/1,add_generated_refed_func/1, maybe_rename_function/3,latest_sindex/0,current_sindex/0, set_current_sindex/1,next_sindex/0,maybe_saved_sindex/2, - parse_and_save/2]). + parse_and_save/2,report_verbose/3]). -include("asn1_records.hrl"). -include_lib("stdlib/include/erl_compile.hrl"). @@ -103,8 +103,8 @@ compile(File,Options) when is_list(Options) -> compile1(File,Options) when is_list(Options) -> - io:format("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File]), - io:format("Compiler Options: ~p~n",[Options]), + report_verbose("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File],Options), + report_verbose("Compiler Options: ~p~n",[Options],Options), Ext = filename:extension(File), Base = filename:basename(File,Ext), OutFile = outfile(Base,"",Options), @@ -152,7 +152,7 @@ inline(true,Name,Module,Options) -> IgorName = filename:rootname(filename:basename(Name)), % io:format("*****~nName: ~p~nModules: ~p~nIgorOptions: ~p~n*****~n", % [IgorName,Modules++RTmodule,IgorOptions]), - io:format("Inlining modules: ~p in ~p~n",[[Module]++RTmodule,IgorName]), + report_verbose("Inlining modules: ~p in ~p~n",[[Module]++RTmodule,IgorName],Options), case catch igor:merge(IgorName,[Module]++RTmodule,[{preprocess,true},{stubs,false},{backups,false}]++IgorOptions) of {'EXIT',{undef,Reason}} -> %% module igor first in R10B io:format("Module igor in syntax_tools must be available:~n~p~n", @@ -173,8 +173,8 @@ inline(_,_,_,_) -> compile_set(SetBase,Files,Options) when is_list(hd(Files)),is_list(Options) -> %% case when there are several input files in a list - io:format("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,Files]), - io:format("Compiler Options: ~p~n",[Options]), + report_verbose("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,Files],Options), + report_verbose("Compiler Options: ~p~n",[Options],Options), OutFile = outfile(SetBase,"",Options), DbFile = outfile(SetBase,"asn1db",Options), Includes = [I || {i,I} <- Options], @@ -802,7 +802,7 @@ check({true,M},File,OutFile,Includes,EncodingRule,DbFile,Options,InputMods) -> NewM = Module#module{typeorval=NewTypeOrVal}, asn1_db:dbput(NewM#module.name,'MODULE',NewM), asn1_db:dbsave(DbFile,M#module.name), - io:format("--~p--~n",[{generated,DbFile}]), + report_verbose("--~p--~n",[{generated,DbFile}],Options), {true,{M,NewM,GenTypeOrVal}} end end; @@ -833,7 +833,7 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) -> Result = case (catch asn1ct_gen:pgen(OutFile,EncodingRule, - M#module.name,GenTOrV)) of + M#module.name,GenTOrV,Options)) of {'EXIT',Reason2} -> io:format("ERROR: ~p~n",[Reason2]), {error,Reason2}; @@ -2518,3 +2518,14 @@ type_check(#'Externaltypereference'{}) -> lists:concat(["_",I]); make_suffix(_) -> "". + +report_verbose(Format, Args, S) -> + case is_verbose(S) of + true -> + io:format(Format, Args); + false -> + ok + end. + +is_verbose(S) -> + lists:member(verbose, S). diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index b9f6c46b53..eab5fb4a2a 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -22,7 +22,7 @@ -include("asn1_records.hrl"). -export([pgen_exports/3, - pgen_hrl/4, + pgen_hrl/5, gen_head/3, demit/1, emit/1, @@ -41,28 +41,29 @@ rt2ct_suffix/0, index2suffix/1, get_record_name_prefix/0]). --export([pgen/4, - pgen_module/5, +-export([pgen/5, + pgen_module/6, mk_var/1, un_hyphen_var/1]). -export([gen_encode_constructed/4, gen_decode_constructed/4]). -%% pgen(Erules, Module, TypeOrVal) +%% pgen(Outfile, Erules, Module, TypeOrVal, Options) %% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module %% .hrl file is only generated if necessary %% Erules = per | ber | ber_bin | per_bin %% Module = atom() %% TypeOrVal = {TypeList,ValueList} %% TypeList = ValueList = [atom()] +%% Options = [Options] from asn1ct:compile() -pgen(OutFile,Erules,Module,TypeOrVal) -> - pgen_module(OutFile,Erules,Module,TypeOrVal,true). +pgen(OutFile,Erules,Module,TypeOrVal,Options) -> + pgen_module(OutFile,Erules,Module,TypeOrVal,Options,true). pgen_module(OutFile,Erules,Module, TypeOrVal = {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets}, - Indent) -> + Options,Indent) -> N2nConvEnums = [CName|| {n2n,CName} <- get(encoding_options)], case N2nConvEnums -- Types of [] -> @@ -72,7 +73,7 @@ pgen_module(OutFile,Erules,Module, UnmatchedTypes}) end, put(outfile,OutFile), - HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Indent), + HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Options,Indent), asn1ct_name:start(), ErlFile = lists:concat([OutFile,".erl"]), Fid = fopen(ErlFile,[write]), @@ -86,7 +87,7 @@ pgen_module(OutFile,Erules,Module, % gen_vars(asn1_db:mod_to_vars(Module)), % gen_tag_table(AllTypes), file:close(Fid), - io:format("--~p--~n",[{generated,ErlFile}]). + asn1ct:report_verbose("--~p--~n",[{generated,ErlFile}],Options). pgen_typeorval(Erules,Module,N2nConvEnums,{Types,Values,_Ptypes,_Classes,Objects,ObjectSets}) -> @@ -1310,7 +1311,7 @@ fopen(F, ModeList) -> exit({error,Reason}) end. -pgen_hrl(Erules,Module,TypeOrVal,_Indent) -> +pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) -> put(currmod,Module), {Types,Values,Ptypes,_,_,_} = TypeOrVal, Ret = @@ -1334,8 +1335,9 @@ pgen_hrl(Erules,Module,TypeOrVal,_Indent) -> Y -> Fid = get(gen_file_out), file:close(Fid), - io:format("--~p--~n", - [{generated,lists:concat([get(outfile),".hrl"])}]), + asn1ct:report_verbose("--~p--~n", + [{generated,lists:concat([get(outfile),".hrl"])}], + Options), Y end. diff --git a/lib/asn1/src/asn1ct_gen_ber.erl b/lib/asn1/src/asn1ct_gen_ber.erl index 7c432f29c3..d70586c75c 100644 --- a/lib/asn1/src/asn1ct_gen_ber.erl +++ b/lib/asn1/src/asn1ct_gen_ber.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -67,7 +67,7 @@ %% TypeList = ValueList = [atom()] pgen(OutFile,Erules,Module,TypeOrVal) -> - asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true). + asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true). %%=============================================================================== diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index b7ac0f407c..a146e92d64 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2002-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -67,7 +67,7 @@ %% TypeList = ValueList = [atom()] pgen(OutFile,Erules,Module,TypeOrVal) -> - asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true). + asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true). %%=============================================================================== diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 06d2489748..23fb392d60 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -43,7 +43,7 @@ %% TypeList = ValueList = [atom()] pgen(OutFile,Erules,Module,TypeOrVal) -> - asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true). + asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true). %% Generate ENCODING ****************************** diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl index 56f895828a..e1feb42a59 100644 --- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl +++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2002-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -43,7 +43,7 @@ %% TypeList = ValueList = [atom()] pgen(OutFile,Erules,Module,TypeOrVal) -> - asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true). + asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true). %% Generate ENCODING ****************************** diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src index 9d3f03fc4c..ca73d259af 100644 --- a/lib/asn1/test/asn1_SUITE.erl.src +++ b/lib/asn1/test/asn1_SUITE.erl.src @@ -2240,7 +2240,8 @@ test_compile_options(Config) -> ?line ok = test_compile_options:wrong_path(Config), ?line ok = test_compile_options:path(Config), ?line ok = test_compile_options:noobj(Config), - ?line ok = test_compile_options:record_name_prefix(Config) + ?line ok = test_compile_options:record_name_prefix(Config), + ?line ok = test_compile_options:verbose(Config) end. testDoubleEllipses(suite) -> []; testDoubleEllipses(Config) -> diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl index d51b2a6c4a..83f38c5e6d 100644 --- a/lib/asn1/test/test_compile_options.erl +++ b/lib/asn1/test/test_compile_options.erl @@ -24,7 +24,7 @@ -export([wrong_path/1,comp/2,path/1,ticket_6143/1,noobj/1, - record_name_prefix/1]). + record_name_prefix/1,verbose/1]). %% OTP-5689 wrong_path(Config) -> @@ -122,6 +122,25 @@ noobj(Config) -> file:delete(filename:join([OutDir,'p_record.erl'])), file:delete(filename:join([OutDir,'p_record.beam'])). +verbose(Config) when is_list(Config) -> + DataDir = ?config(data_dir,Config), + OutDir = ?config(priv_dir,Config), + Asn1File = filename:join([DataDir,"Comment.asn"]), + + %% Test verbose compile + ?line test_server:capture_start(), + ?line ok = asn1ct:compile(Asn1File, [{i,DataDir},{outdir,OutDir},noobj,verbose]), + ?line test_server:capture_stop(), + ?line [Line0|_] = test_server:capture_get(), + ?line lists:prefix("Erlang ASN.1 version", Line0), + + %% Test non-verbose compile + ?line test_server:capture_start(), + ?line ok = asn1ct:compile(Asn1File, [{i,DataDir},{outdir,OutDir},noobj]), + ?line test_server:capture_stop(), + ?line [] = test_server:capture_get(), + ok. + outfiles_check(OutDir) -> outfiles_check(OutDir,outfiles1()). diff --git a/lib/dialyzer/doc/manual.txt b/lib/dialyzer/doc/manual.txt index dac61b74b1..470ddd6c73 100644 --- a/lib/dialyzer/doc/manual.txt +++ b/lib/dialyzer/doc/manual.txt @@ -297,7 +297,7 @@ Option :: {files, [Filename :: string()]} | {include_dirs, [DirName :: string()]} | {output_file, FileName :: string()} | {output_plt, FileName :: string()} - | {analysis_type, 'success_typings' | 'plt_add' | + | {analysis_type, 'succ_typings' | 'plt_add' | 'plt_build' | 'plt_check' | 'plt_remove'} | {warnings, [WarnOpts]} diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml index 7f983a2c0d..1ec2ce830a 100644 --- a/lib/dialyzer/doc/src/dialyzer.xml +++ b/lib/dialyzer/doc/src/dialyzer.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2006</year><year>2009</year> + <year>2006</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -13,12 +13,12 @@ compliance with the License. You should have received a copy of the Erlang Public License along with this software. If not, it can be retrieved online at http://www.erlang.org/. - + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - + </legalnotice> <title>dialyzer</title> @@ -206,7 +206,7 @@ Option : {files, [Filename : string()]} | {include_dirs, [DirName : string()]} | {output_file, FileName : string()} | {output_plt, FileName :: string()} - | {analysis_type, 'success_typings' | 'plt_add' | 'plt_build' | 'plt_check' | 'plt_remove'} + | {analysis_type, 'succ_typings' | 'plt_add' | 'plt_build' | 'plt_check' | 'plt_remove'} | {warnings, [WarnOpts]} | {get_warnings, bool()} diff --git a/lib/hipe/arm/hipe_arm_pp.erl b/lib/hipe/arm/hipe_arm_pp.erl index 7ce8421994..c4dde31188 100644 --- a/lib/hipe/arm/hipe_arm_pp.erl +++ b/lib/hipe/arm/hipe_arm_pp.erl @@ -1,20 +1,20 @@ %% -*- erlang-indent-level: 2 -*- %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -246,6 +246,11 @@ stop_suffix(StOp) -> 'strb' -> "b" end. +imm8m_decode(Value, 0) -> + Value; +imm8m_decode(Value, Rot) -> + (Value bsr (2 * Rot)) bor (Value bsl (2 * (16 - Rot))). + pp_temp(Dev, Temp=#arm_temp{reg=Reg, type=Type}) -> case hipe_arm:temp_is_precoloured(Temp) of true -> @@ -292,7 +297,7 @@ pp_am1(Dev, Am1) -> io:format(Dev, "#~w", [Imm5]) end; {Imm8,Imm4} -> - io:format(Dev, "#~w, 2*~w", [Imm8,Imm4]) + io:format(Dev, "#~s", [to_hex(imm8m_decode(Imm8, Imm4))]) end. pp_am2(Dev, #am2{src=Src,sign=Sign,offset=Am2Offset}) -> diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index b4d80d359a..f3b91b3953 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -322,7 +322,7 @@ -define(nil, #c{tag=?nil_tag}). -define(nonempty_list(Types, Term),?list(Types, Term, ?nonempty_qual)). -define(number(Set, Qualifier), #c{tag=?number_tag, elements=Set, - qualifier=Qualifier}. + qualifier=Qualifier}). -define(opaque(Optypes), #c{tag=?opaque_tag, elements=Optypes}). -define(product(Types), #c{tag=?product_tag, elements=Types}). -define(remote(RemTypes), #c{tag=?remote_tag, elements=RemTypes}). diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 87a0939897..da5f750762 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -154,17 +154,21 @@ transport_accept(#sslsocket{pid = {ListenSocket, #config{cb=CbInfo, ssl=SslOpts} EmOptions = emulated_options(), {ok, InetValues} = inet:getopts(ListenSocket, EmOptions), {CbModule,_,_} = CbInfo, - {ok, Socket} = CbModule:accept(ListenSocket, Timeout), - inet:setopts(Socket, internal_inet_values()), - {ok, Port} = inet:port(Socket), - case ssl_connection_sup:start_child([server, "localhost", Port, Socket, - {SslOpts, socket_options(InetValues)}, self(), - CbInfo]) of - {ok, Pid} -> - CbModule:controlling_process(Socket, Pid), - {ok, SslSocket#sslsocket{pid = Pid}}; - {error, Reason} -> - {error, Reason} + case CbModule:accept(ListenSocket, Timeout) of + {ok, Socket} -> + inet:setopts(Socket, internal_inet_values()), + {ok, Port} = inet:port(Socket), + ConnArgs = [server, "localhost", Port, Socket, + {SslOpts, socket_options(InetValues)}, self(), CbInfo], + case ssl_connection_sup:start_child(ConnArgs) of + {ok, Pid} -> + CbModule:controlling_process(Socket, Pid), + {ok, SslSocket#sslsocket{pid = Pid}}; + {error, Reason} -> + {error, Reason} + end; + {error, Reason} -> + {error, Reason} end; transport_accept(#sslsocket{} = ListenSocket, Timeout) -> @@ -560,10 +564,11 @@ handle_options(Opts0, Role) -> CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed}), SslOptions = [versions, verify, verify_fun, + fail_if_no_peer_cert, verify_client_once, depth, certfile, keyfile, key, password, cacertfile, dhfile, ciphers, debug, reuse_session, reuse_sessions, ssl_imp, - cd_info, renegotiate_at], + cb_info, renegotiate_at], SockOpts = lists:foldl(fun(Key, PropList) -> proplists:delete(Key, PropList) diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 4ec90600e9..e04e2dea42 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -441,7 +441,8 @@ certify(#certificate{} = Cert, Opts#ssl_options.verify, Opts#ssl_options.verify_fun) of {PeerCert, PublicKeyInfo} -> - handle_peer_cert(PeerCert, PublicKeyInfo, State); + handle_peer_cert(PeerCert, PublicKeyInfo, + State#state{client_certificate_requested = false}); #alert{} = Alert -> handle_own_alert(Alert, Version, certify_certificate, State), {stop, normal, State} @@ -1731,19 +1732,49 @@ get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Buffer) end; get_data(#socket_options{packet=Type, packet_size=Size}, _, Buffer) -> PacketOpts = [{packet_size, Size}], - case erlang:decode_packet(Type, Buffer, PacketOpts) of + case decode_packet(Type, Buffer, PacketOpts) of {more, _} -> {ok, <<>>, Buffer}; Decoded -> Decoded end. -deliver_app_data(SO = #socket_options{active=once}, Data, Pid, From) -> - send_or_reply(once, Pid, From, format_reply(SO, Data)), - SO#socket_options{active=false}; -deliver_app_data(SO= #socket_options{active=Active}, Data, Pid, From) -> - send_or_reply(Active, Pid, From, format_reply(SO, Data)), - SO. +decode_packet({http, headers}, Buffer, PacketOpts) -> + decode_packet(httph, Buffer, PacketOpts); +decode_packet({http_bin, headers}, Buffer, PacketOpts) -> + decode_packet(httph_bin, Buffer, PacketOpts); +decode_packet(Type, Buffer, PacketOpts) -> + erlang:decode_packet(Type, Buffer, PacketOpts). + +%% Just like with gen_tcp sockets, an ssl socket that has been configured with +%% {packet, http} (or {packet, http_bin}) will automatically switch to expect +%% HTTP headers after it sees a HTTP Request or HTTP Response line. We +%% represent the current state as follows: +%% #socket_options.packet =:= http: Expect a HTTP Request/Response line +%% #socket_options.packet =:= {http, headers}: Expect HTTP Headers +%% Note that if the user has explicitly configured the socket to expect +%% HTTP headers using the {packet, httph} option, we don't do any automatic +%% switching of states. +deliver_app_data(SOpts = #socket_options{active=Active, packet=Type}, + Data, Pid, From) -> + send_or_reply(Active, Pid, From, format_reply(SOpts, Data)), + SO = case Data of + {P, _, _, _} when ((P =:= http_request) or (P =:= http_response)), + ((Type =:= http) or (Type =:= http_bin)) -> + SOpts#socket_options{packet={Type, headers}}; + http_eoh when tuple_size(Type) =:= 2 -> + % End of headers - expect another Request/Response line + {Type1, headers} = Type, + SOpts#socket_options{packet=Type1}; + _ -> + SOpts + end, + case Active of + once -> + SO#socket_options{active=false}; + _ -> + SO + end. format_reply(#socket_options{active=false, mode=Mode, header=Header}, Data) -> {ok, format_reply(Mode, Header, Data)}; @@ -1938,8 +1969,12 @@ get_socket_opts(Socket, [mode | Tags], SockOpts, Acc) -> get_socket_opts(Socket, Tags, SockOpts, [{mode, SockOpts#socket_options.mode} | Acc]); get_socket_opts(Socket, [packet | Tags], SockOpts, Acc) -> - get_socket_opts(Socket, Tags, SockOpts, - [{packet, SockOpts#socket_options.packet} | Acc]); + case SockOpts#socket_options.packet of + {Type, headers} -> + get_socket_opts(Socket, Tags, SockOpts, [{packet, Type} | Acc]); + Type -> + get_socket_opts(Socket, Tags, SockOpts, [{packet, Type} | Acc]) + end; get_socket_opts(Socket, [header | Tags], SockOpts, Acc) -> get_socket_opts(Socket, Tags, SockOpts, [{header, SockOpts#socket_options.header} | Acc]); diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 8dc987e3ff..68970b6693 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -151,16 +151,17 @@ all(doc) -> all(suite) -> [app, connection_info, controlling_process, controller_dies, peercert, connect_dist, - peername, sockname, socket_options, versions, cipher_suites, + peername, sockname, socket_options, valid_ssl_options, versions, cipher_suites, upgrade, upgrade_with_timeout, tcp_connect, ipv6, ekeyfile, ecertfile, ecacertfile, eoptions, shutdown, shutdown_write, shutdown_both, shutdown_error, ciphers, - send_close, dh_params, + send_close, close_transport_accept, dh_params, server_verify_peer_passive, server_verify_peer_active, server_verify_peer_active_once, server_verify_none_passive, server_verify_none_active, - server_verify_none_active_once, - server_verify_no_cacerts, client_verify_none_passive, + server_verify_none_active_once, server_verify_no_cacerts, + server_require_peer_cert_ok, server_require_peer_cert_fail, + client_verify_none_passive, client_verify_none_active, client_verify_none_active_once %%, session_cache_process_list, session_cache_process_mnesia ,reuse_session, reuse_session_expired, server_does_not_want_to_reuse_session, @@ -605,6 +606,59 @@ socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) -> ok. %%-------------------------------------------------------------------- +valid_ssl_options(doc) -> + ["Test what happens when we give valid options"]; + +valid_ssl_options(suite) -> + []; + +valid_ssl_options(Config) when is_list(Config) -> + ClientOpts = [{reuseaddr, true} | ?config(client_opts, Config)], + ServerOpts = [{reuseaddr, true} | ?config(server_opts, Config)], + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Port = ssl_test_lib:inet_port(ServerNode), + + StartOk = + fun(Peer, Pid, TestOpt) -> + receive + {Pid, ok} when Peer =:= server -> + ok; + {Pid, {ok, _}} when Peer =:= client -> + ok; + {Pid, Error} -> + test_server:fail({Peer, + {option_being_tested, TestOpt}, + {got, Error}}) + end + end, + + %% The following contains both documented and undocumented options as + %% listed in ssl:handle_options/2. It excludes file options which are + %% tested elsewhere (cacertfile, certfile, keyfile). + TestOpts = [{versions, []}, {verify, verify_none}, {verify_fun, fun(_) -> false end}, + {fail_if_no_peer_cert, false}, {verify_client_once, false}, + {depth, 1}, {key, undefined}, {password, "secret"}, {ciphers, []}, + {reuse_sessions, true}, {reuse_session, fun(_,_,_,_) -> true end}, + {renegotiate_at, 1000000000}, {debug, []}, + {cb_info, {gen_tcp, tcp, tcp_closed}}], + [begin + Server = + ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, + {from, self()}, + {options, [TestOpt | ServerOpts]}]), + Client = + ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, {from, self()}, + {options, [TestOpt | ClientOpts]}]), + StartOk(server, Server, TestOpt), + StartOk(client, Client, TestOpt), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + ok + end || TestOpt <- TestOpts], + ok. + +%%-------------------------------------------------------------------- versions(doc) -> ["Test API function versions/0"]; @@ -675,6 +729,32 @@ send_close(Config) when is_list(Config) -> gen_tcp:close(TcpS), {error, _} = ssl:send(SslS, "Hello world"), ssl_test_lib:close(Server). + +%%-------------------------------------------------------------------- +close_transport_accept(doc) -> + ["Tests closing ssl socket when waiting on ssl:transport_accept/1"]; + +close_transport_accept(suite) -> + []; + +close_transport_accept(Config) when is_list(Config) -> + ServerOpts = ?config(server_opts, Config), + {_ClientNode, ServerNode, _Hostname} = ssl_test_lib:run_where(Config), + + Port = 0, + Opts = [{active, false} | ServerOpts], + {ok, ListenSocket} = rpc:call(ServerNode, ssl, listen, [Port, Opts]), + spawn_link(fun() -> + test_server:sleep(?SLEEP), + rpc:call(ServerNode, ssl, close, [ListenSocket]) + end), + case rpc:call(ServerNode, ssl, transport_accept, [ListenSocket]) of + {error, closed} -> + ok; + Other -> + exit({?LINE, Other}) + end. + %%-------------------------------------------------------------------- dh_params(doc) -> ["Test to specify DH-params file in server."]; @@ -806,7 +886,7 @@ tcp_connect(Config) when is_list(Config) -> Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0}, {from, self()}, {timeout, 5000}, - {mfa, {?MODULE, should_close, []}}, + {mfa, {?MODULE, dummy, []}}, {tcp_options, TcpOpts}, {ssl_options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), @@ -815,18 +895,20 @@ tcp_connect(Config) when is_list(Config) -> test_server:format("Testcase ~p connected to Server ~p ~n", [self(), Server]), gen_tcp:send(Socket, "<SOME GARBLED NON SSL MESSAGE>"), - ssl_test_lib:check_result(Server, {error,esslerrssl}, tcp_closed, Socket), - + receive + {tcp_closed, Socket} -> + receive + {Server, {error, Error}} -> + test_server:format("Error ~p", [Error]) + end + end, ssl_test_lib:close(Server). -should_close(Socket) -> - receive - {ssl, Socket, closed} -> - server_closed; - Other -> - exit({?LINE, Other}) - end. +dummy(Socket) -> + %% Should not happen as the ssl connection will not be established + %% due to fatal handshake failiure + exit(kill). %%-------------------------------------------------------------------- ipv6(doc) -> @@ -992,8 +1074,6 @@ eoptions(Config) when is_list(Config) -> ssl_test_lib:check_result(Server0, {error, {eoptions, {active,trice}}}, Client0, {error, {eoptions, {active,trice}}}), - test_server:sleep(?SLEEP), - Server1 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, {from, self()}, @@ -1005,9 +1085,6 @@ eoptions(Config) when is_list(Config) -> {options, [{header, a} | ClientOpts]}]), ssl_test_lib:check_result(Server1, {error, {eoptions, {header, a}}}, Client1, {error, {eoptions, {header, a}}}), - - test_server:sleep(?SLEEP), - Server2 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, @@ -1022,9 +1099,6 @@ eoptions(Config) when is_list(Config) -> ssl_test_lib:check_result(Server2, {error, {eoptions, {mode, a}}}, Client2, {error, {eoptions, {mode, a}}}), - - test_server:sleep(?SLEEP), - Server3 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, {from, self()}, @@ -1036,8 +1110,6 @@ eoptions(Config) when is_list(Config) -> {options, [{packet, 8.0} | ClientOpts]}]), ssl_test_lib:check_result(Server3, {error, {eoptions, {packet, 8.0}}}, Client3, {error, {eoptions, {packet, 8.0}}}), - - test_server:sleep(?SLEEP), %% ssl Server4 = @@ -1051,8 +1123,6 @@ eoptions(Config) when is_list(Config) -> {options, [{verify, 4} | ClientOpts]}]), ssl_test_lib:check_result(Server4, {error, {eoptions, {verify, 4}}}, Client4, {error, {eoptions, {verify, 4}}}), - - test_server:sleep(?SLEEP), Server5 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, @@ -1065,8 +1135,6 @@ eoptions(Config) when is_list(Config) -> {options, [{depth, four} | ClientOpts]}]), ssl_test_lib:check_result(Server5, {error, {eoptions, {depth, four}}}, Client5, {error, {eoptions, {depth, four}}}), - - test_server:sleep(?SLEEP), Server6 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, @@ -1080,9 +1148,6 @@ eoptions(Config) when is_list(Config) -> ssl_test_lib:check_result(Server6, {error, {eoptions, {cacertfile, ""}}}, Client6, {error, {eoptions, {cacertfile, ""}}}), - - test_server:sleep(?SLEEP), - Server7 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, {from, self()}, @@ -1096,8 +1161,6 @@ eoptions(Config) when is_list(Config) -> {error, {eoptions, {certfile, 'cert.pem'}}}, Client7, {error, {eoptions, {certfile, 'cert.pem'}}}), - test_server:sleep(?SLEEP), - Server8 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, {from, self()}, @@ -1110,8 +1173,6 @@ eoptions(Config) when is_list(Config) -> ssl_test_lib:check_result(Server8, {error, {eoptions, {keyfile, 'key.pem'}}}, Client8, {error, {eoptions, {keyfile, 'key.pem'}}}), - - test_server:sleep(?SLEEP), Server9 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, @@ -1125,9 +1186,6 @@ eoptions(Config) when is_list(Config) -> ssl_test_lib:check_result(Server9, {error, {eoptions, {key, 'key.pem'}}}, Client9, {error, {eoptions, {key, 'key.pem'}}}), - - test_server:sleep(?SLEEP), - Server10 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, {from, self()}, @@ -1139,9 +1197,6 @@ eoptions(Config) when is_list(Config) -> {options, [{password, foo} | ClientOpts]}]), ssl_test_lib:check_result(Server10, {error, {eoptions, {password, foo}}}, Client10, {error, {eoptions, {password, foo}}}), - - test_server:sleep(?SLEEP), - %% Misc Server11 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, @@ -1155,9 +1210,6 @@ eoptions(Config) when is_list(Config) -> ssl_test_lib:check_result(Server11, {error, {eoptions, {ssl_imp, cool}}}, Client11, {error, {eoptions, {ssl_imp, cool}}}), - - test_server:sleep(?SLEEP), - Server12 = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, {from, self()}, @@ -1779,7 +1831,66 @@ server_verify_no_cacerts(Config) when is_list(Config) -> | ServerOpts]}]), ssl_test_lib:check_result(Server, {error, {eoptions, {cacertfile, ""}}}). + +%%-------------------------------------------------------------------- + +server_require_peer_cert_ok(doc) -> + ["Test server option fail_if_no_peer_cert when peer sends cert"]; + +server_require_peer_cert_ok(suite) -> + []; + +server_require_peer_cert_ok(Config) when is_list(Config) -> + ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} + | ?config(server_verification_opts, Config)], + ClientOpts = ?config(client_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- + +server_require_peer_cert_fail(doc) -> + ["Test server option fail_if_no_peer_cert when peer doesn't send cert"]; + +server_require_peer_cert_fail(suite) -> + []; + +server_require_peer_cert_fail(Config) when is_list(Config) -> + ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} + | ?config(server_verification_opts, Config)], + BadClientOpts = ?config(client_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Port = ssl_test_lib:inet_port(ServerNode), + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | ServerOpts]}]), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | BadClientOpts]}]), + ssl_test_lib:check_result(Server, {error, esslaccept}, + Client, {error, esslconnect}), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + %%-------------------------------------------------------------------- client_verify_none_passive(doc) -> diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl index f031552457..1bcb9a657b 100644 --- a/lib/ssl/test/ssl_packet_SUITE.erl +++ b/lib/ssl/test/ssl_packet_SUITE.erl @@ -144,7 +144,9 @@ all(suite) -> packet_wait_passive, packet_wait_active, packet_baddata_passive, packet_baddata_active, packet_size_passive, packet_size_active, - packet_erl_decode + packet_erl_decode, + packet_http_decode, + packet_http_bin_decode_multi ]. %% Test cases starts here. @@ -1466,6 +1468,173 @@ client_packet_decode(Socket, CDR) -> end, ok. +%%-------------------------------------------------------------------- +packet_http_decode(doc) -> + ["Test setting the packet option {packet, http}"]; +packet_http_decode(suite) -> + []; + +packet_http_decode(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Request = "GET / HTTP/1.1\r\n" + "host: www.example.com\r\n" + "user-agent: HttpTester\r\n" + "\r\n", + Response = "HTTP/1.1 200 OK\r\n" + "\r\n" + "Hello!", + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_http_decode, [Response]}}, + {options, [{active, true}, binary, {packet, http} | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_decode, [Request]}}, + {options, [{active, true}, binary, {packet, http} | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + +server_http_decode(Socket, HttpResponse) -> + assert_packet_opt(Socket, http), + receive + {ssl, Socket, {http_request, 'GET', _, {1,1}}} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + assert_packet_opt(Socket, http), + receive + {ssl, Socket, {http_header, _, 'Host', _, "www.example.com"}} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + assert_packet_opt(Socket, http), + receive + {ssl, Socket, {http_header, _, 'User-Agent', _, "HttpTester"}} -> ok; + Other3 -> exit({?LINE, Other3}) + end, + assert_packet_opt(Socket, http), + receive + {ssl, Socket, http_eoh} -> ok; + Other4 -> exit({?LINE, Other4}) + end, + assert_packet_opt(Socket, http), + ok = ssl:send(Socket, HttpResponse), + ok. + +client_http_decode(Socket, HttpRequest) -> + ok = ssl:send(Socket, HttpRequest), + receive + {ssl, Socket, {http_response, {1,1}, 200, "OK"}} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + receive + {ssl, Socket, http_eoh} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + ok = ssl:setopts(Socket, [{packet, 0}]), + receive + {ssl, Socket, <<"Hello!">>} -> ok; + Other3 -> exit({?LINE, Other3}) + end, + ok. + +%%-------------------------------------------------------------------- +packet_http_bin_decode_multi(doc) -> + ["Test setting the packet option {packet, http_bin} with multiple requests"]; +packet_http_bin_decode_multi(suite) -> + []; + +packet_http_bin_decode_multi(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Request = <<"GET / HTTP/1.1\r\n" + "host: www.example.com\r\n" + "user-agent: HttpTester\r\n" + "\r\n">>, + Response = <<"HTTP/1.1 200 OK\r\n" + "\r\n" + "Hello!">>, + NumMsgs = 3, + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_http_bin_decode, [Response, NumMsgs]}}, + {options, [{active, true}, binary, {packet, http_bin} | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_bin_decode, [Request, NumMsgs]}}, + {options, [{active, true}, binary, {packet, http_bin} | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + +server_http_bin_decode(Socket, HttpResponse, Count) when Count > 0 -> + assert_packet_opt(Socket, http_bin), + receive + {ssl, Socket, {http_request, 'GET', _, {1,1}}} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + assert_packet_opt(Socket, http_bin), + receive + {ssl, Socket, {http_header, _, 'Host', _, <<"www.example.com">>}} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + assert_packet_opt(Socket, http_bin), + receive + {ssl, Socket, {http_header, _, 'User-Agent', _, <<"HttpTester">>}} -> ok; + Other3 -> exit({?LINE, Other3}) + end, + assert_packet_opt(Socket, http_bin), + receive + {ssl, Socket, http_eoh} -> ok; + Other4 -> exit({?LINE, Other4}) + end, + assert_packet_opt(Socket, http_bin), + ok = ssl:send(Socket, HttpResponse), + server_http_bin_decode(Socket, HttpResponse, Count - 1); +server_http_bin_decode(_, _, _) -> + ok. + +client_http_bin_decode(Socket, HttpRequest, Count) when Count > 0 -> + ok = ssl:send(Socket, HttpRequest), + receive + {ssl, Socket, {http_response, {1,1}, 200, <<"OK">>}} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + receive + {ssl, Socket, http_eoh} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + ok = ssl:setopts(Socket, [{packet, 0}]), + receive + {ssl, Socket, <<"Hello!">>} -> ok; + Other3 -> exit({?LINE, Other3}) + end, + ok = ssl:setopts(Socket, [{packet, http_bin}]), + client_http_bin_decode(Socket, HttpRequest, Count - 1); +client_http_bin_decode(_, _, _) -> + ok. %%-------------------------------------------------------------------- %% Internal functions @@ -1572,3 +1741,6 @@ active_packet(Socket, Data, N) -> Other -> {other, Other, ssl:session_info(Socket),N} end. + +assert_packet_opt(Socket, Type) -> + {ok, [{packet, Type}]} = ssl:getopts(Socket, [packet]). diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index f985058cd7..466e987e3e 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -52,7 +52,11 @@ node_to_hostip(Node) -> Address. start_server(Args) -> - spawn_link(?MODULE, run_server, [Args]). + Result = spawn_link(?MODULE, run_server, [Args]), + receive + {listen, up} -> + Result + end. run_server(Opts) -> Node = proplists:get_value(node, Opts), @@ -61,6 +65,7 @@ run_server(Opts) -> Pid = proplists:get_value(from, Opts), test_server:format("ssl:listen(~p, ~p)~n", [Port, Options]), {ok, ListenSocket} = rpc:call(Node, ssl, listen, [Port, Options]), + Pid ! {listen, up}, case Port of 0 -> {ok, {_, NewPort}} = ssl:sockname(ListenSocket), @@ -298,7 +303,11 @@ cert_options(Config) -> start_upgrade_server(Args) -> - spawn_link(?MODULE, run_upgrade_server, [Args]). + Result = spawn_link(?MODULE, run_upgrade_server, [Args]), + receive + {listen, up} -> + Result + end. run_upgrade_server(Opts) -> Node = proplists:get_value(node, Opts), @@ -310,6 +319,7 @@ run_upgrade_server(Opts) -> test_server:format("gen_tcp:listen(~p, ~p)~n", [Port, TcpOptions]), {ok, ListenSocket} = rpc:call(Node, gen_tcp, listen, [Port, TcpOptions]), + Pid ! {listen, up}, case Port of 0 -> @@ -383,7 +393,11 @@ run_upgrade_client(Opts) -> end. start_server_error(Args) -> - spawn_link(?MODULE, run_server_error, [Args]). + Result = spawn_link(?MODULE, run_server_error, [Args]), + receive + {listen, up} -> + Result + end. run_server_error(Opts) -> Node = proplists:get_value(node, Opts), @@ -393,8 +407,9 @@ run_server_error(Opts) -> test_server:format("ssl:listen(~p, ~p)~n", [Port, Options]), case rpc:call(Node, ssl, listen, [Port, Options]) of {ok, ListenSocket} -> - test_server:sleep(2000), %% To make sure error_client will + %% To make sure error_client will %% get {error, closed} and not {error, connection_refused} + Pid ! {listen, up}, test_server:format("ssl:transport_accept(~p)~n", [ListenSocket]), case rpc:call(Node, ssl, transport_accept, [ListenSocket]) of {error, _} = Error -> @@ -405,6 +420,9 @@ run_server_error(Opts) -> Pid ! {self(), Error} end; Error -> + %% Not really true but as this is an error test + %% this is what we want. + Pid ! {listen, up}, Pid ! {self(), Error} end. @@ -448,9 +466,19 @@ trigger_renegotiate(Socket, _, 0, Id) -> test_server:sleep(1000), case ssl:session_info(Socket) of [{session_id, Id} | _ ] -> + %% If a warning alert is received + %% from openssl this may not be + %% an error! fail_session_not_renegotiated; - _ -> - ok + %% Tests that uses this function will not reuse + %% sessions so if we get a new session id the + %% renegotiation has succeeded. + [{session_id, _} | _ ] -> + ok; + {error, closed} -> + fail_session_fatal_alert_during_renegotiation; + {error, timeout} -> + fail_timeout end; trigger_renegotiate(Socket, ErlData, N, Id) -> diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index adb5b9cd13..624404b556 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -327,7 +327,7 @@ erlang_client_openssl_server_no_wrap_sequence_number(Config) when is_list(Config {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), - ErlData = "From erlang to openssl", + ErlData = "From erlang to openssl\n", N = 10, Port = ssl_test_lib:inet_port(node()), diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 6b76dffd86..f259e15d68 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -19,7 +19,10 @@ SSL_VSN = 3.11 -TICKETS = OTP-8517 OTP-7046 +TICKETS = OTP-8517 \ + OTP-7046 \ + OTP-8557 \ + OTP-8560 #TICKETS_3.10.9 = OTP-8510 diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index e1b569d389..f144cbb938 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -109,6 +109,8 @@ format_error(cannot_parse) -> io_lib:format("cannot parse file, giving up", []); format_error({bad,W}) -> io_lib:format("badly formed '~s'", [W]); +format_error(missing_parenthesis) -> + io_lib:format("badly formed define: missing closing right parenthesis",[]); format_error({call,What}) -> io_lib:format("illegal macro call '~s'",[What]); format_error({undefined,M,none}) -> @@ -415,7 +417,7 @@ scan_toks(From, St) -> leave_file(From, St#epp{location=Cl}); {error,_E} -> epp_reply(From, {error,{St#epp.location,epp,cannot_parse}}), - leave_file(From, St) %This serious, just exit! + leave_file(wait_request(St), St) %This serious, just exit! end. scan_toks([{'-',_Lh},{atom,_Ld,define}=Define|Toks], From, St) -> @@ -491,26 +493,32 @@ scan_extends(_Ts, _As, Ms) -> Ms. scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St) when Type =:= atom; Type =:= var -> - case dict:find({atom,M}, St#epp.macs) of - {ok, Defs} when is_list(Defs) -> - %% User defined macros: can be overloaded - case proplists:is_defined(none, Defs) of - true -> - epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}), + case catch macro_expansion(Toks) of + Expansion when is_list(Expansion) -> + case dict:find({atom,M}, St#epp.macs) of + {ok, Defs} when is_list(Defs) -> + %% User defined macros: can be overloaded + case proplists:is_defined(none, Defs) of + true -> + epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}), + wait_req_scan(St); + false -> + scan_define_cont(From, St, + {atom, M}, + {none, {none,Expansion}}) + end; + {ok, _PreDef} -> + %% Predefined macros: cannot be overloaded + epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}), wait_req_scan(St); - false -> + error -> scan_define_cont(From, St, {atom, M}, - {none, {none,macro_expansion(Toks)}}) + {none, {none,Expansion}}) end; - {ok, _PreDef} -> - %% Predefined macros: cannot be overloaded - epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}), - wait_req_scan(St); - error -> - scan_define_cont(From, St, - {atom, M}, - {none, {none,macro_expansion(Toks)}}) + {error,ErrL,What} -> + epp_reply(From, {error,{ErrL,epp,What}}), + wait_req_scan(St) end; scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) when Type =:= atom; Type =:= var -> @@ -536,6 +544,9 @@ scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) error -> scan_define_cont(From, St, {atom, M}, {Len, {As, Me}}) end; + {error,ErrL,What} -> + epp_reply(From, {error,{ErrL,epp,What}}), + wait_req_scan(St); _ -> epp_reply(From, {error,{loc(Def),epp,{bad,define}}}), wait_req_scan(St) @@ -789,7 +800,7 @@ skip_toks(From, St, [I|Sis]) -> leave_file(From, St#epp{location=Cl,istk=[I|Sis]}); {error,_E} -> epp_reply(From, {error,{St#epp.location,epp,cannot_parse}}), - leave_file(From, St) %This serious, just exit! + leave_file(wait_request(St), St) %This serious, just exit! end; skip_toks(From, St, []) -> scan_toks(From, St). @@ -816,7 +827,7 @@ macro_pars([{var,_L,Name}, {',',_}|Ts], Args) -> macro_pars(Ts, [Name|Args]). macro_expansion([{')',_Lp},{dot,_Ld}]) -> []; -macro_expansion([{dot,_Ld}]) -> []; %Be nice, allow no right paren! +macro_expansion([{dot,Ld}]) -> throw({error,Ld,missing_parenthesis}); macro_expansion([T|Ts]) -> [T|macro_expansion(Ts)]. diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index 3342e8f1ff..4806b5d361 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -23,7 +23,8 @@ upcase_mac/1, upcase_mac_1/1, upcase_mac_2/1, variable/1, variable_1/1, otp_4870/1, otp_4871/1, otp_5362/1, pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1, - otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1]). + otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1, + otp_8562/1]). -export([epp_parse_erl_form/2]). @@ -63,7 +64,7 @@ all(doc) -> all(suite) -> [rec_1, upcase_mac, predef_mac, variable, otp_4870, otp_4871, otp_5362, pmod, not_circular, skip_header, otp_6277, otp_7702, otp_8130, - overload_mac, otp_8388, otp_8470, otp_8503]. + overload_mac, otp_8388, otp_8470, otp_8503, otp_8562]. rec_1(doc) -> ["Recursive macros hang or crash epp (OTP-1398)."]; @@ -616,9 +617,9 @@ otp_8130(Config) when is_list(Config) -> "t() -> 14 = (#file_info{size = 14})#file_info.size, ok.\n">>, ok}, - {otp_8130_7, + {otp_8130_7_new, <<"-record(b, {b}).\n" - "-define(A, {{a,#b.b.\n" + "-define(A, {{a,#b.b).\n" "t() -> {{a,2}} = ?A}}, ok.">>, ok}, @@ -750,7 +751,14 @@ otp_8130(Config) when is_list(Config) -> {otp_8130_c24, <<"\n-include(\"no such file.erl\").\n">>, - {errors,[{{2,2},epp,{include,file,"no such file.erl"}}],[]}} + {errors,[{{2,2},epp,{include,file,"no such file.erl"}}],[]}}, + + {otp_8130_7, + <<"-record(b, {b}).\n" + "-define(A, {{a,#b.b.\n" + "t() -> {{a,2}} = ?A}}, ok.">>, + {errors,[{{2,20},epp,missing_parenthesis}, + {{3,19},epp,{undefined,'A',none}}],[]}} ], ?line [] = compile(Config, Cs), @@ -1047,13 +1055,13 @@ overload_mac(Config) when is_list(Config) -> "-undef(A).\n" "t1() -> ?A.\n", "t2() -> ?A(1).">>, - {errors,[{{4,9},epp,{undefined,'A', none}}, - {{5,9},epp,{undefined,'A', 1}}],[]}}, + {errors,[{{4,10},epp,{undefined,'A', none}}, + {{5,10},epp,{undefined,'A', 1}}],[]}}, %% cannot overload predefined macros {overload_mac_c2, <<"-define(MODULE(X), X).">>, - {errors,[{{1,9},epp,{redefine_predef,'MODULE'}}],[]}}, + {errors,[{{1,50},epp,{redefine_predef,'MODULE'}}],[]}}, %% cannot overload macros with same arity {overload_mac_c3, @@ -1120,27 +1128,27 @@ otp_8388(Config) when is_list(Config) -> {macro_1, <<"-define(m(A), A).\n" "t() -> ?m(,).\n">>, - {errors,[{{2,11},epp,{arg_error,m}}],[]}}, + {errors,[{{2,9},epp,{arg_error,m}}],[]}}, {macro_2, <<"-define(m(A), A).\n" "t() -> ?m(a,).\n">>, - {errors,[{{2,12},epp,{arg_error,m}}],[]}}, + {errors,[{{2,9},epp,{arg_error,m}}],[]}}, {macro_3, <<"-define(LINE, a).\n">>, - {errors,[{{1,9},epp,{redefine_predef,'LINE'}}],[]}}, + {errors,[{{1,50},epp,{redefine_predef,'LINE'}}],[]}}, {macro_4, <<"-define(A(B, C, D), {B,C,D}).\n" "t() -> ?A(a,,3).\n">>, - {errors,[{{2,8},epp,{mismatch,'A'}}],[]}}, + {errors,[{{2,9},epp,{mismatch,'A'}}],[]}}, {macro_5, <<"-define(Q, {?F0(), ?F1(,,4)}).\n">>, - {errors,[{{1,24},epp,{arg_error,'F1'}}],[]}}, + {errors,[{{1,62},epp,{arg_error,'F1'}}],[]}}, {macro_6, <<"-define(FOO(X), ?BAR(X)).\n" "-define(BAR(X), ?FOO(X)).\n" "-undef(FOO).\n" "test() -> ?BAR(1).\n">>, - {errors,[{{4,11},epp,{undefined,'FOO',1}}],[]}} + {errors,[{{4,12},epp,{undefined,'FOO',1}}],[]}} ], ?line [] = compile(Config, Ts), ok. @@ -1175,6 +1183,20 @@ otp_8503(Config) when is_list(Config) -> ?line receive _ -> fail() after 0 -> ok end, ok. +otp_8562(doc) -> + ["OTP-8503. Record with no fields is considered typed."]; +otp_8562(suite) -> + []; +otp_8562(Config) when is_list(Config) -> + Cs = [{otp_8562, + <<"-define(P(), {a,b}.\n" + "-define(P3, .\n">>, + {errors,[{{1,60},epp,missing_parenthesis}, + {{2,13},epp,missing_parenthesis}], []}} + ], + ?line [] = compile(Config, Cs), + ok. + check(Config, Tests) -> eval_tests(Config, fun check_test/2, Tests). diff --git a/lib/test_server/src/ts_run.erl b/lib/test_server/src/ts_run.erl index 3461e1383c..1d611f501c 100644 --- a/lib/test_server/src/ts_run.erl +++ b/lib/test_server/src/ts_run.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -392,7 +392,7 @@ make_test_suite(Vars, _Spec, State) -> {ok, Cwd} = file:get_cwd(), ok = file:set_cwd(TestDir), - Result = (catch make:all(Erl_flags)), + Result = (catch make_all(Erl_flags)), ok = file:set_cwd(Cwd), case Result of up_to_date -> @@ -743,4 +743,52 @@ split_one(Path) -> split_path(Path) -> string:tokens(Path,";"). +%% +%% Run make:all/1 if the test suite seems to be designed +%% to be built/re-built by ts. +%% +make_all(Flags) -> + case filelib:is_regular("Emakefile") of + false -> + make_all_no_emakefile(Flags); + true -> + make:all(Flags) + end. + +make_all_no_emakefile(Flags) -> + case filelib:wildcard("*.beam") of + [] -> + %% Since there are no *.beam files, we will assume + %% that this test suite was designed to be built and + %% re-built by ts. Create an Emakefile so that + %% make:all/1 will be run the next time too + %% (in case a test suite is being interactively + %% developed). + create_emakefile(Flags, "*.erl"); + [_|_] -> + %% There is no Emakefile and there already are + %% some *.beam files here. Assume that this test + %% suite was not designed to be re-built by ts. + %% Only create a Emakefile that will compile + %% generated *_SUITE_make files (if any). + create_emakefile(Flags, "*_SUITE_make.erl") + end. +create_emakefile(Flags, Wc) -> + case filelib:wildcard(Wc) of + [] -> + %% There are no files to be built (i.e. not even any + %% generated *_SUITE_make.erl files). We must handle + %% this case specially, because make:all/1 will crash + %% on Emakefile with an empty list of modules. + io:put_chars("No Emakefile found - not running make:all/1\n"), + up_to_date; + [_|_]=Ms0 -> + io:format("Creating an Emakefile for compiling files matching ~s\n", + [Wc]), + Ms = [list_to_atom(filename:rootname(M, ".erl")) || M <- Ms0], + Make0 = {Ms,Flags}, + Make = io_lib:format("~p. \n", [Make0]), + ok = file:write_file("Emakefile", Make), + make:all(Flags) + end. diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml index 3106c72bd8..207f6fdf16 100644 --- a/lib/xmerl/doc/src/notes.xml +++ b/lib/xmerl/doc/src/notes.xml @@ -31,6 +31,30 @@ <p>This document describes the changes made to the Xmerl application.</p> +<section><title>Xmerl 1.2.5</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + All Erlang files are now built by the test server instead of the test directory Makefile. + </p> + <p> + Erlang files in data directories are now built by the test suites instead of using + prebuilt versions under version control. + </p> + <p> + Removed a number of obsolete guards. + </p> + <p> + Own Id: OTP-8537 + </p> + </item> + </list> + </section> + +</section> + <section><title>Xmerl 1.2.4</title> <section><title>Improvements and New Features</title> diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk index 4162b52a80..83b9d4826f 100644 --- a/lib/xmerl/vsn.mk +++ b/lib/xmerl/vsn.mk @@ -17,14 +17,17 @@ # %CopyrightEnd% # -XMERL_VSN = 1.2.4 +XMERL_VSN = 1.2.5 TICKETS = \ - OTP-8343 + OTP-8537 + +TICKETS_1.2.5 = \ + OTP-8537 TICKETS_1.2.4 = \ - OTP-8343 + OTP-8343 TICKETS_1.2.3 = \ OTP-8251 \ diff --git a/make/fakefop b/make/fakefop new file mode 100755 index 0000000000..bbe81ef3b1 --- /dev/null +++ b/make/fakefop @@ -0,0 +1,113 @@ +#!/bin/sh +# +# Copyright Tuncer Ayaz 2010. All Rights Reserved. +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2010. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# +# Author: Tuncer Ayaz +# + +if [ $# -lt 4 ] +then + echo "Usage: fakefop -fo IGNORED -pdf OUTFILE" + exit 1 +fi + +OUTFILE=$4 +NAME=`basename $4 .pdf` + +echo Write $OUTFILE +cat > $OUTFILE <<EndOfFile +%PDF-1.4 +1 0 obj + << /Type /Catalog + /Outlines 2 0 R + /Pages 3 0 R + >> +endobj + +2 0 obj + << /Type /Outlines + /Count 0 + >> +endobj + +3 0 obj + << /Type /Pages + /Kids [4 0 R] + /Count 1 + >> +endobj + +4 0 obj + << /Type /Page + /Parent 3 0 R + /MediaBox [0 0 612 492] + /Contents 5 0 R + /Resources << /ProcSet 6 0 R + /Font << /F1 7 0 R >> + >> + >> +endobj + +5 0 obj + << /Length 73 >> +stream + BT + /F1 24 Tf + 10 400 Td + ($NAME) Tj + ET + BT + /F1 24 Tf + 10 350 Td + (\(placeholder PDF generated without FOP\)) Tj + ET +endstream +endobj + +6 0 obj + [/PDF /Text] +endobj +7 0 obj + << /Type /Font + /Subtype /Type1 + /Name /F1 + /BaseFont /Helvetica + /Encoding /MacRomanEncoding + >> +endobj +xref +0 8 +0000000000 65535 f +0000000009 00000 n +0000000074 00000 n +0000000120 00000 n +0000000179 00000 n +0000000364 00000 n +0000000466 00000 n +0000000496 00000 n + +trailer + << /Size 8 + /Root 1 0 R + >> +startxref +625 +%%EOF +EndOfFile |