aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/test
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/compiler/test
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/compiler/test')
-rw-r--r--lib/compiler/test/Makefile155
-rw-r--r--lib/compiler/test/andor_SUITE.erl397
-rw-r--r--lib/compiler/test/apply_SUITE.erl107
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl375
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/accessing_tags.S31
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/bad_catch_try.S168
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/bad_dsetel.S52
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/bin_aligned.S47
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/bin_match.S64
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/call_last.S71
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/cons.S38
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/dead_code.S48
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/erl_prim_loader.beambin0 -> 17460 bytes
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/freg_range.S53
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/freg_state.S59
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/freg_uninit.S32
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/illegal_instruction.S26
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S84
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/no_exception_in_catch.S209
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/overwrite_catchtag.S38
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/overwrite_trytag.S53
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/stack.S89
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/state_after_fault_in_catch.S58
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/undef_label.S22
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/uninit.S48
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/unsafe_catch.S67
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/xrange.S44
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/yrange.S76
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl297
-rw-r--r--lib/compiler/test/bs_bit_binaries_SUITE.erl155
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl499
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl991
-rw-r--r--lib/compiler/test/bs_shadowed_size_var.core25
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl396
-rw-r--r--lib/compiler/test/compilation_SUITE.erl599
-rw-r--r--lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl28
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_1.erl31
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_10.erl27
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_11.erl31
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_12.erl29
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_2.erl35
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_3.erl29
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_4.erl150
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_5.erl28
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_6.erl153
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_8.erl31
-rw-r--r--lib/compiler/test/compilation_SUITE_data/beam_compiler_9.erl67
-rw-r--r--lib/compiler/test/compilation_SUITE_data/bin_syntax_1.erl31
-rw-r--r--lib/compiler/test/compilation_SUITE_data/bin_syntax_2.erl41
-rw-r--r--lib/compiler/test/compilation_SUITE_data/bin_syntax_3.erl35
-rw-r--r--lib/compiler/test/compilation_SUITE_data/bin_syntax_4.erl32
-rw-r--r--lib/compiler/test/compilation_SUITE_data/bin_syntax_6.erl39
-rw-r--r--lib/compiler/test/compilation_SUITE_data/catch_in_catch.erl51
-rw-r--r--lib/compiler/test/compilation_SUITE_data/compiler_1.erl742
-rw-r--r--lib/compiler/test/compilation_SUITE_data/compiler_3.erl33
-rw-r--r--lib/compiler/test/compilation_SUITE_data/compiler_5.erl49
-rw-r--r--lib/compiler/test/compilation_SUITE_data/complex_guard.erl31
-rw-r--r--lib/compiler/test/compilation_SUITE_data/const_list_256.erl282
-rw-r--r--lib/compiler/test/compilation_SUITE_data/convopts.erl159
-rw-r--r--lib/compiler/test/compilation_SUITE_data/guards.erl106
-rw-r--r--lib/compiler/test/compilation_SUITE_data/live_var.erl30
-rw-r--r--lib/compiler/test/compilation_SUITE_data/long_string.erl670
-rw-r--r--lib/compiler/test/compilation_SUITE_data/nested_tuples_in_case_expr.erl36
-rw-r--r--lib/compiler/test/compilation_SUITE_data/on_load.erl18
-rw-r--r--lib/compiler/test/compilation_SUITE_data/opt_crash.erl65
-rw-r--r--lib/compiler/test/compilation_SUITE_data/other/vsn_1.erl19
-rw-r--r--lib/compiler/test/compilation_SUITE_data/other/vsn_3.erl24
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_2141.erl24
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_2173.erl31
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_2330.erl35
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_2380.erl36
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_4790.erl63
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5076.erl27
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5092.erl39
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5151.erl61
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5235.erl84
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5244.erl47
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5404.erl51
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5436.erl201
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5481.erl527
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5553.erl82
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5632.erl230
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5714.erl46
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_5872.erl46
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_6121.erl48
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_6121a.erl32
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_6121b.erl33
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_7202.erl48
-rw-r--r--lib/compiler/test/compilation_SUITE_data/pattern_expr.erl30
-rw-r--r--lib/compiler/test/compilation_SUITE_data/trycatch_4.erl50
-rw-r--r--lib/compiler/test/compilation_SUITE_data/vsn_1.erl21
-rw-r--r--lib/compiler/test/compilation_SUITE_data/vsn_2.erl21
-rw-r--r--lib/compiler/test/compilation_SUITE_data/vsn_3.erl22
-rw-r--r--lib/compiler/test/compile_SUITE.erl722
-rw-r--r--lib/compiler/test/compile_SUITE_data/bad_record_use.erl28
-rw-r--r--lib/compiler/test/compile_SUITE_data/bad_record_use2.erl29
-rw-r--r--lib/compiler/test/compile_SUITE_data/big.erl742
-rw-r--r--lib/compiler/test/compile_SUITE_data/include/simple.hrl19
-rw-r--r--lib/compiler/test/compile_SUITE_data/missing_testheap1.erl35
-rw-r--r--lib/compiler/test/compile_SUITE_data/missing_testheap2.erl29
-rw-r--r--lib/compiler/test/compile_SUITE_data/record_access.erl29
-rw-r--r--lib/compiler/test/compile_SUITE_data/simple.erl39
-rw-r--r--lib/compiler/test/compile_SUITE_data/wrong_module_name.erl23
-rw-r--r--lib/compiler/test/compiler.cover3
-rw-r--r--lib/compiler/test/compiler.dynspec10
-rw-r--r--lib/compiler/test/core_SUITE.erl59
-rw-r--r--lib/compiler/test/core_SUITE_data/dehydrated_itracer.core99
-rw-r--r--lib/compiler/test/core_SUITE_data/nested_tries.core36
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl233
-rw-r--r--lib/compiler/test/error_SUITE.erl114
-rw-r--r--lib/compiler/test/error_SUITE_data/head_mismatch_line.erl30
-rw-r--r--lib/compiler/test/float_SUITE.erl120
-rw-r--r--lib/compiler/test/fun_SUITE.erl136
-rw-r--r--lib/compiler/test/guard_SUITE.erl1376
-rw-r--r--lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S30
-rw-r--r--lib/compiler/test/inline_SUITE.erl280
-rw-r--r--lib/compiler/test/inline_SUITE_data/attribute.erl31
-rw-r--r--lib/compiler/test/inline_SUITE_data/barnes2.erl160
-rw-r--r--lib/compiler/test/inline_SUITE_data/bsdecode.erl1188
-rw-r--r--lib/compiler/test/inline_SUITE_data/bsdes.erl747
-rw-r--r--lib/compiler/test/inline_SUITE_data/decode1.erl402
-rw-r--r--lib/compiler/test/inline_SUITE_data/itracer.erl407
-rw-r--r--lib/compiler/test/inline_SUITE_data/pseudoknot.erl2575
-rw-r--r--lib/compiler/test/inline_SUITE_data/smith.erl95
-rw-r--r--lib/compiler/test/lc_SUITE.erl162
-rw-r--r--lib/compiler/test/match_SUITE.erl355
-rw-r--r--lib/compiler/test/misc_SUITE.erl241
-rw-r--r--lib/compiler/test/nested_call_in_case.core21
-rw-r--r--lib/compiler/test/num_bif_SUITE.erl265
-rw-r--r--lib/compiler/test/parteval_SUITE.erl46
-rw-r--r--lib/compiler/test/parteval_SUITE_data/t1.erl140
-rw-r--r--lib/compiler/test/pmod_SUITE.erl90
-rw-r--r--lib/compiler/test/pmod_SUITE_data/pmod_basic.erl72
-rw-r--r--lib/compiler/test/receive_SUITE.erl161
-rw-r--r--lib/compiler/test/record_SUITE.erl525
-rw-r--r--lib/compiler/test/record_SUITE_data/record_access_in_guards.erl177
-rw-r--r--lib/compiler/test/test_lib.erl75
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl911
-rw-r--r--lib/compiler/test/warnings_SUITE.erl554
139 files changed, 24161 insertions, 0 deletions
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
new file mode 100644
index 0000000000..ad2f63e9e5
--- /dev/null
+++ b/lib/compiler/test/Makefile
@@ -0,0 +1,155 @@
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= \
+ andor_SUITE \
+ apply_SUITE \
+ beam_validator_SUITE \
+ bs_bincomp_SUITE \
+ bs_bit_binaries_SUITE \
+ bs_construct_SUITE \
+ bs_match_SUITE \
+ bs_utf_SUITE \
+ core_fold_SUITE \
+ compile_SUITE \
+ compilation_SUITE \
+ core_SUITE \
+ error_SUITE \
+ float_SUITE \
+ fun_SUITE \
+ guard_SUITE \
+ inline_SUITE \
+ lc_SUITE \
+ match_SUITE \
+ misc_SUITE \
+ num_bif_SUITE \
+ pmod_SUITE \
+ parteval_SUITE \
+ receive_SUITE \
+ record_SUITE \
+ trycatch_SUITE \
+ warnings_SUITE \
+ test_lib
+
+NO_OPT= \
+ andor \
+ apply \
+ bs_construct \
+ bs_match \
+ bs_utf \
+ core_fold \
+ float \
+ fun \
+ guard \
+ lc \
+ match \
+ misc \
+ num_bif \
+ receive \
+ record \
+ trycatch
+
+R11= \
+ andor \
+ apply \
+ float \
+ fun \
+ match \
+ num_bif \
+ receive \
+ record \
+ trycatch
+
+CORE_MODULES = \
+ bs_shadowed_size_var \
+ nested_call_in_case
+
+
+NO_OPT_MODULES= $(NO_OPT:%=%_no_opt_SUITE)
+NO_OPT_ERL_FILES= $(NO_OPT_MODULES:%=%.erl)
+POST_OPT_MODULES= $(NO_OPT:%=%_post_opt_SUITE)
+POST_OPT_ERL_FILES= $(POST_OPT_MODULES:%=%.erl)
+R11_MODULES= $(R11:%=%_r11_SUITE)
+R11_ERL_FILES= $(R11_MODULES:%=%.erl)
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+CORE_FILES= $(CORE_MODULES:%=%.core)
+
+##TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+##INSTALL_PROGS= $(TARGET_FILES)
+
+EMAKEFILE=Emakefile
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/compiler_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ERL_MAKE_FLAGS +=
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include +clint
+
+EBIN = .
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(R11_ERL_FILES)
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \
+ > $(EMAKEFILE)
+ $(ERL_TOP)/make/make_emakefile +no_copt +no_postopt $(ERL_COMPILE_FLAGS) \
+ -o$(EBIN) $(NO_OPT_MODULES) >> $(EMAKEFILE)
+ $(ERL_TOP)/make/make_emakefile +no_copt $(ERL_COMPILE_FLAGS) \
+ -o$(EBIN) $(POST_OPT_MODULES) >> $(EMAKEFILE)
+ $(ERL_TOP)/make/make_emakefile +r11 $(ERL_COMPILE_FLAGS) \
+ -o$(EBIN) $(R11_MODULES) >> $(EMAKEFILE)
+
+tests debug opt: make_emakefile
+ erl $(ERL_MAKE_FLAGS) -make
+
+clean:
+ rm -f $(EMAKEFILE)
+ rm -f $(TARGET_FILES)
+ rm -f core
+
+docs:
+
+# ----------------------------------------------------
+# Special targets
+# ----------------------------------------------------
+
+%_no_opt_SUITE.erl: %_SUITE.erl
+ sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@
+
+%_post_opt_SUITE.erl: %_SUITE.erl
+ sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@
+
+%_r11_SUITE.erl: %_SUITE.erl
+ sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+
+release_tests_spec: make_emakefile
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) compiler.dynspec compiler.cover \
+ $(EMAKEFILE) $(ERL_FILES) $(CORE_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \
+ $(R11_ERL_FILES) $(RELSYSDIR)
+ chmod -f -R u+w $(RELSYSDIR)
+ @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+
+release_docs_spec:
diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl
new file mode 100644
index 0000000000..34609a49f2
--- /dev/null
+++ b/lib/compiler/test/andor_SUITE.erl
@@ -0,0 +1,397 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(andor_SUITE).
+
+-export([all/1,
+ t_case/1,t_and_or/1,t_andalso/1,t_orelse/1,inside/1,overlap/1,
+ combined/1,in_case/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [t_case,t_and_or,t_andalso,t_orelse,inside,overlap,combined,in_case].
+
+t_case(Config) when is_list(Config) ->
+ %% We test boolean cases almost but not quite like cases
+ %% generated by andalso/orelse.
+ ?line less = t_case_a(1, 2),
+ ?line not_less = t_case_a(2, 2),
+ ?line {'EXIT',{{case_clause,false},_}} = (catch t_case_b({x,y,z}, 2)),
+ ?line {'EXIT',{{case_clause,true},_}} = (catch t_case_b(a, a)),
+ ?line eq = t_case_c(a, a),
+ ?line ne = t_case_c(42, []),
+ ?line t = t_case_d(x, x, true),
+ ?line f = t_case_d(x, x, false),
+ ?line f = t_case_d(x, y, true),
+ ?line {'EXIT',{badarg,_}} = (catch t_case_d(x, y, blurf)),
+ ?line true = (catch t_case_e({a,b}, {a,b})),
+ ?line false = (catch t_case_e({a,b}, 42)),
+
+ ?line true = t_case_xy(42, 100, 700),
+ ?line true = t_case_xy(42, 100, whatever),
+ ?line false = t_case_xy(42, wrong, 700),
+ ?line false = t_case_xy(42, wrong, whatever),
+
+ ?line true = t_case_xy(0, whatever, 700),
+ ?line true = t_case_xy(0, 100, 700),
+ ?line false = t_case_xy(0, whatever, wrong),
+ ?line false = t_case_xy(0, 100, wrong),
+
+ ok.
+
+t_case_a(A, B) ->
+ case A < B of
+ [_|_] -> ok;
+ true -> less;
+ false -> not_less;
+ {a,b,c} -> ok;
+ _Var -> ok
+ end.
+
+t_case_b(A, B) ->
+ case A =:= B of
+ blurf -> ok
+ end.
+
+t_case_c(A, B) ->
+ case not(A =:= B) of
+ true -> ne;
+ false -> eq
+ end.
+
+t_case_d(A, B, X) ->
+ case (A =:= B) and X of
+ true -> t;
+ false -> f
+ end.
+
+t_case_e(A, B) ->
+ case A =:= B of
+ Bool when is_tuple(A) -> id(Bool)
+ end.
+
+t_case_xy(X, Y, Z) ->
+ Res = t_case_x(X, Y, Z),
+ Res = t_case_y(X, Y, Z).
+
+t_case_x(X, Y, Z) ->
+ case abs(X) =:= 42 of
+ true ->
+ Y =:= 100;
+ false ->
+ Z =:= 700
+ end.
+
+t_case_y(X, Y, Z) ->
+ case abs(X) =:= 42 of
+ false ->
+ Z =:= 700;
+ true ->
+ Y =:= 100
+ end.
+
+t_and_or(Config) when is_list(Config) ->
+ ?line true = true and true,
+ ?line false = true and false,
+ ?line false = false and true,
+ ?line false = false and false,
+
+ ?line true = id(true) and true,
+ ?line false = id(true) and false,
+ ?line false = id(false) and true,
+ ?line false = id(false) and false,
+
+ ?line true = true and id(true),
+ ?line false = true and id(false),
+ ?line false = false and id(true),
+ ?line false = false and id(false),
+
+ ?line true = true or true,
+ ?line true = true or false,
+ ?line true = false or true,
+ ?line false = false or false,
+
+ ?line true = id(true) or true,
+ ?line true = id(true) or false,
+ ?line true = id(false) or true,
+ ?line false = id(false) or false,
+
+ ?line true = true or id(true),
+ ?line true = true or id(false),
+ ?line true = false or id(true),
+ ?line false = false or id(false),
+
+ ok.
+
+t_andalso(Config) when is_list(Config) ->
+ Bs = [true,false],
+ Ps = [{X,Y} || X <- Bs, Y <- Bs],
+ lists:foreach(fun (P) -> t_andalso_1(P) end, Ps),
+
+ ?line true = true andalso true,
+ ?line false = true andalso false,
+ ?line false = false andalso true,
+ ?line false = false andalso false,
+
+ ?line false = false andalso glurf,
+ ?line false = false andalso exit(exit_now),
+
+ ?line true = not id(false) andalso not id(false),
+ ?line false = not id(false) andalso not id(true),
+ ?line false = not id(true) andalso not id(false),
+ ?line false = not id(true) andalso not id(true),
+
+ ?line {'EXIT',{badarg,_}} = (catch not id(glurf) andalso id(true)),
+ ?line {'EXIT',{badarg,_}} = (catch not id(false) andalso not id(glurf)),
+ ?line false = id(false) andalso not id(glurf),
+ ?line false = false andalso not id(glurf),
+
+ ok.
+
+t_orelse(Config) when is_list(Config) ->
+ Bs = [true,false],
+ Ps = [{X,Y} || X <- Bs, Y <- Bs],
+ lists:foreach(fun (P) -> t_orelse_1(P) end, Ps),
+
+ ?line true = true orelse true,
+ ?line true = true orelse false,
+ ?line true = false orelse true,
+ ?line false = false orelse false,
+
+ ?line true = true orelse glurf,
+ ?line true = true orelse exit(exit_now),
+
+ ?line true = not id(false) orelse not id(false),
+ ?line true = not id(false) orelse not id(true),
+ ?line true = not id(true) orelse not id(false),
+ ?line false = not id(true) orelse not id(true),
+
+ ?line {'EXIT',{badarg,_}} = (catch not id(glurf) orelse id(true)),
+ ?line {'EXIT',{badarg,_}} = (catch not id(true) orelse not id(glurf)),
+ ?line true = id(true) orelse not id(glurf),
+ ?line true = true orelse not id(glurf),
+
+ ok.
+
+t_andalso_1({X,Y}) ->
+ io:fwrite("~w andalso ~w: ",[X,Y]),
+ V1 = echo(X) andalso echo(Y),
+ V1 = if
+ X andalso Y -> true;
+ true -> false
+ end,
+ check(V1, X and Y).
+
+t_orelse_1({X,Y}) ->
+ io:fwrite("~w orelse ~w: ",[X,Y]),
+ V1 = echo(X) orelse echo(Y),
+ V1 = if
+ X orelse Y -> true;
+ true -> false
+ end,
+ check(V1, X or Y).
+
+inside(Config) when is_list(Config) ->
+ ?line true = inside(-8, 1),
+ ?line false = inside(-53.5, -879798),
+ ?line false = inside(1.0, -879),
+ ?line false = inside(59, -879),
+ ?line false = inside(-11, 1.0),
+ ?line false = inside(100, 0.2),
+ ?line false = inside(100, 1.2),
+ ?line false = inside(-53.5, 4),
+ ?line false = inside(1.0, 5.3),
+ ?line false = inside(59, 879),
+ ok.
+
+inside(Xm, Ym) ->
+ X = -10.0,
+ Y = -2.0,
+ W = 20.0,
+ H = 4.0,
+ Res = inside(Xm, Ym, X, Y, W, H),
+ Res = if
+ X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H -> true;
+ true -> false
+ end,
+ case not id(Res) of
+ Outside ->
+ Outside = if
+ not(X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H) -> true;
+ true -> false
+ end
+ end,
+ {Res,Xm,Ym,X,Y,W,H} = inside_guard(Xm, Ym, X, Y, W, H),
+ io:format("~p =< ~p andalso ~p < ~p andalso ~p =< ~p andalso ~p < ~p ==> ~p",
+ [X,Xm,Xm,X+W,Y,Ym,Ym,Y+H,Res]),
+ Res.
+
+inside(Xm, Ym, X, Y, W, H) ->
+ X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H.
+
+inside_guard(Xm, Ym, X, Y, W, H) when X =< Xm andalso Xm < X+W
+ andalso Y =< Ym andalso Ym < Y+H ->
+ {true,Xm,Ym,X,Y,W,H};
+inside_guard(Xm, Ym, X, Y, W, H) ->
+ {false,Xm,Ym,X,Y,W,H}.
+
+overlap(Config) when is_list(Config) ->
+ ?line true = overlap(7.0, 2.0, 8.0, 0.5),
+ ?line true = overlap(7.0, 2.0, 8.0, 2.5),
+ ?line true = overlap(7.0, 2.0, 5.3, 2),
+ ?line true = overlap(7.0, 2.0, 0.0, 100.0),
+
+ ?line false = overlap(-1, 2, -35, 0.5),
+ ?line false = overlap(-1, 2, 777, 0.5),
+ ?line false = overlap(-1, 2, 2, 10),
+ ?line false = overlap(2, 10, 12, 55.3),
+ ok.
+
+overlap(Pos1, Len1, Pos2, Len2) ->
+ Res = case Pos1 of
+ Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2)
+ orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) ->
+ true;
+ Pos1 -> false
+ end,
+ Res = (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2)
+ orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1),
+ Res = case Pos1 of
+ Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2)
+ orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) ->
+ true;
+ Pos1 -> false
+ end,
+ id(Res).
+
+
+-define(COMB(A,B,C), (A andalso B orelse C)).
+
+combined(Config) when is_list(Config) ->
+ ?line false = comb(false, false, false),
+ ?line true = comb(false, false, true),
+ ?line false = comb(false, true, false),
+ ?line true = comb(false, true, true),
+
+ ?line false = comb(true, false, false),
+ ?line true = comb(true, true, false),
+ ?line true = comb(true, false, true),
+ ?line true = comb(true, true, true),
+
+ ?line false = comb(false, blurf, false),
+ ?line true = comb(false, blurf, true),
+ ?line true = comb(true, true, blurf),
+
+ ?line false = ?COMB(false, false, false),
+ ?line true = ?COMB(false, false, true),
+ ?line false = ?COMB(false, true, false),
+ ?line true = ?COMB(false, true, true),
+
+ ?line false = ?COMB(true, false, false),
+ ?line true = ?COMB(true, true, false),
+ ?line true = ?COMB(true, false, true),
+ ?line true = ?COMB(true, true, true),
+
+ ?line false = ?COMB(false, blurf, false),
+ ?line true = ?COMB(false, blurf, true),
+ ?line true = ?COMB(true, true, blurf),
+
+ ok.
+-undef(COMB).
+
+comb(A, B, C) ->
+ Res = A andalso B orelse C,
+ Res = if
+ A andalso B orelse C -> true;
+ true -> false
+ end,
+ NotRes = if
+ not(A andalso B orelse C) -> true;
+ true -> false
+ end,
+ NotRes = id(not Res),
+ Res = A andalso B orelse C,
+ Res = if
+ A andalso B orelse C -> true;
+ true -> false
+ end,
+ NotRes = id(not Res),
+ Res = if
+ A andalso B orelse C -> true;
+ true -> false
+ end,
+ id(Res).
+
+%% Test that a boolean expression in a case expression is properly
+%% optimized (in particular, that the error behaviour is correct).
+in_case(Config) when is_list(Config) ->
+ ?line edge_rings = in_case_1(1, 1, 1, 1, 1),
+ ?line not_loop = in_case_1(0.5, 1, 1, 1, 1),
+ ?line loop = in_case_1(0.5, 0.9, 1.1, 1, 4),
+ ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, 0)),
+ ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, nan)),
+ ?line {'EXIT',{badarg,_}} = (catch in_case_1(1, 1, 1, blurf, 1)),
+ ?line {'EXIT',{badarith,_}} = (catch in_case_1([nan], 1, 1, 1, 1)),
+ ok.
+
+in_case_1(LenUp, LenDw, LenN, Rotation, Count) ->
+ Res = in_case_1_body(LenUp, LenDw, LenN, Rotation, Count),
+ Res = in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count),
+ Res.
+
+in_case_1_body(LenUp, LenDw, LenN, Rotation, Count) ->
+ case (LenUp/Count > 0.707) and (LenN/Count > 0.707) and
+ (abs(Rotation) > 0.707) of
+ true ->
+ edge_rings;
+ false ->
+ case (LenUp >= 1) or (LenDw >= 1) or
+ (LenN =< 1) or (Count < 4) of
+ true ->
+ not_loop;
+ false ->
+ loop
+ end
+ end.
+
+in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count) ->
+ case (LenUp/Count > 0.707) andalso (LenN/Count > 0.707) andalso
+ (abs(Rotation) > 0.707) of
+ true -> edge_rings;
+ false when LenUp >= 1 orelse LenDw >= 1 orelse
+ LenN =< 1 orelse Count < 4 -> not_loop;
+ false -> loop
+ end.
+
+check(V1, V0) ->
+ if V1 /= V0 ->
+ io:fwrite("error: ~w.\n", [V1]),
+ ?t:fail();
+ true ->
+ io:fwrite("ok: ~w.\n", [V1])
+ end.
+
+echo(X) ->
+ io:fwrite("eval(~w); ",[X]),
+ X.
+
+id(I) -> I.
+
+
diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl
new file mode 100644
index 0000000000..f23dd6c2db
--- /dev/null
+++ b/lib/compiler/test/apply_SUITE.erl
@@ -0,0 +1,107 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(apply_SUITE).
+
+-export([all/1,mfa/1,fun_apply/1]).
+
+-export([foo/0,bar/1,baz/2]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [mfa,fun_apply].
+
+-define(APPLY0(M, F), (fun(Res) -> Res = M:F() end)(apply(M, F, []))).
+-define(APPLY1(M, F, A1), (fun(Res) -> Res = M:F(A1) end)(apply(M, F, [A1]))).
+-define(APPLY2(M, F, A1, A2), (fun(Res) -> Res = M:F(A1, A2) end)(apply(M, F, [A1,A2]))).
+
+mfa(Config) when is_list(Config) ->
+ ?line ok = ?APPLY0(?MODULE, foo),
+ ?line {[a,b]} = ?APPLY1(?MODULE, bar, [a,b]),
+ ?line {39,{a}} = ?APPLY2(?MODULE, baz, 39, {a}),
+
+ ?line Mod = id(?MODULE),
+ ?line ok = ?APPLY0(Mod, foo),
+ ?line {[a,b]} = ?APPLY1(Mod, bar, [a,b]),
+ ?line {39,{a}} = ?APPLY2(Mod, baz, 39, {a}),
+
+ ?line ok = ?APPLY0(?MODULE, (id(foo))),
+ ?line {[a,b]} = ?APPLY1(?MODULE, (id(bar)), [a,b]),
+ ?line {39,{a}} = ?APPLY2(?MODULE, (id(baz)), 39, {a}),
+
+ ?line ok = ?APPLY0(Mod, (id(foo))),
+ ?line {[a,b]} = ?APPLY1(Mod, (id(bar)), [a,b]),
+ ?line {39,{a}} = ?APPLY2(Mod, (id(baz)), 39, {a}),
+
+ ?line {'EXIT',_} = (catch ?APPLY2(Mod, (id(bazzzzzz)), a, b)),
+ ?line {'EXIT',_} = (catch ?APPLY2({}, baz, a, b)),
+ ?line {'EXIT',_} = (catch ?APPLY2(?MODULE, [], a, b)),
+
+ ?line ok = apply(Mod, foo, id([])),
+ ?line {[a,b|c]} = apply(Mod, bar, id([[a,b|c]])),
+ ?line {[xx],{a}} = apply(?MODULE, baz, id([[xx],{a}])),
+
+ ?line Erlang = id(erlang),
+ ?line Self = self(),
+ ?line Self = ?APPLY0(Erlang, self),
+ ?line 42.0 = ?APPLY1(Erlang, abs, -42.0),
+ ?line b = ?APPLY2(Erlang, element, 2, {a,b,c}),
+ ?line true = ?APPLY1(Erlang, is_function, fun erlang:list_to_binary/1),
+ ?line true = ?APPLY1(Erlang, is_function, fun() -> ok end),
+ ?line false = ?APPLY1(Erlang, is_function, blurf),
+ ?line true = ?APPLY2(Erlang, is_function, fun erlang:list_to_binary/1, 1),
+ ?line true = ?APPLY2(Erlang, is_function, fun() -> ok end, 0),
+ ?line false = ?APPLY2(Erlang, is_function, blurf, 0),
+
+ ?line apply(Mod, foo, []).
+
+foo() ->
+ ok.
+
+bar(A) ->
+ {A}.
+
+baz(A, B) ->
+ {A,B}.
+
+-define(FUNAPPLY0(F), (fun(Res) -> Res = F() end)(apply(F, []))).
+-define(FUNAPPLY1(F, A1), (fun(Res) -> Res = F(A1) end)(apply(F, [A1]))).
+-define(FUNAPPLY2(F, A1, A2), (fun(Res) -> Res = F(A1, A2) end)(apply(F, [A1,A2]))).
+
+fun_apply(Config) when is_list(Config) ->
+ ?line Self = self(),
+
+ ?line Self = ?FUNAPPLY0(fun() -> self() end),
+ ?line Self = ?FUNAPPLY0((id(fun() -> self() end))),
+ ?line ok = ?FUNAPPLY0(fun ?MODULE:foo/0),
+ ?line ok = ?FUNAPPLY0((id(fun ?MODULE:foo/0))),
+
+ ?line -42 = ?FUNAPPLY1(fun(A) -> -A end, 42),
+ ?line [x,yy] = ?FUNAPPLY1((id(fun(T) -> [x|T] end)), [yy]),
+ ?line {[a|b]} = ?FUNAPPLY1(fun ?MODULE:bar/1, [a|b]),
+ ?line {[a|b]} = ?FUNAPPLY1((id(fun ?MODULE:bar/1)), [a|b]),
+
+ ?line {a,b} = ?FUNAPPLY2(fun(A, B) -> {A,B} end, a, b),
+ ?line {a,[b]} = ?FUNAPPLY2((id(fun(A, B) -> {A,B} end)), a, [b]),
+ ?line {42,{a}} = ?FUNAPPLY2((id(fun ?MODULE:baz/2)), 42, {a}),
+
+ ok.
+
+id(I) -> I.
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
new file mode 100644
index 0000000000..ef8feb8a27
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -0,0 +1,375 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_validator_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ beam_files/1,compiler_bug/1,stupid_but_valid/1,
+ xrange/1,yrange/1,stack/1,call_last/1,merge_undefined/1,
+ uninit/1,unsafe_catch/1,
+ dead_code/1,mult_labels/1,
+ overwrite_catchtag/1,overwrite_trytag/1,accessing_tags/1,bad_catch_try/1,
+ cons_guard/1,
+ freg_range/1,freg_uninit/1,freg_state/1,
+ bin_match/1,bin_aligned/1,bad_dsetel/1,
+ state_after_fault_in_catch/1,no_exception_in_catch/1,
+ undef_label/1,illegal_instruction/1]).
+
+-include("test_server.hrl").
+
+init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = test_server:timetrap(?t:minutes(10)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [beam_files,compiler_bug,stupid_but_valid,
+ xrange,yrange,stack,call_last,merge_undefined,
+ uninit,unsafe_catch,
+ dead_code,mult_labels,
+ overwrite_catchtag,overwrite_trytag,accessing_tags,bad_catch_try,
+ cons_guard,
+ freg_range,freg_uninit,freg_state,
+ bin_match,bin_aligned,
+ bad_dsetel,state_after_fault_in_catch,no_exception_in_catch,
+ undef_label,illegal_instruction].
+
+beam_files(Config) when is_list(Config) ->
+ ?line {ok,Cwd} = file:get_cwd(),
+ ?line Parent = filename:dirname(Cwd),
+ ?line Wc = filename:join([Parent,"*","*.beam"]),
+ %% Must have at least two files here, or there will could be
+ %% a grammatical error in the output of the io:format/2 call below. ;-)
+ ?line [_,_|_] = Fs = filelib:wildcard(Wc),
+ ?line io:format("~p files\n", [length(Fs)]),
+ beam_files_1(Fs, 0).
+
+beam_files_1([F|Fs], Errors) ->
+ ?line case beam_validator:file(F) of
+ ok ->
+ beam_files_1(Fs, Errors);
+ {error,Es} ->
+ io:format("File: ~s", [F]),
+ io:format("Error: ~p\n", [Es]),
+ beam_files_1(Fs, Errors+1)
+ end;
+beam_files_1([], 0) -> ok;
+beam_files_1([], Errors) ->
+ ?line io:format("~p error(s)", [Errors]),
+ ?line ?t:fail().
+
+compiler_bug(Config) when is_list(Config) ->
+ %% Check that the compiler returns an error if we try to
+ %% assemble one of the bad '.S' files.
+ ?line Data = ?config(data_dir, Config),
+ ?line File = filename:join(Data, "stack"),
+ ?line error = compile:file(File, [asm,report_errors,binary,time]),
+ ok.
+
+%% The following code is stupid but it should compile.
+stupid_but_valid(Config) when is_list(Config) ->
+ AnAtom = nisse,
+ ?line try setelement(5, setelement(6, AnAtom, value), another_value) of
+ Term -> ?line ?t:fail({what_happened,Term})
+ catch
+ error:badarg -> ok
+ end,
+ ok.
+
+xrange(Config) when is_list(Config) ->
+ Errors = do_val(xrange, Config),
+ ?line
+ [{{t,sum_1,2},
+ {{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}}}},
+ {{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,
+ ok.
+
+yrange(Config) when is_list(Config) ->
+ Errors = do_val(yrange, Config),
+ ?line
+ [{{t,sum_1,2},
+ {{move,{x,1},{y,-1}},5,
+ {invalid_store,{y,-1},term}}},
+ {{t,sum_2,2},
+ {{bif,'+',{f,0},[{x,0},{y,1024}],{x,0}},8,
+ {uninitialized_reg,{y,1024}}}},
+ {{t,sum_3,2},
+ {{move,{x,1},{y,1024}},5,limit}},
+ {{t,sum_4,2},
+ {{move,{x,1},{y,-1}},5,
+ {invalid_store,{y,-1},term}}}] = Errors,
+ ok.
+
+stack(Config) when is_list(Config) ->
+ Errors = do_val(stack, Config),
+ ?line [{{t,a,2},{return,11,{stack_frame,2}}},
+ {{t,b,2},{{deallocate,2},4,{allocated,none}}},
+ {{t,c,2},{{deallocate,2},12,{allocated,none}}},
+ {{t,d,2},
+ {{allocate,2,2},5,{existing_stack_frame,{size,2}}}},
+ {{t,e,2},{{deallocate,5},6,{allocated,2}}},
+ {{t,bad_1,0},{{allocate_zero,2,10},4,{{x,9},not_live}}},
+ {{t,bad_2,0},{{move,{y,0},{x,0}},5,{unassigned,{y,0}}}}] = Errors,
+ ok.
+
+call_last(Config) when is_list(Config) ->
+ Errors = do_val(call_last, Config),
+ ?line [{{t,a,1},{{call_last,1,{f,8},2},11,{allocated,1}}},
+ {{t,b,1},
+ {{call_ext_last,2,{extfunc,lists,seq,2},2},
+ 11,
+ {allocated,1}}}] = Errors,
+ ok.
+
+merge_undefined(Config) when is_list(Config) ->
+ Errors = do_val(merge_undefined, Config),
+ ?line [{{t,handle_call,2},
+ {{call_ext,2,{extfunc,debug,filter,2}},
+ 22,
+ {uninitialized_reg,{y,0}}}}] = Errors,
+ ok.
+
+uninit(Config) when is_list(Config) ->
+ Errors = do_val(uninit, Config),
+ ?line
+ [{{t,sum_1,2},
+ {{move,{y,0},{x,0}},5,{uninitialized_reg,{y,0}}}},
+ {{t,sum_2,2},
+ {{call,1,{f,10}},6,{uninitialized_reg,{y,0}}}},
+ {{t,sum_3,2},
+ {{bif,'+',{f,0},[{x,0},{y,0}],{x,0}},
+ 7,
+ {unassigned,{y,0}}}}] = Errors,
+ ok.
+
+unsafe_catch(Config) when is_list(Config) ->
+ Errors = do_val(unsafe_catch, Config),
+ ?line
+ [{{t,small,2},
+ {{bs_put_integer,{f,0},{integer,16},1,
+ {field_flags,[aligned,unsigned,big]},{y,0}},
+ 20,
+ {unassigned,{y,0}}}}] = Errors,
+ ok.
+
+dead_code(Config) when is_list(Config) ->
+ [] = do_val(dead_code, Config),
+ ok.
+
+mult_labels(Config) when is_list(Config) ->
+ [] = do_val(erl_prim_loader, Config, ".beam"),
+ ok.
+
+overwrite_catchtag(Config) when is_list(Config) ->
+ Errors = do_val(overwrite_catchtag, Config),
+ ?line
+ [{{overwrite_catchtag,foo,1},
+ {{move,{x,0},{y,0}},6,{catchtag,_}}}] = Errors,
+ ok.
+
+overwrite_trytag(Config) when is_list(Config) ->
+ Errors = do_val(overwrite_trytag, Config),
+ ?line
+ [{{overwrite_trytag,foo,1},
+ {{kill,{y,2}},9,{trytag,_}}}] = Errors,
+ ok.
+
+accessing_tags(Config) when is_list(Config) ->
+ Errors = do_val(accessing_tags, Config),
+ ?line
+ [{{accessing_tags,foo,1},
+ {{move,{y,0},{x,0}},6,{catchtag,_}}},
+ {{accessing_tags,bar,1},
+ {{move,{y,0},{x,0}},6,{trytag,_}}}] = Errors,
+ ok.
+
+bad_catch_try(Config) when is_list(Config) ->
+ Errors = do_val(bad_catch_try, Config),
+ ?line [{{bad_catch_try,bad_1,1},
+ {{'catch',{x,0},{f,3}},
+ 5,{invalid_store,{x,0},{catchtag,[3]}}}},
+ {{bad_catch_try,bad_2,1},
+ {{catch_end,{x,9}},
+ 8,{source_not_y_reg,{x,9}}}},
+ {{bad_catch_try,bad_3,1},
+ {{catch_end,{y,1}},9,{bad_type,{atom,kalle}}}},
+ {{bad_catch_try,bad_4,1},
+ {{'try',{x,0},{f,15}},5,{invalid_store,{x,0},{trytag,[15]}}}},
+ {{bad_catch_try,bad_5,1},
+ {{try_case,{y,1}},12,{bad_type,term}}},
+ {{bad_catch_try,bad_6,1},
+ {{try_end,{y,1}},8,{bad_type,{integer,1}}}}] = Errors,
+ ok.
+
+cons_guard(Config) when is_list(Config) ->
+ Errors = do_val(cons, Config),
+ ?line
+ [{{cons,foo,1},
+ {{get_list,{x,0},{x,1},{x,2}},
+ 5,
+ {bad_type,{needed,cons},{actual,term}}}}] = Errors,
+ ok.
+
+freg_range(Config) when is_list(Config) ->
+ Errors = do_val(freg_range, Config),
+ ?line
+ [{{t,sum_1,2},
+ {{bif,fadd,{f,0},[{fr,-1},{fr,1}],{fr,0}},
+ 5,
+ {bad_source,{fr,-1}}}},
+ {{t,sum_2,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1024}],{fr,0}},
+ 6,
+ {uninitialized_reg,{fr,1024}}}},
+ {{t,sum_3,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}},
+ 7,
+ {bad_target,{fr,-1}}}},
+ {{t,sum_4,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}},
+ 7,
+ limit}}] = Errors,
+ ok.
+
+freg_uninit(Config) when is_list(Config) ->
+ Errors = do_val(freg_uninit, Config),
+ ?line
+ [{{t,sum_1,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}},
+ 6,
+ {uninitialized_reg,{fr,1}}}},
+ {{t,sum_2,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}},
+ 9,
+ {uninitialized_reg,{fr,0}}}}] = Errors,
+ ok.
+
+freg_state(Config) when is_list(Config) ->
+ Errors = do_val(freg_state, Config),
+ ?line
+ [{{t,sum_1,2},
+ {{bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}},
+ 6,
+ {bad_floating_point_state,undefined}}},
+ {{t,sum_2,2},
+ {{fmove,{fr,0},{x,0}},
+ 8,
+ {bad_floating_point_state,cleared}}},
+ {{t,sum_3,2},
+ {{bif,'-',{f,0},[{x,1},{x,0}],{x,1}},
+ 8,
+ {unsafe_instruction,{float_error_state,cleared}}}},
+ {{t,sum_4,2},
+ {{fcheckerror,{f,0}},
+ 4,
+ {bad_floating_point_state,undefined}}},
+ {{t,sum_5,2},
+ {fclearerror,5,{bad_floating_point_state,cleared}}}] = Errors,
+ ok.
+
+bin_match(Config) when is_list(Config) ->
+ Errors = do_val(bin_match, Config),
+ ?line
+ [{{t,t,1},{{bs_save,0},4,no_bs_match_state}},
+ {{t,x,1},{{bs_restore,1},16,{no_save_point,1}}}] = Errors,
+ ok.
+
+bin_aligned(Config) when is_list(Config) ->
+ Errors = do_val(bin_aligned, Config),
+ ?line
+ [{{t,decode,1},
+ {{bs_put_integer,{f,0},
+ {integer,5},
+ 1,
+ {field_flags,[unsigned,big,aligned]},
+ {integer,0}},
+ 10,
+ {aligned_flag_set,{bits,3}}}}] = Errors,
+ ok.
+
+bad_dsetel(Config) when is_list(Config) ->
+ Errors = do_val(bad_dsetel, Config),
+ ?line
+ [{{t,t,1},
+ {{set_tuple_element,{x,1},{x,0},1},
+ 15,
+ illegal_context_for_set_tuple_element}}] = Errors,
+ ok.
+
+state_after_fault_in_catch(Config) when is_list(Config) ->
+ Errors = do_val(state_after_fault_in_catch, Config),
+ [{{t,foo,1},
+ {{move,{x,1},{x,0}},10,{uninitialized_reg,{x,1}}}},
+ {{state_after_fault_in_catch,if_end,1},
+ {{move,{x,1},{x,0}},9,{uninitialized_reg,{x,1}}}},
+ {{state_after_fault_in_catch,case_end,1},
+ {{move,{x,1},{x,0}},9,{uninitialized_reg,{x,1}}}},
+ {{state_after_fault_in_catch,badmatch,1},
+ {{move,{x,1},{x,0}},9,{uninitialized_reg,{x,1}}}}] = Errors,
+ ok.
+
+no_exception_in_catch(Config) when is_list(Config) ->
+ Errors = do_val(no_exception_in_catch, Config),
+ [{{no_exception_in_catch,nested_of_1,4},
+ {{move,{x,3},{x,0}},91,{uninitialized_reg,{x,3}}}}] = Errors,
+ ok.
+
+undef_label(Config) when is_list(Config) ->
+ Errors = do_val(undef_label, Config),
+ [{{undef_label,t,1},{undef_labels,[42]}},
+ {{undef_label,x,1},{return,4,no_entry_label}}] = Errors,
+ ok.
+
+illegal_instruction(Config) when is_list(Config) ->
+ Errors = do_val(illegal_instruction, Config),
+ [{{illegal_instruction,t,1},
+ {{my_illegal_instruction,{x,0}},4,unknown_instruction}},
+ {{'_',x,1},{bad_func_info,1,illegal_instruction}},
+ {{'_',y,0},{[],0,illegal_instruction}}] = Errors,
+ ok.
+
+
+
+%%%-------------------------------------------------------------------------
+
+do_val(Name, Config) ->
+ do_val(Name, Config, ".S").
+
+do_val(Name, Config, Type) ->
+ ?line Data = ?config(data_dir, Config),
+ ?line File = filename:join(Data, atom_to_list(Name)++Type),
+ ?line case beam_validator:file(File) of
+ {error,Errors} ->
+ ?line io:format("~p:~n~s",
+ [File,beam_validator:format_error(Errors)]),
+ Errors;
+ ok -> []
+ end.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/accessing_tags.S b/lib/compiler/test/beam_validator_SUITE_data/accessing_tags.S
new file mode 100644
index 0000000000..2728a2fa32
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/accessing_tags.S
@@ -0,0 +1,31 @@
+{module, accessing_tags}. %% version = 0
+
+{exports, [{foo,1},{bar,1}]}.
+
+{attributes, []}.
+
+{function, foo, 1, 2}.
+ {label,1}.
+ {func_info,{atom,accessing_tags},{atom,foo},1}.
+ {label,2}.
+ {allocate,1,1}.
+ {'catch',{y,0},{f,3}}.
+ {move,{y,0},{x,0}}. %Retrieve the catch tag.
+ {call,1,{f,2}}.
+ {label,3}.
+ {catch_end,{y,0}}.
+ {deallocate,1}.
+ return.
+
+{function, bar, 1, 5}.
+ {label,4}.
+ {func_info,{atom,accessing_tags},{atom,bar},1}.
+ {label,5}.
+ {allocate,1,1}.
+ {'try',{y,0},{f,6}}.
+ {move,{y,0},{x,0}}. %Retrieve the try tag.
+ {call,5,{f,2}}.
+ {label,6}.
+ {catch_end,{y,0}}.
+ {deallocate,1}.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/bad_catch_try.S b/lib/compiler/test/beam_validator_SUITE_data/bad_catch_try.S
new file mode 100644
index 0000000000..2a53f0dd93
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/bad_catch_try.S
@@ -0,0 +1,168 @@
+{module, bad_catch_try}. %% version = 0
+
+{exports, [{bad_1,1},
+ {bad_2,1},
+ {bad_3,1},
+ {bad_4,1},
+ {bad_5,1},
+ {bad_6,1},
+ {foo,1},
+ {module_info,0},
+ {module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 31}.
+
+
+{function, bad_1, 1, 2}.
+ {label,1}.
+ {func_info,{atom,bad_catch_try},{atom,bad_1},1}.
+ {label,2}.
+ {allocate,1,1}.
+ {'catch',{x,0},{f,3}}.
+ {call,1,{f,26}}.
+ {label,3}.
+ {catch_end,{x,0}}.
+ {test,is_tuple,{f,4},[{x,0}]}.
+ {test,test_arity,{f,4},[{x,0},2]}.
+ {get_tuple_element,{x,0},0,{x,1}}.
+ {test,is_eq_exact,{f,4},[{x,1},{atom,'EXIT'}]}.
+ {move,{atom,error},{x,0}}.
+ {deallocate,1}.
+ return.
+ {label,4}.
+ {move,{atom,ok},{x,0}}.
+ {deallocate,1}.
+ return.
+
+
+{function, bad_2, 1, 6}.
+ {label,5}.
+ {func_info,{atom,bad_catch_try},{atom,bad_2},1}.
+ {label,6}.
+ {allocate,1,1}.
+ {'catch',{y,0},{f,7}}.
+ {call,1,{f,26}}.
+ {label,7}.
+ {catch_end,{x,9}}.
+ {test,is_tuple,{f,8},[{x,0}]}.
+ {test,test_arity,{f,8},[{x,0},2]}.
+ {get_tuple_element,{x,0},0,{x,1}}.
+ {test,is_eq_exact,{f,8},[{x,1},{atom,'EXIT'}]}.
+ {move,{atom,error},{x,0}}.
+ {deallocate,1}.
+ return.
+ {label,8}.
+ {move,{atom,ok},{x,0}}.
+ {deallocate,1}.
+ return.
+
+
+{function, bad_3, 1, 10}.
+ {label,9}.
+ {func_info,{atom,bad_catch_try},{atom,bad_3},1}.
+ {label,10}.
+ {allocate,1,1}.
+ {'catch',{y,0},{f,11}}.
+ {call,1,{f,26}}.
+ {label,11}.
+ {move,{atom,kalle},{y,1}}.
+ {catch_end,{y,1}}.
+ {test,is_tuple,{f,12},[{x,0}]}.
+ {test,test_arity,{f,12},[{x,0},2]}.
+ {get_tuple_element,{x,0},0,{x,1}}.
+ {test,is_eq_exact,{f,12},[{x,1},{atom,'EXIT'}]}.
+ {move,{atom,error},{x,0}}.
+ {deallocate,1}.
+ return.
+ {label,12}.
+ {move,{atom,ok},{x,0}}.
+ {deallocate,1}.
+ return.
+
+
+{function, bad_4, 1, 14}.
+ {label,13}.
+ {func_info,{atom,bad_catch_try},{atom,bad_4},1}.
+ {label,14}.
+ {allocate_zero,1,1}.
+ {'try',{x,0},{f,15}}.
+ {call,1,{f,26}}.
+ {try_end,{y,0}}.
+ {move,{atom,ok},{x,0}}.
+ {jump,{f,16}}.
+ {label,15}.
+ {try_case,{y,0}}.
+ {test,is_ne_exact,{f,16},[{x,0},{atom,error}]}.
+ {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}.
+ {'%live',1}.
+ {label,16}.
+ {deallocate,1}.
+ return.
+
+
+{function, bad_5, 1, 18}.
+ {label,17}.
+ {func_info,{atom,bad_catch_try},{atom,bad_5},1}.
+ {label,18}.
+ {allocate_zero,1,1}.
+ {'try',{y,0},{f,19}}.
+ {call,1,{f,26}}.
+ {try_end,{y,0}}.
+ {move,{atom,ok},{x,0}}.
+ {jump,{f,20}}.
+ {label,19}.
+ {move,{x,0},{y,1}}.
+ {try_case,{y,1}}.
+ {test,is_ne_exact,{f,20},[{x,0},{atom,error}]}.
+ {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}.
+ {'%live',1}.
+ {label,20}.
+ {deallocate,1}.
+ return.
+
+
+{function, bad_6, 1, 22}.
+ {label,21}.
+ {func_info,{atom,bad_catch_try},{atom,bad_6},1}.
+ {label,22}.
+ {allocate_zero,1,1}.
+ {'try',{y,0},{f,23}}.
+ {call,1,{f,26}}.
+ {move,{integer,1},{y,1}}.
+ {try_end,{y,1}}.
+ {move,{atom,ok},{x,0}}.
+ {jump,{f,24}}.
+ {label,23}.
+ {try_case,{y,0}}.
+ {test,is_ne_exact,{f,24},[{x,0},{atom,error}]}.
+ {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}.
+ {'%live',1}.
+ {label,24}.
+ {deallocate,1}.
+ return.
+
+
+{function, foo, 1, 26}.
+ {label,25}.
+ {func_info,{atom,bad_catch_try},{atom,foo},1}.
+ {label,26}.
+ return.
+
+
+{function, module_info, 0, 28}.
+ {label,27}.
+ {func_info,{atom,bad_catch_try},{atom,module_info},0}.
+ {label,28}.
+ {move,{atom,bad_catch_try},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 30}.
+ {label,29}.
+ {func_info,{atom,bad_catch_try},{atom,module_info},1}.
+ {label,30}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,bad_catch_try},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/bad_dsetel.S b/lib/compiler/test/beam_validator_SUITE_data/bad_dsetel.S
new file mode 100644
index 0000000000..279b2fa97f
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/bad_dsetel.S
@@ -0,0 +1,52 @@
+{module, t}. %% version = 0
+
+{exports, [{module_info,0},{module_info,1},{t,1}]}.
+
+{attributes, []}.
+
+{labels, 8}.
+
+
+{function, t, 1, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,t},1}.
+ {label,2}.
+ {test,is_tuple,{f,3},[{x,0}]}.
+ {test,test_arity,{f,3},[{x,0},7]}.
+ {get_tuple_element,{x,0},0,{x,1}}.
+ {test,is_eq_exact,{f,3},[{x,1},{atom,r}]}.
+ {allocate,0,1}.
+ {move,{x,0},{x,1}}.
+ {move,{integer,1},{x,2}}.
+ {move,{integer,3},{x,0}}.
+ {call_ext,3,{extfunc,erlang,setelement,3}}.
+ {test_heap,6,1}.
+ {put_string,3,{string,"abc"},{x,1}}.
+ {set_tuple_element,{x,1},{x,0},1}.
+ {'%live',1}.
+ {deallocate,0}.
+ return.
+ {label,3}.
+ {test_heap,3,0}.
+ {put_tuple,2,{x,0}}.
+ {put,{atom,badrecord}}.
+ {put,{atom,r}}.
+ {'%live',1}.
+ {call_ext_only,1,{extfunc,erlang,error,1}}.
+
+
+{function, module_info, 0, 5}.
+ {label,4}.
+ {func_info,{atom,t},{atom,module_info},0}.
+ {label,5}.
+ {move,{atom,t},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 7}.
+ {label,6}.
+ {func_info,{atom,t},{atom,module_info},1}.
+ {label,7}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,t},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/bin_aligned.S b/lib/compiler/test/beam_validator_SUITE_data/bin_aligned.S
new file mode 100644
index 0000000000..2f353fbd25
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/bin_aligned.S
@@ -0,0 +1,47 @@
+{module, t}. %% version = 0
+
+{exports, [{decode,1},{module_info,0},{module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 7}.
+
+
+{function, decode, 1, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,decode},1}.
+ {label,2}.
+ {move,{integer,1},{x,1}}.
+ {bif,size,{f,0},[{x,0}],{x,2}}.
+ {bs_add,{f,0},[{x,1},{x,2},1],{x,1}}.
+ {bs_init2,{f,0},{x,1},0,1,{field_flags,[]},{x,1}}.
+ {bs_put_integer,{f,0},
+ {integer,3},
+ 1,
+ {field_flags,[aligned,unsigned,big]},
+ {integer,0}}.
+ {bs_put_binary,{f,0},{atom,all},8,{field_flags,[unsigned,big]},{x,0}}.
+ {bs_put_integer,{f,0},
+ {integer,5},
+ 1,
+ {field_flags,[unsigned,big,aligned]},
+ {integer,0}}.
+ {move,{x,1},{x,0}}.
+ return.
+
+
+{function, module_info, 0, 4}.
+ {label,3}.
+ {func_info,{atom,t},{atom,module_info},0}.
+ {label,4}.
+ {move,{atom,t},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 6}.
+ {label,5}.
+ {func_info,{atom,t},{atom,module_info},1}.
+ {label,6}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,t},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/bin_match.S b/lib/compiler/test/beam_validator_SUITE_data/bin_match.S
new file mode 100644
index 0000000000..96df0f7933
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/bin_match.S
@@ -0,0 +1,64 @@
+{module, bin_match}. %% version = 0
+
+{exports, [{t,1}]}.
+
+{attributes, []}.
+
+{labels, 8}.
+
+
+{function, t, 1, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,t},1}.
+ {label,2}.
+%% {test,bs_start_match,{f,1},[{x,0}]}.
+ {bs_save,0}.
+ {test,bs_get_integer,
+ {f,3},
+ [{integer,8},1,{field_flags,[aligned,unsigned,big]},{x,1}]}.
+ {test,bs_get_integer,
+ {f,3},
+ [{integer,8},1,{field_flags,[aligned,unsigned,big]},{x,2}]}.
+ {test,bs_test_tail,{f,3},[0]}.
+ {test_heap,3,3}.
+ {put_tuple,2,{x,0}}.
+ {put,{x,1}}.
+ {put,{x,2}}.
+ {'%live',1}.
+ return.
+ {label,3}.
+ {bs_restore,0}.
+ {test,bs_get_integer,
+ {f,1},
+ [{integer,32},1,{field_flags,[aligned,unsigned,big]},{x,1}]}.
+ {test,bs_test_tail,{f,1},[0]}.
+ {move,{x,1},{x,0}}.
+ return.
+
+{function, x, 1, 5}.
+ {label,4}.
+ {func_info,{atom,t},{atom,x},1}.
+ {label,5}.
+ {test,bs_start_match,{f,4},[{x,0}]}.
+ {bs_save,0}.
+ {test,bs_get_integer,
+ {f,6},
+ [{integer,8},1,{field_flags,[aligned,unsigned,big]},{x,1}]}.
+ {test,bs_get_integer,
+ {f,6},
+ [{integer,8},1,{field_flags,[aligned,unsigned,big]},{x,2}]}.
+ {test,bs_test_tail,{f,6},[0]}.
+ {test_heap,3,3}.
+ {put_tuple,2,{x,0}}.
+ {put,{x,1}}.
+ {put,{x,2}}.
+ {'%live',1}.
+ return.
+ {label,6}.
+ {bs_restore,1}.
+ {test,bs_get_integer,
+ {f,4},
+ [{integer,32},1,{field_flags,[aligned,unsigned,big]},{x,1}]}.
+ {test,bs_test_tail,{f,4},[0]}.
+ {move,{x,1},{x,0}}.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/call_last.S b/lib/compiler/test/beam_validator_SUITE_data/call_last.S
new file mode 100644
index 0000000000..827b6c0ae6
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/call_last.S
@@ -0,0 +1,71 @@
+{module, call_last}. %% version = 0
+
+{exports, [{a,1},{b,1},{bar,1},{foo,1},{module_info,0},{module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 13}.
+
+
+{function, a, 1, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,a},1}.
+ {label,2}.
+ {allocate,1,1}.
+ {move,{x,0},{y,0}}.
+ {bif,'+',{f,0},[{y,0},{integer,1}],{x,0}}.
+ {'%live',1}.
+ {call,1,{f,6}}.
+ {bif,'+',{f,0},[{y,0},{integer,2}],{x,0}}.
+ {'%live',1}.
+ {call_last,1,{f,8},2}.
+
+
+{function, b, 1, 4}.
+ {label,3}.
+ {func_info,{atom,t},{atom,b},1}.
+ {label,4}.
+ {allocate,1,1}.
+ {move,{x,0},{y,0}}.
+ {bif,'+',{f,0},[{y,0},{integer,1}],{x,0}}.
+ {'%live',1}.
+ {call,1,{f,6}}.
+ {move,{y,0},{x,1}}.
+ {move,{integer,0},{x,0}}.
+ {call_ext_last,2,{extfunc,lists,seq,2},2}.
+
+
+{function, foo, 1, 6}.
+ {label,5}.
+ {func_info,{atom,t},{atom,foo},1}.
+ {label,6}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,glurf},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,put,2}}.
+
+
+{function, bar, 1, 8}.
+ {label,7}.
+ {func_info,{atom,t},{atom,bar},1}.
+ {label,8}.
+ {bif,get,{f,0},[{atom,glurf}],{x,1}}.
+ {bif,'+',{f,0},[{x,0},{x,1}],{x,0}}.
+ {'%live',1}.
+ return.
+
+
+{function, module_info, 0, 10}.
+ {label,9}.
+ {func_info,{atom,t},{atom,module_info},0}.
+ {label,10}.
+ {move,{atom,t},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 12}.
+ {label,11}.
+ {func_info,{atom,t},{atom,module_info},1}.
+ {label,12}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,t},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/cons.S b/lib/compiler/test/beam_validator_SUITE_data/cons.S
new file mode 100644
index 0000000000..83b9daa6f5
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/cons.S
@@ -0,0 +1,38 @@
+{module, cons}. %% version = 0
+
+{exports, [{foo,1},{module_info,0},{module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 7}.
+
+
+{function, foo, 1, 2}.
+ {label,1}.
+ {func_info,{atom,cons},{atom,foo},1}.
+ {label,2}.
+% {test,is_nonempty_list,{f,1},[{x,0}]}.
+ {test_heap,3,1}.
+ {get_list,{x,0},{x,1},{x,2}}. % <= {bad_type,{needed,cons},{actual,term}}
+ {put_tuple,2,{x,0}}.
+ {put,{x,1}}.
+ {put,{x,2}}.
+ {'%live',1}.
+ return.
+
+
+{function, module_info, 0, 4}.
+ {label,3}.
+ {func_info,{atom,cons},{atom,module_info},0}.
+ {label,4}.
+ {move,{atom,cons},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 6}.
+ {label,5}.
+ {func_info,{atom,cons},{atom,module_info},1}.
+ {label,6}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,cons},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/dead_code.S b/lib/compiler/test/beam_validator_SUITE_data/dead_code.S
new file mode 100644
index 0000000000..f964f98fba
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/dead_code.S
@@ -0,0 +1,48 @@
+{module, dead_code}. %% version = 0
+
+{exports, [{execute,0},{module_info,0},{module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 10}.
+
+
+{function, execute, 0, 2}.
+ {label,1}.
+ {func_info,{atom,dead_code},{atom,execute},0}.
+ {label,2}.
+ {allocate,0,0}.
+ {'%live',0}.
+ {call_ext,0,{extfunc,foo,fie,0}}.
+ {test,is_ne,{f,4},[{x,0},{integer,0}]}.
+ {test,is_ne,{f,4},[{x,0},{integer,1}]}.
+ {label,3}.
+ {test,is_ne,{f,4},[{x,0},{integer,2}]}.
+ {test,is_ne,{f,4},[{x,0},{integer,3}]}.
+ {case_end,{x,0}}.
+ {label,4}.
+ {move,{atom,ok},{x,0}}.
+ {'%live',1}.
+ {deallocate,0}.
+ return.
+ {'%','Moved code'}.
+ {label,5}.
+ {case_end,{x,0}}.
+
+
+{function, module_info, 0, 7}.
+ {label,6}.
+ {func_info,{atom,dead_code},{atom,module_info},0}.
+ {label,7}.
+ {move,nil,{x,0}}.
+ {'%live',1}.
+ return.
+
+
+{function, module_info, 1, 9}.
+ {label,8}.
+ {func_info,{atom,dead_code},{atom,module_info},1}.
+ {label,9}.
+ {move,nil,{x,0}}.
+ {'%live',1}.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/erl_prim_loader.beam b/lib/compiler/test/beam_validator_SUITE_data/erl_prim_loader.beam
new file mode 100644
index 0000000000..dd58a88e42
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/erl_prim_loader.beam
Binary files differ
diff --git a/lib/compiler/test/beam_validator_SUITE_data/freg_range.S b/lib/compiler/test/beam_validator_SUITE_data/freg_range.S
new file mode 100644
index 0000000000..ee583a923e
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/freg_range.S
@@ -0,0 +1,53 @@
+{module, freg_range}. %% version = 0
+
+{exports, [{module_info,0},{module_info,1},{prod,2},{sum,2},{sum_prod,3}]}.
+
+{attributes, []}.
+
+{labels, 8}.
+
+
+{function, sum_1, 2, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,sum_1},2}.
+ {label,2}.
+ fclearerror.
+ {bif,fadd,{f,0},[{fr,-1},{fr,1}],{fr,0}}.
+ {'%live',1}.
+ return.
+
+
+{function, sum_2, 2, 4}.
+ {label,3}.
+ {func_info,{atom,t},{atom,sum_2},2}.
+ {label,4}.
+ {fconv,{x,0},{fr,0}}.
+ fclearerror.
+ {bif,fadd,{f,0},[{fr,0},{fr,1024}],{fr,0}}.
+ {'%live',1}.
+ return.
+
+
+{function, sum_3, 2, 6}.
+ {label,5}.
+ {func_info,{atom,t},{atom,sum_3},2}.
+ {label,6}.
+ {fconv,{x,0},{fr,0}}.
+ {fconv,{x,1},{fr,1}}.
+ fclearerror.
+ {bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}}.
+ {'%live',1}.
+ return.
+
+
+{function, sum_4, 2, 8}.
+ {label,7}.
+ {func_info,{atom,t},{atom,sum_4},2}.
+ {label,8}.
+ {fconv,{x,0},{fr,0}}.
+ {fconv,{x,1},{fr,1}}.
+ fclearerror.
+ {bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}}.
+ {'%live',1}.
+ return.
+
diff --git a/lib/compiler/test/beam_validator_SUITE_data/freg_state.S b/lib/compiler/test/beam_validator_SUITE_data/freg_state.S
new file mode 100644
index 0000000000..ff4d7548ae
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/freg_state.S
@@ -0,0 +1,59 @@
+{module, freg_state}. %% version = 0
+
+{exports, []}.
+
+{attributes, []}.
+
+
+{function, sum_1, 2, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,sum_1},2}.
+ {label,2}.
+ {fconv,{x,0},{fr,0}}.
+ {fconv,{x,1},{fr,1}}.
+ {bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}.
+ {'%live',1}.
+ return.
+
+{function, sum_2, 2, 4}.
+ {label,3}.
+ {func_info,{atom,t},{atom,sum_2},2}.
+ {label,4}.
+ {fconv,{x,0},{fr,0}}.
+ {fconv,{x,1},{fr,1}}.
+ fclearerror.
+ {bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}.
+ {fmove,{fr,0},{x,0}}.
+ {'%live',1}.
+ return.
+
+{function, sum_3, 2, 6}.
+ {label,5}.
+ {func_info,{atom,t},{atom,sum_3},2}.
+ {label,6}.
+ {fconv,{x,0},{fr,0}}.
+ {fconv,{x,1},{fr,1}}.
+ fclearerror.
+ {bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}.
+ {bif,'-',{f,0},[{x,1},{x,0}],{x,1}}.
+ {fcheckerror,{f,0}}.
+ {fmove,{fr,0},{x,0}}.
+ {'%live',1}.
+ return.
+
+{function, sum_4, 2, 8}.
+ {label,6}.
+ {func_info,{atom,t},{atom,sum_4},2}.
+ {label,8}.
+ {fcheckerror,{f,0}}.
+ {fmove,{fr,0},{x,0}}.
+ {'%live',1}.
+ return.
+
+{function, sum_5, 2, 10}.
+ {label,9}.
+ {func_info,{atom,t},{atom,sum_5},2}.
+ {label,10}.
+ fclearerror.
+ fclearerror.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/freg_uninit.S b/lib/compiler/test/beam_validator_SUITE_data/freg_uninit.S
new file mode 100644
index 0000000000..f8d805d9ec
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/freg_uninit.S
@@ -0,0 +1,32 @@
+{module, freg_uninit}. %% version = 0
+
+{exports, []}.
+
+{attributes, []}.
+
+{labels, 8}.
+
+
+{function, sum_1, 2, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,sum_1},2}.
+ {label,2}.
+ {fconv,{x,0},{fr,0}}.
+ fclearerror.
+ {bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}.
+ {'%live',1}.
+ return.
+
+
+{function, sum_2, 2, 4}.
+ {label,3}.
+ {func_info,{atom,t},{atom,sum_2},2}.
+ {label,4}.
+ {fconv,{x,0},{fr,0}}.
+ {fconv,{x,1},{fr,1}}.
+ fclearerror.
+ {fcheckerror,{f,0}}.
+ {call,2,{f,8}}.
+ {bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}.
+ {'%live',1}.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/illegal_instruction.S b/lib/compiler/test/beam_validator_SUITE_data/illegal_instruction.S
new file mode 100644
index 0000000000..d6e92abc71
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/illegal_instruction.S
@@ -0,0 +1,26 @@
+{module, illegal_instruction}. %% version = 0
+
+{exports, []}.
+
+{attributes, []}.
+
+{labels, 7}.
+
+
+{function, t, 1, 2}.
+ {label,1}.
+ {func_info,{atom,illegal_instruction},{atom,t},1}.
+ {label,2}.
+ {my_illegal_instruction,{x,0}}.
+ return.
+
+
+{function, x, 1, 4}.
+ {label,3}.
+ bad_func_info.
+ {label,4}.
+ {my_illegal_instruction,{x,0}}.
+ return.
+
+{function, y, 0, 17}.
+ \ No newline at end of file
diff --git a/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S b/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S
new file mode 100644
index 0000000000..3d76127824
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/merge_undefined.S
@@ -0,0 +1,84 @@
+{module, merge_undefined}. %% version = 0
+
+{exports, [{bar,2},{foo,1},{handle_call,2},{module_info,0},{module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 15}.
+
+
+{function, handle_call, 2, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,handle_call},2}.
+ {label,2}.
+ {test,is_atom,{f,1},[{x,0}]}.
+ {select_val,{x,0},{f,1},{list,[{atom,gurka},{f,3},{atom,delete},{f,4}]}}.
+ {label,3}.
+ {allocate_heap,2,6,2}.
+ %% The Y registers are not initialized here.
+ {test,is_eq_exact,{f,5},[{x,0},{atom,ok}]}.
+ {move,{atom,nisse},{x,0}}.
+ {call_ext,1,{extfunc,erlang,exit,1}}.
+ {label,4}.
+ {allocate_heap,1,6,2}.
+ {move,{x,1},{y,0}}.
+ {put_string,2,{string,"~p"},{x,0}}.
+ {put_list,{y,0},nil,{x,1}}.
+ {'%live',2}.
+ {call_ext,2,{extfunc,io,format,2}}.
+ {test,is_ne_exact,{f,6},[{x,0},{atom,ok}]}.
+ {label,5}.
+ {move,{atom,logReader},{x,1}}.
+ {move,{atom,console},{x,0}}.
+ {call_ext,2,{extfunc,debug,filter,2}}.
+ {test_heap,14,1}.
+ {put_list,{atom,logReader},nil,{x,1}}.
+ {put_list,{atom,console},{x,1},{x,1}}.
+ {put_tuple,3,{x,2}}.
+ {put,{atom,debug}}.
+ {put,{atom,filter}}.
+ {put,{x,1}}.
+ {put_tuple,2,{x,1}}.
+ {put,{x,2}}.
+ {put,{x,0}}.
+ {put_tuple,2,{x,0}}.
+ {put,{atom,badmatch}}.
+ {put,{x,1}}.
+ {'%live',1}.
+ {call_ext,1,{extfunc,erlang,exit,1}}.
+ {label,6}.
+ {move,{y,0},{x,0}}.
+ {call_last,1,{f,8},1}.
+
+
+{function, foo, 1, 8}.
+ {label,7}.
+ {func_info,{atom,t},{atom,foo},1}.
+ {label,8}.
+ {move,{atom,ok},{x,0}}.
+ return.
+
+
+{function, bar, 2, 10}.
+ {label,9}.
+ {func_info,{atom,t},{atom,bar},2}.
+ {label,10}.
+ {move,{atom,ok},{x,0}}.
+ return.
+
+
+{function, module_info, 0, 12}.
+ {label,11}.
+ {func_info,{atom,t},{atom,module_info},0}.
+ {label,12}.
+ {move,{atom,t},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 14}.
+ {label,13}.
+ {func_info,{atom,t},{atom,module_info},1}.
+ {label,14}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,t},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/no_exception_in_catch.S b/lib/compiler/test/beam_validator_SUITE_data/no_exception_in_catch.S
new file mode 100644
index 0000000000..e08a718a39
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/no_exception_in_catch.S
@@ -0,0 +1,209 @@
+{module, no_exception_in_catch}. %% version = 0
+
+{exports, [{foo,1},{module_info,0},{module_info,1},{nested_of_1,4}]}.
+
+{attributes, []}.
+
+{labels, 22}.
+
+
+{function, nested_of_1, 4, 2}.
+ {label,1}.
+ {func_info,{atom,no_exception_in_catch},{atom,nested_of_1},4}.
+ {label,2}.
+ {test,is_tuple,{f,1},[{x,0}]}.
+ {test,test_arity,{f,1},[{x,0},3]}.
+ {allocate_zero,15,4}.
+ {get_tuple_element,{x,0},0,{y,9}}.
+ {get_tuple_element,{x,0},1,{y,10}}.
+ {get_tuple_element,{x,0},2,{y,11}}.
+ {move,{x,3},{y,14}}.
+ {move,{x,2},{y,13}}.
+ {move,{x,1},{y,12}}.
+ {move,{atom,nested3},{x,0}}.
+ {call_ext,1,{extfunc,erlang,erase,1}}.
+ {move,{atom,nested4},{x,0}}.
+ {call_ext,1,{extfunc,erlang,erase,1}}.
+ {move,{atom,nested},{x,0}}.
+ {call_ext,1,{extfunc,erlang,erase,1}}.
+ {bif,self,nofail,[],{x,0}}.
+ {'try',{y,8},{f,13}}.
+ {'try',{y,7},{f,11}}.
+ {'try',{y,6},{f,9}}.
+ {'try',{y,5},{f,7}}.
+%% Because the following instructions can't possible throw an exception,
+%% label 7 used to get no state. Now the try_end itself will save the state.
+ {move,{x,0},{y,4}}.
+ {bif,self,nofail,[],{x,0}}.
+ {'%live',1}.
+ {try_end,{y,5}}.
+ {test,is_eq_exact,{f,15},[{x,0},{y,4}]}.
+ {'try',{y,5},{f,6}}.
+ {'try',{y,3},{f,3}}.
+ {move,{y,9},{x,0}}.
+ {call,1,{f,17}}.
+ {try_end,{y,3}}.
+ {test,is_eq_exact,{f,15},[{x,0},{y,11}]}.
+ {move,{y,12},{x,0}}.
+ {call,1,{f,17}}.
+ {test_heap,3,1}.
+ {put_tuple,2,{x,1}}.
+ {put,{atom,value1}}.
+ {put,{x,0}}.
+ {move,{x,1},{x,0}}.
+ {jump,{f,5}}.
+ {label,3}.
+ {try_case,{y,3}}.
+ {move,{x,1},{y,1}}.
+ {move,{x,0},{y,2}}.
+ {move,{x,2},{y,3}}.
+ {bif,'=:=',{f,4},[{x,0},{y,10}],{x,3}}.
+ {move,{x,3},{y,0}}.
+ {bif,'=:=',{f,4},[{x,1},{y,11}],{x,4}}.
+ {bif,'and',{f,4},[{x,3},{x,4}],{x,3}}.
+ {test,is_eq_exact,{f,4},[{x,3},{atom,true}]}.
+ {kill,{y,0}}.
+ {kill,{y,1}}.
+ {kill,{y,2}}.
+ {kill,{y,3}}.
+ {move,{y,12},{x,0}}.
+ {call,1,{f,17}}.
+ {test_heap,3,1}.
+ {put_tuple,2,{x,1}}.
+ {put,{atom,caught1}}.
+ {put,{x,0}}.
+ {move,{x,1},{x,0}}.
+ {jump,{f,5}}.
+ {label,4}.
+ {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}.
+ {'%live',1}.
+ {label,5}.
+ {try_end,{y,5}}.
+ {move,{x,0},{y,5}}.
+ {move,{y,13},{x,0}}.
+ {call,1,{f,17}}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,nested3},{x,0}}.
+ {call_ext,2,{extfunc,erlang,put,2}}.
+ {move,{y,5},{x,0}}.
+ {jump,{f,8}}.
+ {label,6}.
+ {try_case,{y,5}}.
+ {move,{x,2},{y,5}}.
+ {move,{x,1},{y,3}}.
+ {move,{y,13},{x,0}}.
+ {call,1,{f,17}}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,nested3},{x,0}}.
+ {call_ext,2,{extfunc,erlang,put,2}}.
+ {bif,raise,{f,0},[{y,5},{y,3}],{x,0}}.
+ {'%live',1}.
+ {jump,{f,8}}.
+ {label,7}.
+%% The instructions here used to be not checked.
+ {move,{x,3},{x,0}}.
+ {try_case,{y,5}}.
+ {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}.
+ {'%live',1}.
+ {label,8}.
+ {try_end,{y,6}}.
+ {move,{x,0},{y,13}}.
+ {kill,{y,3}}.
+ {kill,{y,4}}.
+ {kill,{y,5}}.
+ {kill,{y,9}}.
+ {kill,{y,10}}.
+ {kill,{y,11}}.
+ {kill,{y,12}}.
+ {move,{y,14},{x,0}}.
+ {call,1,{f,17}}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,nested4},{x,0}}.
+ {call_ext,2,{extfunc,erlang,put,2}}.
+ {move,{y,13},{x,0}}.
+ {jump,{f,10}}.
+ {label,9}.
+ {try_case,{y,6}}.
+ {move,{x,2},{y,13}}.
+ {move,{x,1},{y,12}}.
+ {kill,{y,3}}.
+ {kill,{y,4}}.
+ {kill,{y,5}}.
+ {kill,{y,9}}.
+ {kill,{y,10}}.
+ {kill,{y,11}}.
+ {move,{y,14},{x,0}}.
+ {call,1,{f,17}}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,nested4},{x,0}}.
+ {call_ext,2,{extfunc,erlang,put,2}}.
+ {bif,raise,{f,0},[{y,13},{y,12}],{x,0}}.
+ {'%live',1}.
+ {label,10}.
+ {try_end,{y,7}}.
+ {test_heap,3,1}.
+ {put_tuple,2,{x,1}}.
+ {put,{atom,value}}.
+ {put,{x,0}}.
+ {move,{x,1},{x,0}}.
+ {jump,{f,12}}.
+ {label,11}.
+ {try_case,{y,7}}.
+ {test_heap,6,3}.
+ {put_tuple,2,{x,3}}.
+ {put,{x,0}}.
+ {put,{x,1}}.
+ {put_tuple,2,{x,0}}.
+ {put,{atom,caught}}.
+ {put,{x,3}}.
+ {'%live',1}.
+ {label,12}.
+ {try_end,{y,8}}.
+ {move,{x,0},{y,14}}.
+ {move,{atom,finalized},{x,1}}.
+ {kill,{y,12}}.
+ {kill,{y,13}}.
+ {move,{atom,nested},{x,0}}.
+ {call_ext,2,{extfunc,erlang,put,2}}.
+ {move,{y,14},{x,0}}.
+ {jump,{f,14}}.
+ {label,13}.
+ {try_case,{y,8}}.
+ {move,{x,2},{y,14}}.
+ {move,{x,1},{y,13}}.
+ {move,{atom,finalized},{x,1}}.
+ {kill,{y,12}}.
+ {move,{atom,nested},{x,0}}.
+ {call_ext,2,{extfunc,erlang,put,2}}.
+ {bif,raise,{f,0},[{y,14},{y,13}],{x,0}}.
+ {'%live',1}.
+ {label,14}.
+ {move,{x,0},{y,14}}.
+ {kill,{y,13}}.
+ {move,{atom,nested3},{x,0}}.
+ {call_ext,1,{extfunc,erlang,erase,1}}.
+ {move,{x,0},{y,13}}.
+ {move,{atom,nested4},{x,0}}.
+ {call_ext,1,{extfunc,erlang,erase,1}}.
+ {move,{x,0},{y,12}}.
+ {move,{atom,nested},{x,0}}.
+ {call_ext,1,{extfunc,erlang,erase,1}}.
+ {test_heap,5,1}.
+ {put_tuple,4,{x,1}}.
+ {put,{y,14}}.
+ {put,{y,13}}.
+ {put,{y,12}}.
+ {put,{x,0}}.
+ {move,{x,1},{x,0}}.
+ {deallocate,15}.
+ return.
+ {label,15}.
+ {try_case_end,{x,0}}.
+
+
+{function, foo, 1, 17}.
+ {label,16}.
+ {func_info,{atom,no_exception_in_catch},{atom,foo},1}.
+ {label,17}.
+ {move,{atom,ok},{x,0}}.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/overwrite_catchtag.S b/lib/compiler/test/beam_validator_SUITE_data/overwrite_catchtag.S
new file mode 100644
index 0000000000..f6ad0ac50a
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/overwrite_catchtag.S
@@ -0,0 +1,38 @@
+{module, overwrite_catchtag}. %% version = 0
+
+{exports, [{foo,1},{module_info,0},{module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 8}.
+
+
+{function, foo, 1, 2}.
+ {label,1}.
+ {func_info,{atom,overwrite_catchtag},{atom,foo},1}.
+ {label,2}.
+ {allocate,1,1}.
+ {'catch',{y,0},{f,3}}.
+ {move,{x,0},{y,0}}. % <= {catchtag,3}
+ {call,1,{f,2}}.
+ {label,3}.
+ {catch_end,{y,0}}.
+ {deallocate,1}.
+ return.
+
+
+{function, module_info, 0, 5}.
+ {label,4}.
+ {func_info,{atom,overwrite_catchtag},{atom,module_info},0}.
+ {label,5}.
+ {move,{atom,overwrite_catchtag},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 7}.
+ {label,6}.
+ {func_info,{atom,overwrite_catchtag},{atom,module_info},1}.
+ {label,7}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,overwrite_catchtag},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/overwrite_trytag.S b/lib/compiler/test/beam_validator_SUITE_data/overwrite_trytag.S
new file mode 100644
index 0000000000..db552d5418
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/overwrite_trytag.S
@@ -0,0 +1,53 @@
+{module, overwrite_trytag}. %% version = 0
+
+{exports, [{foo,1},{module_info,0},{module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 9}.
+
+
+{function, foo, 1, 2}.
+ {label,1}.
+ {func_info,{atom,overwrite_trytag},{atom,foo},1}.
+ {label,2}.
+ {allocate_zero,3,1}.
+ {'try',{y,2},{f,3}}.
+ {move,{x,0},{y,1}}.
+ {'%live',1}.
+ {call,1,{f,2}}.
+ {kill,{y,2}}.
+ {try_end,{y,2}}.
+ {move,{x,0},{y,2}}.
+ {move,{y,1},{x,0}}.
+ {call,1,{f,2}}.
+ {move,{y,2},{x,0}}.
+ {jump,{f,4}}.
+ {label,3}.
+ {try_case,{y,2}}.
+ {move,{x,2},{y,2}}.
+ {move,{x,1},{y,0}}.
+ {move,{y,1},{x,0}}.
+ {call,1,{f,2}}.
+ {bif,raise,{f,0},[{y,2},{y,0}],{x,0}}.
+ {'%live',1}.
+ {label,4}.
+ {deallocate,3}.
+ return.
+
+
+{function, module_info, 0, 6}.
+ {label,5}.
+ {func_info,{atom,overwrite_trytag},{atom,module_info},0}.
+ {label,6}.
+ {move,{atom,overwrite_trytag},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 8}.
+ {label,7}.
+ {func_info,{atom,overwrite_trytag},{atom,module_info},1}.
+ {label,8}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,overwrite_trytag},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/stack.S b/lib/compiler/test/beam_validator_SUITE_data/stack.S
new file mode 100644
index 0000000000..244c22a2f9
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/stack.S
@@ -0,0 +1,89 @@
+{module, stack}. %% version = 0
+
+{exports, [{a,2},{b,2},{c,2},{d,2},{e,2}]}.
+
+{attributes, []}.
+
+{labels, 21}.
+
+
+{function, a, 2, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,a},2}.
+ {label,2}.
+ {allocate,2,2}.
+ {move,{x,1},{y,1}}.
+ {move,{x,0},{y,0}}.
+ {'%live',0}.
+ {call,0,{f,16}}.
+ {bif,'+',{f,0},[{y,0},{y,1}],{x,0}}.
+ {'%live',1}.
+ return.
+
+
+{function, b, 2, 4}.
+ {label,3}.
+ {func_info,{atom,t},{atom,b},2}.
+ {label,4}.
+ {deallocate,2}.
+ return.
+
+
+{function, c, 2, 6}.
+ {label,5}.
+ {func_info,{atom,t},{atom,c},2}.
+ {label,6}.
+ {allocate,2,2}.
+ {move,{x,1},{y,1}}.
+ {move,{x,0},{y,0}}.
+ {'%live',0}.
+ {call,0,{f,16}}.
+ {bif,'+',{f,0},[{y,0},{y,1}],{x,0}}.
+ {'%live',1}.
+ {deallocate,2}.
+ {deallocate,2}.
+ return.
+
+
+{function, d, 2, 8}.
+ {label,7}.
+ {func_info,{atom,t},{atom,d},2}.
+ {label,8}.
+ {allocate,2,2}.
+ {allocate,2,2}.
+ {deallocate,2}.
+ return.
+
+{function, e, 2, 14}.
+ {label,13}.
+ {func_info,{atom,t},{atom,e},2}.
+ {label,14}.
+ {allocate,2,2}.
+ {move,{atom,ok},{x,0}}.
+ {deallocate,5}.
+ return.
+
+
+{function, bad_1, 0, 10}.
+ {label,9}.
+ {func_info,{atom,t},{atom,bad_1},0}.
+ {label,10}.
+ {allocate_zero,2,10}.
+ {move,{y,0},{x,0}}.
+ return.
+
+
+{function, bad_2, 0, 12}.
+ {label,11}.
+ {func_info,{atom,t},{atom,bad_2},0}.
+ {label,12}.
+ {allocate_zero,2,0}.
+ {move,{y,0},{x,0}}.
+ return.
+
+{function, foo, 0, 16}.
+ {label,15}.
+ {func_info,{atom,t},{atom,foo},0}.
+ {label,16}.
+ {move,{atom,ok},{x,0}}.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/state_after_fault_in_catch.S b/lib/compiler/test/beam_validator_SUITE_data/state_after_fault_in_catch.S
new file mode 100644
index 0000000000..8e27347ed5
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/state_after_fault_in_catch.S
@@ -0,0 +1,58 @@
+{module, state_after_fault_in_catch}. %% version = 0
+
+{exports, [{foo,1},{if_end,1},{case_end,1},{badmatch,1}]}.
+
+{attributes, []}.
+
+{labels, 12}.
+
+
+{function, foo, 1, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,foo},1}.
+ {label,2}.
+ {allocate,1,0}.
+ {'catch',{y,0},{f,3}}.
+ {move,{atom,apa},{x,0}}.
+ {call_ext,1,{extfunc,erlang,fault,1}}.
+ {label,3}.
+ {catch_end,{y,0}}.
+ {move,{x,1},{x,0}}.
+ return.
+
+{function, if_end, 1, 5}.
+ {label,4}.
+ {func_info,{atom,state_after_fault_in_catch},{atom,if_end},1}.
+ {label,5}.
+ {allocate,1,0}.
+ {'catch',{y,0},{f,6}}.
+ if_end.
+ {label,6}.
+ {catch_end,{y,0}}.
+ {move,{x,1},{x,0}}.
+ return.
+
+{function, case_end, 1, 8}.
+ {label,7}.
+ {func_info,{atom,state_after_fault_in_catch},{atom,case_end},1}.
+ {label,8}.
+ {allocate,1,1}.
+ {'catch',{y,0},{f,9}}.
+ {case_end,{x,0}}.
+ {label,9}.
+ {catch_end,{y,0}}.
+ {move,{x,1},{x,0}}.
+ return.
+
+{function, badmatch, 1, 11}.
+ {label,10}.
+ {func_info,{atom,state_after_fault_in_catch},{atom,badmatch},1}.
+ {label,11}.
+ {allocate,1,1}.
+ {'catch',{y,0},{f,12}}.
+ {badmatch,{x,0}}.
+ {label,12}.
+ {catch_end,{y,0}}.
+ {move,{x,1},{x,0}}.
+ return.
+
diff --git a/lib/compiler/test/beam_validator_SUITE_data/undef_label.S b/lib/compiler/test/beam_validator_SUITE_data/undef_label.S
new file mode 100644
index 0000000000..dd29066bf4
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/undef_label.S
@@ -0,0 +1,22 @@
+{module, undef_label}. %% version = 0
+
+{exports, []}.
+
+{attributes, []}.
+
+{labels, 7}.
+
+
+{function, t, 1, 2}.
+ {label,1}.
+ {func_info,{atom,undef_label},{atom,t},1}.
+ {label,2}.
+ {test,is_eq_exact,{f,42},[{x,0},{atom,x}]}.
+ {move,{atom,ok},{x,0}}.
+ return.
+
+{function, x, 1, 17}.
+ {label,3}.
+ {func_info,{atom,undef_label},{atom,x},1}.
+ {label,4}.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/uninit.S b/lib/compiler/test/beam_validator_SUITE_data/uninit.S
new file mode 100644
index 0000000000..1a45c31411
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/uninit.S
@@ -0,0 +1,48 @@
+{module, uninit}. %% version = 0
+
+{exports, []}.
+
+{attributes, []}.
+
+{function, sum_1, 2, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,sum_1},2}.
+ {label,2}.
+ {allocate,1,2}.
+ {move,{y,0},{x,0}}.
+ {'%live',1}.
+ {call,1,{f,10}}.
+ {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}.
+ {'%live',1}.
+ {deallocate,1}.
+ return.
+
+{function, sum_2, 2, 4}.
+ {label,3}.
+ {func_info,{atom,t},{atom,sum_2},2}.
+ {label,4}.
+ {allocate,1,2}.
+ {'%live',1}.
+ {call,1,{f,10}}.
+ {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}.
+ {'%live',1}.
+ {deallocate,1}.
+ return.
+
+{function, sum_3, 2, 6}.
+ {label,5}.
+ {func_info,{atom,t},{atom,sum_3},2}.
+ {label,6}.
+ {allocate_zero,1,2}.
+ {'%live',1}.
+ {call,1,{f,10}}.
+ {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}.
+ {'%live',1}.
+ {deallocate,1}.
+ return.
+
+{function, id, 1, 10}.
+ {label,9}.
+ {func_info,{atom,t},{atom,id},1}.
+ {label,10}.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/unsafe_catch.S b/lib/compiler/test/beam_validator_SUITE_data/unsafe_catch.S
new file mode 100644
index 0000000000..500ac11377
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/unsafe_catch.S
@@ -0,0 +1,67 @@
+{module, unsafe_catch}. %% version = 0
+
+{exports, [{small,2}]}.
+
+{attributes, []}.
+
+{labels, 14}.
+
+
+{function, small, 2, 5}.
+ {label,4}.
+ {func_info,{atom,t},{atom,small},2}.
+ {label,5}.
+ {allocate_zero,2,2}.
+ {'catch',{y,1},{f,6}}.
+ {bs_init2,{f,0},1,0,2,{field_flags,[]},{x,2}}.
+ {bs_put_integer,{f,0},
+ {integer,8},
+ 1,
+ {field_flags,[aligned,unsigned,big]},
+ {x,0}}.
+ {move,{x,1},{y,0}}.
+ {move,{x,2},{x,0}}.
+ {label,6}.
+ {catch_end,{y,1}}.
+ {test,is_tuple,{f,7},[{x,0}]}.
+ {test,test_arity,{f,7},[{x,0},2]}.
+ {get_tuple_element,{x,0},0,{x,1}}.
+ {test,is_eq_exact,{f,7},[{x,1},{atom,'EXIT'}]}.
+ {bs_init2,{f,0},0,0,0,{field_flags,[]},{x,0}}.
+ {label,7}.
+ {'catch',{y,1},{f,8}}.
+ {bs_init2,{f,0},2,0,1,{field_flags,[]},{x,1}}.
+ {bs_put_integer,{f,0},
+ {integer,16},
+ 1,
+ {field_flags,[aligned,unsigned,big]},
+ {y,0}}.
+ {move,{x,0},{y,0}}.
+ {move,{x,1},{x,0}}.
+ {label,8}.
+ {catch_end,{y,1}}.
+ {test,is_tuple,{f,9},[{x,0}]}.
+ {test,test_arity,{f,9},[{x,0},2]}.
+ {get_tuple_element,{x,0},0,{x,1}}.
+ {test,is_eq_exact,{f,9},[{x,1},{atom,'EXIT'}]}.
+ {bs_init2,{f,0},0,0,0,{field_flags,[]},{x,0}}.
+ {label,9}.
+ {move,{integer,0},{x,1}}.
+ {bif,size,{f,0},[{x,0}],{x,2}}.
+ {bs_add,{f,0},[{x,1},{x,2},1],{x,1}}.
+ {bif,size,{f,0},[{y,0}],{x,2}}.
+ {bs_add,{f,0},[{x,1},{x,2},1],{x,1}}.
+ {bs_init2,{f,0},{x,1},0,2,{field_flags,[]},{x,1}}.
+ {bs_put_binary,{f,0},
+ {atom,all},
+ 8,
+ {field_flags,[aligned,unsigned,big]},
+ {y,0}}.
+ {bs_put_binary,{f,0},
+ {atom,all},
+ 8,
+ {field_flags,[aligned,unsigned,big]},
+ {x,0}}.
+ {move,{x,1},{x,0}}.
+ {deallocate,2}.
+ return.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/xrange.S b/lib/compiler/test/beam_validator_SUITE_data/xrange.S
new file mode 100644
index 0000000000..3abbdffbc2
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/xrange.S
@@ -0,0 +1,44 @@
+{module, xrange}. %% version = 0
+
+{exports, [{module_info,0},{module_info,1},{prod,2},{sum,2},{sum_prod,3}]}.
+
+{attributes, []}.
+
+{labels, 8}.
+
+
+{function, sum_1, 2, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,sum_1},2}.
+ {label,2}.
+ {bif,'+',{f,0},[{x,-1},{x,1}],{x,0}}.
+ {'%live',1}.
+ return.
+
+
+{function, sum_2, 2, 4}.
+ {label,3}.
+ {func_info,{atom,t},{atom,sum_2},2}.
+ {label,4}.
+ {bif,'+',{f,0},[{x,0},{x,1024}],{x,0}}.
+ {'%live',1}.
+ return.
+
+
+{function, sum_3, 2, 6}.
+ {label,5}.
+ {func_info,{atom,t},{atom,sum_3},2}.
+ {label,6}.
+ {bif,'+',{f,0},[{x,0},{x,1}],{x,-1}}.
+ {'%live',1}.
+ return.
+
+
+{function, sum_4, 2, 8}.
+ {label,7}.
+ {func_info,{atom,t},{atom,sum_4},2}.
+ {label,8}.
+ {bif,'+',{f,0},[{x,0},{x,1}],{x,1024}}.
+ {'%live',1}.
+ return.
+
diff --git a/lib/compiler/test/beam_validator_SUITE_data/yrange.S b/lib/compiler/test/beam_validator_SUITE_data/yrange.S
new file mode 100644
index 0000000000..483b14ebd3
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/yrange.S
@@ -0,0 +1,76 @@
+{module, yrange}. %% version = 0
+
+{exports, [{id,1},
+ {module_info,0},
+ {module_info,1},
+ {sum_1,2},
+ {sum_2,2},
+ {sum_3,2},
+ {sum_4,2}]}.
+
+{attributes, []}.
+
+{labels, 15}.
+
+
+{function, sum_1, 2, 2}.
+ {label,1}.
+ {func_info,{atom,t},{atom,sum_1},2}.
+ {label,2}.
+ {allocate,1,2}.
+ {move,{x,1},{y,-1}}.
+ {'%live',1}.
+ {call,1,{f,10}}.
+ {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}.
+ {'%live',1}.
+ {deallocate,1}.
+ return.
+
+
+{function, sum_2, 2, 4}.
+ {label,3}.
+ {func_info,{atom,t},{atom,sum_2},2}.
+ {label,4}.
+ {allocate,1,2}.
+ {move,{x,1},{y,0}}.
+ {'%live',1}.
+ {call,1,{f,10}}.
+ {bif,'+',{f,0},[{x,0},{y,1024}],{x,0}}.
+ {'%live',1}.
+ {deallocate,1}.
+ return.
+
+
+{function, sum_3, 2, 6}.
+ {label,5}.
+ {func_info,{atom,t},{atom,sum_3},2}.
+ {label,6}.
+ {allocate,1,2}.
+ {move,{x,1},{y,1024}}.
+ {'%live',1}.
+ {call,1,{f,10}}.
+ {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}.
+ {'%live',1}.
+ {deallocate,1}.
+ return.
+
+
+{function, sum_4, 2, 8}.
+ {label,7}.
+ {func_info,{atom,t},{atom,sum_4},2}.
+ {label,8}.
+ {allocate,1,2}.
+ {move,{x,1},{y,-1}}.
+ {'%live',1}.
+ {call,1,{f,10}}.
+ {bif,'+',{f,0},[{x,0},{y,0}],{x,0}}.
+ {'%live',1}.
+ {deallocate,1}.
+ return.
+
+
+{function, id, 1, 10}.
+ {label,9}.
+ {func_info,{atom,t},{atom,id},1}.
+ {label,10}.
+ return.
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
new file mode 100644
index 0000000000..a64a5d590b
--- /dev/null
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -0,0 +1,297 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Originally based on Per Gustafsson's test suite.
+%%
+
+-module(bs_bincomp_SUITE).
+
+-export([all/1,
+ byte_aligned/1,bit_aligned/1,extended_byte_aligned/1,
+ extended_bit_aligned/1,mixed/1,filters/1,trim_coverage/1,
+ nomatch/1,sizes/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [byte_aligned,bit_aligned,extended_byte_aligned,
+ extended_bit_aligned,mixed,filters,trim_coverage,
+ nomatch,sizes].
+
+
+byte_aligned(Config) when is_list(Config) ->
+ cs_init(),
+ ?line <<"abcdefg">> = cs(<< <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>),
+ <<1:32/little,2:32/little,3:32/little,4:32/little>> =
+ cs(<< <<X:32/little>> || <<X:32>> <= <<1:32,2:32,3:32,4:32>> >>),
+ ?line cs(<<1:32/little,2:32/little,3:32/little,4:32/little>> =
+ << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>),
+ cs_end().
+
+bit_aligned(Config) when is_list(Config) ->
+ cs_init(),
+ ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
+ cs(<< <<(X+32):7>> || <<X>> <= <<"ABCDEFG">> >>),
+ ?line <<"ABCDEFG">> =
+ cs(<< <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> >>),
+ ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> =
+ cs(<< <<X:31/little>> || <<X:31>> <= <<1:31,2:31,3:31,4:31>> >>),
+ ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> =
+ cs(<< <<X:31/little>> || <<X:15>> <= <<1:15,2:15,3:15,4:15>> >>),
+ cs_end().
+
+extended_byte_aligned(Config) when is_list(Config) ->
+ cs_init(),
+ ?line <<"abcdefg">> = cs(<< <<(X+32)>> || X <- "ABCDEFG" >>),
+ ?line "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>],
+ ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> =
+ cs(<< <<X:32/little>> || X <- [1,2,3,4] >>),
+ ?line [256,512,768,1024] =
+ [X || <<X:16/little>> <= <<1:16,2:16,3:16,4:16>>],
+ cs_end().
+
+extended_bit_aligned(Config) when is_list(Config) ->
+ cs_init(),
+ ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
+ cs(<< <<(X+32):7>> || X <- "ABCDEFG" >>),
+ ?line "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>],
+ ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> =
+ cs(<< <<X:31/little>> || X <- [1,2,3,4] >>),
+ ?line [256,512,768,1024] =
+ [X || <<X:15/little>> <= <<1:15,2:15,3:15,4:15>>],
+ cs_end().
+
+mixed(Config) when is_list(Config) ->
+ cs_init(),
+ ?line <<2,3,3,4,4,5,5,6>> =
+ cs(<< <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>> >>),
+ ?line <<2,3,3,4,4,5,5,6>> =
+ << <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, Y <- [1,2] >>,
+ ?line <<2,3,3,4,4,5,5,6>> =
+ cs(<< <<(X+Y)>> || X <- [1,2,3,4], Y <- [1,2] >>),
+ One = id([1,2,3,4]),
+ Two = id([1,2]),
+ ?line <<2,3,3,4,4,5,5,6>> =
+ cs(<< <<(X+Y)>> || X <- One, Y <- Two >>),
+ ?line [2,3,3,4,4,5,5,6] =
+ [(X+Y) || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>>],
+ ?line [2,3,3,4,4,5,5,6] =
+ [(X+Y) || <<X>> <= <<1,2,3,4>>, Y <- [1,2]],
+ ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>,
+ <<Y:3>> <= <<1:3,2:3>> >>),
+ ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2] >>),
+ ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ cs(<< <<(X+Y):3>> || X <- [1,2,3,4], Y <- [1,2] >>),
+ ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ cs_default(<< <<(X+Y):3>> || {X,Y} <- [{1,1},{1,2},{2,1},{2,2},
+ {3,1},{3,2},{4,1},{4,2}] >>),
+ ?line [2,3,3,4,4,5,5,6] =
+ [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>>],
+ ?line [2,3,3,4,4,5,5,6] =
+ [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, {_,Y} <- [{a,1},{b,2}]],
+ cs_end().
+
+filters(Config) when is_list(Config) ->
+ cs_init(),
+ ?line <<"BDF">> =
+ cs_default(<< <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>,
+ X rem 2 == 0>>),
+ ?line <<"abc">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG",
+ is_less_than(X, $D)>>),
+ ?line <<"efg">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG",
+ not is_less_than(X, $E)>>),
+ ?line <<"b">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG",
+ is_less_than(X, $D),
+ X rem 2 == 0>>),
+ ?line <<"eg">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG",
+ not is_less_than(X, $E),
+ X rem 2 == 1>>),
+
+ %% Filtering by a non-matching pattern.
+ ?line <<"abd">> = cs_default(<< <<X:8>> ||
+ <<0:1,X:7>> <= <<$a:8,$b:8,1:1,$c:7,$d:8,
+ 1:1,$e:7,0:4>> >>),
+
+ ?line <<42,42>> = cs_default(<< <<42:8>> ||
+ 42 <- [1,2,3,42,43,42] >>),
+ cs_end().
+
+is_less_than(X, C) when X < C -> true;
+is_less_than(_, _) -> false.
+
+trim_coverage(Config) when is_list(Config) ->
+ ?line <<0,0,0,2,0,0,5,48,0,11,219,174,0,0,0,0>> = coverage_materialiv(a, b, {1328,777134}),
+ ?line <<67,40,0,0,66,152,0,0,69,66,64,0>> = coverage_trimmer([42,19,777]),
+ ?line <<0,0,2,43,0,0,3,9,0,0,0,3,64,8,0,0,0,0,0,0,
+ 64,68,0,0,0,0,0,0,192,171,198,0,0,0,0,0>> =
+ coverage_lightfv(555, 777, {3.0,40.0,-3555.0}),
+ ok.
+
+coverage_materialiv(A, B, Params) ->
+ A = id(A),
+ B = id(B),
+ <<(tuple_size(Params)):32,
+ (<< <<C:32>> || C <- tuple_to_list(Params)>>)/binary,
+ 0:(((1+tuple_size(Params)) rem 2)*32)>>.
+
+coverage_lightfv(Light, Pname, Params) ->
+ id(<<Light:32,Pname:32,(size(Params)):32,
+ (<< <<C:64/float>> || C <- tuple_to_list(Params)>>)/binary,
+ 0:(((1+size(Params)) rem 2)*32)>>).
+
+coverage_trimmer(Params) ->
+ X = id(0),
+ Y = id(1),
+ id({X,Y}),
+ << <<(begin {A,B,D} = id({C,C,C}), id(0),
+ coverage_summer(A, B, C, D) end):32/float>> ||
+ C <- Params >>.
+
+coverage_summer(A, B, C, D) -> A+B+C+D.
+
+nomatch(Config) when is_list(Config) ->
+ ?line <<>> = << <<X:8>> || X = {_,_} = [_|_] <- [1,2,3] >>,
+ ok.
+
+sizes(Config) when is_list(Config) ->
+ ?line cs_init(),
+ Fun0 = fun(List) ->
+ cs(<< <<E:8>> || E <- List >>)
+ end,
+ ?line <<>> = Fun0([]),
+ ?line <<1>> = Fun0([1]),
+ ?line <<1,2>> = Fun0([1,2]),
+ ?line <<1,2,3>> = Fun0([1,2,3]),
+
+ Fun1 = fun(List) ->
+ cs(<< <<E:16>> || E <- List >>)
+ end,
+ ?line <<>> = Fun1([]),
+ ?line <<1:16>> = Fun1([1]),
+ ?line <<1:16,2:16>> = Fun1([1,2]),
+ ?line <<1:16,2:16,3:16>> = Fun1([1,2,3]),
+
+ Fun2 = fun(List) ->
+ cs(<< <<E:4>> || E <- List >>)
+ end,
+ ?line <<>> = Fun2([]),
+ ?line <<1:4>> = Fun2([1]),
+ ?line <<1:4,13:4>> = Fun2([1,13]),
+ ?line <<1:4,13:4,7:4>> = Fun2([1,13,7]),
+ ?line <<0:1000/unit:8>> = Fun2(lists:duplicate(2000, 0)),
+
+ Fun3 = fun(List) ->
+ cs(<< <<E:3>> || E <- List >>)
+ end,
+ ?line <<>> = Fun3([]),
+ ?line <<40,177,29:5>> = Fun3([1,2,1,3,0,7,5]),
+ ?line <<0:512/unit:3>> = Fun3(lists:duplicate(512, 0)),
+
+ Fun4 = fun(List, Size) ->
+ cs(<< <<E:Size>> || E <- List >>)
+ end,
+ ?line <<>> = Fun4([], 8),
+ ?line <<42:6>> = Fun4([42], 6),
+ ?line <<42:16>> = Fun4([42], 16),
+
+ Fun5 = fun(List, Sz1, Sz2, Sz3) ->
+ cs(<< <<E:Sz1,(E+1):Sz2/unit:8,(E+2):Sz3/unit:8>> || E <- List >>)
+ end,
+ ?line <<>> = Fun5([], 1, 1, 1),
+ ?line <<7:3,8:40,9:56>> = Fun5([7], 3, 5, 7),
+
+ Fun6 = fun(List, Size) ->
+ cs(<< <<E:8,(E+1):Size>> || E <- List >>)
+ end,
+ ?line <<>> = Fun6([], 42),
+ ?line <<42,43:20>> = Fun6([42], 20),
+
+ %% Binary generators.
+
+ Fun10 = fun(Bin) ->
+ cs(<< <<E:16>> || <<E:8>> <= Bin >>)
+ end,
+ ?line <<>> = Fun10(<<>>),
+ ?line <<1:16>> = Fun10(<<1>>),
+ ?line <<1:16,2:16>> = Fun10(<<1,2>>),
+
+ Fun11 = fun(Bin) ->
+ cs(<< <<E:8>> || <<E:16>> <= Bin >>)
+ end,
+ ?line <<>> = Fun11(<<>>),
+ ?line <<1>> = Fun11(<<1:16>>),
+ ?line <<1,2>> = Fun11(<<1:16,2:16>>),
+ ?line <<1,2>> = Fun11(<<1:16,2:16,0:1>>),
+ ?line <<1,2>> = Fun11(<<1:16,2:16,0:7>>),
+ ?line <<1,2>> = Fun11(<<1:16,2:16,42:8>>),
+ ?line <<1,2>> = Fun11(<<1:16,2:16,42:9>>),
+ ?line <<1,2>> = Fun11(<<1:16,2:16,255:15>>),
+
+ Fun12 = fun(Bin, Sz1, Sz2) ->
+ cs(<< <<E:Sz1>> || <<E:Sz2>> <= Bin >>)
+ end,
+ ?line <<>> = Fun12(<<>>, 1, 1),
+ ?line Binary = list_to_binary(lists:seq(0, 255)),
+ ?line Binary = Fun12(Binary, 1, 1),
+ ?line Binary = Fun12(Binary, 4, 4),
+ ?line Binary = Fun12(Binary, 8, 8),
+ ?line <<17:9,19:9>> = Fun12(<<17:6,19:6>>, 9, 6),
+
+ Fun13 = fun(Sz) ->
+ cs_default(<< <<C:8>> || <<C:4>> <= <<1:4,2:4,3:4,0:Sz>> >>)
+ end,
+ ?line <<1,2,3>> = Fun13(0),
+ ?line <<1,2,3,0>> = Fun13(4),
+ ?line <<1,2,3,0>> = Fun13(5),
+ ?line <<1,2,3,0>> = Fun13(6),
+ ?line <<1,2,3,0>> = Fun13(7),
+ ?line <<1,2,3,0,0>> = Fun13(8),
+
+ ?line {'EXIT',_} = (catch << <<C:4>> || <<C:8>> <= {1,2,3} >>),
+
+ ?line cs_end(),
+ ok.
+
+
+
+cs_init() ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ ok.
+
+cs_end() ->
+ erts_debug:set_internal_state(available_internal_state, false),
+ ok.
+
+%% Verify that the allocated size is exact (rounded up to the nearest byte).
+cs(Bin) ->
+ ByteSize = byte_size(Bin),
+ {refc_binary,ByteSize,{binary,ByteSize},_} =
+ erts_debug:get_internal_state({binary_info,Bin}),
+ Bin.
+
+%% Verify that the allocated size of the binary is the default size.
+cs_default(Bin) ->
+ ByteSize = byte_size(Bin),
+ {refc_binary,ByteSize,{binary,256},_} =
+ erts_debug:get_internal_state({binary_info,Bin}),
+ Bin.
+
+id(I) -> I.
diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl
new file mode 100644
index 0000000000..6337460b13
--- /dev/null
+++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl
@@ -0,0 +1,155 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Originally based on Per Gustafsson's test suite.
+%%
+
+-module(bs_bit_binaries_SUITE).
+
+-export([all/1,
+ misc/1,horrid_match/1,test_bitstr/1,test_bit_size/1,asymmetric_tests/1,
+ big_asymmetric_tests/1,binary_to_and_from_list/1,
+ big_binary_to_and_from_list/1,send_and_receive/1,
+ send_and_receive_alot/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [misc,horrid_match,test_bitstr,test_bit_size,asymmetric_tests,
+ big_asymmetric_tests,binary_to_and_from_list,big_binary_to_and_from_list,
+ send_and_receive,send_and_receive_alot].
+
+misc(Config) when is_list(Config) ->
+ ?line <<1:100>> = <<1:100>>,
+ ?line {ok,ok} = {match(7),match(9)},
+ ?line {ok,ok} = {match1(15),match1(31)},
+ ok.
+
+
+match(N) ->
+ <<0:N>> = <<0:N>>,
+ ok.
+
+match1(N) ->
+ <<42:N/little>> = <<42:N/little>>,
+ ok.
+
+test_bit_size(Config) when is_list(Config) ->
+ ?line 101 = erlang:bit_size(<<1:101>>),
+ ?line 1001 = erlang:bit_size(<<1:1001>>),
+ ?line 1001 = erlang:bit_size(<<-10:1001>>),
+ ?line 80 = erlang:bit_size(<<1:80>>),
+ ?line 800 = erlang:bit_size(<<1:800>>),
+ ?line Bin = <<0:16#1000000>>,
+ ?line BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
+ ?line 16#10000001 = erlang:bit_size(BigBin),
+ %% Only run these on computers with lots of memory
+ %% HugeBin = list_to_bitstring([BigBin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
+ %% 16#100000011 = erlang:bit_size(HugeBin),
+ ?line 0 = erlang:bit_size(<<>>),
+ ok.
+
+horrid_match(Config) when is_list(Config) ->
+ ?line <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>,
+ ?line <<42:24/little>> = B,
+ ok.
+
+test_bitstr(Config) when is_list(Config) ->
+ ?line <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>,
+ ?line <<1:1,6>> = B,
+ ?line B = <<1:1,6>>,
+ ok.
+
+asymmetric_tests(Config) when is_list(Config) ->
+ ?line <<1:12>> = <<0,1:4>>,
+ ?line <<0,1:4>> = <<1:12>>,
+ ?line <<1:1,X/bitstring>> = <<128,255,0,0:2>>,
+ ?line <<1,254,0,0:1>> = X,
+ ?line X = <<1,254,0,0:1>>,
+ ?line <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>,
+ ?line <<1,254,0,0:1>> = X1,
+ ?line X1 = <<1,254,0,0:1>>,
+ ok.
+
+big_asymmetric_tests(Config) when is_list(Config) ->
+ ?line <<1:875,1:12>> = <<1:875,0,1:4>>,
+ ?line <<1:875,0,1:4>> = <<1:875,1:12>>,
+ ?line <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>,
+ ?line <<1,254,0,0:1,1:875>> = X,
+ ?line X = <<1,254,0,0:1,1:875>>,
+ ?line <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>,
+ ?line <<1,254,0,0:1,1:875>> = X1,
+ ?line X1 = <<1,254,0,0:1,1:875>>,
+ ok.
+
+binary_to_and_from_list(Config) when is_list(Config) ->
+ ?line <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)),
+ ?line [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>),
+ ?line <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]),
+ ?line [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>),
+ ok.
+
+big_binary_to_and_from_list(Config) when is_list(Config) ->
+ ?line <<1:800,2,3,4,1:1>> =
+ list_to_bitstring(bitstring_to_list(<<1:800,2,3,4,1:1>>)),
+ ?line [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>),
+ ?line <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]),
+ ok.
+
+send_and_receive(Config) when is_list(Config) ->
+ ?line Bin = <<1,2:7>>,
+ Pid = spawn_link(fun() -> receiver(Bin) end),
+ ?line Pid ! {self(),<<1:7,8:5,Bin/bitstring>>},
+ ?line receive
+ ok ->
+ ok
+ end.
+
+receiver(Bin) ->
+ receive
+ {Pid,<<1:7,8:5,Bin/bitstring>>} ->
+ Pid ! ok
+ end.
+
+send_and_receive_alot(Config) when is_list(Config) ->
+ Bin = <<1:1000001>>,
+ Pid = spawn_link(fun() -> receiver_alot(Bin) end),
+ spamalot(100,Bin,Pid).
+
+spamalot(N,Bin,Pid) when N > 0 ->
+ Pid ! {self(),<<1:7,8:5,Bin/bitstring>>},
+ receive
+ ok ->
+ ok
+ end,
+ spamalot(N-1,Bin,Pid);
+spamalot(0,_Bin,Pid) ->
+ Pid ! no_more,
+ ok.
+
+receiver_alot(Bin) ->
+ receive
+ {Pid,<<1:7,8:5,Bin/bitstring>>} ->
+ Pid ! ok;
+ no_more -> ok
+ end,
+ receiver_alot(Bin).
+
+
+
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
new file mode 100644
index 0000000000..1862a28bbe
--- /dev/null
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -0,0 +1,499 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%% While similar to bs_construct_SUITE in the emulator test suite,
+%%% this module is more corncerned with testing sizes than the contents
+%%% of binaries.
+
+-module(bs_construct_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ two/1,test1/1,fail/1,float_bin/1,in_guard/1,in_catch/1,
+ nasty_literals/1,coerce_to_float/1,side_effect/1,
+ opt/1,otp_7556/1,float_arith/1,otp_8054/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [two,test1,fail,float_bin,in_guard,in_catch,nasty_literals,
+ side_effect,opt,otp_7556,float_arith,otp_8054].
+
+init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+two(Config) when is_list(Config) ->
+ <<0,1,2,3,4,6,7,8,9>> = two_1([0], [<<1,2,3,4>>,<<6,7,8,9>>]),
+ ok.
+
+two_1(P, L) ->
+ list_to_binary([P|L]).
+
+
+big(1) ->
+ 57285702734876389752897683.
+
+i(X) -> X.
+
+id(I) -> I.
+
+-define(T(B, L), {B, ??B, L}).
+-define(N(B), {B, ??B, unknown}).
+
+-define(FAIL(Expr), ?line {'EXIT',{badarg,_}} = (catch Expr)).
+
+l(I_13, I_big1, I_16, Bin) ->
+ [
+ ?T(<<-43>>,
+ [256-43]),
+ ?T(<<4:4,7:4>>,
+ [4*16+7]),
+ ?T(<<45:I_16/little>>,
+ [45,0]),
+ ?T(<<777:16/little>>,
+ [9,3]),
+ ?T(<<777:I_13,13:3>>,
+ [24,77]),
+ ?T(<<5:4,987:I_13,537:7>>,
+ [81,237,153]),
+ ?T(<<0.0:32/float>>,
+ [0,0,0,0]),
+ ?T(<<0.125:32/float>>,
+ [62,0,0,0]),
+ ?T(<<1.0:32/little-float>>,
+ [0,0,128,63]),
+ ?T(<<I_big1:32>>,
+ [138,99,0,147]),
+ ?T(<<57285702734876389752897684:(I_16+16)>>,
+ [138,99,0,148]),
+ ?T(<<-1:17/unit:8>>,
+ lists:duplicate(17, 255)),
+ ?T(<<-1:8/unit:17>>,
+ lists:duplicate(17, 255)),
+ ?T(<<4:(I_16-8)/unit:2,5:2/unit:8>>,
+ [0,4,0,5]),
+ ?T(<<1:1, 0:(I_13-7), 1:1>>,
+ [129]),
+ ?T(<<1:3,"string",9:5>>,
+ [46,110,142,77,45,204,233]),
+ ?T(<<37.98:64/native-float>>,
+ native_3798()),
+ ?T(<<32978297842987249827298387697777669766334937:128/native-integer>>,
+ native_bignum()),
+
+ ?T(<<Bin/binary>>,
+ [165,90,195]),
+ ?T(<<79,Bin/binary>>,
+ [79,165,90,195]),
+ ?T(<<3479:I_13,Bin/binary,7:3>>,
+ [108,189,42,214,31]),
+ ?T(<<3479:I_13,Bin/binary,7:1/unit:3>>,
+ [108,189,42,214,31]),
+ ?T(<<869:16/little,3479:I_13,Bin/binary,7:1/unit:3>>,
+ [101,3,108,189,42,214,31]),
+ ?T(<<869:16/little,3479:I_13,Bin/binary,7:1/unit:3,Bin/binary>>,
+ [101,3,108,189,42,214,31,165,90,195]),
+
+ %% Test of aligment flag.
+ ?T(<<0:I_13/unit:8,1:6,0:2>>,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,4]),
+
+ %% Test of literals (coverage).
+ ?T(<<0:128>>,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ ?T(<<0:13/little,7:3>>,[0,7]),
+ ?T(<<16#77FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:264>>,
+ [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
+ 16#77,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,
+ 16#FF,16#FF,16#FF,16#FF,16#FF,16#FF]),
+
+ %% Mix different units.
+ ?T(<<37558955:(I_16-12)/unit:8,1:1>>,
+ [2,61,26,171,<<1:1>>])
+ ].
+
+native_3798() ->
+ case <<1:16/native>> of
+ <<0,1>> -> [64,66,253,112,163,215,10,61];
+ <<1,0>> -> [61,10,215,163,112,253,66,64]
+ end.
+
+native_bignum() ->
+ case <<1:16/native>> of
+ <<0,1>> -> [129,205,18,177,1,213,170,101,39,231,109,128,176,11,73,217];
+ <<1,0>> -> [217,73,11,176,128,109,231,39,101,170,213,1,177,18,205,129]
+ end.
+
+evaluate(Str, Vars) ->
+ {ok,Tokens,_} =
+ erl_scan:string(Str ++ " . "),
+ {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ case erl_eval:expr(Expr, Vars) of
+ {value, Result, _} ->
+ Result
+ end.
+
+eval_list([], _Vars) ->
+ [];
+eval_list([{C_bin, Str, Bytes} | Rest], Vars) ->
+ case catch evaluate(Str, Vars) of
+ {'EXIT', Error} ->
+ io:format("Evaluation error: ~p, ~p, ~p~n", [Str, Vars, Error]),
+ exit(Error);
+ E_bin ->
+ [{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)]
+ end.
+
+one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) ->
+ io:format(" ~s, ~p~n", [Str, Bytes]),
+ Bin = list_to_bitstring(Bytes),
+ if
+ C_bin == Bin ->
+ ok;
+ true ->
+ io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n",
+ [Str, Bytes, bitstring_to_list(C_bin)]),
+ test_server:fail(comp)
+ end,
+ if
+ E_bin == Bin ->
+ ok;
+ true ->
+ io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n",
+ [Str, Bytes, bitstring_to_list(E_bin)]),
+ test_server:fail(comp)
+ end;
+one_test({C_bin, E_bin, Str, Result}) ->
+ io:format(" ~s ~p~n", [Str, C_bin]),
+ if
+ C_bin == E_bin ->
+ ok;
+ true ->
+ Arbitrary = case Result of
+ unknown ->
+ size(C_bin);
+ _ ->
+ Result
+ end,
+ case equal_lists(bitstring_to_list(C_bin),
+ bitstring_to_list(E_bin),
+ Arbitrary) of
+ false ->
+ io:format("ERROR: Compiled not equal to interpreted:"
+ "~n ~p, ~p.~n",
+ [bitstring_to_list(C_bin), bitstring_to_list(E_bin)]),
+ test_server:fail(comp);
+ 0 ->
+ ok;
+ %% For situations where the final bits may not matter, like
+ %% for floats:
+ N when integer(N) ->
+ io:format("Info: compiled and interpreted differ in the"
+ " last bytes:~n ~p, ~p.~n",
+ [bitstring_to_list(C_bin), bitstring_to_list(E_bin)]),
+ ok
+ end
+ end.
+
+equal_lists([], [], _) ->
+ 0;
+equal_lists([], _, _) ->
+ false;
+equal_lists(_, [], _) ->
+ false;
+equal_lists([A|AR], [A|BR], R) ->
+ equal_lists(AR, BR, R);
+equal_lists(A, B, R) ->
+ if
+ length(A) /= length(B) ->
+ false;
+ length(A) =< R ->
+ R;
+ true ->
+ false
+ end.
+
+test1(Config) when is_list(Config) ->
+ ?line I_13 = i(13),
+ ?line I_big1 = big(1),
+ ?line I_16 = i(16),
+ ?line Bin = i(<<16#A5,16#5A,16#C3>>),
+ ?line Vars = lists:sort([{'I_13',I_13},
+ {'I_big1',I_big1},
+ {'I_16',I_16},
+ {'Bin',Bin}]),
+ ?line lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1, I_16, Bin), Vars)).
+
+fail(Config) when is_list(Config) ->
+ I_minus_777 = i(-777),
+ I_minus_2047 = i(-2047),
+
+ %% One negative field size, but the sum of field sizes will be 1 byte.
+ %% Make sure that we reject that properly.
+
+ ?line {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
+ 57:I_minus_2047/unit:8>>),
+
+ %% Same thing, but use literals.
+ ?line {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
+ 57:(-2047)/unit:8>>),
+
+ %% Not numbers.
+ ?line {'EXIT',{badarg,_}} = (catch <<45:(i(not_a_number))>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<13:8,45:(i(not_a_number))>>),
+
+ %% Unaligned sizes.
+ BadSz = i(7),
+ Bitstr = i(<<42:17>>),
+
+ ?line {'EXIT',{badarg,_}} = (catch <<Bitstr:4/binary>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<Bitstr:BadSz/binary>>),
+
+ ?line [] = [X || {X} <- [], X == <<Bitstr:BadSz/binary>>],
+ ?line [] = [X || {X} <- [], X == <<Bitstr:4/binary>>],
+
+ %% Literals with incorrect type.
+ ?line {'EXIT',{badarg,_}} = (catch <<42.0/integer>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<42/binary>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<an_atom/integer>>),
+
+ ok.
+
+float_bin(Config) when is_list(Config) ->
+ %% Some more coverage.
+ ?line {<<1,2,3>>,7.0} = float_bin_1(4),
+ F = 42.0,
+ ?line <<42,0,0,0,0,0,0,69,64>> = <<(id(42)),F/little-float>>,
+ ok.
+
+float_bin_1(F) ->
+ {<<1,2,3>>,F+3.0}.
+
+in_guard(Config) when is_list(Config) ->
+ ?line 1 = in_guard_1(<<16#74ad:16>>, 16#e95, 5),
+ ?line 2 = in_guard_1(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>),
+ ?line 3 = in_guard_1(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
+ ?line nope = in_guard_1(<<1>>, 42, b),
+ ?line nope = in_guard_1(<<1>>, a, b),
+ ?line nope = in_guard_1(<<1,2>>, 1, 1),
+ ?line nope = in_guard_1(<<4,5>>, 1, 2.71),
+ ?line nope = in_guard_1(<<4,5>>, 1, <<12,13>>),
+
+ ?line 1 = in_guard_2(<<0,56>>, 7, blurf),
+ ?line 2 = in_guard_2(<<1,255>>, 511, blurf),
+ ?line 3 = in_guard_2(<<0,3>>, 0, blurf),
+ ?line 4 = in_guard_2(<<>>, 1, {<<7:16>>}),
+ ?line nope = in_guard_2(<<4,5>>, 1, blurf),
+
+ ?line 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>),
+ ?line 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>),
+ ?line nope = in_guard_3(<<>>, <<>>),
+
+ ?line ok = in_guard_4(<<15:4>>, 255),
+ ?line nope = in_guard_4(<<15:8>>, 255),
+ ok.
+
+in_guard_1(Bin, A, B) when <<A:13,B:3>> == Bin -> 1;
+in_guard_1(Bin, A, B) when <<A:16,B/binary>> == Bin -> 2;
+in_guard_1(Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3;
+in_guard_1(Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> cant_happen;
+in_guard_1(_, _, _) -> nope.
+
+in_guard_2(Bin, A, _T) when <<A:13,0:3>> == Bin -> 1;
+in_guard_2(Bin, A, _T) when <<A:16>> == Bin -> 2;
+in_guard_2(Bin, A, _T) when <<A:14,3:2>> == Bin -> 3;
+in_guard_2(_Bin, A, T) when {A,b} > {0,1}, {<<A:14,3:2>>} == T -> 4;
+in_guard_2(_, _, _) -> nope.
+
+in_guard_3(Bin, A) when <<A/binary,42>> =:= Bin -> 42;
+in_guard_3(_, _) -> nope.
+
+in_guard_4(Bin, A) when <<A:4>> =:= Bin -> ok;
+in_guard_4(_, _) -> nope.
+
+in_catch(Config) when is_list(Config) ->
+ ?line <<42,0,5>> = small(42, 5),
+ ?line <<255>> = small(255, <<1,2,3,4,5,6,7,8,9>>),
+ ?line <<1,2>> = small(<<7,8,9,10>>, 258),
+ ?line <<>> = small(<<1,2,3,4,5>>, <<7,8,9,10>>),
+ ok.
+
+small(A, B) ->
+ case begin
+ case catch <<A:8>> of
+ {'EXIT',_} -> <<>>;
+ ResA0 -> ResA0
+ end
+ end of
+ ResA -> ok
+ end,
+ case begin
+ case catch <<B:16>> of
+ {'EXIT',_} -> <<>>;
+ ResB0 -> ResB0
+ end
+ end of
+ ResB -> ok
+ end,
+ <<ResA/binary,ResB/binary>>.
+
+nasty_literals(Config) when is_list(Config) ->
+ case erlang:system_info(endian) of
+ big ->
+ ?line [0,42] = binary_to_list(id(<<42:16/native>>));
+ little ->
+ ?line [42,0] = binary_to_list(id(<<42:16/native>>))
+ end,
+
+ ?line Bin0 = id(<<1,2,3,0:10000000,4,5,6>>),
+ ?line 1250006 = size(Bin0),
+ ?line <<1,2,3,0:10000000,4,5,6>> = Bin0,
+
+ ?line Bin1 = id(<<0:10000000,7,8,-1:10000000,9,10,0:10000000>>),
+ ?line 3750004 = size(Bin1),
+ ?line <<0:10000000,7,8,-1:10000000/signed,9,10,0:10000000>> = Bin1,
+
+ ?line <<255,255,0,0,0>> = id(<<255,255,0,0,0>>),
+
+ %% Coverage.
+ I = 16#7777FFFF7777FFFF7777FFFF7777FFFF7777FFFF7777FFFF,
+ id(<<I:260>>),
+
+ ok.
+
+-define(COF(Int0),
+ ?line (fun(Int) ->
+ true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
+ true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
+ end)(nonliteral(Int0)),
+ ?line true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>,
+ ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
+
+-define(COF64(Int0),
+ ?line (fun(Int) ->
+ true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
+ end)(nonliteral(Int0)),
+ ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
+
+nonliteral(X) -> X.
+
+coerce_to_float(Config) when is_list(Config) ->
+ ?COF(0),
+ ?COF(-1),
+ ?COF(1),
+ ?COF(42),
+ ?COF(255),
+ ?COF(-255),
+ ?COF(38474),
+ ?COF(387498738948729893849444444443),
+ ?COF(-37489378937773899999999999999993),
+ ?COF64(298748888888888888888888888883478264866528467367364766666666666666663),
+ ?COF64(-367546729879999999999947826486652846736736476555566666663),
+ ok.
+
+side_effect(Config) when is_list(Config) ->
+ {'EXIT',{badarg,_}} = (catch side_effect_1(a)),
+ {'EXIT',{badarg,_}} = (catch side_effect_1(<<>>)),
+ ?line ok = side_effect_1(42),
+ ok.
+
+side_effect_1(A) ->
+ <<A:17>>, %Warning intentional.
+ ok.
+
+-record(otp_7029, {a,b}).
+
+opt(Config) when is_list(Config) ->
+ ?line 42 = otp_7029(#otp_7029{a = <<>>,b = 42}),
+ N = 16,
+ ?line <<1,3,65>> = id(<<1,833:N>>),
+ ?line <<1,66,3>> = id(<<1,834:N/little>>),
+ ?line <<1,65,136,0,0>> = id(<<1,17.0:32/float>>),
+ ?line <<1,64,8,0,0,0,0,0,0>> = id(<<1,3.0:N/float-unit:4>>),
+ ?line <<1,0,0,0,0,0,0,8,64>> = id(<<1,3.0:N/little-float-unit:4>>),
+ ?line {'EXIT',{badarg,_}} = (catch id(<<3.1416:N/float>>)),
+
+ B = <<1,2,3,4,5>>,
+ ?line <<0,1,2,3,4,5>> = id(<<0,B/binary>>),
+ ?line <<1,2,3,4,5,19>> = id(<<B:5/binary,19>>),
+ ?line <<1,2,3,42>> = id(<<B:3/binary,42>>),
+
+ ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(2.5)/binary>>),
+ ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(-16)/binary>>),
+ ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(anka)>>),
+ ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:64/float>>),
+ ?line {'EXIT',_} = (catch <<<<23,56,0,2:7>>/binary>>),
+
+ case id(false) of
+ true -> ?line opt_dont_call_me();
+ false -> ok
+ end,
+
+ ok.
+
+opt_dont_call_me() ->
+ N = 16#12345678,
+ <<0:N>>.
+
+otp_7029(R) ->
+ #otp_7029{a = <<>>} = R,
+ R#otp_7029.b.
+
+otp_7556(Config) when is_list(Config) ->
+ [otp_7556(<<>>, 1024, 1024, 1024) || _ <- lists:seq(0, 1023)],
+ ok.
+
+otp_7556(Bin, A, B, C) ->
+ %% When allocating the binary, the sizes 16*A and 16*A would
+ %% be forgotten.
+ <<Bin/binary,(-1):A/unit:16,0:B/unit:16,(-1):C/unit:16>>.
+
+%% Test binary construction combined with floating point operations
+%% (mostly to cover code in beam_flatten that combines the allocation
+%% for a binary construction with a later allocation).
+
+float_arith(Config) when is_list(Config) ->
+ ?line {<<1,2,3,64,69,0,0,0,0,0,0>>,21.0} = do_float_arith(<<1,2,3>>, 42, 2),
+ ok.
+
+do_float_arith(Bin0, X, Y) ->
+ Bin = <<Bin0/binary,X/float>>,
+ {Bin,X / Y}.
+
+otp_8054(Config) when is_list(Config) ->
+ ?line <<"abc">> = otp_8054_1([null,1,2,3], <<"abc">>),
+ ok.
+
+otp_8054_1([H|T], Bin) ->
+ _ = case H of
+ null ->
+ %% The beam_validator would complain about {x,3}
+ %% not being live in bs_append/8 because of a live
+ %% optimization bug.
+ <<Bin/binary>>;
+ _ ->
+ ok
+ end,
+ otp_8054_1(T, Bin);
+otp_8054_1([], Bin) -> Bin.
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
new file mode 100644
index 0000000000..5c2797170b
--- /dev/null
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -0,0 +1,991 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(bs_match_SUITE).
+-compile(nowarn_shadow_vars).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ fun_shadow/1,int_float/1,otp_5269/1,null_fields/1,wiger/1,
+ bin_tail/1,save_restore/1,shadowed_size_var/1,
+ partitioned_bs_match/1,function_clause/1,
+ unit/1,shared_sub_bins/1,bin_and_float/1,
+ dec_subidentifiers/1,skip_optional_tag/1,
+ wfbm/1,degenerated_match/1,bs_sum/1,coverage/1,
+ multiple_uses/1,zero_label/1,followed_by_catch/1,
+ matching_meets_construction/1,simon/1,matching_and_andalso/1,
+ otp_7188/1,otp_7233/1,otp_7240/1,otp_7498/1,
+ match_string/1,zero_width/1,bad_size/1,haystack/1]).
+
+-export([coverage_id/1]).
+
+-include("test_server.hrl").
+
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [fun_shadow,int_float,otp_5269,null_fields,wiger,bin_tail,save_restore,
+ shadowed_size_var,partitioned_bs_match,function_clause,unit,
+ shared_sub_bins,bin_and_float,dec_subidentifiers,skip_optional_tag,
+ wfbm,degenerated_match,bs_sum,coverage,multiple_uses,zero_label,
+ followed_by_catch,matching_meets_construction,simon,matching_and_andalso,
+ otp_7188,otp_7233,otp_7240,otp_7498,match_string,zero_width,bad_size,
+ haystack].
+
+init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+fun_shadow(Config) when is_list(Config) ->
+ %% OTP-5270
+ ?line 7 = fun_shadow_1(),
+ ?line 7 = fun_shadow_2(8),
+ ?line 7 = fun_shadow_3(),
+ ?line no = fun_shadow_4(8),
+ ok.
+
+fun_shadow_1() ->
+ L = 8,
+ F = fun(<<L:L,B:L>>) -> B end,
+ F(<<16:8, 7:16>>).
+
+fun_shadow_2(L) ->
+ F = fun(<<L:L,B:L>>) -> B end,
+ F(<<16:8, 7:16>>).
+
+fun_shadow_3() ->
+ L = 8,
+ F = fun(<<L:L,B:L,L:L>>) -> B end,
+ F(<<16:8, 7:16,16:16>>).
+
+fun_shadow_4(L) ->
+ F = fun(<<L:L,B:L,L:L>>) -> B;
+ (_) -> no end,
+ F(<<16:8, 7:16,15:16>>).
+
+int_float(Config) when is_list(Config) ->
+ %% OTP-5323
+ ?line <<103133.0:64/float>> = <<103133:64/float>>,
+ ?line <<103133:64/float>> = <<103133:64/float>>,
+ ok.
+
+%% Stolen from erl_eval_SUITE and modified.
+%% OTP-5269. Bugs in the bit syntax.
+otp_5269(Config) when is_list(Config) ->
+ ?line check(fun() -> L = 8,
+ F = fun(<<A:L,B:A>>) -> B end,
+ F(<<16:8, 7:16>>)
+ end,
+ 7),
+ ?line check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end,
+ 7),
+ ?line check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end,
+ 32),
+ ?line check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end,
+ [32]),
+ ?line check(fun() -> [X || <<A:8,
+ B:A>> <- [<<16:8,19:16>>],
+ <<X:8>> <- [<<B:8>>]] end,
+ [19]),
+ ?line check(fun() -> A = 4, B = 28, bit_size(<<13:(A+(X=B))>>), X end,
+ 28),
+ ?line check(fun() ->
+ <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>,
+ {Size,B,Rest}
+ end,
+ {2,<<"AB">>,<<"CD">>}),
+ ?line check(fun() -> X = 32,
+ [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end,
+ %% "binsize variable" ^
+ [1,2]),
+
+ ok.
+
+null_fields(Config) when is_list(Config) ->
+ ?line check(fun() ->
+ W = id(0),
+ F = fun(<<_:W>>) -> tail;
+ (<<>>) -> empty
+ end,
+ F(<<>>)
+ end, tail),
+ ?line check(fun() ->
+ F = fun(<<_/binary>>) -> tail;
+ (<<>>) -> empty
+ end,
+ F(<<>>)
+ end, tail),
+ ok.
+
+wiger(Config) when is_list(Config) ->
+ ?line ok1 = wcheck(<<3>>),
+ ?line ok2 = wcheck(<<1,2,3>>),
+ ?line ok3 = wcheck(<<4>>),
+ ?line {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>),
+ ?line {error,<<>>} = wcheck(<<>>),
+ ok.
+
+wcheck(<<A>>) when A==3->
+ ok1;
+wcheck(<<_,_:2/binary>>) ->
+ ok2;
+wcheck(<<_>>) ->
+ ok3;
+wcheck(Other) ->
+ {error,Other}.
+
+bin_tail(Config) when is_list(Config) ->
+ S = <<"abcde">>,
+ ?line $a = bin_tail_c(S, 0),
+ ?line $c = bin_tail_c(S, 2),
+ ?line $e = bin_tail_c(S, 4),
+ ?line {'EXIT',_} = (catch bin_tail_c(S, 5)),
+ ?line {'EXIT',_} = (catch bin_tail_c_var(S, 5)),
+
+ ?line $a = bin_tail_d(S, 0),
+ ?line $b = bin_tail_d(S, 8),
+ ?line $d = bin_tail_d(S, 3*8),
+ ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 1)),
+ ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 9)),
+ ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)),
+ ?line {'EXIT',_} = (catch bin_tail_d_var(S, 1)),
+
+ ?line ok = bin_tail_e(<<2:2,0:1,1:5>>),
+ ?line ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>),
+ ?line error = bin_tail_e(<<3:2,1:1,1:5,42:64>>),
+ ?line error = bin_tail_e(<<>>),
+ ok.
+
+bin_tail_c(Bin, Offset) ->
+ Res = bin_tail_c_dead(Bin, Offset),
+ <<_:Offset/binary,_,Tail/binary>> = Bin,
+ {Res,Tail} = bin_tail_c_var(Bin, Offset),
+ Res.
+
+bin_tail_c_dead(Bin, Offset) ->
+ <<_:Offset/binary,C,_/binary>> = Bin,
+ C.
+
+bin_tail_c_var(Bin, Offset) ->
+ <<_:Offset/binary,C,Tail/binary>> = Bin,
+ {C,Tail}.
+
+
+bin_tail_d(Bin, BitOffset) ->
+ Res = bin_tail_d_dead(Bin, BitOffset),
+ <<_:BitOffset,_:8,Tail/binary>> = Bin,
+ {Res,Tail} = bin_tail_d_var(Bin, BitOffset),
+ Res.
+
+bin_tail_d_dead(Bin, BitOffset) ->
+ <<_:BitOffset,C,_/binary>> = Bin,
+ C.
+
+bin_tail_d_var(Bin, BitOffset) ->
+ <<_:BitOffset,C,Tail/binary>> = Bin,
+ {C,Tail}.
+
+bin_tail_e(Bin) ->
+ case bin_tail_e_dead(Bin) of
+ ok ->
+ <<_,Tail/binary>> = Bin,
+ Tail = bin_tail_e_var(Bin),
+ ok;
+ error ->
+ bin_tail_e_var(Bin)
+ end.
+
+bin_tail_e_dead(Bin) ->
+ case Bin of
+ %% The binary is aligned at the end; neither the bs_skip_bits2 nor
+ %% bs_test_tail2 instructions are needed.
+ <<2:2,_:1,1:5,_/binary>> -> ok;
+ _ -> error
+ end.
+
+bin_tail_e_var(Bin) ->
+ case Bin of
+ %% The binary is aligned at the end; neither the bs_skip_bits2 nor
+ %% bs_test_tail2 instructions are needed.
+ <<2:2,_:1,1:5,Tail/binary>> -> Tail;
+ _ -> error
+ end.
+
+save_restore(Config) when is_list(Config) ->
+ ?line 0 = save_restore_1(<<0:2,42:6>>),
+ ?line {1,3456} = save_restore_1(<<1:2,3456:14>>),
+ ?line {2,7981234} = save_restore_1(<<2:2,7981234:30>>),
+ ?line {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>),
+
+ A = <<" x">>,
+ B = <<".x">>,
+ C = <<"-x">>,
+
+ ?line {" ",<<"x">>} = lll(A),
+ ?line {" ",<<"x">>} = mmm(A),
+ ?line {" ",<<"x">>} = nnn(A),
+ ?line {" ",<<"x">>} = ooo(A),
+
+ ?line {".",<<"x">>} = lll(B),
+ ?line {".",<<"x">>} = mmm(B),
+ ?line {".",<<"x">>} = nnn(B),
+ ?line {".",<<"x">>} = ooo(B),
+
+ ?line {"-",<<"x">>} = lll(C),
+ ?line {"-",<<"x">>} = mmm(C),
+ ?line {"-",<<"x">>} = nnn(C),
+ ?line {"-",<<"x">>} = ooo(C),
+
+ Bin = <<-1:64>>,
+ case bad_float_unpack_match(Bin) of
+ -1 -> ok;
+ _Other -> ?line ?t:fail(bad_return_value_probably_NaN)
+ end.
+
+save_restore_1(Bin) ->
+ case Bin of
+ <<0:2,_:6>> -> 0;
+ <<1:2,A:14>> -> {1,A};
+ <<2:2,A:30>> -> {2,A};
+ <<A:64>> -> {3,A}
+ end.
+
+lll(<<Char, Tail/binary>>) -> {[Char],Tail}.
+
+mmm(<<$.,$.,$., Tail/binary>>) -> Tail;
+mmm(<<$\s,$-,$\s, Tail/binary>>) -> Tail;
+mmm(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail!
+
+nnn(<<"...", Tail/binary>>) -> Tail;
+nnn(<<" - ", Tail/binary>>) -> Tail;
+nnn(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail!
+
+ooo(<<" - ", Tail/binary>>) -> Tail;
+ooo(<<Char, Tail/binary>>) -> {[Char],Tail}.
+
+bad_float_unpack_match(<<F:64/float>>) -> F;
+bad_float_unpack_match(<<I:64/integer-signed>>) -> I.
+
+
+shadowed_size_var(Config) when is_list(Config) ->
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Dir = filename:dirname(code:which(?MODULE)),
+ ?line Core = filename:join(Dir, "bs_shadowed_size_var"),
+ ?line Opts = [from_core,{outdir,PrivDir}|test_lib:opt_opts(?MODULE)],
+ ?line io:format("~p", [Opts]),
+ ?line {ok,Mod} = c:c(Core, Opts),
+ ?line [42|<<"abcde">>] = Mod:filter_essentials([<<42:32>>|<<5:32,"abcde">>]),
+ ok.
+
+partitioned_bs_match(Config) when is_list(Config) ->
+ ?line <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>),
+ ?line error = partitioned_bs_match(10, <<7,8,15,13>>),
+ ?line error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}),
+ ?line ok = partitioned_bs_match(0, <<>>),
+ ?line {'EXIT',{function_clause,[{?MODULE,partitioned_bs_match,[-1,blurf]}|_]}} =
+ (catch partitioned_bs_match(-1, blurf)),
+ ?line {'EXIT',{function_clause,[{?MODULE,partitioned_bs_match,[-1,<<1,2,3>>]}|_]}} =
+ (catch partitioned_bs_match(-1, <<1,2,3>>)),
+
+ ?line {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>),
+ ?line {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>),
+ ?line {'EXIT',{function_clause,[{?MODULE,partitioned_bs_match_2,[4,<<0:17>>]}|_]}} =
+ (catch partitioned_bs_match_2(4, <<0:17>>)),
+ ok.
+
+partitioned_bs_match(_, <<42:8,T/binary>>) ->
+ T;
+partitioned_bs_match(N, _) when N > 0 ->
+ error;
+partitioned_bs_match(_, <<>>) ->
+ ok.
+
+partitioned_bs_match_2(1, <<B:8,T/binary>>) ->
+ {B,T};
+partitioned_bs_match_2(Len, <<_:8,T/binary>>) ->
+ {Len,T}.
+
+function_clause(Config) when is_list(Config) ->
+ ?line ok = function_clause_1(<<0,7,0,7,42>>),
+ ?line {'EXIT',{function_clause,
+ [{?MODULE,function_clause_1,[<<0,1,2,3>>]}|_]}} =
+ (catch function_clause_1(<<0,1,2,3>>)),
+ ?line {'EXIT',{function_clause,
+ [{?MODULE,function_clause_1,[<<0,1,2,3>>]}|_]}} =
+ (catch function_clause_1(<<0,7,0,1,2,3>>)),
+ ok.
+
+function_clause_1(<<0:8,7:8,T/binary>>) ->
+ function_clause_1(T);
+function_clause_1(<<_:8>>) ->
+ ok.
+
+unit(Config) when is_list(Config) ->
+ ?line 42 = peek1(<<42>>),
+ ?line 43 = peek1(<<43,1,2>>),
+ ?line 43 = peek1(<<43,1,2,(-1):1>>),
+ ?line 43 = peek1(<<43,1,2,(-1):2>>),
+ ?line 43 = peek1(<<43,1,2,(-1):7>>),
+
+ ?line 99 = peek8(<<99>>),
+ ?line 100 = peek8(<<100,101>>),
+ ?line {'EXIT',{function_clause,[{?MODULE,peek8,[<<100,101,0:1>>]}|_]}} =
+ (catch peek8(<<100,101,0:1>>)),
+
+ ?line 37484 = peek16(<<37484:16>>),
+ ?line 37489 = peek16(<<37489:16,5566:16>>),
+ ?line {'EXIT',{function_clause,[{?MODULE,peek16,[<<8>>]}|_]}} =
+ (catch peek16(<<8>>)),
+ ?line {'EXIT',{function_clause,[{?MODULE,peek16,[<<42:15>>]}|_]}} =
+ (catch peek16(<<42:15>>)),
+ ?line {'EXIT',{function_clause,[{?MODULE,peek16,[<<1,2,3,4,5>>]}|_]}} =
+ (catch peek16(<<1,2,3,4,5>>)),
+
+ ?line 127 = peek7(<<127:7>>),
+ ?line 100 = peek7(<<100:7,19:7>>),
+ ?line {'EXIT',{function_clause,[{?MODULE,peek7,[<<1,2>>]}|_]}} =
+ (catch peek7(<<1,2>>)),
+ ok.
+
+peek1(<<B:8,_/bitstring>>) -> B.
+
+peek7(<<B:7,_/binary-unit:7>>) -> B.
+
+peek8(<<B:8,_/binary>>) -> B.
+
+peek16(<<B:16,_/binary-unit:16>>) -> B.
+
+shared_sub_bins(Config) when is_list(Config) ->
+ ?line {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0),
+ ok.
+
+sum(<<B,T/binary>>, Acc, Sum) ->
+ sum(T, [T|Acc], Sum+B);
+sum(<<>>, Last, Sum) -> {Sum,Last}.
+
+
+bin_and_float(Config) when is_list(Config) ->
+ ?line 14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0),
+ ok.
+
+bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X),
+ is_float(Y),
+ is_float(Z) ->
+ bin_and_float(T, Sum+X*X+Y*Y+Z*Z);
+bin_and_float(<<>>, Sum) -> Sum.
+
+dec_subidentifiers(Config) when is_list(Config) ->
+ ?line {[],<<1,2,3>>} =
+ do_dec_subidentifiers(<<1:1,42:7,1:1,99:7,1,2,3>>, 0, [], 2),
+ ?line {[5389],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2),
+ ?line {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0),
+ ok.
+
+do_dec_subidentifiers(Buffer, Av, Al, Len) ->
+ Res = dec_subidentifiers(Buffer, Av, Al, Len),
+ Res = dec_subidentifiers2(Buffer, Av, Al, Len),
+ Res = dec_subidentifiers4(Buffer, Av, Al, Len),
+ Res = dec_subidentifiers3(Buffer, Av, Al, Len).
+
+dec_subidentifiers(Buffer, _Av, Al, 0) ->
+ {lists:reverse(Al),Buffer};
+dec_subidentifiers(<<1:1,H:7,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers(T, (Av bsl 7) bor H, Al, Len-1);
+dec_subidentifiers(<<H,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers(T, 0, [((Av bsl 7) bor H)|Al], Len-1).
+
+dec_subidentifiers2(<<Buffer/binary>>, _Av, Al, 0) ->
+ {lists:reverse(Al),Buffer};
+dec_subidentifiers2(<<1:1,H:7,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers2(T, (Av bsl 7) bor H, Al, Len-1);
+dec_subidentifiers2(<<H,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers2(T, 0, [((Av bsl 7) bor H)|Al], Len-1).
+
+dec_subidentifiers3(Buffer, _Av, Al, 0) when is_binary(Buffer) ->
+ {lists:reverse(Al),Buffer};
+dec_subidentifiers3(<<1:1,H:7,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers3(T, (Av bsl 7) bor H, Al, Len-1);
+dec_subidentifiers3(<<H,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers3(T, 0, [((Av bsl 7) bor H)|Al], Len-1).
+
+dec_subidentifiers4(<<1:1,H:7,T/binary>>, Av, Al, Len) when Len =/= 0 ->
+ dec_subidentifiers4(T, (Av bsl 7) bor H, Al, Len-1);
+dec_subidentifiers4(<<H,T/binary>>, Av, Al, Len) when Len =/= 0 ->
+ dec_subidentifiers4(T, 0, [((Av bsl 7) bor H)|Al], Len-1);
+dec_subidentifiers4(Buffer, _Av, Al, 0) ->
+ {lists:reverse(Al),Buffer}.
+
+
+skip_optional_tag(Config) when is_list(Config) ->
+ {ok,<<>>} = skip_optional_tag(<<42>>, <<42>>),
+ {ok,<<>>} = skip_optional_tag(<<42,1>>, <<42,1>>),
+ {ok,<<1,2,3>>} = skip_optional_tag(<<42>>, <<42,1,2,3>>),
+ missing = skip_optional_tag(<<2:3>>, blurf),
+ ok.
+
+skip_optional_tag(<<>>, Binary) ->
+ {ok,Binary};
+skip_optional_tag(<<Tag,RestTag/binary>>, <<Tag,Rest/binary>>) ->
+ skip_optional_tag(RestTag, Rest);
+skip_optional_tag(_, _) -> missing.
+
+-define(DATELEN, 16).
+
+wfbm(Config) when is_list(Config) ->
+ %% check_for_dot_or_space and get_tail is from wfbm4 by Steve Vinoski,
+ %% with modifications.
+ ?line {nomatch,0} = check_for_dot_or_space(<<" ">>),
+ ?line {nomatch,0} = check_for_dot_or_space(<<" abc">>),
+ ?line {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>),
+ ?line {nomatch,0} = check_for_dot_or_space(<<".gurka">>),
+ ?line {nomatch,1} = check_for_dot_or_space(<<"g.urka">>),
+
+ ?line nomatch = get_tail(<<>>),
+ ?line {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>),
+ ?line {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>),
+ ?line nomatch = get_tail(<<"200y.2007.10.23.blurf ">>),
+ ?line {'EXIT',_} = (catch get_tail({no,binary,at,all})),
+ ?line {'EXIT',_} = (catch get_tail(no_binary)),
+ ok.
+
+check_for_dot_or_space(Bin) ->
+ check_for_dot_or_space(Bin, 0).
+
+check_for_dot_or_space(<<$\s, _/binary>>, 0) ->
+ {nomatch,0};
+check_for_dot_or_space(Bin, Len) ->
+ case Bin of
+ <<Front:Len/binary, $\s, _/binary>> ->
+ {ok,Front};
+ <<_:Len/binary, $., _/binary>> ->
+ {nomatch,Len};
+ _ ->
+ check_for_dot_or_space(Bin, Len+1)
+ end.
+
+get_tail(<<>>) ->
+ nomatch;
+get_tail(Bin) ->
+ <<Front:?DATELEN/binary, Tail/binary>> = Bin,
+ case Front of
+ <<_:3/binary,"x/",Y:4/binary,$/,M:2/binary,$/,D:2/binary,$/>> ->
+ case check_for_dot_or_space(Tail) of
+ {ok,Match} ->
+ {ok,<<Y/binary,$/,M/binary,$/,D/binary,$/, Match/binary>>};
+ {nomatch,Skip} -> {skip,?DATELEN + Skip}
+ end;
+ _ -> nomatch
+ end.
+
+degenerated_match(Config) when is_list(Config) ->
+ ?line error = degenerated_match_1(<<>>),
+ ?line 1 = degenerated_match_1(<<1:1>>),
+ ?line 2 = degenerated_match_1(<<42,43>>),
+
+ ?line error = degenerated_match_2(<<>>),
+ ?line no_split = degenerated_match_2(<<1,2>>),
+ ?line {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>),
+
+ ok.
+
+degenerated_match_1(<<>>) -> error;
+degenerated_match_1(Bin) -> byte_size(Bin).
+
+degenerated_match_2(<<>>) -> error;
+degenerated_match_2(Bin) ->
+ case byte_size(Bin) > 4 of
+ true ->
+ split_binary(Bin, 4);
+ false ->
+ no_split
+ end.
+
+bs_sum(Config) when is_list(Config) ->
+ ?line 0 = bs_sum_1([]),
+ ?line 0 = bs_sum_1(<<>>),
+ ?line 42 = bs_sum_1([42]),
+ ?line 1 = bs_sum_1(<<1>>),
+ ?line 10 = bs_sum_1([1,2,3,4]),
+ ?line 15 = bs_sum_1(<<1,2,3,4,5>>),
+ ?line 21 = bs_sum_1([1,2,3|<<4,5,6>>]),
+ ?line 15 = bs_sum_1([1,2,3|{4,5}]),
+ ?line 6 = bs_sum_1([1,2,3|zero]),
+ ?line 6 = bs_sum_1([1,2,3|0]),
+ ?line 7 = bs_sum_1([1,2,3|one]),
+
+ ?line {'EXIT',{function_clause,_}} = (catch bs_sum_1({too,big,tuple})),
+ ?line {'EXIT',{function_clause,_}} = (catch bs_sum_1([1,2,3|{too,big,tuple}])),
+
+ ?line [] = sneaky_alias(<<>>),
+ ?line [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)),
+ ?line {'EXIT',{function_clause,[{?MODULE,sneaky_alias,[<<1>>]}|_]}} =
+ (catch sneaky_alias(id(<<1>>))),
+ ?line {'EXIT',{function_clause,[{?MODULE,sneaky_alias,[[1,2,3,4]]}|_]}} =
+ (catch sneaky_alias(lists:seq(1, 4))),
+ ok.
+
+bs_sum_1(<<H,T/binary>>) -> H+bs_sum_1(T);
+bs_sum_1([H|T]) -> H+bs_sum_1(T);
+bs_sum_1({A,B}=_Tuple=_AliasForNoGoodReason) -> A+B;
+bs_sum_1(0) -> 0;
+bs_sum_1(zero=_Zero) -> 0;
+bs_sum_1(one) -> 1;
+bs_sum_1([]) -> 0;
+bs_sum_1(<<>>) -> 0.
+
+sneaky_alias(<<>>=L) -> binary_to_list(L);
+sneaky_alias(<<From:32,L/binary>>) -> [From|sneaky_alias(L)].
+
+coverage(Config) when is_list(Config) ->
+ ?line 0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>),
+ ?line 6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>),
+ ?line {'EXIT',{function_clause,_}} = (catch coverage_fold(fun(B, A) ->
+ A+B
+ end, 0, [a,b,c])),
+
+ ?line {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple),
+ ?line {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} =
+ coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}),
+
+ ?line {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}),
+
+ ?line [42] = coverage_apply(<<42>>, [coverage_id]),
+
+ ?line do_coverage_bin_to_term_list([]),
+ ?line do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]),
+ ?line {'EXIT',{function_clause,
+ [{?MODULE,coverage_bin_to_term_list,[<<0,0,0,7>>]}|_]}} =
+ (catch do_coverage_bin_to_term_list_1(<<7:32>>)),
+
+ ?line <<>> = coverage_per_key(<<4:32>>),
+ ?line <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>),
+
+ ok.
+
+coverage_fold(Fun, Acc, <<H,T/binary>>) ->
+ IdFun = fun id/1,
+ coverage_fold(Fun, Fun(IdFun(H), IdFun(Acc)), T);
+coverage_fold(Fun, Acc, <<>>) when is_function(Fun, 2) -> Acc.
+
+coverage_build(Acc0, <<H,T/binary>>, Tuple0) ->
+ Str = id(<<H:(id(4)),(H-1):4,"abc">>),
+ Acc = id(<<Acc0/bitstring,Str/bitstring>>),
+ Tuple = setelement(2, setelement(3, Tuple0, 43), 42),
+ if
+ byte_size(Acc) > 0 ->
+ coverage_build(Acc, T, Tuple)
+ end;
+coverage_build(Acc, <<>>, Tuple) -> {Acc,Tuple}.
+
+coverage_setelement(<<H,T1/binary>>, Tuple) when element(1, Tuple) =:= x ->
+ setelement(H, Tuple, T1).
+
+coverage_apply(<<H,T/binary>>, [F|Fs]) ->
+ [?MODULE:F(H)|coverage_apply(T, Fs)];
+coverage_apply(<<>>, []) -> [].
+
+coverage_id(I) -> id(I).
+
+do_coverage_bin_to_term_list(L) ->
+ Bin = << <<(begin BinTerm = term_to_binary(Term),
+ <<(byte_size(BinTerm)):32,BinTerm/binary>> end)/binary>> ||
+ Term <- L >>,
+ L = do_coverage_bin_to_term_list_1(Bin),
+ L = do_coverage_bin_to_term_list_1(<<Bin/binary,7:32,"garbage">>),
+ L = do_coverage_bin_to_term_list_1(<<7:32,"garbage",Bin/binary>>).
+
+do_coverage_bin_to_term_list_1(Bin) ->
+ Res = coverage_bin_to_term_list(Bin),
+ Res = coverage_bin_to_term_list(Bin, []),
+ Res = coverage_bin_to_term_list_catch(Bin),
+ Res = coverage_bin_to_term_list_catch(Bin, []).
+
+coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>) ->
+ try binary_to_term(BinTerm) of
+ Term -> [Term|coverage_bin_to_term_list(T)]
+ catch
+ error:badarg -> coverage_bin_to_term_list(T)
+ end;
+coverage_bin_to_term_list(<<>>) -> [].
+
+coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) ->
+ try binary_to_term(BinTerm) of
+ Term -> coverage_bin_to_term_list(T, [Term|Acc])
+ catch
+ error:badarg -> coverage_bin_to_term_list(T, Acc)
+ end;
+coverage_bin_to_term_list(<<>>, Acc) -> lists:reverse(Acc).
+
+coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>) ->
+ case catch binary_to_term(BinTerm) of
+ {'EXIT',_} -> coverage_bin_to_term_list_catch(T);
+ Term -> [Term|coverage_bin_to_term_list_catch(T)]
+ end;
+coverage_bin_to_term_list_catch(<<>>) -> [].
+
+coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) ->
+ case catch binary_to_term(BinTerm) of
+ {'EXIT',_} -> coverage_bin_to_term_list_catch(T, Acc);
+ Term -> coverage_bin_to_term_list_catch(T, [Term|Acc])
+ end;
+coverage_bin_to_term_list_catch(<<>>, Acc) -> lists:reverse(Acc).
+
+coverage_per_key(<<BinSize:32,Bin/binary>> = B) ->
+ true = (byte_size(B) =:= BinSize),
+ Bin.
+
+multiple_uses(Config) when is_list(Config) ->
+ ?line {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>),
+ ?line true = multiple_uses_2(<<0,0,197,18>>),
+ ?line <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1),
+ ok.
+
+multiple_uses_1(<<X:16,Tail/binary>>) ->
+ %% NOT OPTIMIZED: sub binary is matched or used in more than one place
+ {Y,Z} = multiple_uses_match(Tail),
+ {X,Y,Z,Tail}.
+
+multiple_uses_2(<<_:16,Tail/binary>>) ->
+ %% NOT OPTIMIZED: sub binary is matched or used in more than one place
+ multiple_uses_cmp(Tail, Tail).
+
+multiple_uses_3(<<_:16,Tail/binary>>, Fun) ->
+ %% NOT OPTIMIZED: sub binary is used or returned
+ Fun(Tail).
+
+multiple_uses_match(<<Y:16,Z:16>>) ->
+ {Y,Z}.
+
+multiple_uses_cmp(<<Y:16>>, <<Y:16>>) -> true;
+multiple_uses_cmp(<<_:16>>, <<_:16>>) -> false.
+
+zero_label(Config) when is_list(Config) ->
+ ?line <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>),
+ ?line <<"CE">> = read_pols(<<"noFACE">>),
+ ok.
+
+read_pols(Data) ->
+ <<PolygonType:4/binary,Rest/binary>> = Data,
+ %% Intentional warning.
+ (PolygonType == <<"FACE">>) or (PolygonType == <<"PTCH">>),
+ Rest.
+
+followed_by_catch(Config) when is_list(Config) ->
+ ok = handle(<<0,1,2,3,4,5>>).
+
+-record(rec,{field}).
+handle(<<>>) -> ok;
+handle(Msg) ->
+ <<_DataLen:16, Rest/binary>> = Msg,
+ case catch fooX:func() of
+ [X] ->
+ X#rec.field;
+ _ ->
+ ok
+ end,
+ handle(Rest).
+
+matching_meets_construction(Config) when is_list(Config) ->
+ Bin = id(<<"abc">>),
+ Len = id(2),
+ Tail0 = id(<<1,2,3,4,5>>),
+ ?line <<_:Len/binary,Tail/binary>> = Tail0,
+ ?line Res = <<Tail/binary,Bin/binary>>,
+ ?line <<3,4,5,"abc">> = Res,
+ ?line {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)),
+ ?line {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)),
+ ?line <<"Bbc">> = matching_meets_construction_3(<<"Abc">>),
+
+ ?line <<1,2>> = encode_octet_string(<<1,2,3>>, 2),
+ ok.
+
+matching_meets_construction_1(<<"A",H/binary>>) -> <<"B",H>>.
+
+matching_meets_construction_2(<<"A",H/binary>>) -> <<"B",H/float>>.
+
+matching_meets_construction_3(<<"A",H/binary>>) -> <<"B",H/binary>>.
+
+encode_octet_string(<<OctetString/binary>>, Len) ->
+ <<OctetString:Len/binary-unit:8>>.
+
+simon(Config) when is_list(Config) ->
+ ?line one = simon(blurf, <<>>),
+ ?line two = simon(0, <<42>>),
+ ?line {'EXIT',{function_clause,[{?MODULE,simon,[17,<<1>>]}|_]}} = (catch simon(17, <<1>>)),
+ ?line {'EXIT',{function_clause,[{?MODULE,simon,[0,<<1,2,3>>]}|_]}} = (catch simon(0, <<1,2,3>>)),
+
+ ?line one = simon2(blurf, <<9>>),
+ ?line two = simon2(0, <<9,1>>),
+ ?line {'EXIT',{function_clause,[{?MODULE,simon2,[0,<<9,10,11>>]}|_]}} =
+ (catch simon2(0, <<9,10,11>>)),
+ ok.
+
+simon(_, <<>>) -> one;
+simon(0, <<_>>) -> two.
+
+simon2(_, <<9>>) -> one;
+simon2(0, <<_:16>>) -> two.
+
+
+%% OTP-7113: Crash in v3_codegen.
+matching_and_andalso(Config) when is_list(Config) ->
+ ?line ok = matching_and_andalso_1(<<1,2,3>>, 3),
+ ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)),
+ ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)),
+ ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)),
+ ok.
+
+matching_and_andalso_1(<<Bitmap/binary>>, K)
+ when is_integer(K) andalso size(Bitmap) >= K andalso 0 < K ->
+ ok.
+
+%% Thanks to Tomas Stejskal.
+otp_7188(Config) when is_list(Config) ->
+ MP3 = <<84,65,71,68,117,154,105,232,107,121,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,68,97,110,105,101,108,32,76,
+ 97,110,100,97,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,
+ 101,115,116,32,79,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,50,48,48,48,50,48,48,48,32,45,32,66,101,115,
+ 116,32,79,102,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+ 32,32,12>>,
+ ?line {ok,{"ID3v1",
+ [{title,<<68,117,154,105,232,107,121>>},
+ {artist,<<"Daniel Landa">>},
+ {album,<<"Best Of">>}]}} = parse_v1_or_v11_tag(MP3).
+
+parse_v1_or_v11_tag(<<"TAG", Title:30/binary,
+ Artist:30/binary, Album:30/binary,
+ _Year:4/binary, _Comment:28/binary,
+ 0:8, Track:8, _Genre:8>>) ->
+ {ok,
+ {"ID3v1.1",
+ [{track, Track}, {title, trim(Title)},
+ {artist, trim(Artist)}, {album, trim(Album)}]}};
+parse_v1_or_v11_tag(<<"TAG", Title:30/binary,
+ Artist:30/binary, Album:30/binary,
+ _Year:4/binary, _Comment:30/binary,
+ _Genre:8>>) ->
+ {ok,
+ {"ID3v1",
+ [{title, trim(Title)},
+ {artist, trim(Artist)},
+ {album, trim(Album)}]}};
+parse_v1_or_v11_tag(_) ->
+ error.
+
+trim(Bin) ->
+ list_to_binary(trim_blanks(binary_to_list(Bin))).
+
+trim_blanks(L) ->
+ lists:reverse(skip_blanks_and_zero(lists:reverse(L))).
+
+skip_blanks_and_zero([$\s|T]) ->
+ skip_blanks_and_zero(T);
+skip_blanks_and_zero([0|T]) ->
+ skip_blanks_and_zero(T);
+skip_blanks_and_zero(L) ->
+ L.
+
+%% OTP-7233. Record and binary matching optimizations clashed.
+%% Thanks to Vladimir Klebansky.
+
+-record(rec_otp_7233, {key, val}).
+
+otp_7233(Config) when is_list(Config) ->
+ ?line otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}),
+ ?line [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format),
+ erase(io_format),
+ ?line otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}),
+ ?line undefined = get(io_format),
+ ok.
+
+otp_7233_1(Rec) ->
+ <<K:2/binary,_Rest:5/binary>> = Rec#rec_otp_7233.key,
+ case K of
+ <<"XX">> ->
+ Value = Rec#rec_otp_7233.val,
+ case lists:keysearch("xxxxxxxx", 1, Value) of
+ {value,T} -> put(io_format, [Rec#rec_otp_7233.key,T]);
+ false -> ok
+ end;
+ _ -> ok
+ end.
+
+
+otp_7240(Config) when is_list(Config) ->
+ ?line a = otp_7240_a(0, <<>>),
+ ?line b = otp_7240_a(1, 2),
+
+ ?line a = otp_7240_b(anything, <<>>),
+ ?line b = otp_7240_b(1, {x,y}),
+
+ ?line a = otp_7240_c(anything, <<>>),
+ ?line b = otp_7240_c(1, <<2>>),
+
+ ?line a = otp_7240_d(anything, <<>>),
+ ?line b = otp_7240_d(again, <<2>>),
+
+ ?line a = otp_7240_e(anything, <<>>),
+ ?line b = otp_7240_e(1, 41),
+
+ ?line a = otp_7240_f(anything, <<>>),
+ ?line b = otp_7240_f(1, {}),
+
+ ok.
+
+otp_7240_a(_, <<>>) -> a;
+otp_7240_a(1, 2) -> b.
+
+otp_7240_b(_, <<>>) -> a;
+otp_7240_b(1, {_,_}) -> b.
+
+otp_7240_c(_, <<>>) -> a;
+otp_7240_c(1, <<2>>) -> b.
+
+otp_7240_d(_, <<>>) -> a;
+otp_7240_d(_, <<2>>) -> b.
+
+otp_7240_e(_, <<>>) -> a;
+otp_7240_e(1, B) when B < 42 -> b.
+
+otp_7240_f(_, <<>>) -> a;
+otp_7240_f(1, B) when is_tuple(B) -> b.
+
+otp_7498(Config) when is_list(Config) ->
+ ?line <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0),
+ ?line <<2,3>> = otp_7498_foo(<<1,2,3>>, 1),
+ ?line <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2),
+
+ ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0),
+ ?line <<2,3>> = otp_7498_bar(<<1,2,3>>, 1),
+ ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2),
+ ?line <<>> = otp_7498_bar(<<>>, 2),
+ ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3),
+
+ ok.
+
+otp_7498_foo(Bin, 0) ->
+ otp_7498_foo(Bin, 42);
+otp_7498_foo(<<_A, Rest/bitstring>>, 1) ->
+ otp_7498_foo(Rest, 43);
+otp_7498_foo(Bin, _I) ->
+ Bin.
+
+otp_7498_bar(Bin, 0) ->
+ otp_7498_bar(Bin, 42);
+otp_7498_bar(<<_A, Rest/bitstring>>, 1) ->
+ otp_7498_bar(Rest, 43);
+otp_7498_bar(<<>>, 2) ->
+ otp_7498_bar(<<>>, 44);
+otp_7498_bar(Bin, _I) ->
+ Bin.
+
+
+match_string(Config) when is_list(Config) ->
+ %% To make sure that native endian really is handled correctly
+ %% (i.e. that the compiler does not attempt to use bs_match_string/4
+ %% instructions for native segments), running this test is not enough.
+ %% Either examine the generated for do_match_string_native/1 or
+ %% check the coverage for the v3_kernel module.
+ case erlang:system_info(endian) of
+ little ->
+ ?line do_match_string_native(<<$a,0,$b,0>>);
+ big ->
+ ?line do_match_string_native(<<0,$a,0,$b>>)
+ end,
+
+ ?line do_match_string_big(<<0,$a,0,$b>>),
+ ?line do_match_string_little(<<$a,0,$b,0>>),
+
+ ?line do_match_string_big_signed(<<255,255>>),
+ ?line do_match_string_little_signed(<<255,255>>),
+
+ ?line plain = no_match_string_opt(<<"abc">>),
+ ?line strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>),
+
+ ok.
+
+do_match_string_native(<<$a:16/native,$b:16/native>>) -> ok.
+
+do_match_string_big(<<$a:16/big,$b:16/big>>) -> ok.
+
+do_match_string_little(<<$a:16/little,$b:16/little>>) -> ok.
+
+do_match_string_big_signed(<<(-1):16/signed>>) -> ok.
+
+do_match_string_little_signed(<<(-1):16/little-signed>>) -> ok.
+
+no_match_string_opt(<<"abc">>) -> plain;
+no_match_string_opt(<<$a:9,$b:9,$c:9>>) -> strange.
+
+
+%% OTP-7591: A zero-width segment in matching would crash the compiler.
+
+zero_width(Config) when is_list(Config) ->
+ ?line <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>,
+ ?line 2 = Len,
+ ?line Str = <<"hi">>,
+
+ %% Match sure that values that cannot fit in a segment will not match.
+ case id(<<0:8>>) of
+ <<256:8>> -> ?line ?t:fail();
+ _ -> ok
+ end,
+ ok.
+
+
+%% OTP_7650: A invalid size for binary segments could crash the compiler.
+bad_size(Config) when is_list(Config) ->
+ Tuple = {a,b,c},
+ ?line {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)),
+ Binary = <<1,2,3>>,
+ ?line {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)),
+ ok.
+
+haystack(Config) when is_list(Config) ->
+ ?line <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>),
+ ?line [<<0:10/unit:8>>,
+ <<0:20/unit:8>>] = haystack_2(<<1:8192>>),
+ ok.
+
+%% Used to crash the compiler.
+haystack_1(Haystack) ->
+ Subs = [10],
+ [begin
+ <<B:Y/binary>> = Haystack,
+ B
+ end || Y <- Subs],
+ Haystack.
+
+%% There would be an incorrect badmatch exception.
+haystack_2(Haystack) ->
+ Subs = [{687,10},{369,20}],
+ [begin
+ <<_:X/binary,B:Y/binary,_/binary>> = Haystack,
+ B
+ end || {X,Y} <- Subs ].
+
+check(F, R) ->
+ R = F().
+
+id(I) -> I.
diff --git a/lib/compiler/test/bs_shadowed_size_var.core b/lib/compiler/test/bs_shadowed_size_var.core
new file mode 100644
index 0000000000..d1d5ebba6d
--- /dev/null
+++ b/lib/compiler/test/bs_shadowed_size_var.core
@@ -0,0 +1,25 @@
+module 'bs_shadowed_size_var' ['filter_essentials'/1]
+ attributes []
+
+%% Reduced code from beam_asm inlined using the old inliner.
+
+'filter_essentials'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <[#{#<Sz>(32,1,'integer',['unsigned','big']) }#|T]> when 'true' ->
+ let <_cor4> =
+ case T of
+ %% Variable 'Sz' repeated here. Should work.
+ <#{#<Sz>(32,1,'integer',['unsigned','big']),
+ #<Data>(Sz,8,'binary',['unsigned','big'])}#> when 'true' ->
+ Data
+ <_cor5> when 'true' ->
+ primop 'match_fail'
+ ({'case_clause',{_cor5}})
+ end
+ in [Sz|_cor4]
+ <_cor5> when 'true' ->
+ primop 'match_fail'
+ ({'function_clause',_cor5})
+ end
+end
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
new file mode 100644
index 0000000000..d93bdef73d
--- /dev/null
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -0,0 +1,396 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(bs_utf_SUITE).
+
+-export([all/1,
+ utf8_roundtrip/1,unused_utf_char/1,utf16_roundtrip/1,
+ utf32_roundtrip/1,guard/1,extreme_tripping/1,
+ literals/1,coverage/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [utf8_roundtrip,unused_utf_char,utf16_roundtrip,
+ utf32_roundtrip,guard,extreme_tripping,
+ literals,coverage].
+
+utf8_roundtrip(Config) when is_list(Config) ->
+ ?line [utf8_roundtrip_1(P) || P <- utf_data()],
+ ok.
+
+utf8_roundtrip_1({Str,Bin,Bin}) ->
+ ?line Str = utf8_to_list(Bin),
+ ?line Bin = list_to_utf8(Str),
+ ?line [ok = utf8_guard(C, <<42,C/utf8>>) || C <- Str],
+ ?line [error = utf8_guard(C, <<C/utf8>>) || C <- Str],
+ ok.
+
+utf8_guard(C, Bin) when <<42,C/utf8>> =:= Bin -> ok;
+utf8_guard(_, _) -> error.
+
+utf8_to_list(<<C/utf8,T/binary>>) ->
+ [C|utf8_to_list(T)];
+utf8_to_list(<<>>) -> [].
+
+list_to_utf8(L) ->
+ list_to_utf8(L, <<>>).
+
+list_to_utf8([H|T], Bin) ->
+ list_to_utf8(T, <<Bin/binary,H/utf8>>);
+list_to_utf8([], Bin) -> Bin.
+
+unused_utf_char(Config) when is_list(Config) ->
+ [true = utf8_len(Utf8) =:= length(Str) ||
+ {Str,Utf8} <- utf_data()],
+ ok.
+
+utf8_len(B) ->
+ utf8_len(B, 0).
+
+utf8_len(<<_/utf8,T/binary>>, N) ->
+ utf8_len(T, N+1);
+utf8_len(<<>>, N) -> N.
+
+utf16_roundtrip(Config) when is_list(Config) ->
+ ?line {Str,Big,Big,Little,Little} = utf16_data(),
+ ?line 4 = utf16_big_len(Big),
+ ?line 4 = utf16_little_len(Little),
+ ?line Str = big_utf16_to_list(Big),
+ ?line Str = little_utf16_to_list(Little),
+
+ ?line Big = list_to_big_utf16(Str),
+ ?line Little = list_to_little_utf16(Str),
+
+ ok.
+
+utf16_big_len(B) ->
+ utf16_big_len(B, 0).
+
+utf16_big_len(<<_/utf16,T/binary>>, N) ->
+ utf16_big_len(T, N+1);
+utf16_big_len(<<>>, N) -> N.
+
+utf16_little_len(B) ->
+ utf16_little_len(B, 0).
+
+utf16_little_len(<<_/little-utf16,T/binary>>, N) ->
+ utf16_little_len(T, N+1);
+utf16_little_len(<<>>, N) -> N.
+
+list_to_big_utf16(List) ->
+ list_to_big_utf16(List, <<>>).
+
+list_to_big_utf16([H|T], Bin) ->
+ list_to_big_utf16(T, <<Bin/binary,H/utf16>>);
+list_to_big_utf16([], Bin) -> Bin.
+
+list_to_little_utf16(List) ->
+ list_to_little_utf16(List, <<>>).
+
+list_to_little_utf16([H|T], Bin) ->
+ list_to_little_utf16(T, <<Bin/binary,H/little-utf16>>);
+list_to_little_utf16([], Bin) -> Bin.
+
+big_utf16_to_list(<<H/utf16,T/binary>>) ->
+ [H|big_utf16_to_list(T)];
+big_utf16_to_list(<<>>) -> [].
+
+little_utf16_to_list(<<H/little-utf16,T/binary>>) ->
+ [H|little_utf16_to_list(T)];
+little_utf16_to_list(<<>>) -> [].
+
+utf32_roundtrip(Config) when is_list(Config) ->
+ ?line {Str,Big,Big,Little,Little} = utf32_data(),
+ ?line 4 = utf32_big_len(Big),
+ ?line 4 = utf32_little_len(Little),
+ ?line Str = big_utf32_to_list(Big),
+ ?line Str = little_utf32_to_list(Little),
+
+ ?line Big = list_to_big_utf32(Str),
+ ?line Little = list_to_little_utf32(Str),
+
+ ok.
+
+utf32_big_len(B) ->
+ utf32_big_len(B, 0).
+
+utf32_big_len(<<_/utf32,T/binary>>, N) ->
+ utf32_big_len(T, N+1);
+utf32_big_len(<<>>, N) -> N.
+
+utf32_little_len(B) ->
+ utf32_little_len(B, 0).
+
+utf32_little_len(<<_/little-utf32,T/binary>>, N) ->
+ utf32_little_len(T, N+1);
+utf32_little_len(<<>>, N) -> N.
+
+list_to_big_utf32(List) ->
+ list_to_big_utf32(List, <<>>).
+
+list_to_big_utf32([H|T], Bin) ->
+ list_to_big_utf32(T, <<Bin/binary,H/utf32>>);
+list_to_big_utf32([], Bin) -> Bin.
+
+list_to_little_utf32(List) ->
+ list_to_little_utf32(List, <<>>).
+
+list_to_little_utf32([H|T], Bin) ->
+ list_to_little_utf32(T, <<Bin/binary,H/little-utf32>>);
+list_to_little_utf32([], Bin) -> Bin.
+
+big_utf32_to_list(<<H/utf32,T/binary>>) ->
+ [H|big_utf32_to_list(T)];
+big_utf32_to_list(<<>>) -> [].
+
+little_utf32_to_list(<<H/little-utf32,T/binary>>) ->
+ [H|little_utf32_to_list(T)];
+little_utf32_to_list(<<>>) -> [].
+
+
+guard(Config) when is_list(Config) ->
+ ?line error = do_guard(16#D800),
+ ok.
+
+do_guard(C) when byte_size(<<C/utf8>>) =/= 42 -> ok;
+do_guard(C) when byte_size(<<C/utf16>>) =/= 42 -> ok;
+do_guard(C) when byte_size(<<C/utf32>>) =/= 42 -> ok;
+do_guard(_) -> error.
+
+%% The purpose of this test is to make sure that
+%% the delayed creation of sub-binaries works.
+
+extreme_tripping(Config) when is_list(Config) ->
+ ?line Unicode = lists:seq(0, 1024),
+ ?line Utf8 = unicode_to_utf8(Unicode, <<>>),
+ ?line Utf16 = utf8_to_utf16(Utf8, <<>>),
+ ?line Utf32 = utf8_to_utf32(Utf8, <<>>),
+ ?line Utf32 = utf16_to_utf32(Utf16, <<>>),
+ ?line Utf8 = utf32_to_utf8(Utf32, <<>>),
+ ?line Unicode = utf32_to_unicode(Utf32),
+ ok.
+
+unicode_to_utf8([C|T], Bin) ->
+ unicode_to_utf8(T, <<Bin/bytes,C/utf8>>);
+unicode_to_utf8([], Bin) -> Bin.
+
+utf8_to_utf16(<<C/utf8,T/binary>>, Bin) ->
+ utf8_to_utf16(T, <<Bin/bytes,C/utf16>>);
+utf8_to_utf16(<<>>, Bin) -> Bin.
+
+utf16_to_utf32(<<C/utf16,T/binary>>, Bin) ->
+ utf16_to_utf32(T, <<Bin/bytes,C/utf32>>);
+utf16_to_utf32(<<>>, Bin) -> Bin.
+
+utf8_to_utf32(<<C/utf8,T/binary>>, Bin) ->
+ utf8_to_utf32(T, <<Bin/bytes,C/utf32>>);
+utf8_to_utf32(<<>>, Bin) -> Bin.
+
+utf32_to_utf8(<<C/utf32,T/binary>>, Bin) ->
+ utf32_to_utf8(T, <<Bin/bytes,C/utf8>>);
+utf32_to_utf8(<<>>, Bin) -> Bin.
+
+utf32_to_unicode(<<C/utf32,T/binary>>) ->
+ [C|utf32_to_unicode(T)];
+utf32_to_unicode(<<>>) -> [].
+
+literals(Config) when is_list(Config) ->
+ ?line abc_utf8 = match_literal(<<"abc"/utf8>>),
+ ?line abc_utf8 = match_literal(<<$a,$b,$c>>),
+
+ ?line abc_utf16be = match_literal(<<"abc"/utf16>>),
+ ?line abc_utf16be = match_literal(<<$a:16,$b:16,$c:16>>),
+ ?line abc_utf16le = match_literal(<<"abc"/little-utf16>>),
+ ?line abc_utf16le = match_literal(<<$a:16/little,$b:16/little,$c:16/little>>),
+
+ ?line abc_utf32be = match_literal(<<"abc"/utf32>>),
+ ?line abc_utf32be = match_literal(<<$a:32,$b:32,$c:32>>),
+ ?line abc_utf32le = match_literal(<<"abc"/little-utf32>>),
+ ?line abc_utf32le = match_literal(<<$a:32/little,$b:32/little,$c:32/little>>),
+
+ ?line bjorn_utf8 = match_literal(<<"bj\366rn"/utf8>>),
+ ?line bjorn_utf8 = match_literal(<<$b,$j,195,182,$r,$n>>),
+
+ ?line bjorn_utf16be = match_literal(<<"bj\366rn"/utf16>>),
+ ?line bjorn_utf16be = match_literal(<<$b:16,$j:16,246:16,$r:16,$n:16>>),
+ ?line bjorn_utf16le = match_literal(<<"bj\366rn"/little-utf16>>),
+ ?line bjorn_utf16le = match_literal(<<$b:16/little,$j:16/little,
+ 246:16/little,$r:16/little,
+ $n:16/little>>),
+ ?line <<244,143,191,191>> = <<16#10ffff/utf8>>,
+
+ %% Invalid literals.
+ I = 0,
+ ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf8,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf16,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf16,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf32,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf32,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf8,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf8,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/utf8,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf16,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf16,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf16,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/little-utf16,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/utf16,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/little-utf16,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf32,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf32,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf32,I/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/little-utf32,I/utf8>>),
+
+ B = 16#10FFFF+1,
+ ?line {'EXIT',{badarg,_}} = (catch <<B/utf8>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<B/utf16>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<B/little-utf16>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<B/utf32>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<B/little-utf32>>),
+
+ %% Matching of bad literals.
+ ?line error = bad_literal_match(<<237,160,128>>), %16#D800 in UTF-8
+ ?line error = bad_literal_match(<<239,191,190>>), %16#FFFE in UTF-8
+ ?line error = bad_literal_match(<<239,191,191>>), %16#FFFF in UTF-8
+ ?line error = bad_literal_match(<<244,144,128,128>>), %16#110000 in UTF-8
+
+ ?line error = bad_literal_match(<<255,254>>), %16#FFFE in UTF-16
+ ?line error = bad_literal_match(<<255,255>>), %16#FFFF in UTF-16
+
+ ?line error = bad_literal_match(<<16#D800:32>>),
+ ?line error = bad_literal_match(<<16#FFFE:32>>),
+ ?line error = bad_literal_match(<<16#FFFF:32>>),
+ ?line error = bad_literal_match(<<16#110000:32>>),
+ ?line error = bad_literal_match(<<16#D800:32/little>>),
+ ?line error = bad_literal_match(<<16#FFFE:32/little>>),
+ ?line error = bad_literal_match(<<16#FFFF:32/little>>),
+ ?line error = bad_literal_match(<<16#110000:32/little>>),
+
+ ok.
+
+match_literal(<<"abc"/utf8>>) -> abc_utf8;
+match_literal(<<"abc"/big-utf16>>) -> abc_utf16be;
+match_literal(<<"abc"/little-utf16>>) -> abc_utf16le;
+match_literal(<<"abc"/big-utf32>>) -> abc_utf32be;
+match_literal(<<"abc"/little-utf32>>) -> abc_utf32le;
+match_literal(<<"bj\366rn"/utf8>>) -> bjorn_utf8;
+match_literal(<<"bj\366rn"/big-utf16>>) -> bjorn_utf16be;
+match_literal(<<"bj\366rn"/little-utf16>>) -> bjorn_utf16le.
+
+bad_literal_match(<<16#D800/utf8>>) -> ok;
+bad_literal_match(<<16#FFFE/utf8>>) -> ok;
+bad_literal_match(<<16#FFFF/utf8>>) -> ok;
+bad_literal_match(<<16#110000/utf8>>) -> ok;
+bad_literal_match(<<16#FFFE/utf16>>) -> ok;
+bad_literal_match(<<16#FFFF/utf16>>) -> ok;
+bad_literal_match(<<16#D800/utf32>>) -> ok;
+bad_literal_match(<<16#110000/utf32>>) -> ok;
+bad_literal_match(<<16#D800/little-utf32>>) -> ok;
+bad_literal_match(<<16#110000/little-utf32>>) -> ok;
+bad_literal_match(_) -> error.
+
+coverage(Config) when is_list(Config) ->
+ %% Cover bit syntax matching optimizations in v3_kernel.
+ ?line 0 = coverage_1(<<4096/utf8,65536/utf8,0>>),
+ ?line 1 = coverage_1(<<4096/utf8,65536/utf8,1>>),
+
+ ?line 0 = coverage_2(<<4096/utf8,65536/utf8,0>>),
+ ?line 1 = coverage_2(<<1024/utf8,1025/utf8,1>>),
+
+ ?line {'EXIT',{function_clause,_}} = (catch coverage_3(1)),
+
+ %% Cover beam_flatten (combining the heap allocation in
+ %% a subsequent test_heap instruction into the bs_init2
+ %% instruction).
+ {ok,<<533/utf8>>} = cover_test_heap_utf8(533),
+ {ok,<<1024/utf16>>} = cover_test_heap_utf16(1024),
+ {ok,<<7966/utf32>>} = cover_test_heap_utf32(7966),
+
+ ok.
+
+coverage_1(<<4096/utf8,65536/utf8,0>>) -> 0;
+coverage_1(<<4096/utf8,65536/utf8,1>>) -> 1.
+
+coverage_2(<<4096/utf8,65536/utf8,0>>) -> 0;
+coverage_2(<<1024/utf8,1025/utf8,1>>) -> 1.
+
+coverage_3(<<16#7fffffff/utf8,65536/utf8,0>>) -> 0.
+
+cover_test_heap_utf8(C) -> {ok,<<C/utf8>>}.
+cover_test_heap_utf16(C) -> {ok,<<C/utf16>>}.
+cover_test_heap_utf32(C) -> {ok,<<C/utf32>>}.
+
+utf_data() ->
+%% From RFC-3629.
+
+ %% Give the compiler a chance to do some constant propagation.
+ NotIdentical = 16#2262,
+
+ [
+ %% "A<NOT IDENTICAL TO><ALPHA>."
+ {[16#0041,NotIdentical,16#0391,16#002E],
+ <<16#0041/utf8,NotIdentical/utf8,16#0391/utf8,16#002E/utf8>>,
+ <<16#41,16#E2,16#89,16#A2,16#CE,16#91,16#2E>>},
+
+ %% Korean "hangugeo" (meaning "the Korean language")
+ {[16#D55C,16#AD6D,16#C5B4],
+ <<16#D55C/utf8,16#AD6D/utf8,16#C5B4/utf8>>,
+ <<16#ED,16#95,16#9C,16#EA,16#B5,16#AD,16#EC,16#96,16#B4>>},
+
+ %% Japanese "nihongo" (meaning "the Japanese language").
+ {[16#65E5,16#672C,16#8A9E],
+ <<16#65E5/utf8,16#672C/utf8,16#8A9E/utf8>>,
+ <<16#E6,16#97,16#A5,16#E6,16#9C,16#AC,16#E8,16#AA,16#9E>>}
+ ].
+
+utf16_data() ->
+ %% Example from RFC-2781. "*=Ra", where "*" represents a
+ %% hypothetical Ra hieroglyph (code point 16#12345).
+
+ %% Give the compiler a chance to do some constant propagation.
+ RaHieroglyph = 16#12345,
+
+ %% First as a list of Unicode characters.
+ {[RaHieroglyph,16#3D,16#52,16#61],
+
+ %% Big endian (the two binaries should be equal).
+ <<RaHieroglyph/big-utf16,16#3D/big-utf16,16#52/big-utf16,16#61/big-utf16>>,
+ <<16#D8,16#08,16#DF,16#45,16#00,16#3D,16#00,16#52,16#00,16#61>>,
+
+ %% Little endian (the two binaries should be equal).
+ <<RaHieroglyph/little-utf16,16#3D/little-utf16,
+ 16#52/little-utf16,16#61/little-utf16>>,
+ <<16#08,16#D8,16#45,16#DF,16#3D,16#00,16#52,16#00,16#61,16#00>>}.
+
+utf32_data() ->
+ %% "A<NOT IDENTICAL TO><ALPHA>."
+ NotIdentical = 16#2262,
+ {[16#0041,NotIdentical,16#0391,16#002E],
+
+ %% Big endian.
+ <<16#0041/utf32,NotIdentical/utf32,16#0391/utf32,16#002E/utf32>>,
+ <<16#41:32,NotIdentical:32,16#0391:32,16#2E:32>>,
+
+ %% Little endian.
+ <<16#0041/little-utf32,NotIdentical/little-utf32,
+ 16#0391/little-utf32,16#002E/little-utf32>>,
+ <<16#41:32/little,NotIdentical:32/little,
+ 16#0391:32/little,16#2E:32/little>>}.
+
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
new file mode 100644
index 0000000000..d4843c9eba
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -0,0 +1,599 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%% Purpose : Compiles various modules with tough code
+
+-module(compilation_SUITE).
+
+-include("test_server.hrl").
+
+-compile(export_all).
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [self_compile_old_inliner,self_compile,
+ compiler_1,compiler_3,compiler_5,
+ beam_compiler_1, beam_compiler_2, beam_compiler_3,
+ beam_compiler_4, beam_compiler_5, beam_compiler_6,
+ beam_compiler_7, beam_compiler_8, beam_compiler_9,
+ beam_compiler_10, beam_compiler_11, beam_compiler_12,
+ nested_tuples_in_case_expr,
+ otp_2330, guards, vsn,
+ otp_2380, otp_2141, otp_2173, otp_4790,
+ const_list_256,
+ bin_syntax_1, bin_syntax_2, bin_syntax_3,
+ bin_syntax_4, bin_syntax_5, bin_syntax_6,
+ live_var, convopts,
+ bad_functional_value,
+ catch_in_catch, redundant_case, long_string,
+ otp_5076, complex_guard, otp_5092, otp_5151,
+ otp_5235,otp_5244,
+ trycatch_4, opt_crash,
+ otp_5404,otp_5436,otp_5481,otp_5553,otp_5632,
+ otp_5714,otp_5872,otp_6121,otp_6121a,otp_6121b,
+ otp_7202,otp_7345,on_load
+ ].
+
+-define(comp(N),
+ N(Config) when is_list(Config) -> try_it(N, Config)).
+
+-define(comp_fail(N),
+ N(Config) when is_list(Config) -> failure(N, Config)).
+
+?comp(compiler_1).
+?comp(compiler_3).
+?comp(compiler_4).
+?comp(compiler_5).
+
+?comp(beam_compiler_1).
+?comp(beam_compiler_2).
+?comp(beam_compiler_3).
+?comp(beam_compiler_4).
+?comp(beam_compiler_5).
+?comp(beam_compiler_6).
+?comp(beam_compiler_8).
+?comp(beam_compiler_9).
+?comp(beam_compiler_10).
+?comp(beam_compiler_11).
+?comp(beam_compiler_12).
+?comp(beam_compiler_13).
+
+?comp(nested_tuples_in_case_expr).
+
+?comp(otp_2330).
+?comp(otp_2380).
+?comp(otp_2141).
+?comp(otp_2173).
+?comp(otp_4790).
+?comp(otp_5235).
+
+?comp(otp_5244).
+
+?comp(guards).
+
+?comp(pattern_expr).
+
+?comp(const_list_256).
+
+?comp(bin_syntax_1).
+?comp(bin_syntax_2).
+?comp(bin_syntax_3).
+?comp(bin_syntax_4).
+
+?comp(bin_syntax_6).
+
+?comp(otp_5076).
+
+?comp(complex_guard).
+
+?comp(otp_5092).
+?comp(otp_5151).
+
+%%% By Per Gustafsson <[email protected]>
+
+bin_syntax_5(Config) when is_list(Config) ->
+ {<<45>>,<<>>} = split({int, 1}, <<1:16,45>>).
+
+split({int, N}, <<N:16,B:N/binary,T/binary>>) ->
+ {B,T}.
+
+%% This program works with the old version of the compiler
+%% but, the core erlang that it produces have the same variable appearing
+%% looks like this:
+%%
+%% split({int, N}, <<_core1:16, B:N/binary, T/binary>>) when _core1==N
+%%
+%% with my change it will look like this:
+%%
+%% split({int, N}, <<_core1:16, B:_core1/binary, T/binary>>) when _core1==N
+%%
+%% This means that everything worked fine as long as the pattern
+%% matching order was left-to-right but on core erlang any order should be possible
+
+?comp(live_var).
+
+?comp(trycatch_4).
+?comp(bad_functional_value).
+
+?comp(catch_in_catch).
+
+?comp(opt_crash).
+
+?comp(otp_5404).
+?comp(otp_5436).
+?comp(otp_5481).
+?comp(otp_5553).
+?comp(otp_5632).
+?comp(otp_5714).
+?comp(otp_5872).
+?comp(otp_6121).
+?comp(otp_6121a).
+?comp(otp_6121b).
+?comp(convopts).
+?comp(otp_7202).
+?comp(on_load).
+
+beam_compiler_7(doc) ->
+ "Code snippet submitted from Ulf Wiger which fails in R3 Beam.";
+beam_compiler_7(suite) -> [];
+beam_compiler_7(Config) when list(Config) ->
+ ?line done = empty(2, false).
+
+empty(N, Toggle) when N > 0 ->
+ %% R3 Beam copies the second argument to the first before call.
+ empty(N-1, not(Toggle));
+empty(_, _) ->
+ done.
+
+redundant_case(Config) when is_list(Config) ->
+ d = redundant_case_1(1),
+ d = redundant_case_1(2),
+ d = redundant_case_1(3),
+ d = redundant_case_1(4),
+ d = redundant_case_1(5),
+ d = redundant_case_1({glurf,glarf}),
+ ok.
+
+%% This function always returns 'd'. Check that the compiler otptimizes
+%% it properly.
+redundant_case_1(1) -> d;
+redundant_case_1(2) -> d;
+redundant_case_1(3) -> d;
+redundant_case_1(4) -> d;
+redundant_case_1(_) -> d.
+
+failure(Module, Conf) ->
+ ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Module)),
+ ?line Out = ?config(priv_dir,Conf),
+ ?line io:format("Compiling: ~s\n", [Src]),
+ ?line CompRc = compile:file(Src, [{outdir,Out},return,time]),
+ ?line io:format("Result: ~p\n",[CompRc]),
+ ?line case CompRc of
+ error -> ok;
+ {error,Errors,_} -> check_errors(Errors);
+ _ -> test_server:fail({no_error, CompRc})
+ end,
+ ok.
+
+check_errors([{_,Eds}|T]) ->
+ check_error(Eds),
+ check_errors(T);
+check_errors([]) -> ok.
+
+check_error([{_,Mod,Error}|T]) ->
+ check_error_1(Mod:format_error(Error)),
+ check_error(T);
+check_error([{Mod,Error}|T]) ->
+ check_error_1(Mod:format_error(Error)),
+ check_error(T);
+check_error([]) -> ok.
+
+check_error_1(Str0) ->
+ Str = lists:flatten(Str0),
+ io:format("~s\n", [Str]),
+ case Str of
+ "internal"++_=Str ->
+ ?t:fail(internal_compiler_error);
+ _ ->
+ ok
+ end.
+
+-define(TC(Body), tc(fun() -> Body end, ?LINE)).
+
+try_it(Module, Conf) ->
+ %% Change 'false' to 'true' to start a new node for every module.
+ try_it(false, Module, Conf).
+
+try_it(StartNode, Module, Conf) ->
+ ?line OtherOpts = [], %Can be changed to [time] if needed
+ ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Module)),
+ ?line Out = ?config(priv_dir,Conf),
+ ?line io:format("Compiling: ~s\n", [Src]),
+ ?line CompRc0 = compile:file(Src, [clint,{outdir,Out},report,
+ bin_opt_info|OtherOpts]),
+ ?line io:format("Result: ~p\n",[CompRc0]),
+ ?line {ok,_Mod} = CompRc0,
+
+ ?line Dog = test_server:timetrap(test_server:minutes(10)),
+ Node = case StartNode of
+ false ->
+ node();
+ true ->
+ ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
+ ?line {ok,Node0} = start_node(compiler, Pa),
+ Node0
+ end,
+
+ ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
+ ?line load_and_call(Out, Module),
+ ?line test_server:timetrap_cancel(Dog),
+
+ ?line NewDog = test_server:timetrap(test_server:minutes(10)),
+ ?line io:format("Compiling (without optimization): ~s\n", [Src]),
+ ?line CompRc1 = compile:file(Src,
+ [no_copt,no_postopt,{outdir,Out},report|OtherOpts]),
+
+ ?line io:format("Result: ~p\n",[CompRc1]),
+ ?line {ok,_Mod} = CompRc1,
+ ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
+ ?line test_server:timetrap_cancel(NewDog),
+
+ ?line LastDog = test_server:timetrap(test_server:minutes(10)),
+ ?line io:format("Compiling (with old inliner): ~s\n", [Src]),
+ ?line CompRc2 = compile:file(Src, [{outdir,Out},report,bin_opt_info,
+ {inline,1000}|OtherOpts]),
+ ?line io:format("Result: ~p\n",[CompRc2]),
+ ?line {ok,_Mod} = CompRc2,
+ ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
+ ?line test_server:timetrap_cancel(LastDog),
+
+ case StartNode of
+ false -> ok;
+ true -> ?line test_server:stop_node(Node)
+ end,
+ ?line test_server:timetrap_cancel(LastDog),
+ ok.
+
+load_and_call(Out, Module) ->
+ ?line io:format("Loading...\n",[]),
+ ?line {module,Module} = code:load_abs(filename:join(Out, Module)),
+
+ ?line io:format("Calling...\n",[]),
+ %% Call M:M, and expect ok back, that's our interface
+ ?line CallRc = Module:Module(),
+ ?line io:format("Got value: ~p\n",[CallRc]),
+
+ ?line ok = CallRc,
+
+ %% Smoke-test of beam disassembler.
+ ?line test_lib:smoke_disasm(Module),
+
+ ?line true = erlang:delete_module(Module),
+ ?line true = erlang:purge_module(Module),
+
+ %% Restore state of trap_exit just in case. (Since the compiler
+ %% uses a temporary process, we will get {'EXIT',Pid,normal} messages
+ %% if trap_exit is true.)
+
+ process_flag(trap_exit, false),
+ ok.
+
+
+tc(F, Line) ->
+ {Diff,Value} = timer:tc(erlang, apply, [F,[]]),
+ io:format("~p: ~p\n", [Line,Diff]),
+ Value.
+
+start_node(Name, Args) ->
+ case test_server:start_node(Name, slave, [{args, Args}]) of
+ {ok, Node} ->
+ {ok, Node};
+ Error ->
+ ?line test_server:fail(Error)
+ end.
+
+from(H, [H | T]) -> T;
+from(H, [_ | T]) -> from(H, T);
+from(_, []) -> [].
+
+vsn(suite) -> [vsn_1, vsn_2, vsn_3].
+
+vsn_1(doc) ->
+ "Test generation of 'vsn' attribute";
+vsn_1(suite) -> [];
+vsn_1(Conf) when list(Conf) ->
+ ?line M = vsn_1,
+
+ ?line compile_load(M, ?config(data_dir, Conf), Conf),
+ ?line Vsn1 = get_vsn(M),
+ ?line timer:sleep(1000),
+
+ ?line compile_load(M, ?config(data_dir, Conf), Conf),
+ ?line Vsn2 = get_vsn(M),
+
+ ?line compile_load(M, filename:join(?config(data_dir, Conf), "other"),
+ Conf),
+ ?line Vsn3 = get_vsn(M),
+ ?line if
+ Vsn1 == Vsn2, Vsn2 == Vsn3 ->
+ ok;
+ true ->
+ test_server:fail({vsn, Vsn1, Vsn2, Vsn3})
+ end,
+ ok.
+
+vsn_2(doc) ->
+ "Test overriding of generation of 'vsn' attribute";
+vsn_2(suite) -> [];
+vsn_2(Conf) when list(Conf) ->
+ ?line M = vsn_2,
+
+ ?line compile_load(M, ?config(data_dir, Conf), Conf),
+ ?line Vsn = get_vsn(M),
+ ?line case Vsn of
+ [34] ->
+ ok;
+ _ ->
+ test_server:fail({vsn, Vsn})
+ end,
+ ok.
+
+vsn_3(doc) ->
+ "Test that different code yields different generated 'vsn'";
+vsn_3(suite) -> [];
+vsn_3(Conf) when list(Conf) ->
+ ?line M = vsn_3,
+
+ ?line compile_load(M, ?config(data_dir, Conf), Conf),
+ ?line Vsn1 = get_vsn(M),
+
+ ?line compile_load(M, filename:join(?config(data_dir, Conf), "other"),
+ Conf),
+ ?line Vsn2 = get_vsn(M),
+ ?line if
+ Vsn1 /= Vsn2 ->
+ ok;
+ true ->
+ test_server:fail({vsn, Vsn1, Vsn2})
+ end,
+ ok.
+
+get_vsn(M) ->
+ {value, {vsn, V}} = lists:keysearch(vsn, 1, M:module_info(attributes)),
+ V.
+
+long_string(Config) when is_list(Config) ->
+ %% The test must complete in one minute - it should be plenty of time.
+ ?line Dog = test_server:timetrap(test_server:minutes(1)),
+ ?line try_it(long_string, Config),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+compile_load(Module, Dir, Conf) ->
+ ?line Src = filename:join(Dir, atom_to_list(Module)),
+ ?line Out = ?config(priv_dir,Conf),
+ ?line CompRc = compile:file(Src, [{outdir,Out}]),
+ ?line {ok, Module} = CompRc,
+ ?line code:purge(Module),
+ ?line {module, Module} =
+ code:load_abs(filename:join(Out, atom_to_list(Module))),
+ ok.
+
+self_compile(Config) when is_list(Config) ->
+ self_compile_1(Config, "new", [inline]).
+
+self_compile_old_inliner(Config) when is_list(Config) ->
+ %% The old inliner is useful for testing that sys_core_fold does not
+ %% introduce name capture problems.
+ self_compile_1(Config, "old", [verbose,{inline,500}]).
+
+self_compile_1(Config, Prefix, Opts) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(40)),
+
+ ?line Priv = ?config(priv_dir,Config),
+ ?line Version = compiler_version(),
+
+ %% Compile the compiler. (In this node to get better coverage.)
+ ?line CompA = make_compiler_dir(Priv, Prefix++"compiler_a"),
+ ?line VsnA = Version ++ ".0",
+ ?line compile_compiler(compiler_src(), CompA, VsnA, [clint|Opts]),
+
+ %% Compile the compiler again using the newly compiled compiler.
+ %% (In another node because reloading the compiler would disturb cover.)
+ CompilerB = Prefix++"compiler_b",
+ ?line CompB = make_compiler_dir(Priv, Prefix++"compiler_b"),
+ ?line VsnB = VsnA ++ ".0",
+ ?line self_compile_node(CompilerB, CompA, CompB, VsnB, Opts),
+
+ %% Compare compiler directories.
+ ?line compare_compilers(CompA, CompB),
+
+ %% Compile and compare compiler C.
+ ?line CompilerC = Prefix++"compiler_c",
+ ?line CompC = make_compiler_dir(Priv, CompilerC),
+ ?line VsnC = VsnB ++ ".0",
+ ?line self_compile_node(CompilerC, CompB, CompC, VsnC, Opts),
+ ?line compare_compilers(CompB, CompC),
+
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+self_compile_node(NodeName0, CompilerDir, OutDir, Version, Opts) ->
+ ?line NodeName = list_to_atom(NodeName0),
+ ?line Dog = test_server:timetrap(test_server:minutes(10)),
+ ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)) ++
+ " -pa " ++ CompilerDir,
+ ?line {ok,Node} = start_node(NodeName, Pa),
+ ?line Files = compiler_src(),
+ ?line ok = rpc:call(Node, ?MODULE, compile_compiler, [Files,OutDir,Version,Opts]),
+ ?line test_server:stop_node(Node),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+compile_compiler(Files, OutDir, Version, InlineOpts) ->
+ io:format("~s", [code:which(compile)]),
+ io:format("Compiling ~s into ~s", [Version,OutDir]),
+ Opts = [report,
+ bin_opt_info,
+ {outdir,OutDir},
+ {d,'COMPILER_VSN',"\""++Version++"\""},
+ nowarn_shadow_vars,
+ {i,filename:join(code:lib_dir(stdlib), "include")}|InlineOpts],
+ lists:foreach(fun(File) ->
+ {ok,_} = compile:file(File, Opts)
+ end, Files).
+
+compiler_src() ->
+ filelib:wildcard(filename:join([code:lib_dir(compiler), "src", "*.erl"])).
+
+compiler_modules(Dir) ->
+ Files = filelib:wildcard(filename:join(Dir, "*.beam")),
+ [list_to_atom(filename:rootname(filename:basename(F))) || F <- Files].
+
+make_compiler_dir(Priv, Dir0) ->
+ ?line Dir = filename:join(Priv, Dir0),
+ ?line ok = file:make_dir(Dir),
+ Dir.
+
+make_current(Dir) ->
+ true = code:add_patha(Dir),
+ lists:foreach(fun(File) ->
+ c:l(File)
+ end, compiler_modules(Dir)),
+ io:format("~p\n", [code:which(compile)]).
+
+compiler_version() ->
+ {value,{version,Version}} = lists:keysearch(version, 1,
+ compile:module_info(compile)),
+ Version.
+
+compare_compilers(ADir, BDir) ->
+ {[],[],D} = beam_lib:cmp_dirs(ADir, BDir),
+ [] = [T || {A,_}=T <- D,
+ filename:basename(A) =/= "beam_asm.beam"]. %Contains compiler version.
+
+
+%%%
+%%% The only test of the following code is that it compiles.
+%%%
+
+%% Slightly simplifed from megaco_binary_term_id_gen.
+%% beam_block failed to note that the {gc_bif,'-'...} instruction could
+%% fail, and that therefore {y,0} need to be initialized.
+%% {allocate,8,6}.
+%% %% {init,{y,0}} needed here.
+%% {get_list,{x,1},{x,6},{x,7}}.
+%% {'catch',{y,7},{f,3}}.
+%% {move,{x,4},{y,1}}.
+%% {move,{x,3},{y,2}}.
+%% {move,{x,2},{y,3}}.
+%% {move,{x,5},{y,4}}.
+%% {move,{x,7},{y,5}}.
+%% {move,{x,6},{y,6}}.
+%% {gc_bif,'-',{f,0},8,[{x,3},{x,6}],{x,0}}.
+%% {move,{x,0},{y,0}}.
+
+encode_wildcards3([],[],_,_) -> [];
+encode_wildcards3([Level|Levels],[BitsInLevel|BitsRest],LevelNo,TotSize) ->
+ case (catch ?MODULE:encode_wildcard(Level,BitsInLevel,TotSize-BitsInLevel,
+ length(Levels))) of
+ {'EXIT',{Reason,Info}} ->
+ exit({Reason,{LevelNo,Info}});
+
+ no_wildcard ->
+ encode_wildcards3(Levels,BitsRest,LevelNo+1,TotSize-BitsInLevel);
+
+ {level,Wl} ->
+ [Wl|
+ encode_wildcards3(Levels,BitsRest,LevelNo+1,TotSize-BitsInLevel)];
+
+ {recursive,Wr} ->
+ [Wr]
+ end.
+
+%% Slightly simplified code from hipe_rtl_ssapre.
+%% beam_block used to do the following incorrect optimization:
+%%
+%% {gc_bif,length,{f,0},1,[{x,0}],{x,3}}.
+%% ^^^^^ Was {x,0} - changing to {x,3} is not safe.
+%% {gc_bif,'+',{f,0},0,[{y,2},{integer,1}],{x,0}}.
+%% ^^^ Only one register live
+%% . . .
+%% {call_last,4,{f,2},4}. %% beam_validator noted that {x,3} wasn't live.
+
+find_operands(Cfg,XsiGraph,[],_Count) ->
+ {Cfg,XsiGraph};
+find_operands(Cfg,XsiGraph,ActiveList,Count) ->
+ {NewCfg,TempActiveList}=?MODULE:find_operands_for_active_list(Cfg,XsiGraph,
+ ActiveList,[]),
+ NewActiveList=lists:reverse(TempActiveList),
+ [Count+1, length(NewActiveList), length(digraph:vertices(XsiGraph))],
+ find_operands(NewCfg,XsiGraph,NewActiveList,Count+1).
+
+
+%% The following code
+%%
+%% {get_list,{x,2},{x,0},{x,1}}.
+%% {gc_bif,length,{f,0},1,[{x,0}],{x,0}}.
+%% {move,{x,0},{x,1}}.
+%%
+%% was incorrectly optimized to
+%%
+%% {get_list,{x,2},{x,0},{y,0}}.
+%% {gc_bif,length,{f,0},3,[{x,0}],{x,1}}.
+%%
+%% because beam_block:is_transparent({x,1},
+%% {gc_bif,length,{f,0},3,[{x,0}],{x,1}}
+%% incorrectly returned true.
+
+-record(contextId,{cid,device_type,contextRef}).
+-record(dpRef,{cid,tlli,ms_device_context_id}).
+-record(qosProfileBssgp,{peak_bit_rate_msb,
+ peak_bit_rate_lsb,
+ t_a_precedence}).
+-record(llUnitdataReq,{sapi,
+ l3_pdu_length,
+ pdu_life}).
+-record(ptmsi,{value}).
+
+otp_7345(Config) when is_list(Config) ->
+ #llUnitdataReq{l3_pdu_length=3,pdu_life=4} =
+ otp_7345(#contextId{}, 0, [[1,2,3],4,5]).
+
+
+otp_7345(ObjRef, _RdEnv, Args) ->
+ Cid = ObjRef#contextId.cid,
+ _DpRef =
+ #dpRef{cid = Cid,
+ ms_device_context_id = cid_id,
+ tlli = #ptmsi{value = 0}},
+ _QosProfile =
+ #qosProfileBssgp{peak_bit_rate_msb = 0,
+ peak_bit_rate_lsb = 80,
+ t_a_precedence = 49},
+ [Cpdu|_] = Args,
+ LlUnitdataReq =
+ #llUnitdataReq{sapi = 7,
+ l3_pdu_length = length(Cpdu),
+ pdu_life =
+ id(42)
+ div
+ 10},
+ id(LlUnitdataReq).
+
+id(I) -> I.
diff --git a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl b/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl
new file mode 100644
index 0000000000..126a573e83
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bad_functional_value).
+
+-export([?MODULE/0,a/0]).
+
+?MODULE() ->
+ ok.
+
+a() ->
+ .list_to_atom("ok").
+
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_1.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_1.erl
new file mode 100644
index 0000000000..d6c9c869c8
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_1.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_1).
+-export([beam_compiler_1/0]).
+
+beam_compiler_1() ->
+ ok.
+
+-record(foo,{a,b}).
+
+try_me() ->
+ X = #foo{},
+ Y = #foo{},
+ {X#foo.a == Y#foo.a,X#foo.b}.
+
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_10.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_10.erl
new file mode 100644
index 0000000000..a1264055bd
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_10.erl
@@ -0,0 +1,27 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_10).
+-export([?MODULE/0,start_timer/0]).
+
+?MODULE() ->
+ ok.
+
+start_timer() ->
+ Self = self(),
+ spawn(fun() -> receive after 1000 -> Self ! show end end).
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_11.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_11.erl
new file mode 100644
index 0000000000..4be32ab505
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_11.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_11).
+
+-export([?MODULE/0,a/0]).
+
+?MODULE() ->
+ ok.
+
+a() ->
+ case foo:bar() of
+ A -> ok
+ end,
+ A = 3.
+
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_12.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_12.erl
new file mode 100644
index 0000000000..baee6b9bce
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_12.erl
@@ -0,0 +1,29 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_12).
+
+-export([?MODULE/0,t/1]).
+
+?MODULE() ->
+ ok.
+
+t(Name) ->
+ {ok = {file_info,_,regular,_,AccTime1,ModTime1,_,_,_,_,_,_,_,_}} =
+ prim_file:read_file_info(Name).
+
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_2.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_2.erl
new file mode 100644
index 0000000000..0c094d584a
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_2.erl
@@ -0,0 +1,35 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_2).
+-export([beam_compiler_2/0]).
+
+beam_compiler_2() ->
+ ok.
+
+-record(foo,{a,b}).
+
+try_me() ->
+ try_me({foo,x,z},{foo,y,z}).
+
+try_me(X,Y) ->
+ f(X#foo.a =/= Y#foo.a,X#foo.b =/= X#foo.b).
+
+f(A,B) ->
+ A.
+
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_3.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_3.erl
new file mode 100644
index 0000000000..aced49b69c
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_3.erl
@@ -0,0 +1,29 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_3).
+-export([beam_compiler_3/0, f/0]).
+
+%% From Ulf Wiger.
+
+beam_compiler_3() ->
+ ok.
+
+f() ->
+ [_|T] = lists:reverse("xxx"),
+ T.
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_4.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_4.erl
new file mode 100644
index 0000000000..5e74d3cd3c
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_4.erl
@@ -0,0 +1,150 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_4).
+-export([beam_compiler_4/0]).
+
+%% From Ulf Wiger.
+
+beam_compiler_4() ->
+ ok.
+
+selected_alarm(_Env, Parameters) ->
+ UnWebParam = x,
+ [Time, Severity, Info, Cause,
+ Type, Sender, Name, FaultId] = bar:foo(),
+
+ %% The following case generates no test heap instructions,
+ %% but the test heap generated before the call to bar:foo(),
+ %% will be moved to here. And the number of words to allocate
+ %% will be ridicously big (> 65535) and will not fit in a 16 big
+ %% word.
+
+ SenderLink = case Name of
+ "pchScheduledConnectionAlarm" ->
+ Sender;
+ "pchVpVcAlarm" ->
+ Sender;
+ "pchSystemMemoryAlarm" ->
+ Sender;
+ "uniProtocolRestartFailureAlarm" ->
+ Sender;
+ "spvcScheduledConnectionAlarm" ->
+ Sender;
+ "eqmSwitchCoreInterfaceAlarm" ->
+ Sender;
+ "atmPhysicalLayerAlarm" ->
+ Sender;
+ "atmBufferCongestionAlarm" ->
+ Sender;
+ "sdhLinkAlarm" ->
+ Sender;
+ "sdhFarEndAlarm" ->
+ Sender;
+ "sdhUpperQosAlarm" ->
+ Sender;
+ "sdhLowerQosAlarm" ->
+ Sender;
+ "eqmSwitchCoreAlarm" ->
+ Sender;
+ "eqmEtAlarm" ->
+ Sender;
+ "eqmHwIdentityFaultAlarm" ->
+ Sender;
+ "eqmOperatorBlockedEquipmentAlarm" ->
+ Sender;
+ "pdh34PathAlarm" ->
+ Sender;
+ "pdh34ObservationAlarm" ->
+ Sender;
+ "pdh34UpperQosAlarm" ->
+ Sender;
+ "pdh34LowerQosAlarm" ->
+ Sender;
+ "nsySynchRefAlarm" ->
+ Sender;
+ "nsySynchRefBlockedAlarm" ->
+ Sender;
+ "nsySynchNodeHoldoverAlarm" ->
+ Sender;
+ "nsySynchNodeNotWorkingAlarm" ->
+ Sender;
+ "eqmAtbAlarm" ->
+ Sender;
+ "eqmCbEtAlarm" ->
+ Sender;
+ "eqmCpAlarm" ->
+ Sender;
+ "eqmCpInterfaceAlarm" ->
+ Sender;
+ "eqmCbClkAlarm" ->
+ Sender;
+ "eqmCbClkInterfaceAlarm" ->
+ Sender;
+ "eqmCbClkVelocityAlarm" ->
+ Sender;
+ "eqmCbClkPhaseDiffAlarm" ->
+ Sender;
+ "eqmHwNotFoundAlarm" ->
+ Sender;
+ "eqmPduAlarm" ->
+ Sender;
+ "eqmFanAlarm" ->
+ Sender;
+ "eqmLocAlarm" ->
+ Sender;
+ "eqmCustomerDefined1Alarm" ->
+ Sender;
+ "eqmCustomerDefined2Alarm" ->
+ Sender;
+ "eqmCustomerDefined3Alarm" ->
+ Sender;
+ "eqmCustomerDefined4Alarm" ->
+ Sender;
+ "eqmOperatorBlockedLinkAlarm" ->
+ Sender;
+ "eqmPowerFilterAlarm" ->
+ Sender;
+ "eqmCbAbrAlarm" ->
+ Sender;
+ "eqmAlarmCutOffAlarm" ->
+ Sender;
+ OtherAlarm ->
+ Sender
+ end,
+
+ %% The testHeap instruction generated here will move up to before
+ %% the case.
+
+ bar:foo("<TABLE>
+ <TR><TD ALIGN=LEFT>Fault id:
+ <TD>" ++ FaultId ++ "
+ <TR><TD ALIGN=LEFT>Name:
+ <TD>" ++ Name ++ "
+ <TR><TD ALIGN=LEFT>Sender:
+ <TD>" ++ SenderLink ++ "
+ <TR><TD ALIGN=LEFT>Class:
+ <TD>" ++ Type ++ "
+ <TR><TD ALIGN=LEFT>Cause:
+ <TD>" ++ Cause ++ "
+ <TR><TD ALIGN=LEFT>Severity:
+ <TD>" ++ Severity ++ "
+ <TR><TD ALIGN=LEFT>Information:
+ <TD>" ++ Info ++ "
+ <TR><TD ALIGN=LEFT>Time:
+ <TD>" ++ Time).
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_5.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_5.erl
new file mode 100644
index 0000000000..a23a0d518c
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_5.erl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_5).
+-export([beam_compiler_5/0]).
+
+-compile(export_all).
+
+beam_compiler_5() ->
+ ok.
+
+t() ->
+ [_|_] = x.
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_6.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_6.erl
new file mode 100644
index 0000000000..f263fd75b2
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_6.erl
@@ -0,0 +1,153 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_6).
+-export([beam_compiler_6/0]).
+
+%% From Ulf Wiger, modified by Bjorn Gustavsson to provoke the
+%% same error with partly corrected compiler in P3A.
+
+beam_compiler_6() ->
+ ok.
+
+selected_alarm(_Env, Parameters) ->
+ UnWebParam = x,
+ [Time, Severity, Info, Cause,
+ Type, Sender, Name, FaultId] = bar:foo(),
+
+ %% Each branch of the case needs two words of heap,
+ %% but the test heap generated before the call to bar:foo(),
+ %% will be merged to the testHeap of each branch, summed and
+ %% moved before the branch. And the number of words to allocate
+ %% will be ridiculously big (> 65535) and will not fit in a
+ %% 16 bit word.
+
+ SenderLink =
+ case Name of
+ "pchScheduledConnectionAlarm" ->
+ [Sender];
+ "pchVpVcAlarm" ->
+ [Sender];
+ "pchSystemMemoryAlarm" ->
+ [Sender];
+ "uniProtocolRestartFailureAlarm" ->
+ [Sender];
+ "spvcScheduledConnectionAlarm" ->
+ [Sender];
+ "eqmSwitchCoreInterfaceAlarm" ->
+ [Sender];
+ "atmPhysicalLayerAlarm" ->
+ [Sender];
+ "atmBufferCongestionAlarm" ->
+ [Sender];
+ "sdhLinkAlarm" ->
+ [Sender];
+ "sdhFarEndAlarm" ->
+ [Sender];
+ "sdhUpperQosAlarm" ->
+ [Sender];
+ "sdhLowerQosAlarm" ->
+ [Sender];
+ "eqmSwitchCoreAlarm" ->
+ [Sender];
+ "eqmEtAlarm" ->
+ [Sender];
+ "eqmHwIdentityFaultAlarm" ->
+ [Sender];
+ "eqmOperatorBlockedEquipmentAlarm" ->
+ [Sender];
+ "pdh34PathAlarm" ->
+ [Sender];
+ "pdh34ObservationAlarm" ->
+ [Sender];
+ "pdh34UpperQosAlarm" ->
+ [Sender];
+ "pdh34LowerQosAlarm" ->
+ [Sender];
+ "nsySynchRefAlarm" ->
+ [Sender];
+ "nsySynchRefBlockedAlarm" ->
+ [Sender];
+ "nsySynchNodeHoldoverAlarm" ->
+ [Sender];
+ "nsySynchNodeNotWorkingAlarm" ->
+ [Sender];
+ "eqmAtbAlarm" ->
+ [Sender];
+ "eqmCbEtAlarm" ->
+ [Sender];
+ "eqmCpAlarm" ->
+ [Sender];
+ "eqmCpInterfaceAlarm" ->
+ [Sender];
+ "eqmCbClkAlarm" ->
+ [Sender];
+ "eqmCbClkInterfaceAlarm" ->
+ [Sender];
+ "eqmCbClkVelocityAlarm" ->
+ [Sender];
+ "eqmCbClkPhaseDiffAlarm" ->
+ [Sender];
+ "eqmHwNotFoundAlarm" ->
+ [Sender];
+ "eqmPduAlarm" ->
+ [Sender];
+ "eqmFanAlarm" ->
+ [Sender];
+ "eqmLocAlarm" ->
+ [Sender];
+ "eqmCustomerDefined1Alarm" ->
+ [Sender];
+ "eqmCustomerDefined2Alarm" ->
+ [Sender];
+ "eqmCustomerDefined3Alarm" ->
+ [Sender];
+ "eqmCustomerDefined4Alarm" ->
+ [Sender];
+ "eqmOperatorBlockedLinkAlarm" ->
+ [Sender];
+ "eqmPowerFilterAlarm" ->
+ [Sender];
+ "eqmCbAbrAlarm" ->
+ [Sender];
+ "eqmAlarmCutOffAlarm" ->
+ [Sender];
+ OtherAlarm ->
+ [Sender]
+ end,
+
+ %% The testHeap instruction generated here will move up to before
+ %% the case.
+
+ bar:foo("<TABLE>
+ <TR><TD ALIGN=LEFT>Fault id:
+ <TD>" ++ FaultId ++ "
+ <TR><TD ALIGN=LEFT>Name:
+ <TD>" ++ Name ++ "
+ <TR><TD ALIGN=LEFT>Sender:
+ <TD>" ++ SenderLink ++ "
+ <TR><TD ALIGN=LEFT>Class:
+ <TD>" ++ Type ++ "
+ <TR><TD ALIGN=LEFT>Cause:
+ <TD>" ++ Cause ++ "
+ <TR><TD ALIGN=LEFT>Severity:
+ <TD>" ++ Severity ++ "
+ <TR><TD ALIGN=LEFT>Information:
+ <TD>" ++ Info ++ "
+ <TR><TD ALIGN=LEFT>Time:
+ <TD>" ++ Time).
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_8.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_8.erl
new file mode 100644
index 0000000000..f1f4839798
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_8.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_8).
+
+-compile(export_all).
+
+beam_compiler_8() ->
+ ok.
+
+t(Key, Me) ->
+ Fun = fun(X) ->
+ me_rec:key_values(X, Key) < me_rec:key_values(Me, Key)
+ end.
+
+
diff --git a/lib/compiler/test/compilation_SUITE_data/beam_compiler_9.erl b/lib/compiler/test/compilation_SUITE_data/beam_compiler_9.erl
new file mode 100644
index 0000000000..581b908753
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/beam_compiler_9.erl
@@ -0,0 +1,67 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_compiler_9).
+
+-export([compile/2, test/0, ?MODULE/0]).
+
+?MODULE() ->
+ ok.
+
+test() ->
+ Failures = failures(),
+ compile_files([hd(Failures)]).
+
+compile_files([File | Files]) ->
+ Pid = spawn(?MODULE, compile, [File, self()]),
+ Time = infinity,
+ receive
+ done ->
+ compile_files(Files)
+ after
+ Time ->
+ io:fwrite("Compilation not completed within ~w ms~n", [Time]),
+ exit(Pid, die),
+ compile_files(Files)
+ end;
+
+compile_files([]) ->
+ done.
+
+
+
+compile(File, Parent) ->
+ io:fwrite("Compiling: ~s~n", [File]),
+ statistics(runtime),
+ statistics(wall_clock),
+ statistics(reductions),
+ Result = c:c(File),
+ {_, Rslc} = statistics(runtime),
+ {_, Tslc} = statistics(wall_clock),
+ {_, Reds} = statistics(reductions),
+ io:fwrite("Result: ~w~n", [Result]),
+ io:fwrite("Reductions: ~w~n", [Reds]),
+ io:fwrite("Time: ~w~n", [Tslc]),
+ io:fwrite("Cpu time: ~w~n", [Rslc]),
+ io:nl(),
+ Parent ! done.
+
+
+
+failures() ->
+ [test].
diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_1.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_1.erl
new file mode 100644
index 0000000000..7df1543d83
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_1.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bin_syntax_1).
+
+-export([f/2,?MODULE/0]).
+
+?MODULE() ->
+ ok.
+
+f(X, Y) ->
+ case X of
+ a ->
+ Y2 = 8
+ end,
+ <<5:Y2>> = Y.
diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_2.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_2.erl
new file mode 100644
index 0000000000..dcf7b0f8bd
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_2.erl
@@ -0,0 +1,41 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bin_syntax_2).
+
+-export([?MODULE/0]).
+
+%% This module tests that constant propagation is done properly.
+
+?MODULE() ->
+ 258 = b(<<1,2>>),
+ F = c(),
+ 259 = F(<<1,3>>),
+ ok.
+
+b(B) ->
+ Sz = 16,
+ <<X:Sz/integer>> = B,
+ X.
+
+c() ->
+ Size = 16,
+ fun(Bin) ->
+ <<X:Size/integer>> = Bin,
+ X
+ end.
diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_3.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_3.erl
new file mode 100644
index 0000000000..93d35d5628
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_3.erl
@@ -0,0 +1,35 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bin_syntax_3).
+-export([?MODULE/0,decode_integer/3]).
+
+?MODULE() ->
+ ok.
+
+decode_integer(Len, <<B1:1,B2:7,Bs/binary>>, RemovedBytes) when B1 == 0 ->
+ Bin = <<Skip:Len/unit:8, Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>,
+ Size = size(Bin),
+ <<Int:Size/unit:8>> = Bin,
+ {Int,Buffer2,RemovedBytes};
+decode_integer(Len,<<B1:1,B2:7,Bs/binary>>,RemovedBytes) ->
+ Bin = <<Skip:Len/unit:8,Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>,
+ Size = size(Bin),
+ <<N:Size/unit:8>> = <<B2,Bs/binary>>,
+ Int = N - (1 bsl (8 * size(Bin) -1)),
+ {Int,Buffer2,RemovedBytes}.
diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_4.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_4.erl
new file mode 100644
index 0000000000..fe0ce80270
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_4.erl
@@ -0,0 +1,32 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bin_syntax_4).
+-export([?MODULE/0,f4b/2,f4c/2]).
+
+?MODULE() ->
+ ok.
+
+f4b(X, Y) ->
+ fun (<< A:Y >>, Y, B) -> fum(A, X, Y, B) end.
+
+f4c(X, Y) ->
+ fun (Y, << A:Y >>, B) -> fum(A, X, Y, B) end.
+
+fum(A, B, C, D) ->
+ {A,B,C,D}.
diff --git a/lib/compiler/test/compilation_SUITE_data/bin_syntax_6.erl b/lib/compiler/test/compilation_SUITE_data/bin_syntax_6.erl
new file mode 100644
index 0000000000..8de3a9094f
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/bin_syntax_6.erl
@@ -0,0 +1,39 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bin_syntax_6).
+-export([?MODULE/0,x/1,y/1]).
+
+?MODULE() ->
+ ok.
+
+x(X) ->
+ blurf(),
+ B = {X,"OK",<<>>},
+ catch b({a,B}).
+
+y(X) ->
+ blurf(),
+ B = {X,"OK",<<42>>},
+ catch b({a,B}).
+
+blurf() ->
+ ok.
+
+b(_) ->
+ ok.
diff --git a/lib/compiler/test/compilation_SUITE_data/catch_in_catch.erl b/lib/compiler/test/compilation_SUITE_data/catch_in_catch.erl
new file mode 100644
index 0000000000..c732a912f0
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/catch_in_catch.erl
@@ -0,0 +1,51 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(catch_in_catch).
+
+-export([?MODULE/0,do_start/1]).
+
+?MODULE() ->
+ process_flag(trap_exit, true),
+ Pid = spawn_link(?MODULE, do_start, [x]),
+ receive
+ {'EXIT',Pid,good_exit} -> ok;
+ Other ->
+ io:format("Unexpected: ~p\n", [Other]),
+ error
+ after 32000 ->
+ io:format("No message received\n"),
+ error
+ end.
+
+do_start(Param) ->
+ init(Param),
+ exit(good_exit).
+
+init(Param) ->
+ process_flag(trap_exit, true),
+ %% The catches were improperly nested, causing a "No catch found" crash.
+ (catch begin
+ foo(Param),
+ (catch exit(bar))
+ end
+ ),
+ ignore.
+
+foo(_) ->
+ ok.
diff --git a/lib/compiler/test/compilation_SUITE_data/compiler_1.erl b/lib/compiler/test/compilation_SUITE_data/compiler_1.erl
new file mode 100644
index 0000000000..6dbd80d962
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/compiler_1.erl
@@ -0,0 +1,742 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(compiler_1).
+-compile([export_all]).
+
+compiler_1() -> ok.
+
+-define(log(Format,Args),mnesia_test_lib:log(Format,Args,?FILE,?LINE)).
+-define(warning(Format,Args),?log("<WARNING> " ++ Format,Args)).
+-define(error(Format,Args),
+ mnesia_test_lib:note_error(Format,Args,?FILE,?LINE),
+ ?log("<ERROR> " ++ Format,Args)).
+
+-define(match(ExpectedRes,Expr),
+ fun() ->
+ AcTuAlReS = (catch (Expr)),
+ case AcTuAlReS of
+ ExpectedRes ->
+ ?log("ok, result as expected: ~p~n",[AcTuAlReS]),
+ {success,AcTuAlReS};
+ _ ->
+ ?error("actual result was: ~p~n",[AcTuAlReS]),
+ {fail,AcTuAlReS}
+ end
+ end()).
+
+-define(match_inverse(NotExpectedRes,Expr),
+ fun() ->
+ AcTuAlReS = (catch (Expr)),
+ case AcTuAlReS of
+ NotExpectedRes ->
+ ?error("actual result was: ~p~n",[AcTuAlReS]),
+ {fail,AcTuAlReS};
+ _ ->
+ ?log("ok, result as expected: ~p~n",[AcTuAlReS]),
+ {success,AcTuAlReS}
+ end
+ end()).
+
+-define(match_receive(ExpectedMsg),
+ ?match(ExpectedMsg,mnesia_test_lib:pick_msg())).
+
+%% ExpectedMsgs must be completely bound
+-define(match_multi_receive(ExpectedMsgs),
+ fun() ->
+ TmPeXpCtEdMsGs = lists:sort(ExpectedMsgs),
+ ?match(TmPeXpCtEdMsGs,
+ lists:sort(lists:map(fun(_) ->
+ mnesia_test_lib:pick_msg()
+ end,
+ TmPeXpCtEdMsGs)))
+ end()).
+
+-define(setup(), mnesia_test_lib:setup(?FILE,?LINE)).
+
+-define(start_activities(Nodes),
+ fun() ->
+ AcTiViTyPiDs =
+ lists:map(fun(Node) ->
+ spawn_link(Node,
+ mnesia_test_lib,
+ activity_evaluator,
+ [self()])
+ end,
+ Nodes),
+ ?match_multi_receive(AcTiViTyPiDs)
+ end()).
+
+-define(start_transactions(Pids),
+ ?match_multi_receive(lists:map(fun(Pid) ->
+ Pid ! begin_trans,
+ {Pid,begin_trans}
+ end,
+ Pids))).
+
+-define(acquire_nodes(N,Nodes),
+ mnesia_test_lib:acquire_nodes(N,Nodes,?FILE,?LINE)).
+
+
+
+%%% Copyright (C) 1996, Ellemtel Telecommunications Systems Laboratories
+%%% Author: Hakan Mattsson [email protected]
+%%% Purpose: Evil usage of the API
+%%%
+%%% Invoke all functions in the API and try to cover all legal uses
+%%% cases as well the illegal dito. This is a complement to the
+%%% other more explicit test cases.
+%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%
+%%% show/0
+%%%
+%%% Prints out the complete test case structure
+%%%
+%%% show/1
+%%%
+%%% Prints out parts of the test case structure
+%%%
+%%% test/0
+%%%
+%%% Run the complete test suite.
+%%% Reads Nodes from nodes.profile and starts them if neccessary.
+%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
+%%%
+%%% test/1
+%%%
+%%% Run parts of the test suite.
+%%% Reads Nodes from nodes.profile and starts them if neccessary.
+%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
+%%%
+%%% test/2
+%%%
+%%% Run parts of the test suite on the given Nodes,
+%%% assuming that the nodes are up and running.
+%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
+%%%
+%%% test/3
+%%%
+%%% Run parts of the test suite on permutations of the given Nodes,
+%%% assuming that the nodes are up and running. Uses test/2.
+%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
+%%%
+%%% See the module mnesia_test_lib for further information.
+%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+show() -> mnesia_test_lib:show([{?MODULE,all}]).
+show(TestCases) -> mnesia_test_lib:show([{?MODULE,TestCases}]).
+test() -> mnesia_test_lib:test([{?MODULE,all}]).
+test(TestCases) -> mnesia_test_lib:test([{?MODULE,TestCases}]).
+test(TestCases,Nodes) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes).
+test(TestCases,Nodes,Config) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes,Config).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+old_all(suite) ->
+ [
+ system_info, table_info, error_description,
+ db_node_lifecycle, start_and_stop, transaction, checkpoint, backup,
+ table_lifecycle, replica_management, replica_location, index_lifecycle,
+ trans_access, dirty_access, table_sync, snmp_access, debug_support
+ ].
+
+trans_access(suite) ->
+ [ {mnesia_dirty_access_test,all} ].
+
+dirty_access(suite) ->
+ [ {mnesia_trans_access_test,all} ].
+
+%% Get meta info about Mnesia
+system_info(suite) -> [];
+system_info(Nodes) ->
+ ?match(yes,mnesia:system_info(is_running)),
+ ?match(Nodes,mnesia:system_info(db_nodes)),
+ ?match(Nodes,mnesia:system_info(running_db_nodes)),
+ ?match(true,mnesia:system_info(have_disc)),
+ ?match(A when atom(A),mnesia:system_info(debug)),
+ ?match(L when list(L),mnesia:system_info(directory)),
+ ?match(L when list(L),mnesia:system_info(log_version)),
+ ?match({_,_},mnesia:system_info(schema_version)),
+ ?match(L when list(L),mnesia:system_info(tables)),
+ ?match(L when list(L),mnesia:system_info(local_tables)),
+ ?match(L when list(L),mnesia:system_info(held_locks)),
+ ?match(L when list(L),mnesia:system_info(lock_queue)),
+ ?match(L when list(L),mnesia:system_info(transactions)),
+ ?match(I when integer(I),mnesia:system_info(transaction_failures)),
+ ?match(I when integer(I),mnesia:system_info(transaction_commits)),
+ ?match(I when integer(I),mnesia:system_info(transaction_restarts)),
+ ?match(L when list(L),mnesia:system_info(checkpoints)),
+ ?match(A when atom(A),mnesia:system_info(backup_module)),
+ ?match(true,mnesia:system_info(auto_repair)),
+ ?match({_,_},mnesia:system_info(dump_log_interval)),
+ ?match(A when atom(A),mnesia:system_info(dump_log_update_in_place)),
+ ?match(I when integer(I),mnesia:system_info(transaction_log_writes)),
+ ?match({'EXIT',{aborted,badarg}},mnesia:system_info(ali_baba)),
+ done.
+
+%% Get meta info about table
+table_info(suite) -> [];
+table_info(Nodes) ->
+ [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes),
+
+ Tab = table_info,
+ Type = bag,
+ ValPos = 3,
+ Attrs = [k,v],
+ Arity = length(Attrs) +1,
+ Schema = [{name,Tab},{type,Type},{attributes,Attrs},{index,[ValPos]},
+ {disc_only_copies,[Node1]},{ram_copies,[Node2]},{disc_copies,[Node3]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+
+ Size = 10,
+ Keys = lists:seq(1,Size),
+ Records = [{Tab,A,7} || A <- Keys],
+ lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records),
+ ?match(Mem when integer(Mem),mnesia:table_info(Tab,memory)),
+ ?match(Size,mnesia:table_info(Tab,size)),
+ ?match(Type,mnesia:table_info(Tab,type)),
+ ?match([Node3],mnesia:table_info(Tab,disc_copies)),
+ ?match([Node2],mnesia:table_info(Tab,ram_copies)),
+ ?match([Node1],mnesia:table_info(Tab,disc_only_copies)),
+ Read = [Node1,Node2,Node3],
+ ?match(true,lists:member(mnesia:table_info(Tab,where_to_read),Read)),
+ Write = lists:sort([Node1,Node2,Node3]),
+ ?match(Write,lists:sort(mnesia:table_info(Tab,where_to_write))),
+ WriteLock = lists:sort([Node2,Node3]),
+ ?match([ValPos],mnesia:table_info(Tab,index)),
+ ?match(Arity,mnesia:table_info(Tab,arity)),
+ ?match(Attrs,mnesia:table_info(Tab,attributes)),
+ ?match({Tab,'_','_'},mnesia:table_info(Tab,wild_pattern)),
+ ?match({atomic,Attrs}, mnesia:transaction(fun() ->
+ mnesia:table_info(Tab,attributes) end)),
+
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Add and drop db nodes
+
+db_node_lifecycle(suite) -> [];
+db_node_lifecycle(Nodes) ->
+ [Node1,Node2] = ?acquire_nodes(2,Nodes),
+ Tab = db_node_lifecycle,
+
+ Schema = [{name,Tab},{ram_copies,[Node1,Node2]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ ?match({aborted,active}, rpc:call(Node1,mnesia,del_db_node,[Node2])),
+
+ ?match([], mnesia_test_lib:stop_mnesia(Nodes)),
+ ?match(ok, mnesia:delete_schema(Nodes)),
+ ?match({error,_}, mnesia:create_schema(foo)),
+ ?match({error,_}, mnesia:create_schema([foo])),
+ ?match({error,_}, mnesia:create_schema([foo@bar])),
+ ?match({error,_}, mnesia:start()),
+
+ ?match(ok, mnesia:create_schema(Nodes)),
+ ?match([],mnesia_test_lib:start_mnesia(Nodes)),
+ ?match({atomic,ok}, rpc:call(Node1,mnesia,del_db_node,[Node2])),
+ ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[Node2])),
+ ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo])),
+ ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo@bar])),
+
+ ?match([], mnesia_test_lib:stop_mnesia([Node2])),
+ ?match(ok,mnesia:delete_schema([Node2])),
+ AddFun = fun() -> ?match({aborted,nested_transaction},
+ mnesia:add_db_node(Node2)), ok end,
+ ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[AddFun])),
+ DelFun = fun() -> ?match({aborted,nested_transaction},
+ mnesia:del_db_node(Node2)), ok end,
+ ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[DelFun])),
+
+ ?match({atomic,ok}, rpc:call(Node1,mnesia,add_db_node,[Node2])),
+ ?match({aborted,already_exists}, rpc:call(Node1,mnesia,add_db_node,[Node2])),
+ ?match([],mnesia_test_lib:start_mnesia([Node2])),
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Start and stop the system
+
+start_and_stop(suite) -> [];
+start_and_stop(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+
+ ?match(stopped, rpc:call(Node1,mnesia,stop,[])),
+ ?match(stopped, rpc:call(Node1,mnesia,stop,[])),
+ ?match({started,_}, rpc:call(Node1,mnesia,start,[])),
+ ?match({started,_}, rpc:call(Node1,mnesia,start,[])),
+ ?match(stopped, rpc:call(Node1,mnesia,stop,[])),
+ ?match([],mnesia_test_lib:start_mnesia(Nodes)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Checkpoints and backup management
+
+checkpoint(suite) -> [];
+checkpoint(Nodes) ->
+ OneNode = ?acquire_nodes(1,Nodes),
+ checkpoint(OneNode,Nodes),
+ TwoNodes = ?acquire_nodes(2,Nodes),
+ checkpoint(TwoNodes,Nodes).
+
+checkpoint(TabNodes,Nodes) ->
+ [Node1] = ?acquire_nodes(1,TabNodes),
+ CreateTab = fun(Type,N,Ns) ->
+ Tab0 = lists:concat(["local_checkpoint_",Type,N]),
+ Tab = list_to_atom(Tab0),
+ Schema = [{name,Tab},{Type,Ns}],
+ ?match({atomic,ok},mnesia:delete_table(Tab)),
+ ?match({atomic,ok},mnesia:create_table(Schema)),
+ Tab
+ end,
+ CreateTabs = fun(Type) ->
+ CreateTab(Type,1,hd(TabNodes)),
+ CreateTab(Type,2,TabNodes),
+ CreateTab(Type,3,lists:last(TabNodes))
+ end,
+ Types = [ram_copies,disc_copies,disc_only_copies],
+ Tabs = lists:append(lists:map(CreateTabs,Types)),
+ Recs = lists:sort([{T,N,N} || T <- Tabs,N <- lists:seq(1,10)]),
+ lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs),
+
+ CpName = a_checkpoint_name,
+ MinArgs = [{name,CpName},{min,Tabs},{allow_remote,false}],
+ ?match({ok,CpName,[Node1]},
+ rpc:call(Node1,mnesia,activate_checkpoint,[MinArgs])),
+ ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])),
+
+ MaxArgs = [{name,CpName},{max,Tabs},{allow_remote,true}],
+ ?match({ok,CpName,[Node1]},
+ rpc:call(Node1,mnesia,activate_checkpoint,[MaxArgs])),
+ ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])),
+
+ Args = [{name,CpName},{min,Tabs},{allow_remote,false}],
+ ?match({ok,CpName,[Node1]},
+ rpc:call(Node1,mnesia,activate_checkpoint,[Args])),
+ Recs2 = lists:sort([{T,K,0} || {T,K,_} <- Recs]),
+ lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs2),
+ ?match({atomic,ok},rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])),
+
+ ?match({error,no_exists},mnesia:deactivate_checkpoint(CpName)),
+ ?match({error,badarg},mnesia:activate_checkpoint(foo)),
+ ?match({error,badarg},mnesia:activate_checkpoint([{foo,foo}])),
+ ?match({error,badarg},mnesia:activate_checkpoint([{max,foo}])),
+ ?match({error,badarg},mnesia:activate_checkpoint([{min,foo}])),
+ ?match({error,no_exists},mnesia:activate_checkpoint([{min,[foo@bar]}])),
+ ?match({error,badarg},mnesia:activate_checkpoint([{allow_remote,foo}])),
+
+ Fun = fun(Tab) -> ?match({atomic,ok},mnesia:delete_table(Tab)) end,
+ lists:foreach(Fun,Tabs),
+ done.
+
+backup(suite) ->
+ [
+ backup_schema, restore_schema, backup_checkpoint, restore_tables
+ ].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Use and misuse transactions
+
+transaction(suite) -> [];
+transaction(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+ ?match({atomic,ali_baba}, mnesia:transaction(fun() -> ali_baba end)),
+ ?match({aborted,_}, mnesia:transaction(no_fun)),
+ ?match({aborted,_}, mnesia:transaction(?MODULE,no_fun,[foo])),
+
+ {success,[A,B,C,D,E,F,G,H]} = ?start_activities(lists:duplicate(8,Node1)),
+ ?start_transactions([A,B,C,D,E,F,G,H]),
+
+ A ! fun() -> mnesia:abort(abort_bad_trans) end,
+ ?match_receive({A,{aborted,abort_bad_trans}}),
+
+ B ! fun() -> 1 = 2 end,
+ ?match_receive({B,{aborted,_}}),
+
+ C ! fun() -> throw(throw_bad_trans) end,
+ ?match_receive({C,{aborted,{throw,throw_bad_trans}}}),
+
+ D ! fun() -> exit(exit_bad_trans) end,
+ ?match_receive({D,{aborted,exit_bad_trans}}),
+
+ E ! fun() -> exit(normal) end,
+ ?match_receive({E,{aborted,normal}}),
+
+ F ! fun() -> exit(abnormal) end,
+ ?match_receive({F,{aborted,abnormal}}),
+
+ G ! fun() -> exit(G,abnormal) end,
+ ?match_receive({'EXIT',G,abnormal}),
+
+ H ! fun() -> exit(H,kill) end,
+ ?match_receive({'EXIT',H,killed}),
+
+ ?match({atomic,ali_baba},
+ mnesia:transaction(fun() -> ali_baba end,infinity)),
+ ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,1)),
+ ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,0)),
+ ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,-1)),
+ ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,foo)),
+ Fun = fun() -> ?match({aborted,nested_transaction},
+ mnesia:transaction(fun() -> ok end)), ok end,
+ ?match({atomic,ok},mnesia:transaction(Fun)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Create and delete tables
+
+%% Get meta info about table
+
+replica_location(suite) -> [];
+replica_location(Nodes) ->
+ [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes),
+ Tab = replica_location,
+
+ %% Create three replicas
+ Schema = [{name,Tab},{disc_only_copies,[Node1]},
+ {ram_copies,[Node2]},{disc_copies,[Node3]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1],[Node2],[Node3],Nodes),
+
+ %% Delete one replica
+ ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node3],Nodes),
+
+ %% Move one replica
+ ?match({atomic,ok}, mnesia:move_table_copy(Tab, Node1, Node2)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node3],Nodes),
+
+ %% Change replica type
+ ?match({atomic,ok}, mnesia:change_table_copy_type(Tab, Node2,ram_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[],[Node2],[Node3],Nodes),
+
+ done.
+
+table_lifecycle(suite) -> [];
+table_lifecycle(Nodes) ->
+ [Node1,Node2] = ?acquire_nodes(2,Nodes),
+
+ ?match({atomic,ok}, mnesia:create_table([{type,bag},
+ {ram_copies,[Node1]},
+ {attributes,[rajtan,tajtan]},
+ {name,order_of_args}])),
+ ?match([],mnesia:dirty_read({order_of_args,4711})),
+ ?match({atomic,ok}, mnesia:create_table([{name,already_exists},
+ {ram_copies,[Node1]}])),
+ ?match({aborted,already_exists},
+ mnesia:create_table([{name,already_exists},{ram_copies,[Node1]}])),
+ ?match({aborted,not_a_db_node},
+ mnesia:create_table([{name,no_node},{ram_copies,[foo]}])),
+ ?match({aborted,not_a_db_node},
+ mnesia:create_table([{name,no_host},{ram_copies,[foo@bar]}])),
+ ?match({aborted,badarg},
+ mnesia:create_table([{name,zero_arity},{attributes,[]}])),
+ ?match({aborted,badarg}, mnesia:create_table([])),
+ ?match({aborted,badarg}, mnesia:create_table(atom)),
+ ?match({aborted,badarg},
+ mnesia:create_table({cstruct,table_name_as_atom})),
+ ?match({aborted,bad_type},
+ mnesia:create_table([{name,no_host},{ram_copies,foo}])),
+ ?match({aborted,bad_type},
+ mnesia:create_table([{name,no_host},{disc_only_copies,foo}])),
+ ?match({aborted,bad_type},
+ mnesia:create_table([{name,no_host},{disc_copies,foo}])),
+
+ CreateFun =
+ fun() -> ?match({aborted,nested_transaction},
+ mnesia:create_table([{name,nested_trans}])), ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(CreateFun)),
+ ?match({atomic,ok},mnesia:create_table([{name,remote_tab},
+ {ram_copies,[Node2]}])),
+
+ ?match({atomic,ok}, mnesia:create_table([{name,a_brand_new_tab},
+ {ram_copies,[Node1]}])),
+ ?match([],mnesia:dirty_read({a_brand_new_tab,4711})),
+ ?match({atomic,ok}, mnesia:delete_table(a_brand_new_tab)),
+ ?match({'EXIT',{aborted,no_exists}},
+ mnesia:dirty_read({a_brand_new_tab,4711})),
+ ?match({aborted,no_exists}, mnesia:delete_table(a_brand_new_tab)),
+ ?match({aborted,badarg}, mnesia:create_table([])),
+
+ ?match({atomic,ok}, mnesia:create_table([{name,nested_del_trans},
+ {ram_copies,[Node1]}])),
+ DeleteFun = fun() -> ?match({aborted,nested_transaction},
+ mnesia:delete_table(nested_del_trans)), ok end,
+ ?match({atomic,ok}, mnesia:transaction(DeleteFun)),
+
+ ?match({aborted,bad_type},
+ mnesia:create_table([{name,create_with_index},{index,2}])),
+ ?match({aborted,bad_index},
+ mnesia:create_table([{name,create_with_index},{index,[-1]}])),
+ ?match({aborted,bad_index},
+ mnesia:create_table([{name,create_with_index},{index,[0]}])),
+ ?match({aborted,bad_index},
+ mnesia:create_table([{name,create_with_index},{index,[1]}])),
+ ?match({aborted,bad_index},
+ mnesia:create_table([{name,create_with_index},{index,[2]}])),
+ ?match({atomic,ok},
+ mnesia:create_table([{name,create_with_index},{index,[3]},
+ {ram_copies,[Node1]}])),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Add, drop and move replicas, change storage types
+%% Change table layout (only arity change supported)
+
+replica_management(suite) -> [];
+replica_management(Nodes) ->
+ %% add_table_copy/3, del_table_copy/2, move_table_copy/3,
+ %% change_table_copy_type/3, transform_table/3
+
+ [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes),
+
+ Tab = replica_management,
+ Attrs = [k,v],
+
+ %%
+ %% Add, delete and change replicas
+ %%
+ ?match({atomic,ok},
+ mnesia:create_table([{name,Tab},{attributes,Attrs},
+ {ram_copies,[Node1]}])),
+ mnesia_test_lib:verify_replica_location(Tab,[],[Node1],[],Nodes),
+ %% R - -
+ ?match({aborted,combine_error},
+ mnesia:add_table_copy(Tab, Node2, disc_copies)),
+ ?match({aborted,combine_error},
+ mnesia:change_table_copy_type(Tab, Node1, disc_copies)),
+ ?match({atomic,ok}, mnesia:del_table_copy(Tab,Node1)),
+ mnesia_test_lib:verify_replica_location(Tab,[],[],[],Nodes),
+ %% - - -
+ ?match({aborted,no_exists},
+ mnesia:add_table_copy(Tab, Node3, ram_copies)),
+
+ ?match({atomic,ok}, mnesia:create_table([{name,Tab},
+ {attributes,Attrs},
+ {disc_copies,[Node1]}])),
+ mnesia_test_lib:verify_replica_location(Tab,[],[],[Node1],Nodes),
+ %% D - -
+ ?match({aborted,badarg},
+ mnesia:add_table_copy(Tab, Node2, bad_storage_type)),
+ ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node2, disc_only_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node1],Nodes),
+ %% D DO -
+ ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node3, ram_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes),
+ %% D DO R
+ ?match({atomic,ok},
+ mnesia:change_table_copy_type(Tab, Node1, disc_only_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1,Node2],[Node3],[],Nodes),
+ %% DO DO R
+ ?match({aborted,already_exists},
+ mnesia:add_table_copy(Tab, Node3, ram_copies)),
+ ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node1)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[],Nodes),
+ %% - DO R
+ ?match({aborted,_}, mnesia:del_table_copy(Tab, Node1)),
+ ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node1, disc_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes),
+ %% D DO R
+ ?match({atomic,ok},
+ mnesia:change_table_copy_type(Tab, Node3, disc_only_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2,Node3],[],[Node1],Nodes),
+ %% D DO DO
+ ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node1],Nodes),
+ %% D - DO
+ ?match({aborted,already_exists},
+ mnesia:change_table_copy_type(Tab, Node1, disc_copies)),
+
+ %%
+ %% Move replica
+ %%
+ ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node1,Node2)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2],Nodes),
+ %% - D DO
+ ?match({aborted,_}, mnesia:move_table_copy(Tab,Node1,Node2)),
+ ?match([], mnesia_test_lib:stop_mnesia([Node3])),
+ mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2],
+ Nodes -- [Node3]),
+ %% - D DO
+ ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node3,Node1)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2],
+ Nodes -- [Node3]),
+ %% DO D -
+ ?match([],mnesia_test_lib:start_mnesia([Node3])),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2],Nodes),
+ %% DO D -
+
+ %%
+ %% Transformer
+ %%
+
+ NewAttrs = Attrs ++ [extra],
+ Transformer =
+ fun(Rec) -> list_to_tuple(tuple_to_list(Rec) ++ [initial_value]) end,
+ ?match({atomic,ok}, mnesia:transform_table(Tab, Transformer,NewAttrs)),
+ ?match({atomic,ok}, mnesia:transform_table(Tab, fun(R) -> R end, Attrs)),
+ ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, 0)),
+ ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, -1)),
+ ?match({aborted,badarg}, mnesia:transform_table(Tab, Transformer, [])),
+ ?match({aborted,bad_type}, mnesia:transform_table(Tab, no_fun, NewAttrs)),
+
+ NestedFun =
+ fun() ->
+ ?match({aborted,_},
+ mnesia:move_table_copy(Tab,Node1,Node2)),
+ ?match({aborted,_},
+ mnesia:add_table_copy(Tab,Node1,ram_copies)),
+ ?match({aborted,_},
+ mnesia:del_table_copy(Tab,Node1)),
+ T = fun(_) -> 4711 end,
+ ?match({aborted,_},
+ mnesia:transform_table(Tab,Transformer, T)),
+ ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(NestedFun)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Add and drop indecies
+
+index_lifecycle(suite) ->
+ [ add_table_index, create_live_table_index, del_table_index ].
+
+%% Add table index
+
+add_table_index(suite) -> [];
+add_table_index(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+ Tab = add_table_index,
+ Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ ValPos = 3,
+ BadValPos = ValPos + 1,
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,BadValPos)),
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,2)),
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,1)),
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,0)),
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,-1)),
+ ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)),
+ ?match({aborted,already_exists}, mnesia:add_table_index(Tab,ValPos)),
+
+ NestedFun = fun() ->
+ ?match({aborted,nested_transaction},
+ mnesia:add_table_index(Tab,ValPos)),
+
+ ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(NestedFun)),
+ done.
+
+create_live_table_index(suite) -> [];
+create_live_table_index(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+ Tab = create_live_table_index,
+ Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ ValPos = 3,
+ mnesia:dirty_write({Tab,1,2}),
+
+ Fun = fun() ->
+ ?match(ok, mnesia:write({Tab,2,2})),
+ ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(Fun)),
+ ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)),
+ done.
+
+%% Drop table index
+
+del_table_index(suite) ->[];
+del_table_index(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+ Tab = del_table_index,
+ Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ ValPos = 3,
+ BadValPos = ValPos + 1,
+ ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)),
+ ?match({aborted,no_exists},
+ mnesia:del_table_index(Tab,BadValPos)),
+ ?match({atomic,ok}, mnesia:del_table_index(Tab,ValPos)),
+
+ NestedFun =
+ fun() ->
+ ?match({aborted,nested_transaction},
+ mnesia:del_table_index(Tab,ValPos)),
+ ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(NestedFun)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Syncronize table with log or disc
+%%
+table_sync(suite) ->
+ [ dump_tables, dump_log, change_dump_log_config, wait_for_tables, force_load_table ].
+
+%% Dump ram tables on disc
+dump_tables(suite) -> [];
+dump_tables(Nodes) ->
+ [Node1,Node2] = ?acquire_nodes(2,Nodes),
+ Tab = dump_tables,
+ Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node2]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+
+ %% Dump 10 records
+ Size = 10,
+ Keys = lists:seq(1,Size),
+ Records = [{Tab,A,7} || A <- Keys],
+ lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records),
+ AllKeys = fun() -> lists:sort(mnesia:all_keys(Tab)) end,
+
+ ?match({atomic,Keys}, mnesia:transaction(AllKeys)),
+ ?match(ok, mnesia:dump_tables(Tab)),
+
+ %% Delete one record
+ ?match(ok,mnesia:dirty_delete({Tab,5})),
+ Keys2 = lists:delete(5,Keys),
+ ?match({atomic,Keys2}, mnesia:transaction(AllKeys)),
+
+ %% Check that all 10 is restored after a stop
+ ?match([], mnesia_test_lib:stop_mnesia([Node1,Node2])),
+ ?match([],mnesia_test_lib:start_mnesia([Node1,Node2])),
+ ?match(ok,mnesia:wait_for_tables([Tab],infinity)),
+ ?match({atomic,Keys}, mnesia:transaction(AllKeys)),
+
+ ?match(ok, mnesia:dump_tables([foo])),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Make Mnesia table accessible via SNMP
+
+snmp_access(suite) ->
+ [
+ snmp_open_table, snmp_close_table,
+ snmp_get_row, snmp_get_next_index, snmp_get_mnesia_key
+ ].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Check that the debug support has not decayed
+
+debug_support(suite) ->
+ [ info, schema, schema, kill, lkill ].
+
diff --git a/lib/compiler/test/compilation_SUITE_data/compiler_3.erl b/lib/compiler/test/compilation_SUITE_data/compiler_3.erl
new file mode 100644
index 0000000000..47891a22b5
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/compiler_3.erl
@@ -0,0 +1,33 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(compiler_3).
+-export([compiler_3/0]).
+-record(rec,{a}).
+
+compiler_3() ->
+ guard_record().
+
+guard_record() ->
+ 1=func(#rec{}),
+ {'EXIT',_} = (catch func({rec})),
+ ok.
+
+func(X) when record(X,
+rec) ->
+ 1.
diff --git a/lib/compiler/test/compilation_SUITE_data/compiler_5.erl b/lib/compiler/test/compilation_SUITE_data/compiler_5.erl
new file mode 100644
index 0000000000..c2a0c2064f
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/compiler_5.erl
@@ -0,0 +1,49 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(compiler_5).
+-export([compiler_5/0]).
+
+compiler_5() ->
+ f0(),
+ f1(),
+ f2(),
+ ok.
+
+%% compiler treats records with 1 and 2 fields differently...
+-record(nil, {}).
+-record(foo, {hello=1}).
+-record(bar, {hello=2,there=3}).
+
+f0() ->
+ R1 = #nil{},
+ R2 = R1#nil{}, %% stupid code, but compiler shouldn't crash
+ R1 = R2,
+ ok.
+
+f1() ->
+ R1 = #foo{},
+ R2 = R1#foo{}, %% stupid code, but compiler shouldn't crash
+ R1 = R2,
+ ok.
+
+f2() ->
+ R1 = #bar{},
+ R2 = R1#bar{}, %% stupid code, but compiler shouldn't crash
+ R1 = R2,
+ ok.
diff --git a/lib/compiler/test/compilation_SUITE_data/complex_guard.erl b/lib/compiler/test/compilation_SUITE_data/complex_guard.erl
new file mode 100644
index 0000000000..961aa6a460
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/complex_guard.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(complex_guard).
+
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f(X1,Y1,Z1) ->
+ if
+ ((X1 =:= 4) or (X1 =:= 5)) and ((Y1 =:= 4) or (Y1 =:= 5)) and ((Z1 =:= 4) or (Z1 =:= 5)) or ((X1 =:= 1) or (X1 =:= 2) or (X1 =:= 3)) and ((Y1 =:= 1) or (Y1 =:= 2) or (Y1 =:= 3)) and ((Z1 =:= 1) or (Z1 =:= 2) or (Z1 =:= 3)) ->
+ true
+ end.
+
diff --git a/lib/compiler/test/compilation_SUITE_data/const_list_256.erl b/lib/compiler/test/compilation_SUITE_data/const_list_256.erl
new file mode 100644
index 0000000000..0baf427911
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/const_list_256.erl
@@ -0,0 +1,282 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(const_list_256).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ put_list(x),
+ ok.
+
+put_list(A) ->
+ [{A, 255},
+ {A, 254},
+ {A, 253},
+ {A, 252},
+ {A, 251},
+ {A, 250},
+ {A, 249},
+ {A, 248},
+ {A, 247},
+ {A, 246},
+ {A, 245},
+ {A, 244},
+ {A, 243},
+ {A, 242},
+ {A, 241},
+ {A, 240},
+ {A, 239},
+ {A, 238},
+ {A, 237},
+ {A, 236},
+ {A, 235},
+ {A, 234},
+ {A, 233},
+ {A, 232},
+ {A, 231},
+ {A, 230},
+ {A, 229},
+ {A, 228},
+ {A, 227},
+ {A, 226},
+ {A, 225},
+ {A, 224},
+ {A, 223},
+ {A, 222},
+ {A, 221},
+ {A, 220},
+ {A, 219},
+ {A, 218},
+ {A, 217},
+ {A, 216},
+ {A, 215},
+ {A, 214},
+ {A, 213},
+ {A, 212},
+ {A, 211},
+ {A, 210},
+ {A, 209},
+ {A, 208},
+ {A, 207},
+ {A, 206},
+ {A, 205},
+ {A, 204},
+ {A, 203},
+ {A, 202},
+ {A, 201},
+ {A, 200},
+ {A, 199},
+ {A, 198},
+ {A, 197},
+ {A, 196},
+ {A, 195},
+ {A, 194},
+ {A, 193},
+ {A, 192},
+ {A, 191},
+ {A, 190},
+ {A, 189},
+ {A, 188},
+ {A, 187},
+ {A, 186},
+ {A, 185},
+ {A, 184},
+ {A, 183},
+ {A, 182},
+ {A, 181},
+ {A, 180},
+ {A, 179},
+ {A, 178},
+ {A, 177},
+ {A, 176},
+ {A, 175},
+ {A, 174},
+ {A, 173},
+ {A, 172},
+ {A, 171},
+ {A, 170},
+ {A, 169},
+ {A, 168},
+ {A, 167},
+ {A, 166},
+ {A, 165},
+ {A, 164},
+ {A, 163},
+ {A, 162},
+ {A, 161},
+ {A, 160},
+ {A, 159},
+ {A, 158},
+ {A, 157},
+ {A, 156},
+ {A, 155},
+ {A, 154},
+ {A, 153},
+ {A, 152},
+ {A, 151},
+ {A, 150},
+ {A, 149},
+ {A, 148},
+ {A, 147},
+ {A, 146},
+ {A, 145},
+ {A, 144},
+ {A, 143},
+ {A, 142},
+ {A, 141},
+ {A, 140},
+ {A, 139},
+ {A, 138},
+ {A, 137},
+ {A, 136},
+ {A, 135},
+ {A, 134},
+ {A, 133},
+ {A, 132},
+ {A, 131},
+ {A, 130},
+ {A, 129},
+ {A, 128},
+ {A, 127},
+ {A, 126},
+ {A, 125},
+ {A, 124},
+ {A, 123},
+ {A, 122},
+ {A, 121},
+ {A, 120},
+ {A, 119},
+ {A, 118},
+ {A, 117},
+ {A, 116},
+ {A, 115},
+ {A, 114},
+ {A, 113},
+ {A, 112},
+ {A, 111},
+ {A, 110},
+ {A, 109},
+ {A, 108},
+ {A, 107},
+ {A, 106},
+ {A, 105},
+ {A, 104},
+ {A, 103},
+ {A, 102},
+ {A, 101},
+ {A, 100},
+ {A, 99},
+ {A, 98},
+ {A, 97},
+ {A, 96},
+ {A, 95},
+ {A, 94},
+ {A, 93},
+ {A, 92},
+ {A, 91},
+ {A, 90},
+ {A, 89},
+ {A, 88},
+ {A, 87},
+ {A, 86},
+ {A, 85},
+ {A, 84},
+ {A, 83},
+ {A, 82},
+ {A, 81},
+ {A, 80},
+ {A, 79},
+ {A, 78},
+ {A, 77},
+ {A, 76},
+ {A, 75},
+ {A, 74},
+ {A, 73},
+ {A, 72},
+ {A, 71},
+ {A, 70},
+ {A, 69},
+ {A, 68},
+ {A, 67},
+ {A, 66},
+ {A, 65},
+ {A, 64},
+ {A, 63},
+ {A, 62},
+ {A, 61},
+ {A, 60},
+ {A, 59},
+ {A, 58},
+ {A, 57},
+ {A, 56},
+ {A, 55},
+ {A, 54},
+ {A, 53},
+ {A, 52},
+ {A, 51},
+ {A, 50},
+ {A, 49},
+ {A, 48},
+ {A, 47},
+ {A, 46},
+ {A, 45},
+ {A, 44},
+ {A, 43},
+ {A, 42},
+ {A, 41},
+ {A, 40},
+ {A, 39},
+ {A, 38},
+ {A, 37},
+ {A, 36},
+ {A, 35},
+ {A, 34},
+ {A, 33},
+ {A, 32},
+ {A, 31},
+ {A, 30},
+ {A, 29},
+ {A, 28},
+ {A, 27},
+ {A, 26},
+ {A, 25},
+ {A, 24},
+ {A, 23},
+ {A, 22},
+ {A, 21},
+ {A, 20},
+ {A, 19},
+ {A, 18},
+ {A, 17},
+ {A, 16},
+ {A, 15},
+ {A, 14},
+ {A, 13},
+ {A, 12},
+ {A, 11},
+ {A, 10},
+ {A, 9},
+ {A, 8},
+ {A, 7},
+ {A, 6},
+ {A, 5},
+ {A, 4},
+ {A, 3},
+ {A, 2},
+ {A, 1},
+ {A, 0}].
diff --git a/lib/compiler/test/compilation_SUITE_data/convopts.erl b/lib/compiler/test/compilation_SUITE_data/convopts.erl
new file mode 100644
index 0000000000..429c683ca9
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/convopts.erl
@@ -0,0 +1,159 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(convopts).
+
+-export([?MODULE/0]).
+
+-define(UINT32_MAX, ((1 bsl 32) - 1)).
+
+?MODULE() ->
+ Type = 12345,
+ Inst = 1,
+ Zone = 0,
+ case convopts([{dest, {tipc_name, Type, Inst, Zone}}]) of
+ {ok, [{$B, <<Type:32, Inst:32, Zone:32>>}]} ->
+ ok;
+ Other ->
+ {error, Other}
+ end.
+
+
+
+convopts(Opts) ->
+ catch
+ case getopts(Opts, [active, recvfrom, importance, distribution,
+ dest]) of
+ {[Active, Recvfrom, Importance, Distribution,
+ Dest], []} ->
+ {R, RR} =
+ case {Active, Recvfrom} of
+ {[], [recvfrom]} ->
+ throw({error, einval});
+ {_, [recvfrom]} ->
+ {$r, $R};
+ {_, _} ->
+ {$e, $E}
+ end,
+ {ok,
+ lists:flatten(
+ [case Active of
+ [{active, true}] ->
+ [{R, <<?UINT32_MAX:32>>}];
+ [{active, N}] when integer(N),
+ 0 =< N, N < ?UINT32_MAX ->
+ [{R, <<N:32>>}];
+ [{active, N}] when integer(N),
+ -?UINT32_MAX < N, N < 0 ->
+ [{RR, <<-N:32>>}];
+ [{active, once}] ->
+ [{R, <<1:32>>}];
+ [{active, false}] ->
+ [{R, <<0:32>>}];
+ [] ->
+ [];
+ _ ->
+ throw({error, einval})
+ end,
+ case Importance of
+ [{importance, normal}] ->
+ [{$i, []}];
+ [{importance, high}] ->
+ [{$I, []}];
+ [] ->
+ [];
+ _ ->
+ throw({error, einval})
+ end,
+ case Distribution of
+ [distribution] ->
+ [{$d, []}];
+ [] ->
+ [];
+ _ ->
+ throw({error, einval})
+ end,
+ case Dest of
+ %% Port addressed message
+ [{dest, {tipc_port_id, Port, Proc}}]
+ when binary(Port),
+ integer(Proc), 0 =< Proc, Proc =< ?UINT32_MAX
+ ;
+ list(Port),
+ integer(Proc), 0 =< Proc, Proc =< ?UINT32_MAX ->
+ [{$p, [Port | <<Proc:32>>]}];
+ %% Name addressed message
+ [{dest, {tipc_name, Type, Inst, Zone}}]
+ when integer(Type), 0 =< Type, Type =< ?UINT32_MAX,
+ integer(Inst), 0 =< Inst, Inst =< ?UINT32_MAX,
+ integer(Zone), 0 =< Zone, Zone =< ?UINT32_MAX ->
+ [{$B, <<Type:32, Inst:32, Zone:32>>}];
+ %%
+ %% This undocumented clause uses an undocumented
+ %% feature of the TIPC socket interface that takes
+ %% advantage of some gory internals of the protocol.
+ %% It is protocol implementation dependant and
+ %% breaks the whole idea of location transparency
+ %% for name addressed messages. Therefore it should
+ %% only be used when all other possibilities are
+ %% exhausted.
+ %%
+ [{dest, {tipc_name, Type, Inst,
+ {tipc_processor_id,
+ Zone, Subnetwork, Processor}}}]
+ when integer(Type), 0 =< Type, Type =< ?UINT32_MAX,
+ integer(Inst), 0 =< Inst, Inst =< ?UINT32_MAX,
+ integer(Zone),
+ 0 =< Zone, Zone < 16#FF,
+ integer(Subnetwork),
+ 0 =< Subnetwork, Subnetwork < 16#FFF,
+ integer(Processor),
+ 0 =< Processor, Processor < 16#FFF ->
+ [{$B, <<Type:32,
+ Inst:32,
+ Zone:8, Subnetwork:12, Processor:12>>}];
+ [] ->
+ [];
+ _ ->
+ throw({error, einval})
+ end
+ ])};
+ _ ->
+ throw({error, einval})
+ end.
+
+
+
+getopts(List, Options) when list(List), list(Options) ->
+ getopts_1(Options, List, []).
+
+getopts_1([], List, Result) ->
+ {lists:reverse(Result), List};
+getopts_1([Option | Options], List, Result) ->
+ {Optvals, Remaining} = getopts_2(List, Option, [], []),
+ getopts_1(Options, Remaining, [Optvals | Result]).
+
+getopts_2([], _Option, Result, Remaining) ->
+ {lists:reverse(Result), lists:reverse(Remaining)};
+getopts_2([Option | Tail], Option, Result, Remaining) ->
+ getopts_2(Tail, Option, [Option | Result], Remaining);
+getopts_2([Optval | Tail], Option, Result, Remaining)
+ when element(1, Optval) == Option ->
+ getopts_2(Tail, Option, [Optval | Result], Remaining);
+getopts_2([Other | Tail], Option, Result, Remaining) ->
+ getopts_2(Tail, Option, Result, [Other | Remaining]).
diff --git a/lib/compiler/test/compilation_SUITE_data/guards.erl b/lib/compiler/test/compilation_SUITE_data/guards.erl
new file mode 100644
index 0000000000..84e41b8ede
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/guards.erl
@@ -0,0 +1,106 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(guards).
+
+-export([guards/0]).
+
+guards() ->
+ ok = t(),
+ ok = f(),
+ ok = ct(1),
+ ok = multi(1),
+ ok = multi(2),
+ ok = multi(3).
+
+%% The following tests are always true.
+t() when integer(42) ->
+ ok;
+t() when float(2.0) ->
+ ok;
+t() when number(7) ->
+ ok;
+t() when number(3.14) ->
+ ok;
+t() when atom(error) ->
+ ok;
+t() when list([a]) ->
+ ok;
+t() when tuple({}) ->
+ ok;
+t() when tuple({1, 2}) ->
+ ok.
+
+%% The following tests are always false.
+f() when integer(a) ->
+ ok;
+f() when float(b) ->
+ ok;
+f() when number(c) ->
+ ok;
+f() when atom(42) ->
+ ok;
+f() when list(33) ->
+ ok;
+f() when list({}) ->
+ ok;
+f() when list({1, 2}) ->
+ ok;
+f() when tuple(33) ->
+ ok;
+f() when tuple([a]) ->
+ ok;
+f() when tuple([]) ->
+ ok;
+f() when tuple(35) ->
+ ok;
+f() ->
+ ok.
+
+%% The following tests are always true.
+ct(X) ->
+ case X of
+ Y when integer(42) ->
+ ok;
+ Y when float(2.0) ->
+ ok;
+ Y when number(7) ->
+ ok;
+ Y when number(3.14) ->
+ ok;
+ Y when atom(error) ->
+ ok;
+ Y when list([a]) ->
+ ok;
+ Y when tuple({}) ->
+ ok;
+ Y when tuple({1, 2}) ->
+ ok
+ end.
+
+multi(X) ->
+ case X of
+ Y when float(Y) ; integer(Y) ->
+ ok;
+ Y when Y > 1, Y < 10 ; atom(Y) ->
+ ok;
+ Y when Y == 4, number(Y) ; list(Y) ->
+ pannkaka;
+ Y when Y==3 ; Y==5 ; Y==6 ->
+ ok
+ end.
diff --git a/lib/compiler/test/compilation_SUITE_data/live_var.erl b/lib/compiler/test/compilation_SUITE_data/live_var.erl
new file mode 100644
index 0000000000..483eec0630
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/live_var.erl
@@ -0,0 +1,30 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(live_var).
+-export([?MODULE/0,start/0]).
+
+?MODULE() ->
+ ok.
+
+start() ->
+ receive
+ after 3000 ->
+ A = 5
+ end,
+ A.
diff --git a/lib/compiler/test/compilation_SUITE_data/long_string.erl b/lib/compiler/test/compilation_SUITE_data/long_string.erl
new file mode 100644
index 0000000000..b3cf77b13f
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/long_string.erl
@@ -0,0 +1,670 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(long_string).
+
+-export([?MODULE/0]).
+
+?MODULE() ->
+ Options = "some stupid long string",
+ 49252 = length(generate(Options, "348927432097sfkjfkljf329")),
+ ok.
+
+generate(Options, Glurf) ->
+ "asdhfaslfdjhhwleirsk e4kjhr430usduy fdk;///s llsjkf;laskjfsdfkjasdfkj
+sdkljflasdfkjasldkfjasd" ++ Options ++
+"CSAgICAgICBWZXJzaW9uIDIsIEp1bmUgMTk5MQoKIENvcHlyaWdodCAoQykgMTk4OSwgMTk5MSBG
+cmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIEluYy4KICAgICAgICAgICAgICAgICAgICAgICA1OSBU
+ZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCiBFdmVy
+eW9uZSBpcyBwZXJtaXR0ZWQgdG8gY29weSBhbmQgZGlzdHJpYnV0ZSB2ZXJiYXRpbSBjb3BpZXMK
+IG9mIHRoaXMgbGljZW5zZSBkb2N1bWVudCwgYnV0IGNoYW5naW5nIGl0IGlzIG5vdCBhbGxvd2Vk
+LgoKCQkJICAgIFByZWFtYmxlCgogIFRoZSBsaWNlbnNlcyBmb3IgbW9zdCBzb2Z0d2FyZSBhcmUg
+ZGVzaWduZWQgdG8gdGFrZSBhd2F5IHlvdXIKZnJlZWRvbSB0byBzaGFyZSBhbmQgY2hhbmdlIGl0
+LiAgQnkgY29udHJhc3QsIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMKTGljZW5zZSBpcyBpbnRlbmRl
+ZCB0byBndWFyYW50ZWUgeW91ciBmcmVlZG9tIHRvIHNoYXJlIGFuZCBjaGFuZ2UgZnJlZQpzb2Z0
+d2FyZS0tdG8gbWFrZSBzdXJlIHRoZSBzb2Z0d2FyZSBpcyBmcmVlIGZvciBhbGwgaXRzIHVzZXJz
+LiAgVGhpcwpHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFwcGxpZXMgdG8gbW9zdCBvZiB0aGUgRnJl
+ZSBTb2Z0d2FyZQpGb3VuZGF0aW9uJ3Mgc29mdHdhcmUgYW5kIHRvIGFueSBvdGhlciBwcm9ncmFt
+IHdob3NlIGF1dGhvcnMgY29tbWl0IHRvCnVzaW5nIGl0LiAgKFNvbWUgb3RoZXIgRnJlZSBTb2Z0
+d2FyZSBGb3VuZGF0aW9uIHNvZnR3YXJlIGlzIGNvdmVyZWQgYnkKdGhlIEdOVSBMaWJyYXJ5IEdl
+bmVyYWwgUHVibGljIExpY2Vuc2UgaW5zdGVhZC4pICBZb3UgY2FuIGFwcGx5IGl0IHRvCnlvdXIg
+cHJvZ3JhbXMsIHRvby4KCiAgV2hlbiB3ZSBzcGVhayBvZiBmcmVlIHNvZnR3YXJlLCB3ZSBhcmUg
+cmVmZXJyaW5nIHRvIGZyZWVkb20sIG5vdApwcmljZS4gIE91ciBHZW5lcmFsIFB1YmxpYyBMaWNl
+bnNlcyBhcmUgZGVzaWduZWQgdG8gbWFrZSBzdXJlIHRoYXQgeW91CmhhdmUgdGhlIGZyZWVkb20g
+dG8gZGlzdHJpYnV0ZSBjb3BpZXMgb2YgZnJlZSBzb2Z0d2FyZSAoYW5kIGNoYXJnZSBmb3IKdGhp
+cyBzZXJ2aWNlIGlmIHlvdSB3aXNoKSwgdGhhdCB5b3UgcmVjZWl2ZSBzb3VyY2UgY29kZSBvciBj
+YW4gZ2V0IGl0CmlmIHlvdSB3YW50IGl0LCB0aGF0IHlvdSBjYW4gY2hhbmdlIHRoZSBzb2Z0d2Fy
+ZSBvciB1c2UgcGllY2VzIG9mIGl0CmluIG5ldyBmcmVlIHByb2dyYW1zOyBhbmQgdGhhdCB5b3Ug
+a25vdyB5b3UgY2FuIGRvIHRoZXNlIHRoaW5ncy4KCiAgVG8gcHJvdGVjdCB5b3VyIHJpZ2h0cywg
+d2UgbmVlZCB0byBtYWtlIHJlc3RyaWN0aW9ucyB0aGF0IGZvcmJpZAphbnlvbmUgdG8gZGVueSB5
+b3UgdGhlc2UgcmlnaHRzIG9yIHRvIGFzayB5b3UgdG8gc3VycmVuZGVyIHRoZSByaWdodHMuClRo
+ZXNlIHJlc3RyaWN0aW9ucyB0cmFuc2xhdGUgdG8gY2VydGFpbiByZXNwb25zaWJpbGl0aWVzIGZv
+ciB5b3UgaWYgeW91CmRpc3RyaWJ1dGUgY29waWVzIG9mIHRoZSBzb2Z0d2FyZSwgb3IgaWYgeW91
+IG1vZGlmeSBpdC4KCiAgRm9yIGV4YW1wbGUsIGlmIHlvdSBkaXN0cmlidXRlIGNvcGllcyBvZiBz
+dWNoIGEgcHJvZ3JhbSwgd2hldGhlcgpncmF0aXMgb3IgZm9yIGEgZmVlLCB5b3UgbXVzdCBnaXZl
+IHRoZSByZWNpcGllbnRzIGFsbCB0aGUgcmlnaHRzIHRoYXQKeW91IGhhdmUuICBZb3UgbXVzdCBt
+YWtlIHN1cmUgdGhhdCB0aGV5LCB0b28sIHJlY2VpdmUgb3IgY2FuIGdldCB0aGUKc291cmNlIGNv
+ZGUuICBBbmQgeW91IG11c3Qgc2hvdyB0aGVtIHRoZXNlIHRlcm1zIHNvIHRoZXkga25vdyB0aGVp
+cgpyaWdodHMuCgogIFdlIHByb3RlY3QgeW91ciByaWdodHMgd2l0aCB0d28gc3RlcHM6ICgxKSBj
+b3B5cmlnaHQgdGhlIHNvZnR3YXJlLCBhbmQKKDIpIG9mZmVyIHlvdSB0aGlzIGxpY2Vuc2Ugd2hp
+Y2ggZ2l2ZXMgeW91IGxlZ2FsIHBlcm1pc3Npb24gdG8gY29weSwKZGlzdHJpYnV0ZSBhbmQvb3Ig
+bW9kaWZ5IHRoZSBzb2Z0d2FyZS4KCiAgQWxzbywgZm9yIGVhY2ggYXV0aG9yJ3MgcHJvdGVjdGlv
+biBhbmQgb3Vycywgd2Ugd2FudCB0byBtYWtlIGNlcnRhaW4KdGhhdCBldmVyeW9uZSB1bmRlcnN0
+YW5kcyB0aGF0IHRoZXJlIGlzIG5vIHdhcnJhbnR5IGZvciB0aGlzIGZyZWUKc29mdHdhcmUuICBJ
+ZiB0aGUgc29mdHdhcmUgaXMgbW9kaWZpZWQgYnkgc29tZW9uZSBlbHNlIGFuZCBwYXNzZWQgb24s
+IHdlCndhbnQgaXRzIHJlY2lwaWVudHMgdG8ga25vdyB0aGF0IHdoYXQgdGhleSBoYXZlIGlzIG5v
+dCB0aGUgb3JpZ2luYWwsIHNvCnRoYXQgYW55IHByb2JsZW1zIGludHJvZHVjZWQgYnkgb3RoZXJz
+IHdpbGwgbm90IHJlZmxlY3Qgb24gdGhlIG9yaWdpbmFsCmF1dGhvcnMnIHJlcHV0YXRpb25zLgoK
+ICBGaW5hbGx5LCBhbnkgZnJlZSBwcm9ncmFtIGlzIHRocmVhdGVuZWQgY29uc3RhbnRseSBieSBz
+b2Z0d2FyZQpwYXRlbnRzLiAgV2Ugd2lzaCB0byBhdm9pZCB0aGUgZGFuZ2VyIHRoYXQgcmVkaXN0
+cmlidXRvcnMgb2YgYSBmcmVlCnByb2dyYW0gd2lsbCBpbmRpdmlkdWFsbHkgb2J0YWluIHBhdGVu
+dCBsaWNlbnNlcywgaW4gZWZmZWN0IG1ha2luZyB0aGUKcHJvZ3JhbSBwcm9wcmlldGFyeS4gIFRv
+IHByZXZlbnQgdGhpcywgd2UgaGF2ZSBtYWRlIGl0IGNsZWFyIHRoYXQgYW55CnBhdGVudCBtdXN0
+IGJlIGxpY2Vuc2VkIGZvciBldmVyeW9uZSdzIGZyZWUgdXNlIG9yIG5vdCBsaWNlbnNlZCBhdCBh
+bGwuCgogIFRoZSBwcmVjaXNlIHRlcm1zIGFuZCBjb25kaXRpb25zIGZvciBjb3B5aW5nLCBkaXN0
+cmlidXRpb24gYW5kCm1vZGlmaWNhdGlvbiBmb2xsb3cuCgwKCQkgICAgR05VIEdFTkVSQUwgUFVC
+TElDIExJQ0VOU0UKICAgVEVSTVMgQU5EIENPTkRJVElPTlMgRk9SIENPUFlJTkcsIERJU1RSSUJV
+VElPTiBBTkQgTU9ESUZJQ0FUSU9OCgogIDAuIFRoaXMgTGljZW5zZSBhcHBsaWVzIHRvIGFueSBw
+cm9ncmFtIG9yIG90aGVyIHdvcmsgd2hpY2ggY29udGFpbnMKYSBub3RpY2UgcGxhY2VkIGJ5IHRo
+ZSBjb3B5cmlnaHQgaG9sZGVyIHNheWluZyBpdCBtYXkgYmUgZGlzdHJpYnV0ZWQKdW5kZXIgdGhl
+IHRlcm1zIG9mIHRoaXMgR2VuZXJhbCBQdWJsaWMgTGljZW5zZS4gIFRoZSAiUHJvZ3JhbSIsIGJl
+bG93LApyZWZlcnMgdG8gYW55IHN1Y2ggcHJvZ3JhbSBvciB3b3JrLCBhbmQgYSAid29yayBiYXNl
+ZCBvbiB0aGUgUHJvZ3JhbSIKbWVhbnMgZWl0aGVyIHRoZSBQcm9ncmFtIG9yIGFueSBkZXJpdmF0
+aXZlIHdvcmsgdW5kZXIgY29weXJpZ2h0IGxhdzoKdGhhdCBpcyB0byBzYXksIGEgd29yayBjb250
+YWluaW5nIHRoZSBQcm9ncmFtIG9yIGEgcG9ydGlvbiBvZiBpdCwKZWl0aGVyIHZlcmJhdGltIG9y
+IHdpdGggbW9kaWZpY2F0aW9ucyBhbmQvb3IgdHJhbnNsYXRlZCBpbnRvIGFub3RoZXIKbGFuZ3Vh
+Z2UuICAoSGVyZWluYWZ0ZXIsIHRyYW5zbGF0aW9uIGlzIGluY2x1ZGVkIHdpdGhvdXQgbGltaXRh
+dGlvbiBpbgp0aGUgdGVybSAibW9kaWZpY2F0aW9uIi4pICBFYWNoIGxpY2Vuc2VlIGlzIGFkZHJl
+c3NlZCBhcyAieW91Ii4KCkFjdGl2aXRpZXMgb3RoZXIgdGhhbiBjb3B5aW5nLCBkaXN0cmlidXRp
+b24gYW5kIG1vZGlmaWNhdGlvbiBhcmUgbm90CmNvdmVyZWQgYnkgdGhpcyBMaWNlbnNlOyB0aGV5
+IGFyZSBvdXRzaWRlIGl0cyBzY29wZS4gIFRoZSBhY3Qgb2YKcnVubmluZyB0aGUgUHJvZ3JhbSBp
+cyBub3QgcmVzdHJpY3RlZCwgYW5kIHRoZSBvdXRwdXQgZnJvbSB0aGUgUHJvZ3JhbQppcyBjb3Zl
+cmVkIG9ubHkgaWYgaXRzIGNvbnRlbnRzIGNvbnN0aXR1dGUgYSB3b3JrIGJhc2VkIG9uIHRoZQpQ
+cm9ncmFtIChpbmRlcGVuZGVudCBvZiBoYXZpbmcgYmVlbiBtYWRlIGJ5IHJ1bm5pbmcgdGhlIFBy
+b2dyYW0pLgpXaGV0aGVyIHRoYXQgaXMgdHJ1ZSBkZXBlbmRzIG9uIHdoYXQgdGhlIFByb2dyYW0g
+ZG9lcy4KCiAgMS4gWW91IG1heSBjb3B5IGFuZCBkaXN0cmlidXRlIHZlcmJhdGltIGNvcGllcyBv
+ZiB0aGUgUHJvZ3JhbSdzCnNvdXJjZSBjb2RlIGFzIHlvdSByZWNlaXZlIGl0LCBpbiBhbnkgbWVk
+aXVtLCBwcm92aWRlZCB0aGF0IHlvdQpjb25zcGljdW91c2x5IGFuZCBhcHByb3ByaWF0ZWx5IHB1
+Ymxpc2ggb24gZWFjaCBjb3B5IGFuIGFwcHJvcHJpYXRlCmNvcHlyaWdodCBub3RpY2UgYW5kIGRp
+c2NsYWltZXIgb2Ygd2FycmFudHk7IGtlZXAgaW50YWN0IGFsbCB0aGUKbm90aWNlcyB0aGF0IHJl
+ZmVyIHRvIHRoaXMgTGljZW5zZSBhbmQgdG8gdGhlIGFic2VuY2Ugb2YgYW55IHdhcnJhbnR5Owph
+bmQgZ2l2ZSBhbnkgb3RoZXIgcmVjaXBpZW50cyBvZiB0aGUgUHJvZ3JhbSBhIGNvcHkgb2YgdGhp
+cyBMaWNlbnNlCmFsb25nIHdpdGggdGhlIFByb2dyYW0uCgpZb3UgbWF5IGNoYXJnZSBhIGZlZSBm
+b3IgdGhlIHBoeXNpY2FsIGFjdCBvZiB0cmFuc2ZlcnJpbmcgYSBjb3B5LCBhbmQKeW91IG1heSBh
+dCB5b3VyIG9wdGlvbiBvZmZlciB3YXJyYW50eSBwcm90ZWN0aW9uIGluIGV4Y2hhbmdlIGZvciBh
+IGZlZS4KCiAgMi4gWW91IG1heSBtb2RpZnkgeW91ciBjb3B5IG9yIGNvcGllcyBvZiB0aGUgUHJv
+Z3JhbSBvciBhbnkgcG9ydGlvbgpvZiBpdCwgdGh1cyBmb3JtaW5nIGEgd29yayBiYXNlZCBvbiB0
+aGUgUHJvZ3JhbSwgYW5kIGNvcHkgYW5kCmRpc3RyaWJ1dGUgc3VjaCBtb2RpZmljYXRpb25zIG9y
+IHdvcmsgdW5kZXIgdGhlIHRlcm1zIG9mIFNlY3Rpb24gMQphYm92ZSwgcHJvdmlkZWQgdGhhdCB5
+b3UgYWxzbyBtZWV0IGFsbCBvZiB0aGVzZSBjb25kaXRpb25zOgoKICAgIGEpIFlvdSBtdXN0IGNh
+dXNlIHRoZSBtb2RpZmllZCBmaWxlcyB0byBjYXJyeSBwcm9taW5lbnQgbm90aWNlcwogICAgc3Rh
+dGluZyB0aGF0IHlvdSBjaGFuZ2VkIHRoZSBmaWxlcyBhbmQgdGhlIGRhdGUgb2YgYW55IGNoYW5n
+ZS4KCiAgICBiKSBZb3UgbXVzdCBjYXVzZSBhbnkgd29yayB0aGF0IHlvdSBkaXN0cmlidXRlIG9y
+IHB1Ymxpc2gsIHRoYXQgaW4KICAgIHdob2xlIG9yIGluIHBhcnQgY29udGFpbnMgb3IgaXMgZGVy
+aXZlZCBmcm9tIHRoZSBQcm9ncmFtIG9yIGFueQogICAgcGFydCB0aGVyZW9mLCB0byBiZSBsaWNl
+bnNlZCBhcyBhIHdob2xlIGF0IG5vIGNoYXJnZSB0byBhbGwgdGhpcmQKICAgIHBhcnRpZXMgdW5k
+ZXIgdGhlIHRlcm1zIG9mIHRoaXMgTGljZW5zZS4KCiAgICBjKSBJZiB0aGUgbW9kaWZpZWQgcHJv
+Z3JhbSBub3JtYWxseSByZWFkcyBjb21tYW5kcyBpbnRlcmFjdGl2ZWx5CiAgICB3aGVuIHJ1biwg
+eW91IG11c3QgY2F1c2UgaXQsIHdoZW4gc3RhcnRlZCBydW5uaW5nIGZvciBzdWNoCiAgICBpbnRl
+cmFjdGl2ZSB1c2UgaW4gdGhlIG1vc3Qgb3JkaW5hcnkgd2F5LCB0byBwcmludCBvciBkaXNwbGF5
+IGFuCiAgICBhbm5vdW5jZW1lbnQgaW5jbHVkaW5nIGFuIGFwcHJvcHJpYXRlIGNvcHlyaWdodCBu
+b3RpY2UgYW5kIGEKICAgIG5vdGljZSB0aGF0IHRoZXJlIGlzIG5vIHdhcnJhbnR5IChvciBlbHNl
+LCBzYXlpbmcgdGhhdCB5b3UgcHJvdmlkZQogICAgYSB3YXJyYW50eSkgYW5kIHRoYXQgdXNlcnMg
+bWF5IHJlZGlzdHJpYnV0ZSB0aGUgcHJvZ3JhbSB1bmRlcgogICAgdGhlc2UgY29uZGl0aW9ucywg
+YW5kIHRlbGxpbmcgdGhlIHVzZXIgaG93IHRvIHZpZXcgYSBjb3B5IG9mIHRoaXMKICAgIExpY2Vu
+c2UuICAoRXhjZXB0aW9uOiBpZiB0aGUgUHJvZ3JhbSBpdHNlbGYgaXMgaW50ZXJhY3RpdmUgYnV0
+CiAgICBkb2VzIG5vdCBub3JtYWxseSBwcmludCBzdWNoIGFuIGFubm91bmNlbWVudCwgeW91ciB3
+b3JrIGJhc2VkIG9uCiAgICB0aGUgUHJvZ3JhbSBpcyBub3QgcmVxdWlyZWQgdG8gcHJpbnQgYW4g
+YW5ub3VuY2VtZW50LikKDApUaGVzZSByZXF1aXJlbWVudHMgYXBwbHkgdG8gdGhlIG1vZGlmaWVk
+IHdvcmsgYXMgYSB3aG9sZS4gIElmCmlkZW50aWZpYWJsZSBzZWN0aW9ucyBvZiB0aGF0IHdvcmsg
+YXJlIG5vdCBkZXJpdmVkIGZyb20gdGhlIFByb2dyYW0sCmFuZCBjYW4gYmUgcmVhc29uYWJseSBj
+b25zaWRlcmVkIGluZGVwZW5kZW50IGFuZCBzZXBhcmF0ZSB3b3JrcyBpbgp0aGVtc2VsdmVzLCB0
+aGVuIHRoaXMgTGljZW5zZSwgYW5kIGl0cyB0ZXJtcywgZG8gbm90IGFwcGx5IHRvIHRob3NlCnNl
+Y3Rpb25zIHdoZW4geW91IGRpc3RyaWJ1dGUgdGhlbSBhcyBzZXBhcmF0ZSB3b3Jrcy4gIEJ1dCB3
+aGVuIHlvdQpkaXN0cmlidXRlIHRoZSBzYW1lIHNlY3Rpb25zIGFzIHBhcnQgb2YgYSB3aG9sZSB3
+aGljaCBpcyBhIHdvcmsgYmFzZWQKb24gdGhlIFByb2dyYW0sIHRoZSBkaXN0cmlidXRpb24gb2Yg
+dGhlIHdob2xlIG11c3QgYmUgb24gdGhlIHRlcm1zIG9mCnRoaXMgTGljZW5zZSwgd2hvc2UgcGVy
+bWlzc2lvbnMgZm9yIG90aGVyIGxpY2Vuc2VlcyBleHRlbmQgdG8gdGhlCmVudGlyZSB3aG9sZSwg
+YW5kIHRodXMgdG8gZWFjaCBhbmQgZXZlcnkgcGFydCByZWdhcmRsZXNzIG9mIHdobyB3cm90ZSBp
+dC4KClRodXMsIGl0IGlzIG5vdCB0aGUgaW50ZW50IG9mIHRoaXMgc2VjdGlvbiB0byBjbGFpbSBy
+aWdodHMgb3IgY29udGVzdAp5b3VyIHJpZ2h0cyB0byB3b3JrIHdyaXR0ZW4gZW50aXJlbHkgYnkg
+eW91OyByYXRoZXIsIHRoZSBpbnRlbnQgaXMgdG8KZXhlcmNpc2UgdGhlIHJpZ2h0IHRvIGNvbnRy
+b2wgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkZXJpdmF0aXZlIG9yCmNvbGxlY3RpdmUgd29ya3MgYmFz
+ZWQgb24gdGhlIFByb2dyYW0uCgpJbiBhZGRpdGlvbiwgbWVyZSBhZ2dyZWdhdGlvbiBvZiBhbm90
+aGVyIHdvcmsgbm90IGJhc2VkIG9uIHRoZSBQcm9ncmFtCndpdGggdGhlIFByb2dyYW0gKG9yIHdp
+dGggYSB3b3JrIGJhc2VkIG9uIHRoZSBQcm9ncmFtKSBvbiBhIHZvbHVtZSBvZgphIHN0b3JhZ2Ug
+b3IgZGlzdHJpYnV0aW9uIG1lZGl1bSBkb2VzIG5vdCBicmluZyB0aGUgb3RoZXIgd29yayB1bmRl
+cgp0aGUgc2NvcGUgb2YgdGhpcyBMaWNlbnNlLgoKICAzLiBZb3UgbWF5IGNvcHkgYW5kIGRpc3Ry
+aWJ1dGUgdGhlIFByb2dyYW0gKG9yIGEgd29yayBiYXNlZCBvbiBpdCwKdW5kZXIgU2VjdGlvbiAy
+KSBpbiBvYmplY3QgY29kZSBvciBleGVjdXRhYmxlIGZvcm0gdW5kZXIgdGhlIHRlcm1zIG9mClNl
+Y3Rpb25zIDEgYW5kIDIgYWJvdmUgcHJvdmlkZWQgdGhhdCB5b3UgYWxzbyBkbyBvbmUgb2YgdGhl
+IGZvbGxvd2luZzoKCiAgICBhKSBBY2NvbXBhbnkgaXQgd2l0aCB0aGUgY29tcGxldGUgY29ycmVz
+cG9uZGluZyBtYWNoaW5lLXJlYWRhYmxlCiAgICBzb3VyY2UgY29kZSwgd2hpY2ggbXVzdCBiZSBk
+aXN0cmlidXRlZCB1bmRlciB0aGUgdGVybXMgb2YgU2VjdGlvbnMKICAgIDEgYW5kIDIgYWJvdmUg
+b24gYSBtZWRpdW0gY3VzdG9tYXJpbHkgdXNlZCBmb3Igc29mdHdhcmUgaW50ZXJjaGFuZ2U7IG9y
+LAoKICAgIGIpIEFjY29tcGFueSBpdCB3aXRoIGEgd3JpdHRlbiBvZmZlciwgdmFsaWQgZm9yIGF0
+IGxlYXN0IHRocmVlCiAgICB5ZWFycywgdG8gZ2l2ZSBhbnkgdGhpcmQgcGFydHksIGZvciBhIGNo
+YXJnZSBubyBtb3JlIHRoYW4geW91cgogICAgY29zdCBvZiBwaHlzaWNhbGx5IHBlcmZvcm1pbmcg
+c291cmNlIGRpc3RyaWJ1dGlvbiwgYSBjb21wbGV0ZQogICAgbWFjaGluZS1yZWFkYWJsZSBjb3B5
+IG9mIHRoZSBjb3JyZXNwb25kaW5nIHNvdXJjZSBjb2RlLCB0byBiZQogICAgZGlzdHJpYnV0ZWQg
+dW5kZXIgdGhlIHRlcm1zIG9mIFNlY3Rpb25zIDEgYW5kIDIgYWJvdmUgb24gYSBtZWRpdW0KICAg
+IGN1c3RvbWFyaWx5IHVzZWQgZm9yIHNvZnR3YXJlIGludGVyY2hhbmdlOyBvciwKCiAgICBjKSBB
+Y2NvbXBhbnkgaXQgd2l0aCB0aGUgaW5mb3JtYXRpb24geW91IHJlY2VpdmVkIGFzIHRvIHRoZSBv
+ZmZlcgogICAgdG8gZGlzdHJpYnV0ZSBjb3JyZXNwb25kaW5nIHNvdXJjZSBjb2RlLiAgKFRoaXMg
+YWx0ZXJuYXRpdmUgaXMKICAgIGFsbG93ZWQgb25seSBmb3Igbm9uY29tbWVyY2lhbCBkaXN0cmli
+dXRpb24gYW5kIG9ubHkgaWYgeW91CiAgICByZWNlaXZlZCB0aGUgcHJvZ3JhbSBpbiBvYmplY3Qg
+Y29kZSBvciBleGVjdXRhYmxlIGZvcm0gd2l0aCBzdWNoCiAgICBhbiBvZmZlciwgaW4gYWNjb3Jk
+IHdpdGggU3Vic2VjdGlvbiBiIGFib3ZlLikKClRoZSBzb3VyY2UgY29kZSBmb3IgYSB3b3JrIG1l
+YW5zIHRoZSBwcmVmZXJyZWQgZm9ybSBvZiB0aGUgd29yayBmb3IKbWFraW5nIG1vZGlmaWNhdGlv
+bnMgdG8gaXQuICBGb3IgYW4gZXhlY3V0YWJsZSB3b3JrLCBjb21wbGV0ZSBzb3VyY2UKY29kZSBt
+ZWFucyBhbGwgdGhlIHNvdXJjZSBjb2RlIGZvciBhbGwgbW9kdWxlcyBpdCBjb250YWlucywgcGx1
+cyBhbnkKYXNzb2NpYXRlZCBpbnRlcmZhY2UgZGVmaW5pdGlvbiBmaWxlcywgcGx1cyB0aGUgc2Ny
+aXB0cyB1c2VkIHRvCmNvbnRyb2wgY29tcGlsYXRpb24gYW5kIGluc3RhbGxhdGlvbiBvZiB0aGUg
+ZXhlY3V0YWJsZS4gIEhvd2V2ZXIsIGFzIGEKc3BlY2lhbCBleGNlcHRpb24sIHRoZSBzb3VyY2Ug
+Y29kZSBkaXN0cmlidXRlZCBuZWVkIG5vdCBpbmNsdWRlCmFueXRoaW5nIHRoYXQgaXMgbm9ybWFs
+bHkgZGlzdHJpYnV0ZWQgKGluIGVpdGhlciBzb3VyY2Ugb3IgYmluYXJ5CmZvcm0pIHdpdGggdGhl
+IG1ham9yIGNvbXBvbmVudHMgKGNvbXBpbGVyLCBrZXJuZWwsIGFuZCBzbyBvbikgb2YgdGhlCm9w
+ZXJhdGluZyBzeXN0ZW0gb24gd2hpY2ggdGhlIGV4ZWN1dGFibGUgcnVucywgdW5sZXNzIHRoYXQg
+Y29tcG9uZW50Cml0c2VsZiBhY2NvbXBhbmllcyB0aGUgZXhlY3V0YWJsZS4KCklmIGRpc3RyaWJ1
+dGlvbiBvZiBleGVjdXRhYmxlIG9yIG9iamVjdCBjb2RlIGlzIG1hZGUgYnkgb2ZmZXJpbmcKYWNj
+ZXNzIHRvIGNvcHkgZnJvbSBhIGRlc2lnbmF0ZWQgcGxhY2UsIHRoZW4gb2ZmZXJpbmcgZXF1aXZh
+bGVudAphY2Nlc3MgdG8gY29weSB0aGUgc291cmNlIGNvZGUgZnJvbSB0aGUgc2FtZSBwbGFjZSBj
+b3VudHMgYXMKZGlzdHJpYnV0aW9uIG9mIHRoZSBzb3VyY2UgY29kZSwgZXZlbiB0aG91Z2ggdGhp
+cmQgcGFydGllcyBhcmUgbm90CmNvbXBlbGxlZCB0byBjb3B5IHRoZSBzb3VyY2UgYWxvbmcgd2l0
+aCB0aGUgb2JqZWN0IGNvZGUuCgwKICA0LiBZb3UgbWF5IG5vdCBjb3B5LCBtb2RpZnksIHN1Ymxp
+Y2Vuc2UsIG9yIGRpc3RyaWJ1dGUgdGhlIFByb2dyYW0KZXhjZXB0IGFzIGV4cHJlc3NseSBwcm92
+aWRlZCB1bmRlciB0aGlzIExpY2Vuc2UuICBBbnkgYXR0ZW1wdApvdGhlcndpc2UgdG8gY29weSwg
+bW9kaWZ5LCBzdWJsaWNlbnNlIG9yIGRpc3RyaWJ1dGUgdGhlIFByb2dyYW0gaXMKdm9pZCwgYW5k
+IHdpbGwgYXV0b21hdGljYWxseSB0ZXJtaW5hdGUgeW91ciByaWdodHMgdW5kZXIgdGhpcyBMaWNl
+bnNlLgpIb3dldmVyLCBwYXJ0aWVzIHdobyBoYXZlIHJlY2VpdmVkIGNvcGllcywgb3IgcmlnaHRz
+LCBmcm9tIHlvdSB1bmRlcgp0aGlzIExpY2Vuc2Ugd2lsbCBub3QgaGF2ZSB0aGVpciBsaWNlbnNl
+cyB0ZXJtaW5hdGVkIHNvIGxvbmcgYXMgc3VjaApwYXJ0aWVzIHJlbWFpbiBpbiBmdWxsIGNvbXBs
+aWFuY2UuCgogIDUuIFlvdSBhcmUgbm90IHJlcXVpcmVkIHRvIGFjY2VwdCB0aGlzIExpY2Vuc2Us
+IHNpbmNlIHlvdSBoYXZlIG5vdApzaWduZWQgaXQuICBIb3dldmVyLCBub3RoaW5nIGVsc2UgZ3Jh
+bnRzIHlvdSBwZXJtaXNzaW9uIHRvIG1vZGlmeSBvcgpkaXN0cmlidXRlIHRoZSBQcm9ncmFtIG9y
+IGl0cyBkZXJpdmF0aXZlIHdvcmtzLiAgVGhlc2UgYWN0aW9ucyBhcmUKcHJvaGliaXRlZCBieSBs
+YXcgaWYgeW91IGRvIG5vdCBhY2NlcHQgdGhpcyBMaWNlbnNlLiAgVGhlcmVmb3JlLCBieQptb2Rp
+Znlpbmcgb3IgZGlzdHJpYnV0aW5nIHRoZSBQcm9ncmFtIChvciBhbnkgd29yayBiYXNlZCBvbiB0
+aGUKUHJvZ3JhbSksIHlvdSBpbmRpY2F0ZSB5b3VyIGFjY2VwdGFuY2Ugb2YgdGhpcyBMaWNlbnNl
+IHRvIGRvIHNvLCBhbmQKYWxsIGl0cyB0ZXJtcyBhbmQgY29uZGl0aW9ucyBmb3IgY29weWluZywg
+ZGlzdHJpYnV0aW5nIG9yIG1vZGlmeWluZwp0aGUgUHJvZ3JhbSBvciB3b3JrcyBiYXNlZCBvbiBp
+dC4KCiAgNi4gRWFjaCB0aW1lIHlvdSByZWRpc3RyaWJ1dGUgdGhlIFByb2dyYW0gKG9yIGFueSB3
+b3JrIGJhc2VkIG9uIHRoZQpQcm9ncmFtKSwgdGhlIHJlY2lwaWVudCBhdXRvbWF0aWNhbGx5IHJl
+Y2VpdmVzIGEgbGljZW5zZSBmcm9tIHRoZQpvcmlnaW5hbCBsaWNlbnNvciB0byBjb3B5LCBkaXN0
+cmlidXRlIG9yIG1vZGlmeSB0aGUgUHJvZ3JhbSBzdWJqZWN0IHRvCnRoZXNlIHRlcm1zIGFuZCBj
+b25kaXRpb25zLiAgWW91IG1heSBub3QgaW1wb3NlIGFueSBmdXJ0aGVyCnJlc3RyaWN0aW9ucyBv
+biB0aGUgcmVjaXBpZW50cycgZXhlcmNpc2Ugb2YgdGhlIHJpZ2h0cyBncmFudGVkIGhlcmVpbi4K
+WW91IGFyZSBub3QgcmVzcG9uc2libGUgZm9yIGVuZm9yY2luZyBjb21wbGlhbmNlIGJ5IHRoaXJk
+IHBhcnRpZXMgdG8KdGhpcyBMaWNlbnNlLgoKICA3LiBJZiwgYXMgYSBjb25zZXF1ZW5jZSBvZiBh
+IGNvdXJ0IGp1ZGdtZW50IG9yIGFsbGVnYXRpb24gb2YgcGF0ZW50CmluZnJpbmdlbWVudCBvciBm
+b3IgYW55IG90aGVyIHJlYXNvbiAobm90IGxpbWl0ZWQgdG8gcGF0ZW50IGlzc3VlcyksCmNvbmRp
+dGlvbnMgYXJlIGltcG9zZWQgb24geW91ICh3aGV0aGVyIGJ5IGNvdXJ0IG9yZGVyLCBhZ3JlZW1l
+bnQgb3IKb3RoZXJ3aXNlKSB0aGF0IGNvbnRyYWRpY3QgdGhlIGNvbmRpdGlvbnMgb2YgdGhpcyBM
+aWNlbnNlLCB0aGV5IGRvIG5vdApleGN1c2UgeW91IGZyb20gdGhlIGNvbmRpdGlvbnMgb2YgdGhp
+cyBMaWNlbnNlLiAgSWYgeW91IGNhbm5vdApkaXN0cmlidXRlIHNvIGFzIHRvIHNhdGlzZnkgc2lt
+dWx0YW5lb3VzbHkgeW91ciBvYmxpZ2F0aW9ucyB1bmRlciB0aGlzCkxpY2Vuc2UgYW5kIGFueSBv
+dGhlciBwZXJ0aW5lbnQgb2JsaWdhdGlvbnMsIHRoZW4gYXMgYSBjb25zZXF1ZW5jZSB5b3UKbWF5
+IG5vdCBkaXN0cmlidXRlIHRoZSBQcm9ncmFtIGF0IGFsbC4gIEZvciBleGFtcGxlLCBpZiBhIHBh
+dGVudApsaWNlbnNlIHdvdWxkIG5vdCBwZXJtaXQgcm95YWx0eS1mcmVlIHJlZGlzdHJpYnV0aW9u
+IG9mIHRoZSBQcm9ncmFtIGJ5CmFsbCB0aG9zZSB3aG8gcmVjZWl2ZSBjb3BpZXMgZGlyZWN0bHkg
+b3IgaW5kaXJlY3RseSB0aHJvdWdoIHlvdSwgdGhlbgp0aGUgb25seSB3YXkgeW91IGNvdWxkIHNh
+dGlzZnkgYm90aCBpdCBhbmQgdGhpcyBMaWNlbnNlIHdvdWxkIGJlIHRvCnJlZnJhaW4gZW50aXJl
+bHkgZnJvbSBkaXN0cmlidXRpb24gb2YgdGhlIFByb2dyYW0uCgpJZiBhbnkgcG9ydGlvbiBvZiB0
+aGlzIHNlY3Rpb24gaXMgaGVsZCBpbnZhbGlkIG9yIHVuZW5mb3JjZWFibGUgdW5kZXIKYW55IHBh
+cnRpY3VsYXIgY2lyY3Vtc3RhbmNlLCB0aGUgYmFsYW5jZSBvZiB0aGUgc2VjdGlvbiBpcyBpbnRl
+bmRlZCB0bwphcHBseSBhbmQgdGhlIHNlY3Rpb24gYXMgYSB3aG9sZSBpcyBpbnRlbmRlZCB0byBh
+cHBseSBpbiBvdGhlcgpjaXJjdW1zdGFuY2VzLgoKSXQgaXMgbm90IHRoZSBwdXJwb3NlIG9mIHRo
+aXMgc2VjdGlvbiB0byBpbmR1Y2UgeW91IHRvIGluZnJpbmdlIGFueQpwYXRlbnRzIG9yIG90aGVy
+IHByb3BlcnR5IHJpZ2h0IGNsYWltcyBvciB0byBjb250ZXN0IHZhbGlkaXR5IG9mIGFueQpzdWNo
+IGNsYWltczsgdGhpcyBzZWN0aW9uIGhhcyB0aGUgc29sZSBwdXJwb3NlIG9mIHByb3RlY3Rpbmcg
+dGhlCmludGVncml0eSBvZiB0aGUgZnJlZSBzb2Z0d2FyZSBkaXN0cmlidXRpb24gc3lzdGVtLCB3
+aGljaCBpcwppbXBsZW1lbnRlZCBieSBwdWJsaWMgbGljZW5zZSBwcmFjdGljZXMuICBNYW55IHBl
+b3BsZSBoYXZlIG1hZGUKZ2VuZXJvdXMgY29udHJpYnV0aW9ucyB0byB0aGUgd2lkZSByYW5nZSBv
+ZiBzb2Z0d2FyZSBkaXN0cmlidXRlZAp0aHJvdWdoIHRoYXQgc3lzdGVtIGluIHJlbGlhbmNlIG9u
+IGNvbnNpc3RlbnQgYXBwbGljYXRpb24gb2YgdGhhdApzeXN0ZW07IGl0IGlzIHVwIHRvIHRoZSBh
+dXRob3IvZG9ub3IgdG8gZGVjaWRlIGlmIGhlIG9yIHNoZSBpcyB3aWxsaW5nCnRvIGRpc3RyaWJ1
+dGUgc29mdHdhcmUgdGhyb3VnaCBhbnkgb3RoZXIgc3lzdGVtIGFuZCBhIGxpY2Vuc2VlIGNhbm5v
+dAppbXBvc2UgdGhhdCBjaG9pY2UuCgpUaGlzIHNlY3Rpb24gaXMgaW50ZW5kZWQgdG8gbWFrZSB0
+aG9yb3VnaGx5IGNsZWFyIHdoYXQgaXMgYmVsaWV2ZWQgdG8KYmUgYSBjb25zZXF1ZW5jZSBvZiB0
+aGUgcmVzdCBvZiB0aGlzIExpY2Vuc2UuCgwKICA4LiBJZiB0aGUgZGlzdHJpYnV0aW9uIGFuZC9v
+ciB1c2Ugb2YgdGhlIFByb2dyYW0gaXMgcmVzdHJpY3RlZCBpbgpjZXJ0YWluIGNvdW50cmllcyBl
+aXRoZXIgYnkgcGF0ZW50cyBvciBieSBjb3B5cmlnaHRlZCBpbnRlcmZhY2VzLCB0aGUKb3JpZ2lu
+YWwgY29weXJpZ2h0IGhvbGRlciB3aG8gcGxhY2VzIHRoZSBQcm9ncmFtIHVuZGVyIHRoaXMgTGlj
+ZW5zZQptYXkgYWRkIGFuIGV4cGxpY2l0IGdlb2dyYXBoaWNhbCBkaXN0cmlidXRpb24gbGltaXRh
+dGlvbiBleGNsdWRpbmcKdGhvc2UgY291bnRyaWVzLCBzbyB0aGF0IGRpc3RyaWJ1dGlvbiBpcyBw
+ZXJtaXR0ZWQgb25seSBpbiBvciBhbW9uZwpjb3VudHJpZXMgbm90IHRodXMgZXhjbHVkZWQuICBJ
+biBzdWNoIGNhc2UsIHRoaXMgTGljZW5zZSBpbmNvcnBvcmF0ZXMKdGhlIGxpbWl0YXRpb24gYXMg
+aWYgd3JpdHRlbiBpbiB0aGUgYm9keSBvZiB0aGlzIExpY2Vuc2UuCgogIDkuIFRoZSBGcmVlIFNv
+ZnR3YXJlIEZvdW5kYXRpb24gbWF5IHB1Ymxpc2ggcmV2aXNlZCBhbmQvb3IgbmV3IHZlcnNpb25z
+Cm9mIHRoZSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZyb20gdGltZSB0byB0aW1lLiAgU3VjaCBu
+ZXcgdmVyc2lvbnMgd2lsbApiZSBzaW1pbGFyIGluIHNwaXJpdCB0byB0aGUgcHJlc2VudCB2ZXJz
+aW9uLCBidXQgbWF5IGRpZmZlciBpbiBkZXRhaWwgdG8KYWRkcmVzcyBuZXcgcHJvYmxlbXMgb3Ig
+Y29uY2VybnMuCgpFYWNoIHZlcnNpb24gaXMgZ2l2ZW4gYSBkaXN0aW5ndWlzaGluZyB2ZXJzaW9u
+IG51bWJlci4gIElmIHRoZSBQcm9ncmFtCnNwZWNpZmllcyBhIHZlcnNpb24gbnVtYmVyIG9mIHRo
+aXMgTGljZW5zZSB3aGljaCBhcHBsaWVzIHRvIGl0IGFuZCAiYW55CmxhdGVyIHZlcnNpb24iLCB5
+b3UgaGF2ZSB0aGUgb3B0aW9uIG9mIGZvbGxvd2luZyB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMK
+ZWl0aGVyIG9mIHRoYXQgdmVyc2lvbiBvciBvZiBhbnkgbGF0ZXIgdmVyc2lvbiBwdWJsaXNoZWQg
+YnkgdGhlIEZyZWUKU29mdHdhcmUgRm91bmRhdGlvbi4gIElmIHRoZSBQcm9ncmFtIGRvZXMgbm90
+IHNwZWNpZnkgYSB2ZXJzaW9uIG51bWJlciBvZgp0aGlzIExpY2Vuc2UsIHlvdSBtYXkgY2hvb3Nl
+IGFueSB2ZXJzaW9uIGV2ZXIgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlCkZvdW5kYXRp
+b24uCgogIDEwLiBJZiB5b3Ugd2lzaCB0byBpbmNvcnBvcmF0ZSBwYXJ0cyBvZiB0aGUgUHJvZ3Jh
+bSBpbnRvIG90aGVyIGZyZWUKcHJvZ3JhbXMgd2hvc2UgZGlzdHJpYnV0aW9uIGNvbmRpdGlvbnMg
+YXJlIGRpZmZlcmVudCwgd3JpdGUgdG8gdGhlIGF1dGhvcgp0byBhc2sgZm9yIHBlcm1pc3Npb24u
+ICBGb3Igc29mdHdhcmUgd2hpY2ggaXMgY29weXJpZ2h0ZWQgYnkgdGhlIEZyZWUKU29mdHdhcmUg
+Rm91bmRhdGlvbiwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgd2Ugc29t
+ZXRpbWVzCm1ha2UgZXhjZXB0aW9ucyBmb3IgdGhpcy4gIE91ciBkZWNpc2lvbiB3aWxsIGJlIGd1
+aWRlZCBieSB0aGUgdHdvIGdvYWxzCm9mIHByZXNlcnZpbmcgdGhlIGZyZWUgc3RhdHVzIG9mIGFs
+bCBkZXJpdmF0aXZlcyBvZiBvdXIgZnJlZSBzb2Z0d2FyZSBhbmQKb2YgcHJvbW90aW5nIHRoZSBz
+aGFyaW5nIGFuZCByZXVzZSBvZiBzb2Z0d2FyZSBnZW5lcmFsbHkuCgoJCQkgICAgTk8gV0FSUkFO
+VFkKCiAgMTEuIEJFQ0FVU0UgVEhFIFBST0dSQU0gSVMgTElDRU5TRUQgRlJFRSBPRiBDSEFSR0Us
+IFRIRVJFIElTIE5PIFdBUlJBTlRZCkZPUiBUSEUgUFJPR1JBTSwgVE8gVEhFIEVYVEVOVCBQRVJN
+SVRURUQgQlkgQVBQTElDQUJMRSBMQVcuICBFWENFUFQgV0hFTgpPVEhFUldJU0UgU1RBVEVEIElO
+IFdSSVRJTkcgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORC9PUiBPVEhFUiBQQVJUSUVTClBST1ZJ
+REUgVEhFIFBST0dSQU0gIkFTIElTIiBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFSVRI
+RVIgRVhQUkVTU0VECk9SIElNUExJRUQsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBU
+SEUgSU1QTElFRCBXQVJSQU5USUVTIE9GCk1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1Ig
+QSBQQVJUSUNVTEFSIFBVUlBPU0UuICBUSEUgRU5USVJFIFJJU0sgQVMKVE8gVEhFIFFVQUxJVFkg
+QU5EIFBFUkZPUk1BTkNFIE9GIFRIRSBQUk9HUkFNIElTIFdJVEggWU9VLiAgU0hPVUxEIFRIRQpQ
+Uk9HUkFNIFBST1ZFIERFRkVDVElWRSwgWU9VIEFTU1VNRSBUSEUgQ09TVCBPRiBBTEwgTkVDRVNT
+QVJZIFNFUlZJQ0lORywKUkVQQUlSIE9SIENPUlJFQ1RJT04uCgogIDEyLiBJTiBOTyBFVkVOVCBV
+TkxFU1MgUkVRVUlSRUQgQlkgQVBQTElDQUJMRSBMQVcgT1IgQUdSRUVEIFRPIElOIFdSSVRJTkcK
+V0lMTCBBTlkgQ09QWVJJR0hUIEhPTERFUiwgT1IgQU5ZIE9USEVSIFBBUlRZIFdITyBNQVkgTU9E
+SUZZIEFORC9PUgpSRURJU1RSSUJVVEUgVEhFIFBST0dSQU0gQVMgUEVSTUlUVEVEIEFCT1ZFLCBC
+RSBMSUFCTEUgVE8gWU9VIEZPUiBEQU1BR0VTLApJTkNMVURJTkcgQU5ZIEdFTkVSQUwsIFNQRUNJ
+QUwsIElOQ0lERU5UQUwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIEFSSVNJTkcKT1VUIE9GIFRI
+RSBVU0UgT1IgSU5BQklMSVRZIFRPIFVTRSBUSEUgUFJPR1JBTSAoSU5DTFVESU5HIEJVVCBOT1Qg
+TElNSVRFRApUTyBMT1NTIE9GIERBVEEgT1IgREFUQSBCRUlORyBSRU5ERVJFRCBJTkFDQ1VSQVRF
+IE9SIExPU1NFUyBTVVNUQUlORUQgQlkKWU9VIE9SIFRISVJEIFBBUlRJRVMgT1IgQSBGQUlMVVJF
+IE9GIFRIRSBQUk9HUkFNIFRPIE9QRVJBVEUgV0lUSCBBTlkgT1RIRVIKUFJPR1JBTVMpLCBFVkVO
+IElGIFNVQ0ggSE9MREVSIE9SIE9USEVSIFBBUlRZIEhBUyBCRUVOIEFEVklTRUQgT0YgVEhFClBP
+U1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFUy4KCgkJICAgICBFTkQgT0YgVEVSTVMgQU5EIENPTkRJ
+VElPTlMKDAoJICAgIEhvdyB0byBBcHBseSBUaGVzZSBUZXJtcyB0byBZb3VyIE5ldyBQcm9ncmFt
+cwoKICBJZiB5b3UgZGV2ZWxvcCBhIG5ldyBwcm9ncmFtLCBhbmQgeW91IHdhbnQgaXQgdG8gYmUg
+b2YgdGhlIGdyZWF0ZXN0CnBvc3NpYmxlIHVzZSB0byB0aGUgcHVibGljLCB0aGUgYmVzdCB3YXkg
+dG8gYWNoaWV2ZSB0aGlzIGlzIHRvIG1ha2UgaXQKZnJlZSBzb2Z0d2FyZSB3aGljaCBldmVyeW9u
+ZSBjYW4gcmVkaXN0cmlidXRlIGFuZCBjaGFuZ2UgdW5kZXIgdGhlc2UgdGVybXMuCgogIFRvIGRv
+IHNvLCBhdHRhY2ggdGhlIGZvbGxvd2luZyBub3RpY2VzIHRvIHRoZSBwcm9ncmFtLiAgSXQgaXMg
+c2FmZXN0CnRvIGF0dGFjaCB0aGVtIHRvIHRoZSBzdGFydCBvZiBlYWNoIHNvdXJjZSBmaWxlIHRv
+IG1vc3QgZWZmZWN0aXZlbHkKY29udmV5IHRoZSBleGNsdXNpb24gb2Ygd2FycmFudHk7IGFuZCBl
+YWNoIGZpbGUgc2hvdWxkIGhhdmUgYXQgbGVhc3QKdGhlICJjb3B5cmlnaHQiIGxpbmUgYW5kIGEg
+cG9pbnRlciB0byB3aGVyZSB0aGUgZnVsbCBub3RpY2UgaXMgZm91bmQuCgogICAgPG9uZSBsaW5l
+IHRvIGdpdmUgdGhlIHByb2dyYW0ncyBuYW1lIGFuZCBhIGJyaWVmIGlkZWEgb2Ygd2hhdCBpdCBk
+b2VzLj4KICAgIENvcHlyaWdodCAoQykgPHllYXI+ICA8bmFtZSBvZiBhdXRob3I+CgogICAgVGhp
+cyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9v
+ciBtb2RpZnkKICAgIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGlj
+IExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5CiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9u
+OyBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgogICAgKGF0IHlvdXIgb3B0aW9u
+KSBhbnkgbGF0ZXIgdmVyc2lvbi4KCiAgICBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4g
+dGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJS
+QU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAgICBNRVJDSEFOVEFC
+SUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCiAgICBH
+TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgoKICAgIFlvdSBzaG91
+bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNl
+CiAgICBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBT
+b2Z0d2FyZQogICAgRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAs
+IEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQQoKCkFsc28gYWRkIGluZm9ybWF0aW9uIG9uIGhv
+dyB0byBjb250YWN0IHlvdSBieSBlbGVjdHJvbmljIGFuZCBwYXBlciBtYWlsLgoKSWYgdGhlIHBy
+b2dyYW0gaXMgaW50ZXJhY3RpdmUsIG1ha2UgaXQgb3V0cHV0IGEgc2hvcnQgbm90aWNlIGxpa2Ug
+dGhpcwp3aGVuIGl0IHN0YXJ0cyBpbiBhbiBpbnRlcmFjdGl2ZSBtb2RlOgoKICAgIEdub21vdmlz
+aW9uIHZlcnNpb24gNjksIENvcHlyaWdodCAoQykgeWVhciBuYW1lIG9mIGF1dGhvcgogICAgR25v
+bW92aXNpb24gY29tZXMgd2l0aCBBQlNPTFVURUxZIE5PIFdBUlJBTlRZOyBmb3IgZGV0YWlscyB0
+eXBlIGBzaG93IHcnLgogICAgVGhpcyBpcyBmcmVlIHNvZnR3YXJlLCBhbmQgeW91IGFyZSB3ZWxj
+b21lIHRvIHJlZGlzdHJpYnV0ZSBpdAogICAgdW5kZXIgY2VydGFpbiBjb25kaXRpb25zOyB0eXBl
+IGBzaG93IGMnIGZvciBkZXRhaWxzLgoKVGhlIGh5cG90aGV0aWNhbCBjb21tYW5kcyBgc2hvdyB3
+JyBhbmQgYHNob3cgYycgc2hvdWxkIHNob3cgdGhlIGFwcHJvcHJpYXRlCnBhcnRzIG9mIHRoZSBH
+ZW5lcmFsIFB1YmxpYyBMaWNlbnNlLiAgT2YgY291cnNlLCB0aGUgY29tbWFuZHMgeW91IHVzZSBt
+YXkKYmUgY2FsbGVkIHNvbWV0aGluZyBvdGhlciB0aGFuIGBzaG93IHcnIGFuZCBgc2hvdyBjJzsg
+dGhleSBjb3VsZCBldmVuIGJlCm1vdXNlLWNsaWNrcyBvciBtZW51IGl0ZW1zLS13aGF0ZXZlciBz
+dWl0cyB5b3VyIHByb2dyYW0uCgpZb3Ugc2hvdWxkIGFsc28gZ2V0IHlvdXIgZW1wbG95ZXIgKGlm
+IHlvdSB3b3JrIGFzIGEgcHJvZ3JhbW1lcikgb3IgeW91cgpzY2hvb2wsIGlmIGFueSwgdG8gc2ln
+biBhICJjb3B5cmlnaHQgZGlzY2xhaW1lciIgZm9yIHRoZSBwcm9ncmFtLCBpZgpuZWNlc3Nhcnku
+ICBIZXJlIGlzIGEgc2FtcGxlOyBhbHRlciB0aGUgbmFtZXM6CgogIFlveW9keW5lLCBJbmMuLCBo
+ZXJlYnkgZGlzY2xhaW1zIGFsbCBjb3B5cmlnaHQgaW50ZXJlc3QgaW4gdGhlIHByb2dyYW0KICBg
+R25vbW92aXNpb24nICh3aGljaCBtYWtlcyBwYXNzZXMgYXQgY29tcGlsZXJzKSB3cml0dGVuIGJ5
+IEphbWVzIEhhY2tlci4KCiAgPHNpZ25hdHVyZSBvZiBUeSBDb29uPiwgMSBBcHJpbCAxOTg5CiAg
+VHkgQ29vbiwgUHJlc2lkZW50IG9mIFZpY2UKClRoaXMgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBk
+b2VzIG5vdCBwZXJtaXQgaW5jb3Jwb3JhdGluZyB5b3VyIHByb2dyYW0gaW50bwpwcm9wcmlldGFy
+eSBwcm9ncmFtcy4gIElmIHlvdXIgcHJvZ3JhbSBpcyBhIHN1YnJvdXRpbmUgbGlicmFyeSwgeW91
+IG1heQpjb25zaWRlciBpdCBtb3JlIHVzZWZ1bCB0byBwZXJtaXQgbGlua2luZyBwcm9wcmlldGFy
+eSBhcHBsaWNhdGlvbnMgd2l0aCB0aGUKbGlicmFyeS4gIElmIHRoaXMgaXMgd2hhdCB5b3Ugd2Fu
+dCB0byBkbywgdXNlIHRoZSBHTlUgTGlicmFyeSBHZW5lcmFsClB1YmxpYyBMaWNlbnNlIGluc3Rl
+YWQgb2YgdGhpcyBMaWNlbnNlLgo=
+ClxjaGFwdGVye1RoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZX0KClxiZWdpbntjZW50ZXJ9
+CntccGFyaW5kZW50IDBpbgoKVmVyc2lvbiAyLCBKdW5lIDE5OTEKCkNvcHlyaWdodCBcY29weXJp
+Z2h0XCAxOTg5LCAxOTkxIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLgoKXGJpZ3NraXAK
+CjU5IFRlbXBsZSBQbGFjZSAtIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNywgVVNB
+CgpcYmlnc2tpcAoKRXZlcnlvbmUgaXMgcGVybWl0dGVkIHRvIGNvcHkgYW5kIGRpc3RyaWJ1dGUg
+dmVyYmF0aW0gY29waWVzCm9mIHRoaXMgbGljZW5zZSBkb2N1bWVudCwgYnV0IGNoYW5naW5nIGl0
+IGlzIG5vdCBhbGxvd2VkLgp9ClxlbmR7Y2VudGVyfQoKXGJlZ2lue2NlbnRlcn0Ke1xiZlxsYXJn
+ZSBQcmVhbWJsZX0KXGVuZHtjZW50ZXJ9CgoKVGhlIGxpY2Vuc2VzIGZvciBtb3N0IHNvZnR3YXJl
+IGFyZSBkZXNpZ25lZCB0byB0YWtlIGF3YXkgeW91ciBmcmVlZG9tIHRvCnNoYXJlIGFuZCBjaGFu
+Z2UgaXQuICBCeSBjb250cmFzdCwgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGlzCmlu
+dGVuZGVkIHRvIGd1YXJhbnRlZSB5b3VyIGZyZWVkb20gdG8gc2hhcmUgYW5kIGNoYW5nZSBmcmVl
+IHNvZnR3YXJlLS0tdG8KbWFrZSBzdXJlIHRoZSBzb2Z0d2FyZSBpcyBmcmVlIGZvciBhbGwgaXRz
+IHVzZXJzLiAgVGhpcyBHZW5lcmFsIFB1YmxpYwpMaWNlbnNlIGFwcGxpZXMgdG8gbW9zdCBvZiB0
+aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uJ3Mgc29mdHdhcmUgYW5kIHRvCmFueSBvdGhlciBw
+cm9ncmFtIHdob3NlIGF1dGhvcnMgY29tbWl0IHRvIHVzaW5nIGl0LiAgKFNvbWUgb3RoZXIgRnJl
+ZQpTb2Z0d2FyZSBGb3VuZGF0aW9uIHNvZnR3YXJlIGlzIGNvdmVyZWQgYnkgdGhlIEdOVSBMaWJy
+YXJ5IEdlbmVyYWwgUHVibGljCkxpY2Vuc2UgaW5zdGVhZC4pICBZb3UgY2FuIGFwcGx5IGl0IHRv
+IHlvdXIgcHJvZ3JhbXMsIHRvby4KCldoZW4gd2Ugc3BlYWsgb2YgZnJlZSBzb2Z0d2FyZSwgd2Ug
+YXJlIHJlZmVycmluZyB0byBmcmVlZG9tLCBub3QgcHJpY2UuCk91ciBHZW5lcmFsIFB1YmxpYyBM
+aWNlbnNlcyBhcmUgZGVzaWduZWQgdG8gbWFrZSBzdXJlIHRoYXQgeW91IGhhdmUgdGhlCmZyZWVk
+b20gdG8gZGlzdHJpYnV0ZSBjb3BpZXMgb2YgZnJlZSBzb2Z0d2FyZSAoYW5kIGNoYXJnZSBmb3Ig
+dGhpcyBzZXJ2aWNlCmlmIHlvdSB3aXNoKSwgdGhhdCB5b3UgcmVjZWl2ZSBzb3VyY2UgY29kZSBv
+ciBjYW4gZ2V0IGl0IGlmIHlvdSB3YW50IGl0LAp0aGF0IHlvdSBjYW4gY2hhbmdlIHRoZSBzb2Z0
+d2FyZSBvciB1c2UgcGllY2VzIG9mIGl0IGluIG5ldyBmcmVlIHByb2dyYW1zOwphbmQgdGhhdCB5
+b3Uga25vdyB5b3UgY2FuIGRvIHRoZXNlIHRoaW5ncy4KClRvIHByb3RlY3QgeW91ciByaWdodHMs
+IHdlIG5lZWQgdG8gbWFrZSByZXN0cmljdGlvbnMgdGhhdCBmb3JiaWQgYW55b25lIHRvCmRlbnkg
+eW91IHRoZXNlIHJpZ2h0cyBvciB0byBhc2sgeW91IHRvIHN1cnJlbmRlciB0aGUgcmlnaHRzLiAg
+VGhlc2UKcmVzdHJpY3Rpb25zIHRyYW5zbGF0ZSB0byBjZXJ0YWluIHJlc3BvbnNpYmlsaXRpZXMg
+Zm9yIHlvdSBpZiB5b3UKZGlzdHJpYnV0ZSBjb3BpZXMgb2YgdGhlIHNvZnR3YXJlLCBvciBpZiB5
+b3UgbW9kaWZ5IGl0LgoKRm9yIGV4YW1wbGUsIGlmIHlvdSBkaXN0cmlidXRlIGNvcGllcyBvZiBz
+dWNoIGEgcHJvZ3JhbSwgd2hldGhlciBncmF0aXMgb3IKZm9yIGEgZmVlLCB5b3UgbXVzdCBnaXZl
+IHRoZSByZWNpcGllbnRzIGFsbCB0aGUgcmlnaHRzIHRoYXQgeW91IGhhdmUuICBZb3UKbXVzdCBt
+YWtlIHN1cmUgdGhhdCB0aGV5LCB0b28sIHJlY2VpdmUgb3IgY2FuIGdldCB0aGUgc291cmNlIGNv
+ZGUuICBBbmQKeW91IG11c3Qgc2hvdyB0aGVtIHRoZXNlIHRlcm1zIHNvIHRoZXkga25vdyB0aGVp
+ciByaWdodHMuCgpXZSBwcm90ZWN0IHlvdXIgcmlnaHRzIHdpdGggdHdvIHN0ZXBzOiAoMSkgY29w
+eXJpZ2h0IHRoZSBzb2Z0d2FyZSwgYW5kICgyKQpvZmZlciB5b3UgdGhpcyBsaWNlbnNlIHdoaWNo
+IGdpdmVzIHlvdSBsZWdhbCBwZXJtaXNzaW9uIHRvIGNvcHksCmRpc3RyaWJ1dGUgYW5kL29yIG1v
+ZGlmeSB0aGUgc29mdHdhcmUuCgpBbHNvLCBmb3IgZWFjaCBhdXRob3IncyBwcm90ZWN0aW9uIGFu
+ZCBvdXJzLCB3ZSB3YW50IHRvIG1ha2UgY2VydGFpbiB0aGF0CmV2ZXJ5b25lIHVuZGVyc3RhbmRz
+IHRoYXQgdGhlcmUgaXMgbm8gd2FycmFudHkgZm9yIHRoaXMgZnJlZSBzb2Z0d2FyZS4gIElmCnRo
+ZSBzb2Z0d2FyZSBpcyBtb2RpZmllZCBieSBzb21lb25lIGVsc2UgYW5kIHBhc3NlZCBvbiwgd2Ug
+d2FudCBpdHMKcmVjaXBpZW50cyB0byBrbm93IHRoYXQgd2hhdCB0aGV5IGhhdmUgaXMgbm90IHRo
+ZSBvcmlnaW5hbCwgc28gdGhhdCBhbnkKcHJvYmxlbXMgaW50cm9kdWNlZCBieSBvdGhlcnMgd2ls
+bCBub3QgcmVmbGVjdCBvbiB0aGUgb3JpZ2luYWwgYXV0aG9ycycKcmVwdXRhdGlvbnMuCgpGaW5h
+bGx5LCBhbnkgZnJlZSBwcm9ncmFtIGlzIHRocmVhdGVuZWQgY29uc3RhbnRseSBieSBzb2Z0d2Fy
+ZSBwYXRlbnRzLgpXZSB3aXNoIHRvIGF2b2lkIHRoZSBkYW5nZXIgdGhhdCByZWRpc3RyaWJ1dG9y
+cyBvZiBhIGZyZWUgcHJvZ3JhbSB3aWxsCmluZGl2aWR1YWxseSBvYnRhaW4gcGF0ZW50IGxpY2Vu
+c2VzLCBpbiBlZmZlY3QgbWFraW5nIHRoZSBwcm9ncmFtCnByb3ByaWV0YXJ5LiAgVG8gcHJldmVu
+dCB0aGlzLCB3ZSBoYXZlIG1hZGUgaXQgY2xlYXIgdGhhdCBhbnkgcGF0ZW50IG11c3QKYmUgbGlj
+ZW5zZWQgZm9yIGV2ZXJ5b25lJ3MgZnJlZSB1c2Ugb3Igbm90IGxpY2Vuc2VkIGF0IGFsbC4KClRo
+ZSBwcmVjaXNlIHRlcm1zIGFuZCBjb25kaXRpb25zIGZvciBjb3B5aW5nLCBkaXN0cmlidXRpb24g
+YW5kCm1vZGlmaWNhdGlvbiBmb2xsb3cuCgpcYmVnaW57Y2VudGVyfQp7XExhcmdlIFxzYyBUZXJt
+cyBhbmQgQ29uZGl0aW9ucyBGb3IgQ29weWluZywgRGlzdHJpYnV0aW9uIGFuZAogIE1vZGlmaWNh
+dGlvbn0KXGVuZHtjZW50ZXJ9CgoKJVxyZW5ld2NvbW1hbmR7XHRoZWVudW1pfXtcYWxwaGF7ZW51
+bWl9fQpcYmVnaW57ZW51bWVyYXRlfQoKXGFkZHRvY291bnRlcntlbnVtaX17LTF9CgpcaXRlbSAK
+ClRoaXMgTGljZW5zZSBhcHBsaWVzIHRvIGFueSBwcm9ncmFtIG9yIG90aGVyIHdvcmsgd2hpY2gg
+Y29udGFpbnMgYSBub3RpY2UKcGxhY2VkIGJ5IHRoZSBjb3B5cmlnaHQgaG9sZGVyIHNheWluZyBp
+dCBtYXkgYmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlCnRlcm1zIG9mIHRoaXMgR2VuZXJhbCBQdWJs
+aWMgTGljZW5zZS4gIFRoZSBgYFByb2dyYW0nJywgYmVsb3csIHJlZmVycyB0bwphbnkgc3VjaCBw
+cm9ncmFtIG9yIHdvcmssIGFuZCBhIGBgd29yayBiYXNlZCBvbiB0aGUgUHJvZ3JhbScnIG1lYW5z
+IGVpdGhlcgp0aGUgUHJvZ3JhbSBvciBhbnkgZGVyaXZhdGl2ZSB3b3JrIHVuZGVyIGNvcHlyaWdo
+dCBsYXc6IHRoYXQgaXMgdG8gc2F5LCBhCndvcmsgY29udGFpbmluZyB0aGUgUHJvZ3JhbSBvciBh
+IHBvcnRpb24gb2YgaXQsIGVpdGhlciB2ZXJiYXRpbSBvciB3aXRoCm1vZGlmaWNhdGlvbnMgYW5k
+L29yIHRyYW5zbGF0ZWQgaW50byBhbm90aGVyIGxhbmd1YWdlLiAgKEhlcmVpbmFmdGVyLAp0cmFu
+c2xhdGlvbiBpcyBpbmNsdWRlZCB3aXRob3V0IGxpbWl0YXRpb24gaW4gdGhlIHRlcm0gYGBtb2Rp
+ZmljYXRpb24nJy4pCkVhY2ggbGljZW5zZWUgaXMgYWRkcmVzc2VkIGFzIGBgeW91JycuCgpBY3Rp
+dml0aWVzIG90aGVyIHRoYW4gY29weWluZywgZGlzdHJpYnV0aW9uIGFuZCBtb2RpZmljYXRpb24g
+YXJlIG5vdApjb3ZlcmVkIGJ5IHRoaXMgTGljZW5zZTsgdGhleSBhcmUgb3V0c2lkZSBpdHMgc2Nv
+cGUuICBUaGUgYWN0IG9mCnJ1bm5pbmcgdGhlIFByb2dyYW0gaXMgbm90IHJlc3RyaWN0ZWQsIGFu
+ZCB0aGUgb3V0cHV0IGZyb20gdGhlIFByb2dyYW0KaXMgY292ZXJlZCBvbmx5IGlmIGl0cyBjb250
+ZW50cyBjb25zdGl0dXRlIGEgd29yayBiYXNlZCBvbiB0aGUKUHJvZ3JhbSAoaW5kZXBlbmRlbnQg
+b2YgaGF2aW5nIGJlZW4gbWFkZSBieSBydW5uaW5nIHRoZSBQcm9ncmFtKS4KV2hldGhlciB0aGF0
+IGlzIHRydWUgZGVwZW5kcyBvbiB3aGF0IHRoZSBQcm9ncmFtIGRvZXMuCgpcaXRlbSBZb3UgbWF5
+IGNvcHkgYW5kIGRpc3RyaWJ1dGUgdmVyYmF0aW0gY29waWVzIG9mIHRoZSBQcm9ncmFtJ3Mgc291
+cmNlCiAgY29kZSBhcyB5b3UgcmVjZWl2ZSBpdCwgaW4gYW55IG1lZGl1bSwgcHJvdmlkZWQgdGhh
+dCB5b3UgY29uc3BpY3VvdXNseQogIGFuZCBhcHByb3ByaWF0ZWx5IHB1Ymxpc2ggb24gZWFjaCBj
+b3B5IGFuIGFwcHJvcHJpYXRlIGNvcHlyaWdodCBub3RpY2UKICBhbmQgZGlzY2xhaW1lciBvZiB3
+YXJyYW50eTsga2VlcCBpbnRhY3QgYWxsIHRoZSBub3RpY2VzIHRoYXQgcmVmZXIgdG8KICB0aGlz
+IExpY2Vuc2UgYW5kIHRvIHRoZSBhYnNlbmNlIG9mIGFueSB3YXJyYW50eTsgYW5kIGdpdmUgYW55
+IG90aGVyCiAgcmVjaXBpZW50cyBvZiB0aGUgUHJvZ3JhbSBhIGNvcHkgb2YgdGhpcyBMaWNlbnNl
+IGFsb25nIHdpdGggdGhlIFByb2dyYW0uCgpZb3UgbWF5IGNoYXJnZSBhIGZlZSBmb3IgdGhlIHBo
+eXNpY2FsIGFjdCBvZiB0cmFuc2ZlcnJpbmcgYSBjb3B5LCBhbmQgeW91Cm1heSBhdCB5b3VyIG9w
+dGlvbiBvZmZlciB3YXJyYW50eSBwcm90ZWN0aW9uIGluIGV4Y2hhbmdlIGZvciBhIGZlZS4KClxp
+dGVtCgpZb3UgbWF5IG1vZGlmeSB5b3VyIGNvcHkgb3IgY29waWVzIG9mIHRoZSBQcm9ncmFtIG9y
+IGFueSBwb3J0aW9uCm9mIGl0LCB0aHVzIGZvcm1pbmcgYSB3b3JrIGJhc2VkIG9uIHRoZSBQcm9n
+cmFtLCBhbmQgY29weSBhbmQKZGlzdHJpYnV0ZSBzdWNoIG1vZGlmaWNhdGlvbnMgb3Igd29yayB1
+bmRlciB0aGUgdGVybXMgb2YgU2VjdGlvbiAxCmFib3ZlLCBwcm92aWRlZCB0aGF0IHlvdSBhbHNv
+IG1lZXQgYWxsIG9mIHRoZXNlIGNvbmRpdGlvbnM6CgpcYmVnaW57ZW51bWVyYXRlfQoKXGl0ZW0g
+CgpZb3UgbXVzdCBjYXVzZSB0aGUgbW9kaWZpZWQgZmlsZXMgdG8gY2FycnkgcHJvbWluZW50IG5v
+dGljZXMgc3RhdGluZyB0aGF0CnlvdSBjaGFuZ2VkIHRoZSBmaWxlcyBhbmQgdGhlIGRhdGUgb2Yg
+YW55IGNoYW5nZS4KClxpdGVtCgpZb3UgbXVzdCBjYXVzZSBhbnkgd29yayB0aGF0IHlvdSBkaXN0
+cmlidXRlIG9yIHB1Ymxpc2gsIHRoYXQgaW4Kd2hvbGUgb3IgaW4gcGFydCBjb250YWlucyBvciBp
+cyBkZXJpdmVkIGZyb20gdGhlIFByb2dyYW0gb3IgYW55CnBhcnQgdGhlcmVvZiwgdG8gYmUgbGlj
+ZW5zZWQgYXMgYSB3aG9sZSBhdCBubyBjaGFyZ2UgdG8gYWxsIHRoaXJkCnBhcnRpZXMgdW5kZXIg
+dGhlIHRlcm1zIG9mIHRoaXMgTGljZW5zZS4KClxpdGVtCklmIHRoZSBtb2RpZmllZCBwcm9ncmFt
+IG5vcm1hbGx5IHJlYWRzIGNvbW1hbmRzIGludGVyYWN0aXZlbHkKd2hlbiBydW4sIHlvdSBtdXN0
+IGNhdXNlIGl0LCB3aGVuIHN0YXJ0ZWQgcnVubmluZyBmb3Igc3VjaAppbnRlcmFjdGl2ZSB1c2Ug
+aW4gdGhlIG1vc3Qgb3JkaW5hcnkgd2F5LCB0byBwcmludCBvciBkaXNwbGF5IGFuCmFubm91bmNl
+bWVudCBpbmNsdWRpbmcgYW4gYXBwcm9wcmlhdGUgY29weXJpZ2h0IG5vdGljZSBhbmQgYQpub3Rp
+Y2UgdGhhdCB0aGVyZSBpcyBubyB3YXJyYW50eSAob3IgZWxzZSwgc2F5aW5nIHRoYXQgeW91IHBy
+b3ZpZGUKYSB3YXJyYW50eSkgYW5kIHRoYXQgdXNlcnMgbWF5IHJlZGlzdHJpYnV0ZSB0aGUgcHJv
+Z3JhbSB1bmRlcgp0aGVzZSBjb25kaXRpb25zLCBhbmQgdGVsbGluZyB0aGUgdXNlciBob3cgdG8g
+dmlldyBhIGNvcHkgb2YgdGhpcwpMaWNlbnNlLiAgKEV4Y2VwdGlvbjogaWYgdGhlIFByb2dyYW0g
+aXRzZWxmIGlzIGludGVyYWN0aXZlIGJ1dApkb2VzIG5vdCBub3JtYWxseSBwcmludCBzdWNoIGFu
+IGFubm91bmNlbWVudCwgeW91ciB3b3JrIGJhc2VkIG9uCnRoZSBQcm9ncmFtIGlzIG5vdCByZXF1
+aXJlZCB0byBwcmludCBhbiBhbm5vdW5jZW1lbnQuKQoKXGVuZHtlbnVtZXJhdGV9CgoKVGhlc2Ug
+cmVxdWlyZW1lbnRzIGFwcGx5IHRvIHRoZSBtb2RpZmllZCB3b3JrIGFzIGEgd2hvbGUuICBJZgpp
+ZGVudGlmaWFibGUgc2VjdGlvbnMgb2YgdGhhdCB3b3JrIGFyZSBub3QgZGVyaXZlZCBmcm9tIHRo
+ZSBQcm9ncmFtLAphbmQgY2FuIGJlIHJlYXNvbmFibHkgY29uc2lkZXJlZCBpbmRlcGVuZGVudCBh
+bmQgc2VwYXJhdGUgd29ya3MgaW4KdGhlbXNlbHZlcywgdGhlbiB0aGlzIExpY2Vuc2UsIGFuZCBp
+dHMgdGVybXMsIGRvIG5vdCBhcHBseSB0byB0aG9zZQpzZWN0aW9ucyB3aGVuIHlvdSBkaXN0cmli
+dXRlIHRoZW0gYXMgc2VwYXJhdGUgd29ya3MuICBCdXQgd2hlbiB5b3UKZGlzdHJpYnV0ZSB0aGUg
+c2FtZSBzZWN0aW9ucyBhcyBwYXJ0IG9mIGEgd2hvbGUgd2hpY2ggaXMgYSB3b3JrIGJhc2VkCm9u
+IHRoZSBQcm9ncmFtLCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSB3aG9sZSBtdXN0IGJlIG9uIHRo
+ZSB0ZXJtcyBvZgp0aGlzIExpY2Vuc2UsIHdob3NlIHBlcm1pc3Npb25zIGZvciBvdGhlciBsaWNl
+bnNlZXMgZXh0ZW5kIHRvIHRoZQplbnRpcmUgd2hvbGUsIGFuZCB0aHVzIHRvIGVhY2ggYW5kIGV2
+ZXJ5IHBhcnQgcmVnYXJkbGVzcyBvZiB3aG8gd3JvdGUgaXQuCgpUaHVzLCBpdCBpcyBub3QgdGhl
+IGludGVudCBvZiB0aGlzIHNlY3Rpb24gdG8gY2xhaW0gcmlnaHRzIG9yIGNvbnRlc3QKeW91ciBy
+aWdodHMgdG8gd29yayB3cml0dGVuIGVudGlyZWx5IGJ5IHlvdTsgcmF0aGVyLCB0aGUgaW50ZW50
+IGlzIHRvCmV4ZXJjaXNlIHRoZSByaWdodCB0byBjb250cm9sIHRoZSBkaXN0cmlidXRpb24gb2Yg
+ZGVyaXZhdGl2ZSBvcgpjb2xsZWN0aXZlIHdvcmtzIGJhc2VkIG9uIHRoZSBQcm9ncmFtLgoKSW4g
+YWRkaXRpb24sIG1lcmUgYWdncmVnYXRpb24gb2YgYW5vdGhlciB3b3JrIG5vdCBiYXNlZCBvbiB0
+aGUgUHJvZ3JhbQp3aXRoIHRoZSBQcm9ncmFtIChvciB3aXRoIGEgd29yayBiYXNlZCBvbiB0aGUg
+UHJvZ3JhbSkgb24gYSB2b2x1bWUgb2YKYSBzdG9yYWdlIG9yIGRpc3RyaWJ1dGlvbiBtZWRpdW0g
+ZG9lcyBub3QgYnJpbmcgdGhlIG90aGVyIHdvcmsgdW5kZXIKdGhlIHNjb3BlIG9mIHRoaXMgTGlj
+ZW5zZS4KClxpdGVtCllvdSBtYXkgY29weSBhbmQgZGlzdHJpYnV0ZSB0aGUgUHJvZ3JhbSAob3Ig
+YSB3b3JrIGJhc2VkIG9uIGl0LAp1bmRlciBTZWN0aW9uIDIpIGluIG9iamVjdCBjb2RlIG9yIGV4
+ZWN1dGFibGUgZm9ybSB1bmRlciB0aGUgdGVybXMgb2YKU2VjdGlvbnMgMSBhbmQgMiBhYm92ZSBw
+cm92aWRlZCB0aGF0IHlvdSBhbHNvIGRvIG9uZSBvZiB0aGUgZm9sbG93aW5nOgoKXGJlZ2lue2Vu
+dW1lcmF0ZX0KClxpdGVtCgpBY2NvbXBhbnkgaXQgd2l0aCB0aGUgY29tcGxldGUgY29ycmVzcG9u
+ZGluZyBtYWNoaW5lLXJlYWRhYmxlCnNvdXJjZSBjb2RlLCB3aGljaCBtdXN0IGJlIGRpc3RyaWJ1
+dGVkIHVuZGVyIHRoZSB0ZXJtcyBvZiBTZWN0aW9ucwoxIGFuZCAyIGFib3ZlIG9uIGEgbWVkaXVt
+IGN1c3RvbWFyaWx5IHVzZWQgZm9yIHNvZnR3YXJlIGludGVyY2hhbmdlOyBvciwKClxpdGVtCgpB
+Y2NvbXBhbnkgaXQgd2l0aCBhIHdyaXR0ZW4gb2ZmZXIsIHZhbGlkIGZvciBhdCBsZWFzdCB0aHJl
+ZQp5ZWFycywgdG8gZ2l2ZSBhbnkgdGhpcmQgcGFydHksIGZvciBhIGNoYXJnZSBubyBtb3JlIHRo
+YW4geW91cgpjb3N0IG9mIHBoeXNpY2FsbHkgcGVyZm9ybWluZyBzb3VyY2UgZGlzdHJpYnV0aW9u
+LCBhIGNvbXBsZXRlCm1hY2hpbmUtcmVhZGFibGUgY29weSBvZiB0aGUgY29ycmVzcG9uZGluZyBz
+b3VyY2UgY29kZSwgdG8gYmUKZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIFNlY3Rpb25z
+IDEgYW5kIDIgYWJvdmUgb24gYSBtZWRpdW0KY3VzdG9tYXJpbHkgdXNlZCBmb3Igc29mdHdhcmUg
+aW50ZXJjaGFuZ2U7IG9yLAoKXGl0ZW0KCkFjY29tcGFueSBpdCB3aXRoIHRoZSBpbmZvcm1hdGlv
+biB5b3UgcmVjZWl2ZWQgYXMgdG8gdGhlIG9mZmVyCnRvIGRpc3RyaWJ1dGUgY29ycmVzcG9uZGlu
+ZyBzb3VyY2UgY29kZS4gIChUaGlzIGFsdGVybmF0aXZlIGlzCmFsbG93ZWQgb25seSBmb3Igbm9u
+Y29tbWVyY2lhbCBkaXN0cmlidXRpb24gYW5kIG9ubHkgaWYgeW91CnJlY2VpdmVkIHRoZSBwcm9n
+cmFtIGluIG9iamVjdCBjb2RlIG9yIGV4ZWN1dGFibGUgZm9ybSB3aXRoIHN1Y2gKYW4gb2ZmZXIs
+IGluIGFjY29yZCB3aXRoIFN1YnNlY3Rpb24gYiBhYm92ZS4pCgpcZW5ke2VudW1lcmF0ZX0KCgpU
+aGUgc291cmNlIGNvZGUgZm9yIGEgd29yayBtZWFucyB0aGUgcHJlZmVycmVkIGZvcm0gb2YgdGhl
+IHdvcmsgZm9yCm1ha2luZyBtb2RpZmljYXRpb25zIHRvIGl0LiAgRm9yIGFuIGV4ZWN1dGFibGUg
+d29yaywgY29tcGxldGUgc291cmNlCmNvZGUgbWVhbnMgYWxsIHRoZSBzb3VyY2UgY29kZSBmb3Ig
+YWxsIG1vZHVsZXMgaXQgY29udGFpbnMsIHBsdXMgYW55CmFzc29jaWF0ZWQgaW50ZXJmYWNlIGRl
+ZmluaXRpb24gZmlsZXMsIHBsdXMgdGhlIHNjcmlwdHMgdXNlZCB0bwpjb250cm9sIGNvbXBpbGF0
+aW9uIGFuZCBpbnN0YWxsYXRpb24gb2YgdGhlIGV4ZWN1dGFibGUuICBIb3dldmVyLCBhcyBhCnNw
+ZWNpYWwgZXhjZXB0aW9uLCB0aGUgc291cmNlIGNvZGUgZGlzdHJpYnV0ZWQgbmVlZCBub3QgaW5j
+bHVkZQphbnl0aGluZyB0aGF0IGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIChpbiBlaXRoZXIgc291
+cmNlIG9yIGJpbmFyeQpmb3JtKSB3aXRoIHRoZSBtYWpvciBjb21wb25lbnRzIChjb21waWxlciwg
+a2VybmVsLCBhbmQgc28gb24pIG9mIHRoZQpvcGVyYXRpbmcgc3lzdGVtIG9uIHdoaWNoIHRoZSBl
+eGVjdXRhYmxlIHJ1bnMsIHVubGVzcyB0aGF0IGNvbXBvbmVudAppdHNlbGYgYWNjb21wYW5pZXMg
+dGhlIGV4ZWN1dGFibGUuCgpJZiBkaXN0cmlidXRpb24gb2YgZXhlY3V0YWJsZSBvciBvYmplY3Qg
+Y29kZSBpcyBtYWRlIGJ5IG9mZmVyaW5nCmFjY2VzcyB0byBjb3B5IGZyb20gYSBkZXNpZ25hdGVk
+IHBsYWNlLCB0aGVuIG9mZmVyaW5nIGVxdWl2YWxlbnQKYWNjZXNzIHRvIGNvcHkgdGhlIHNvdXJj
+ZSBjb2RlIGZyb20gdGhlIHNhbWUgcGxhY2UgY291bnRzIGFzCmRpc3RyaWJ1dGlvbiBvZiB0aGUg
+c291cmNlIGNvZGUsIGV2ZW4gdGhvdWdoIHRoaXJkIHBhcnRpZXMgYXJlIG5vdApjb21wZWxsZWQg
+dG8gY29weSB0aGUgc291cmNlIGFsb25nIHdpdGggdGhlIG9iamVjdCBjb2RlLgoKXGl0ZW0KWW91
+IG1heSBub3QgY29weSwgbW9kaWZ5LCBzdWJsaWNlbnNlLCBvciBkaXN0cmlidXRlIHRoZSBQcm9n
+cmFtCmV4Y2VwdCBhcyBleHByZXNzbHkgcHJvdmlkZWQgdW5kZXIgdGhpcyBMaWNlbnNlLiAgQW55
+IGF0dGVtcHQKb3RoZXJ3aXNlIHRvIGNvcHksIG1vZGlmeSwgc3VibGljZW5zZSBvciBkaXN0cmli
+dXRlIHRoZSBQcm9ncmFtIGlzCnZvaWQsIGFuZCB3aWxsIGF1dG9tYXRpY2FsbHkgdGVybWluYXRl
+IHlvdXIgcmlnaHRzIHVuZGVyIHRoaXMgTGljZW5zZS4KSG93ZXZlciwgcGFydGllcyB3aG8gaGF2
+ZSByZWNlaXZlZCBjb3BpZXMsIG9yIHJpZ2h0cywgZnJvbSB5b3UgdW5kZXIKdGhpcyBMaWNlbnNl
+IHdpbGwgbm90IGhhdmUgdGhlaXIgbGljZW5zZXMgdGVybWluYXRlZCBzbyBsb25nIGFzIHN1Y2gK
+cGFydGllcyByZW1haW4gaW4gZnVsbCBjb21wbGlhbmNlLgoKXGl0ZW0KWW91IGFyZSBub3QgcmVx
+dWlyZWQgdG8gYWNjZXB0IHRoaXMgTGljZW5zZSwgc2luY2UgeW91IGhhdmUgbm90CnNpZ25lZCBp
+dC4gIEhvd2V2ZXIsIG5vdGhpbmcgZWxzZSBncmFudHMgeW91IHBlcm1pc3Npb24gdG8gbW9kaWZ5
+IG9yCmRpc3RyaWJ1dGUgdGhlIFByb2dyYW0gb3IgaXRzIGRlcml2YXRpdmUgd29ya3MuICBUaGVz
+ZSBhY3Rpb25zIGFyZQpwcm9oaWJpdGVkIGJ5IGxhdyBpZiB5b3UgZG8gbm90IGFjY2VwdCB0aGlz
+IExpY2Vuc2UuICBUaGVyZWZvcmUsIGJ5Cm1vZGlmeWluZyBvciBkaXN0cmlidXRpbmcgdGhlIFBy
+b2dyYW0gKG9yIGFueSB3b3JrIGJhc2VkIG9uIHRoZQpQcm9ncmFtKSwgeW91IGluZGljYXRlIHlv
+dXIgYWNjZXB0YW5jZSBvZiB0aGlzIExpY2Vuc2UgdG8gZG8gc28sIGFuZAphbGwgaXRzIHRlcm1z
+IGFuZCBjb25kaXRpb25zIGZvciBjb3B5aW5nLCBkaXN0cmlidXRpbmcgb3IgbW9kaWZ5aW5nCnRo
+ZSBQcm9ncmFtIG9yIHdvcmtzIGJhc2VkIG9uIGl0LgoKXGl0ZW0KRWFjaCB0aW1lIHlvdSByZWRp
+c3RyaWJ1dGUgdGhlIFByb2dyYW0gKG9yIGFueSB3b3JrIGJhc2VkIG9uIHRoZQpQcm9ncmFtKSwg
+dGhlIHJlY2lwaWVudCBhdXRvbWF0aWNhbGx5IHJlY2VpdmVzIGEgbGljZW5zZSBmcm9tIHRoZQpv
+cmlnaW5hbCBsaWNlbnNvciB0byBjb3B5LCBkaXN0cmlidXRlIG9yIG1vZGlmeSB0aGUgUHJvZ3Jh
+bSBzdWJqZWN0IHRvCnRoZXNlIHRlcm1zIGFuZCBjb25kaXRpb25zLiAgWW91IG1heSBub3QgaW1w
+b3NlIGFueSBmdXJ0aGVyCnJlc3RyaWN0aW9ucyBvbiB0aGUgcmVjaXBpZW50cycgZXhlcmNpc2Ug
+b2YgdGhlIHJpZ2h0cyBncmFudGVkIGhlcmVpbi4KWW91IGFyZSBub3QgcmVzcG9uc2libGUgZm9y
+IGVuZm9yY2luZyBjb21wbGlhbmNlIGJ5IHRoaXJkIHBhcnRpZXMgdG8KdGhpcyBMaWNlbnNlLgoK
+XGl0ZW0KSWYsIGFzIGEgY29uc2VxdWVuY2Ugb2YgYSBjb3VydCBqdWRnbWVudCBvciBhbGxlZ2F0
+aW9uIG9mIHBhdGVudAppbmZyaW5nZW1lbnQgb3IgZm9yIGFueSBvdGhlciByZWFzb24gKG5vdCBs
+aW1pdGVkIHRvIHBhdGVudCBpc3N1ZXMpLApjb25kaXRpb25zIGFyZSBpbXBvc2VkIG9uIHlvdSAo
+d2hldGhlciBieSBjb3VydCBvcmRlciwgYWdyZWVtZW50IG9yCm90aGVyd2lzZSkgdGhhdCBjb250
+cmFkaWN0IHRoZSBjb25kaXRpb25zIG9mIHRoaXMgTGljZW5zZSwgdGhleSBkbyBub3QKZXhjdXNl
+IHlvdSBmcm9tIHRoZSBjb25kaXRpb25zIG9mIHRoaXMgTGljZW5zZS4gIElmIHlvdSBjYW5ub3QK
+ZGlzdHJpYnV0ZSBzbyBhcyB0byBzYXRpc2Z5IHNpbXVsdGFuZW91c2x5IHlvdXIgb2JsaWdhdGlv
+bnMgdW5kZXIgdGhpcwpMaWNlbnNlIGFuZCBhbnkgb3RoZXIgcGVydGluZW50IG9ibGlnYXRpb25z
+LCB0aGVuIGFzIGEgY29uc2VxdWVuY2UgeW91Cm1heSBub3QgZGlzdHJpYnV0ZSB0aGUgUHJvZ3Jh
+bSBhdCBhbGwuICBGb3IgZXhhbXBsZSwgaWYgYSBwYXRlbnQKbGljZW5zZSB3b3VsZCBub3QgcGVy
+bWl0IHJveWFsdHktZnJlZSByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZ3JhbSBieQphbGwgdGhv
+c2Ugd2hvIHJlY2VpdmUgY29waWVzIGRpcmVjdGx5IG9yIGluZGlyZWN0bHkgdGhyb3VnaCB5b3Us
+IHRoZW4KdGhlIG9ubHkgd2F5IHlvdSBjb3VsZCBzYXRpc2Z5IGJvdGggaXQgYW5kIHRoaXMgTGlj
+ZW5zZSB3b3VsZCBiZSB0bwpyZWZyYWluIGVudGlyZWx5IGZyb20gZGlzdHJpYnV0aW9uIG9mIHRo
+ZSBQcm9ncmFtLgoKSWYgYW55IHBvcnRpb24gb2YgdGhpcyBzZWN0aW9uIGlzIGhlbGQgaW52YWxp
+ZCBvciB1bmVuZm9yY2VhYmxlIHVuZGVyCmFueSBwYXJ0aWN1bGFyIGNpcmN1bXN0YW5jZSwgdGhl
+IGJhbGFuY2Ugb2YgdGhlIHNlY3Rpb24gaXMgaW50ZW5kZWQgdG8KYXBwbHkgYW5kIHRoZSBzZWN0
+aW9uIGFzIGEgd2hvbGUgaXMgaW50ZW5kZWQgdG8gYXBwbHkgaW4gb3RoZXIKY2lyY3Vtc3RhbmNl
+cy4KCkl0IGlzIG5vdCB0aGUgcHVycG9zZSBvZiB0aGlzIHNlY3Rpb24gdG8gaW5kdWNlIHlvdSB0
+byBpbmZyaW5nZSBhbnkKcGF0ZW50cyBvciBvdGhlciBwcm9wZXJ0eSByaWdodCBjbGFpbXMgb3Ig
+dG8gY29udGVzdCB2YWxpZGl0eSBvZiBhbnkKc3VjaCBjbGFpbXM7IHRoaXMgc2VjdGlvbiBoYXMg
+dGhlIHNvbGUgcHVycG9zZSBvZiBwcm90ZWN0aW5nIHRoZQppbnRlZ3JpdHkgb2YgdGhlIGZyZWUg
+c29mdHdhcmUgZGlzdHJpYnV0aW9uIHN5c3RlbSwgd2hpY2ggaXMKaW1wbGVtZW50ZWQgYnkgcHVi
+bGljIGxpY2Vuc2UgcHJhY3RpY2VzLiAgTWFueSBwZW9wbGUgaGF2ZSBtYWRlCmdlbmVyb3VzIGNv
+bnRyaWJ1dGlvbnMgdG8gdGhlIHdpZGUgcmFuZ2Ugb2Ygc29mdHdhcmUgZGlzdHJpYnV0ZWQKdGhy
+b3VnaCB0aGF0IHN5c3RlbSBpbiByZWxpYW5jZSBvbiBjb25zaXN0ZW50IGFwcGxpY2F0aW9uIG9m
+IHRoYXQKc3lzdGVtOyBpdCBpcyB1cCB0byB0aGUgYXV0aG9yL2Rvbm9yIHRvIGRlY2lkZSBpZiBo
+ZSBvciBzaGUgaXMgd2lsbGluZwp0byBkaXN0cmlidXRlIHNvZnR3YXJlIHRocm91Z2ggYW55IG90
+aGVyIHN5c3RlbSBhbmQgYSBsaWNlbnNlZSBjYW5ub3QKaW1wb3NlIHRoYXQgY2hvaWNlLgoKVGhp
+cyBzZWN0aW9uIGlzIGludGVuZGVkIHRvIG1ha2UgdGhvcm91Z2hseSBjbGVhciB3aGF0IGlzIGJl
+bGlldmVkIHRvCmJlIGEgY29uc2VxdWVuY2Ugb2YgdGhlIHJlc3Qgb2YgdGhpcyBMaWNlbnNlLgoK
+XGl0ZW0KSWYgdGhlIGRpc3RyaWJ1dGlvbiBhbmQvb3IgdXNlIG9mIHRoZSBQcm9ncmFtIGlzIHJl
+c3RyaWN0ZWQgaW4KY2VydGFpbiBjb3VudHJpZXMgZWl0aGVyIGJ5IHBhdGVudHMgb3IgYnkgY29w
+eXJpZ2h0ZWQgaW50ZXJmYWNlcywgdGhlCm9yaWdpbmFsIGNvcHlyaWdodCBob2xkZXIgd2hvIHBs
+YWNlcyB0aGUgUHJvZ3JhbSB1bmRlciB0aGlzIExpY2Vuc2UKbWF5IGFkZCBhbiBleHBsaWNpdCBn
+ZW9ncmFwaGljYWwgZGlzdHJpYnV0aW9uIGxpbWl0YXRpb24gZXhjbHVkaW5nCnRob3NlIGNvdW50
+cmllcywgc28gdGhhdCBkaXN0cmlidXRpb24gaXMgcGVybWl0dGVkIG9ubHkgaW4gb3IgYW1vbmcK
+Y291bnRyaWVzIG5vdCB0aHVzIGV4Y2x1ZGVkLiAgSW4gc3VjaCBjYXNlLCB0aGlzIExpY2Vuc2Ug
+aW5jb3Jwb3JhdGVzCnRoZSBsaW1pdGF0aW9uIGFzIGlmIHdyaXR0ZW4gaW4gdGhlIGJvZHkgb2Yg
+dGhpcyBMaWNlbnNlLgoKXGl0ZW0KVGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiBtYXkgcHVi
+bGlzaCByZXZpc2VkIGFuZC9vciBuZXcgdmVyc2lvbnMKb2YgdGhlIEdlbmVyYWwgUHVibGljIExp
+Y2Vuc2UgZnJvbSB0aW1lIHRvIHRpbWUuICBTdWNoIG5ldyB2ZXJzaW9ucyB3aWxsCmJlIHNpbWls
+YXIgaW4gc3Bpcml0IHRvIHRoZSBwcmVzZW50IHZlcnNpb24sIGJ1dCBtYXkgZGlmZmVyIGluIGRl
+dGFpbCB0bwphZGRyZXNzIG5ldyBwcm9ibGVtcyBvciBjb25jZXJucy4KCkVhY2ggdmVyc2lvbiBp
+cyBnaXZlbiBhIGRpc3Rpbmd1aXNoaW5nIHZlcnNpb24gbnVtYmVyLiAgSWYgdGhlIFByb2dyYW0K
+c3BlY2lmaWVzIGEgdmVyc2lvbiBudW1iZXIgb2YgdGhpcyBMaWNlbnNlIHdoaWNoIGFwcGxpZXMg
+dG8gaXQgYW5kIGBgYW55CmxhdGVyIHZlcnNpb24nJywgeW91IGhhdmUgdGhlIG9wdGlvbiBvZiBm
+b2xsb3dpbmcgdGhlIHRlcm1zIGFuZCBjb25kaXRpb25zCmVpdGhlciBvZiB0aGF0IHZlcnNpb24g
+b3Igb2YgYW55IGxhdGVyIHZlcnNpb24gcHVibGlzaGVkIGJ5IHRoZSBGcmVlClNvZnR3YXJlIEZv
+dW5kYXRpb24uICBJZiB0aGUgUHJvZ3JhbSBkb2VzIG5vdCBzcGVjaWZ5IGEgdmVyc2lvbiBudW1i
+ZXIgb2YKdGhpcyBMaWNlbnNlLCB5b3UgbWF5IGNob29zZSBhbnkgdmVyc2lvbiBldmVyIHB1Ymxp
+c2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZQpGb3VuZGF0aW9uLgoKXGl0ZW0KSWYgeW91IHdpc2gg
+dG8gaW5jb3Jwb3JhdGUgcGFydHMgb2YgdGhlIFByb2dyYW0gaW50byBvdGhlciBmcmVlCnByb2dy
+YW1zIHdob3NlIGRpc3RyaWJ1dGlvbiBjb25kaXRpb25zIGFyZSBkaWZmZXJlbnQsIHdyaXRlIHRv
+IHRoZSBhdXRob3IKdG8gYXNrIGZvciBwZXJtaXNzaW9uLiAgRm9yIHNvZnR3YXJlIHdoaWNoIGlz
+IGNvcHlyaWdodGVkIGJ5IHRoZSBGcmVlClNvZnR3YXJlIEZvdW5kYXRpb24sIHdyaXRlIHRvIHRo
+ZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IHdlIHNvbWV0aW1lcwptYWtlIGV4Y2VwdGlvbnMg
+Zm9yIHRoaXMuICBPdXIgZGVjaXNpb24gd2lsbCBiZSBndWlkZWQgYnkgdGhlIHR3byBnb2Fscwpv
+ZiBwcmVzZXJ2aW5nIHRoZSBmcmVlIHN0YXR1cyBvZiBhbGwgZGVyaXZhdGl2ZXMgb2Ygb3VyIGZy
+ZWUgc29mdHdhcmUgYW5kCm9mIHByb21vdGluZyB0aGUgc2hhcmluZyBhbmQgcmV1c2Ugb2Ygc29m
+dHdhcmUgZ2VuZXJhbGx5LgoKXGJlZ2lue2NlbnRlcn0Ke1xMYXJnZVxzYwpObyBXYXJyYW50eQp9
+ClxlbmR7Y2VudGVyfQoKXGl0ZW0Ke1xzYyBCZWNhdXNlIHRoZSBwcm9ncmFtIGlzIGxpY2Vuc2Vk
+IGZyZWUgb2YgY2hhcmdlLCB0aGVyZSBpcyBubyB3YXJyYW50eQpmb3IgdGhlIHByb2dyYW0sIHRv
+IHRoZSBleHRlbnQgcGVybWl0dGVkIGJ5IGFwcGxpY2FibGUgbGF3LiAgRXhjZXB0IHdoZW4Kb3Ro
+ZXJ3aXNlIHN0YXRlZCBpbiB3cml0aW5nIHRoZSBjb3B5cmlnaHQgaG9sZGVycyBhbmQvb3Igb3Ro
+ZXIgcGFydGllcwpwcm92aWRlIHRoZSBwcm9ncmFtIGBgYXMgaXMnJyB3aXRob3V0IHdhcnJhbnR5
+IG9mIGFueSBraW5kLCBlaXRoZXIgZXhwcmVzc2VkCm9yIGltcGxpZWQsIGluY2x1ZGluZywgYnV0
+IG5vdCBsaW1pdGVkIHRvLCB0aGUgaW1wbGllZCB3YXJyYW50aWVzIG9mCm1lcmNoYW50YWJpbGl0
+eSBhbmQgZml0bmVzcyBmb3IgYSBwYXJ0aWN1bGFyIHB1cnBvc2UuICBUaGUgZW50aXJlIHJpc2sg
+YXMKdG8gdGhlIHF1YWxpdHkgYW5kIHBlcmZvcm1hbmNlIG9mIHRoZSBwcm9ncmFtIGlzIHdpdGgg
+eW91LiAgU2hvdWxkIHRoZQpwcm9ncmFtIHByb3ZlIGRlZmVjdGl2ZSwgeW91IGFzc3VtZSB0aGUg
+Y29zdCBvZiBhbGwgbmVjZXNzYXJ5IHNlcnZpY2luZywKcmVwYWlyIG9yIGNvcnJlY3Rpb24ufQoK
+XGl0ZW0Ke1xzYyBJbiBubyBldmVudCB1bmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcg
+b3IgYWdyZWVkIHRvIGluIHdyaXRpbmcKd2lsbCBhbnkgY29weXJpZ2h0IGhvbGRlciwgb3IgYW55
+IG90aGVyIHBhcnR5IHdobyBtYXkgbW9kaWZ5IGFuZC9vcgpyZWRpc3RyaWJ1dGUgdGhlIHByb2dy
+YW0gYXMgcGVybWl0dGVkIGFib3ZlLCBiZSBsaWFibGUgdG8geW91IGZvciBkYW1hZ2VzLAppbmNs
+dWRpbmcgYW55IGdlbmVyYWwsIHNwZWNpYWwsIGluY2lkZW50YWwgb3IgY29uc2VxdWVudGlhbCBk
+YW1hZ2VzIGFyaXNpbmcKb3V0IG9mIHRoZSB1c2Ugb3IgaW5hYmlsaXR5IHRvIHVzZSB0aGUgcHJv
+Z3JhbSAoaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZAp0byBsb3NzIG9mIGRhdGEgb3IgZGF0YSBi
+ZWluZyByZW5kZXJlZCBpbmFjY3VyYXRlIG9yIGxvc3NlcyBzdXN0YWluZWQgYnkKeW91IG9yIHRo
+aXJkIHBhcnRpZXMgb3IgYSBmYWlsdXJlIG9mIHRoZSBwcm9ncmFtIHRvIG9wZXJhdGUgd2l0aCBh
+bnkgb3RoZXIKcHJvZ3JhbXMpLCBldmVuIGlmIHN1Y2ggaG9sZGVyIG9yIG90aGVyIHBhcnR5IGhh
+cyBiZWVuIGFkdmlzZWQgb2YgdGhlCnBvc3NpYmlsaXR5IG9mIHN1Y2ggZGFtYWdlcy59CgpcZW5k
+e2VudW1lcmF0ZX0KCgpcYmVnaW57Y2VudGVyfQp7XExhcmdlXHNjIEVuZCBvZiBUZXJtcyBhbmQg
+Q29uZGl0aW9uc30KXGVuZHtjZW50ZXJ9CgoKXHBhZ2VicmVha1syXQoKXHNlY3Rpb24qe0FwcGVu
+ZGl4OiBIb3cgdG8gQXBwbHkgVGhlc2UgVGVybXMgdG8gWW91ciBOZXcgUHJvZ3JhbXN9CgpJZiB5
+b3UgZGV2ZWxvcCBhIG5ldyBwcm9ncmFtLCBhbmQgeW91IHdhbnQgaXQgdG8gYmUgb2YgdGhlIGdy
+ZWF0ZXN0CnBvc3NpYmxlIHVzZSB0byB0aGUgcHVibGljLCB0aGUgYmVzdCB3YXkgdG8gYWNoaWV2
+ZSB0aGlzIGlzIHRvIG1ha2UgaXQKZnJlZSBzb2Z0d2FyZSB3aGljaCBldmVyeW9uZSBjYW4gcmVk
+aXN0cmlidXRlIGFuZCBjaGFuZ2UgdW5kZXIgdGhlc2UKdGVybXMuCgogIFRvIGRvIHNvLCBhdHRh
+Y2ggdGhlIGZvbGxvd2luZyBub3RpY2VzIHRvIHRoZSBwcm9ncmFtLiAgSXQgaXMgc2FmZXN0IHRv
+CiAgYXR0YWNoIHRoZW0gdG8gdGhlIHN0YXJ0IG9mIGVhY2ggc291cmNlIGZpbGUgdG8gbW9zdCBl
+ZmZlY3RpdmVseSBjb252ZXkKICB0aGUgZXhjbHVzaW9uIG9mIHdhcnJhbnR5OyBhbmQgZWFjaCBm
+aWxlIHNob3VsZCBoYXZlIGF0IGxlYXN0IHRoZQogIGBgY29weXJpZ2h0JycgbGluZSBhbmQgYSBw
+b2ludGVyIHRvIHdoZXJlIHRoZSBmdWxsIG5vdGljZSBpcyBmb3VuZC4KClxiZWdpbntxdW90ZX0K
+b25lIGxpbmUgdG8gZ2l2ZSB0aGUgcHJvZ3JhbSdzIG5hbWUgYW5kIGEgYnJpZWYgaWRlYSBvZiB3
+aGF0IGl0IGRvZXMuIFxcCkNvcHlyaWdodCAoQykgeXl5eSAgbmFtZSBvZiBhdXRob3IgXFwKClRo
+aXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQv
+b3IgbW9kaWZ5Cml0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExp
+Y2Vuc2UgYXMgcHVibGlzaGVkIGJ5CnRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhl
+ciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCihhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVy
+IHZlcnNpb24uCgpUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBp
+dCB3aWxsIGJlIHVzZWZ1bCwKYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4g
+dGhlIGltcGxpZWQgd2FycmFudHkgb2YKTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEg
+UEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQpHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBm
+b3IgbW9yZSBkZXRhaWxzLgoKWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUg
+R05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5v
+dCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxl
+IFBsYWNlIC0gU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3LCBVU0EuClxlbmR7cXVv
+dGV9CgpBbHNvIGFkZCBpbmZvcm1hdGlvbiBvbiBob3cgdG8gY29udGFjdCB5b3UgYnkgZWxlY3Ry
+b25pYyBhbmQgcGFwZXIgbWFpbC4KCklmIHRoZSBwcm9ncmFtIGlzIGludGVyYWN0aXZlLCBtYWtl
+IGl0IG91dHB1dCBhIHNob3J0IG5vdGljZSBsaWtlIHRoaXMKd2hlbiBpdCBzdGFydHMgaW4gYW4g
+aW50ZXJhY3RpdmUgbW9kZToKClxiZWdpbntxdW90ZX0KR25vbW92aXNpb24gdmVyc2lvbiA2OSwg
+Q29weXJpZ2h0IChDKSB5eXl5ICBuYW1lIG9mIGF1dGhvciBcXApHbm9tb3Zpc2lvbiBjb21lcyB3
+aXRoIEFCU09MVVRFTFkgTk8gV0FSUkFOVFk7IGZvciBkZXRhaWxzIHR5cGUgYHNob3cgdycuIFxc
+ClRoaXMgaXMgZnJlZSBzb2Z0d2FyZSwgYW5kIHlvdSBhcmUgd2VsY29tZSB0byByZWRpc3RyaWJ1
+dGUgaXQKdW5kZXIgY2VydGFpbiBjb25kaXRpb25zOyB0eXBlIGBzaG93IGMnIGZvciBkZXRhaWxz
+LgpcZW5ke3F1b3RlfQoKClRoZSBoeXBvdGhldGljYWwgY29tbWFuZHMge1x0dCBzaG93IHd9IGFu
+ZCB7XHR0IHNob3cgY30gc2hvdWxkIHNob3cgdGhlCmFwcHJvcHJpYXRlIHBhcnRzIG9mIHRoZSBH
+ZW5lcmFsIFB1YmxpYyBMaWNlbnNlLiAgT2YgY291cnNlLCB0aGUgY29tbWFuZHMKeW91IHVzZSBt
+YXkgYmUgY2FsbGVkIHNvbWV0aGluZyBvdGhlciB0aGFuIHtcdHQgc2hvdyB3fSBhbmQge1x0dCBz
+aG93IGN9Owp0aGV5IGNvdWxkIGV2ZW4gYmUgbW91c2UtY2xpY2tzIG9yIG1lbnUgaXRlbXMtLS13
+aGF0ZXZlciBzdWl0cyB5b3VyCnByb2dyYW0uCgpZb3Ugc2hvdWxkIGFsc28gZ2V0IHlvdXIgZW1w
+bG95ZXIgKGlmIHlvdSB3b3JrIGFzIGEgcHJvZ3JhbW1lcikgb3IgeW91cgpzY2hvb2wsIGlmIGFu
+eSwgdG8gc2lnbiBhIGBgY29weXJpZ2h0IGRpc2NsYWltZXInJyBmb3IgdGhlIHByb2dyYW0sIGlm
+Cm5lY2Vzc2FyeS4gIEhlcmUgaXMgYSBzYW1wbGU7IGFsdGVyIHRoZSBuYW1lczoKClxiZWdpbntx
+dW90ZX0KWW95b2R5bmUsIEluYy4sIGhlcmVieSBkaXNjbGFpbXMgYWxsIGNvcHlyaWdodCBpbnRl
+cmVzdCBpbiB0aGUgcHJvZ3JhbSBcXApgR25vbW92aXNpb24nICh3aGljaCBtYWtlcyBwYXNzZXMg
+YXQgY29tcGlsZXJzKSB3cml0dGVuIGJ5IEphbWVzIEhhY2tlci4gXFwKCnNpZ25hdHVyZSBvZiBU
+eSBDb29uLCAxIEFwcmlsIDE5ODkgXFwKVHkgQ29vbiwgUHJlc2lkZW50IG9mIFZpY2UKXGVuZHtx
+dW90ZX0KCgpUaGlzIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZG9lcyBub3QgcGVybWl0IGluY29y
+cG9yYXRpbmcgeW91ciBwcm9ncmFtCmludG8gcHJvcHJpZXRhcnkgcHJvZ3JhbXMuICBJZiB5b3Vy
+IHByb2dyYW0gaXMgYSBzdWJyb3V0aW5lIGxpYnJhcnksIHlvdQptYXkgY29uc2lkZXIgaXQgbW9y
+ZSB1c2VmdWwgdG8gcGVybWl0IGxpbmtpbmcgcHJvcHJpZXRhcnkgYXBwbGljYXRpb25zCndpdGgg
+dGhlIGxpYnJhcnkuICBJZiB0aGlzIGlzIHdoYXQgeW91IHdhbnQgdG8gZG8sIHVzZSB0aGUgR05V
+IExpYnJhcnkKR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBpbnN0ZWFkIG9mIHRoaXMgTGljZW5zZS4K
+Cgo=
+" ++ Glurf ++ lists:reverse(Glurf++"kalle").
diff --git a/lib/compiler/test/compilation_SUITE_data/nested_tuples_in_case_expr.erl b/lib/compiler/test/compilation_SUITE_data/nested_tuples_in_case_expr.erl
new file mode 100644
index 0000000000..62402c10b7
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/nested_tuples_in_case_expr.erl
@@ -0,0 +1,36 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(nested_tuples_in_case_expr).
+-export([nested_tuples_in_case_expr/0,t/2]).
+
+nested_tuples_in_case_expr() ->
+ ok.
+
+t(A, B) ->
+ case {{element(1, A),element(2, B)},{element(2, A),element(2, B)}} of
+ {Same,Same} -> ok;
+ {{0,1},{up,X}} -> bar(X);
+ {_,{X,_}} -> bar(X)
+ end.
+
+bar(X) -> X.
+
+
+
+
diff --git a/lib/compiler/test/compilation_SUITE_data/on_load.erl b/lib/compiler/test/compilation_SUITE_data/on_load.erl
new file mode 100644
index 0000000000..92bcf74624
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/on_load.erl
@@ -0,0 +1,18 @@
+-module(on_load).
+-export([?MODULE/0]).
+
+-on_load(do_on_load/0).
+
+%% Only test that the compiler is able to compile a module
+%% with an on_load attribute. (There will be more thorough tests
+%% of the functionality in code_SUITE in the Kernel application.)
+
+?MODULE() ->
+ ok.
+
+do_on_load() ->
+ local_function(),
+ true.
+
+local_function() ->
+ ok.
diff --git a/lib/compiler/test/compilation_SUITE_data/opt_crash.erl b/lib/compiler/test/compilation_SUITE_data/opt_crash.erl
new file mode 100644
index 0000000000..3a1d625c28
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/opt_crash.erl
@@ -0,0 +1,65 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(opt_crash).
+-export([?MODULE/0,test/0]).
+
+?MODULE() ->
+ ok.
+
+test() ->
+ URI_Before =
+ {absoluteURI,
+ {scheme,fun() -> nil end},
+ {'hier-part',
+ {'net-path',
+ {srvr,
+ {userinfo,nil},
+ fun() -> nil end},
+ nil},
+ {'query',nil}}},
+
+ {absoluteURI,
+ {scheme,_},
+ {'hier-part',
+ {'net-path',
+ {srvr,
+ {userinfo,nil},
+ HostportBefore},
+ nil},
+ {'query',nil}}} = URI_Before,
+
+ %% ... some funky code ommitted, not relevant ...
+
+ {absoluteURI,
+ {scheme,_},
+ {'hier-part',
+ {'net-path',
+ {srvr,
+ {userinfo,nil},
+ HostportAfter},
+ nil},
+ {'query',nil}}} = URI_Before,
+ %% NOTE: I intended to write URI_After instead of URI_Before
+ %% but the accident revealed that when you add the line below,
+ %% it causes internal error in v3_codegen on compilation
+ {hostport,{hostname,"HostName"},{port,nil}} = HostportAfter,
+
+ ok.
+
+
diff --git a/lib/compiler/test/compilation_SUITE_data/other/vsn_1.erl b/lib/compiler/test/compilation_SUITE_data/other/vsn_1.erl
new file mode 100644
index 0000000000..7cb0778b95
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/other/vsn_1.erl
@@ -0,0 +1,19 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(vsn_1).
diff --git a/lib/compiler/test/compilation_SUITE_data/other/vsn_3.erl b/lib/compiler/test/compilation_SUITE_data/other/vsn_3.erl
new file mode 100644
index 0000000000..3870e0704d
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/other/vsn_3.erl
@@ -0,0 +1,24 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(vsn_3).
+
+-export([f/1]).
+
+f(X) ->
+ 2*X.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_2141.erl b/lib/compiler/test/compilation_SUITE_data/otp_2141.erl
new file mode 100644
index 0000000000..3e766546be
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_2141.erl
@@ -0,0 +1,24 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_2141).
+-export([otp_2141/0]).
+
+
+otp_2141() ->
+ ok.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_2173.erl b/lib/compiler/test/compilation_SUITE_data/otp_2173.erl
new file mode 100644
index 0000000000..7e9d4c417b
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_2173.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_2173).
+-compile(export_all).
+
+-record(t, {a = fun(X) -> X*X end}).
+
+otp_2173() ->
+ ok.
+
+t() ->
+ #t{}.
+
+
+
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_2330.erl b/lib/compiler/test/compilation_SUITE_data/otp_2330.erl
new file mode 100644
index 0000000000..f5f6717968
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_2330.erl
@@ -0,0 +1,35 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_2330).
+-export([otp_2330/0, handle_interface/1]).
+
+otp_2330() ->
+ ok.
+
+handle_interface(Data)->
+ Ctrl = 1,
+ case Data of
+ ok ->
+ case Ctrl of
+ [Viar]->integer_to_list(Viar);
+ _ -> []
+
+ end
+ end.
+
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_2380.erl b/lib/compiler/test/compilation_SUITE_data/otp_2380.erl
new file mode 100644
index 0000000000..db2028b347
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_2380.erl
@@ -0,0 +1,36 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_2380).
+-export([test/0, otp_2380/0]).
+
+otp_2380() ->
+ ok.
+
+-define(FUNC(Name),
+ case Name of
+ dpCh -> 5;
+ dpEvent -> 1;
+ dpc -> 4;
+ dpFm -> 6;
+ dpFm1 -> 6;
+ _ -> false
+ end).
+
+test() ->
+ N = ?FUNC(dpCh).
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_4790.erl b/lib/compiler/test/compilation_SUITE_data/otp_4790.erl
new file mode 100644
index 0000000000..130ee44e80
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_4790.erl
@@ -0,0 +1,63 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_4790).
+
+-export([?MODULE/0]).
+
+?MODULE() ->
+ pan_test().
+
+
+% --------------------------- OTP Ticket --------------------------------
+% *Id: OTP-4790
+% *Notes: In the code below, the compiler incorrectly assumes
+% wings_pref:get_value(pan_speed) returns a float,
+% causing a crash at run-time.
+
+% The same error could cause tuple tests to be removed,
+% but that would propbably only cause a crash if the
+% Erlang code was incorrect or if it depended on a catch
+% to catch exceptions. Therefore, I consider it unlikely
+% that Erlang programs that don't use floating point
+% arithmetic are likely to be bitten by this bug.
+% -----------------------------------------------------------------------
+
+-record(view, {pan_x,pan_y,distance}).
+
+pan_test() ->
+ pan(13, 3).
+
+pan(Dx0, Dy0) ->
+ #view{pan_x=PanX0,pan_y=PanY0,distance=D} = View = current(),
+ S = D*(1/8)/(51-pref_get_value(pan_speed)),
+ Dx = Dx0*S,
+ Dy = Dy0*S,
+ PanX = PanX0 + Dx,
+ PanY = PanY0 - Dy,
+ set_current(View#view{pan_x=PanX,pan_y=PanY}).
+
+current() ->
+ #view{pan_x=2.0,pan_y=9.75,distance=25.3}.
+
+set_current(#view{pan_x=X,pan_y=Y,distance=D})
+ when is_float(X), is_float(Y), is_float(D) ->
+ io:format("X=~p Y=~p D=~p\n", [X,Y,D]).
+
+pref_get_value(pan_speed) ->
+ 32.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5076.erl b/lib/compiler/test/compilation_SUITE_data/otp_5076.erl
new file mode 100644
index 0000000000..f05a4e1148
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5076.erl
@@ -0,0 +1,27 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5076).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ [] = t(),
+ ok.
+
+t() ->
+ [3 || {3=4} <- []].
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5092.erl b/lib/compiler/test/compilation_SUITE_data/otp_5092.erl
new file mode 100644
index 0000000000..e445e5e1e9
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5092.erl
@@ -0,0 +1,39 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5092).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ [] = t(),
+ [] = t2(),
+ [t] = t4(),
+ [] = t5(),
+ ok.
+
+t() ->
+ [t || {C=D}={_,_} <- []].
+
+t2() ->
+ [X || {X,{Y}={X,X}} <- []].
+
+t4() ->
+ [t || "a"++"b" = "ab" <- ["ab"]].
+
+t5() ->
+ [{X,Y} || {X} <- [], begin Y = X, Y =:= X end].
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5151.erl b/lib/compiler/test/compilation_SUITE_data/otp_5151.erl
new file mode 100644
index 0000000000..2dccb979df
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5151.erl
@@ -0,0 +1,61 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5151).
+
+-export([?MODULE/0]).
+-export([read_variables/1,read_variables_1/1,read_variables_2/1,
+ read_variables_3/1,read_variables_4/1]).
+
+?MODULE() ->
+ ok.
+
+read_variables(Name) ->
+ case file:consult(Name) of
+ {ok,Vars} -> Vars;
+ {error,Reason} ->
+ erlang:error({bad_installation,file:format_error(Reason)}, [Name])
+ end.
+
+read_variables_1(Name) ->
+ case file:consult(Name) of
+ {ok,Vars} -> Vars;
+ {error,Reason} ->
+ erlang:error({bad_installation,file:format_error(Reason)})
+ end.
+
+read_variables_2(Name) ->
+ case file:consult(Name) of
+ {ok,Vars} -> Vars;
+ {error,Reason} ->
+ erlang:error({bad_installation,file:format_error(Reason)}, [Name])
+ end.
+
+read_variables_3(Name) ->
+ case file:consult(Name) of
+ {ok,Vars} -> Vars;
+ {error,Reason} ->
+ erlang:error({bad_installation,file:format_error(Reason)})
+ end.
+
+read_variables_4(Name) ->
+ case file:consult(Name) of
+ {ok,Vars} -> Vars;
+ {error,Reason} ->
+ exit({bad_installation,file:format_error(Reason)})
+ end.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5235.erl b/lib/compiler/test/compilation_SUITE_data/otp_5235.erl
new file mode 100644
index 0000000000..1c918cdf9d
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5235.erl
@@ -0,0 +1,84 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5235).
+-export([?MODULE/0]).
+
+-record(commit, {node,
+ decision, % presume_commit | Decision
+ ram_copies = [],
+ disc_copies = [],
+ disc_only_copies = [],
+ snmp = [],
+ schema_ops = [self(),make_ref()]
+ }).
+
+?MODULE() ->
+ process_flag(trap_exit, true),
+ N = 1024,
+ clone(N),
+ wait(N).
+
+wait(0) -> ok;
+wait(N) ->
+ receive
+ {'EXIT',_,normal} ->
+ wait(N-1);
+ Other ->
+ exit(Other)
+ end.
+
+clone(0) -> ok;
+clone(N) ->
+ spawn_link(fun worker/0),
+ clone(N-1).
+
+worker() ->
+ Seq = lists:seq(1, 10),
+ PidList = [{N,self()} || N <- Seq],
+ Commit = #commit{ram_copies=PidList,disc_copies=[],
+ disc_only_copies=[],snmp=[]},
+ List = lists:duplicate(2, Commit),
+ verify(run(2, List)).
+
+verify([#commit{node=true,ram_copies=L}|T]) ->
+ verify_1(L, 1),
+ verify(T);
+verify([]) -> ok.
+
+verify_1([{N,Pid}|T], N) when Pid =:= self() ->
+ verify_1(T, N+1);
+verify_1([], _) -> ok.
+
+run(0, L) -> L;
+run(N, L) -> run(N-1, reverse(L)).
+
+reverse([]) -> [];
+reverse([H|R]) when record(H, commit) ->
+ [H#commit{
+ ram_copies = lists:reverse(H#commit.ram_copies),
+ disc_copies = lists:reverse(H#commit.disc_copies),
+ disc_only_copies = lists:reverse(H#commit.disc_only_copies),
+ snmp = lists:reverse(H#commit.snmp),
+ node = erlang:yield()
+ }
+ | reverse(R)].
+
+
+
+
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5244.erl b/lib/compiler/test/compilation_SUITE_data/otp_5244.erl
new file mode 100644
index 0000000000..30849c6b5e
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5244.erl
@@ -0,0 +1,47 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5244).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ L = [{stretch,0,0},
+ {bad,[]},
+ {bad,atom},
+ {bad,0},
+ {bad,16#AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA},
+ {bad,16#555555555555555555555555555555555555555555555555555}],
+ remove_failure(L, unit, 0).
+
+remove_failure([], _Unit, _MaxFailure) ->
+ ok;
+remove_failure([{bad,Bad}|_], _Unit, _MaxFailure) ->
+ Bad;
+remove_failure([{stretch,_,Mi}=Stretch | Specs], Unit, _MaxFailure) ->
+ {MinMax,NewMaxFailure} = max_failure(),
+ case {MinMax,remove_failure(Specs, Unit, NewMaxFailure)} of
+ {min,{NewMaxFailure,Rest}} ->
+ {done,[{fixed,Mi} | Rest]};
+ {min,_} when Specs =/= [] ->
+ remove_failure([Stretch|tl(Specs)], Unit, NewMaxFailure);
+ {min,_} ->
+ ok
+ end.
+
+max_failure() ->
+ {min,1}.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5404.erl b/lib/compiler/test/compilation_SUITE_data/otp_5404.erl
new file mode 100644
index 0000000000..2de147c082
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5404.erl
@@ -0,0 +1,51 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5404).
+-compile(export_all).
+
+%% Thanks to Martin Bjorklund.
+
+?MODULE() ->
+ ok.
+
+-record(bar, {status, vs = []}).
+
+y() ->
+ x({foo, 1, []}).
+
+get_bar() ->
+ #bar{status = 1}.
+
+x(Trans) ->
+ {foo, Barno, _} = Trans,
+ case get_bar() of
+ Bar when Bar#bar.status /= 2 ->
+ if 1 == 1 ->
+ mnesia:dirty_delete({bar, Barno}),
+ Vs = [1,2] ++ Bar#bar.vs,
+ Bar33 = Bar#bar{status = 1},
+ Bar1 = Bar#bar{status = 3,
+ vs = Vs},
+ [{payment, Barno}];
+ true ->
+ Barno
+ end;
+ _ ->
+ Trans
+ end.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5436.erl b/lib/compiler/test/compilation_SUITE_data/otp_5436.erl
new file mode 100644
index 0000000000..4df8d50647
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5436.erl
@@ -0,0 +1,201 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5436).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+-record(readerState, {action_index,
+ log_index,
+ log_name,
+ time_period,
+ rec_id_period,
+ result_format,
+ action_status,
+ filter_type,
+ event_list,
+ sender_list,
+ read_status}).
+
+handle_call(delete,_From,State) ->
+ case catch debug:filter(console,logReader) of
+ true ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,306,console,self(),sysAssert:format_time2(erlang:now())])|"delete, State: ~p ~n"],[State]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["delete, State: ~p ~n",[State]]),
+ ok
+ end;
+ false ->
+ disabled;
+ {'EXIT',{undef,_}} ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,306,console,self(),sysAssert:format_time2(erlang:now())])|"delete, State: ~p ~n"],[State]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["delete, State: ~p ~n",[State]]),
+ ok
+ end;
+ {'EXIT',_} ->
+ debug:filter(console,logReader);
+ _ ->
+ exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}})
+ end,
+ ?MODULE:clean_result(State),
+ {stop,normal,ok,State};
+handle_call(die,_,State) ->
+ {stop,normal,ok,State};
+handle_call(_Action,_From,#readerState{action_status = 2} = State) ->
+ {reply,error,State};
+handle_call(update_action_attr,_From,State) ->
+ NewState = ?MODULE:handle_update_action_attr(State),
+ case catch debug:filter(console,logReader) of
+ true ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,317,console,self(),sysAssert:format_time2(erlang:now())])|"update_action_attr, State: ~p ~n"],[NewState]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["update_action_attr, State: ~p ~n",[NewState]]),
+ ok
+ end;
+ false ->
+ disabled;
+ {'EXIT',{undef,_}} ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,317,console,self(),sysAssert:format_time2(erlang:now())])|"update_action_attr, State: ~p ~n"],[NewState]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["update_action_attr, State: ~p ~n",[NewState]]),
+ ok
+ end;
+ {'EXIT',_} ->
+ debug:filter(console,logReader);
+ _ ->
+ exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}})
+ end,
+ {reply,ok,NewState};
+handle_call(update_event_filter,_From,State) ->
+ NewState = State#readerState{event_list = ?MODULE:get_event_list(State#readerState.action_index)},
+ case catch debug:filter(console,logReader) of
+ true ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,323,console,self(),sysAssert:format_time2(erlang:now())])|"update_event_filter, State: ~p ~n"],[NewState]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["update_event_filter, State: ~p ~n",[NewState]]),
+ ok
+ end;
+ false ->
+ disabled;
+ {'EXIT',{undef,_}} ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,323,console,self(),sysAssert:format_time2(erlang:now())])|"update_event_filter, State: ~p ~n"],[NewState]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["update_event_filter, State: ~p ~n",[NewState]]),
+ ok
+ end;
+ {'EXIT',_} ->
+ debug:filter(console,logReader);
+ _ ->
+ exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}})
+ end,
+ {reply,ok,NewState};
+handle_call(update_sender_filter,_From,State) ->
+ NewState = State#readerState{sender_list = ?MODULE:get_sender_list(State#readerState.action_index)},
+ case catch debug:filter(console,logReader) of
+ true ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,329,console,self(),sysAssert:format_time2(erlang:now())])|"update_sender_filter, State: ~p ~n"],[NewState]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["update_sender_filter, State: ~p ~n",[NewState]]),
+ ok
+ end;
+ false ->
+ disabled;
+ {'EXIT',{undef,_}} ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,329,console,self(),sysAssert:format_time2(erlang:now())])|"update_sender_filter, State: ~p ~n"],[NewState]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["update_sender_filter, State: ~p ~n",[NewState]]),
+ ok
+ end;
+ {'EXIT',_} ->
+ debug:filter(console,logReader);
+ _ ->
+ exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}})
+ end,
+ {reply,ok,NewState};
+handle_call(Request,_From,State) ->
+ case catch debug:filter(console,logReader) of
+ true ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,332,console,self(),sysAssert:format_time2(erlang:now())])|"Call ~p, State: ~p ~n"],[Request,State]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["Call ~p, State: ~p ~n",[Request,State]]),
+ ok
+ end;
+ false ->
+ disabled;
+ {'EXIT',{undef,_}} ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,332,console,self(),sysAssert:format_time2(erlang:now())])|"Call ~p, State: ~p ~n"],[Request,State]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["Call ~p, State: ~p ~n",[Request,State]]),
+ ok
+ end;
+ {'EXIT',_} ->
+ debug:filter(console,logReader);
+ _ ->
+ exit({badmatch,{{debug,filter,[console,logReader]},debug:filter(console,logReader)}})
+ end,
+ {stop,{error,unknown,Request},State}.
+
+handle_info(Request,State) ->
+ case catch debug:filter(readlog,logReader) of
+ true ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,345,readlog,self(),sysAssert:format_time2(erlang:now())])|"Info ~p, State: ~p ~n"],[Request,State]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["Info ~p, State: ~p ~n",[Request,State]]),
+ ok
+ end;
+ false ->
+ disabled;
+ {'EXIT',{undef,_}} ->
+ case io:format([io_lib:format("~nSYS_DBG {~p,~p,~p}, ~w ~s:~n-- ",[logReader,345,readlog,self(),sysAssert:format_time2(erlang:now())])|"Info ~p, State: ~p ~n"],[Request,State]) of
+ ok ->
+ ok;
+ _ ->
+ io:format("*** Bad format (~p, ~p) ***~n",["Info ~p, State: ~p ~n",[Request,State]]),
+ ok
+ end;
+ {'EXIT',_} ->
+ debug:filter(readlog,logReader);
+ _ ->
+ exit({badmatch,{{debug,filter,[readlog,logReader]},debug:filter(readlog,logReader)}})
+ end,
+ {stop,{error,unknown,Request},State}.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5481.erl b/lib/compiler/test/compilation_SUITE_data/otp_5481.erl
new file mode 100644
index 0000000000..5cf114ac4e
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5481.erl
@@ -0,0 +1,527 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5481).
+
+-export([?MODULE/0,encode_cc_clpn/1,get_oper_status/2,foo/0]).
+
+?MODULE() ->
+ ok.
+
+-record(pchVp, {vplEntry,
+ vplLastChange,
+ vplReceiveTrafficDescrIndex = 0,
+ vplTransmitTrafficDescrIndex = 0,
+ vplConnId,
+ vplGroupShapingId}).
+
+-record(pchVc, {vclEntry,
+ vclLastChange,
+ vplConnId,
+ vclConnId,
+ vclShapingMode = 1}).
+-record(spvcVpc, {spvcVpcEntry,
+ currentState,
+ spvcRerCap = false,
+ spvcRerStatus = false}).
+-record(spvcVpcPerm, {spvcVpcEntry,
+ spvcVpcTargetAddress,
+ spvcVpcTargetSelectType,
+ spvcVpcUserName,
+ spvcVpcProviderName,
+ spvcVpcApplication}).
+-record(spvcVcc, {spvcVccEntry,
+ spvcVccTargetAddress,
+ spvcVccTargetSelectType,
+ spvcVccTargetVpi,
+ spvcVccApplication,
+ spvcVccFrKey,
+ spvcVccTranslationMode,
+ spvcRerCap = false,
+ currentState,
+ spvcRerStatus = false}).
+-record(spvcVccPerm, {spvcVccEntry,
+ spvcVccTargetAddress,
+ spvcVccTargetSelectType,
+ spvcVccTargetVpi,
+ spvcVccTargetType,
+ spvcVccApplication,
+ spvcVccFrKey,
+ spvcVccTranslationMode = 2}).
+-record(spvcObj, {spvcEntry,
+ spvcTargetAddress,
+ spvcTargetSelectType,
+ spvcTargetVpi,
+ spvcTargetVci,
+ spvcLastReleaseCause,
+ spvcLastReleaseDiagnostic,
+ spvcRetryInterval = 1000,
+ spvcRetryTimer = 0,
+ spvcRetryThreshold = 1,
+ spvcRetryFailures = 0,
+ spvcRetryLimit = 15,
+ spvcFrKey,
+ spvcVccTranslationMode = 2,
+ spvcRerCap = false,
+ spvcRerStatus = false}).
+-record(spvcTargetVc, {entry,
+ userName = [],
+ providerName = [],
+ opState,
+ rowStatus}).
+
+-record(spvcTargetVp, {entry,
+ userName = [],
+ providerName = [],
+ opState,
+ rowStatus}).
+
+-record(spvcFr, {spvcFrEntry,
+ spvcFrAtmEntry,
+ spvcFrTargetAddress,
+ spvcFrTargetSelectType,
+ spvcFrProviderName,
+ currentState}).
+
+-record(spvcFrPerm, {spvcFrEntry,
+ spvcFrAtmEntry,
+ spvcFrAtmTranslation,
+ spvcFrAdminStatus,
+ spvcFrConnect}).
+
+-record(hci_clpn, {hci_pci,
+ hci_type_of_number,
+ hci_numbering_plan_indicator,
+ hci_presentation_indicator,
+ hci_screening_indicator,
+ hci_number_digits,
+ hci_incomplete_indicator = 0,
+ hci_binary}).
+
+encode_cc_clpn(Spvc) when Spvc#spvcObj.spvcFrKey == undefined ->
+ If = case Spvc of
+ Spvc when record(Spvc,spvcObj) ->
+ case Spvc#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Spvc when record(Spvc,spvcVcc) ->
+ {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpc) ->
+ {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpcPerm) ->
+ {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVccPerm) ->
+ {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVc) ->
+ {If_Value,_,_} = Spvc#spvcTargetVc.entry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVp) ->
+ {If_Value,_} = Spvc#spvcTargetVp.entry,
+ If_Value;
+ Spvc when record(Spvc,pchVc) ->
+ {If_Value,_,_} = Spvc#pchVc.vclEntry,
+ If_Value;
+ Spvc when record(Spvc,pchVp) ->
+ {If_Value,_} = Spvc#pchVp.vplEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFr) ->
+ {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFrPerm) ->
+ {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end,
+ Col = [2],
+ SpvcAddress = case x:x(get_next,[If],Col) of
+ [{[2,If,20|Address],_}] ->
+ Address;
+ _ ->
+ lists:duplicate(20,0)
+ end,
+ #hci_clpn{hci_type_of_number = 0,
+ hci_numbering_plan_indicator = 2,
+ hci_presentation_indicator = 0,
+ hci_screening_indicator = 1,
+ hci_number_digits = SpvcAddress};
+encode_cc_clpn(Spvc) ->
+ {If,_} = Spvc#spvcObj.spvcFrKey,
+ Col = [4],
+ SpvcFrAddress = case x:x(get_next,[If],Col) of
+ [{[4,If,20|Address],_}] ->
+ Address;
+ _ ->
+ lists:duplicate(20,0)
+ end,
+ #hci_clpn{hci_type_of_number = 0,
+ hci_numbering_plan_indicator = 2,
+ hci_presentation_indicator = 0,
+ hci_screening_indicator = 1,
+ hci_number_digits = SpvcFrAddress}.
+
+
+
+get_oper_status(spvcVpc,Obj) when record(Obj,spvcVpc) ->
+ State = Obj#spvcVpc.currentState,
+ LinkState = get_link_opstate(case Obj of
+ Obj when record(Obj,spvcObj) ->
+ case Obj#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Obj when record(Obj,spvcVcc) ->
+ {If_Value,_,_,_} =
+Obj#spvcVcc.spvcVccEntry,
+ If_Value;
+ Obj when record(Obj,spvcVpc) ->
+ {If_Value,_,_} = Obj#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Obj when record(Obj,spvcVpcPerm) ->
+ {If_Value,_,_} =
+Obj#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Obj when record(Obj,spvcVccPerm) ->
+ {If_Value,_,_,_} =
+Obj#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Obj when record(Obj,spvcTargetVc) ->
+ {If_Value,_,_} = Obj#spvcTargetVc.entry,
+ If_Value;
+ Obj when record(Obj,spvcTargetVp) ->
+ {If_Value,_} = Obj#spvcTargetVp.entry,
+ If_Value;
+ Obj when record(Obj,pchVc) ->
+ {If_Value,_,_} = Obj#pchVc.vclEntry,
+ If_Value;
+ Obj when record(Obj,pchVp) ->
+ {If_Value,_} = Obj#pchVp.vplEntry,
+ If_Value;
+ Obj when record(Obj,spvcFr) ->
+ {If_Value,_} = Obj#spvcFr.spvcFrEntry,
+ If_Value;
+ Obj when record(Obj,spvcFrPerm) ->
+ {If_Value,_} = Obj#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end),
+ debug_disabled,
+ case {State,LinkState} of
+ {not_in_service,_} ->
+ 10;
+ {created,_} ->
+ 10;
+ {_,disabled} ->
+ 6;
+ {wait,_} ->
+ 2;
+ {outgoing_callproceeding,_} ->
+ 2;
+ {release_at_restart,_} ->
+ 2;
+ {active,_} ->
+ 3;
+ {rest_in_peace,_} ->
+ 4;
+ {_Other,_} ->
+ 1
+ end;
+get_oper_status(spvcVpc,_) ->
+ debug_disabled,
+ 1;
+get_oper_status(spvcVcc,Obj) when record(Obj,spvcVcc) ->
+ State = Obj#spvcVcc.currentState,
+ LinkState = get_link_opstate(case Obj of
+ Obj when record(Obj,spvcObj) ->
+ case Obj#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Obj when record(Obj,spvcVcc) ->
+ {If_Value,_,_,_} =
+Obj#spvcVcc.spvcVccEntry,
+ If_Value;
+ Obj when record(Obj,spvcVpc) ->
+ {If_Value,_,_} = Obj#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Obj when record(Obj,spvcVpcPerm) ->
+ {If_Value,_,_} =
+Obj#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Obj when record(Obj,spvcVccPerm) ->
+ {If_Value,_,_,_} =
+Obj#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Obj when record(Obj,spvcTargetVc) ->
+ {If_Value,_,_} = Obj#spvcTargetVc.entry,
+ If_Value;
+ Obj when record(Obj,spvcTargetVp) ->
+ {If_Value,_} = Obj#spvcTargetVp.entry,
+ If_Value;
+ Obj when record(Obj,pchVc) ->
+ {If_Value,_,_} = Obj#pchVc.vclEntry,
+ If_Value;
+ Obj when record(Obj,pchVp) ->
+ {If_Value,_} = Obj#pchVp.vplEntry,
+ If_Value;
+ Obj when record(Obj,spvcFr) ->
+ {If_Value,_} = Obj#spvcFr.spvcFrEntry,
+ If_Value;
+ Obj when record(Obj,spvcFrPerm) ->
+ {If_Value,_} = Obj#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end),
+ debug_disabled,
+ case {State,LinkState} of
+ {not_in_service,_} ->
+ 10;
+ {created,_} ->
+ 10;
+ {_,disabled} ->
+ 6;
+ {wait,_} ->
+ 2;
+ {outgoing_callproceeding,_} ->
+ 2;
+ {release_at_restart,_} ->
+ 2;
+ {active,_} ->
+ 3;
+ {rest_in_peace,_} ->
+ 4;
+ {_Other,_} ->
+ 1
+ end;
+get_oper_status(spvcVcc,_) ->
+ debug_disabled,
+ 1;
+get_oper_status(spvcTargetVp,Obj) when record(Obj,spvcTargetVp) ->
+ debug_disabled,
+ Key = Obj#spvcTargetVp.entry,
+ case get_link_opstate(case Key of
+ Key when record(Key,spvcObj) ->
+ case Key#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Key when record(Key,spvcVcc) ->
+ {If_Value,_,_,_} = Key#spvcVcc.spvcVccEntry,
+ If_Value;
+ Key when record(Key,spvcVpc) ->
+ {If_Value,_,_} = Key#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Key when record(Key,spvcVpcPerm) ->
+ {If_Value,_,_} = Key#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Key when record(Key,spvcVccPerm) ->
+ {If_Value,_,_,_} = Key#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Key when record(Key,spvcTargetVc) ->
+ {If_Value,_,_} = Key#spvcTargetVc.entry,
+ If_Value;
+ Key when record(Key,spvcTargetVp) ->
+ {If_Value,_} = Key#spvcTargetVp.entry,
+ If_Value;
+ Key when record(Key,pchVc) ->
+ {If_Value,_,_} = Key#pchVc.vclEntry,
+ If_Value;
+ Key when record(Key,pchVp) ->
+ {If_Value,_} = Key#pchVp.vplEntry,
+ If_Value;
+ Key when record(Key,spvcFr) ->
+ {If_Value,_} = Key#spvcFr.spvcFrEntry,
+ If_Value;
+ Key when record(Key,spvcFrPerm) ->
+ {If_Value,_} = Key#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end) of
+ disabled ->
+ debug_disabled,
+ 4;
+ enabled ->
+ debug_disabled,
+ case (x:x({pchVp,Key}))#pchVp.vplConnId of
+ undefined ->
+ debug_disabled,
+ 3;
+ _ ->
+ debug_disabled,
+ 2
+ end
+ end;
+get_oper_status(spvcTargetVp,_) ->
+ debug_disabled,
+ 1;
+get_oper_status(spvcTargetVc,Obj) when record(Obj,spvcTargetVc) ->
+ debug_disabled,
+ Key = Obj#spvcTargetVc.entry,
+ case get_link_opstate(case Key of
+ Key when record(Key,spvcObj) ->
+ case Key#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Key when record(Key,spvcVcc) ->
+ {If_Value,_,_,_} = Key#spvcVcc.spvcVccEntry,
+ If_Value;
+ Key when record(Key,spvcVpc) ->
+ {If_Value,_,_} = Key#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Key when record(Key,spvcVpcPerm) ->
+ {If_Value,_,_} = Key#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Key when record(Key,spvcVccPerm) ->
+ {If_Value,_,_,_} = Key#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Key when record(Key,spvcTargetVc) ->
+ {If_Value,_,_} = Key#spvcTargetVc.entry,
+ If_Value;
+ Key when record(Key,spvcTargetVp) ->
+ {If_Value,_} = Key#spvcTargetVp.entry,
+ If_Value;
+ Key when record(Key,pchVc) ->
+ {If_Value,_,_} = Key#pchVc.vclEntry,
+ If_Value;
+ Key when record(Key,pchVp) ->
+ {If_Value,_} = Key#pchVp.vplEntry,
+ If_Value;
+ Key when record(Key,spvcFr) ->
+ {If_Value,_} = Key#spvcFr.spvcFrEntry,
+ If_Value;
+ Key when record(Key,spvcFrPerm) ->
+ {If_Value,_} = Key#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end) of
+ disabled ->
+ debug_disabled,
+ 4;
+ enabled ->
+ debug_disabled,
+ case (x:x({pchVc,Key}))#pchVc.vclConnId of
+ undefined ->
+ debug_disabled,
+ 3;
+ _ ->
+ debug_disabled,
+ 2
+ end
+ end;
+get_oper_status(spvcTargetVc,_) ->
+ debug_disabled,
+ 1.
+
+get_link_opstate(If) ->
+ debug_disabled,
+ case x:x(x:x(If),cnhChi,get_link_opstate,[If]) of
+ {genError,_} ->
+ debug_disabled,
+ disabled;
+ Return ->
+ debug_disabled,
+ Return
+ end.
+
+-record(record_A,{
+ field_1,
+ field_2,
+ field_3,
+ field_4,
+ field_5
+ }).
+-record(record_B, { field_1 }).
+-record(record_C, { }).
+
+foo() ->
+ case something of
+ [#record_A{} = A] ->
+ B = foo3(#record_C{}),
+ C = element(B, A),
+ foo2(A),
+ D = C#record_B.field_1,
+ foo4(A#record_A.field_4,
+ B,
+ #record_C{},
+ D)
+ end.
+
+foo2(_) -> ok.
+foo3(_) -> 1.
+foo4(_,_,_,_) -> ok.
+
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5553.erl b/lib/compiler/test/compilation_SUITE_data/otp_5553.erl
new file mode 100644
index 0000000000..9a7004a980
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5553.erl
@@ -0,0 +1,82 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5553).
+
+-export([?MODULE/0,test/0,handle_cast/2]).
+
+?MODULE() ->
+ ok.
+
+split_quoted_string([34 | _Rest]) -> %% 34 is '"'
+ ok.
+
+test() ->
+ %% does not start with quote
+ io:format("test: split_quoted_string/1 - 5~n"),
+ try split_quoted_string("foo \"bar\"") of
+ SQS_Res5 -> throw({error, test_case_failed, SQS_Res5})
+ catch
+ error: does_not_start_with_quote -> ok
+ end,
+
+ %% no ending quote
+ io:format("test: split_quoted_string/1 - 6~n"),
+ try split_quoted_string("\"foo ") of
+ SQS_Res6 -> throw({error, test_case_failed, SQS_Res6})
+ catch
+ error: no_end_quote -> ok
+ end,
+
+ ok.
+
+test2() ->
+ try split_quoted_string("") of
+ SQS_Res5 -> throw({error, test_case_failed, SQS_Res5})
+ catch
+ error: does_not_start_with_quote -> ok
+ after
+ ok
+ end,
+ try split_quoted_string("") of
+ SQS_Res6 -> throw({error, test_case_failed, SQS_Res6})
+ catch
+ error: no_end_quote -> ok
+ after
+ ok
+ end,
+ ok.
+
+-record(state, {connect_all, known = [], synced = [],
+ lockers = [], syncers = [], node_name = node(),
+ the_locker, the_deleter}).
+
+handle_cast({in_sync, Node, IsKnown}, S) ->
+ NewS = cancel_locker(Node, S, get({sync_tag_my, Node})),
+ NKnown = case lists:member(Node, Known = NewS#state.known) of
+ false when IsKnown == true ->
+1/0,
+ gen_server:cast({global_name_server, Node},
+ {in_sync, node(), false}),
+ [Node | Known];
+ _ ->
+ Known
+ end.
+
+cancel_locker(Node, S, Tag) ->
+ ok.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5632.erl b/lib/compiler/test/compilation_SUITE_data/otp_5632.erl
new file mode 100644
index 0000000000..ebf8e47ca2
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5632.erl
@@ -0,0 +1,230 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5632).
+-export([?MODULE/0]).
+-export([pstnproxy_add_headers/2,macosx_workaround/0,fast_cut/3,test/1,test2/1,
+ create_int_jumper_cables/1]).
+
+-import(lists, [foldl/3,last/1,member/2,reverse/1,reverse/2,seq/2,sort/1]).
+
+?MODULE() ->
+ ok.
+
+-record(request, {
+ header
+ }).
+
+
+-record(siporigin, {
+ proto
+ }).
+
+
+%% Test a problem in beam_jump.erl.
+pstnproxy_add_headers(Request, Origin) when is_record(Request, request),
+ is_record(Origin, siporigin) ->
+ NewHeaders1 = Request#request.header,
+ NewHeaders2 =
+ case (Origin#siporigin.proto == tls) or (Origin#siporigin.proto == tls6) of
+ true ->
+ keylist:delete("X-Foo2", NewHeaders1);
+ false ->
+ keylist:delete("X-Foo2", NewHeaders1)
+ end,
+ NewHeaders3 =
+ case (Origin#siporigin.proto == tls) or (Origin#siporigin.proto == tls6) of
+ true ->
+ keylist:delete("X-Foo3", NewHeaders2);
+ false ->
+ keylist:delete("X-Foo3", NewHeaders2)
+ end,
+ Request#request{header = NewHeaders3}.
+
+%% Test a problem in beam_validator.erl.
+macosx_workaround() ->
+ try 1.0/zero()
+ catch
+ error:_ -> ok
+ end.
+
+zero() -> 0.0.
+
+-record(we, {id,
+ perm = 0,
+ name,
+ es,
+ fs,
+ he,
+ vc,
+ vp,
+ mat = default,
+ next_id,
+ mode,
+ mirror = none,
+ light = none,
+ has_shape = true}).
+
+-record(edge, {vs,
+ ve,
+ a = none,
+ b = none,
+ lf,
+ rf,
+ ltpr,
+ ltsu,
+ rtpr,
+ rtsu}).
+
+
+fast_cut(Edge,Pos0,We0) ->
+ {NewEdge = NewV,We} = wings_we:new_ids(1,We0),
+ #we{es = Etab0,
+ vc = Vct0,
+ vp = Vtab0,
+ he = Htab0} = We,
+ Template = gb_trees:get(Edge,Etab0),
+ #edge{vs = Vstart,
+ ve = Vend,
+ a = ACol,
+ b = BCol,
+ lf = Lf,
+ rf = Rf,
+ ltpr = EdgeA,
+ rtsu = EdgeB,
+ rtpr = NextBCol} = Template,
+ VendPos = gb_trees:get(Vend,Vtab0),
+ Vct1 = gb_trees:update(Vend,NewEdge,Vct0),
+ VstartPos = wings_vertex:pos(Vstart,Vtab0),
+ if
+ Pos0 =:= default ->
+ NewVPos0 = e3d_vec:average([VstartPos,VendPos]);
+ true ->
+ NewVPos0 = Pos0
+ end,
+ NewVPos = wings_util:share(NewVPos0),
+ Vct = gb_trees:insert(NewV,NewEdge,Vct1),
+ Vtab = gb_trees:insert(NewV,NewVPos,Vtab0),
+ AColOther = ?MODULE:get_vtx_color(EdgeA,Lf,Etab0),
+ BColOther = ?MODULE:get_vtx_color(NextBCol,Rf,Etab0),
+ Weight = if
+ Pos0 == default ->
+ 0.500000;
+ true ->
+ ADist = e3d_vec:dist(Pos0,VstartPos),
+ BDist = e3d_vec:dist(Pos0,VendPos),
+ try
+ ADist / (ADist + BDist)
+ catch
+ error:badarith ->
+ 0.500000
+ end
+ end,
+ NewColA = wings_color:mix(Weight,AColOther,ACol),
+ NewColB = wings_color:mix(Weight,BCol,BColOther),
+ NewEdgeRec = Template#edge{vs = NewV,
+ a = NewColA,
+ ltsu = Edge,
+ rtpr = Edge},
+ Etab1 = gb_trees:insert(NewEdge,NewEdgeRec,Etab0),
+ Etab2 = ?MODULE:patch_edge(EdgeA,NewEdge,Edge,Etab1),
+ Etab3 = ?MODULE:patch_edge(EdgeB,NewEdge,Edge,Etab2),
+ EdgeRec = Template#edge{ve = NewV,
+ b = NewColB,
+ rtsu = NewEdge,
+ ltpr = NewEdge},
+ Etab = gb_trees:update(Edge,EdgeRec,Etab3),
+ Htab = case gb_sets:is_member(Edge,Htab0) of
+ false ->
+ Htab0;
+ true ->
+ gb_sets:insert(NewEdge,Htab0)
+ end,
+ {We#we{es = Etab,
+ vc = Vct,
+ vp = Vtab,
+ he = Htab},NewV}.
+
+%% A problem in beam_bool.
+
+-record(a, {a,b,c}).
+
+test(As) ->
+ case As of
+ A when A#a.b == []; A#a.b == undefined ->
+ true;
+ _ ->
+ false
+ end.
+
+test2(As) ->
+ case As of
+ A when A#a.b == {a,b,c}; A#a.b == undefined ->
+ true;
+ _ ->
+ false
+ end.
+
+%% Record updating problems.
+
+-record(int_jumper_cable, {id,
+ connectionFieldRef,
+ aiuPlugInUnitRef,
+ connFieldConnector,
+ aiuConnector,
+ dlAttenuation = 1,
+ ulAttenuation = 1,
+ electricalDlDelay = 100,
+ electricalUlDelay = 100,
+ optionals = []}).
+
+create_int_jumper_cables(_Config) ->
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},637}),
+ ct:comment("Create IntJumperCable MO"),
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},639}),
+ Parent = "ManagedElement=1,Equipment=1",
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},641}),
+ I1 = #int_jumper_cable{id = 1,
+ connectionFieldRef = Parent ++ ",ConnectionField=1",
+ aiuPlugInUnitRef = Parent ++ ",Subrack=2,Slot=6,PlugInUnit=1",
+ connFieldConnector = "J1",
+ aiuConnector = 1},
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},650}),
+ I2 = I1#int_jumper_cable{id = 2,
+ connFieldConnector = "H1",
+ aiuConnector = 2},
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},657}),
+ I3 = I1#int_jumper_cable{id = 3,
+ aiuPlugInUnitRef = Parent ++ ",Subrack=2,Slot=9,PlugInUnit=1",
+ connFieldConnector = "J2"},
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},663}),
+ I4 = I3#int_jumper_cable{id = 4,
+ connFieldConnector = "H2",
+ aiuConnector = 2},
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},670}),
+ I5 = I1#int_jumper_cable{id = 5,
+ aiuPlugInUnitRef = Parent ++ ",Subrack=2,Slot=12,PlugInUnit=1",
+ connFieldConnector = "J3"},
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},677}),
+ I6 = I5#int_jumper_cable{id = 6,
+ connFieldConnector = "H3",
+ aiuConnector = 2},
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},684}),
+ [_MO1,_MO2,_MO3,_MO4,_MO5,_MO6] = mub_util:create(mp_mub,Parent,[I1,I2,I3,I4,I5,I6]),
+ ct_line:line({{ccl_setup_SUITE,create_int_jumper_cables},686}),
+ ok.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5714.erl b/lib/compiler/test/compilation_SUITE_data/otp_5714.erl
new file mode 100644
index 0000000000..5aefa0a803
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5714.erl
@@ -0,0 +1,46 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5714).
+-export([?MODULE/0,foo/1,mktree_text/1]).
+-binary(<<1,2,3>>).
+
+?MODULE() ->
+ [<<1,2,3>>] = proplists:get_value(binary, ?MODULE:module_info(attributes)),
+ ok.
+
+-record(foo_record, {key,blabla}).
+foo(A) ->
+ hd(tl(element(2,element(2,catch erlang:error(apa))))),
+ case A of
+ A ->
+ B = #foo_record{ key = key1},
+ C = B#foo_record{ key = key2},
+ {X,Y} = {a,b}
+ end.
+
+mktree_text(Val) ->
+ case erlang:is_integer(Val) of
+ _A = IsInteger ->
+ _A;
+ _A ->
+ IsInteger = erlang:exit({{bug,mktree_text,4},{line,34},match,[_A]})
+ end,
+ ok;
+mktree_text(_A1) ->
+ erlang:exit({{bug,mktree_text,4},{line,33},function_clause,[_A1]}).
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_5872.erl b/lib/compiler/test/compilation_SUITE_data/otp_5872.erl
new file mode 100644
index 0000000000..cada7ad994
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_5872.erl
@@ -0,0 +1,46 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_5872).
+-export([?MODULE/0,chunk_request_body/3]).
+
+?MODULE() ->
+ ok.
+
+chunk_request_body(Body,_ChunkSize,Acc) when Body == <<>>; Body == [] ->
+ LastChunk = "0\r\n",
+ lists:reverse(["\r\n",LastChunk|Acc]);
+chunk_request_body(Body,ChunkSize,Acc) when binary(Body), size(Body) >= ChunkSize ->
+ <<ChunkBody:ChunkSize/binary,
+ Rest/binary>> = Body,
+ Chunk = [ibrowse_lib:dec2hex(4,ChunkSize),"\r\n",ChunkBody,"\r\n"],
+ chunk_request_body(Rest,ChunkSize,[Chunk|Acc]);
+chunk_request_body(Body,_ChunkSize,Acc) when binary(Body) ->
+ BodySize = size(Body),
+ Chunk = [ibrowse_lib:dec2hex(4,BodySize),"\r\n",Body,"\r\n"],
+ LastChunk = "0\r\n",
+ lists:reverse(["\r\n",LastChunk,Chunk|Acc]);
+chunk_request_body(Body,ChunkSize,Acc) when list(Body), length(Body) >= ChunkSize ->
+ {ChunkBody,Rest} = ?MODULE:split_list_at(Body,ChunkSize),
+ Chunk = [ibrowse_lib:dec2hex(4,ChunkSize),"\r\n",ChunkBody,"\r\n"],
+ chunk_request_body(Rest,ChunkSize,[Chunk|Acc]);
+chunk_request_body(Body,_ChunkSize,Acc) when list(Body) ->
+ BodySize = length(Body),
+ Chunk = [ibrowse_lib:dec2hex(4,BodySize),"\r\n",Body,"\r\n"],
+ LastChunk = "0\r\n",
+ lists:reverse(["\r\n",LastChunk,Chunk|Acc]).
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_6121.erl b/lib/compiler/test/compilation_SUITE_data/otp_6121.erl
new file mode 100644
index 0000000000..c71f7806a0
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_6121.erl
@@ -0,0 +1,48 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_6121).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ 42 = digit_map_timer(<<1>>, 42),
+ test(),
+ Beam = code:which(?MODULE),
+ Sz = filelib:file_size(Beam),
+ io:format("Size of Beam file: ~p\n", [Sz]),
+ if
+ 100 < Sz, Sz < 100000 ->
+ ok
+ end.
+
+test() ->
+ %% Make sure that the compiler does not make an unreasonable
+ %% expansion when trying to optimize the following expressions.
+ <<0:(8*128*1024)>> = id(<<0:(8*128*1024)>>),
+ <<100:(8*128*1024)>> = id(<<100:(8*128*1024)>>),
+ <<1009797879398749873879789879388:(8*128*1024)>> =
+ id(<<1009797879398749873879789879388:(8*128*1024)>>),
+ <<7:(8*128*1024)/little>> = id(<<7:(8*128*1024)/little>>),
+ ok.
+
+id(I) -> I.
+
+digit_map_timer(<<_:8>>, Int) when is_integer(Int) andalso Int >= 0 ->
+ Int;
+digit_map_timer(_, _) ->
+ error.
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_6121a.erl b/lib/compiler/test/compilation_SUITE_data/otp_6121a.erl
new file mode 100644
index 0000000000..caed631aa2
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_6121a.erl
@@ -0,0 +1,32 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_6121a).
+-export([?MODULE/0]).
+
+%% Thanks to Martin Bjorklund.
+
+?MODULE() ->
+ G = fun() -> ok end,
+ try
+ fun() -> ok end
+ after
+ fun({A, B}) -> A + B end
+ end,
+ ok.
+
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_6121b.erl b/lib/compiler/test/compilation_SUITE_data/otp_6121b.erl
new file mode 100644
index 0000000000..967f078942
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_6121b.erl
@@ -0,0 +1,33 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_6121b).
+-export([?MODULE/0]).
+
+%% Thanks to Tim Rath.
+
+?MODULE() ->
+ A = {6},
+ try
+ io:fwrite("")
+ after
+ fun () ->
+ fun () -> {B} = A end
+ end
+ end.
+
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_7202.erl b/lib/compiler/test/compilation_SUITE_data/otp_7202.erl
new file mode 100644
index 0000000000..9dca244aa5
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/otp_7202.erl
@@ -0,0 +1,48 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(otp_7202).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ test().
+
+test() ->
+ List = [a],
+ Error = case func() of
+ no_value -> true;
+ {ok, V} -> V
+ end,
+ %% Liveness calculation for the make_fun2 instruction was wrong -
+ %% it looked like Error would not be needed by the make_fun2 instruction.
+ lists:foreach(fun(_E) ->
+ case Error of
+ true ->
+ ok;
+ false ->
+ ok
+ end
+ end, List).
+
+func() ->
+ no_value.
+
+
+
+
+
diff --git a/lib/compiler/test/compilation_SUITE_data/pattern_expr.erl b/lib/compiler/test/compilation_SUITE_data/pattern_expr.erl
new file mode 100644
index 0000000000..02eacced81
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/pattern_expr.erl
@@ -0,0 +1,30 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(pattern_expr).
+
+-export(pattern_expr/0).
+
+pattern_expr() ->
+ f().
+
+f() ->
+ case 4 of
+ 2+2 ->
+ ok
+ end.
diff --git a/lib/compiler/test/compilation_SUITE_data/trycatch_4.erl b/lib/compiler/test/compilation_SUITE_data/trycatch_4.erl
new file mode 100644
index 0000000000..7ea710856f
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/trycatch_4.erl
@@ -0,0 +1,50 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(trycatch_4).
+-export([trycatch_4/0]).
+-record(state, {foo}).
+
+trycatch_4() ->
+ handle_info({foo}, #state{}),
+ ok.
+
+handle_info({_}, State) ->
+ foo(),
+ State#state{foo = bar},
+ case ok of
+ _ ->
+ case catch foo() of
+ ok ->
+ {stop, State}
+ end
+ end;
+handle_info(_, State) ->
+ (catch begin
+ foo(),
+ State#state{foo = bar}
+ end),
+ case ok of
+ _ ->
+ case catch foo() of
+ ok ->
+ {stop, State}
+ end
+ end.
+
+foo() -> ok.
diff --git a/lib/compiler/test/compilation_SUITE_data/vsn_1.erl b/lib/compiler/test/compilation_SUITE_data/vsn_1.erl
new file mode 100644
index 0000000000..a9e23f7c25
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/vsn_1.erl
@@ -0,0 +1,21 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(vsn_1).
+
+-hubbub(himmap).
diff --git a/lib/compiler/test/compilation_SUITE_data/vsn_2.erl b/lib/compiler/test/compilation_SUITE_data/vsn_2.erl
new file mode 100644
index 0000000000..4833458cf4
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/vsn_2.erl
@@ -0,0 +1,21 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(vsn_2).
+
+-vsn(34).
diff --git a/lib/compiler/test/compilation_SUITE_data/vsn_3.erl b/lib/compiler/test/compilation_SUITE_data/vsn_3.erl
new file mode 100644
index 0000000000..7b970b2b75
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/vsn_3.erl
@@ -0,0 +1,22 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(vsn_3).
+
+f(X) ->
+ 2*X.
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
new file mode 100644
index 0000000000..7c3990a855
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -0,0 +1,722 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(compile_SUITE).
+
+%% Tests compile:file/1 and compile:file/2 with various options.
+
+-include("test_server.hrl").
+
+-export([all/1,
+ app_test/1,
+ file_1/1, module_mismatch/1, big_file/1, outdir/1,
+ binary/1, cond_and_ifdef/1, listings/1, listings_big/1,
+ other_output/1, package_forms/1, encrypted_abstr/1,
+ bad_record_use/1, bad_record_use1/1, bad_record_use2/1, strict_record/1,
+ missing_testheap/1, cover/1, env/1, core/1, asm/1]).
+
+-export([init/3]).
+
+
+%% To cover the stripping of 'type' and 'spec' in beam_asm.
+-type all_return_type() :: [atom()].
+-spec all('suite' | [_]) -> all_return_type().
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [app_test,
+ file_1, module_mismatch, big_file, outdir, binary,
+ cond_and_ifdef, listings, listings_big,
+ other_output, package_forms,
+ encrypted_abstr,
+ bad_record_use, strict_record,
+ missing_testheap, cover, env, core, asm].
+
+
+%% Test that the Application file has no `basic' errors.";
+app_test(Config) when is_list(Config) ->
+ ?line ?t:app_test(compiler).
+
+%% Tests that we can compile and run a simple Erlang program,
+%% using compile:file/1.
+
+file_1(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(5)),
+ ?line {Simple, Target} = files(Config, "file_1"),
+ ?line {ok, Cwd} = file:get_cwd(),
+ ?line ok = file:set_cwd(filename:dirname(Target)),
+ ?line {ok,simple} = compile:file(Simple), %Smoke test only.
+ ?line {ok,simple} = compile:file(Simple, [slim]), %Smoke test only.
+ ?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test.
+ ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test.
+ ?line {ok,simple} = compile:file(Simple, [debug_info]),
+ ?line ok = file:set_cwd(Cwd),
+ ?line true = exists(Target),
+ ?line passed = run(Target, test, []),
+
+ %% Cleanup.
+ ?line ok = file:delete(Target),
+ ?line ok = file:del_dir(filename:dirname(Target)),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+module_mismatch(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line File = filename:join(DataDir, "wrong_module_name.erl"),
+ ?line {error,[{"wrong_module_name.beam",
+ [{compile,{module_name,arne,"wrong_module_name"}}]}],
+ []} = compile:file(File, [return]),
+ ?line error = compile:file(File, [report]),
+
+ ?line {ok,arne,[]} = compile:file(File,
+ [return,no_error_module_mismatch]),
+
+ ok.
+
+big_file(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(5)),
+ ?line DataDir = ?config(data_dir, Config),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Big = filename:join(DataDir, "big.erl"),
+ ?line Target = filename:join(PrivDir, "big.beam"),
+ ?line ok = file:set_cwd(PrivDir),
+ ?line {ok,big} = compile:file(Big, []),
+ ?line {ok,big} = compile:file(Big, [r9,debug_info]),
+ ?line {ok,big} = compile:file(Big, [no_postopt]),
+ ?line true = exists(Target),
+
+ %% Cleanup.
+ ?line ok = file:delete(Target),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+%% Tests that the {outdir, Dir} option works.
+
+outdir(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(60)),
+ ?line {Simple, Target} = files(Config, "outdir"),
+ ?line {ok, simple} = compile:file(Simple, [{outdir, filename:dirname(Target)}]),
+ ?line true = exists(Target),
+ ?line passed = run(Target, test, []),
+ ?line ok = file:delete(Target),
+ ?line ok = file:del_dir(filename:dirname(Target)),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+%% Tests that the binary option works.
+
+binary(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(60)),
+ ?line {Simple, Target} = files(Config, "binary"),
+ ?line {ok, simple, Binary} = compile:file(Simple, [binary]),
+ ?line code:load_binary(simple, Target, Binary),
+ ?line passed = simple:test(),
+ ?line true = code:delete(simple),
+ ?line false = code:purge(simple),
+ ?line ok = file:del_dir(filename:dirname(Target)),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+%% Tests that conditional compilation, defining values, including files work.
+
+cond_and_ifdef(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(60)),
+ ?line {Simple, Target} = files(Config, "cond_and_ifdef"),
+ ?line IncludeDir = filename:join(filename:dirname(Simple), "include"),
+ ?line Options = [{outdir, filename:dirname(Target)},
+ {d, need_foo}, {d, foo_value, 42},
+ {i, IncludeDir}, report],
+ ?line {ok, simple} = compile:file(Simple, Options),
+ ?line true = exists(Target),
+ ?line {hiker, 42} = run(Target, foo, []),
+ ?line ok = file:delete(Target),
+ ?line ok = file:del_dir(filename:dirname(Target)),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+listings(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(8)),
+ ?line DataDir = ?config(data_dir, Config),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Simple = filename:join(DataDir, simple),
+ ?line TargetDir = filename:join(PrivDir, listings),
+ ?line ok = file:make_dir(TargetDir),
+
+ %% Test all dedicated listing options.
+ ?line do_listing(Simple, TargetDir, 'S'),
+ ?line do_listing(Simple, TargetDir, 'E'),
+ ?line do_listing(Simple, TargetDir, 'P'),
+ ?line do_listing(Simple, TargetDir, dpp, ".pp"),
+ ?line do_listing(Simple, TargetDir, dabstr, ".abstr"),
+ ?line do_listing(Simple, TargetDir, dexp, ".expand"),
+ ?line do_listing(Simple, TargetDir, dcore, ".core"),
+ ?line do_listing(Simple, TargetDir, doldinline, ".oldinline"),
+ ?line do_listing(Simple, TargetDir, dinline, ".inline"),
+ ?line do_listing(Simple, TargetDir, dcore, ".core"),
+ ?line do_listing(Simple, TargetDir, dcopt, ".copt"),
+ ?line do_listing(Simple, TargetDir, dsetel, ".dsetel"),
+ ?line do_listing(Simple, TargetDir, dkern, ".kernel"),
+ ?line do_listing(Simple, TargetDir, dlife, ".life"),
+ ?line do_listing(Simple, TargetDir, dcg, ".codegen"),
+ ?line do_listing(Simple, TargetDir, dblk, ".block"),
+ ?line do_listing(Simple, TargetDir, dbool, ".bool"),
+ ?line do_listing(Simple, TargetDir, dtype, ".type"),
+ ?line do_listing(Simple, TargetDir, ddead, ".dead"),
+ ?line do_listing(Simple, TargetDir, djmp, ".jump"),
+ ?line do_listing(Simple, TargetDir, dclean, ".clean"),
+ ?line do_listing(Simple, TargetDir, dpeep, ".peep"),
+ ?line do_listing(Simple, TargetDir, dopt, ".optimize"),
+
+ %% First clean up.
+ ?line Listings = filename:join(PrivDir, listings),
+ ?line lists:foreach(fun(F) -> ok = file:delete(F) end,
+ filelib:wildcard(filename:join(Listings, "*"))),
+
+ %% Test options that produce a listing file if 'binary' is not given.
+ ?line do_listing(Simple, TargetDir, to_pp, ".P"),
+ ?line do_listing(Simple, TargetDir, to_exp, ".E"),
+ ?line do_listing(Simple, TargetDir, to_core0, ".core"),
+ ?line ok = file:delete(filename:join(Listings, "simple.core")),
+ ?line do_listing(Simple, TargetDir, to_core, ".core"),
+ ?line do_listing(Simple, TargetDir, to_kernel, ".kernel"),
+
+ %% Final clean up.
+ ?line lists:foreach(fun(F) -> ok = file:delete(F) end,
+ filelib:wildcard(filename:join(Listings, "*"))),
+ ?line ok = file:del_dir(Listings),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+listings_big(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(10)),
+ ?line DataDir = ?config(data_dir, Config),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Big = filename:join(DataDir, big),
+ ?line TargetDir = filename:join(PrivDir, listings_big),
+ ?line ok = file:make_dir(TargetDir),
+ ?line do_listing(Big, TargetDir, 'S'),
+ ?line do_listing(Big, TargetDir, 'E'),
+ ?line do_listing(Big, TargetDir, 'P'),
+ ?line do_listing(Big, TargetDir, dkern, ".kernel"),
+
+ ?line Target = filename:join(TargetDir, big),
+ ?line {ok,big} = compile:file(Target, [asm,{outdir,TargetDir}]),
+
+ %% Cleanup.
+ ?line ok = file:delete(Target ++ ".beam"),
+ ?line lists:foreach(fun(F) -> ok = file:delete(F) end,
+ filelib:wildcard(filename:join(TargetDir, "*"))),
+ ?line ok = file:del_dir(TargetDir),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+other_output(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(8)),
+ ?line DataDir = ?config(data_dir, Config),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Simple = filename:join(DataDir, simple),
+ ?line TargetDir = filename:join(PrivDir, other_output),
+ ?line ok = file:make_dir(TargetDir),
+
+ io:put_chars("to_pp"),
+ ?line {ok,[],PP} = compile:file(Simple, [to_pp,binary,time]),
+ ?line [] = [E || E <- PP,
+ begin
+ case element(1, E) of
+ attribute -> false;
+ function -> false;
+ eof -> false
+ end
+ end],
+
+ io:put_chars("to_exp (file)"),
+ ?line {ok,simple,Expand} = compile:file(Simple, [to_exp,binary,time]),
+ ?line case Expand of
+ {simple,Exports,Forms} when is_list(Exports), is_list(Forms) -> ok
+ end,
+ io:put_chars("to_exp (forms)"),
+ ?line {ok,simple,Expand} = compile:forms(PP, [to_exp,binary,time]),
+
+ io:put_chars("to_core (file)"),
+ ?line {ok,simple,Core} = compile:file(Simple, [to_core,binary,time]),
+ ?line c_module = element(1, Core),
+ ?line {ok,_} = core_lint:module(Core),
+ io:put_chars("to_core (forms)"),
+ ?line {ok,simple,Core} = compile:forms(PP, [to_core,binary,time]),
+
+ io:put_chars("to_kernel (file)"),
+ ?line {ok,simple,Kernel} = compile:file(Simple, [to_kernel,binary,time]),
+ ?line k_mdef = element(1, Kernel),
+ io:put_chars("to_kernel (forms)"),
+ ?line {ok,simple,Kernel} = compile:forms(PP, [to_kernel,binary,time]),
+
+ io:put_chars("to_asm (file)"),
+ ?line {ok,simple,Asm} = compile:file(Simple, [to_asm,binary,time]),
+ ?line {simple,_,_,_,_} = Asm,
+ io:put_chars("to_asm (forms)"),
+ ?line {ok,simple,Asm} = compile:forms(PP, [to_asm,binary,time]),
+
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+package_forms(Config) when is_list(Config) ->
+ Fs = [{attribute,1,file,{"./p.erl",1}},
+ {attribute,1,module,[p,p]},
+ {attribute,3,compile,export_all},
+ {attribute,1,file,
+ {"/clearcase/otp/erts/lib/stdlib/include/qlc.hrl",1}},
+ {attribute,6,file,{"./p.erl",6}},
+ {function,7,q,0,
+ [{clause,7,[],[],
+ [{call,8,
+ {remote,8,{atom,8,qlc},{atom,8,q}},
+ [{tuple,-8,
+ [{atom,-8,qlc_lc},
+ {'fun',-8,
+ {clauses,
+ [{clause,-8,[],[],
+ [{tuple,-8,
+ [{atom,-8,simple_v1},
+ {atom,-8,'X'},
+ {'fun',-8,{clauses,[{clause,-8,[],[],[{nil,8}]}]}},
+ {integer,-8,8}]}]}]}},
+ {atom,-8,undefined}]}]}]}]},
+ {eof,9}],
+ {ok,'p.p',_} = compile:forms(Fs, ['S',report]),
+ ok.
+
+encrypted_abstr(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(10)),
+ ?line {Simple,Target} = files(Config, "encrypted_abstr"),
+
+ Res = case has_crypto() of
+ no ->
+ %% No crypto.
+ ?line encrypted_abstr_no_crypto(Simple, Target),
+ {comment,"The crypto application is missing or broken"};
+ yes ->
+ %% Simulate not having crypto by removing
+ %% the crypto application from the path.
+ ?line OldPath = code:get_path(),
+ try
+ ?line NewPath = OldPath -- [filename:dirname(code:which(crypto))],
+ ?line (catch crypto:stop()),
+ ?line code:delete(crypto),
+ ?line code:purge(crypto),
+ ?line code:set_path(NewPath),
+ ?line encrypted_abstr_no_crypto(Simple, Target)
+ after
+ code:set_path(OldPath)
+ end,
+
+ %% Now run the tests that require crypto.
+ ?line encrypted_abstr_1(Simple, Target),
+ ?line ok = file:delete(Target),
+ ?line ok = file:del_dir(filename:dirname(Target))
+ end,
+
+ %% Cleanup.
+ ?line test_server:timetrap_cancel(Dog),
+ Res.
+
+encrypted_abstr_1(Simple, Target) ->
+ ?line TargetDir = filename:dirname(Target),
+ ?line Key = "ablurf123BX#$;3",
+ ?line install_crypto_key(Key),
+ ?line {ok,simple} = compile:file(Simple,
+ [debug_info,{debug_info_key,Key},
+ {outdir,TargetDir}]),
+ ?line verify_abstract(Target),
+
+ ?line {ok,simple} = compile:file(Simple,
+ [{debug_info_key,Key},
+ {outdir,TargetDir}]),
+ ?line verify_abstract(Target),
+
+ ?line {ok,simple} = compile:file(Simple,
+ [debug_info,{debug_info_key,{des3_cbc,Key}},
+ {outdir,TargetDir}]),
+ ?line verify_abstract(Target),
+
+ ?line {ok,{simple,[{compile_info,CInfo}]}} =
+ beam_lib:chunks(Target, [compile_info]),
+ ?line {value,{_,Opts}} = lists:keysearch(options, 1, CInfo),
+ ?line {value,{_,'********'}} = lists:keysearch(debug_info_key, 1, Opts),
+
+ %% Try some illegal forms of crypto keys.
+ ?line error = compile:file(Simple,
+ [debug_info,{debug_info_key,{blurf,"ss"}},report]),
+ ?line error = compile:file(Simple,
+ [debug_info,{debug_info_key,{blurf,1,"ss"}},report]),
+ ?line error = compile:file(Simple,
+ [debug_info,{debug_info_key,42},report]),
+
+ %% Place the crypto key in .erlang.crypt.
+ ?line beam_lib:clear_crypto_key_fun(),
+ ?line {ok,OldCwd} = file:get_cwd(),
+ ?line ok = file:set_cwd(TargetDir),
+
+ ?line error = compile:file(Simple, [encrypt_debug_info,report]),
+
+ ?line NewKey = "better use another key here",
+ ?line write_crypt_file(["[{debug_info,des3_cbc,simple,\"",NewKey,"\"}].\n"]),
+ ?line {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]),
+ ?line verify_abstract("simple.beam"),
+ ?line ok = file:delete(".erlang.crypt"),
+ ?line beam_lib:clear_crypto_key_fun(),
+ ?line {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} =
+ beam_lib:chunks("simple.beam", [abstract_code]),
+ ?line ok = file:set_cwd(OldCwd),
+ ok.
+
+
+write_crypt_file(Contents0) ->
+ Contents = list_to_binary([Contents0]),
+ io:format("~s\n", [binary_to_list(Contents)]),
+ ok = file:write_file(".erlang.crypt", Contents).
+
+encrypted_abstr_no_crypto(Simple, Target) ->
+ ?line TargetDir = filename:dirname(Target),
+ ?line Key = "ablurf123BX#$;3",
+ ?line error = compile:file(Simple,
+ [debug_info,{debug_info_key,Key},
+ {outdir,TargetDir},report]),
+ ok.
+
+verify_abstract(Target) ->
+ {ok,{simple,[Chunk]}} = beam_lib:chunks(Target, [abstract_code]),
+ {abstract_code,{raw_abstract_v1,_}} = Chunk.
+
+has_crypto() ->
+ try
+ crypto:start(),
+ crypto:info(),
+ crypto:stop(),
+ yes
+ catch
+ error:_ -> no
+ end.
+
+install_crypto_key(Key) ->
+ F = fun (init) -> ok;
+ ({debug_info,des3_cbc,_,_}) -> Key;
+ (clear) -> ok
+ end,
+ ok = beam_lib:crypto_key_fun(F).
+
+%% Miscellanous tests, mainly to get better coverage.
+cover(Config) when is_list(Config) ->
+ ?line io:format("~p\n", [compile:options()]),
+ ok.
+
+do_listing(Source, TargetDir, Type) ->
+ do_listing(Source, TargetDir, Type, "." ++ atom_to_list(Type)).
+
+do_listing(Source, TargetDir, Type, Ext) ->
+ io:format("Source: ~p TargetDir: ~p\n Type: ~p Ext: ~p\n",
+ [Source, TargetDir, Type, Ext]),
+ case compile:file(Source, [Type, time, {outdir, TargetDir}]) of
+ {ok, _} -> ok;
+ Other -> test_server:fail({unexpected_result, Other})
+ end,
+ SourceBase = filename:rootname(filename:basename(Source)),
+
+ Target = filename:join(TargetDir, SourceBase ++ Ext),
+ true = exists(Target).
+
+files(Config, Name) ->
+ ?line code:delete(simple),
+ ?line code:purge(simple),
+ ?line DataDir = ?config(data_dir, Config),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Simple = filename:join(DataDir, "simple"),
+ ?line TargetDir = filename:join(PrivDir, Name),
+ ?line ok = file:make_dir(TargetDir),
+ ?line Target = filename:join(TargetDir, "simple"++code:objfile_extension()),
+ {Simple, Target}.
+
+
+run(Target, Func, Args) ->
+ ?line Module = list_to_atom(filename:rootname(filename:basename(Target))),
+ ?line {module, Module} = code:load_abs(filename:rootname(Target)),
+ ?line Result = (catch apply(Module, Func, Args)),
+ ?line true = code:delete(Module),
+ ?line false = code:purge(Module),
+ Result.
+
+exists(Name) ->
+ case file:read_file_info(Name) of
+ {ok, _} -> true;
+ {error, _} -> false
+ end.
+
+bad_record_use(suite) -> [bad_record_use1, bad_record_use2].
+
+%% Tests that the compiler does not accept
+%% bad use of records.
+bad_record_use1(Config) when is_list(Config) ->
+ ?line {ok, Cwd} = file:get_cwd(),
+ ?line file:set_cwd(?config(data_dir, Config)),
+ ?line true=exists("bad_record_use.erl"),
+ ?line Ret=c:c(bad_record_use),
+ ?line file:set_cwd(Cwd),
+ ?line error=Ret,
+ ok.
+
+%% Tests that the compiler does not accept
+%% bad use of records.
+bad_record_use2(Config) when is_list(Config) ->
+ ?line {ok, Cwd} = file:get_cwd(),
+ ?line file:set_cwd(?config(data_dir, Config)),
+ ?line true=exists("bad_record_use2.erl"),
+ ?line Ret=c:c(bad_record_use),
+ ?line file:set_cwd(Cwd),
+ ?line error=Ret,
+ ok.
+
+strict_record(Config) when is_list(Config) ->
+ ?line Priv = ?config(priv_dir, Config),
+ ?line file:set_cwd(?config(data_dir, Config)),
+ ?line Opts = [{outdir,Priv},report_errors],
+ M = record_access,
+
+ ?line {ok,M} = c:c(M, [strict_record_tests|Opts]),
+ ?line Turtle = test_strict(),
+
+ ?line {ok,M} = c:c(M, [no_strict_record_tests|Opts]),
+ ?line Turtle = test_sloppy(),
+
+ %% The option first given wins.
+ ?line {ok,M} = c:c(M, [no_strict_record_tests,strict_record_tests|Opts]),
+ ?line Turtle = test_sloppy(),
+ ?line {ok,M} = c:c(M, [strict_record_tests,no_strict_record_tests|Opts]),
+ ?line Turtle = test_strict(),
+
+ %% Default (possibly influenced by ERL_COMPILER_OPTIONS).
+ ?line {ok,M} = c:c(M, [{outdir,Priv},report_errors]),
+ ?line try
+ {1,2} = record_access:test(Turtle),
+ {comment,"Default: no_strict_record_tests"}
+ catch
+ error:{badrecord,tortoise} ->
+ {comment,"Default: strict_record_tests"}
+ end.
+
+test_strict() ->
+ Turtle = record_access:turtle(),
+ ?line try
+ record_access:test(Turtle)
+ catch
+ error:{badrecord,tortoise} ->
+ ok
+ end,
+ Turtle.
+
+test_sloppy() ->
+ Turtle = record_access:turtle(),
+ {1,2} = record_access:test(Turtle),
+ Turtle.
+
+missing_testheap(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ Opts = [{outdir,PrivDir}],
+ OldPath = code:get_path(),
+ try
+ code:add_patha(PrivDir),
+ c:c(filename:join(DataDir, "missing_testheap1"), Opts),
+ c:c(filename:join(DataDir, "missing_testheap2"), Opts),
+ ?line ok = test(fun() ->
+ missing_testheap1:f({a,self()},{state,true,b})
+ end, {a,b}),
+ ?line ok = test(fun() ->
+ missing_testheap2:f({a,self()},16#80000000) end,
+ bigger)
+ after
+ code:set_path(OldPath),
+ file:delete(filename:join(PrivDir, "missing_testheap1.beam")),
+ file:delete(filename:join(PrivDir, "missing_testheap2.beam"))
+ end,
+ ok.
+
+test(Fun, Result) ->
+ test(500, Fun, Result, []).
+
+test(0, _, _, _) ->
+ ok;
+test(Iter, Fun, Result, Filler) ->
+ spawn(?MODULE, init, [self(), Fun, list_to_tuple(Filler)]),
+ receive
+ {result, Result} ->
+ test(Iter-1, Fun, Result, [0|Filler]);
+ {result, Other} ->
+ io:format("Expected ~p; got ~p~n", [Result, Other]),
+ test_server:fail()
+ end.
+
+init(ReplyTo, Fun, _Filler) ->
+ ReplyTo ! {result, Fun()}.
+
+env(Config) when is_list(Config) ->
+ ?line {Simple,Target} = files(Config, "file_1"),
+ ?line {ok,Cwd} = file:get_cwd(),
+ ?line ok = file:set_cwd(filename:dirname(Target)),
+
+ true = os:putenv("ERL_COMPILER_OPTIONS", "binary"),
+ try
+ env_1(Simple, Target)
+ after
+ true = os:putenv("ERL_COMPILER_OPTIONS", "ignore_me"),
+ file:set_cwd(Cwd),
+ file:delete(Target),
+ file:del_dir(filename:dirname(Target))
+ end,
+ ok.
+
+env_1(Simple, Target) ->
+ %% file
+ ?line {ok,simple,<<_/binary>>} = compile:file(Simple),
+ ?line {ok,simple} = compile:noenv_file(Simple, [debug_info]),
+ ?line true = exists(Target),
+ ?line {ok,{simple,[{abstract_code,Abstr0}]}} =
+ beam_lib:chunks(Target, [abstract_code]),
+ ?line {raw_abstract_v1,Forms} = Abstr0,
+
+ %% forms
+ ?line true = os:putenv("ERL_COMPILER_OPTIONS", "strong_validation"),
+ ?line {ok,simple} = compile:forms(Forms),
+ ?line {ok,simple,<<"FOR1",_/binary>>} = compile:noenv_forms(Forms, []),
+
+ %% output_generated
+ ?line false = compile:output_generated([]),
+ ?line true = compile:noenv_output_generated([]),
+
+ ?line ok = file:delete(Target),
+
+ ok.
+
+%% Test pretty-printing in Core Erlang format and then try to
+%% compile the generated Core Erlang files.
+
+core(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(5)),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Outdir = filename:join(PrivDir, "core"),
+ ?line ok = file:make_dir(Outdir),
+
+ ?line Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"),
+ ?line TestBeams = filelib:wildcard(Wc),
+ ?line Abstr = [begin {ok,{Mod,[{abstract_code,
+ {raw_abstract_v1,Abstr}}]}} =
+ beam_lib:chunks(Beam, [abstract_code]),
+ {Mod,Abstr} end || Beam <- TestBeams],
+ ?line Res = p_run(fun(F) -> do_core(F, Outdir) end, Abstr),
+ ?line test_server:timetrap_cancel(Dog),
+ Res.
+
+
+do_core({M,A}, Outdir) ->
+ try
+ {ok,M,Core} = compile:forms(A, [to_core,report]),
+ CoreFile = filename:join(Outdir, atom_to_list(M)++".core"),
+ CorePP = core_pp:format(Core),
+ ok = file:write_file(CoreFile, CorePP),
+ case compile:file(CoreFile, [clint,from_core,binary]) of
+ {ok,M,_} ->
+ ok = file:delete(CoreFile);
+ Other ->
+ io:format("*** core_lint failure '~p' for ~s\n",
+ [Other,CoreFile]),
+ error
+ end
+ catch Class:Error ->
+ io:format("~p: ~p ~p\n~p\n",
+ [M,Class,Error,erlang:get_stacktrace()]),
+ error
+ end.
+
+%% Compile to Beam assembly language (.S) and the try to
+%% run .S throught the compiler again.
+
+asm(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(20)),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Outdir = filename:join(PrivDir, "asm"),
+ ?line ok = file:make_dir(Outdir),
+
+ ?line Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"),
+ ?line TestBeams = filelib:wildcard(Wc),
+ ?line Res = p_run(fun(F) -> do_asm(F, Outdir) end, TestBeams),
+ ?line test_server:timetrap_cancel(Dog),
+ Res.
+
+
+do_asm(Beam, Outdir) ->
+ {ok,{M,[{abstract_code,{raw_abstract_v1,A}}]}} =
+ beam_lib:chunks(Beam, [abstract_code]),
+ try
+ {ok,M,Asm} = compile:forms(A, ['S']),
+ AsmFile = filename:join(Outdir, atom_to_list(M)++".S"),
+ {ok,Fd} = file:open(AsmFile, [write]),
+ beam_listing:module(Fd, Asm),
+ ok = file:close(Fd),
+ case compile:file(AsmFile, [from_asm,no_postopt,binary,report]) of
+ {ok,M,_} ->
+ ok = file:delete(AsmFile);
+ Other ->
+ io:format("*** failure '~p' for ~s\n",
+ [Other,AsmFile]),
+ error
+ end
+ catch Class:Error ->
+ io:format("~p: ~p ~p\n~p\n",
+ [M,Class,Error,erlang:get_stacktrace()]),
+ error
+ end.
+
+%% p_run(fun() -> ok|error, List) -> ok
+%% Will fail the test case if there were any errors.
+
+p_run(Test, List) ->
+ N = erlang:system_info(schedulers) + 1,
+ p_run_loop(Test, List, N, [], 0, 0).
+
+p_run_loop(_, [], _, [], Errors, Ws) ->
+ case Errors of
+ 0 ->
+ case Ws of
+ 0 -> ok;
+ 1 -> {comment,"1 core_lint failure"};
+ N -> {comment,integer_to_list(N)++" core_lint failures"}
+ end;
+ N -> ?t:fail({N,errors})
+ end;
+p_run_loop(Test, [H|T], N, Refs, Errors, Ws) when length(Refs) < N ->
+ {_,Ref} = erlang:spawn_monitor(fun() -> exit(Test(H)) end),
+ p_run_loop(Test, T, N, [Ref|Refs], Errors, Ws);
+p_run_loop(Test, List, N, Refs0, Errors0, Ws0) ->
+ receive
+ {'DOWN',Ref,process,_,Res} ->
+ {Errors,Ws} = case Res of
+ ok -> {Errors0,Ws0};
+ error -> {Errors0+1,Ws0};
+ warning -> {Errors0,Ws0+1}
+ end,
+ Refs = Refs0 -- [Ref],
+ p_run_loop(Test, List, N, Refs, Errors, Ws)
+ end.
diff --git a/lib/compiler/test/compile_SUITE_data/bad_record_use.erl b/lib/compiler/test/compile_SUITE_data/bad_record_use.erl
new file mode 100644
index 0000000000..c2adbfa8de
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/bad_record_use.erl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bad_record_use).
+-export([test/0]).
+
+-record(bad_use, {a=undefined,
+ b=undefined,
+ c=undefined}).
+
+test() ->
+ NewRecord=#bad_use{a=1, b=2, a=2}.
+
diff --git a/lib/compiler/test/compile_SUITE_data/bad_record_use2.erl b/lib/compiler/test/compile_SUITE_data/bad_record_use2.erl
new file mode 100644
index 0000000000..1de44b2df4
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/bad_record_use2.erl
@@ -0,0 +1,29 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bad_record_use2).
+-export([test/0]).
+
+-record(bad_use, {a=undefined,
+ b=undefined,
+ c=undefined}).
+
+test() ->
+ R=#bad_use{a=1, b=2},
+ R2=R#bad_use{a=1, b=2, a=2},
+ ok.
diff --git a/lib/compiler/test/compile_SUITE_data/big.erl b/lib/compiler/test/compile_SUITE_data/big.erl
new file mode 100644
index 0000000000..4cd8e15f13
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/big.erl
@@ -0,0 +1,742 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(big).
+-compile([export_all]).
+
+compiler_1() -> ok.
+
+-define(log(Format,Args),mnesia_test_lib:log(Format,Args,?FILE,?LINE)).
+-define(warning(Format,Args),?log("<WARNING> " ++ Format,Args)).
+-define(error(Format,Args),
+ mnesia_test_lib:note_error(Format,Args,?FILE,?LINE),
+ ?log("<ERROR> " ++ Format,Args)).
+
+-define(match(ExpectedRes,Expr),
+ fun() ->
+ AcTuAlReS = (catch (Expr)),
+ case AcTuAlReS of
+ ExpectedRes ->
+ ?log("ok, result as expected: ~p~n",[AcTuAlReS]),
+ {success,AcTuAlReS};
+ _ ->
+ ?error("actual result was: ~p~n",[AcTuAlReS]),
+ {fail,AcTuAlReS}
+ end
+ end()).
+
+-define(match_inverse(NotExpectedRes,Expr),
+ fun() ->
+ AcTuAlReS = (catch (Expr)),
+ case AcTuAlReS of
+ NotExpectedRes ->
+ ?error("actual result was: ~p~n",[AcTuAlReS]),
+ {fail,AcTuAlReS};
+ _ ->
+ ?log("ok, result as expected: ~p~n",[AcTuAlReS]),
+ {success,AcTuAlReS}
+ end
+ end()).
+
+-define(match_receive(ExpectedMsg),
+ ?match(ExpectedMsg,mnesia_test_lib:pick_msg())).
+
+%% ExpectedMsgs must be completely bound
+-define(match_multi_receive(ExpectedMsgs),
+ fun() ->
+ TmPeXpCtEdMsGs = lists:sort(ExpectedMsgs),
+ ?match(TmPeXpCtEdMsGs,
+ lists:sort(lists:map(fun(_) ->
+ mnesia_test_lib:pick_msg()
+ end,
+ TmPeXpCtEdMsGs)))
+ end()).
+
+-define(setup(), mnesia_test_lib:setup(?FILE,?LINE)).
+
+-define(start_activities(Nodes),
+ fun() ->
+ AcTiViTyPiDs =
+ lists:map(fun(Node) ->
+ spawn_link(Node,
+ mnesia_test_lib,
+ activity_evaluator,
+ [self()])
+ end,
+ Nodes),
+ ?match_multi_receive(AcTiViTyPiDs)
+ end()).
+
+-define(start_transactions(Pids),
+ ?match_multi_receive(lists:map(fun(Pid) ->
+ Pid ! begin_trans,
+ {Pid,begin_trans}
+ end,
+ Pids))).
+
+-define(acquire_nodes(N,Nodes),
+ mnesia_test_lib:acquire_nodes(N,Nodes,?FILE,?LINE)).
+
+
+
+%%% Copyright (C) 1996, Ellemtel Telecommunications Systems Laboratories
+%%% Author: Hakan Mattsson [email protected]
+%%% Purpose: Evil usage of the API
+%%%
+%%% Invoke all functions in the API and try to cover all legal uses
+%%% cases as well the illegal dito. This is a complement to the
+%%% other more explicit test cases.
+%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%
+%%% show/0
+%%%
+%%% Prints out the complete test case structure
+%%%
+%%% show/1
+%%%
+%%% Prints out parts of the test case structure
+%%%
+%%% test/0
+%%%
+%%% Run the complete test suite.
+%%% Reads Nodes from nodes.profile and starts them if neccessary.
+%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
+%%%
+%%% test/1
+%%%
+%%% Run parts of the test suite.
+%%% Reads Nodes from nodes.profile and starts them if neccessary.
+%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
+%%%
+%%% test/2
+%%%
+%%% Run parts of the test suite on the given Nodes,
+%%% assuming that the nodes are up and running.
+%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
+%%%
+%%% test/3
+%%%
+%%% Run parts of the test suite on permutations of the given Nodes,
+%%% assuming that the nodes are up and running. Uses test/2.
+%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
+%%%
+%%% See the module mnesia_test_lib for further information.
+%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+show() -> mnesia_test_lib:show([{?MODULE,all}]).
+show(TestCases) -> mnesia_test_lib:show([{?MODULE,TestCases}]).
+test() -> mnesia_test_lib:test([{?MODULE,all}]).
+test(TestCases) -> mnesia_test_lib:test([{?MODULE,TestCases}]).
+test(TestCases,Nodes) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes).
+test(TestCases,Nodes,Config) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes,Config).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+old_all(suite) ->
+ [
+ system_info, table_info, error_description,
+ db_node_lifecycle, start_and_stop, transaction, checkpoint, backup,
+ table_lifecycle, replica_management, replica_location, index_lifecycle,
+ trans_access, dirty_access, table_sync, snmp_access, debug_support
+ ].
+
+trans_access(suite) ->
+ [ {mnesia_dirty_access_test,all} ].
+
+dirty_access(suite) ->
+ [ {mnesia_trans_access_test,all} ].
+
+%% Get meta info about Mnesia
+system_info(suite) -> [];
+system_info(Nodes) ->
+ ?match(yes,mnesia:system_info(is_running)),
+ ?match(Nodes,mnesia:system_info(db_nodes)),
+ ?match(Nodes,mnesia:system_info(running_db_nodes)),
+ ?match(true,mnesia:system_info(have_disc)),
+ ?match(A when atom(A),mnesia:system_info(debug)),
+ ?match(L when list(L),mnesia:system_info(directory)),
+ ?match(L when list(L),mnesia:system_info(log_version)),
+ ?match({_,_},mnesia:system_info(schema_version)),
+ ?match(L when list(L),mnesia:system_info(tables)),
+ ?match(L when list(L),mnesia:system_info(local_tables)),
+ ?match(L when list(L),mnesia:system_info(held_locks)),
+ ?match(L when list(L),mnesia:system_info(lock_queue)),
+ ?match(L when list(L),mnesia:system_info(transactions)),
+ ?match(I when integer(I),mnesia:system_info(transaction_failures)),
+ ?match(I when integer(I),mnesia:system_info(transaction_commits)),
+ ?match(I when integer(I),mnesia:system_info(transaction_restarts)),
+ ?match(L when list(L),mnesia:system_info(checkpoints)),
+ ?match(A when atom(A),mnesia:system_info(backup_module)),
+ ?match(true,mnesia:system_info(auto_repair)),
+ ?match({_,_},mnesia:system_info(dump_log_interval)),
+ ?match(A when atom(A),mnesia:system_info(dump_log_update_in_place)),
+ ?match(I when integer(I),mnesia:system_info(transaction_log_writes)),
+ ?match({'EXIT',{aborted,badarg}},mnesia:system_info(ali_baba)),
+ done.
+
+%% Get meta info about table
+table_info(suite) -> [];
+table_info(Nodes) ->
+ [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes),
+
+ Tab = table_info,
+ Type = bag,
+ ValPos = 3,
+ Attrs = [k,v],
+ Arity = length(Attrs) +1,
+ Schema = [{name,Tab},{type,Type},{attributes,Attrs},{index,[ValPos]},
+ {disc_only_copies,[Node1]},{ram_copies,[Node2]},{disc_copies,[Node3]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+
+ Size = 10,
+ Keys = lists:seq(1,Size),
+ Records = [{Tab,A,7} || A <- Keys],
+ lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records),
+ ?match(Mem when integer(Mem),mnesia:table_info(Tab,memory)),
+ ?match(Size,mnesia:table_info(Tab,size)),
+ ?match(Type,mnesia:table_info(Tab,type)),
+ ?match([Node3],mnesia:table_info(Tab,disc_copies)),
+ ?match([Node2],mnesia:table_info(Tab,ram_copies)),
+ ?match([Node1],mnesia:table_info(Tab,disc_only_copies)),
+ Read = [Node1,Node2,Node3],
+ ?match(true,lists:member(mnesia:table_info(Tab,where_to_read),Read)),
+ Write = lists:sort([Node1,Node2,Node3]),
+ ?match(Write,lists:sort(mnesia:table_info(Tab,where_to_write))),
+ WriteLock = lists:sort([Node2,Node3]),
+ ?match([ValPos],mnesia:table_info(Tab,index)),
+ ?match(Arity,mnesia:table_info(Tab,arity)),
+ ?match(Attrs,mnesia:table_info(Tab,attributes)),
+ ?match({Tab,'_','_'},mnesia:table_info(Tab,wild_pattern)),
+ ?match({atomic,Attrs}, mnesia:transaction(fun() ->
+ mnesia:table_info(Tab,attributes) end)),
+
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Add and drop db nodes
+
+db_node_lifecycle(suite) -> [];
+db_node_lifecycle(Nodes) ->
+ [Node1,Node2] = ?acquire_nodes(2,Nodes),
+ Tab = db_node_lifecycle,
+
+ Schema = [{name,Tab},{ram_copies,[Node1,Node2]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ ?match({aborted,active}, rpc:call(Node1,mnesia,del_db_node,[Node2])),
+
+ ?match([], mnesia_test_lib:stop_mnesia(Nodes)),
+ ?match(ok, mnesia:delete_schema(Nodes)),
+ ?match({error,_}, mnesia:create_schema(foo)),
+ ?match({error,_}, mnesia:create_schema([foo])),
+ ?match({error,_}, mnesia:create_schema([foo@bar])),
+ ?match({error,_}, mnesia:start()),
+
+ ?match(ok, mnesia:create_schema(Nodes)),
+ ?match([],mnesia_test_lib:start_mnesia(Nodes)),
+ ?match({atomic,ok}, rpc:call(Node1,mnesia,del_db_node,[Node2])),
+ ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[Node2])),
+ ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo])),
+ ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo@bar])),
+
+ ?match([], mnesia_test_lib:stop_mnesia([Node2])),
+ ?match(ok,mnesia:delete_schema([Node2])),
+ AddFun = fun() -> ?match({aborted,nested_transaction},
+ mnesia:add_db_node(Node2)), ok end,
+ ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[AddFun])),
+ DelFun = fun() -> ?match({aborted,nested_transaction},
+ mnesia:del_db_node(Node2)), ok end,
+ ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[DelFun])),
+
+ ?match({atomic,ok}, rpc:call(Node1,mnesia,add_db_node,[Node2])),
+ ?match({aborted,already_exists}, rpc:call(Node1,mnesia,add_db_node,[Node2])),
+ ?match([],mnesia_test_lib:start_mnesia([Node2])),
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Start and stop the system
+
+start_and_stop(suite) -> [];
+start_and_stop(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+
+ ?match(stopped, rpc:call(Node1,mnesia,stop,[])),
+ ?match(stopped, rpc:call(Node1,mnesia,stop,[])),
+ ?match({started,_}, rpc:call(Node1,mnesia,start,[])),
+ ?match({started,_}, rpc:call(Node1,mnesia,start,[])),
+ ?match(stopped, rpc:call(Node1,mnesia,stop,[])),
+ ?match([],mnesia_test_lib:start_mnesia(Nodes)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Checkpoints and backup management
+
+checkpoint(suite) -> [];
+checkpoint(Nodes) ->
+ OneNode = ?acquire_nodes(1,Nodes),
+ checkpoint(OneNode,Nodes),
+ TwoNodes = ?acquire_nodes(2,Nodes),
+ checkpoint(TwoNodes,Nodes).
+
+checkpoint(TabNodes,Nodes) ->
+ [Node1] = ?acquire_nodes(1,TabNodes),
+ CreateTab = fun(Type,N,Ns) ->
+ Tab0 = lists:concat(["local_checkpoint_",Type,N]),
+ Tab = list_to_atom(Tab0),
+ Schema = [{name,Tab},{Type,Ns}],
+ ?match({atomic,ok},mnesia:delete_table(Tab)),
+ ?match({atomic,ok},mnesia:create_table(Schema)),
+ Tab
+ end,
+ CreateTabs = fun(Type) ->
+ CreateTab(Type,1,hd(TabNodes)),
+ CreateTab(Type,2,TabNodes),
+ CreateTab(Type,3,lists:last(TabNodes))
+ end,
+ Types = [ram_copies,disc_copies,disc_only_copies],
+ Tabs = lists:append(lists:map(CreateTabs,Types)),
+ Recs = lists:sort([{T,N,N} || T <- Tabs,N <- lists:seq(1,10)]),
+ lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs),
+
+ CpName = a_checkpoint_name,
+ MinArgs = [{name,CpName},{min,Tabs},{allow_remote,false}],
+ ?match({ok,CpName,[Node1]},
+ rpc:call(Node1,mnesia,activate_checkpoint,[MinArgs])),
+ ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])),
+
+ MaxArgs = [{name,CpName},{max,Tabs},{allow_remote,true}],
+ ?match({ok,CpName,[Node1]},
+ rpc:call(Node1,mnesia,activate_checkpoint,[MaxArgs])),
+ ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])),
+
+ Args = [{name,CpName},{min,Tabs},{allow_remote,false}],
+ ?match({ok,CpName,[Node1]},
+ rpc:call(Node1,mnesia,activate_checkpoint,[Args])),
+ Recs2 = lists:sort([{T,K,0} || {T,K,_} <- Recs]),
+ lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs2),
+ ?match({atomic,ok},rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])),
+
+ ?match({error,no_exists},mnesia:deactivate_checkpoint(CpName)),
+ ?match({error,badarg},mnesia:activate_checkpoint(foo)),
+ ?match({error,badarg},mnesia:activate_checkpoint([{foo,foo}])),
+ ?match({error,badarg},mnesia:activate_checkpoint([{max,foo}])),
+ ?match({error,badarg},mnesia:activate_checkpoint([{min,foo}])),
+ ?match({error,no_exists},mnesia:activate_checkpoint([{min,[foo@bar]}])),
+ ?match({error,badarg},mnesia:activate_checkpoint([{allow_remote,foo}])),
+
+ Fun = fun(Tab) -> ?match({atomic,ok},mnesia:delete_table(Tab)) end,
+ lists:foreach(Fun,Tabs),
+ done.
+
+backup(suite) ->
+ [
+ backup_schema, restore_schema, backup_checkpoint, restore_tables
+ ].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Use and misuse transactions
+
+transaction(suite) -> [];
+transaction(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+ ?match({atomic,ali_baba}, mnesia:transaction(fun() -> ali_baba end)),
+ ?match({aborted,_}, mnesia:transaction(no_fun)),
+ ?match({aborted,_}, mnesia:transaction(?MODULE,no_fun,[foo])),
+
+ {success,[A,B,C,D,E,F,G,H]} = ?start_activities(lists:duplicate(8,Node1)),
+ ?start_transactions([A,B,C,D,E,F,G,H]),
+
+ A ! fun() -> mnesia:abort(abort_bad_trans) end,
+ ?match_receive({A,{aborted,abort_bad_trans}}),
+
+ B ! fun() -> 1 = 2 end,
+ ?match_receive({B,{aborted,_}}),
+
+ C ! fun() -> throw(throw_bad_trans) end,
+ ?match_receive({C,{aborted,{throw,throw_bad_trans}}}),
+
+ D ! fun() -> exit(exit_bad_trans) end,
+ ?match_receive({D,{aborted,exit_bad_trans}}),
+
+ E ! fun() -> exit(normal) end,
+ ?match_receive({E,{aborted,normal}}),
+
+ F ! fun() -> exit(abnormal) end,
+ ?match_receive({F,{aborted,abnormal}}),
+
+ G ! fun() -> exit(G,abnormal) end,
+ ?match_receive({'EXIT',G,abnormal}),
+
+ H ! fun() -> exit(H,kill) end,
+ ?match_receive({'EXIT',H,killed}),
+
+ ?match({atomic,ali_baba},
+ mnesia:transaction(fun() -> ali_baba end,infinity)),
+ ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,1)),
+ ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,0)),
+ ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,-1)),
+ ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,foo)),
+ Fun = fun() -> ?match({aborted,nested_transaction},
+ mnesia:transaction(fun() -> ok end)), ok end,
+ ?match({atomic,ok},mnesia:transaction(Fun)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Create and delete tables
+
+%% Get meta info about table
+
+replica_location(suite) -> [];
+replica_location(Nodes) ->
+ [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes),
+ Tab = replica_location,
+
+ %% Create three replicas
+ Schema = [{name,Tab},{disc_only_copies,[Node1]},
+ {ram_copies,[Node2]},{disc_copies,[Node3]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1],[Node2],[Node3],Nodes),
+
+ %% Delete one replica
+ ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node3],Nodes),
+
+ %% Move one replica
+ ?match({atomic,ok}, mnesia:move_table_copy(Tab, Node1, Node2)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node3],Nodes),
+
+ %% Change replica type
+ ?match({atomic,ok}, mnesia:change_table_copy_type(Tab, Node2,ram_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[],[Node2],[Node3],Nodes),
+
+ done.
+
+table_lifecycle(suite) -> [];
+table_lifecycle(Nodes) ->
+ [Node1,Node2] = ?acquire_nodes(2,Nodes),
+
+ ?match({atomic,ok}, mnesia:create_table([{type,bag},
+ {ram_copies,[Node1]},
+ {attributes,[rajtan,tajtan]},
+ {name,order_of_args}])),
+ ?match([],mnesia:dirty_read({order_of_args,4711})),
+ ?match({atomic,ok}, mnesia:create_table([{name,already_exists},
+ {ram_copies,[Node1]}])),
+ ?match({aborted,already_exists},
+ mnesia:create_table([{name,already_exists},{ram_copies,[Node1]}])),
+ ?match({aborted,not_a_db_node},
+ mnesia:create_table([{name,no_node},{ram_copies,[foo]}])),
+ ?match({aborted,not_a_db_node},
+ mnesia:create_table([{name,no_host},{ram_copies,[foo@bar]}])),
+ ?match({aborted,badarg},
+ mnesia:create_table([{name,zero_arity},{attributes,[]}])),
+ ?match({aborted,badarg}, mnesia:create_table([])),
+ ?match({aborted,badarg}, mnesia:create_table(atom)),
+ ?match({aborted,badarg},
+ mnesia:create_table({cstruct,table_name_as_atom})),
+ ?match({aborted,bad_type},
+ mnesia:create_table([{name,no_host},{ram_copies,foo}])),
+ ?match({aborted,bad_type},
+ mnesia:create_table([{name,no_host},{disc_only_copies,foo}])),
+ ?match({aborted,bad_type},
+ mnesia:create_table([{name,no_host},{disc_copies,foo}])),
+
+ CreateFun =
+ fun() -> ?match({aborted,nested_transaction},
+ mnesia:create_table([{name,nested_trans}])), ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(CreateFun)),
+ ?match({atomic,ok},mnesia:create_table([{name,remote_tab},
+ {ram_copies,[Node2]}])),
+
+ ?match({atomic,ok}, mnesia:create_table([{name,a_brand_new_tab},
+ {ram_copies,[Node1]}])),
+ ?match([],mnesia:dirty_read({a_brand_new_tab,4711})),
+ ?match({atomic,ok}, mnesia:delete_table(a_brand_new_tab)),
+ ?match({'EXIT',{aborted,no_exists}},
+ mnesia:dirty_read({a_brand_new_tab,4711})),
+ ?match({aborted,no_exists}, mnesia:delete_table(a_brand_new_tab)),
+ ?match({aborted,badarg}, mnesia:create_table([])),
+
+ ?match({atomic,ok}, mnesia:create_table([{name,nested_del_trans},
+ {ram_copies,[Node1]}])),
+ DeleteFun = fun() -> ?match({aborted,nested_transaction},
+ mnesia:delete_table(nested_del_trans)), ok end,
+ ?match({atomic,ok}, mnesia:transaction(DeleteFun)),
+
+ ?match({aborted,bad_type},
+ mnesia:create_table([{name,create_with_index},{index,2}])),
+ ?match({aborted,bad_index},
+ mnesia:create_table([{name,create_with_index},{index,[-1]}])),
+ ?match({aborted,bad_index},
+ mnesia:create_table([{name,create_with_index},{index,[0]}])),
+ ?match({aborted,bad_index},
+ mnesia:create_table([{name,create_with_index},{index,[1]}])),
+ ?match({aborted,bad_index},
+ mnesia:create_table([{name,create_with_index},{index,[2]}])),
+ ?match({atomic,ok},
+ mnesia:create_table([{name,create_with_index},{index,[3]},
+ {ram_copies,[Node1]}])),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Add, drop and move replicas, change storage types
+%% Change table layout (only arity change supported)
+
+replica_management(suite) -> [];
+replica_management(Nodes) ->
+ %% add_table_copy/3, del_table_copy/2, move_table_copy/3,
+ %% change_table_copy_type/3, transform_table/3
+
+ [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes),
+
+ Tab = replica_management,
+ Attrs = [k,v],
+
+ %%
+ %% Add, delete and change replicas
+ %%
+ ?match({atomic,ok},
+ mnesia:create_table([{name,Tab},{attributes,Attrs},
+ {ram_copies,[Node1]}])),
+ mnesia_test_lib:verify_replica_location(Tab,[],[Node1],[],Nodes),
+ %% R - -
+ ?match({aborted,combine_error},
+ mnesia:add_table_copy(Tab, Node2, disc_copies)),
+ ?match({aborted,combine_error},
+ mnesia:change_table_copy_type(Tab, Node1, disc_copies)),
+ ?match({atomic,ok}, mnesia:del_table_copy(Tab,Node1)),
+ mnesia_test_lib:verify_replica_location(Tab,[],[],[],Nodes),
+ %% - - -
+ ?match({aborted,no_exists},
+ mnesia:add_table_copy(Tab, Node3, ram_copies)),
+
+ ?match({atomic,ok}, mnesia:create_table([{name,Tab},
+ {attributes,Attrs},
+ {disc_copies,[Node1]}])),
+ mnesia_test_lib:verify_replica_location(Tab,[],[],[Node1],Nodes),
+ %% D - -
+ ?match({aborted,badarg},
+ mnesia:add_table_copy(Tab, Node2, bad_storage_type)),
+ ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node2, disc_only_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node1],Nodes),
+ %% D DO -
+ ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node3, ram_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes),
+ %% D DO R
+ ?match({atomic,ok},
+ mnesia:change_table_copy_type(Tab, Node1, disc_only_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1,Node2],[Node3],[],Nodes),
+ %% DO DO R
+ ?match({aborted,already_exists},
+ mnesia:add_table_copy(Tab, Node3, ram_copies)),
+ ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node1)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[],Nodes),
+ %% - DO R
+ ?match({aborted,_}, mnesia:del_table_copy(Tab, Node1)),
+ ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node1, disc_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes),
+ %% D DO R
+ ?match({atomic,ok},
+ mnesia:change_table_copy_type(Tab, Node3, disc_only_copies)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node2,Node3],[],[Node1],Nodes),
+ %% D DO DO
+ ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node1],Nodes),
+ %% D - DO
+ ?match({aborted,already_exists},
+ mnesia:change_table_copy_type(Tab, Node1, disc_copies)),
+
+ %%
+ %% Move replica
+ %%
+ ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node1,Node2)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2],Nodes),
+ %% - D DO
+ ?match({aborted,_}, mnesia:move_table_copy(Tab,Node1,Node2)),
+ ?match([], mnesia_test_lib:stop_mnesia([Node3])),
+ mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2],
+ Nodes -- [Node3]),
+ %% - D DO
+ ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node3,Node1)),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2],
+ Nodes -- [Node3]),
+ %% DO D -
+ ?match([],mnesia_test_lib:start_mnesia([Node3])),
+ mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2],Nodes),
+ %% DO D -
+
+ %%
+ %% Transformer
+ %%
+
+ NewAttrs = Attrs ++ [extra],
+ Transformer =
+ fun(Rec) -> list_to_tuple(tuple_to_list(Rec) ++ [initial_value]) end,
+ ?match({atomic,ok}, mnesia:transform_table(Tab, Transformer,NewAttrs)),
+ ?match({atomic,ok}, mnesia:transform_table(Tab, fun(R) -> R end, Attrs)),
+ ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, 0)),
+ ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, -1)),
+ ?match({aborted,badarg}, mnesia:transform_table(Tab, Transformer, [])),
+ ?match({aborted,bad_type}, mnesia:transform_table(Tab, no_fun, NewAttrs)),
+
+ NestedFun =
+ fun() ->
+ ?match({aborted,_},
+ mnesia:move_table_copy(Tab,Node1,Node2)),
+ ?match({aborted,_},
+ mnesia:add_table_copy(Tab,Node1,ram_copies)),
+ ?match({aborted,_},
+ mnesia:del_table_copy(Tab,Node1)),
+ T = fun(_) -> 4711 end,
+ ?match({aborted,_},
+ mnesia:transform_table(Tab,Transformer, T)),
+ ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(NestedFun)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Add and drop indecies
+
+index_lifecycle(suite) ->
+ [ add_table_index, create_live_table_index, del_table_index ].
+
+%% Add table index
+
+add_table_index(suite) -> [];
+add_table_index(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+ Tab = add_table_index,
+ Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ ValPos = 3,
+ BadValPos = ValPos + 1,
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,BadValPos)),
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,2)),
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,1)),
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,0)),
+ ?match({aborted,bad_index}, mnesia:add_table_index(Tab,-1)),
+ ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)),
+ ?match({aborted,already_exists}, mnesia:add_table_index(Tab,ValPos)),
+
+ NestedFun = fun() ->
+ ?match({aborted,nested_transaction},
+ mnesia:add_table_index(Tab,ValPos)),
+
+ ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(NestedFun)),
+ done.
+
+create_live_table_index(suite) -> [];
+create_live_table_index(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+ Tab = create_live_table_index,
+ Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ ValPos = 3,
+ mnesia:dirty_write({Tab,1,2}),
+
+ Fun = fun() ->
+ ?match(ok, mnesia:write({Tab,2,2})),
+ ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(Fun)),
+ ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)),
+ done.
+
+%% Drop table index
+
+del_table_index(suite) ->[];
+del_table_index(Nodes) ->
+ [Node1] = ?acquire_nodes(1,Nodes),
+ Tab = del_table_index,
+ Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+ ValPos = 3,
+ BadValPos = ValPos + 1,
+ ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)),
+ ?match({aborted,no_exists},
+ mnesia:del_table_index(Tab,BadValPos)),
+ ?match({atomic,ok}, mnesia:del_table_index(Tab,ValPos)),
+
+ NestedFun =
+ fun() ->
+ ?match({aborted,nested_transaction},
+ mnesia:del_table_index(Tab,ValPos)),
+ ok
+ end,
+ ?match({atomic,ok},mnesia:transaction(NestedFun)),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Syncronize table with log or disc
+%%
+table_sync(suite) ->
+ [ dump_tables, dump_log, change_dump_log_config, wait_for_tables, force_load_table ].
+
+%% Dump ram tables on disc
+dump_tables(suite) -> [];
+dump_tables(Nodes) ->
+ [Node1,Node2] = ?acquire_nodes(2,Nodes),
+ Tab = dump_tables,
+ Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node2]}],
+ ?match({atomic,ok}, mnesia:create_table(Schema)),
+
+ %% Dump 10 records
+ Size = 10,
+ Keys = lists:seq(1,Size),
+ Records = [{Tab,A,7} || A <- Keys],
+ lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records),
+ AllKeys = fun() -> lists:sort(mnesia:all_keys(Tab)) end,
+
+ ?match({atomic,Keys}, mnesia:transaction(AllKeys)),
+ ?match(ok, mnesia:dump_tables(Tab)),
+
+ %% Delete one record
+ ?match(ok,mnesia:dirty_delete({Tab,5})),
+ Keys2 = lists:delete(5,Keys),
+ ?match({atomic,Keys2}, mnesia:transaction(AllKeys)),
+
+ %% Check that all 10 is restored after a stop
+ ?match([], mnesia_test_lib:stop_mnesia([Node1,Node2])),
+ ?match([],mnesia_test_lib:start_mnesia([Node1,Node2])),
+ ?match(ok,mnesia:wait_for_tables([Tab],infinity)),
+ ?match({atomic,Keys}, mnesia:transaction(AllKeys)),
+
+ ?match(ok, mnesia:dump_tables([foo])),
+ done.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Make Mnesia table accessible via SNMP
+
+snmp_access(suite) ->
+ [
+ snmp_open_table, snmp_close_table,
+ snmp_get_row, snmp_get_next_index, snmp_get_mnesia_key
+ ].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Check that the debug support has not decayed
+
+debug_support(suite) ->
+ [ info, schema, schema, kill, lkill ].
+
diff --git a/lib/compiler/test/compile_SUITE_data/include/simple.hrl b/lib/compiler/test/compile_SUITE_data/include/simple.hrl
new file mode 100644
index 0000000000..cbe6e4f1a4
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/include/simple.hrl
@@ -0,0 +1,19 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-define(included_value, hiker).
diff --git a/lib/compiler/test/compile_SUITE_data/missing_testheap1.erl b/lib/compiler/test/compile_SUITE_data/missing_testheap1.erl
new file mode 100644
index 0000000000..65ee11541d
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/missing_testheap1.erl
@@ -0,0 +1,35 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(missing_testheap1).
+
+-compile(export_all).
+%%-export([Function/Arity, ...]).
+-record(state,{e1,e2}).
+
+f({a,DpId},State) when State ==
+#state{e1=true,
+ e2=a} ->
+ {a,a};
+
+f({a,DpId},State) when State ==
+#state{e1=true,
+ e2=b} ->
+ {a,b}.
+
+
diff --git a/lib/compiler/test/compile_SUITE_data/missing_testheap2.erl b/lib/compiler/test/compile_SUITE_data/missing_testheap2.erl
new file mode 100644
index 0000000000..014210fa5a
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/missing_testheap2.erl
@@ -0,0 +1,29 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(missing_testheap2).
+
+-compile(export_all).
+
+f({a,DpId},16#7fffffff) ->
+ big;
+
+f({a,DpId},16#80000000) ->
+ bigger.
+
+
diff --git a/lib/compiler/test/compile_SUITE_data/record_access.erl b/lib/compiler/test/compile_SUITE_data/record_access.erl
new file mode 100644
index 0000000000..c89f9ad7c7
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/record_access.erl
@@ -0,0 +1,29 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(record_access).
+-export([turtle/0,test/1]).
+
+-record(turtle, {a,b,c}).
+-record(tortoise, {a,b,c}).
+
+turtle() ->
+ #turtle{a=1,b=2,c=3}.
+
+test(T) ->
+ {T#tortoise.a,T#tortoise.b}.
diff --git a/lib/compiler/test/compile_SUITE_data/simple.erl b/lib/compiler/test/compile_SUITE_data/simple.erl
new file mode 100644
index 0000000000..2021056388
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/simple.erl
@@ -0,0 +1,39 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(simple).
+
+-export([test/0]).
+
+-ifdef(need_foo).
+-export([foo/0]).
+-endif.
+
+test() ->
+ passed.
+
+%% Conditional inclusion.
+%% Compile with [{d, need_foo}, {d, foo_value, 42}].
+
+-ifdef(need_foo).
+-include("simple.hrl").
+
+foo() ->
+ {?included_value, ?foo_value}.
+
+-endif.
diff --git a/lib/compiler/test/compile_SUITE_data/wrong_module_name.erl b/lib/compiler/test/compile_SUITE_data/wrong_module_name.erl
new file mode 100644
index 0000000000..ea437556a4
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/wrong_module_name.erl
@@ -0,0 +1,23 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(arne).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ ok.
diff --git a/lib/compiler/test/compiler.cover b/lib/compiler/test/compiler.cover
new file mode 100644
index 0000000000..5ec2408a35
--- /dev/null
+++ b/lib/compiler/test/compiler.cover
@@ -0,0 +1,3 @@
+%% -*- erlang -*-
+{exclude,[sys_pre_attributes,core_parse]}.
+
diff --git a/lib/compiler/test/compiler.dynspec b/lib/compiler/test/compiler.dynspec
new file mode 100644
index 0000000000..7e452cef6c
--- /dev/null
+++ b/lib/compiler/test/compiler.dynspec
@@ -0,0 +1,10 @@
+%% -*- erlang -*-
+%% You can test this file using this command.
+%% file:script("compiler.dynspec", [{'Os',"Unix"}]).
+
+case Os of
+ "VxWorks" ->
+ [{skip,{compile_SUITE,listings,"VxWorks filesystem too slow"}}];
+ _ ->
+ []
+end.
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
new file mode 100644
index 0000000000..54cf799057
--- /dev/null
+++ b/lib/compiler/test/core_SUITE.erl
@@ -0,0 +1,59 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(core_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ dehydrated_itracer/1,nested_tries/1]).
+
+-include("test_server.hrl").
+
+-define(comp(N),
+ N(Config) when is_list(Config) -> try_it(N, Config)).
+
+init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = test_server:timetrap(?t:minutes(5)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [dehydrated_itracer,nested_tries].
+
+?comp(dehydrated_itracer).
+?comp(nested_tries).
+
+try_it(Mod, Conf) ->
+ ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)),
+ ?line Out = ?config(priv_dir,Conf),
+ ?line io:format("Compiling: ~s\n", [Src]),
+ ?line CompRc0 = compile:file(Src, [from_core,{outdir,Out},report,time]),
+ ?line io:format("Result: ~p\n",[CompRc0]),
+ ?line {ok,Mod} = CompRc0,
+
+ ?line {module,Mod} = code:load_abs(filename:join(Out, Mod)),
+ ?line ok = Mod:Mod(),
+ ok.
+
+
+
+
diff --git a/lib/compiler/test/core_SUITE_data/dehydrated_itracer.core b/lib/compiler/test/core_SUITE_data/dehydrated_itracer.core
new file mode 100644
index 0000000000..e64e981edc
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/dehydrated_itracer.core
@@ -0,0 +1,99 @@
+module 'dehydrated_itracer' ['dehydrated_itracer'/0,
+ 'module_info'/0,
+ 'module_info'/1]
+ attributes []
+'dehydrated_itracer'/0 =
+ %% Line 5
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ %% Line 6
+ case apply 'itracer'/0
+ () of
+ <{'vector',65536}> when 'true' ->
+ %% Line 7
+ 'ok'
+ ( <_cor0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor0})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ primop 'match_fail'
+ ({'function_clause'})
+ -| ['compiler_generated'] )
+ end
+'itracer'/0 =
+ %% Line 8
+ fun () ->
+ let <Dir> =
+ %% Line 9
+ apply 'vcreate'/3
+ (0, 0, 256)
+ in %% Line 10
+ apply 'initialize'/1
+ (Dir)
+'initialize'/1 =
+ %% Line 12
+ fun (_cor0) ->
+ %% Line 23
+ case _cor0 of
+ <{'vector',_pre0}> when 'true' ->
+ let <_cor4> =
+ call 'erlang':'*'
+ (_pre0, 2)
+ in let <Up2> = {'vector',_cor4}
+ in case Up2 of
+ <{'vector',_pre0}> when 'true' ->
+ let <_cor4> =
+ call 'erlang':'*'
+ (_pre0, -1)
+ in let <Down> = {'vector',_cor4}
+ in case _cor0 of
+%%% The case would be optimized away, and pre0 would be used directly,
+%%% only it would be the wrong pre0.
+ <{'vector',_pre0}> when 'true' ->
+ let <_cor4> =
+ call 'erlang':'*'
+ (_pre0, 256)
+ in {'vector',_cor4}
+ <_cor7> when 'true' ->
+ call 'erlang':'error'
+ ({'badrecord','vector'})
+ end
+ <_cor7> when 'true' ->
+ call 'erlang':'error'
+ ({'badrecord','vector'})
+ end
+ <_cor7> when 'true' ->
+ call 'erlang':'error'
+ ({'badrecord','vector'})
+ end
+'vcreate'/3 =
+ %% Line 19
+ fun (_cor2,_cor1,_cor0) ->
+ %% Line 20
+ {'vector',_cor0}
+'mul'/2 =
+ %% Line 22
+ fun (_cor1,_cor0) ->
+ %% Line 23
+ case _cor0 of
+ <{'vector',_pre0}> when 'true' ->
+ let <_cor4> =
+ call 'erlang':'*'
+ (_pre0, _cor1)
+ in {'vector',_cor4}
+ <_cor7> when 'true' ->
+ call 'erlang':'error'
+ ({'badrecord','vector'})
+ end
+'module_info'/0 =
+ fun () ->
+ call 'erlang':'get_module_info'
+ ('dehydrated_itracer')
+'module_info'/1 =
+ fun (_cor0) ->
+ call 'erlang':'get_module_info'
+ ('dehydrated_itracer', _cor0)
+end \ No newline at end of file
diff --git a/lib/compiler/test/core_SUITE_data/nested_tries.core b/lib/compiler/test/core_SUITE_data/nested_tries.core
new file mode 100644
index 0000000000..d9010b808b
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/nested_tries.core
@@ -0,0 +1,36 @@
+module 'nested_tries' ['nested_tries'/0, 'reg'/2]
+ attributes []
+
+'nested_tries'/0 =
+ fun () -> 'ok'
+
+'reg'/2 =
+ fun (_cor1,_cor0) ->
+ let <_X_var__238> = 1
+ in case %% Line 4
+ <_cor1,_cor0> of
+ <Id,Pid>
+ when call 'erlang':'and'
+ (try 'true'
+ of <_X_var__235> -> _X_var__235
+ catch <_X_var__236,_X_var__237> -> 'false',
+ try
+ let <_cor2> =
+ try
+ call 'erlang':'and'
+ ('true',
+ call 'erlang':'is_integer'(call 'erlang':'element'(3, Pid)))
+ of <_X_var__232> -> _X_var__232
+ catch <_X_var__233,_X_var__234> -> 'false'
+ in let <_cor4> = call 'erlang':'element'(2, Pid)
+ in let <_cor3> = _X_var__238
+ in let <_cor5> = call 'erlang':'=='(_cor4, _cor3)
+ in call 'erlang':'and'(_cor2, _cor5)
+ of <Try> -> Try
+ catch <T,R> -> 'false') -> 'true'
+ <_cor7,_cor6> when 'true' ->
+ primop 'match_fail'
+ ({( 'function_clause'
+ -| [{'name',{'reg',2}}] ),_cor7,_cor6})
+ end
+end
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
new file mode 100644
index 0000000000..5f2c905d4a
--- /dev/null
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -0,0 +1,233 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(core_fold_SUITE).
+
+-export([all/1,
+ t_element/1,setelement/1,t_length/1,append/1,t_apply/1,bifs/1,
+ eq/1,nested_call_in_case/1,coverage/1]).
+
+-export([foo/0,foo/1,foo/2,foo/3]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [t_element,setelement,t_length,append,t_apply,bifs,
+ eq,nested_call_in_case,coverage].
+
+t_element(Config) when is_list(Config) ->
+ X = make_ref(),
+ ?line X = id(element(1, {X,y,z})),
+ ?line b = id(element(2, {a,b,c,d})),
+
+ %% No optimization, but should work.
+ Tuple = id({x,y,z}),
+ Pos = id(3),
+ ?line x = id(element(1, Tuple)),
+ ?line c = id(element(Pos, {a,b,c,d})),
+ ?line X = id(element(Pos, {a,b,X,d})),
+ ?line z = id(element(Pos, Tuple)),
+
+ %% Calls that will fail.
+ ?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,c,d})),
+ ?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,X,d})),
+ ?line {'EXIT',{badarg,_}} = (catch element(5.0, {a,b,X,d})),
+ case id({a,b,c}) of
+ {_,_,_}=Tup ->
+ ?line {'EXIT',{badarg,_}} = (catch element(4, Tup))
+ end,
+
+ ok.
+
+setelement(Config) when is_list(Config) ->
+ X = id(b),
+ New = id([1,2,3]),
+ ?line {y,b,c} = id(setelement(1, {a,b,c}, y)),
+ ?line {y,b,c} = id(setelement(1, {a,X,c}, y)),
+ ?line {a,y,c} = id(setelement(2, {a,X,c}, y)),
+ ?line {a,[1,2,3],c} = id(setelement(2, {a,b,c}, New)),
+ ?line {a,[1,2,3],c} = id(setelement(2, {a,X,c}, New)),
+ ?line {a,b,[1,2,3]} = id(setelement(3, {a,b,c}, New)),
+ ?line {a,b,[1,2,3]} = id(setelement(3, {a,X,c}, New)),
+
+ ?line {'EXIT',{badarg,_}} = (catch setelement_crash({a,b,c,d,e,f})),
+ ?line error = setelement_crash_2({a,b,c,d,e,f}, <<42>>),
+ ok.
+
+setelement_crash(Tuple) ->
+ %% Used to crash the compiler because sys_core_dsetel did not notice that
+ %% X1 was used in bit syntax construction.
+ X1 = setelement(5, Tuple, new),
+ X2 = setelement(3, X1, new),
+ {X2,<<X1>>}.
+
+setelement_crash_2(Tuple, Bin) ->
+ %% Used to crash the compiler because sys_core_dsetel did not notice that
+ %% X1 was used as a size field in bit syntax matching.
+ X1 = setelement(5, Tuple, new),
+ X2 = setelement(3, X1, new),
+ case Bin of
+ <<42:X1>> -> X2;
+ _ -> error
+ end.
+
+t_length(Config) when is_list(Config) ->
+ Blurf = id({blurf,a,b}),
+ Tail = id([42,43,44,45]),
+ ?line 0 = id(length([])),
+ ?line 1 = id(length([x])),
+ ?line 2 = id(length([x,Blurf])),
+ ?line 4 = id(length([x,Blurf,a,b])),
+
+ %% No or partial optimization.
+ ?line 4 = length(Tail),
+ ?line 5 = id(length([x|Tail])),
+
+ %% Will fail.
+ ?line {'EXIT',{badarg,_}} = (catch id(length([a,b|c]))),
+ ?line {'EXIT',{badarg,_}} = (catch id(length([a,Blurf|c]))),
+ ?line {'EXIT',{badarg,_}} = (catch id(length(atom))),
+
+ ok.
+
+-define(APPEND(A, B), (fun(Res) ->
+ Res = lists:append(A, B),
+ Res = erlang:append(A, B),
+ Res = erlang:'++'(A, B)
+ end)(A++B)).
+
+append(Config) when is_list(Config) ->
+ A = id(0),
+ ?line [a,b,c,d,e,f,g,h,i,j,k] = id(?APPEND([a,b,c,d,e,f],[g,h,i,j,k])),
+ ?line [a,b,c,d,e] = id(?APPEND([a,b,c],id([d,e]))),
+ ?line [0,1,2,3,4,5,6] = id(?APPEND([A,1,2,3],[4,5,6])),
+ ?line {'EXIT',{badarg,_}} = (catch id(?APPEND([A|blurf],[4,5,6]))),
+ ok.
+
+t_apply(Config) when is_list(Config) ->
+ ?line ok = apply(?MODULE, foo, []),
+ ?line 4 = apply(?MODULE, foo, [3]),
+ ?line 7 = apply(?MODULE, foo, [3,4]),
+ ?line 12 = apply(?MODULE, foo, [id(8),4]),
+ ?line 21 = apply(?MODULE, foo, [8,id(9),4]),
+ ?line 20 = apply(?MODULE, foo, [8,8,id(4)]),
+ ?line 24 = apply(?MODULE, foo, [id(10),10,4]),
+
+ M = id(?MODULE),
+ ?line ok = apply(M, foo, []),
+ ?line 4 = apply(M, foo, [3]),
+ ?line 16.0 = apply(M, foo, [12.0,4]),
+
+ %% Will fail.
+ ?line {'EXIT',{badarg,_}} = (catch apply([a,b,c], foo, [])),
+ ?line {'EXIT',{badarg,_}} = (catch apply(42, foo, [])),
+ ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, 45, [xx])),
+ ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, {a,b})),
+ ?line {'EXIT',{badarg,_}} = (catch apply(M, M, [1009|10010])),
+ ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, [10000|9999])),
+ ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, a)),
+
+ ok.
+
+foo() ->
+ ok.
+
+foo(A) ->
+ A+1.
+
+foo(A, B) ->
+ A + B.
+
+foo(A, B, C) ->
+ A + B + C.
+
+bifs(Config) when is_list(Config) ->
+ ?line <<1,2,3,4>> = id(list_to_binary([1,2,3,4])),
+ ok.
+
+-define(CMP_SAME(A0, B), (fun(A) -> true = A == B, false = A /= B end)(id(A0))).
+-define(CMP_DIFF(A0, B), (fun(A) -> false = A == B, true = A /= B end)(id(A0))).
+
+eq(Config) when is_list(Config) ->
+ ?line ?CMP_SAME([a,b,c], [a,b,c]),
+ ?line ?CMP_SAME([42.0], [42.0]),
+ ?line ?CMP_SAME([42], [42]),
+ ?line ?CMP_SAME([42.0], [42]),
+
+ ?line ?CMP_DIFF(a, [a]),
+ ?line ?CMP_DIFF(a, {1,2,3}),
+
+ ok.
+
+%% OTP-7117.
+nested_call_in_case(Config) when is_list(Config) ->
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Dir = filename:dirname(code:which(?MODULE)),
+ ?line Core = filename:join(Dir, "nested_call_in_case"),
+ ?line Opts = [from_core,{outdir,PrivDir}|test_lib:opt_opts(?MODULE)],
+ ?line io:format("~p", [Opts]),
+ ?line {ok,Mod} = c:c(Core, Opts),
+ ?line yes = Mod:a([1,2,3], 2),
+ ?line no = Mod:a([1,2,3], 4),
+ ?line {'EXIT',_} = (catch Mod:a(not_a_list, 42)),
+ ok.
+
+coverage(Config) when is_list(Config) ->
+ ?line {'EXIT',{{case_clause,{a,b,c}},_}} =
+ (catch cover_will_match_list_type({a,b,c})),
+ ?line {'EXIT',{{case_clause,{a,b,c,d}},_}} =
+ (catch cover_will_match_list_type({a,b,c,d})),
+ ?line a = cover_remove_non_vars_alias({a,b,c}),
+ ?line error = cover_will_match_lit_list(),
+
+ %% Make sure that we don't attempt to make literals
+ %% out of pids. (Putting a pid into a #c_literal{}
+ %% would crash later compiler passes.)
+ case list_to_pid("<0.42.0>") of
+ Pid when is_pid(Pid) -> ok
+ end,
+ ok.
+
+cover_will_match_list_type(A) ->
+ case A of
+ {a,_,_} -> %Set type of A to {a,_,_}.
+ case A of
+ {a,_,_,_} -> ok %Compare type and pattern.
+ end
+ end.
+
+%% Make sure the remove_non_vars/4 can handle aliases in the type argument.
+cover_remove_non_vars_alias(X) ->
+ case X of
+ {a=Y,_,_} -> %Set type of A to {a=Y,_,_}.
+ case X of
+ {_,_,_} -> %Compare type and pattern.
+ Y
+ end
+ end.
+
+cover_will_match_lit_list() ->
+ case {1,2,3} of %Literal case expression.
+ {_,$A,$A} -> %Pattern that does not match.
+ ok;
+ _ ->
+ error
+ end.
+
+id(I) -> I.
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
new file mode 100644
index 0000000000..477730c3ac
--- /dev/null
+++ b/lib/compiler/test/error_SUITE.erl
@@ -0,0 +1,114 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(error_SUITE).
+
+-include("test_server.hrl").
+
+-export([all/1,
+ head_mismatch_line/1,r11b_binaries/1]).
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [head_mismatch_line,r11b_binaries].
+
+%% Tests that a head mismatch is reported on the correct line (OTP-2125).
+head_mismatch_line(Config) when is_list(Config) ->
+ ?line [E|_] = get_compilation_errors(Config, "head_mismatch_line"),
+ ?line {26, Mod, Reason} = E,
+ ?line Mod:format_error(Reason),
+ ok.
+
+%% Compiles a test file and returns the list of errors.
+
+get_compilation_errors(Config, Filename) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line File = filename:join(DataDir, Filename),
+ ?line {error, [{_Name, E}|_], []} = compile:file(File, [return_errors]),
+ E.
+
+r11b_binaries(Config) when is_list(Config) ->
+ Ts = [{r11b_binaries,
+ <<"
+ t1(Bin) ->
+ case Bin of
+ _ when size(Bin) > 20 -> erlang:error(too_long);
+ <<_,T/binary>> -> t1(T);
+ <<>> -> ok
+ end.
+
+ t2(<<_,T/bytes>>) ->
+ split_binary(T, 4).
+
+ t3(X) ->
+ <<42,X/binary>>.
+
+ t4(X) ->
+ <<N:32>> = X,
+ N.
+ ">>,
+ [r11],
+ {error,
+ [{5,v3_core,no_binaries},
+ {6,v3_core,no_binaries},
+ {9,v3_core,no_binaries},
+ {13,v3_core,no_binaries},
+ {16,v3_core,no_binaries}],
+ []} }],
+ ?line [] = run(Config, Ts),
+ ok.
+
+
+run(Config, Tests) ->
+ F = fun({N,P,Ws,E}, BadL) ->
+ case catch run_test(Config, P, Ws) of
+ E ->
+ BadL;
+ Bad ->
+ ?t:format("~nTest ~p failed. Expected~n ~p~n"
+ "but got~n ~p~n", [N, E, Bad]),
+ fail()
+ end
+ end,
+ lists:foldl(F, [], Tests).
+
+
+%% Compiles a test module and returns the list of errors and warnings.
+
+run_test(Conf, Test0, Warnings) ->
+ Filename = 'errors_test.erl',
+ ?line DataDir = ?config(priv_dir, Conf),
+ ?line Test = ["-module(errors_test). ", Test0],
+ ?line File = filename:join(DataDir, Filename),
+ ?line Opts = [binary,export_all,return|Warnings],
+ ?line ok = file:write_file(File, Test),
+
+ %% Compile once just to print all errors and warnings.
+ ?line compile:file(File, [binary,export_all,report|Warnings]),
+
+ %% Test result of compilation.
+ ?line Res = case compile:file(File, Opts) of
+ {error,[{_File,Es}],Ws} ->
+ {error,Es,Ws}
+ end,
+ file:delete(File),
+ Res.
+
+fail() ->
+ io:format("failed~n"),
+ ?t:fail().
diff --git a/lib/compiler/test/error_SUITE_data/head_mismatch_line.erl b/lib/compiler/test/error_SUITE_data/head_mismatch_line.erl
new file mode 100644
index 0000000000..619c1329a4
--- /dev/null
+++ b/lib/compiler/test/error_SUITE_data/head_mismatch_line.erl
@@ -0,0 +1,30 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(head_mismatch_line).
+
+-export([foo/1, bar/2]).
+
+foo(a) ->
+ ok;
+
+bar(x) -> % The mismatch should be here.
+ ok;
+bar(y) ->
+ ok.
+
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
new file mode 100644
index 0000000000..3d2dbf47e9
--- /dev/null
+++ b/lib/compiler/test/float_SUITE.erl
@@ -0,0 +1,120 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(float_SUITE).
+-export([all/1,pending/1,bif_calls/1,math_functions/1,mixed_float_and_int/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [pending,bif_calls,math_functions,mixed_float_and_int].
+
+%% Thanks to Tobias Lindahl <[email protected]>
+%% Shows the effect of pending exceptions on the x86.
+
+pending(Config) when is_list(Config) ->
+ ?line case catch float_mul(1, 1.1e300, 3.14e300) of
+ {'EXIT',{badarith,_}} -> ok;
+ Other -> ?t:fail({expected_exception,Other})
+ end,
+ ?line 0.0 = float_sub(2.0).
+
+float_sub(A)->
+ catch A - 2.0.
+
+float_mul(0, _, _)->
+ ok;
+float_mul(Iter, A, B) when is_float(A), is_float(B) ->
+ A*B,
+ float_mul(Iter-1, A, B).
+
+%% Thanks to Mikael Pettersson and Tobias Lindahl (HiPE).
+
+bif_calls(Config) when is_list(Config) ->
+ ?line {'EXIT',{badarith,_}} = (catch bad_arith(2.0, 1.7)),
+ ?line {'EXIT',{badarith,_}} = (catch bad_arith_again(2.0, [])),
+ ?line {'EXIT',{badarith,_}} = (catch bad_arith_xor(2.0, [])),
+ ?line {'EXIT',{badarith,_}} = (catch bad_arith_hd(2.0, [])),
+ ?line {'EXIT',{badarith,_}} = (catch bad_negate(2.0, 1.7)),
+ ok.
+
+bad_arith(X, Y) when is_float(X) ->
+ X1 = X * 1.7e+308,
+ X2 = X1 + 1.0,
+ Y1 = Y * 2, %Calls erts_mixed_times/2.
+ %(A BIF call.)
+ {X2, Y1}.
+
+bad_arith_xor(X, Y) when is_float(X) ->
+ X1 = X * 1.7e+308,
+ Y1 = Y xor true, %A failing BIF call.
+ {X1 + 1.0, Y1}.
+
+bad_arith_hd(X, Y) when is_float(X) ->
+ X1 = X * 1.7e+308,
+ Y1 = hd(Y), %A failing BIF call.
+ {X1 + 1.0, Y1}.
+
+bad_arith_again(X, Y) when is_float(X) ->
+ X1 = X * 1.7e+308,
+ Y1 = element(1, Y), %A failing BIF call.
+ {X1 + 1.0, Y1}.
+
+bad_negate(X, Y) when is_float(X) ->
+ X1 = X * 1.7e+308,
+ X2 = X1 + 1.0,
+ Y1 = -Y, %BIF call.
+ {X2, Y1}.
+
+math_functions(Config) when is_list(Config) ->
+ %% Mostly silly coverage.
+ ?line 0.0 = math:tan(0),
+ ?line 0.0 = math:atan2(0, 1),
+ ?line 0.0 = math:sinh(0),
+ ?line 1.0 = math:cosh(0),
+ ?line 0.0 = math:tanh(0),
+ ?line 1.0 = math:log10(10),
+ ?line -1.0 = math:cos(math:pi()),
+ ?line 1.0 = math:exp(0),
+ ?line 1.0 = math:pow(math:pi(), 0),
+
+ ?line 0.0 = math:tan(id(0)),
+ ?line 0.0 = math:atan2(id(0), 1),
+ ?line 0.0 = math:sinh(id(0)),
+ ?line 1.0 = math:cosh(id(0)),
+ ?line 0.0 = math:tanh(id(0)),
+ ?line 1.0 = math:log10(id(10)),
+ ?line 1.0 = math:exp(id(0)),
+
+ %% Only for coverage (of beam_type.erl).
+ ?line {'EXIT',{undef,_}} = (catch math:fnurfla(0)),
+ ?line {'EXIT',{undef,_}} = (catch math:fnurfla(0, 0)),
+ ?line {'EXIT',{badarg,_}} = (catch float(kalle)),
+ ?line {'EXIT',{badarith,_}} = (catch name/1),
+ ok.
+
+mixed_float_and_int(Config) when is_list(Config) ->
+ ?line 129.0 = pc(77, 23, 5),
+ ok.
+
+pc(Cov, NotCov, X) ->
+ round(Cov/(Cov+NotCov)*100) + 42 + 2.0*X.
+
+id(I) -> I.
+
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
new file mode 100644
index 0000000000..fb2667245a
--- /dev/null
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -0,0 +1,136 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(fun_SUITE).
+
+-export([all/1,
+ test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [test1,overwritten_fun,otp_7202,bif_fun].
+
+%%% The help functions below are copied from emulator:bs_construct_SUITE.
+
+-define(T(B, L), {B, ??B, L}).
+
+l1() ->
+ [
+ ?T((begin A = 3, F = fun(A) -> 1; (_) -> 2 end, F(2) end), 1),
+ ?T((begin G = fun(1=0) -> ok end, {'EXIT',_} = (catch G(2)), ok end), ok)
+ ].
+
+test1(suite) -> [];
+test1(Config) when is_list(Config) ->
+ ?line lists:foreach(fun one_test/1, eval_list(l1(), [])),
+ ok.
+
+evaluate(Str, Vars) ->
+ {ok,Tokens,_} =
+ erl_scan:string(Str ++ " . "),
+ {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ case erl_eval:expr(Expr, Vars) of
+ {value, Result, _} ->
+ Result
+ end.
+
+eval_list([], _Vars) ->
+ [];
+eval_list([{C_bin, Str, Bytes} | Rest], Vars) ->
+ case catch evaluate(Str, Vars) of
+ {'EXIT', Error} ->
+ io:format("Evaluation error: ~p, ~p, ~p~n", [Str, Vars, Error]),
+ exit(Error);
+ E_bin ->
+ [{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)]
+ end.
+
+one_test({C, E, Str, Correct}) ->
+ io:format(" ~s, ~p~n", [Str, Correct]),
+ if
+ C == Correct ->
+ ok;
+ true ->
+ io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n",
+ [Str, Correct, C]),
+ test_server:fail(comp)
+ end,
+ if
+ E == Correct ->
+ ok;
+ true ->
+ io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n",
+ [Str, Correct, E]),
+ test_server:fail(comp)
+ end.
+
+-record(b, {c}).
+
+%% OTP-7102. (Thanks to Simon Cornish.)
+
+overwritten_fun(Config) when is_list(Config) ->
+ ?line {a2,a} = overwritten_fun_1(a),
+ ?line {a2,{b,c}} = overwritten_fun_1(#b{c=c}),
+ ?line one = overwritten_fun_1(#b{c=[]}),
+ ok.
+
+overwritten_fun_1(A) ->
+ F = fun() ->
+ {ok, A}
+ end,
+ if A#b.c == [] ->
+ one;
+ true ->
+ case F() of
+ {ok, A2} ->
+ {a2, A2};
+ _ ->
+ three
+ end
+ end.
+
+%% OTP-7202. The liveness calculation for the make_fun2 instruction was wrong.
+
+otp_7202(Config) when is_list(Config) ->
+ otp_7202().
+
+otp_7202() ->
+ List = [a],
+ Error = case otp_7202_func() of
+ no_value -> true;
+ {ok, V} -> V
+ end,
+ lists:foreach(fun(_E) ->
+ case Error of
+ true ->
+ ok;
+ false ->
+ ok
+ end
+ end, List).
+
+otp_7202_func() ->
+ no_value.
+
+bif_fun(Config) when is_list(Config) ->
+ ?line F = fun abs/1,
+ ?line 5 = F(-5),
+ ok.
+
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
new file mode 100644
index 0000000000..5ae41f13e7
--- /dev/null
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -0,0 +1,1376 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(guard_SUITE).
+
+-include("test_server.hrl").
+
+-export([all/1,
+ misc/1,const_cond/1,basic_not/1,complex_not/1,nested_nots/1,
+ semicolon/1,complex_semicolon/1,comma/1,
+ or_guard/1,more_or_guards/1,
+ complex_or_guards/1,and_guard/1,
+ xor_guard/1,more_xor_guards/1,
+ old_guard_tests/1,
+ build_in_guard/1,gbif/1,
+ t_is_boolean/1,is_function_2/1,
+ tricky/1,rel_ops/1,literal_type_tests/1,
+ basic_andalso_orelse/1,traverse_dcd/1,
+ check_qlc_hrl/1,andalso_semi/1,tuple_size/1]).
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [misc,const_cond,basic_not,complex_not,nested_nots,
+ semicolon,complex_semicolon,
+ comma,or_guard,more_or_guards,
+ complex_or_guards,and_guard,
+ xor_guard,more_xor_guards,
+ build_in_guard,old_guard_tests,gbif,
+ t_is_boolean,is_function_2,tricky,rel_ops,literal_type_tests,
+ basic_andalso_orelse,traverse_dcd,check_qlc_hrl,andalso_semi,
+ tuple_size].
+
+misc(Config) when is_list(Config) ->
+ ?line 42 = case id(42) of
+ X when -X -> ok;
+ X -> X
+ end,
+ ?line {a,b,c} = misc_1([{{a,b,c}},{[4]},{[3]},{-2}]),
+ ?line none = misc_1([{{a,b,c}},{[4]},{[3]},{-3}]),
+ ?line none = misc_1([{{a,b,c}},{[4]},{[7]},{-2}]),
+ ?line none = misc_1([{{a,b,c}},{[4]},{[3]},{[1,2,3]}]),
+
+ ?line {ok,buf,<<>>} = get_data({o,true,raw}, 0, buf),
+ ?line {ok,buf,<<>>} = get_data({o,true,raw}, 42, buf),
+ ?line {ok,buf,<<>>} = get_data({o,false,raw}, 0, buf),
+ ?line error = get_data({o,false,raw}, 42, buf),
+ ?line {ok,buf,<<>>} = get_data({o,true,0}, 0, buf),
+ ?line {ok,buf,<<>>} = get_data({o,true,0}, 42, buf),
+ ?line {ok,buf,<<>>} = get_data({o,false,0}, 0, buf),
+ ?line error = get_data({o,false,0}, 42, buf),
+ ok.
+
+
+misc_1([{W},{X},{Y},{Z}]) ->
+ if
+ X > Y andalso abs(Z) =:= 2 ->
+ id(W);
+ true ->
+ none
+ end.
+
+get_data({o,Active,Raw}, BytesToRead, Buffer)
+ when Raw =:= raw; Raw =:= 0 ->
+ if
+ Active =/= false orelse BytesToRead =:= 0 ->
+ {ok,Buffer,<<>>};
+ true ->
+ error
+ end.
+
+const_cond(Config) when is_list(Config) ->
+ ?line ok = const_cond({}, 0),
+ ?line ok = const_cond({a}, 1),
+ ?line error = const_cond({a,b}, 3),
+ ?line error = const_cond({a}, 0),
+ ?line error = const_cond({a,b}, 1),
+ ok.
+
+const_cond(T, Sz) ->
+ case T of
+ _X when false -> never;
+ _X when tuple(T), eq == eq, tuple_size(T) == Sz -> ok;
+ _X when tuple(T), eq == leq, tuple_size(T) =< Sz -> ok;
+ _X -> error
+ end.
+
+basic_not(Config) when is_list(Config) ->
+ True = id(true),
+ False = id(false),
+ Glurf = id(glurf),
+ A = id(5),
+ B = id(37.5),
+ C = id(-1),
+ D = id(5),
+ ATuple = {False,True,Glurf},
+
+ ?line check(fun() -> if not false -> ok; true -> error end end, ok),
+ ?line check(fun() -> if not true -> ok; true -> error end end, error),
+ ?line check(fun() -> if not False -> ok; true -> error end end, ok),
+ ?line check(fun() -> if not True -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt),
+ ?line check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt),
+ ?line check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq),
+
+ ?line check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge;
+ not (7 == 453) -> ne; true -> eq end end, le),
+ ?line check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge;
+ not (7 == -8) -> ne; true -> eq end end, ge),
+ ?line check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge;
+ not (7 == 7) -> ne; true -> eq end end, le),
+
+ ?line check(fun() -> if not (A > B) -> le; not (A < B) -> ge;
+ not (A == B) -> ne; true -> eq end end, le),
+ ?line check(fun() -> if not (A > C) -> le; not (A < C) -> ge;
+ not (A == C) -> ne; true -> eq end end, ge),
+ ?line check(fun() -> if not (A > D) -> le; not (A < D) -> ge;
+ not (A == D) -> ne; true -> eq end end, le),
+
+ ?line check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok),
+ ?line check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error),
+ ?line check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if not glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if not Glurf -> ok; true -> error end end, error),
+
+ ok.
+
+complex_not(Config) when is_list(Config) ->
+ ATuple = id({false,true,gurka}),
+ ?line check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok),
+ ?line check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if not(element(3, ATuple) == gurka) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok;
+ true -> error end end, ok),
+
+ ?line check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok;
+ true -> error end end, ok),
+ ?line check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok;
+ true -> error end end, error),
+
+ ?line check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok;
+ true -> error end end, error),
+
+ %% orelse
+ ?line check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok;
+ true -> error end end, error),
+
+ ok.
+
+nested_nots(Config) when is_list(Config) ->
+ ?line true = nested_not_1(0, 0),
+ ?line true = nested_not_1(0, 1),
+ ?line true = nested_not_1(a, b),
+ ?line true = nested_not_1(10, 0),
+ ?line false = nested_not_1(z, a),
+ ?line false = nested_not_1(3.4, {anything,goes}),
+ ?line false = nested_not_1(3.4, atom),
+ ?line true = nested_not_1(3.0, [list]),
+
+ ?line true = nested_not_2(false, false, 42),
+ ?line true = nested_not_2(false, true, 42),
+ ?line true = nested_not_2(true, false, 42),
+ ?line true = nested_not_2(true, true, 42),
+ ?line true = nested_not_2(false, false, atom),
+ ?line false = nested_not_2(false, true, atom),
+ ?line false = nested_not_2(true, false, atom),
+ ?line false = nested_not_2(true, true, atom),
+ ok.
+
+nested_not_1(X, Y) when not (((X>Y) or not(is_atom(X))) and
+ (is_atom(Y) or (X==3.4))) ->
+ true;
+nested_not_1(_, _) ->
+ false.
+
+nested_not_2(X, Y, Z) ->
+ nested_not_2(X, Y, Z, true).
+
+nested_not_2(X, Y, Z, True)
+ when not(True and not((not(X) and not(Y)) or not(is_atom(Z)))) ->
+ true;
+nested_not_2(_, _, _, _) ->
+ false.
+
+semicolon(Config) when is_list(Config) ->
+
+ %% True/false combined using ';' (literal atoms).
+
+ ?line check(fun() -> if true; false -> ok end end, ok),
+ ?line check(fun() -> if false; true -> ok end end, ok),
+ ?line check(fun() -> if true; true -> ok end end, ok),
+ ?line check(fun() -> if false; false -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if false; false -> ok end),
+ exit
+ end, exit),
+
+ %% True/false combined used ';'.
+
+ True = id(true),
+ False = id(false),
+
+ ?line check(fun() -> if True; False -> ok end end, ok),
+ ?line check(fun() -> if False; True -> ok end end, ok),
+ ?line check(fun() -> if True; True -> ok end end, ok),
+ ?line check(fun() -> if False; False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if False; False -> ok end),
+ exit
+ end, exit),
+
+ %% Combine true/false with a non-boolean value.
+ Glurf = id(glurf),
+
+
+ ?line check(fun() -> if True; Glurf -> ok end end, ok),
+ ?line check(fun() -> if Glurf; True -> ok end end, ok),
+ ?line check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if False; Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf; False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end),
+ exit
+ end, exit),
+
+ %% Combine true/false with errors.
+
+ ATuple = id({false,true,gurka}),
+
+ ?line check(fun() -> if True; element(42, ATuple) -> ok end end, ok),
+ ?line check(fun() -> if element(42, ATuple); True -> ok end end, ok),
+ ?line check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if False; element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if element(42, ATuple);
+ False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if element(42, ATuple);
+ element(42, ATuple) -> ok end),
+ exit
+ end, exit),
+
+ ok.
+
+complex_semicolon(Config) when is_list(Config) ->
+ ?line ok = csemi1(int, {blurf}),
+ ?line ok = csemi1(string, {blurf}),
+ ?line ok = csemi1(float, [a]),
+ ?line error = csemi1(35, 42),
+
+ %% 2
+ ?line ok = csemi2({}, {a,b,c}),
+ ?line ok = csemi2({1,3.5}, {a,b,c}),
+ ?line ok = csemi2(dum, {a,b,c}),
+
+ ?line ok = csemi2({45,-19.3}, {}),
+ ?line ok = csemi2({45,-19.3}, {dum}),
+ ?line ok = csemi2({45,-19.3}, {dum,dum}),
+
+ ?line error = csemi2({45}, {dum}),
+ ?line error = csemi2([], {dum}),
+ ?line error = csemi2({dum}, []),
+ ?line error = csemi2([], []),
+
+ %% 3
+ ?line csemi3(fun csemi3a/4),
+ ?line csemi3(fun csemi3b/4),
+ ?line csemi3(fun csemi3c/4),
+
+ %% 4
+ ?line csemi4(fun csemi4a/4),
+ ?line csemi4(fun csemi4b/4),
+ ?line csemi4(fun csemi4c/4),
+ ?line csemi4(fun csemi4d/4),
+
+ %% 4, 'orelse' instead of 'or'
+ ?line csemi4_orelse(fun csemi4_orelse_a/4),
+ ?line csemi4_orelse(fun csemi4_orelse_b/4),
+ ?line csemi4_orelse(fun csemi4_orelse_c/4),
+ ?line csemi4_orelse(fun csemi4_orelse_d/4),
+
+ %% 5
+ ?line error = csemi5(0, 0),
+ ?line ok = csemi5(5, 0),
+ ?line ok = csemi5(4, -4),
+ ?line ok = csemi5(10, -4),
+
+ %% 6
+ ?line error = csemi6({a}, 0),
+ ?line ok = csemi6({a,b}, 0),
+ ?line ok = csemi6({}, 3),
+ ?line ok = csemi6({a,b,c}, 3),
+
+ ok.
+
+csemi1(Type, Val) when is_list(Val), Type == float;
+ Type == int; Type == string -> ok;
+csemi1(_, _) -> error.
+
+csemi2(A, B) when tuple_size(A) > 1; tuple_size(B) > 2 -> ok;
+csemi2(_, _) -> error.
+
+csemi3(Csemi3) ->
+ ok = Csemi3({}, {a,b,c}, [0], [0]),
+ ok = Csemi3({1,3.5}, {a,b,c}, -1, -1),
+ ok = Csemi3(dum, {a,b,c}, 0.0, 0.0),
+ ok = Csemi3(dum, {c}, b, a),
+ ok = Csemi3(dum, <<1,2,3>>, 0.0, 0.0),
+ ok = Csemi3(<<3.5/float>>, {a,b,c}, -1, -1),
+
+ ok = Csemi3({45,-19.3}, {}, [], []),
+ ok = Csemi3({45,-19.3}, {dum}, 42, 42),
+ ok = Csemi3({45,-19.3}, {dum,dum}, 33, 33),
+
+ ok = Csemi3({45}, {dum}, 1.0, 0),
+ ok = Csemi3([a], {dum}, 1.0, 0),
+ ok = Csemi3({dum}, [], 1.0, 0),
+ ok = Csemi3([], [], 1.0, 0),
+ ok = Csemi3(blurf, {dum}, 1.0, 0),
+ ok = Csemi3({a}, blurf, 1.0, 0),
+ ok = Csemi3([a], [dum], 1.0, 0),
+ ok = Csemi3({dum}, [], 1.0, 0),
+ ok = Csemi3([], [], 1.0, 0),
+
+ error = Csemi3({45}, {dum}, 0, 0),
+ error = Csemi3([a], {dum}, 0, 0),
+ error = Csemi3({dum}, [], 0, 0),
+ error = Csemi3([], [], 0, 0),
+
+ ok.
+
+csemi3a(A, B, X, Y) when X > Y; size(A) > 1; size(B) > 2 -> ok;
+csemi3a(_, _, _, _) -> error.
+
+csemi3b(A, B, X, Y) when size(A) > 1; X > Y; size(B) > 2 -> ok;
+csemi3b(_, _, _, _) -> error.
+
+csemi3c(A, B, X, Y) when size(A) > 1; size(B) > 2; X > Y -> ok;
+csemi3c(_, _, _, _) -> error.
+
+
+csemi4(Test) ->
+ ok = Test({a,b}, 2, {c,d}, 2),
+ ok = Test({1,2,3}, 0, [], 0),
+ ok = Test({}, 2, blurf, 0),
+ ok = Test({}, 2, {1}, 2),
+
+ error = Test([], 4, {}, 0),
+ error = Test({}, 0, [a,b], 4),
+ error = Test({}, 0, [a,b], 0),
+ error = Test([], 0, {}, 0),
+ error = Test({}, 0, {}, 0),
+
+ ok.
+
+csemi4a(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1);
+ (tuple_size(B) > 1) or (Y > 1) -> ok;
+csemi4a(_, _, _, _) -> error.
+
+csemi4b(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1);
+ (tuple_size(B) > 1) or (Y > 1) -> ok;
+csemi4b(_, _, _, _) -> error.
+
+csemi4c(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1);
+ (Y > 1) or (tuple_size(B) > 1) -> ok;
+csemi4c(_, _, _, _) -> error.
+
+csemi4d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1);
+ (Y > 1) or (tuple_size(B) > 1) -> ok;
+csemi4d(_, _, _, _) -> error.
+
+
+csemi4_orelse(Test) ->
+ ok = Test({a,b}, 2, {c,d}, 2),
+ ok = Test({1,2,3}, 0, [], 0),
+ ok = Test({}, 2, blurf, 0),
+ ok = Test({}, 2, {1}, 2),
+
+ ?line error = Test([], 1, {}, 0),
+
+ ok.
+
+csemi4_orelse_a(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1);
+ (tuple_size(B) > 1) orelse (Y > 1) -> ok;
+csemi4_orelse_a(_, _, _, _) -> error.
+
+csemi4_orelse_b(A, X, B, Y) when (X > 1) orelse (tuple_size(A) > 1);
+ (tuple_size(B) > 1) orelse (Y > 1) -> ok;
+csemi4_orelse_b(_, _, _, _) -> error.
+
+csemi4_orelse_c(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1);
+ (Y > 1) orelse (tuple_size(B) > 1) -> ok;
+csemi4_orelse_c(_, _, _, _) -> error.
+
+csemi4_orelse_d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1);
+ (Y > 1) or (tuple_size(B) > 1) -> ok;
+csemi4_orelse_d(_, _, _, _) -> error.
+
+csemi5(A, B) when hd([A+B]) > 1; abs(B) > 2 -> ok;
+csemi5(_, _) -> error.
+
+csemi6(A, B) when hd([tuple_size(A)]) > 1; abs(B) > 2 -> ok;
+csemi6(_, _) -> error.
+
+comma(Config) when is_list(Config) ->
+
+ %% ',' combinations of literal true/false.
+
+ ?line check(fun() -> if true, false -> ok; true -> error end end, error),
+ ?line check(fun() -> if false, true -> ok; true -> error end end, error),
+ ?line check(fun() -> if true, true -> ok end end, ok),
+ ?line check(fun() -> if false, false -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if true, false -> ok;
+ false, true -> ok;
+ false, false -> ok
+ end),
+ exit
+ end, exit),
+
+ %% ',' combinations of true/false in variables.
+
+ True = id(true),
+ False = id(false),
+
+ ?line check(fun() -> if True, False -> ok; true -> error end end, error),
+ ?line check(fun() -> if False, True -> ok; true -> error end end, error),
+ ?line check(fun() -> if True, True -> ok end end, ok),
+ ?line check(fun() -> if False, False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True, False -> ok;
+ False, True -> ok;
+ False, False -> ok
+ end),
+ exit
+ end, exit),
+
+ %% ',' combinations of true/false, and non-boolean in variables.
+
+ Glurf = id(glurf),
+
+ ?line check(fun() -> if True, Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf, True -> ok; true -> error end end, error),
+ ?line check(fun() -> if True, True -> ok end end, ok),
+ ?line check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True, Glurf -> ok;
+ Glurf, True -> ok;
+ Glurf, Glurf -> ok
+ end),
+ exit
+ end, exit),
+
+ %% ',' combinations of true/false with errors.
+ ATuple = id({a,b,c}),
+
+ ?line check(fun() -> if True, element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if element(42, ATuple), True -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if True, True -> ok end end, ok),
+ ?line check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True, element(42, ATuple) -> ok;
+ element(42, ATuple), True -> ok;
+ element(42, ATuple), element(42, ATuple) -> ok
+ end),
+ exit
+ end, exit),
+
+ ok.
+
+or_guard(Config) when is_list(Config) ->
+ True = id(true),
+ False = id(false),
+ Glurf = id(glurf),
+
+ %% 'or' combinations of literal true/false.
+ ?line check(fun() -> if true or false -> ok end end, ok),
+ ?line check(fun() -> if false or true -> ok end end, ok),
+ ?line check(fun() -> if true or true -> ok end end, ok),
+ ?line check(fun() -> if false or false -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if glurf or true -> ok; true -> error end end, error),
+ ?line check(fun() -> if true or glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if glurf or glurf -> ok; true -> error end end, error),
+
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if false or false -> ok end),
+ exit
+ end, exit),
+
+
+ %% 'or' combinations using variables containing true/false.
+ ?line check(fun() -> if True or False -> ok end end, ok),
+ ?line check(fun() -> if False or True -> ok end end, ok),
+ ?line check(fun() -> if True or True -> ok end end, ok),
+ ?line check(fun() -> if False or False -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if True or Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf or True -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error),
+
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if False or False -> ok end),
+ exit
+ end, exit),
+
+ ok.
+
+more_or_guards(Config) when is_list(Config) ->
+ True = id(true),
+ False = id(false),
+ ATuple = id({false,true,gurka}),
+
+ ?line check(fun() ->
+ if element(42, ATuple) or False -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if False or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(18, ATuple) or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if True or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(42, ATuple) or True -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(1, ATuple) or element(42, ATuple) or True -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(1, ATuple) or True or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if
+ (<<False:8>> == <<0>>) or element(2, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if
+ element(2, ATuple) or (<<True:8>> == <<1>>) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(2, ATuple) or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if
+ element(1, ATuple) or
+ element(2, ATuple) or
+ element(19, ATuple) -> ok;
+ true -> error end
+ end, error),
+ ok.
+
+complex_or_guards(Config) when is_list(Config) ->
+ %% complex_or_1/2
+ ?line ok = complex_or_1({a,b,c,d}, {1,2,3}),
+ ?line ok = complex_or_1({a,b,c,d}, {1}),
+ ?line ok = complex_or_1({a}, {1,2,3}),
+ ?line error = complex_or_1({a}, {1}),
+
+ ?line error = complex_or_1(1, 2),
+ ?line error = complex_or_1([], {a,b,c,d}),
+ ?line error = complex_or_1({a,b,c,d}, []),
+
+
+ %% complex_or_2/1
+ ?line ok = complex_or_2({true,{}}),
+ ?line ok = complex_or_2({false,{a}}),
+ ?line ok = complex_or_2({false,{a,b,c}}),
+ ?line ok = complex_or_2({true,{a,b,c,d}}),
+
+ ?line error = complex_or_2({blurf,{a,b,c}}),
+
+ ?line error = complex_or_2({true}),
+ ?line error = complex_or_2({true,no_tuple}),
+ ?line error = complex_or_2({true,[]}),
+
+ %% complex_or_3/2
+ ?line ok = complex_or_3({true}, {}),
+ ?line ok = complex_or_3({false}, {a}),
+ ?line ok = complex_or_3({false}, {a,b,c}),
+ ?line ok = complex_or_3({true}, {a,b,c,d}),
+ ?line ok = complex_or_3({false}, <<1,2,3>>),
+ ?line ok = complex_or_3({true}, <<1,2,3,4>>),
+
+ ?line error = complex_or_3(blurf, {a,b,c}),
+
+ ?line error = complex_or_3({false}, <<1,2,3,4>>),
+ ?line error = complex_or_3([], <<1,2>>),
+ ?line error = complex_or_3({true}, 45),
+ ?line error = complex_or_3(<<>>, <<>>),
+
+ %% complex_or_4/2
+ ?line ok = complex_or_4(<<1,2,3>>, {true}),
+ ?line ok = complex_or_4(<<1,2,3>>, {false}),
+ ?line ok = complex_or_4(<<1,2,3>>, {true}),
+ ?line ok = complex_or_4({1,2,3}, {true}),
+ ?line error = complex_or_4({1,2,3,4}, {false}),
+
+ ?line error = complex_or_4(<<1,2,3,4>>, []),
+ ?line error = complex_or_4([], {true}),
+
+ %% complex_or_5/2
+ ?line ok = complex_or_5(<<1>>, {false}),
+ ?line ok = complex_or_5(<<1,2,3>>, {true}),
+ ?line ok = complex_or_5(<<1,2,3,4>>, {false}),
+ ?line ok = complex_or_5({1,2,3}, {false}),
+ ?line ok = complex_or_5({1,2,3,4}, {false}),
+
+ ?line error = complex_or_5(blurf, {false}),
+ ?line error = complex_or_5(<<1>>, klarf),
+ ?line error = complex_or_5(blurf, klarf),
+
+ %% complex_or_6/2
+ ?line ok = complex_or_6({true,true}, {1,2,3,4}),
+ ?line ok = complex_or_6({true,true}, <<1,2,3,4>>),
+ ?line ok = complex_or_6({false,false}, <<1,2,3,4>>),
+ ?line ok = complex_or_6({false,true}, <<1>>),
+ ?line ok = complex_or_6({true,false}, {1}),
+ ?line ok = complex_or_6({true,true}, {1}),
+
+ ?line error = complex_or_6({false,false}, {1}),
+
+ ?line error = complex_or_6({true}, {1,2,3,4}),
+ ?line error = complex_or_6({}, {1,2,3,4}),
+ ?line error = complex_or_6([], {1,2,3,4}),
+ ?line error = complex_or_6([], {1,2,3,4}),
+ ?line error = complex_or_6({true,false}, klurf),
+
+ ok.
+
+complex_or_1(A, B) ->
+ if
+ ((3 < tuple_size(A)) and (tuple_size(A) < 9)) or
+ ((2 < tuple_size(B)) and (tuple_size(B) < 7)) -> ok;
+ true -> error
+ end.
+
+complex_or_2(Tuple) ->
+ if
+ element(1, Tuple) or not (tuple_size(element(2, Tuple)) > 3) -> ok;
+ true -> error
+ end.
+
+complex_or_3(A, B) ->
+ if
+ not (size(B) > 3) or element(1, A) -> ok;
+ true -> error
+ end.
+
+complex_or_4(A, B) ->
+ if
+ not (is_tuple(A) and (size(A) > 3)) or element(1, B) -> ok;
+ true -> error
+ end.
+
+complex_or_5(A, B) ->
+ if
+ not (is_tuple(A) or (size(A) > 3)) or not element(1, B) -> ok;
+ true -> error
+ end.
+
+complex_or_6(A, B) ->
+ if
+ not (not element(1, A) and not element(2, A)) or
+ not (not (size(B) > 3)) -> ok;
+ true -> error
+ end.
+
+and_guard(Config) when is_list(Config) ->
+
+ %% 'and' combinations of literal true/false.
+
+ ?line check(fun() -> if true and false -> ok; true -> error end end, error),
+ ?line check(fun() -> if false and true -> ok; true -> error end end, error),
+ ?line check(fun() -> if true and true -> ok end end, ok),
+ ?line check(fun() -> if false and false -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if glurf and true -> ok; true -> error end end, error),
+ ?line check(fun() -> if true and glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if glurf and glurf -> ok; true -> error end end, error),
+
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if true and false -> ok;
+ false and true -> ok;
+ false and false -> ok
+ end),
+ exit
+ end, exit),
+
+ %% 'and' combinations of true/false in variables.
+
+ True = id(true),
+ False = id(false),
+
+ ?line check(fun() -> if True and False -> ok; true -> error end end, error),
+ ?line check(fun() -> if False and True -> ok; true -> error end end, error),
+ ?line check(fun() -> if True and True -> ok end end, ok),
+ ?line check(fun() -> if False and False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True and False -> ok;
+ False and True -> ok;
+ False and False -> ok
+ end),
+ exit
+ end, exit),
+
+ %% 'and' combinations of true/false and a non-boolean in variables.
+
+ Glurf = id(glurf),
+
+ ?line check(fun() -> if True and Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf and True -> ok; true -> error end end, error),
+ ?line check(fun() -> if True and True -> ok end end, ok),
+ ?line check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True and Glurf -> ok;
+ Glurf and True -> ok;
+ Glurf and Glurf -> ok
+ end),
+ exit
+ end, exit),
+
+ %% 'and' combinations of true/false with errors.
+ ATuple = id({a,b,c}),
+
+ ?line check(fun() -> if True and element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if element(42, ATuple) and True -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if True and True -> ok end end, ok),
+ ?line check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True and element(42, ATuple) -> ok;
+ element(42, ATuple) and True -> ok;
+ element(42, ATuple) and element(42, ATuple) -> ok
+ end),
+ exit
+ end, exit),
+
+ ?line ok = relprod({'Set',a,b}, {'Set',a,b}),
+
+ ok.
+
+relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set'), (erlang:size(R2) =:= 3) and (erlang:element(1,R2) =:= 'Set') ->
+ ok.
+
+
+xor_guard(Config) when is_list(Config) ->
+
+ %% 'xor' combinations of literal true/false.
+ ?line check(fun() -> if true xor false -> ok end end, ok),
+ ?line check(fun() -> if false xor true -> ok end end, ok),
+ ?line check(fun() -> if true xor true -> ok; true -> error end end, error),
+ ?line check(fun() -> if false xor false -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end),
+ exit
+ end, exit),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end),
+ exit
+ end, exit),
+
+
+ %% 'xor' combinations using variables containing true/false.
+
+ True = id(true),
+ False = id(false),
+
+ ?line check(fun() -> if True xor False -> ok end end, ok),
+ ?line check(fun() -> if False xor True -> ok end end, ok),
+ ?line check(fun() -> if True xor True -> ok; true -> error end end, error),
+ ?line check(fun() -> if False xor False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end),
+ exit
+ end, exit),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end),
+ exit
+ end, exit),
+
+ ok.
+
+more_xor_guards(Config) when is_list(Config) ->
+ True = id(true),
+ False = id(false),
+ ATuple = id({false,true,gurka}),
+
+ ?line check(fun() ->
+ if element(42, ATuple) xor False -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if False xor element(42, ATuple) xor False -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(18, ATuple) xor element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if True xor element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(42, ATuple) xor True -> ok;
+ true -> error end
+ end, error),
+ ok.
+
+build_in_guard(Config) when is_list(Config) ->
+ SubBin = <<5.0/float>>,
+ ?line B = <<1,SubBin/binary,3.5/float>>,
+ ?line if
+ B =:= <<1,SubBin/binary,3.5/float>> -> ok
+ end.
+
+old_guard_tests(Config) when list(Config) ->
+ %% Check that all the old guard tests are still recognized.
+ ?line list = og(Config),
+ ?line atom = og(an_atom),
+ ?line binary = og(<<1,2>>),
+ ?line float = og(3.14),
+ ?line integer = og(43),
+ ?line a_function = og(fun() -> ok end),
+ ?line pid = og(self()),
+ ?line reference = og(make_ref()),
+ ?line tuple = og({}),
+
+ ?line number = on(45.333),
+ ?line number = on(-19),
+ ok.
+
+og(V) when atom(V) -> atom;
+og(V) when binary(V) -> binary;
+og(V) when float(V) -> float;
+og(V) when integer(V) -> integer;
+og(V) when function(V) -> a_function;
+og(V) when list(V) -> list;
+og(V) when pid(V) -> pid;
+og(V) when port(V) -> port;
+og(V) when reference(V) -> reference;
+og(V) when tuple(V) -> tuple;
+og(_) -> what.
+
+on(V) when number(V) -> number;
+on(_) -> not_number.
+
+gbif(Config) when is_list(Config) ->
+ ?line error = gbif_1(1, {false,true}),
+ ?line ok = gbif_1(2, {false,true}),
+ ok.
+
+gbif_1(P, T) when element(P, T) -> ok;
+gbif_1(_, _) -> error.
+
+
+t_is_boolean(Config) when is_list(Config) ->
+ ?line true = is_boolean(true),
+ ?line true = is_boolean(false),
+ ?line true = is_boolean(id(true)),
+ ?line true = is_boolean(id(false)),
+
+ ?line false = is_boolean(glurf),
+ ?line false = is_boolean(id(glurf)),
+
+ ?line false = is_boolean([]),
+ ?line false = is_boolean(id([])),
+ ?line false = is_boolean(42),
+ ?line false = is_boolean(id(-42)),
+
+ ?line false = is_boolean(math:pi()),
+ ?line false = is_boolean(384793478934378924978439789873478934897),
+
+ ?line false = is_boolean(id(self())),
+ ?line false = is_boolean(id({x,y,z})),
+ ?line false = is_boolean(id([a,b,c])),
+ ?line false = is_boolean(id(make_ref())),
+ ?line false = is_boolean(id(<<1,2,3>>)),
+ ?line false = is_boolean({id(x),y,z}),
+ ?line false = is_boolean([id(a),b,c]),
+
+ ?line ok = bool(true),
+ ?line ok = bool(false),
+ ?line ok = bool(id(true)),
+ ?line ok = bool(id(false)),
+
+ ?line error = bool(glurf),
+ ?line error = bool(id(glurf)),
+
+ ?line error = bool([]),
+ ?line error = bool(id([])),
+ ?line error = bool(42),
+ ?line error = bool(id(-42)),
+
+ ?line error = bool(math:pi()),
+ ?line error = bool(384793478934378924978439789873478934897),
+
+ ?line error = bool(id(self())),
+ ?line error = bool(id({x,y,z})),
+ ?line error = bool(id([a,b,c])),
+ ?line error = bool(id(make_ref())),
+ ?line error = bool(id(<<1,2,3>>)),
+
+ ?line true = my_is_bool(true),
+ ?line true = my_is_bool(false),
+ ?line false = my_is_bool([]),
+ ?line false = my_is_bool([1,2,3,4]),
+ ?line false = my_is_bool({a,b,c}),
+
+ ok.
+
+bool(X) when is_boolean(X) -> ok;
+bool(_) -> error.
+
+my_is_bool(V) ->
+ Res = my_is_bool_a(V),
+ Res = my_is_bool_b(V).
+
+my_is_bool_a(V) ->
+ case V of
+ true -> true;
+ false -> true;
+ _ -> false
+ end.
+
+my_is_bool_b(V) ->
+ case V of
+ false -> true;
+ true -> true;
+ _ -> false
+ end.
+
+is_function_2(Config) when is_list(Config) ->
+ true = is_function(id(fun ?MODULE:all/1), 1),
+ true = is_function(id(fun() -> ok end), 0),
+ false = is_function(id(fun ?MODULE:all/1), 0),
+ false = is_function(id(fun() -> ok end), 1),
+
+ F = fun(_) -> ok end,
+ if
+ is_function(F, 1) -> ok
+ end.
+
+tricky(Config) when is_list(Config) ->
+ ?line not_ok = tricky_1(1, 2),
+ ?line not_ok = tricky_1(1, blurf),
+ ?line not_ok = tricky_1(foo, 2),
+ ?line not_ok = tricky_1(a, b),
+
+ ?line error = tricky_2(0.5),
+ ?line error = tricky_2(a),
+ ?line error = tricky_2({a,b,c}),
+
+ ?line false = rb(100000, [1], 42),
+ ?line true = rb(100000, [], 42),
+ ?line true = rb(555, [a,b,c], 19),
+ ok.
+
+tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok;
+tricky_1(_, _) -> not_ok.
+
+tricky_2(X) when float(X) or float(X) -> ok;
+tricky_2(_) -> error.
+
+%% From dets_v9:read_buckets/11, simplified.
+
+rb(Size, ToRead, SoFar) when SoFar + Size < 81920; ToRead == [] -> true;
+rb(_, _, _) -> false.
+
+
+-define(T(Op,A,B),
+ ok = if A Op B -> ok; true -> error end,
+ ok = if not (A Op B) -> error; true -> ok end,
+ (fun(X, Y, True, False) ->
+ ok = if X Op Y -> ok; true -> error end,
+ ok = if False; X Op Y; False -> ok; true -> error end,
+ ok = if X Op Y, True -> ok; true -> error end,
+ ok = if not (X Op Y) -> error; true -> ok end,
+ ok = if False; not (X Op Y); False -> error; true -> ok end
+ end)(id(A), id(B), id(true), id(false))).
+
+-define(F(Op,A,B),
+ ok = if A Op B -> error; true -> ok end,
+ ok = if not (A Op B) -> ok; true -> error end,
+ (fun(X, Y, True, False) ->
+ ok = if X Op Y -> error; true -> ok end,
+ ok = if False; X Op Y; False -> error; true -> ok end,
+ ok = if not (X Op Y); False -> ok; true -> error end,
+ ok = if not (X Op Y), True -> ok; true -> error end
+ end)(id(A), id(B), id(true), id(false))).
+
+
+rel_ops(Config) when is_list(Config) ->
+ ?line ?T(=/=, 1, 1.0),
+ ?line ?F(=/=, 2, 2),
+ ?line ?F(=/=, {a}, {a}),
+
+ ?line ?F(/=, a, a),
+ ?line ?F(/=, 0, 0.0),
+ ?line ?T(/=, 0, 1),
+ ?line ?F(/=, {a}, {a}),
+
+ ?line ?T(==, 1, 1.0),
+ ?line ?F(==, a, {}),
+
+ ?line ?F(=:=, 1, 1.0),
+ ?line ?T(=:=, 42.0, 42.0),
+
+ ?line ?F(>, a, b),
+ ?line ?T(>, 42, 1.0),
+ ?line ?F(>, 42, 42.0),
+
+ ?line ?T(<, a, b),
+ ?line ?F(<, 42, 1.0),
+ ?line ?F(<, 42, 42.0),
+
+ ?line ?T(=<, 1.5, 5),
+ ?line ?F(=<, -9, -100.344),
+ ?line ?T(=<, 42, 42.0),
+
+ ?line ?T(>=, 42, 42.0),
+ ?line ?F(>=, a, b),
+ ?line ?T(>=, 1.0, 0),
+
+ %% Coverage of beam_block:is_exact_eq_ok/1 and collect/1.
+ ?line true = any_atom /= id(42),
+ ?line true = [] /= id(42),
+
+ ok.
+
+-undef(TestOp).
+
+
+%% Test type tests on literal values. (From emulator test suites.)
+literal_type_tests(Config) when is_list(Config) ->
+ case ?MODULE of
+ guard_SUITE -> literal_type_tests_1(Config);
+ _ -> {skip,"Enough to run this case once."}
+ end.
+
+literal_type_tests_1(Config) ->
+ %% Generate an Erlang module with all different type of type tests.
+ ?line Tests = make_test([{T,L} || T <- type_tests(), L <- literals()] ++
+ [{is_function,L1,L2} ||
+ L1 <- literals(), L2 <- literals()]),
+ ?line Mod = literal_test,
+ ?line Func = {function, 0, test, 0, [{clause,0,[],[],Tests}]},
+ ?line Form = [{attribute,0,module,Mod},
+ {attribute,0,compile,export_all},
+ Func, {eof,0}],
+
+ %% Print generated code for inspection.
+ ?line lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form),
+
+ %% Test compile:form/1. This implies full optimization (default).
+ ?line {ok,Mod,Code1} = compile:forms(Form),
+ ?line smoke_disasm(Config, Mod, Code1),
+ ?line {module,Mod} = code:load_binary(Mod, Mod, Code1),
+ ?line Mod:test(),
+ ?line true = code:delete(Mod),
+ ?line code:purge(Mod),
+
+ %% Test compile:form/2. Turn off all optimizations.
+ ?line {ok,Mod,Code2} = compile:forms(Form, [binary,report,time,
+ no_copt,no_postopt]),
+ ?line smoke_disasm(Config, Mod, Code2),
+ ?line {module,Mod} = code:load_binary(Mod, Mod, Code2),
+ ?line Mod:test(),
+ ?line true = code:delete(Mod),
+ ?line code:purge(Mod),
+ ok.
+
+make_test([{T,L1,L2}|Ts]) ->
+ [test(T, L1, L2)|make_test(Ts)];
+make_test([{T,L}|Ts]) ->
+ [test(T, L)|make_test(Ts)];
+make_test([]) -> [].
+
+test(T, L) ->
+ S0 = io_lib:format("begin io:format(\"~~p~~n\", [{~p,~p}]), if ~w(~w) -> true; true -> false end end. ", [T,L,T,L]),
+ S = lists:flatten(S0),
+ {ok,Toks,_Line} = erl_scan:string(S),
+ {ok,E} = erl_parse:parse_exprs(Toks),
+ {value,Val,_Bs} = erl_eval:exprs(E, []),
+ {match,0,{atom,0,Val},hd(E)}.
+
+test(T, L1, L2) ->
+ S0 = io_lib:format("begin io:format(\"~~p~~n\", [{~p,~p,~p}]), if ~w(~w, ~w) -> true; true -> false end end. ", [T,L1,L2,T,L1,L2]),
+ S = lists:flatten(S0),
+ {ok,Toks,_Line} = erl_scan:string(S),
+ {ok,E} = erl_parse:parse_exprs(Toks),
+ {value,Val,_Bs} = erl_eval:exprs(E, []),
+ {match,0,{atom,0,Val},hd(E)}.
+
+smoke_disasm(Config, Mod, Bin) ->
+ Priv = ?config(priv_dir, Config),
+ File = filename:join(Priv, atom_to_list(Mod)++".beam"),
+ ok = file:write_file(File, Bin),
+ test_lib:smoke_disasm(File).
+
+literals() ->
+ [42,
+ 3.14,
+ -3,
+ 32982724987789283473473838474,
+ [],
+ xxxx,
+ {a,b,c},
+ [a,list],
+ <<1,2,3>>,
+ <<42:17>>].
+
+type_tests() ->
+ [is_boolean,
+ is_integer,
+ is_float,
+ is_number,
+ is_atom,
+ is_list,
+ is_tuple,
+ is_pid,
+ is_reference,
+ is_port,
+ is_binary,
+ is_function].
+
+basic_andalso_orelse(Config) when is_list(Config) ->
+ ?line T = id({type,integers,23,42}),
+ ?line 65 = if
+ ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
+ element(2, T)) == integers ->
+ element(3, T) + element(4, T);
+ true -> error
+ end,
+ ?line 65 = case [] of
+ [] when ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
+ element(2, T)) == integers ->
+ element(3, T) + element(4, T)
+ end,
+
+ ?line 42 = basic_rt({type,integers,40,2}),
+ ?line 5.0 = basic_rt({vector,{3.0,4.0}}),
+ ?line 20 = basic_rt(['+',3,7]),
+ ?line {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}),
+ ?line 12 = basic_rt({klurf,4}),
+
+ ?line error = basic_rt({type,integers,40,2,3}),
+ ?line error = basic_rt({kalle,integers,40,2}),
+ ?line error = basic_rt({kalle,integers,40,2}),
+ ?line error = basic_rt({1,2}),
+ ?line error = basic_rt([]),
+
+ RelProdBody =
+ fun(R1, R2) ->
+ if
+ (erlang:size(R1) =:= 3) andalso (erlang:element(1,R1) =:= 'Set'),
+ (erlang:size(R2) =:= 3) andalso (erlang:element(1,R2) =:= 'Set') ->
+ ok
+ end
+ end,
+
+ ?line ok = RelProdBody({'Set',a,b}, {'Set',a,b}),
+
+ %% 'andalso'/'orelse' with calls known to fail already at compile time.
+ %% Used to crash the code generator.
+ error = (fun() ->
+ R = {vars,true},
+ if
+ is_record(R, vars, 2) andalso element(99, R) -> ok;
+ true -> error
+ end
+ end)(),
+ error = (fun(X) ->
+ L = {a,b,c},
+ if
+ is_list(X) andalso length(L) > 4 -> ok;
+ true -> error
+ end
+ end)([]),
+ ok.
+
+basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 4 andalso element(1, T) =:= type andalso
+ element(2, T) == integers ->
+ element(3, T) + element(4, T);
+basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= vector ->
+ {X,Y} = element(2, T),
+ if
+ is_float(X), is_float(Y) ->
+ math:sqrt(X*X+Y*Y)
+ end;
+basic_rt(['+',A,B]) ->
+ 2*id(A+B);
+basic_rt({R1,R2}) when erlang:size(R1) =:= 3 andalso erlang:element(1,R1) =:= 'Set',
+ erlang:size(R2) =:= 3 andalso erlang:element(1,R2) =:= 'Set' ->
+ R1 = id(R1),
+ R2 = id(R2),
+ R1;
+basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= klurf ->
+ 3*id(element(2, T));
+basic_rt(_) ->
+ error.
+
+traverse_dcd(Config) when is_list(Config) ->
+ L0 = [{log_header,dcd_log,"1.0",a,b,c},{log_header,dcd_log,"2.0",a,b,c},
+ {log_header,dcd_log,"0.0",a,b,c},blurf],
+ {cont,[{log_header,dcd_log,"0.0",a,b,c},blurf],log,funny} =
+ traverse_dcd({cont,L0}, log, funny),
+ L1 = [{log_header,dcd_log,"1.0"}],
+ {cont,L1,log,funny} = traverse_dcd({cont,L1}, log, funny),
+ L2 = [{a,tuple}],
+ {cont,L2,log,funny} = traverse_dcd({cont,L2}, log, funny),
+ ok.
+
+%% The function starts out with 3 arguments in {x,0}, {x,1}, {x,2}.
+%% The outer match of a two tuple will places the first element in {x,3} and
+%% second in {x,4}. The guard for the first clause must make ensure that all of those
+%% registers are restored before entering the second clause.
+%%
+%% (From mnesia_checkpoint.erl, modified.)
+
+traverse_dcd({Cont,[LogH|Rest]},Log,Fun)
+ when is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header
+andalso erlang:element(2,LogH) == dcd_log,
+is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header
+andalso erlang:element(3,LogH) >= "1.0" ->
+ traverse_dcd({Cont,Rest},Log,Fun);
+traverse_dcd({Cont,Recs},Log,Fun) ->
+ {Cont,Recs,Log,Fun}.
+
+
+check_qlc_hrl(Config) when is_list(Config) ->
+ St = {r1,false,dum},
+ ?line foo = cqlc(qlc, q, [{lc,1,2,3}], St),
+ ?line foo = cqlc(qlc, q, [{lc,1,2,3},b], St),
+ ?line St = cqlc(qlc, q, [], St),
+ ?line St = cqlc(qlc, blurf, [{lc,1,2,3},b], St),
+ ?line St = cqlc(q, q, [{lc,1,2,3},b], St),
+ ?line St = cqlc(qlc, q, [{lc,1,2,3},b,c], St),
+ ?line St = cqlc(qlc, q, [a,b], St),
+ ?line {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}),
+ ok.
+
+%% From erl_lint.erl; original name was check_qlc_hrl/4.
+cqlc(M, F, As, St) ->
+ Arity = length(As),
+ case As of
+ [{lc,_L,_E,_Qs}|_] when M =:= qlc, F =:= q,
+ Arity < 3,
+ not (((element(1, St) =:= r1) orelse fail) and (tuple_size(St) =:= 3) and element(2, St)) ->
+ foo;
+ _ ->
+ St
+ end.
+
+%% OTP-7679: Thanks to Hunter Morris.
+andalso_semi(Config) when is_list(Config) ->
+ ?line ok = andalso_semi_foo(0),
+ ?line ok = andalso_semi_foo(1),
+ ?line {'EXIT',{function_clause,_}} = (catch andalso_semi_foo(2)),
+
+ ?line ok = andalso_semi_bar([a,b,c]),
+ ?line ok = andalso_semi_bar(1),
+ ?line {'EXIT',{function_clause,_}} = (catch andalso_semi_bar([a,b])),
+ ok.
+
+andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 ->
+ ok.
+
+andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 ->
+ ok.
+
+
+tuple_size(Config) when is_list(Config) ->
+ ?line 10 = do_tuple_size({1,2,3,4}),
+ ?line {'EXIT',{function_clause,_}} = (catch do_tuple_size({1,2,3})),
+ ?line {'EXIT',{function_clause,_}} = (catch do_tuple_size(42)),
+
+ ?line error = ludicrous_tuple_size({a,b,c}),
+ ?line error = ludicrous_tuple_size([a,b,c]),
+
+ %% Test the "unsafe case" - the register assigned the tuple size is
+ %% not killed.
+ ?line DataDir = test_lib:get_data_dir(Config),
+ ?line File = filename:join(DataDir, "guard_SUITE_tuple_size"),
+ ?line {ok,Mod,Code} = compile:file(File, [from_asm,binary]),
+ ?line code:load_binary(Mod, File, Code),
+ ?line 14 = Mod:t({1,2,3,4}),
+
+ ok.
+
+do_tuple_size(T) when tuple_size(T) =:= 4 ->
+ {A,B,C,D} = T,
+ A+B+C+D.
+
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= 16#7777777777777777777777777777777777 -> ok;
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= 16#10000000000000000 -> ok;
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= (1 bsl 64) - 1 -> ok;
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= 16#FFFFFFFFFFFFFFFF -> ok;
+ludicrous_tuple_size(_) -> error.
+
+
+%% Call this function to turn off constant propagation.
+id(I) -> I.
+
+check(F, Result) ->
+ case F() of
+ Result -> ok;
+ Other ->
+ io:format("Expected: ~p\n", [Result]),
+ io:format(" Got: ~p\n", [Other]),
+ test_server:fail()
+ end.
diff --git a/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S b/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S
new file mode 100644
index 0000000000..c0bf04ed8f
--- /dev/null
+++ b/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S
@@ -0,0 +1,30 @@
+{module, guard_SUITE_tuple_size}. %% version = 0
+
+{exports, [{t,1}]}.
+
+{attributes, []}.
+
+{labels, 5}.
+
+
+{function, t, 1, 2}.
+ {label,1}.
+ {func_info,{atom,guard_SUITE_tuple_size},{atom,t},1}.
+ {label,2}.
+ {bif,tuple_size,{f,4},[{x,0}],{x,1}}.
+ {test,is_eq_exact,{f,4},[{x,1},{integer,4}]}.
+ {test,is_tuple,{f,3},[{x,0}]}.
+ {test,test_arity,{f,3},[{x,0},4]}.
+ {get_tuple_element,{x,0},0,{x,5}}.
+ {get_tuple_element,{x,0},1,{x,2}}.
+ {get_tuple_element,{x,0},2,{x,3}}.
+ {get_tuple_element,{x,0},3,{x,4}}.
+ {gc_bif,'+',{f,0},5,[{x,1},{x,2}],{x,0}}.
+ {gc_bif,'+',{f,0},5,[{x,0},{x,3}],{x,0}}.
+ {gc_bif,'+',{f,0},5,[{x,0},{x,4}],{x,0}}.
+ {gc_bif,'+',{f,0},5,[{x,0},{x,5}],{x,0}}.
+ return.
+ {label,3}.
+ {badmatch,{x,0}}.
+ {label,4}.
+ {jump,{f,1}}.
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
new file mode 100644
index 0000000000..396fb450b7
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -0,0 +1,280 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%% Purpose : Tests inlining.
+
+-module(inline_SUITE).
+
+-include("test_server.hrl").
+
+-compile(export_all).
+-compile({inline,[badarg/2]}).
+
+%% Needed by test case `lists'.
+-compile(inline_list_funcs).
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [attribute,bsdecode,bsdes,barnes2,decode1,smith,itracer,pseudoknot,lists,
+ really_inlined,otp_7223,coverage].
+
+attribute(Config) when is_list(Config) ->
+ Name = "attribute",
+ ?line Src = filename:join(?config(data_dir, Config), Name),
+ ?line Out = ?config(priv_dir,Config),
+
+ ?line {ok,attribute=Mod} = compile:file(Src, [{outdir,Out},report,time]),
+ ?line Outfile = filename:join(Out, Name++".beam"),
+ ?line {ok,{Mod,[{locals,Locals}]}} = beam_lib:chunks(Outfile, [locals]),
+ ?line io:format("locals: ~p\n", [Locals]),
+
+ %% The inliner should have removed all local functions.
+ ?line [] = Locals,
+
+ ok.
+
+-define(comp(Name),
+ Name(Config) when list(Config) ->
+ try_inline(Name, Config)).
+
+?comp(bsdecode).
+?comp(bsdes).
+?comp(barnes2).
+?comp(decode1).
+?comp(smith).
+?comp(itracer).
+?comp(pseudoknot).
+
+try_inline(Mod, Config) ->
+ ?line Src = filename:join(?config(data_dir, Config), atom_to_list(Mod)),
+ ?line Out = ?config(priv_dir,Config),
+
+ %% Normal compilation.
+ ?line io:format("Compiling: ~s\n", [Src]),
+ ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,clint]),
+
+ ?line Dog = test_server:timetrap(test_server:minutes(10)),
+ ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
+ ?line {ok,Node} = start_node(compiler, Pa),
+ ?line NormalResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
+ ?line test_server:timetrap_cancel(Dog),
+
+ %% Inlining.
+ ?line io:format("Compiling with old inliner: ~s\n", [Src]),
+ ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,
+ {inline,1000},clint]),
+
+ %% Run inlined code.
+ ?line Dog3 = test_server:timetrap(test_server:minutes(10)),
+ ?line OldInlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
+ ?line test_server:timetrap_cancel(Dog3),
+
+ %% Compare results.
+ ?line compare(NormalResult, OldInlinedResult),
+ ?line NormalResult = OldInlinedResult,
+
+ %% Inlining.
+ ?line io:format("Compiling with new inliner: ~s\n", [Src]),
+ ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,
+ bin_opt_info,inline,clint]),
+
+ %% Run inlined code.
+ ?line Dog4 = test_server:timetrap(test_server:minutes(10)),
+ ?line InlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
+ ?line test_server:timetrap_cancel(Dog4),
+
+ %% Compare results.
+ ?line compare(NormalResult, InlinedResult),
+ ?line NormalResult = InlinedResult,
+
+ %% Delete Beam file.
+ ?line ok = file:delete(filename:join(Out, atom_to_list(Mod)++code:objfile_extension())),
+
+ ?line ?t:stop_node(Node),
+ ok.
+
+compare(Same, Same) -> ok;
+compare([Same|T1], [Same|T2]) ->
+ compare(T1, T2);
+compare([{X,Y,RGB1}|T1], [{X,Y,RGB2}|T2]) ->
+ io:format("X = ~p, Y = ~p, RGB normal = ~p, RGB inlined ~p\n", [X,Y,RGB1,RGB2]),
+ compare(T1, T2);
+compare([H1|_], [H2|_]) ->
+ io:format("Normal = ~p, Inlined = ~p\n", [H1,H2]),
+ ?t:fail();
+compare([], []) -> ok.
+
+start_node(Name, Args) ->
+ case test_server:start_node(Name, slave, [{args,Args}]) of
+ {ok,Node} -> {ok, Node};
+ Error -> ?line test_server:fail(Error)
+ end.
+
+load_and_call(Out, Module) ->
+ ?line io:format("Loading...\n",[]),
+ ?line code:purge(Module),
+ ?line LoadRc = code:load_abs(filename:join(Out, Module)),
+ ?line {module,Module} = LoadRc,
+
+ ?line io:format("Calling...\n",[]),
+ ?line {Time,CallResult} = timer:tc(Module, Module, []),
+ ?line io:format("Time: ~p\n", [Time]),
+ CallResult.
+
+%% Macros used by lists/1 below.
+
+-define(TestHighOrder_2(Name, Body, List),
+ begin
+ put(?MODULE, []),
+ (fun({Res,Res2}) ->
+ {Res,Res2} = my_apply(lists, Name, [Body,List], [])
+ end)(begin
+ (fun(R) ->
+ {R,get(?MODULE)}
+ end)(lists:Name(Body, List))
+ end)
+ end).
+
+-define(TestHighOrder_3(Name, Body, Init, List),
+ begin
+ put(?MODULE, []),
+ (fun({Res,Res2}) ->
+ {Res,Res2} = my_apply(lists, Name, [Body,Init,List], [])
+ end)(begin
+ (fun(R) ->
+ {R,get(?MODULE)}
+ end)(lists:Name(Body, Init, List))
+ end)
+ end).
+
+%% For each high order function in the lists module, verify
+%% that the inlined version produces the same result and is evaluated
+%% in the same order as the function in the lists module.
+%%
+%% Note: This module must be compiled with the inline_lists_funcs option.
+
+lists(Config) when is_list(Config) ->
+ ?line List = lists:seq(1, 20),
+
+ %% lists:map/2
+ ?line ?TestHighOrder_2(map, (fun(E) ->
+ R = E band 16#ff,
+ put(?MODULE, [E|get(?MODULE)]),
+ R
+ end), List),
+
+ %% lists:flatmap/2
+ ?line ?TestHighOrder_2(flatmap, (fun(E) ->
+ R = lists:duplicate(E, E),
+ put(?MODULE, [E|get(?MODULE)]),
+ R
+ end), List),
+
+ %% lists:foreach/2
+ ?line ?TestHighOrder_2(foreach,
+ (fun(E) ->
+ put(?MODULE, [E bor 7|get(?MODULE)])
+ end), List),
+
+ %% lists:filter/2
+ ?line ?TestHighOrder_2(filter, (fun(E) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ (E bsr 1) band 1 =/= 0
+ end), List),
+
+ %% lists:any/2
+ ?line ?TestHighOrder_2(any, (fun(E) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ false %Force it to go through all.
+ end), List),
+
+ %% lists:all/2
+ ?line ?TestHighOrder_2(all, (fun(E) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ true %Force it to go through all.
+ end), List),
+
+ %% lists:foldl/3
+ ?line ?TestHighOrder_3(foldl, (fun(E, A) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ A bxor E
+ end), 0, List),
+
+ %% lists:foldr/3
+ ?line ?TestHighOrder_3(foldr, (fun(E, A) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ A bxor (bnot E)
+ end), 0, List),
+
+ %% lists:mapfoldl/3
+ ?line ?TestHighOrder_3(mapfoldl, (fun(E, A) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ {bnot E,A bxor (bnot E)}
+ end), 0, List),
+
+ %% lists:mapfoldr/3
+ ?line ?TestHighOrder_3(mapfoldr, (fun(E, A) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ {bnot E,A bxor (bnot E)}
+ end), 0, List),
+
+ %% Cleanup.
+ erase(?MODULE),
+ ok.
+
+my_apply(M, F, A, Init) ->
+ put(?MODULE, Init),
+ Res = apply(M, F, A),
+ {Res,get(?MODULE)}.
+
+really_inlined(Config) when is_list(Config) ->
+ %% Make sure that badarg/2 really gets inlined.
+ {'EXIT',{badarg,[{?MODULE,fail_me_now,[]}|_]}} = (catch fail_me_now()),
+ ok.
+
+fail_me_now() ->
+ badarg(foo(bar), []).
+
+foo(_X) ->
+ badarg.
+
+%% Inlined.
+badarg(badarg, A) ->
+ erlang:error(badarg, A);
+badarg(Reply, _A) ->
+ Reply.
+
+otp_7223(Config) when is_list(Config) ->
+ ?line {'EXIT', {{case_clause,{1}},_}} = (catch otp_7223_1(1)),
+ ok.
+
+-compile({inline,[{otp_7223_1,1}]}).
+otp_7223_1(X) ->
+ otp_7223_2(X).
+
+-compile({inline,[{otp_7223_2,1}]}).
+otp_7223_2({a}) ->
+ 1.
+
+coverage(Config) when is_list(Config) ->
+ ?line Src = filename:join(?config(data_dir, Config), bsdecode),
+ ?line Out = ?config(priv_dir,Config),
+ ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,{inline,0},clint]),
+ ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,{inline,20},verbose,clint]),
+ ?line ok = file:delete(filename:join(Out, "bsdecode"++code:objfile_extension())),
+ ok.
diff --git a/lib/compiler/test/inline_SUITE_data/attribute.erl b/lib/compiler/test/inline_SUITE_data/attribute.erl
new file mode 100644
index 0000000000..961086a888
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/attribute.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(attribute).
+-export([test/1]).
+-compile(inline).
+
+%% If -compile(inline) above is recognized, the local function add/2
+%% will not be present in the Beam file.
+
+test(X) -> add(X, 2).
+
+add(X, Y) -> X+Y.
+
+
+
diff --git a/lib/compiler/test/inline_SUITE_data/barnes2.erl b/lib/compiler/test/inline_SUITE_data/barnes2.erl
new file mode 100644
index 0000000000..a986331060
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/barnes2.erl
@@ -0,0 +1,160 @@
+% file: "barnes.erl"
+
+-module(barnes2).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ Stars = create_scenario(1000, 1.0),
+ R = hd(loop(10,1000.0,Stars,0)),
+ Str = lists:flatten(io:lib_format("~s", [R])),
+ {R,Str =:= {1.00000,-1.92269e+4,-1.92269e+4,2.86459e-2,2.86459e-2}}.
+
+create_scenario(N, M) ->
+ create_scenario0(0, 0, trunc(math:sqrt(N)), M).
+
+create_scenario0(_X, _SN, _SN, _M) ->
+ [];
+create_scenario0(SN, Y, SN, M) ->
+ create_scenario0(0, Y+1, SN, M);
+create_scenario0(X, Y, SN, M) ->
+ XPos0 = (((20000.0 * 2) / SN) * X) - 20000.0,
+ YPos0 = (((20000.0 * 2) / SN) * Y) - 20000.0,
+ Calibrate = ((20000.0 * 2) / SN) / 2,
+ XPos = XPos0 + Calibrate,
+ YPos = YPos0 + Calibrate,
+ [{M, XPos, YPos, 0.0, 0.0} | create_scenario0(X+1, Y, SN, M)].
+
+relpos_to_quadrant(DX, DY) when DX >= 0 ->
+ if
+ DY >= 0 -> 0;
+ true -> 3
+ end;
+relpos_to_quadrant(_, DY) ->
+ if
+ DY >= 0 -> 1;
+ true -> 2
+ end.
+
+quadrant_to_dx(0, D) -> D;
+quadrant_to_dx(1, D) -> -D;
+quadrant_to_dx(2, D) -> -D;
+quadrant_to_dx(3, D) -> D.
+
+quadrant_to_dy(Q,D) ->
+ if
+ Q < 2 -> D;
+ true -> -D
+ end.
+
+create_tree(Stars) ->
+ create_tree0(Stars, empty).
+
+create_tree0([],Tree) ->
+ Tree;
+create_tree0([{M,X,Y,_,_} | Stars], Tree) ->
+ create_tree0(Stars, insert_tree_element(Tree, M, X, Y, 0.0, 0.0, 20000.0)).
+
+insert_tree_element(empty, M, X, Y, _OX, _OY, _D) ->
+ {body,M,X,Y};
+insert_tree_element({branch,M0,SubTree}, M, X, Y, OX, OY, D) ->
+ Q = relpos_to_quadrant(X-OX,Y-OY),
+ D2 = D / 2,
+ DX = quadrant_to_dx(Q,D2),
+ DY = quadrant_to_dy(Q,D2),
+ {branch,M0+M,setelement(Q+1,SubTree,
+ insert_tree_element(element(Q+1,SubTree),
+ M, X, Y, OX+DX, OY+DY,D2))};
+insert_tree_element({body,M0,X0,Y0},M,X,Y,OX,OY,D) ->
+ resolve_body_conflict(M,X,Y,M0,X0,Y0,OX,OY,D).
+
+resolve_body_conflict(M0, X0, Y0, M1, X1, Y1, OX, OY, D) ->
+ T = {empty,empty,empty,empty},
+ Q0 = relpos_to_quadrant(X0-OX,Y0-OY),
+ Q1 = relpos_to_quadrant(X1-OX,Y1-OY),
+ D2 = D / 2,
+ if
+ Q0 == Q1 -> DX = quadrant_to_dx(Q0,D2),
+ DY = quadrant_to_dy(Q1,D2),
+ {branch,M0+M1,setelement(Q0+1,T,
+ resolve_body_conflict(M0,X0,Y0,
+ M1,X1,Y1,
+ OX+DX,OY+DY,
+ D2))} ;
+ true -> {branch,M0+M1, setelement(Q1+1,
+ setelement(Q0+1,T,{body,M0,X0,Y0}),
+ {body,M1,X1,Y1})}
+ end.
+
+compute_acceleration(empty, _, _, _, _, _,L) ->
+ {{0.0, 0.0},L+1};
+compute_acceleration({body,BM,BX,BY}, _D, _OX, _OY, X, Y,L) ->
+ DX = BX - X,
+ DY = BY - Y,
+ R2 = (DX * DX) + (DY * DY),
+ Divisor = R2 * math:sqrt(R2),
+ if
+ Divisor < 0.000001 -> % was: Divisor < ?EPSILON ->
+ {{0.0, 0.0},L+1};
+ true ->
+ Expr = BM / Divisor,
+ {{DX * Expr, DY * Expr},L+1}
+ end;
+compute_acceleration({branch,M,SubTree}, D, OX, OY, X, Y,L) ->
+ DX = OX - X,
+ DY = OY - Y,
+ R2 = (DX * DX) + (DY * DY),
+ DD = D*D,
+ R2_THETA2 = 0.09 * R2, % TRY 2.0 *R2, !!! was: R2_THETA2 = ?THETA2*R2,
+ if
+ % Ok to approximate?
+ DD < R2_THETA2 ->
+ Divisor = R2 * math:sqrt(R2),
+ if
+ Divisor < 0.000001 ->
+ {{0.0,0.0},L};
+ true ->
+ Expr = M / Divisor,
+ {{DX*Expr, DY*Expr},L+1}
+ end;
+ % Not ok to approximate...
+ true ->
+ D2 = D / 2,
+ {{AX0, AY0},L1} = compute_acceleration(element(1,SubTree),
+ D2, OX + quadrant_to_dx(0,D2),
+ OY + quadrant_to_dy(0,D2),X,Y,L),
+ {{AX1, AY1},L2} = compute_acceleration(element(2,SubTree),
+ D2, OX + quadrant_to_dx(1,D2),
+ OY + quadrant_to_dy(1,D2),X,Y,L1),
+ {{AX2, AY2},L3} = compute_acceleration(element(3,SubTree),
+ D2,OX + quadrant_to_dx(2,D2),
+ OY + quadrant_to_dy(2,D2),X,Y,L2),
+ {{AX3, AY3},L4} = compute_acceleration(element(4,SubTree),
+ D2, OX + quadrant_to_dx(3,D2),
+ OY + quadrant_to_dy(3,D2),X,Y,L3),
+ {{AX0+AX1+AX2+AX3, AY0+AY1+AY2+AY3},L4+1}
+ end.
+
+compute_star_accelerations(_Tree,[],L) ->
+ {[],L};
+compute_star_accelerations(Tree,[{_,X, Y,_,_}|Stars],L) ->
+ {A,AL} = compute_acceleration(Tree, 20000.0, 0.0, 0.0, X, Y,L),
+ {B,BL} = compute_star_accelerations(Tree, Stars,AL),
+ {[A | B],BL}.
+
+compute_next_state([],_,_) ->
+ [];
+compute_next_state([{M,X,Y,VX,VY}|Stars],[{AX,AY}|Accs],Time) ->
+ VX0 = VX + (AX * Time),
+ VY0 = VY + (AY * Time),
+ [{M,X+(VX*Time),Y+(VY*Time),VX0,VY0} | compute_next_state(Stars,Accs,Time)].
+
+advance_time(Time,Stars,L) ->
+ Tree = create_tree(Stars),
+ {Acc,NL} = compute_star_accelerations(Tree, Stars,L),
+ {compute_next_state(Stars, Acc, Time),NL}.
+
+loop(0,_Time,Stars,_L) ->
+ Stars;
+loop(N,Time,Stars,L) ->
+ {NS,NL} = advance_time(Time,Stars,L),
+ loop(N-1,Time,NS,NL).
diff --git a/lib/compiler/test/inline_SUITE_data/bsdecode.erl b/lib/compiler/test/inline_SUITE_data/bsdecode.erl
new file mode 100644
index 0000000000..ae134ad02e
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/bsdecode.erl
@@ -0,0 +1,1188 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bsdecode).
+-export([?MODULE/0]).
+
+-record(protocolErrors, {invalidManIE = false,
+ outOfSequence = false,
+ incorrectOptIE = false}).
+
+-record(mvsT_msisdn, {value}).
+
+
+-record(mvsgT_pdpAddressType, {pdpTypeNbr,
+ address}).
+
+-record(mvsgT_ipAddress, {version,
+ a1,
+ a2,
+ a3,
+ a4,
+ a5,
+ a6,
+ a7,
+ a8}).
+
+-record(mvsgT_imsi, {value}).
+
+-record(mvsgT_tid, {imsi,
+ nsapi}).
+
+-record(sesT_qualityOfServiceV0, {delayClass,
+ reliabilityClass,
+ peakThroughput,
+ precedenceClass,
+ meanThroughput}).
+
+-record(sesT_deleteReqV0, {tid}).
+
+-record(sesT_deleteResV0, {tid,
+ cause}).
+
+-record(sesT_createReqV0, {tid,
+ tidRaw,
+ qos,
+ recovery,
+ selMode,
+ flowLblData,
+ flowLblSig,
+ endUserAdd,
+ accPointName,
+ protConOpt,
+ sgsnAddSig,
+ sgsnAddUser,
+ msisdn}).
+
+-record(sesT_updateReqV0, {tid,
+ tidRaw,
+ qos,
+ recovery,
+ flowLblData,
+ flowLblSig,
+ sgsnAddSig,
+ sgsnAddUser}).
+
+-record(masT_ipcpData, {type,
+ ipAddress,
+ rawMessage}).
+
+-record(masT_ipcp, {exists,
+ code,
+ id,
+ ipcpList}).
+
+-record(masT_pap, {exists,
+ code,
+ id,
+ username,
+ password}).
+
+-record(masT_chap, {code,
+ id,
+ value,
+ name}).
+
+-record(masT_protocolConfigOptions, {chap,
+ pap,
+ ipcp}).
+
+?MODULE() ->
+ Res = test(),
+ {Res,Res =:=
+ {ok,{sesT_createReqV0,{mvsgT_tid,{mvsgT_imsi,<<81,67,101,7,0,0,0,240>>},6},
+ [81,67,101,7,0,0,0,96],
+ {sesT_qualityOfServiceV0,1,4,9,2,18},0,
+ subscribed,0,0,{mvsgT_pdpAddressType,ietf_ipv4,[]},
+ [<<97,112,110,48,49,51,97>>,<<101,114,105,99,115,115,111,110>>,<<115,101>>],
+ {masT_protocolConfigOptions,[],
+ {masT_pap,true,1,5,[117,115,101,114,53],[112,97,115,115,53]},[]},
+ {mvsgT_ipAddress,ipv4,172,28,12,1,0,0,0,0},
+ {mvsgT_ipAddress,ipv4,172,28,12,3,0,0,0,0},
+ {mvsT_msisdn,<<145,148,113,129,0,0,0,0>>}},1}}.
+
+test() ->
+ Pdu = <<30,
+ 16,
+ 0,
+ 90,
+ 0,
+ 1,
+ 0,
+ 0,
+ 255,
+ 255,
+ 255,
+ 255,
+ 81,
+ 67,
+ 101,
+ 7,
+ 0,
+ 0,
+ 0,
+ 96,
+ 6,
+ 12,
+ 146,
+ 18,
+ 14,
+ 0,
+ 15,
+ 252,
+ 16,
+ 0,
+ 0,
+ 17,
+ 0,
+ 0,
+ 128,
+ 0,
+ 2,
+ 241,
+ 33,
+ 131,
+ 0,
+ 20,
+ 7,
+ 97,
+ 112,
+ 110,
+ 48,
+ 49,
+ 51,
+ 97,
+ 8,
+ 101,
+ 114,
+ 105,
+ 99,
+ 115,
+ 115,
+ 111,
+ 110,
+ 2,
+ 115,
+ 101,
+ 132,
+ 0,
+ 20,
+ 128,
+ 192,
+ 35,
+ 16,
+ 1,
+ 5,
+ 0,
+ 16,
+ 5,
+ 117,
+ 115,
+ 101,
+ 114,
+ 53,
+ 5,
+ 112,
+ 97,
+ 115,
+ 115,
+ 53,
+ 133,
+ 0,
+ 4,
+ 172,
+ 28,
+ 12,
+ 1,
+ 133,
+ 0,
+ 4,
+ 172,
+ 28,
+ 12,
+ 3,
+ 134,
+ 0,
+ 8,
+ 145,
+ 148,
+ 113,
+ 129,
+ 0,
+ 0,
+ 0,
+ 0>>,
+ decode_v0_opt(10,Pdu).
+
+decode_v0_opt(0,Pdu) ->
+ decode_gtpc_msg(Pdu);
+decode_v0_opt(N,Pdu) ->
+ decode_gtpc_msg(Pdu),
+ decode_v0_opt(N - 1,Pdu).
+
+decode_gtpc_msg(<<0:3,
+ _:4,
+ 0:1,
+ 16:8,
+ _Length:16,
+ SequenceNumber:16,
+ _FlowLabel:16,
+ _SNDCP_N_PDU_Number:8,
+ _:3/binary-unit:8,
+ TID:8/binary-unit:8,
+ InformationElements/binary>>) ->
+ Errors = #protocolErrors{},
+ {ok,TID2} = tid_internal_storage(TID,[]),
+ EmptyCreateReq = #sesT_createReqV0{tid = TID2,
+ tidRaw = binary_to_list(TID)},
+ case catch decode_ie_create(InformationElements,0,Errors,EmptyCreateReq) of
+ {ok,CreateReq} ->
+ {ok,CreateReq,SequenceNumber};
+ {fault,Cause,CreateReq} ->
+ {fault,Cause,CreateReq,SequenceNumber};
+ {'EXIT',_Reason} ->
+ {fault,193,EmptyCreateReq,SequenceNumber}
+ end;
+decode_gtpc_msg(<<0:3,
+ _:4,
+ 0:1,
+ 18:8,
+ _Length:16,
+ SequenceNumber:16,
+ _FlowLabel:16,
+ _SNDCP_N_PDU_Number:8,
+ _:3/binary-unit:8,
+ TID:8/binary-unit:8,
+ InformationElements/binary>>) ->
+ io:format("hej",[]),
+ Errors = #protocolErrors{},
+ {ok,TID2} = tid_internal_storage(TID,[]),
+ EmptyUpdateReq = #sesT_updateReqV0{tid = TID2,
+ tidRaw = binary_to_list(TID)},
+ case catch decode_ie_update(InformationElements,0,Errors,EmptyUpdateReq) of
+ {ok,UpdateReq} ->
+ {ok,UpdateReq,SequenceNumber};
+ {fault,Cause,UpdateReq} ->
+ {fault,Cause,UpdateReq,SequenceNumber};
+ {'EXIT',Reason} ->
+ io:format("hej",[]),
+ {fault,193,EmptyUpdateReq,SequenceNumber,Reason}
+ end;
+decode_gtpc_msg(<<0:3,
+ _:4,
+ 0:1,
+ 20:8,
+ _Length:16,
+ SequenceNumber:16,
+ _FlowLabel:16,
+ _SNDCP_N_PDU_Number:8,
+ _:3/binary-unit:8,
+ TID:8/binary-unit:8,
+ _InformationElements/binary>>) ->
+ {ok,TID2} = tid_internal_storage(TID,[]),
+ DeleteReq = #sesT_deleteReqV0{tid = TID2},
+ {ok,DeleteReq,SequenceNumber};
+decode_gtpc_msg(<<0:3,
+ _:4,
+ 0:1,
+ 21:8,
+ _Length:16,
+ SequenceNumber:16,
+ _FlowLabel:16,
+ _SNDCP_N_PDU_Number:8,
+ _:3/binary-unit:8,
+ TID:8/binary-unit:8,
+ InformationElements/binary>>) ->
+ Errors = #protocolErrors{},
+ {ok,TID2} = tid_internal_storage(TID,[]),
+ EmptyDeleteRes = #sesT_deleteResV0{tid = TID2},
+ case catch decode_ie_delete_res(InformationElements,0,Errors,EmptyDeleteRes) of
+ {ok,DeleteRes} ->
+ {ok,DeleteRes,SequenceNumber};
+ {fault,Cause,DeleteRes} ->
+ {fault,Cause,DeleteRes,SequenceNumber};
+ {'EXIT',_Reason} ->
+ {fault,193,EmptyDeleteRes,SequenceNumber}
+ end;
+decode_gtpc_msg(_GTP_C_Message) ->
+ {fault}.
+
+decode_ie_create(<<>>,PresentIEs,Errors,CreateReq) ->
+ if
+ PresentIEs band 1917 /= 1917 ->
+ {fault,202,CreateReq};
+ true ->
+ case Errors of
+ #protocolErrors{invalidManIE = true} ->
+ {fault,201,CreateReq};
+ #protocolErrors{outOfSequence = true} ->
+ {fault,193,CreateReq};
+ #protocolErrors{incorrectOptIE = true} ->
+ {fault,203,CreateReq};
+ _ ->
+ {ok,CreateReq}
+ end
+ end;
+decode_ie_create(<<6:8,
+ QoSElement:3/binary-unit:8,
+ Rest/binary>>,PresentIEs,Errors,CreateReq) ->
+ if
+ PresentIEs band 1 == 1 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 1 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ <<_:2,
+ DelayClass:3,
+ ReliabilityClass:3,
+ PeakThroughput:4,
+ _:1,
+ PrecedenceClass:3,
+ _:3,
+ MeanThroughput:5>> = QoSElement,
+ QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass,
+ reliabilityClass = ReliabilityClass,
+ peakThroughput = PeakThroughput,
+ precedenceClass = PrecedenceClass,
+ meanThroughput = MeanThroughput},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{qos = QoS},
+ decode_ie_create(Rest,PresentIEs bor 1,UpdatedErrors,UpdatedCreateReq);
+ true ->
+ <<_:2,
+ DelayClass:3,
+ ReliabilityClass:3,
+ PeakThroughput:4,
+ _:1,
+ PrecedenceClass:3,
+ _:3,
+ MeanThroughput:5>> = QoSElement,
+ QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass,
+ reliabilityClass = ReliabilityClass,
+ peakThroughput = PeakThroughput,
+ precedenceClass = PrecedenceClass,
+ meanThroughput = MeanThroughput},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{qos = QoS},
+ decode_ie_create(Rest,PresentIEs bor 1,Errors,UpdatedCreateReq)
+ end;
+decode_ie_create(<<14:8,
+ Recovery:8,
+ Rest/binary>>,PresentIEs,Errors,CreateReq) ->
+ if
+ PresentIEs band 2 == 2 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 2 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{recovery = Recovery},
+ decode_ie_create(Rest,PresentIEs bor 2,UpdatedErrors,UpdatedCreateReq);
+ true ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{recovery = Recovery},
+ decode_ie_create(Rest,PresentIEs bor 2,Errors,UpdatedCreateReq)
+ end;
+decode_ie_create(<<15:8,
+ _:6,
+ SelectionMode:2,
+ Rest/binary>>,PresentIEs,Errors,CreateReq) ->
+ if
+ PresentIEs band 4 == 4 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 4 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{selMode = selection_mode_internal_storage(SelectionMode)},
+ decode_ie_create(Rest,PresentIEs bor 4,UpdatedErrors,UpdatedCreateReq);
+ true ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{selMode = selection_mode_internal_storage(SelectionMode)},
+ decode_ie_create(Rest,PresentIEs bor 4,Errors,UpdatedCreateReq)
+ end;
+decode_ie_create(<<16:8,
+ FlowLabel:16,
+ Rest/binary>>,PresentIEs,Errors,CreateReq) ->
+ if
+ PresentIEs band 8 == 8 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 8 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblData = FlowLabel},
+ decode_ie_create(Rest,PresentIEs bor 8,UpdatedErrors,UpdatedCreateReq);
+ true ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblData = FlowLabel},
+ decode_ie_create(Rest,PresentIEs bor 8,Errors,UpdatedCreateReq)
+ end;
+decode_ie_create(<<17:8,
+ FlowLabel:16,
+ Rest/binary>>,PresentIEs,Errors,CreateReq) ->
+ if
+ PresentIEs band 16 == 16 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 16 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblSig = FlowLabel},
+ decode_ie_create(Rest,PresentIEs bor 16,UpdatedErrors,UpdatedCreateReq);
+ true ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblSig = FlowLabel},
+ decode_ie_create(Rest,PresentIEs bor 16,Errors,UpdatedCreateReq)
+ end;
+decode_ie_create(<<128:8,
+ Length:16,
+ More/binary>>,PresentIEs,Errors,CreateReq) ->
+ <<PDPElement:Length/binary-unit:8,
+ Rest/binary>> = More,
+ if
+ PresentIEs band 32 == 32 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 32 ->
+ case pdp_addr_internal_storage(PDPElement) of
+ {ok,PDPAddress} ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{endUserAdd = PDPAddress},
+ decode_ie_create(Rest,PresentIEs bor 32,UpdatedErrors,UpdatedCreateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true,
+ outOfSequence = true},
+ decode_ie_create(Rest,PresentIEs bor 32,UpdatedErrors,CreateReq)
+ end;
+ true ->
+ case pdp_addr_internal_storage(PDPElement) of
+ {ok,PDPAddress} ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{endUserAdd = PDPAddress},
+ decode_ie_create(Rest,PresentIEs bor 32,Errors,UpdatedCreateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true},
+ decode_ie_create(Rest,PresentIEs bor 32,UpdatedErrors,CreateReq)
+ end
+ end;
+decode_ie_create(<<131:8,
+ Length:16,
+ More/binary>>,PresentIEs,Errors,CreateReq) ->
+ <<APNElement:Length/binary-unit:8,
+ Rest/binary>> = More,
+ if
+ PresentIEs band 64 == 64 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 64 ->
+ case catch apn_internal_storage(APNElement,[]) of
+ {ok,APN} ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{accPointName = APN},
+ decode_ie_create(Rest,PresentIEs bor 64,UpdatedErrors,UpdatedCreateReq);
+ _ ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true,
+ invalidManIE = true},
+ decode_ie_create(Rest,PresentIEs bor 64,UpdatedErrors,CreateReq)
+ end;
+ true ->
+ case catch apn_internal_storage(APNElement,[]) of
+ {ok,APN} ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{accPointName = APN},
+ decode_ie_create(Rest,PresentIEs bor 64,Errors,UpdatedCreateReq);
+ _ ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true},
+ decode_ie_create(Rest,PresentIEs bor 64,UpdatedErrors,CreateReq)
+ end
+ end;
+decode_ie_create(<<132:8,
+ Length:16,
+ More/binary>>,PresentIEs,Errors,CreateReq) ->
+ <<ConfigurationElement:Length/binary-unit:8,
+ Rest/binary>> = More,
+ if
+ PresentIEs band 128 == 128 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 128 ->
+ case catch pco_internal_storage(ConfigurationElement) of
+ {ok,PCO} ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{protConOpt = PCO},
+ decode_ie_create(Rest,PresentIEs bor 128,UpdatedErrors,UpdatedCreateReq);
+ _ ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true,
+ incorrectOptIE = true},
+ decode_ie_create(Rest,PresentIEs bor 128,UpdatedErrors,CreateReq)
+ end;
+ true ->
+ case catch pco_internal_storage(ConfigurationElement) of
+ {ok,PCO} ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{protConOpt = PCO},
+ decode_ie_create(Rest,PresentIEs bor 128,Errors,UpdatedCreateReq);
+ _ ->
+ UpdatedErrors = Errors#protocolErrors{incorrectOptIE = true},
+ decode_ie_create(Rest,PresentIEs bor 128,UpdatedErrors,CreateReq)
+ end
+ end;
+decode_ie_create(<<133:8,
+ Length:16,
+ More/binary>>,PresentIEs,Errors,CreateReq) ->
+ <<AddressElement:Length/binary-unit:8,
+ Rest/binary>> = More,
+ if
+ PresentIEs band 768 == 768 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 512 ->
+ if
+ PresentIEs band 256 == 0 ->
+ case gsn_addr_internal_storage(AddressElement) of
+ {ok,GSNAddr} ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddSig = GSNAddr},
+ decode_ie_create(Rest,PresentIEs bor 256,UpdatedErrors,UpdatedCreateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true,
+ outOfSequence = true},
+ decode_ie_create(Rest,PresentIEs bor 256,UpdatedErrors,CreateReq)
+ end;
+ true ->
+ case gsn_addr_internal_storage(AddressElement) of
+ {ok,GSNAddr} ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddUser = GSNAddr},
+ decode_ie_create(Rest,PresentIEs bor 512,UpdatedErrors,UpdatedCreateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true,
+ outOfSequence = true},
+ decode_ie_create(Rest,PresentIEs bor 512,UpdatedErrors,CreateReq)
+ end
+ end;
+ PresentIEs < 256 ->
+ case gsn_addr_internal_storage(AddressElement) of
+ {ok,GSNAddr} ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddSig = GSNAddr},
+ decode_ie_create(Rest,PresentIEs bor 256,Errors,UpdatedCreateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true},
+ decode_ie_create(Rest,PresentIEs bor 256,UpdatedErrors,CreateReq)
+ end;
+ true ->
+ case gsn_addr_internal_storage(AddressElement) of
+ {ok,GSNAddr} ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddUser = GSNAddr},
+ decode_ie_create(Rest,PresentIEs bor 512,Errors,UpdatedCreateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true},
+ decode_ie_create(Rest,PresentIEs bor 512,UpdatedErrors,CreateReq)
+ end
+ end;
+decode_ie_create(<<134:8,
+ Length:16,
+ More/binary>>,PresentIEs,Errors,CreateReq) ->
+ <<MSISDNElement:Length/binary-unit:8,
+ Rest/binary>> = More,
+ if
+ PresentIEs band 1024 == 1024 ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ PresentIEs > 1024 ->
+ case msisdn_internal_storage(MSISDNElement,[]) of
+ {ok,MSISDN} ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{msisdn = MSISDN},
+ decode_ie_create(Rest,PresentIEs bor 1024,UpdatedErrors,UpdatedCreateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true,
+ invalidManIE = true},
+ decode_ie_create(Rest,PresentIEs bor 1024,UpdatedErrors,CreateReq)
+ end;
+ true ->
+ UpdatedCreateReq = CreateReq#sesT_createReqV0{msisdn = #mvsT_msisdn{value = MSISDNElement}},
+ decode_ie_create(Rest,PresentIEs bor 1024,Errors,UpdatedCreateReq)
+ end;
+decode_ie_create(UnexpectedIE,PresentIEs,Errors,CreateReq) ->
+ case check_ie(UnexpectedIE) of
+ {defined_ie,Rest} ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ {handled_ie,Rest} ->
+ decode_ie_create(Rest,PresentIEs,Errors,CreateReq);
+ {unhandled_ie} ->
+ {fault,193,CreateReq}
+ end.
+
+decode_ie_update(<<>>,PresentIEs,Errors,UpdateReq) ->
+ if
+ PresentIEs band 61 /= 61 ->
+ {fault,202,UpdateReq};
+ true ->
+ case Errors of
+ #protocolErrors{invalidManIE = true} ->
+ {fault,201,UpdateReq};
+ #protocolErrors{outOfSequence = true} ->
+ {fault,193,UpdateReq};
+ #protocolErrors{incorrectOptIE = true} ->
+ {fault,203,UpdateReq};
+ _ ->
+ {ok,UpdateReq}
+ end
+ end;
+decode_ie_update(<<6:8,
+ QoSElement:3/binary-unit:8,
+ Rest/binary>>,PresentIEs,Errors,UpdateReq) ->
+ if
+ PresentIEs band 1 == 1 ->
+ decode_ie_update(Rest,PresentIEs,Errors,UpdateReq);
+ PresentIEs > 1 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ <<_:2,
+ DelayClass:3,
+ ReliabilityClass:3,
+ PeakThroughput:4,
+ _:1,
+ PrecedenceClass:3,
+ _:3,
+ MeanThroughput:5>> = QoSElement,
+ QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass,
+ reliabilityClass = ReliabilityClass,
+ peakThroughput = PeakThroughput,
+ precedenceClass = PrecedenceClass,
+ meanThroughput = MeanThroughput},
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{qos = QoS},
+ decode_ie_update(Rest,PresentIEs bor 1,UpdatedErrors,UpdatedUpdateReq);
+ true ->
+ <<_:2,
+ DelayClass:3,
+ ReliabilityClass:3,
+ PeakThroughput:4,
+ _:1,
+ PrecedenceClass:3,
+ _:3,
+ MeanThroughput:5>> = QoSElement,
+ QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass,
+ reliabilityClass = ReliabilityClass,
+ peakThroughput = PeakThroughput,
+ precedenceClass = PrecedenceClass,
+ meanThroughput = MeanThroughput},
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{qos = QoS},
+ decode_ie_update(Rest,PresentIEs bor 1,Errors,UpdatedUpdateReq)
+ end;
+decode_ie_update(<<14:8,
+ Recovery:8,
+ Rest/binary>>,PresentIEs,Errors,UpdateReq) ->
+ if
+ PresentIEs band 2 == 2 ->
+ decode_ie_update(Rest,PresentIEs,Errors,UpdateReq);
+ PresentIEs > 2 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{recovery = Recovery},
+ decode_ie_update(Rest,PresentIEs bor 2,UpdatedErrors,UpdatedUpdateReq);
+ true ->
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{recovery = Recovery},
+ decode_ie_update(Rest,PresentIEs bor 2,Errors,UpdatedUpdateReq)
+ end;
+decode_ie_update(<<16:8,
+ FlowLabel:16,
+ Rest/binary>>,PresentIEs,Errors,UpdateReq) ->
+ if
+ PresentIEs band 4 == 4 ->
+ decode_ie_update(Rest,PresentIEs,Errors,UpdateReq);
+ PresentIEs > 4 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblData = FlowLabel},
+ decode_ie_update(Rest,PresentIEs bor 4,UpdatedErrors,UpdatedUpdateReq);
+ true ->
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblData = FlowLabel},
+ decode_ie_update(Rest,PresentIEs bor 4,Errors,UpdatedUpdateReq)
+ end;
+decode_ie_update(<<17:8,
+ FlowLabel:16,
+ Rest/binary>>,PresentIEs,Errors,UpdateReq) ->
+ if
+ PresentIEs band 8 == 8 ->
+ decode_ie_update(Rest,PresentIEs,Errors,UpdateReq);
+ PresentIEs > 8 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblSig = FlowLabel},
+ decode_ie_update(Rest,PresentIEs bor 8,UpdatedErrors,UpdatedUpdateReq);
+ true ->
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblSig = FlowLabel},
+ decode_ie_update(Rest,PresentIEs bor 8,Errors,UpdatedUpdateReq)
+ end;
+decode_ie_update(<<133:8,
+ Length:16,
+ More/binary>>,PresentIEs,Errors,UpdateReq) ->
+ <<AddressElement:Length/binary-unit:8,
+ Rest/binary>> = More,
+ if
+ PresentIEs band 48 == 48 ->
+ decode_ie_update(Rest,PresentIEs,Errors,UpdateReq);
+ PresentIEs > 32 ->
+ if
+ PresentIEs band 16 == 0 ->
+ case gsn_addr_internal_storage(AddressElement) of
+ {ok,GSNAddr} ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddSig = GSNAddr},
+ decode_ie_update(Rest,PresentIEs bor 16,UpdatedErrors,UpdatedUpdateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true,
+ outOfSequence = true},
+ decode_ie_update(Rest,PresentIEs bor 16,UpdatedErrors,UpdateReq)
+ end;
+ true ->
+ case gsn_addr_internal_storage(AddressElement) of
+ {ok,GSNAddr} ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddUser = GSNAddr},
+ decode_ie_update(Rest,PresentIEs bor 32,UpdatedErrors,UpdatedUpdateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true,
+ outOfSequence = true},
+ decode_ie_update(Rest,PresentIEs bor 32,UpdatedErrors,UpdateReq)
+ end
+ end;
+ PresentIEs < 16 ->
+ case gsn_addr_internal_storage(AddressElement) of
+ {ok,GSNAddr} ->
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddSig = GSNAddr},
+ decode_ie_update(Rest,PresentIEs bor 16,Errors,UpdatedUpdateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true},
+ decode_ie_update(Rest,PresentIEs bor 16,UpdatedErrors,UpdateReq)
+ end;
+ true ->
+ case gsn_addr_internal_storage(AddressElement) of
+ {ok,GSNAddr} ->
+ UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddUser = GSNAddr},
+ decode_ie_update(Rest,PresentIEs bor 32,Errors,UpdatedUpdateReq);
+ {fault} ->
+ UpdatedErrors = Errors#protocolErrors{invalidManIE = true},
+ decode_ie_update(Rest,PresentIEs bor 32,UpdatedErrors,UpdateReq)
+ end
+ end;
+decode_ie_update(UnexpectedIE,PresentIEs,Errors,UpdateReq) ->
+ case check_ie(UnexpectedIE) of
+ {defined_ie,Rest} ->
+ decode_ie_update(Rest,PresentIEs,Errors,UpdateReq);
+ {handled_ie,Rest} ->
+ decode_ie_update(Rest,PresentIEs,Errors,UpdateReq);
+ {unhandled_ie} ->
+ {fault,193,UpdateReq}
+ end.
+
+decode_ie_delete_res(<<>>,PresentIEs,Errors,DeleteRes) ->
+ if
+ PresentIEs band 1 /= 1 ->
+ {fault,202,DeleteRes};
+ true ->
+ case Errors of
+ #protocolErrors{invalidManIE = true} ->
+ {fault,201,DeleteRes};
+ #protocolErrors{outOfSequence = true} ->
+ {fault,193,DeleteRes};
+ #protocolErrors{incorrectOptIE = true} ->
+ {fault,203,DeleteRes};
+ _ ->
+ {ok,DeleteRes}
+ end
+ end;
+decode_ie_delete_res(<<1:8,
+ Cause:8,
+ Rest/binary>>,PresentIEs,Errors,DeleteRes) ->
+ if
+ PresentIEs band 1 == 1 ->
+ decode_ie_delete_res(Rest,PresentIEs,Errors,DeleteRes);
+ PresentIEs > 1 ->
+ UpdatedErrors = Errors#protocolErrors{outOfSequence = true},
+ UpdatedDeleteRes = DeleteRes#sesT_deleteResV0{cause = Cause},
+ decode_ie_delete_res(Rest,PresentIEs bor 1,UpdatedErrors,UpdatedDeleteRes);
+ true ->
+ UpdatedDeleteRes = DeleteRes#sesT_deleteResV0{cause = Cause},
+ decode_ie_delete_res(Rest,PresentIEs bor 1,Errors,UpdatedDeleteRes)
+ end;
+decode_ie_delete_res(UnexpectedIE,PresentIEs,Errors,DeleteRes) ->
+ case check_ie(UnexpectedIE) of
+ {defined_ie,Rest} ->
+ decode_ie_delete_res(Rest,PresentIEs,Errors,DeleteRes);
+ {handled_ie,Rest} ->
+ decode_ie_delete_res(Rest,PresentIEs,Errors,DeleteRes);
+ {unhandled_ie} ->
+ {fault,193,DeleteRes}
+ end.
+
+check_ie(<<1:8,
+ _:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<2:8,
+ _:8/binary-unit:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<3:8,
+ _:6/binary-unit:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<4:8,
+ _:4/binary-unit:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<5:8,
+ _:4/binary-unit:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<6:8,
+ _:3/binary-unit:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<8:8,
+ _:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<9:8,
+ _:28/binary-unit:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<11:8,
+ _:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<12:8,
+ _:3/binary-unit:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<13:8,
+ _:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<14:8,
+ _:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<15:8,
+ _:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<16:8,
+ _:16,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<17:8,
+ _:16,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<18:8,
+ _:32,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<19:8,
+ _:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<127:8,
+ _:4/binary-unit:8,
+ Rest/binary>>) ->
+ {defined_ie,Rest};
+check_ie(<<1:1,
+ _:7,
+ Length:16,
+ More/binary>>) ->
+ if
+ Length > size(More) ->
+ {unhandled_ie};
+ true ->
+ <<_:Length/binary-unit:8,
+ Rest/binary>> = More,
+ {handled_ie,Rest}
+ end;
+check_ie(_UnhandledIE) ->
+ {unhandled_ie}.
+
+tid_internal_storage(Bin,_) ->
+ Size = size(Bin) - 1,
+ <<Front:Size/binary,
+ NSAPI:4,
+ DigitN:4>> = Bin,
+ Result = case DigitN of
+ 15 ->
+ #mvsgT_tid{imsi = #mvsgT_imsi{value = Front},
+ nsapi = NSAPI};
+ _ ->
+ #mvsgT_tid{imsi = #mvsgT_imsi{value = <<Front/binary,
+ 15:4,
+ DigitN:4>>},
+ nsapi = NSAPI}
+ end,
+ {ok,Result}.
+
+selection_mode_internal_storage(0) ->
+ subscribed;
+selection_mode_internal_storage(1) ->
+ msRequested;
+selection_mode_internal_storage(2) ->
+ sgsnSelected;
+selection_mode_internal_storage(3) ->
+ sgsnSelected.
+
+pdp_addr_internal_storage(<<_:4,
+ 0:4,
+ 1:8>>) ->
+ {ok,#mvsgT_pdpAddressType{pdpTypeNbr = etsi_ppp,
+ address = []}};
+pdp_addr_internal_storage(<<_:4,
+ 0:4,
+ 2:8>>) ->
+ {ok,#mvsgT_pdpAddressType{pdpTypeNbr = etsi_osp_ihoss,
+ address = []}};
+pdp_addr_internal_storage(<<_:4,
+ 1:4,
+ 33:8>>) ->
+ {ok,#mvsgT_pdpAddressType{pdpTypeNbr = ietf_ipv4,
+ address = []}};
+pdp_addr_internal_storage(<<_:4,
+ 1:4,
+ 33:8,
+ IP_A:8,
+ IP_B:8,
+ IP_C:8,
+ IP_D:8>>) ->
+ {ok,#mvsgT_pdpAddressType{pdpTypeNbr = ietf_ipv4,
+ address = [IP_A,IP_B,IP_C,IP_D]}};
+pdp_addr_internal_storage(<<_:4,
+ 1:4,
+ 87:8,
+ IP_A:16,
+ IP_B:16,
+ IP_C:16,
+ IP_D:16,
+ IP_E:16,
+ IP_F:16,
+ IP_G:16,
+ IP_H:16>>) ->
+ {ok,#mvsgT_pdpAddressType{pdpTypeNbr = ietf_ipv6,
+ address = [IP_A,IP_B,IP_C,IP_D,IP_E,IP_F,IP_G,IP_H]}};
+pdp_addr_internal_storage(_PDP_ADDR) ->
+ {fault}.
+
+apn_internal_storage(<<>>,APN) ->
+ {ok,lists:reverse(APN)};
+apn_internal_storage(<<Length:8,
+ Rest/binary>>,APN) ->
+ <<Label:Length/binary-unit:8,
+ MoreAPNLabels/binary>> = Rest,
+ apn_internal_storage(MoreAPNLabels,[Label|APN]).
+
+pco_internal_storage(<<1:1,
+ _:4,
+ 0:3,
+ PPPConfigurationOptions/binary>>) ->
+ case ppp_configuration_options(PPPConfigurationOptions,#masT_pap{exists = false},[],[]) of
+ {ok,PAP,CHAP,IPCP} ->
+ {ok,#masT_protocolConfigOptions{pap = PAP,
+ chap = CHAP,
+ ipcp = IPCP}};
+ {fault} ->
+ {fault}
+ end;
+pco_internal_storage(<<1:1,
+ _:4,
+ 1:3,
+ _OSP_IHOSSConfigurationOptions/binary>>) ->
+ {ok,osp_ihoss};
+pco_internal_storage(_UnknownConfigurationOptions) ->
+ {fault}.
+
+ppp_configuration_options(<<>>,PAP,CHAP,IPCP) ->
+ {ok,PAP,CHAP,IPCP};
+ppp_configuration_options(<<49185:16,
+ Length:8,
+ More/binary>>,PAP,CHAP,IPCP) ->
+ <<_LCP:Length/binary-unit:8,
+ Rest/binary>> = More,
+ ppp_configuration_options(Rest,PAP,CHAP,IPCP);
+ppp_configuration_options(<<49187:16,
+ _Length:8,
+ 1:8,
+ Identifier:8,
+ DataLength:16,
+ More/binary>>,_PAP,CHAP,IPCP) ->
+ ActualDataLength = DataLength - 4,
+ <<Data:ActualDataLength/binary-unit:8,
+ Rest/binary>> = More,
+ <<PeerIDLength:8,
+ PeerData/binary>> = Data,
+ <<PeerID:PeerIDLength/binary-unit:8,
+ PasswdLength:8,
+ PasswordData/binary>> = PeerData,
+ <<Password:PasswdLength/binary,
+ _Padding/binary>> = PasswordData,
+ ppp_configuration_options(Rest,#masT_pap{exists = true,
+ code = 1,
+ id = Identifier,
+ username = binary_to_list(PeerID),
+ password = binary_to_list(Password)},CHAP,IPCP);
+ppp_configuration_options(<<49187:16,
+ Length:8,
+ More/binary>>,PAP,CHAP,IPCP) ->
+ <<PAP:Length/binary-unit:8,
+ Rest/binary>> = More,
+ ppp_configuration_options(Rest,PAP,CHAP,IPCP);
+ppp_configuration_options(<<49699:16,
+ _Length:8,
+ 1:8,
+ Identifier:8,
+ DataLength:16,
+ More/binary>>,PAP,CHAP,IPCP) ->
+ ActualDataLength = DataLength - 4,
+ <<Data:ActualDataLength/binary-unit:8,
+ Rest/binary>> = More,
+ <<ValueSize:8,
+ ValueAndName/binary>> = Data,
+ <<Value:ValueSize/binary-unit:8,
+ Name/binary>> = ValueAndName,
+ ppp_configuration_options(Rest,PAP,[#masT_chap{code = 1,
+ id = Identifier,
+ value = binary_to_list(Value),
+ name = binary_to_list(Name)}|CHAP],IPCP);
+ppp_configuration_options(<<49699:16,
+ _Length:8,
+ 2:8,
+ Identifier:8,
+ DataLength:16,
+ More/binary>>,PAP,CHAP,IPCP) ->
+ ActualDataLength = DataLength - 4,
+ <<Data:ActualDataLength/binary-unit:8,
+ Rest/binary>> = More,
+ <<ValueSize:8,
+ ValueAndName/binary>> = Data,
+ <<Value:ValueSize/binary-unit:8,
+ Name/binary>> = ValueAndName,
+ ppp_configuration_options(Rest,PAP,[#masT_chap{code = 2,
+ id = Identifier,
+ value = binary_to_list(Value),
+ name = binary_to_list(Name)}|CHAP],IPCP);
+ppp_configuration_options(<<49699:16,
+ Length:8,
+ More/binary>>,PAP,CHAP,IPCP) ->
+ <<CHAP:Length/binary-unit:8,
+ Rest/binary>> = More,
+ ppp_configuration_options(Rest,PAP,CHAP,IPCP);
+ppp_configuration_options(<<32801:16,
+ _Length:8,
+ 1:8,
+ Identifier:8,
+ OptionsLength:16,
+ More/binary>>,PAP,CHAP,IPCP) ->
+ ActualOptionsLength = OptionsLength - 4,
+ <<Options:ActualOptionsLength/binary-unit:8,
+ Rest/binary>> = More,
+ case Options of
+ <<3:8,
+ 6:8,
+ A1:8,
+ A2:8,
+ A3:8,
+ A4:8>> ->
+ ppp_configuration_options(Rest,PAP,CHAP,[#masT_ipcp{exists = true,
+ code = 1,
+ id = Identifier,
+ ipcpList = [#masT_ipcpData{type = 3,
+ ipAddress = #mvsgT_ipAddress{version = ipv4,
+ a1 = A1,
+ a2 = A2,
+ a3 = A3,
+ a4 = A4,
+ a5 = 0,
+ a6 = 0,
+ a7 = 0,
+ a8 = 0},
+ rawMessage = binary_to_list(Options)}]}|IPCP]);
+ <<129:8,
+ 6:8,
+ B1:8,
+ B2:8,
+ B3:8,
+ B4:8>> ->
+ ppp_configuration_options(Rest,PAP,CHAP,[#masT_ipcp{exists = true,
+ code = 1,
+ id = Identifier,
+ ipcpList = [#masT_ipcpData{type = 129,
+ ipAddress = #mvsgT_ipAddress{version = ipv4,
+ a1 = B1,
+ a2 = B2,
+ a3 = B3,
+ a4 = B4},
+ rawMessage = binary_to_list(Options)}]}|IPCP]);
+ <<131:8,
+ 6:8,
+ C1:8,
+ C2:8,
+ C3:8,
+ C4:8>> ->
+ ppp_configuration_options(Rest,PAP,CHAP,[#masT_ipcp{exists = true,
+ code = 1,
+ id = Identifier,
+ ipcpList = [#masT_ipcpData{type = 131,
+ ipAddress = #mvsgT_ipAddress{version = ipv4,
+ a1 = C1,
+ a2 = C2,
+ a3 = C3,
+ a4 = C4},
+ rawMessage = binary_to_list(Options)}]}|IPCP]);
+ _ ->
+ ppp_configuration_options(Rest,PAP,CHAP,IPCP)
+ end;
+ppp_configuration_options(<<_UnknownProtocolID:16,
+ Length:8,
+ More/binary>>,PAP,CHAP,IPCP) ->
+ <<_Skipped:Length/binary-unit:8,
+ Rest/binary>> = More,
+ ppp_configuration_options(Rest,PAP,CHAP,IPCP);
+ppp_configuration_options(_Unhandled,_PAP,_CHAP,_IPCP) ->
+ {fault}.
+
+gsn_addr_internal_storage(<<IP_A:8,
+ IP_B:8,
+ IP_C:8,
+ IP_D:8>>) ->
+ {ok,#mvsgT_ipAddress{version = ipv4,
+ a1 = IP_A,
+ a2 = IP_B,
+ a3 = IP_C,
+ a4 = IP_D,
+ a5 = 0,
+ a6 = 0,
+ a7 = 0,
+ a8 = 0}};
+gsn_addr_internal_storage(<<IP_A:16,
+ IP_B:16,
+ IP_C:16,
+ IP_D:16,
+ IP_E:16,
+ IP_F:16,
+ IP_G:16,
+ IP_H:16>>) ->
+ {ok,#mvsgT_ipAddress{version = ipv6,
+ a1 = IP_A,
+ a2 = IP_B,
+ a3 = IP_C,
+ a4 = IP_D,
+ a5 = IP_E,
+ a6 = IP_F,
+ a7 = IP_G,
+ a8 = IP_H}};
+gsn_addr_internal_storage(_GSN_ADDR) ->
+ {fault}.
+
+msisdn_internal_storage(<<>>,MSISDN) ->
+ {ok,#mvsT_msisdn{value = lists:reverse(MSISDN)}};
+msisdn_internal_storage(<<255:8,
+ _Rest/binary>>,MSISDN) ->
+ {ok,#mvsT_msisdn{value = lists:reverse(MSISDN)}};
+msisdn_internal_storage(<<15:4,
+ DigitN:4,
+ _Rest/binary>>,MSISDN) when DigitN < 10 ->
+ {ok,#mvsT_msisdn{value = lists:reverse([DigitN bor 240|MSISDN])}};
+msisdn_internal_storage(<<DigitNplus1:4,
+ DigitN:4,
+ Rest/binary>>,MSISDN) when DigitNplus1 < 10, DigitN < 10 ->
+ NewMSISDN = [DigitNplus1 bsl 4 bor DigitN|MSISDN],
+ msisdn_internal_storage(Rest,NewMSISDN);
+msisdn_internal_storage(_Rest,_MSISDN) ->
+ {fault}.
diff --git a/lib/compiler/test/inline_SUITE_data/bsdes.erl b/lib/compiler/test/inline_SUITE_data/bsdes.erl
new file mode 100644
index 0000000000..8d2d1a8287
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/bsdes.erl
@@ -0,0 +1,747 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(bsdes).
+-export([?MODULE/0]).
+
+-define(ITERATIONS, 100). %% for benchmarking use a higher number
+
+?MODULE() ->
+ Res = test(),
+ {Res,Res =:= <<0,0,0,0,0,0,0,1>>}.
+
+test() ->
+ Bin = <<1:64>>,
+ Size= size(Bin),
+ Key = <<4704650607608769871263876:64>>,
+ Jumbled = run_encode(?ITERATIONS, Bin, Key),
+ Unjumbled = run_decode(?ITERATIONS, Jumbled, Key),
+ <<Bin:Size/binary,_/binary>> = Unjumbled.
+
+run_encode(1, Bin, Key) ->
+ encode(Bin, Key);
+run_encode(N, Bin, Key) ->
+ encode(Bin, Key),
+ run_encode(N-1, Bin, Key).
+
+run_decode(1, Bin, Key) ->
+ decode(Bin, Key);
+run_decode(N, Bin, Key) ->
+ decode(Bin, Key),
+ run_decode(N-1, Bin, Key).
+
+encode(Data, Key) ->
+ Keys = schedule(Key),
+ list_to_binary(encode_data(Data, Keys)).
+
+decode(Data, Key) ->
+ Keys = lists:reverse(schedule(Key)),
+ list_to_binary(decode_data(Data, Keys)).
+
+encode_data(<<Data:8/binary, Rest/binary>>, Keys) ->
+ [ipinv(des_core(ip(Data), Keys))|encode_data(Rest, Keys)];
+encode_data(<<Rest/binary>>, Keys) ->
+ case size(Rest) of
+ 0 -> [];
+ X ->
+ Y = 8-X,
+ Data = <<Rest/binary, 0:Y/integer-unit:8>>,
+ [ipinv(des_core(ip(Data), Keys))]
+ end.
+
+decode_data(<<Data:8/binary, Rest/binary>>, Keys) ->
+ [ipinv(dechiper(ip(Data), Keys))|decode_data(Rest, Keys)];
+decode_data(_, _Keys) ->
+ [].
+
+schedule(Key) ->
+ NewKey=pc1(Key),
+ subkeys(NewKey, 1).
+
+subkeys(_Key, 17) ->
+ [];
+subkeys(Key, N) ->
+ TmpKey =
+ case rotate(N) of
+ 1 ->
+ <<X1:1, L:27, X2:1, R:27>> = Key,
+ <<L:27, X1:1, R:27, X2:1>>;
+ 2 ->
+ <<X1:2, L:26, X2:2, R:26>> = Key,
+ <<L:26, X1:2, R:26, X2:2>>;
+ _ ->
+ error
+ end,
+ [pc2(TmpKey)|subkeys(TmpKey, N+1)].
+
+pc2(<<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, I8:1,
+ _I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, I16:1,
+ I17:1, _I18:1, I19:1, I20:1, I21:1, _I22:1, I23:1, I24:1,
+ _I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, I32:1,
+ I33:1, I34:1, _I35:1, I36:1, I37:1, _I38:1, I39:1, I40:1,
+ I41:1, I42:1, _I43:1, I44:1, I45:1, I46:1, I47:1, I48:1,
+ I49:1, I50:1, I51:1, I52:1, I53:1, _I54:1, I55:1, I56:1>>) ->
+ <<I14:1, I17:1, I11:1, I24:1, I1:1, I5:1, I3:1, I28:1,
+ I15:1, I6:1, I21:1, I10:1, I23:1, I19:1, I12:1, I4:1,
+ I26:1, I8:1, I16:1, I7:1, I27:1, I20:1, I13:1, I2:1,
+ I41:1, I52:1, I31:1, I37:1, I47:1, I55:1, I30:1, I40:1,
+ I51:1, I45:1, I33:1, I48:1, I44:1, I49:1, I39:1, I56:1,
+ I34:1, I53:1, I46:1, I42:1, I50:1, I36:1, I29:1, I32:1>>.
+
+pc1(<<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, _:1,
+ I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, _:1,
+ I17:1, I18:1, I19:1, I20:1, I21:1, I22:1, I23:1, _:1,
+ I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, _:1,
+ I33:1, I34:1, I35:1, I36:1, I37:1, I38:1, I39:1, _:1,
+ I41:1, I42:1, I43:1, I44:1, I45:1, I46:1, I47:1, _:1,
+ I49:1, I50:1, I51:1, I52:1, I53:1, I54:1, I55:1, _:1,
+ I57:1, I58:1, I59:1, I60:1, I61:1, I62:1, I63:1, _:1>>) ->
+ <<I57:1, I49:1, I41:1, I33:1, I25:1, I17:1, I9:1, I1:1,
+ I58:1, I50:1, I42:1, I34:1, I26:1, I18:1, I10:1, I2:1,
+ I59:1, I51:1, I43:1, I35:1, I27:1, I19:1, I11:1, I3:1,
+ I60:1, I52:1, I44:1, I36:1, I63:1, I55:1, I47:1, I39:1,
+ I31:1, I23:1, I15:1, I7:1, I62:1, I54:1, I46:1, I38:1,
+ I30:1, I22:1, I14:1, I6:1, I61:1, I53:1, I45:1, I37:1,
+ I29:1, I21:1, I13:1, I5:1, I28:1, I20:1, I12:1, I4:1>>.
+
+ip(<<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, I8:1,
+ I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, I16:1,
+ I17:1, I18:1, I19:1, I20:1, I21:1, I22:1, I23:1, I24:1,
+ I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, I32:1,
+ I33:1, I34:1, I35:1, I36:1, I37:1, I38:1, I39:1, I40:1,
+ I41:1, I42:1, I43:1, I44:1, I45:1, I46:1, I47:1, I48:1,
+ I49:1, I50:1, I51:1, I52:1, I53:1, I54:1, I55:1, I56:1,
+ I57:1, I58:1, I59:1, I60:1, I61:1, I62:1, I63:1, I64:1>>) ->
+ <<I58:1, I50:1, I42:1, I34:1, I26:1, I18:1, I10:1, I2:1,
+ I60:1, I52:1, I44:1, I36:1, I28:1, I20:1, I12:1, I4:1,
+ I62:1, I54:1, I46:1, I38:1, I30:1, I22:1, I14:1, I6:1,
+ I64:1, I56:1, I48:1, I40:1, I32:1, I24:1, I16:1, I8:1,
+ I57:1, I49:1, I41:1, I33:1, I25:1, I17:1, I9:1, I1:1,
+ I59:1, I51:1, I43:1, I35:1, I27:1, I19:1, I11:1, I3:1,
+ I61:1, I53:1, I45:1, I37:1, I29:1, I21:1, I13:1, I5:1,
+ I63:1, I55:1, I47:1, I39:1, I31:1, I23:1, I15:1, I7:1>>.
+
+ipinv(<<I58:1, I50:1, I42:1, I34:1, I26:1, I18:1, I10:1, I2:1,
+ I60:1, I52:1, I44:1, I36:1, I28:1, I20:1, I12:1, I4:1,
+ I62:1, I54:1, I46:1, I38:1, I30:1, I22:1, I14:1, I6:1,
+ I64:1, I56:1, I48:1, I40:1, I32:1, I24:1, I16:1, I8:1,
+ I57:1, I49:1, I41:1, I33:1, I25:1, I17:1, I9:1, I1:1,
+ I59:1, I51:1, I43:1, I35:1, I27:1, I19:1, I11:1, I3:1,
+ I61:1, I53:1, I45:1, I37:1, I29:1, I21:1, I13:1, I5:1,
+ I63:1, I55:1, I47:1, I39:1, I31:1, I23:1, I15:1, I7:1>>) ->
+ <<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, I8:1,
+ I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, I16:1,
+ I17:1, I18:1, I19:1, I20:1, I21:1, I22:1, I23:1, I24:1,
+ I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, I32:1,
+ I33:1, I34:1, I35:1, I36:1, I37:1, I38:1, I39:1, I40:1,
+ I41:1, I42:1, I43:1, I44:1, I45:1, I46:1, I47:1, I48:1,
+ I49:1, I50:1, I51:1, I52:1, I53:1, I54:1, I55:1, I56:1,
+ I57:1, I58:1, I59:1, I60:1, I61:1, I62:1, I63:1, I64:1>>.
+
+dechiper(<<L:4/binary, R:4/binary>>, Keys) ->
+ dechiper(L, R, Keys, 16).
+
+dechiper(L, R, [], 0) ->
+ <<L:4/binary, R:4/binary>>;
+dechiper(L, R, [Key|Rest], I) ->
+ NewL=ebit(L),
+ XorL=xor48(NewL, Key),
+ Sboxed=sboxing(XorL),
+ Ped=p(Sboxed),
+ EndL = xor32(Ped, R),
+ dechiper(EndL,L,Rest,I-1).
+
+des_core(<<L:4/binary, R:4/binary>>, Keys) ->
+ des_core(L, R, Keys, 0).
+
+des_core(L, R, [], 16) ->
+ <<L:4/binary, R:4/binary>>;
+des_core(L, R, [Key|Rest], I) when I<16 ->
+ NewR=ebit(R),
+ XorR=xor48(NewR, Key),
+ Sboxed=sboxing(XorR),
+ Ped=p(Sboxed),
+ EndR = xor32(Ped, L),
+ des_core(R, EndR, Rest, I+1).
+
+ebit(<<I1:1, I2:2, I3:2,I4:2,I5:2,I6:2,
+ I7:2,I8:2,I9:2,I10:2,I11:2,I12:2,
+ I13:2,I14:2,I15:2,I16:2,I17:1>>) ->
+ <<I17:1, I1:1, I2:2, I3:2, I3:2,
+ I4:2, I5:2, I5:2, I6:2,
+ I7:2, I7:2, I8:2, I9:2,
+ I9:2, I10:2, I11:2, I11:2,
+ I12:2, I13:2, I13:2, I14:2,
+ I15:2, I15:2, I16:2, I17:1, I1:1>>.
+
+p(<<I1:1, I2:1, I3:1, I4:1, I5:1, I6:1, I7:1, I8:1,
+ I9:1, I10:1, I11:1, I12:1, I13:1, I14:1, I15:1, I16:1,
+ I17:1, I18:1, I19:1, I20:1, I21:1, I22:1, I23:1, I24:1,
+ I25:1, I26:1, I27:1, I28:1, I29:1, I30:1, I31:1, I32:1>>) ->
+ <<I16:1, I7:1, I20:1, I21:1, I29:1, I12:1, I28:1, I17:1,
+ I1:1, I15:1, I23:1, I26:1, I5:1, I18:1, I31:1, I10:1,
+ I2:1, I8:1, I24:1, I14:1, I32:1, I27:1, I3:1, I9:1,
+ I19:1, I13:1, I30:1, I6:1, I22:1, I11:1, I4:1, I25:1>>.
+
+rotate(1) -> 1;
+rotate(2) -> 1;
+rotate(9) -> 1;
+rotate(16) -> 1;
+rotate(N) when N>0, N<17 -> 2.
+
+%xor64(<<I1:16, I2:16, I3:16, I4:16>>,<<J1:16, J2:16, J3:16, J4:16>>) ->
+% K1 = I1 bxor J1,
+% K2 = I2 bxor J2,
+% K3 = I3 bxor J3,
+% K4 = I4 bxor J4,
+% <<K1:16, K2:16, K3:16, K4:16>>.
+
+xor48(<<I1:16, I2:16, I3:16>>,<<J1:16, J2:16, J3:16>>) ->
+ K1 = I1 bxor J1,
+ K2 = I2 bxor J2,
+ K3 = I3 bxor J3,
+ <<K1:16, K2:16, K3:16>>.
+
+xor32(<<I1:16, I2:16>>,<<J1:16, J2:16>>) ->
+ K1 = I1 bxor J1,
+ K2 = I2 bxor J2,
+ <<K1:16, K2:16>>.
+
+sboxing(<<A1:6, A2:6, A3:6, A4:6, A5:6, A6:6, A7:6, A8:6>>) ->
+ S1=sbox(A1, 1),
+ S2=sbox(A2, 2),
+ S3=sbox(A3, 3),
+ S4=sbox(A4, 4),
+ S5=sbox(A5, 5),
+ S6=sbox(A6, 6),
+ S7=sbox(A7, 7),
+ S8=sbox(A8, 8),
+ <<S1:4,S2:4,S3:4,S4:4,S5:4,S6:4,S7:4,S8:4>>.
+
+sbox(0,1) -> 14;
+sbox(1,1) -> 0;
+sbox(2,1) -> 4;
+sbox(3,1) -> 15;
+sbox(4,1) -> 13;
+sbox(5,1) -> 7;
+sbox(6,1) -> 1;
+sbox(7,1) -> 4;
+sbox(8,1) -> 2;
+sbox(9,1) -> 14;
+sbox(10,1) -> 15;
+sbox(11,1) -> 2;
+sbox(12,1) -> 11;
+sbox(13,1) -> 13;
+sbox(14,1) -> 8;
+sbox(15,1) -> 1;
+sbox(16,1) -> 3;
+sbox(17,1) -> 10;
+sbox(18,1) -> 10;
+sbox(19,1) -> 6;
+sbox(20,1) -> 6;
+sbox(21,1) -> 12;
+sbox(22,1) -> 12;
+sbox(23,1) -> 11;
+sbox(24,1) -> 5;
+sbox(25,1) -> 9;
+sbox(26,1) -> 9;
+sbox(27,1) -> 5;
+sbox(28,1) -> 0;
+sbox(29,1) -> 3;
+sbox(30,1) -> 7;
+sbox(31,1) -> 8;
+sbox(32,1) -> 4;
+sbox(33,1) -> 15;
+sbox(34,1) -> 1;
+sbox(35,1) -> 12;
+sbox(36,1) -> 14;
+sbox(37,1) -> 8;
+sbox(38,1) -> 8;
+sbox(39,1) -> 2;
+sbox(40,1) -> 13;
+sbox(41,1) -> 4;
+sbox(42,1) -> 6;
+sbox(43,1) -> 9;
+sbox(44,1) -> 2;
+sbox(45,1) -> 1;
+sbox(46,1) -> 11;
+sbox(47,1) -> 7;
+sbox(48,1) -> 15;
+sbox(49,1) -> 5;
+sbox(50,1) -> 12;
+sbox(51,1) -> 11;
+sbox(52,1) -> 9;
+sbox(53,1) -> 3;
+sbox(54,1) -> 7;
+sbox(55,1) -> 14;
+sbox(56,1) -> 3;
+sbox(57,1) -> 10;
+sbox(58,1) -> 10;
+sbox(59,1) -> 0;
+sbox(60,1) -> 5;
+sbox(61,1) -> 6;
+sbox(62,1) -> 0;
+sbox(63,1) -> 13;
+sbox(0,2) -> 15;
+sbox(1,2) -> 3;
+sbox(2,2) -> 1;
+sbox(3,2) -> 13;
+sbox(4,2) -> 8;
+sbox(5,2) -> 4;
+sbox(6,2) -> 14;
+sbox(7,2) -> 7;
+sbox(8,2) -> 6;
+sbox(9,2) -> 15;
+sbox(10,2) -> 11;
+sbox(11,2) -> 2;
+sbox(12,2) -> 3;
+sbox(13,2) -> 8;
+sbox(14,2) -> 4;
+sbox(15,2) -> 14;
+sbox(16,2) -> 9;
+sbox(17,2) -> 12;
+sbox(18,2) -> 7;
+sbox(19,2) -> 0;
+sbox(20,2) -> 2;
+sbox(21,2) -> 1;
+sbox(22,2) -> 13;
+sbox(23,2) -> 10;
+sbox(24,2) -> 12;
+sbox(25,2) -> 6;
+sbox(26,2) -> 0;
+sbox(27,2) -> 9;
+sbox(28,2) -> 5;
+sbox(29,2) -> 11;
+sbox(30,2) -> 10;
+sbox(31,2) -> 5;
+sbox(32,2) -> 0;
+sbox(33,2) -> 13;
+sbox(34,2) -> 14;
+sbox(35,2) -> 8;
+sbox(36,2) -> 7;
+sbox(37,2) -> 10;
+sbox(38,2) -> 11;
+sbox(39,2) -> 1;
+sbox(40,2) -> 10;
+sbox(41,2) -> 3;
+sbox(42,2) -> 4;
+sbox(43,2) -> 15;
+sbox(44,2) -> 13;
+sbox(45,2) -> 4;
+sbox(46,2) -> 1;
+sbox(47,2) -> 2;
+sbox(48,2) -> 5;
+sbox(49,2) -> 11;
+sbox(50,2) -> 8;
+sbox(51,2) -> 6;
+sbox(52,2) -> 12;
+sbox(53,2) -> 7;
+sbox(54,2) -> 6;
+sbox(55,2) -> 12;
+sbox(56,2) -> 9;
+sbox(57,2) -> 0;
+sbox(58,2) -> 3;
+sbox(59,2) -> 5;
+sbox(60,2) -> 2;
+sbox(61,2) -> 14;
+sbox(62,2) -> 15;
+sbox(63,2) -> 9;
+sbox(0,3) -> 10;
+sbox(1,3) -> 13;
+sbox(2,3) -> 0;
+sbox(3,3) -> 7;
+sbox(4,3) -> 9;
+sbox(5,3) -> 0;
+sbox(6,3) -> 14;
+sbox(7,3) -> 9;
+sbox(8,3) -> 6;
+sbox(9,3) -> 3;
+sbox(10,3) -> 3;
+sbox(11,3) -> 4;
+sbox(12,3) -> 15;
+sbox(13,3) -> 6;
+sbox(14,3) -> 5;
+sbox(15,3) -> 10;
+sbox(16,3) -> 1;
+sbox(17,3) -> 2;
+sbox(18,3) -> 13;
+sbox(19,3) -> 8;
+sbox(20,3) -> 12;
+sbox(21,3) -> 5;
+sbox(22,3) -> 7;
+sbox(23,3) -> 14;
+sbox(24,3) -> 11;
+sbox(25,3) -> 12;
+sbox(26,3) -> 4;
+sbox(27,3) -> 11;
+sbox(28,3) -> 2;
+sbox(29,3) -> 15;
+sbox(30,3) -> 8;
+sbox(31,3) -> 1;
+sbox(32,3) -> 13;
+sbox(33,3) -> 1;
+sbox(34,3) -> 6;
+sbox(35,3) -> 10;
+sbox(36,3) -> 4;
+sbox(37,3) -> 13;
+sbox(38,3) -> 9;
+sbox(39,3) -> 0;
+sbox(40,3) -> 8;
+sbox(41,3) -> 6;
+sbox(42,3) -> 15;
+sbox(43,3) -> 9;
+sbox(44,3) -> 3;
+sbox(45,3) -> 8;
+sbox(46,3) -> 0;
+sbox(47,3) -> 7;
+sbox(48,3) -> 11;
+sbox(49,3) -> 4;
+sbox(50,3) -> 1;
+sbox(51,3) -> 15;
+sbox(52,3) -> 2;
+sbox(53,3) -> 14;
+sbox(54,3) -> 12;
+sbox(55,3) -> 3;
+sbox(56,3) -> 5;
+sbox(57,3) -> 11;
+sbox(58,3) -> 10;
+sbox(59,3) -> 5;
+sbox(60,3) -> 14;
+sbox(61,3) -> 2;
+sbox(62,3) -> 7;
+sbox(63,3) -> 12;
+sbox(0,4) -> 7;
+sbox(1,4) -> 13;
+sbox(2,4) -> 13;
+sbox(3,4) -> 8;
+sbox(4,4) -> 14;
+sbox(5,4) -> 11;
+sbox(6,4) -> 3;
+sbox(7,4) -> 5;
+sbox(8,4) -> 0;
+sbox(9,4) -> 6;
+sbox(10,4) -> 6;
+sbox(11,4) -> 15;
+sbox(12,4) -> 9;
+sbox(13,4) -> 0;
+sbox(14,4) -> 10;
+sbox(15,4) -> 3;
+sbox(16,4) -> 1;
+sbox(17,4) -> 4;
+sbox(18,4) -> 2;
+sbox(19,4) -> 7;
+sbox(20,4) -> 8;
+sbox(21,4) -> 2;
+sbox(22,4) -> 5;
+sbox(23,4) -> 12;
+sbox(24,4) -> 11;
+sbox(25,4) -> 1;
+sbox(26,4) -> 12;
+sbox(27,4) -> 10;
+sbox(28,4) -> 4;
+sbox(29,4) -> 14;
+sbox(30,4) -> 15;
+sbox(31,4) -> 9;
+sbox(32,4) -> 10;
+sbox(33,4) -> 3;
+sbox(34,4) -> 6;
+sbox(35,4) -> 15;
+sbox(36,4) -> 9;
+sbox(37,4) -> 0;
+sbox(38,4) -> 0;
+sbox(39,4) -> 6;
+sbox(40,4) -> 12;
+sbox(41,4) -> 10;
+sbox(42,4) -> 11;
+sbox(43,4) -> 1;
+sbox(44,4) -> 7;
+sbox(45,4) -> 13;
+sbox(46,4) -> 13;
+sbox(47,4) -> 8;
+sbox(48,4) -> 15;
+sbox(49,4) -> 9;
+sbox(50,4) -> 1;
+sbox(51,4) -> 4;
+sbox(52,4) -> 3;
+sbox(53,4) -> 5;
+sbox(54,4) -> 14;
+sbox(55,4) -> 11;
+sbox(56,4) -> 5;
+sbox(57,4) -> 12;
+sbox(58,4) -> 2;
+sbox(59,4) -> 7;
+sbox(60,4) -> 8;
+sbox(61,4) -> 2;
+sbox(62,4) -> 4;
+sbox(63,4) -> 14;
+sbox(0,5) -> 2;
+sbox(1,5) -> 14;
+sbox(2,5) -> 12;
+sbox(3,5) -> 11;
+sbox(4,5) -> 4;
+sbox(5,5) -> 2;
+sbox(6,5) -> 1;
+sbox(7,5) -> 12;
+sbox(8,5) -> 7;
+sbox(9,5) -> 4;
+sbox(10,5) -> 10;
+sbox(11,5) -> 7;
+sbox(12,5) -> 11;
+sbox(13,5) -> 13;
+sbox(14,5) -> 6;
+sbox(15,5) -> 1;
+sbox(16,5) -> 8;
+sbox(17,5) -> 5;
+sbox(18,5) -> 5;
+sbox(19,5) -> 0;
+sbox(20,5) -> 3;
+sbox(21,5) -> 15;
+sbox(22,5) -> 15;
+sbox(23,5) -> 10;
+sbox(24,5) -> 13;
+sbox(25,5) -> 3;
+sbox(26,5) -> 0;
+sbox(27,5) -> 9;
+sbox(28,5) -> 14;
+sbox(29,5) -> 8;
+sbox(30,5) -> 9;
+sbox(31,5) -> 6;
+sbox(32,5) -> 4;
+sbox(33,5) -> 11;
+sbox(34,5) -> 2;
+sbox(35,5) -> 8;
+sbox(36,5) -> 1;
+sbox(37,5) -> 12;
+sbox(38,5) -> 11;
+sbox(39,5) -> 7;
+sbox(40,5) -> 10;
+sbox(41,5) -> 1;
+sbox(42,5) -> 13;
+sbox(43,5) -> 14;
+sbox(44,5) -> 7;
+sbox(45,5) -> 2;
+sbox(46,5) -> 8;
+sbox(47,5) -> 13;
+sbox(48,5) -> 15;
+sbox(49,5) -> 6;
+sbox(50,5) -> 9;
+sbox(51,5) -> 15;
+sbox(52,5) -> 12;
+sbox(53,5) -> 0;
+sbox(54,5) -> 5;
+sbox(55,5) -> 9;
+sbox(56,5) -> 6;
+sbox(57,5) -> 10;
+sbox(58,5) -> 3;
+sbox(59,5) -> 4;
+sbox(60,5) -> 0;
+sbox(61,5) -> 5;
+sbox(62,5) -> 14;
+sbox(63,5) -> 3;
+sbox(0,6) -> 12;
+sbox(1,6) -> 10;
+sbox(2,6) -> 1;
+sbox(3,6) -> 15;
+sbox(4,6) -> 10;
+sbox(5,6) -> 4;
+sbox(6,6) -> 15;
+sbox(7,6) -> 2;
+sbox(8,6) -> 9;
+sbox(9,6) -> 7;
+sbox(10,6) -> 2;
+sbox(11,6) -> 12;
+sbox(12,6) -> 6;
+sbox(13,6) -> 9;
+sbox(14,6) -> 8;
+sbox(15,6) -> 5;
+sbox(16,6) -> 0;
+sbox(17,6) -> 6;
+sbox(18,6) -> 13;
+sbox(19,6) -> 1;
+sbox(20,6) -> 3;
+sbox(21,6) -> 13;
+sbox(22,6) -> 4;
+sbox(23,6) -> 14;
+sbox(24,6) -> 14;
+sbox(25,6) -> 0;
+sbox(26,6) -> 7;
+sbox(27,6) -> 11;
+sbox(28,6) -> 5;
+sbox(29,6) -> 3;
+sbox(30,6) -> 11;
+sbox(31,6) -> 8;
+sbox(32,6) -> 9;
+sbox(33,6) -> 4;
+sbox(34,6) -> 14;
+sbox(35,6) -> 3;
+sbox(36,6) -> 15;
+sbox(37,6) -> 2;
+sbox(38,6) -> 5;
+sbox(39,6) -> 12;
+sbox(40,6) -> 2;
+sbox(41,6) -> 9;
+sbox(42,6) -> 8;
+sbox(43,6) -> 5;
+sbox(44,6) -> 12;
+sbox(45,6) -> 15;
+sbox(46,6) -> 3;
+sbox(47,6) -> 10;
+sbox(48,6) -> 7;
+sbox(49,6) -> 11;
+sbox(50,6) -> 0;
+sbox(51,6) -> 14;
+sbox(52,6) -> 4;
+sbox(53,6) -> 1;
+sbox(54,6) -> 10;
+sbox(55,6) -> 7;
+sbox(56,6) -> 1;
+sbox(57,6) -> 6;
+sbox(58,6) -> 13;
+sbox(59,6) -> 0;
+sbox(60,6) -> 11;
+sbox(61,6) -> 8;
+sbox(62,6) -> 6;
+sbox(63,6) -> 13;
+sbox(0,7) -> 4;
+sbox(1,7) -> 13;
+sbox(2,7) -> 11;
+sbox(3,7) -> 0;
+sbox(4,7) -> 2;
+sbox(5,7) -> 11;
+sbox(6,7) -> 14;
+sbox(7,7) -> 7;
+sbox(8,7) -> 15;
+sbox(9,7) -> 4;
+sbox(10,7) -> 0;
+sbox(11,7) -> 9;
+sbox(12,7) -> 8;
+sbox(13,7) -> 1;
+sbox(14,7) -> 13;
+sbox(15,7) -> 10;
+sbox(16,7) -> 3;
+sbox(17,7) -> 14;
+sbox(18,7) -> 12;
+sbox(19,7) -> 3;
+sbox(20,7) -> 9;
+sbox(21,7) -> 5;
+sbox(22,7) -> 7;
+sbox(23,7) -> 12;
+sbox(24,7) -> 5;
+sbox(25,7) -> 2;
+sbox(26,7) -> 10;
+sbox(27,7) -> 15;
+sbox(28,7) -> 6;
+sbox(29,7) -> 8;
+sbox(30,7) -> 1;
+sbox(31,7) -> 6;
+sbox(32,7) -> 1;
+sbox(33,7) -> 6;
+sbox(34,7) -> 4;
+sbox(35,7) -> 11;
+sbox(36,7) -> 11;
+sbox(37,7) -> 13;
+sbox(38,7) -> 13;
+sbox(39,7) -> 8;
+sbox(40,7) -> 12;
+sbox(41,7) -> 1;
+sbox(42,7) -> 3;
+sbox(43,7) -> 4;
+sbox(44,7) -> 7;
+sbox(45,7) -> 10;
+sbox(46,7) -> 14;
+sbox(47,7) -> 7;
+sbox(48,7) -> 10;
+sbox(49,7) -> 9;
+sbox(50,7) -> 15;
+sbox(51,7) -> 5;
+sbox(52,7) -> 6;
+sbox(53,7) -> 0;
+sbox(54,7) -> 8;
+sbox(55,7) -> 15;
+sbox(56,7) -> 0;
+sbox(57,7) -> 14;
+sbox(58,7) -> 5;
+sbox(59,7) -> 2;
+sbox(60,7) -> 9;
+sbox(61,7) -> 3;
+sbox(62,7) -> 2;
+sbox(63,7) -> 12;
+sbox(0,8) -> 13;
+sbox(1,8) -> 1;
+sbox(2,8) -> 2;
+sbox(3,8) -> 15;
+sbox(4,8) -> 8;
+sbox(5,8) -> 13;
+sbox(6,8) -> 4;
+sbox(7,8) -> 8;
+sbox(8,8) -> 6;
+sbox(9,8) -> 10;
+sbox(10,8) -> 15;
+sbox(11,8) -> 3;
+sbox(12,8) -> 11;
+sbox(13,8) -> 7;
+sbox(14,8) -> 1;
+sbox(15,8) -> 4;
+sbox(16,8) -> 10;
+sbox(17,8) -> 12;
+sbox(18,8) -> 9;
+sbox(19,8) -> 5;
+sbox(20,8) -> 3;
+sbox(21,8) -> 6;
+sbox(22,8) -> 14;
+sbox(23,8) -> 11;
+sbox(24,8) -> 5;
+sbox(25,8) -> 0;
+sbox(26,8) -> 0;
+sbox(27,8) -> 14;
+sbox(28,8) -> 12;
+sbox(29,8) -> 9;
+sbox(30,8) -> 7;
+sbox(31,8) -> 2;
+sbox(32,8) -> 7;
+sbox(33,8) -> 2;
+sbox(34,8) -> 11;
+sbox(35,8) -> 1;
+sbox(36,8) -> 4;
+sbox(37,8) -> 14;
+sbox(38,8) -> 1;
+sbox(39,8) -> 7;
+sbox(40,8) -> 9;
+sbox(41,8) -> 4;
+sbox(42,8) -> 12;
+sbox(43,8) -> 10;
+sbox(44,8) -> 14;
+sbox(45,8) -> 8;
+sbox(46,8) -> 2;
+sbox(47,8) -> 13;
+sbox(48,8) -> 0;
+sbox(49,8) -> 15;
+sbox(50,8) -> 6;
+sbox(51,8) -> 12;
+sbox(52,8) -> 10;
+sbox(53,8) -> 9;
+sbox(54,8) -> 13;
+sbox(55,8) -> 0;
+sbox(56,8) -> 15;
+sbox(57,8) -> 3;
+sbox(58,8) -> 3;
+sbox(59,8) -> 5;
+sbox(60,8) -> 5;
+sbox(61,8) -> 6;
+sbox(62,8) -> 8;
+sbox(63,8) -> 11.
diff --git a/lib/compiler/test/inline_SUITE_data/decode1.erl b/lib/compiler/test/inline_SUITE_data/decode1.erl
new file mode 100644
index 0000000000..d51bedcb2e
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/decode1.erl
@@ -0,0 +1,402 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%----------------------------------------------------------------------
+% decode1.erl (new version)
+%----------------------------------------------------------------------
+% -*- Erlang -*-
+% File: decode1.erl (~jb/decode/decode1.erl)
+% Author: Johan Bevemyr
+% Created: Tue Jan 14 09:33:49 1997
+% Purpose:
+% Notes: Rewritten for use in ETOS. (Happi)
+
+-module(decode1).
+
+-export([?MODULE/0,
+ decode_ie_heads_setup/1,
+ run_dummy/2,
+ run_orig/2]).
+
+?MODULE() ->
+ FrameList = [89,128,0,8,132,0,26,133,133,0,38,148,94,
+ 128,0,2,129,128,92,128,0,2,0,0,112,128,0,
+ 10,194,69,0,0,0,0,0,18,52,95],
+ Frame = concat_binary([list_to_binary([89]),list_to_binary([128]),
+ list_to_binary([0]),list_to_binary([8]),
+ list_to_binary([132]),list_to_binary([0]),
+ list_to_binary([26]),list_to_binary([133]),
+ list_to_binary([133]),list_to_binary([0]),
+ list_to_binary([38]),list_to_binary([148]),
+ list_to_binary([94]),list_to_binary([128]),
+ list_to_binary([0]),list_to_binary([2]),
+ list_to_binary([129]),list_to_binary([128]),
+ list_to_binary([92]),list_to_binary([128]),
+ list_to_binary([0]),list_to_binary([2]),
+ list_to_binary([0]),list_to_binary([0]),
+ list_to_binary([112]),list_to_binary([128]),
+ list_to_binary([0]),list_to_binary([10]),
+ list_to_binary([194]),list_to_binary([69]),
+ list_to_binary([0]),list_to_binary([0]),
+ list_to_binary([0]),list_to_binary([0]),
+ list_to_binary([0]),list_to_binary([18]),
+ list_to_binary([52]),list_to_binary([95])]),
+
+ R = loop(2,0,Frame),
+ {R,R =:= {0,[{ie,112,itu_t_standard,ignore,10,<<194,69,0,0,0,0,0,18,52,95>>},
+ {ie,92,itu_t_standard,ignore,2,<<0,0>>},
+ {ie,94,itu_t_standard,ignore,2,<<129,128>>},
+ {ie,89,itu_t_standard,ignore,8,<<132,0,26,133,133,0,38,148>>}]}}.
+
+loop(0,R,_) -> R;
+loop(N,R,Frame) -> loop(N-1, decode1:decode_ie_heads_setup(Frame),Frame).
+
+run_dummy(0,Frame) ->
+ done;
+run_dummy(N,Frame) ->
+ parse_dummy(Frame),
+ run_dummy(N-1,Frame).
+
+parse_dummy(Frame) -> true.
+
+run_orig(0,Frame) ->
+ done;
+run_orig(N,Frame) ->
+ decode1:decode_ie_heads_setup(Frame),
+ run_orig(N-1,Frame).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Macros
+%
+
+-define(VALID_ACTION(Flag), if ((Flag) band 16#10) == 16#10 -> true;
+ true -> false
+ end).
+-define(GET_ACTION(Flag), ((Flag) band 16#03)).
+
+-define(getint16(X1,X0), (16#100*X1 + X0)).
+
+-define(IS_EXTENDED(X), (if ((X) band 16#80) == 16#80 -> false;
+ true -> true
+ end)).
+
+
+%%% ----------------------------------------------------------
+%%% # ie
+%%% Description: Used to encapsulate the ie head
+%%% ----------------------------------------------------------
+
+
+-record(ie,{identifier,
+ coding,
+ action_ind,
+ length,
+ ie_body = binary}).
+
+%%% ----------------------------------------------------------
+%%% # bbc
+%%% Description: BROADBAND BEARER CAPABILITY
+%%% ----------------------------------------------------------
+
+-record(scct_bbc,
+ {scct_pci, % parameter compatibility info
+ scct_bearer_class,
+ scct_atm_transfer_capability,
+ scct_user_plane_connection_configuration,
+ scct_susceptibility_to_clipping}).
+
+
+%%% ----------------------------------------------------------
+%%% # cause
+%%% Description: CAUSE
+%%% ----------------------------------------------------------
+
+-record(scct_cause,
+ {scct_pci, % parameter compatibility info
+ scct_location,
+ scct_cause_value,
+ scct_diagnostics_list = []}).
+
+
+%%% ----------------------------------------------------------
+%%% # release_complete_uni
+%%% Description:
+%%% ----------------------------------------------------------
+
+-record(release_complete_uni,
+ {scct_cause_list=[], % Cause IE's in a list where each element
+ % is a record of scct_cause{}
+ scct_geidt_list=[]}). % Generic Identifier Transport IE's in a list
+ % where each element is a record of scct_geidt{}
+
+
+-define(IE_BB_BEARER_CAPABILITY, 16#5e).
+-define(SCCT_PUB_NETW_SERV_LOCAL_USR, 2).
+-define(SCCT_ERR_INVALID_IE_CONT, 100).
+-define(DECRES_THROW_RELCOMP, error_throw_relcomp).
+
+-define(SCCT_P_TO_P, 0).
+-define(SCCT_P_TO_MP, 1).
+
+-define(IE_ENDPT_REF, 16#54).
+-define(IE_BB_REPEAT_INDICATOR, 16#63).
+
+-define(SCCT_ERR_MAND_IE_MISSING, 96).
+
+-define(A_CLEAR_CALL, 0).
+-define(A_DISCARD_PROCEED, 1).
+-define(A_DISCARD_PROCEED_STATUS, 2).
+
+-define(SCCT_BCOB_A, 1).
+-define(SCCT_BCOB_C, 3).
+-define(SCCT_BCOB_X, 16).
+-define(SCCT_TRANSP_VP_SERV, 24).
+
+-define(SCCT_CBR, 5).
+-define(SCCT_CBR_WITH_CLR_CLP_0_1, 7).
+-define(SCCT_RT_VBR, 9).
+-define(SCCT_RT_VBR_WITH_CLR_CLP_0_1, 19).
+-define(SCCT_NON_RT_VBR, 10).
+-define(SCCT_NON_RT_VBR_WITH_CLR_CLP_0_1, 11).
+-define(SCCT_ABR, 12).
+-define(SCCT_NOT_SUSCEPT_TO_CLIPPING, 0).
+-define(SCCT_SUSCEPT_TO_CLIPPING, 1).
+
+
+
+%%% ----------------------------------------------------------
+%%% -type decode_ie_heads_setup(Bin)->
+%%%
+%%% Input: Binary to body of incoming Message
+%%% Output:
+%%%
+%%% Exceptions:
+%%% Description:decode_ie_heads_setup is used both p-p and p-mp setup
+%%% Never fails. Needs to be exported to be able to check
+%%% if setup is p-p or p-mp.
+%%% Note that if broadband rep indicator is present
+%%% order must be incoming IE's must be preserved, this
+%%% only applicable in msg setup
+%%% ----------------------------------------------------------
+decode_ie_heads_setup(Bin)->
+ decode_ie_heads_setup(Bin,no_bbc_ie,no_epr,[],no_brep).
+
+decode_ie_heads_setup(Bin,TypeOfCall,EprFlag,IEList,BrepFlag) when is_binary(Bin),size(Bin) >= 4 ->
+ {Bin1,Bin2} = split_binary(Bin,4),
+ [Id,F,L1,L0]= binary_to_list(Bin1),
+ Action = decode_action(F),
+ Coding = decode_ie_coding(F),
+ case ?getint16(L1,L0) of
+ Len when Len >0 ->
+ %%catch needed we cannot trust indata
+ case catch split_binary(Bin2,Len) of
+ {'EXIT',_} -> %%binary unpacked as far as possible
+ decode_ie_heads_setup(not_a_binary,TypeOfCall,EprFlag,
+ IEList,BrepFlag);
+ {Bin3,Bin4} ->
+ IE= #ie {identifier = Id,
+ coding = Coding,
+ action_ind= Action,
+ length= Len,
+ ie_body= Bin3},
+ case Id of
+ ?IE_BB_BEARER_CAPABILITY ->
+ BbcRec=#scct_bbc{},
+ %%catch needed we cannot trust indata
+ case catch
+ dec_bearer_capability(BbcRec,
+ binary_to_list(Bin3)) of
+ {'EXIT',_} -> %mand content error
+ CauseRec=#scct_cause{scct_location=
+ ?SCCT_PUB_NETW_SERV_LOCAL_USR,
+ scct_cause_value=
+ ?SCCT_ERR_INVALID_IE_CONT,
+ scct_diagnostics_list=
+ [?IE_BB_BEARER_CAPABILITY]},
+ RelCompUniMsg =
+ #release_complete_uni{scct_cause_list=
+ [CauseRec]},
+ {?DECRES_THROW_RELCOMP,RelCompUniMsg};
+ NewBbcRec ->
+ case NewBbcRec
+ #scct_bbc.scct_user_plane_connection_configuration of
+ ?SCCT_P_TO_P ->
+ decode_ie_heads_setup(Bin4,
+ ?SCCT_P_TO_P,
+ EprFlag,
+ [IE|IEList],
+ BrepFlag);
+ ?SCCT_P_TO_MP ->
+ decode_ie_heads_setup(Bin4,
+ ?SCCT_P_TO_MP,
+ EprFlag,
+ [IE|IEList],
+ BrepFlag)
+ end
+ end;
+ ?IE_ENDPT_REF ->
+ decode_ie_heads_setup(Bin4,TypeOfCall,yes_epr,
+ [IE|IEList],BrepFlag);
+ ?IE_BB_REPEAT_INDICATOR ->
+ decode_ie_heads_setup(Bin4,TypeOfCall,EprFlag,
+ [IE|IEList],yes_brep);
+ _ ->
+ decode_ie_heads_setup(Bin4,TypeOfCall,EprFlag,
+ [IE|IEList],BrepFlag)
+ end
+ end;
+ Len when Len == 0 ->%ie body empty, treat as if whole ie was missing
+ decode_ie_heads_setup(Bin2,TypeOfCall,EprFlag,IEList,BrepFlag)
+ end;
+decode_ie_heads_setup(_,?SCCT_P_TO_MP,yes_epr,IEList,no_brep) ->
+ {?SCCT_P_TO_MP,IEList};
+decode_ie_heads_setup(_,?SCCT_P_TO_MP,yes_epr,IEList,yes_brep) ->
+%Order of incoming IEs must be preserved since BroadB Repeat Ind is present
+ {?SCCT_P_TO_MP,reverse(IEList)};
+decode_ie_heads_setup(_,?SCCT_P_TO_MP,no_epr,_,no_brep) ->
+ CauseRec=#scct_cause{scct_location=?SCCT_PUB_NETW_SERV_LOCAL_USR,
+ scct_cause_value=?SCCT_ERR_MAND_IE_MISSING,
+ scct_diagnostics_list=[?IE_ENDPT_REF]},
+ RelCompUniMsg =#release_complete_uni{scct_cause_list=[CauseRec]},
+ {?DECRES_THROW_RELCOMP,RelCompUniMsg};
+decode_ie_heads_setup(_,?SCCT_P_TO_P,_,IEList,no_brep) ->
+ {?SCCT_P_TO_P,IEList};
+decode_ie_heads_setup(_,?SCCT_P_TO_P,_,IEList,yes_brep) ->
+%Order of incoming IEs must be preserved since BrodB Repeat Ind is present
+ {?SCCT_P_TO_P,reverse(IEList)};
+decode_ie_heads_setup(_,no_bbc_ie,_,_,_) ->
+ CauseRec=#scct_cause{scct_location=?SCCT_PUB_NETW_SERV_LOCAL_USR,
+ scct_cause_value=?SCCT_ERR_MAND_IE_MISSING,
+ scct_diagnostics_list=[?IE_BB_BEARER_CAPABILITY]},
+ RelCompUniMsg =#release_complete_uni{scct_cause_list=[CauseRec]},
+ {?DECRES_THROW_RELCOMP,RelCompUniMsg}.
+
+
+
+%%%
+%%% Decode message type and header
+%%%
+
+decode_action(Flag) ->
+ case ?VALID_ACTION(Flag) of
+ true ->
+ case ?GET_ACTION(Flag) of
+ ?A_CLEAR_CALL -> clear_call;
+ ?A_DISCARD_PROCEED -> discard_proceed;
+ ?A_DISCARD_PROCEED_STATUS -> discard_proceed_status;
+ _ -> undefined
+ end;
+ false ->
+ ignore
+ end.
+
+
+%%%
+%%% Decode ie coding
+%%%
+
+decode_ie_coding(F) ->
+ case F band 16#60 of
+ 0 -> itu_t_standard;
+ 16#60 -> atm_forum_specific;
+ _ -> undefined
+ end.
+
+
+%%% --------------------------------------------------------------------------
+%%%
+%%% Decode of INFORMATION ELEMENT: Broadband Bearer Capability
+%%%
+%%% --------------------------------------------------------------------------
+
+dec_bearer_capability(BbcRec, [Octet5 | Rest]) ->
+ NewBbcRec =
+ case Octet5 band 16#1f of
+ 16#01 ->
+ BbcRec#scct_bbc{scct_bearer_class = ?SCCT_BCOB_A};
+ 16#03 ->
+ BbcRec#scct_bbc{scct_bearer_class = ?SCCT_BCOB_C};
+ 16#10 ->
+ BbcRec#scct_bbc{scct_bearer_class = ?SCCT_BCOB_X};
+ 16#18 ->
+ BbcRec#scct_bbc{scct_bearer_class = ?SCCT_TRANSP_VP_SERV}
+ end,
+
+ case ?IS_EXTENDED(Octet5) of
+ true ->
+ dec_bearer_capability_5a(NewBbcRec, Rest);
+ false ->
+ dec_bearer_capability_6(NewBbcRec, Rest)
+ end.
+
+dec_bearer_capability_5a(BbcRec,[Octet5a | Rest]) ->
+ NewBbcRec =
+ case Octet5a band 16#7f of
+ 16#05 ->
+ BbcRec#scct_bbc{scct_atm_transfer_capability =
+ ?SCCT_CBR};
+ 16#07 ->
+ BbcRec#scct_bbc{scct_atm_transfer_capability =
+ ?SCCT_CBR_WITH_CLR_CLP_0_1};
+ 16#09 ->
+ BbcRec#scct_bbc{scct_atm_transfer_capability =
+ ?SCCT_RT_VBR};
+ 16#13 ->
+ BbcRec#scct_bbc{scct_atm_transfer_capability =
+ ?SCCT_RT_VBR_WITH_CLR_CLP_0_1};
+ 16#0a ->
+ BbcRec#scct_bbc{scct_atm_transfer_capability =
+ ?SCCT_NON_RT_VBR};
+ 16#0b ->
+ BbcRec#scct_bbc{scct_atm_transfer_capability =
+ ?SCCT_NON_RT_VBR_WITH_CLR_CLP_0_1};
+ 16#0c ->
+ BbcRec#scct_bbc{scct_atm_transfer_capability =
+ ?SCCT_ABR}
+ end,
+ dec_bearer_capability_6(NewBbcRec,Rest).
+
+
+dec_bearer_capability_6(BbcRec, [Octet6]) ->
+ STC =
+ case (Octet6 bsr 5) band 16#03 of
+ 16#00 ->
+ ?SCCT_NOT_SUSCEPT_TO_CLIPPING;
+ 16#01 ->
+ ?SCCT_SUSCEPT_TO_CLIPPING
+ end,
+
+ UPCC =
+ case Octet6 band 16#03 of
+ 16#00 ->
+ ?SCCT_P_TO_P;
+ 16#01 ->
+ ?SCCT_P_TO_MP
+ end,
+
+ NewBbcRec = BbcRec#scct_bbc{scct_susceptibility_to_clipping = STC,
+ scct_user_plane_connection_configuration = UPCC}.
+
+
+reverse(L) ->
+ reverse(L,[]).
+
+reverse([E|Rest],Acc) ->
+ reverse(Rest,[E|acc]);
+reverse([],Acc) -> Acc.
diff --git a/lib/compiler/test/inline_SUITE_data/itracer.erl b/lib/compiler/test/inline_SUITE_data/itracer.erl
new file mode 100644
index 0000000000..93f24e9bb1
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/itracer.erl
@@ -0,0 +1,407 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(itracer).
+-export([itracer/0]).
+
+%%%---------------------------------------------------------------------------
+%%%
+%%% This is a little raytracer.
+%%%
+%%%---------------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------------
+%% Constructors.
+%%----------------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------------
+%%
+%%----------------------------------------------------------------------------
+
+itracer() ->
+ C1 = ccreate(),
+ C2 = set_width(C1,100),
+ C3 = set_height(C2,100),
+ C4 = initialize(C3),
+ Sphere1 = screate(40,vcreate(35,10,0),{1,0,0}),
+ Sphere2 = screate(35,vcreate(-25,-25,50),{0,1,0}),
+ PL = traceloop(C4,50,50,[Sphere1,Sphere2]).
+
+
+%%----------------------------------------------------------------------------
+%%
+%%----------------------------------------------------------------------------
+
+overflow_prevent(A) when A<1 -> A;
+overflow_prevent(_) -> 1.
+
+
+%%----------------------------------------------------------------------------
+%%
+%%----------------------------------------------------------------------------
+
+traceloop(Camera,Width,Height,Scene) ->
+ traceloop(Camera,Width,Height,0,0,Scene,[]).
+
+
+traceloop(_,_,Height,_,Y,_,PL) when Height=<Y ->
+ PL;
+
+traceloop(Camera,Width,Height,X,Y,Scene,PL) when Width=<X ->
+ traceloop(Camera,Width,Height,0,Y+1,Scene,PL);
+
+traceloop(Camera,Width,Height,X,Y,Scene,PL) ->
+ Ray = ray(Camera,X/Width,Y/Height),
+ {R1,G1,B1} = traceray(Ray,Scene,1),
+ R2 = overflow_prevent(R1),
+ G2 = overflow_prevent(G1),
+ B2 = overflow_prevent(B1),
+ P = {trunc(R2*255), trunc(G2*255), trunc(B2*255)},
+ traceloop(Camera,Width,Height,X+1,Y,Scene,[{X,Y,P}|PL]).
+
+
+%%----------------------------------------------------------------------------
+%%
+%%----------------------------------------------------------------------------
+
+traceray(Ray,Scene,Level) ->
+ Hit = findintersection(Ray,Scene,Level),
+ case Hit of
+ nohit -> {0,0,0};
+ {[T|Ts],Object} -> shaderay(Ray,Scene,Level,T,Object)
+ end.
+
+
+%%----------------------------------------------------------------------------
+%%
+%%----------------------------------------------------------------------------
+
+% Here we loop through all the objects in the scene to find the
+% closest intersection.
+
+findintersection(_,[],_) -> nohit;
+
+findintersection(Ray,[Object|Objects],Level) ->
+ Ts = intersection(Object,Ray),
+ Hit1 = findintersection(Ray,Objects,Level),
+ Hit2 = closesthit(Ts,Object,Hit1).
+
+
+closesthit(nohit,_,nohit) -> nohit;
+closesthit(nohit,_,{[T|Ts],Obj}) when T>0 -> {[T|Ts],Obj};
+closesthit(nohit,_,_) -> nohit;
+closesthit([T|Ts],Obj,nohit) when T>0 -> {[T|Ts],Obj};
+closesthit(_,_,nohit) -> nohit;
+closesthit([T1|Ts1],Obj1,{[T2|Ts2],Obj2}) when T1>0,T1<T2 -> {[T1|Ts1],Obj1};
+closesthit([T1|Ts1],Obj1,{[T2|Ts2],Obj2}) when T2>0,T2<T1 -> {[T2|Ts2],Obj2};
+closesthit(_,_,_) -> nohit.
+
+
+
+%%----------------------------------------------------------------------------
+%%
+%%----------------------------------------------------------------------------
+
+shaderay(Ray,Scene,Level,T,Object) ->
+ Direction = get_direction(Ray),
+ Origin = get_origin(Ray),
+ Point = add(Origin, mul(T, Direction)),
+ Normal = calcnormal(Object, Point),
+ Diffuse = -dot(Normal, Direction),
+ ReflectionVector = reflection(Ray,Normal),
+ NewOrigin = add(Point, mul(0.0001, Normal)),
+ ReflectionRay = rcreate(NewOrigin,ReflectionVector),
+ {Red1,Green1,Blue1} = get_color(Object),
+ if
+ Level<4, Diffuse>0 ->
+ {Red2,Green2,Blue2} = traceray(ReflectionRay,Scene,Level+1),
+ {Diffuse*Red1 + 0.5*Red2,
+ Diffuse*Green1 + 0.5*Green2,
+ Diffuse*Blue1 + 0.5*Blue2};
+ Level<4, Diffuse<0 ->
+ {0,0,0};
+ true ->
+ {0,0,0}
+ end.
+
+
+%%----------------------------------------------------------------------------
+%% Har nedan foljer bara ett gang testfunktioner....
+%%----------------------------------------------------------------------------
+-record(camera,{width,height,zoom,position,lookat,up,right,down,corner}).
+
+%%%---------------------------------------------------------------------------
+%%%
+%%% Useful camera operations.
+%%%
+%%%---------------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------------
+%% Constructors.
+%%----------------------------------------------------------------------------
+
+ccreate() ->
+ #camera{width=100, height=100, zoom=256,
+ position = vcreate(0,0,-256),
+ lookat = vcreate(0,0,0),
+ up = vcreate(0,1,0)}.
+
+
+
+%%----------------------------------------------------------------------------
+%% Selectors and modifiers.
+%%----------------------------------------------------------------------------
+
+set_width(C,Width) -> C#camera{width=Width}.
+set_height(C,Height) -> C#camera{height=Height}.
+set_zoom(C,Zoom) -> C#camera{zoom=Zoom}.
+cset_position(C,Pos) -> C#camera{position=Pos}.
+set_lookat(C,Lookat) -> C#camera{lookat=Lookat}.
+set_up(C,Up) -> C#camera{up=Up}.
+
+get_width(C) -> C#camera.width.
+get_height(C) -> C#camera.height.
+get_zoom(C) -> C#camera.zoom.
+cget_position(C) -> C#camera.position.
+get_lookat(C) -> C#camera.lookat.
+get_up(C) -> C#camera.up.
+
+
+
+%%----------------------------------------------------------------------------
+%% Operators.
+%%----------------------------------------------------------------------------
+
+initialize(C) ->
+ Dir = normalize(sub(C#camera.lookat, C#camera.position)),
+ Up1 = normalize(C#camera.up),
+ D = dot(Up1, Dir),
+ Up2 = normalize(sub(Up1, mul(D, Dir))),
+ Down = mul(-1, Up2),
+ Right = normalize(cross(Up2,Dir)),
+ Corner1 = mul(C#camera.zoom, Dir),
+ Corner2 = add(Corner1, mul(-C#camera.width/2, Right)),
+ Corner3 = add(Corner2, mul(-C#camera.height/2, Down)),
+ C2 = C#camera{down=Down, right=Right, corner=Corner3}.
+
+
+%
+% X och Y ska ligga i intervallet [0..1]
+%
+ray(C,X,Y) ->
+ Right = mul(C#camera.width*X, C#camera.right),
+ Down = mul(C#camera.height*Y, C#camera.down),
+ Point = add(C#camera.corner, add(Right,Down)),
+ rcreate(C#camera.position,normalize(Point)).
+
+
+
+%%----------------------------------------------------------------------------
+%% E N D O F F I L E
+%%----------------------------------------------------------------------------
+-record(vector,{x,y,z}).
+
+
+%%%---------------------------------------------------------------------------
+%%%
+%%% Useful vector operations.
+%%%
+%%%---------------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------------
+%% Constructors.
+%%----------------------------------------------------------------------------
+
+vcreate() ->
+ #vector{x=0,y=0,z=0}.
+
+
+vcreate(X,Y,Z) ->
+ #vector{x=X,y=Y,z=Z}.
+
+
+
+%%----------------------------------------------------------------------------
+%% Selectors and modifiers.
+%%----------------------------------------------------------------------------
+
+set_x(V,X) -> V#vector{x=X}.
+set_y(V,Y) -> V#vector{y=Y}.
+set_z(V,Z) -> V#vector{z=Z}.
+
+get_x(V) -> V#vector.x.
+get_y(V) -> V#vector.y.
+get_z(V) -> V#vector.z.
+
+
+
+%%----------------------------------------------------------------------------
+%% Operators.
+%%----------------------------------------------------------------------------
+
+add(A,B) ->
+ #vector{x=A#vector.x+B#vector.x,
+ y=A#vector.y+B#vector.y,
+ z=A#vector.z+B#vector.z}.
+
+
+sub(A,B) ->
+ #vector{x=A#vector.x-B#vector.x,
+ y=A#vector.y-B#vector.y,
+ z=A#vector.z-B#vector.z}.
+
+
+mul(T,A) ->
+ #vector{x=A#vector.x * T,
+ y=A#vector.y * T,
+ z=A#vector.z * T}.
+
+
+dot(A,B) ->
+ A#vector.x*B#vector.x +
+ A#vector.y*B#vector.y +
+ A#vector.z*B#vector.z.
+
+
+normalize(A) ->
+ S = 1 / math:sqrt(dot(A,A)),
+ vcreate(A#vector.x * S, A#vector.y * S, A#vector.z * S).
+
+
+cross(A,B) ->
+ #vector{x = A#vector.y*B#vector.z - A#vector.z*B#vector.y,
+ y = A#vector.z*B#vector.x - A#vector.x*B#vector.z,
+ z = A#vector.x*B#vector.y - A#vector.y*B#vector.x}.
+
+
+%%----------------------------------------------------------------------------
+%% E N D O F F I L E
+%%----------------------------------------------------------------------------
+-record(ray,{origin,direction}).
+
+%%%---------------------------------------------------------------------------
+%%%
+%%% Useful ray stuff.
+%%%
+%%%---------------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------------
+%% Constructors.
+%%----------------------------------------------------------------------------
+
+rcreate() ->
+ #ray{origin=vcreate(0,0,0), direction=vcreate(0,0,1)}.
+
+
+rcreate(Origin,Direction) ->
+ #ray{origin=Origin, direction=Direction}.
+
+
+
+%%----------------------------------------------------------------------------
+%% Selectors and modifiers.
+%%----------------------------------------------------------------------------
+
+set_origin(R,Origin) -> R#ray{origin=Origin}.
+set_direction(R,Direction) -> R#ray{direction=Direction}.
+
+get_origin(R) -> R#ray.origin.
+get_direction(R) -> R#ray.direction.
+
+
+
+%%----------------------------------------------------------------------------
+%%
+%%----------------------------------------------------------------------------
+
+reflection(R,N) ->
+ A = mul(2*dot(N, R#ray.direction), N),
+ normalize(sub(R#ray.direction, A)).
+
+
+
+%%----------------------------------------------------------------------------
+%% E N D O F F I L E
+%%----------------------------------------------------------------------------
+-record(sphere,{radius,position,color}).
+
+%%%---------------------------------------------------------------------------
+%%%
+%%% Useful sphere operations.
+%%%
+%%%---------------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------------
+%% Constructors.
+%%----------------------------------------------------------------------------
+
+screate() ->
+ #sphere{radius=1, position=vcreate(0,0,0), color={1,1,1}}.
+
+
+screate(Radius,Position,Color) ->
+ #sphere{radius=Radius, position=Position, color=Color}.
+
+
+
+%%----------------------------------------------------------------------------
+%% Selectors and modifiers.
+%%----------------------------------------------------------------------------
+
+set_radius(S,Radius) -> S#sphere{radius=Radius}.
+sset_position(S,Position) -> S#sphere{position=Position}.
+set_color(S,Color) -> S#sphere{color=Color}.
+
+get_radius(S) -> S#sphere.radius.
+sget_position(S) -> S#sphere.position.
+get_color(S) -> S#sphere.color.
+
+
+
+%%----------------------------------------------------------------------------
+%% Calculates the intersection between a ray and the sphere.
+%%----------------------------------------------------------------------------
+
+intersection(S,Ray) ->
+ SR = sub(S#sphere.position,get_origin(Ray)),
+ B = dot(SR,get_direction(Ray)),
+ C = dot(SR,SR),
+ Root = B*B-C + S#sphere.radius * S#sphere.radius,
+ if
+ Root>0 ->
+ SquareRoot = math:sqrt(Root),
+ [B-SquareRoot,B+SquareRoot];
+ true ->
+ nohit
+ end.
+
+calcnormal(S,P) ->
+ normalize(sub(P, S#sphere.position)).
+ %mul(1/S#sphere.radius, sub(P, S#sphere.position)).
+
+
+
+%%----------------------------------------------------------------------------
+%% E N D O F F I L E
+%%----------------------------------------------------------------------------
diff --git a/lib/compiler/test/inline_SUITE_data/pseudoknot.erl b/lib/compiler/test/inline_SUITE_data/pseudoknot.erl
new file mode 100644
index 0000000000..5b2bf1694a
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/pseudoknot.erl
@@ -0,0 +1,2575 @@
+-module(pseudoknot).
+
+-export([?MODULE/0]).
+
+?MODULE() ->
+ R = loop(1, 0),
+ abs(R-33.7976) < 0.0001.
+
+append([H|T], Z) ->
+ [H|append(T, Z)];
+append([], X) ->
+ X.
+
+atan2(Y,X) when X>0.0 ->
+ math:atan(Y/X);
+atan2(Y,X) when Y<0.0 ->
+ if
+ X == 0.0 -> -1.57079632679489661923;
+ true -> math:atan(Y/X) - 3.14159265358979323846
+ end;
+atan2(Y,X) ->
+ if
+ X == 0.0 -> 1.57079632679489661923;
+ true -> math:atan(Y/X) + 3.14159265358979323846
+ end.
+
+% -- POINTS ------------------------------------------------------------------
+
+%pt ::= {X, Y, Z} where X,Y,Z are floats
+
+pt_sub({X1, Y1, Z1}, {X2, Y2, Z2})
+ when is_float(X1), is_float(Y1), is_float(Z1),
+ is_float(X2), is_float(Y2), is_float(Z2) ->
+ {X1 - X2, Y1 - Y2, Z1 - Z2}.
+
+pt_dist({X1, Y1, Z1}, {X2, Y2, Z2})
+ when is_float(X1), is_float(Y1), is_float(Z1),
+ is_float(X2), is_float(Y2), is_float(Z2) ->
+ Dx = X1 - X2,
+ Dy = Y1 - Y2,
+ Dz = Z1 - Z2,
+ math:sqrt(Dx * Dx + Dy * Dy + Dz * Dz).
+
+pt_phi({X, Y, Z})
+ when is_float(X), is_float(Z) ->
+ B = atan2(X, Z),
+ atan2(math:cos(B) * Z + math:sin(B) * X, Y).
+
+pt_theta ({X, _, Z}) ->
+ atan2(X, Z).
+
+% -- COORDINATE TRANSFORMATIONS ----------------------------------------------
+
+% The notation for the transformations follows "Paul, R.P. (1981) Robot
+% Manipulators. MIT Press." with the exception that our transformation
+% matrices don't have the perspective terms and are the transpose of
+% Paul's one. See also "M\"antyl\"a, M. (1985) An Introduction to
+% Solid Modeling, Computer Science Press" Appendix A.
+%
+% The components of a transformation matrix are named like this:
+%
+% a b c
+% d e f
+% g h i
+% tx ty tz
+%
+% The components tx, ty, and tz are the translation vector.
+
+%tfo ::= {A,B,C,D,E,F,G,H,I,Tx,Ty,Tz} where all elements are floats
+
+tfo_id() -> {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}.
+
+% The function "tfo-apply" multiplies a transformation matrix, tfo, by a
+% point vector, p. The result is a new point.
+
+tfo_apply ({A,B,C,D,E,F,G,H,I,Tx,Ty,Tz}, {X,Y,Z})
+ when is_float(A), is_float(B), is_float(C), is_float(D), is_float(E),
+ is_float(F), is_float(G), is_float(H), is_float(I),
+ is_float(Tx), is_float(Ty), is_float(Tz), is_float(X), is_float(Y), is_float(Z) ->
+ {X * A + Y * D + Z * G + Tx,
+ X * B + Y * E + Z * H + Ty,
+ X * C + Y * F + Z * I + Tz}.
+
+% The function "tfo-combine" multiplies two transformation matrices A and B.
+% The result is a new matrix which cumulates the transformations described
+% by A and B.
+
+tfo_combine({A_a,A_b,A_c,A_d,A_e,A_f,A_g,A_h,A_i,A_tx,A_ty,A_tz},
+ {B_a,B_b,B_c,B_d,B_e,B_f,B_g,B_h,B_i,B_tx,B_ty,B_tz})
+ when is_float(A_a), is_float(A_b), is_float(A_c), is_float(A_d), is_float(A_e),
+ is_float(A_f), is_float(A_g), is_float(A_h), is_float(A_i), is_float(A_tx),
+ is_float(A_ty), is_float(A_tz),
+ is_float(B_a), is_float(B_b), is_float(B_c), is_float(B_d), is_float(B_e),
+ is_float(B_f), is_float(B_g), is_float(B_h), is_float(B_i), is_float(B_tx),
+ is_float(B_ty), is_float(B_tz) ->
+ {A_a * B_a + A_b * B_d + A_c * B_g,
+ A_a * B_b + A_b * B_e + A_c * B_h,
+ A_a * B_c + A_b * B_f + A_c * B_i,
+ A_d * B_a + A_e * B_d + A_f * B_g,
+ A_d * B_b + A_e * B_e + A_f * B_h,
+ A_d * B_c + A_e * B_f + A_f * B_i,
+ A_g * B_a + A_h * B_d + A_i * B_g,
+ A_g * B_b + A_h * B_e + A_i * B_h,
+ A_g * B_c + A_h * B_f + A_i * B_i,
+ A_tx * B_a + A_ty * B_d + A_tz * B_g + B_tx,
+ A_tx * B_b + A_ty * B_e + A_tz * B_h + B_ty,
+ A_tx * B_c + A_ty * B_f + A_tz * B_i + B_tz}.
+
+% The function "tfo-inv-ortho" computes the inverse of a homogeneous
+% transformation matrix.
+
+tfo_inv_ortho({A,B,C,D,E,F,G,H,I,Tx,Ty,Tz})
+ when is_float(A), is_float(B), is_float(C), is_float(D), is_float(E), is_float(F),
+ is_float(G), is_float(H), is_float(I), is_float(Tx), is_float(Ty), is_float(Tz) ->
+ {A,D,G,
+ B,E,H,
+ C,F,I,
+ -(A * Tx + B * Ty + C * Tz),
+ -(D * Tx + E * Ty + F * Tz),
+ -(G * Tx + H * Ty + I * Tz)}.
+
+% Given three points p1, p2, and p3, the function "tfo-align" computes
+% a transformation matrix such that point p1 gets mapped to (0,0,0), p2 gets
+% mapped to the Y axis and p3 gets mapped to the YZ plane.
+
+tfo_align({X1,Y1,Z1},{X2,Y2,Z2},{X3,Y3,Z3})
+ when is_float(X1), is_float(Y1), is_float(Z1),
+ is_float(X2), is_float(Y2), is_float(Z2),
+ is_float(X3), is_float(Y3), is_float(Z3) ->
+ X31 = X3 - X1,
+ Y31 = Y3 - Y1,
+ Z31 = Z3 - Z1,
+ Rotpy = pt_sub({X2,Y2,Z2},{X1,Y1,Z1}),
+ Phi = pt_phi(Rotpy),
+ Theta = pt_theta(Rotpy),
+ Sinp = math:sin(Phi),
+ Sint = math:sin(Theta),
+ Cosp = math:cos(Phi),
+ Cost = math:cos(Theta),
+ Sinpsint = Sinp * Sint,
+ Sinpcost = Sinp * Cost,
+ Cospsint = Cosp * Sint,
+ Cospcost = Cosp * Cost,
+ Rotpz = {Cost * X31 - Sint * Z31,
+ Sinpsint * X31 + Cosp * Y31 + Sinpcost * Z31,
+ Cospsint * X31 - Sinp * Y31 + Cospcost * Z31},
+ Rho = pt_theta(Rotpz),
+ Cosr = math:cos(Rho),
+ Sinr = math:sin(Rho),
+ X = Z1 * Sint - X1 * Cost,
+ Y = -X1 * Sinpsint - Y1 * Cosp - Z1 * Sinpcost,
+ Z = Y1 * Sinp - Z1 * Cospcost - X1 * Cospsint,
+ {Cost * Cosr - Cospsint * Sinr,
+ Sinpsint,
+ Cost * Sinr + Cospsint * Cosr,
+ Sinp * Sinr,
+ Cosp,
+ -Sinp * Cosr,
+ -Sint * Cosr - Cospcost * Sinr,
+ Sinpcost,
+ Cospcost * Cosr - Sint * Sinr,
+ X * Cosr - Z * Sinr,
+ Y,
+ X * Sinr + Z * Cosr}.
+
+% -- NUCLEIC ACID CONFORMATIONS DATA BASE ------------------------------------
+
+% Numbering of atoms follows the paper:
+%
+% IUPAC-IUB Joint Commission on Biochemical Nomenclature (JCBN)
+% (1983) Abbreviations and Symbols for the Description of
+% Conformations of Polynucleotide Chains. Eur. J. Biochem 131,
+% 9-15.
+
+% Define part common to all 4 nucleotide types.
+
+%nuc ::= {
+% tfo,tfo,tfo,tfo,
+% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,
+% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,
+% A/C/G/U,
+% nuc_specific
+% }
+
+% dgf_base_tfo ; defines the standard position for wc and wc_dumas
+% p_o3'_275_tfo ; defines the standard position for the connect function
+% p_o3'_180_tfo
+% p_o3'_60_tfo
+% p o1p o2p o5' c5' h5' h5'' c4' h4' o4' c1' h1' c2' h2'' o2' h2' c3'
+% h3' o3' n1 n3 c2 c4 c5 c6
+
+type({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,X,
+ _}) -> X.
+
+nuc_C1_({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,X,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _}) -> X.
+
+nuc_C2({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,X,_,_,_,_,
+ _}) -> X.
+
+nuc_C3_({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ X,_,_,_,_,_,_,_,_,_,
+ _}) -> X.
+
+nuc_C4({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,X,_,_,_,
+ _}) -> X.
+
+nuc_C4_({_,_,_,_,_,_,_,_,_,_,
+ _,X,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _}) -> X.
+
+nuc_N1({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,X,_,_,_,_,_,_,
+ _}) -> X.
+
+nuc_O3_({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,X,_,_,_,_,_,_,_,
+ _}) -> X.
+
+nuc_P({_,_,_,_,X,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _}) -> X.
+
+nuc_dgf_base_tfo({X,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _}) -> X.
+
+nuc_p_o3__180_tfo({_,_,X,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _}) -> X.
+
+nuc_p_o3__275_tfo({_,X,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _}) -> X.
+
+nuc_p_o3__60_tfo({_,_,_,X,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _}) -> X.
+
+rA_N9({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,a,
+ {_,_,X,_,_,_,_,_}}) -> X.
+
+rG_N9({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,g,
+ {_,_,X,_,_,_,_,_,_}}) -> X.
+
+
+%nuc ::= {
+% tfo,tfo,tfo,tfo,
+% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,
+% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,
+% A/C/G/U,
+% nuc_specific
+% }
+
+% Define remaining atoms for each nucleotide type.
+
+%nuc_specific
+% a {N6,N7,N9,C8,H2,H61,H62,H8}
+% c {N4,O2,H41,H42,H5,H6}
+% g {N2,N7,N9,C8,O6,H1,H21,H22,H8}
+% u {O2,O4,H3,H5,H6}
+
+% Database of nucleotide conformations:
+
+rA() ->
+ {
+ {-0.0018, -0.8207, 0.5714, % dgf_base_tfo
+ 0.2679, -0.5509, -0.7904,
+ 0.9634, 0.1517, 0.2209,
+ 0.0073, 8.4030, 0.6232},
+ {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo
+ -0.0433, -0.4257, 0.9038,
+ -0.5788, 0.7480, 0.3246,
+ 1.5227, 6.9114, -7.0765},
+ {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo
+ 0.4552, 0.6637, 0.5935,
+ -0.8042, 0.0203, 0.5941,
+ -6.9472, -4.1186, -5.9108},
+ {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo
+ -0.8247, 0.5587, -0.0878,
+ 0.0426, 0.2162, 0.9754,
+ 6.2694, -7.0540, 3.3316},
+ {2.8930, 8.5380, -3.3280}, % P
+ {1.6980, 7.6960, -3.5570}, % O1P
+ {3.2260, 9.5010, -4.4020}, % O2P
+ {4.1590, 7.6040, -3.0340}, % O5'
+ {5.4550, 8.2120, -2.8810}, % C5'
+ {5.4546, 8.8508, -1.9978}, % H5'
+ {5.7588, 8.6625, -3.8259}, % H5''
+ {6.4970, 7.1480, -2.5980}, % C4'
+ {7.4896, 7.5919, -2.5214}, % H4'
+ {6.1630, 6.4860, -1.3440}, % O4'
+ {6.5400, 5.1200, -1.4190}, % C1'
+ {7.2763, 4.9681, -0.6297}, % H1'
+ {7.1940, 4.8830, -2.7770}, % C2'
+ {6.8667, 3.9183, -3.1647}, % H2''
+ {8.5860, 5.0910, -2.6140}, % O2'
+ {8.9510, 4.7626, -1.7890}, % H2'
+ {6.5720, 6.0040, -3.6090}, % C3'
+ {5.5636, 5.7066, -3.8966}, % H3'
+ {7.3801, 6.3562, -4.7350}, % O3'
+ {4.7150, 0.4910, -0.1360}, % N1
+ {6.3490, 2.1730, -0.6020}, % N3
+ {5.9530, 0.9650, -0.2670}, % C2
+ {5.2900, 2.9790, -0.8260}, % C4
+ {3.9720, 2.6390, -0.7330}, % C5
+ {3.6770, 1.3160, -0.3660}, % C6
+ a, {
+ {2.4280, 0.8450, -0.2360}, % N6
+ {3.1660, 3.7290, -1.0360}, % N7
+ {5.3170, 4.2990, -1.1930}, % N9
+ {4.0100, 4.6780, -1.2990}, % C8
+ {6.6890, 0.1903, -0.0518}, % H2
+ {1.6470, 1.4460, -0.4040}, % H61
+ {2.2780, -0.1080, -0.0280}, % H62
+ {3.4421, 5.5744, -1.5482}} % H8
+ }.
+
+rA01() ->
+ {
+ {-0.0043, -0.8175, 0.5759, % dgf_base_tfo
+ 0.2617, -0.5567, -0.7884,
+ 0.9651, 0.1473, 0.2164,
+ 0.0359, 8.3929, 0.5532},
+ {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo
+ -0.0433, -0.4257, 0.9038,
+ -0.5788, 0.7480, 0.3246,
+ 1.5227, 6.9114, -7.0765},
+ {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo
+ 0.4552, 0.6637, 0.5935,
+ -0.8042, 0.0203, 0.5941,
+ -6.9472, -4.1186, -5.9108},
+ {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo
+ -0.8247, 0.5587, -0.0878,
+ 0.0426, 0.2162, 0.9754,
+ 6.2694, -7.0540, 3.3316},
+ {2.8930, 8.5380, -3.3280}, % P
+ {1.6980, 7.6960, -3.5570}, % O1P
+ {3.2260, 9.5010, -4.4020}, % O2P
+ {4.1590, 7.6040, -3.0340}, % O5'
+ {5.4352, 8.2183, -2.7757}, % C5'
+ {5.3830, 8.7883, -1.8481}, % H5'
+ {5.7729, 8.7436, -3.6691}, % H5''
+ {6.4830, 7.1518, -2.5252}, % C4'
+ {7.4749, 7.5972, -2.4482}, % H4'
+ {6.1626, 6.4620, -1.2827}, % O4'
+ {6.5431, 5.0992, -1.3905}, % C1'
+ {7.2871, 4.9328, -0.6114}, % H1'
+ {7.1852, 4.8935, -2.7592}, % C2'
+ {6.8573, 3.9363, -3.1645}, % H2''
+ {8.5780, 5.1025, -2.6046}, % O2'
+ {8.9516, 4.7577, -1.7902}, % H2'
+ {6.5522, 6.0300, -3.5612}, % C3'
+ {5.5420, 5.7356, -3.8459}, % H3'
+ {7.3487, 6.4089, -4.6867}, % O3'
+ {4.7442, 0.4514, -0.1390}, % N1
+ {6.3687, 2.1459, -0.5926}, % N3
+ {5.9795, 0.9335, -0.2657}, % C2
+ {5.3052, 2.9471, -0.8125}, % C4
+ {3.9891, 2.5987, -0.7230}, % C5
+ {3.7016, 1.2717, -0.3647}, % C6
+ a, {
+ {2.4553, 0.7925, -0.2390}, % N6
+ {3.1770, 3.6859, -1.0198}, % N7
+ {5.3247, 4.2695, -1.1710}, % N9
+ {4.0156, 4.6415, -1.2759}, % C8
+ {6.7198, 0.1618, -0.0547}, % H2
+ {1.6709, 1.3900, -0.4039}, % H61
+ {2.3107, -0.1627, -0.0373}, % H62
+ {3.4426, 5.5361, -1.5199}} % H8
+ }.
+
+rA02() ->
+ {
+ {0.5566, 0.0449, 0.8296, % dgf_base_tfo
+ 0.5125, 0.7673, -0.3854,
+ -0.6538, 0.6397, 0.4041,
+ -9.1161, -3.7679, -2.9968},
+ {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo
+ -0.0433, -0.4257, 0.9038,
+ -0.5788, 0.7480, 0.3246,
+ 1.5227, 6.9114, -7.0765},
+ {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo
+ 0.4552, 0.6637, 0.5935,
+ -0.8042, 0.0203, 0.5941,
+ -6.9472, -4.1186, -5.9108},
+ {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo
+ -0.8247, 0.5587, -0.0878,
+ 0.0426, 0.2162, 0.9754,
+ 6.2694, -7.0540, 3.3316},
+ {2.8930, 8.5380, -3.3280}, % P
+ {1.6980, 7.6960, -3.5570}, % O1P
+ {3.2260, 9.5010, -4.4020}, % O2P
+ {4.1590, 7.6040, -3.0340}, % O5'
+ {4.5778, 6.6594, -4.0364}, % C5'
+ {4.9220, 7.1963, -4.9204}, % H5'
+ {3.7996, 5.9091, -4.1764}, % H5''
+ {5.7873, 5.8869, -3.5482}, % C4'
+ {6.0405, 5.0875, -4.2446}, % H4'
+ {6.9135, 6.8036, -3.4310}, % O4'
+ {7.7293, 6.4084, -2.3392}, % C1'
+ {8.7078, 6.1815, -2.7624}, % H1'
+ {7.1305, 5.1418, -1.7347}, % C2'
+ {7.2040, 5.1982, -0.6486}, % H2''
+ {7.7417, 4.0392, -2.3813}, % O2'
+ {8.6785, 4.1443, -2.5630}, % H2'
+ {5.6666, 5.2728, -2.1536}, % C3'
+ {5.1747, 5.9805, -1.4863}, % H3'
+ {4.9997, 4.0086, -2.1973}, % O3'
+ {10.3245, 8.5459, 1.5467}, % N1
+ {9.8051, 6.9432, -0.1497}, % N3
+ {10.5175, 7.4328, 0.8408}, % C2
+ {8.7523, 7.7422, -0.4228}, % C4
+ {8.4257, 8.9060, 0.2099}, % C5
+ {9.2665, 9.3242, 1.2540}, % C6
+ a, {
+ {9.0664, 10.4462, 1.9610}, % N6
+ {7.2750, 9.4537, -0.3428}, % N7
+ {7.7962, 7.5519, -1.3859}, % N9
+ {6.9479, 8.6157, -1.2771}, % C8
+ {11.4063, 6.9047, 1.1859}, % H2
+ {8.2845, 11.0341, 1.7552}, % H61
+ {9.6584, 10.6647, 2.7198}, % H62
+ {6.0430, 8.9853, -1.7594}} % H8
+ }.
+
+rA03() ->
+ {
+ {-0.5021, 0.0731, 0.8617, % dgf_base_tfo
+ -0.8112, 0.3054, -0.4986,
+ -0.2996, -0.9494, -0.0940,
+ 6.4273, -5.1944, -3.7807},
+ {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo
+ -0.0433, -0.4257, 0.9038,
+ -0.5788, 0.7480, 0.3246,
+ 1.5227, 6.9114, -7.0765},
+ {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo
+ 0.4552, 0.6637, 0.5935,
+ -0.8042, 0.0203, 0.5941,
+ -6.9472, -4.1186, -5.9108},
+ {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo
+ -0.8247, 0.5587, -0.0878,
+ 0.0426, 0.2162, 0.9754,
+ 6.2694, -7.0540, 3.3316},
+ {2.8930, 8.5380, -3.3280}, % P
+ {1.6980, 7.6960, -3.5570}, % O1P
+ {3.2260, 9.5010, -4.4020}, % O2P
+ {4.1590, 7.6040, -3.0340}, % O5'
+ {4.1214, 6.7116, -1.9049}, % C5'
+ {3.3465, 5.9610, -2.0607}, % H5'
+ {4.0789, 7.2928, -0.9837}, % H5''
+ {5.4170, 5.9293, -1.8186}, % C4'
+ {5.4506, 5.3400, -0.9023}, % H4'
+ {5.5067, 5.0417, -2.9703}, % O4'
+ {6.8650, 4.9152, -3.3612}, % C1'
+ {7.1090, 3.8577, -3.2603}, % H1'
+ {7.7152, 5.7282, -2.3894}, % C2'
+ {8.5029, 6.2356, -2.9463}, % H2''
+ {8.1036, 4.8568, -1.3419}, % O2'
+ {8.3270, 3.9651, -1.6184}, % H2'
+ {6.7003, 6.7565, -1.8911}, % C3'
+ {6.5898, 7.5329, -2.6482}, % H3'
+ {7.0505, 7.2878, -0.6105}, % O3'
+ {9.6740, 4.7656, -7.6614}, % N1
+ {9.0739, 4.3013, -5.3941}, % N3
+ {9.8416, 4.2192, -6.4581}, % C2
+ {7.9885, 5.0632, -5.6446}, % C4
+ {7.6822, 5.6856, -6.8194}, % C5
+ {8.5831, 5.5215, -7.8840}, % C6
+ a, {
+ {8.4084, 6.0747, -9.0933}, % N6
+ {6.4857, 6.3816, -6.7035}, % N7
+ {6.9740, 5.3703, -4.7760}, % N9
+ {6.1133, 6.1613, -5.4808}, % C8
+ {10.7627, 3.6375, -6.4220}, % H2
+ {7.6031, 6.6390, -9.2733}, % H61
+ {9.1004, 5.9708, -9.7893}, % H62
+ {5.1705, 6.6830, -5.3167}} % H8
+ }.
+
+rA04() ->
+ {
+ {-0.5426, -0.8175, 0.1929, % dgf_base_tfo
+ 0.8304, -0.5567, -0.0237,
+ 0.1267, 0.1473, 0.9809,
+ -0.5075, 8.3929, 0.2229},
+ {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo
+ -0.0433, -0.4257, 0.9038,
+ -0.5788, 0.7480, 0.3246,
+ 1.5227, 6.9114, -7.0765},
+ {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo
+ 0.4552, 0.6637, 0.5935,
+ -0.8042, 0.0203, 0.5941,
+ -6.9472, -4.1186, -5.9108},
+ {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo
+ -0.8247, 0.5587, -0.0878,
+ 0.0426, 0.2162, 0.9754,
+ 6.2694, -7.0540, 3.3316},
+ {2.8930, 8.5380, -3.3280}, % P
+ {1.6980, 7.6960, -3.5570}, % O1P
+ {3.2260, 9.5010, -4.4020}, % O2P
+ {4.1590, 7.6040, -3.0340}, % O5'
+ {5.4352, 8.2183, -2.7757}, % C5'
+ {5.3830, 8.7883, -1.8481}, % H5'
+ {5.7729, 8.7436, -3.6691}, % H5''
+ {6.4830, 7.1518, -2.5252}, % C4'
+ {7.4749, 7.5972, -2.4482}, % H4'
+ {6.1626, 6.4620, -1.2827}, % O4'
+ {6.5431, 5.0992, -1.3905}, % C1'
+ {7.2871, 4.9328, -0.6114}, % H1'
+ {7.1852, 4.8935, -2.7592}, % C2'
+ {6.8573, 3.9363, -3.1645}, % H2''
+ {8.5780, 5.1025, -2.6046}, % O2'
+ {8.9516, 4.7577, -1.7902}, % H2'
+ {6.5522, 6.0300, -3.5612}, % C3'
+ {5.5420, 5.7356, -3.8459}, % H3'
+ {7.3487, 6.4089, -4.6867}, % O3'
+ {3.6343, 2.6680, 2.0783}, % N1
+ {5.4505, 3.9805, 1.2446}, % N3
+ {4.7540, 3.3816, 2.1851}, % C2
+ {4.8805, 3.7951, 0.0354}, % C4
+ {3.7416, 3.0925, -0.2305}, % C5
+ {3.0873, 2.4980, 0.8606}, % C6
+ a, {
+ {1.9600, 1.7805, 0.7462}, % N6
+ {3.4605, 3.1184, -1.5906}, % N7
+ {5.3247, 4.2695, -1.1710}, % N9
+ {4.4244, 3.8244, -2.0953}, % C8
+ {5.0814, 3.4352, 3.2234}, % H2
+ {1.5423, 1.6454, -0.1520}, % H61
+ {1.5716, 1.3398, 1.5392}, % H62
+ {4.2675, 3.8876, -3.1721}} % H8
+ }.
+
+rA05() ->
+ {
+ {-0.5891, 0.0449, 0.8068, % dgf_base_tfo
+ 0.5375, 0.7673, 0.3498,
+ -0.6034, 0.6397, -0.4762,
+ -0.3019, -3.7679, -9.5913},
+ {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo
+ -0.0433, -0.4257, 0.9038,
+ -0.5788, 0.7480, 0.3246,
+ 1.5227, 6.9114, -7.0765},
+ {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo
+ 0.4552, 0.6637, 0.5935,
+ -0.8042, 0.0203, 0.5941,
+ -6.9472, -4.1186, -5.9108},
+ {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo
+ -0.8247, 0.5587, -0.0878,
+ 0.0426, 0.2162, 0.9754,
+ 6.2694, -7.0540, 3.3316},
+ {2.8930, 8.5380, -3.3280}, % P
+ {1.6980, 7.6960, -3.5570}, % O1P
+ {3.2260, 9.5010, -4.4020}, % O2P
+ {4.1590, 7.6040, -3.0340}, % O5'
+ {4.5778, 6.6594, -4.0364}, % C5'
+ {4.9220, 7.1963, -4.9204}, % H5'
+ {3.7996, 5.9091, -4.1764}, % H5''
+ {5.7873, 5.8869, -3.5482}, % C4'
+ {6.0405, 5.0875, -4.2446}, % H4'
+ {6.9135, 6.8036, -3.4310}, % O4'
+ {7.7293, 6.4084, -2.3392}, % C1'
+ {8.7078, 6.1815, -2.7624}, % H1'
+ {7.1305, 5.1418, -1.7347}, % C2'
+ {7.2040, 5.1982, -0.6486}, % H2''
+ {7.7417, 4.0392, -2.3813}, % O2'
+ {8.6785, 4.1443, -2.5630}, % H2'
+ {5.6666, 5.2728, -2.1536}, % C3'
+ {5.1747, 5.9805, -1.4863}, % H3'
+ {4.9997, 4.0086, -2.1973}, % O3'
+ {10.2594, 10.6774, -1.0056}, % N1
+ {9.7528, 8.7080, -2.2631}, % N3
+ {10.4471, 9.7876, -1.9791}, % C2
+ {8.7271, 8.5575, -1.3991}, % C4
+ {8.4100, 9.3803, -0.3580}, % C5
+ {9.2294, 10.5030, -0.1574}, % C6
+ a, {
+ {9.0349, 11.3951, 0.8250}, % N6
+ {7.2891, 8.9068, 0.3121}, % N7
+ {7.7962, 7.5519, -1.3859}, % N9
+ {6.9702, 7.8292, -0.3353}, % C8
+ {11.3132, 10.0537, -2.5851}, % H2
+ {8.2741, 11.2784, 1.4629}, % H61
+ {9.6733, 12.1368, 0.9529}, % H62
+ {6.0888, 7.3990, 0.1403}} % H8
+ }.
+
+rA06() ->
+ {
+ {-0.9815, 0.0731, -0.1772, % dgf_base_tfo
+ 0.1912, 0.3054, -0.9328,
+ -0.0141, -0.9494, -0.3137,
+ 5.7506, -5.1944, 4.7470},
+ {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo
+ -0.0433, -0.4257, 0.9038,
+ -0.5788, 0.7480, 0.3246,
+ 1.5227, 6.9114, -7.0765},
+ {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo
+ 0.4552, 0.6637, 0.5935,
+ -0.8042, 0.0203, 0.5941,
+ -6.9472, -4.1186, -5.9108},
+ {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo
+ -0.8247, 0.5587, -0.0878,
+ 0.0426, 0.2162, 0.9754,
+ 6.2694, -7.0540, 3.3316},
+ {2.8930, 8.5380, -3.3280}, % P
+ {1.6980, 7.6960, -3.5570}, % O1P
+ {3.2260, 9.5010, -4.4020}, % O2P
+ {4.1590, 7.6040, -3.0340}, % O5'
+ {4.1214, 6.7116, -1.9049}, % C5'
+ {3.3465, 5.9610, -2.0607}, % H5'
+ {4.0789, 7.2928, -0.9837}, % H5''
+ {5.4170, 5.9293, -1.8186}, % C4'
+ {5.4506, 5.3400, -0.9023}, % H4'
+ {5.5067, 5.0417, -2.9703}, % O4'
+ {6.8650, 4.9152, -3.3612}, % C1'
+ {7.1090, 3.8577, -3.2603}, % H1'
+ {7.7152, 5.7282, -2.3894}, % C2'
+ {8.5029, 6.2356, -2.9463}, % H2''
+ {8.1036, 4.8568, -1.3419}, % O2'
+ {8.3270, 3.9651, -1.6184}, % H2'
+ {6.7003, 6.7565, -1.8911}, % C3'
+ {6.5898, 7.5329, -2.6482}, % H3'
+ {7.0505, 7.2878, -0.6105}, % O3'
+ {6.6624, 3.5061, -8.2986}, % N1
+ {6.5810, 3.2570, -5.9221}, % N3
+ {6.5151, 2.8263, -7.1625}, % C2
+ {6.8364, 4.5817, -5.8882}, % C4
+ {7.0116, 5.4064, -6.9609}, % C5
+ {6.9173, 4.8260, -8.2361}, % C6
+ a, {
+ {7.0668, 5.5163, -9.3763}, % N6
+ {7.2573, 6.7070, -6.5394}, % N7
+ {6.9740, 5.3703, -4.7760}, % N9
+ {7.2238, 6.6275, -5.2453}, % C8
+ {6.3146, 1.7741, -7.3641}, % H2
+ {7.2568, 6.4972, -9.3456}, % H61
+ {7.0437, 5.0478, -10.2446}, % H62
+ {7.4108, 7.6227, -4.8418}} % H8
+ }.
+
+rA07() ->
+ {
+ {0.2379, 0.1310, -0.9624, % dgf_base_tfo
+ -0.5876, -0.7696, -0.2499,
+ -0.7734, 0.6249, -0.1061,
+ 30.9870, -26.9344, 42.6416},
+ {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo
+ 0.2952, -0.9481, -0.1180,
+ 0.5882, 0.2777, -0.7595,
+ -58.8919, -11.3095, 6.0866},
+ {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo
+ 0.9731, -0.0359, -0.2275,
+ -0.2290, -0.2532, -0.9399,
+ 3.5401, -29.7913, 52.2796},
+ {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo
+ -0.1183, 0.1805, -0.9764,
+ 0.4380, -0.8730, -0.2145,
+ 19.9023, 54.8054, 15.2799},
+ {41.8210, 8.3880, 43.5890}, % P
+ {42.5400, 8.0450, 44.8330}, % O1P
+ {42.2470, 9.6920, 42.9910}, % O2P
+ {40.2550, 8.2030, 43.7340}, % O5'
+ {39.3505, 8.4697, 42.6565}, % C5'
+ {39.1377, 7.5433, 42.1230}, % H5'
+ {39.7203, 9.3119, 42.0717}, % H5''
+ {38.0405, 8.9195, 43.2869}, % C4'
+ {37.3687, 9.3036, 42.5193}, % H4'
+ {37.4319, 7.8146, 43.9387}, % O4'
+ {37.1959, 8.1354, 45.3237}, % C1'
+ {36.1788, 8.5202, 45.3970}, % H1'
+ {38.1721, 9.2328, 45.6504}, % C2'
+ {39.1555, 8.7939, 45.8188}, % H2''
+ {37.7862, 10.0617, 46.7013}, % O2'
+ {37.3087, 9.6229, 47.4092}, % H2'
+ {38.1844, 10.0268, 44.3367}, % C3'
+ {39.1578, 10.5054, 44.2289}, % H3'
+ {37.0547, 10.9127, 44.3441}, % O3'
+ {34.8811, 4.2072, 47.5784}, % N1
+ {35.1084, 6.1336, 46.1818}, % N3
+ {34.4108, 5.1360, 46.7207}, % C2
+ {36.3908, 6.1224, 46.6053}, % C4
+ {36.9819, 5.2334, 47.4697}, % C5
+ {36.1786, 4.1985, 48.0035}, % C6
+ a, {
+ {36.6103, 3.2749, 48.8452}, % N6
+ {38.3236, 5.5522, 47.6595}, % N7
+ {37.3887, 7.0024, 46.2437}, % N9
+ {38.5055, 6.6096, 46.9057}, % C8
+ {33.3553, 5.0152, 46.4771}, % H2
+ {37.5730, 3.2804, 49.1507}, % H61
+ {35.9775, 2.5638, 49.1828}, % H62
+ {39.5461, 6.9184, 47.0041}} % H8
+ }.
+
+rA08() ->
+ {
+ {0.1084, -0.0895, -0.9901, % dgf_base_tfo
+ 0.9789, -0.1638, 0.1220,
+ -0.1731, -0.9824, 0.0698,
+ -2.9039, 47.2655, 33.0094},
+ {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo
+ 0.2952, -0.9481, -0.1180,
+ 0.5882, 0.2777, -0.7595,
+ -58.8919, -11.3095, 6.0866},
+ {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo
+ 0.9731, -0.0359, -0.2275,
+ -0.2290, -0.2532, -0.9399,
+ 3.5401, -29.7913, 52.2796},
+ {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo
+ -0.1183, 0.1805, -0.9764,
+ 0.4380, -0.8730, -0.2145,
+ 19.9023, 54.8054, 15.2799},
+ {41.8210, 8.3880, 43.5890}, % P
+ {42.5400, 8.0450, 44.8330}, % O1P
+ {42.2470, 9.6920, 42.9910}, % O2P
+ {40.2550, 8.2030, 43.7340}, % O5'
+ {39.4850, 8.9301, 44.6977}, % C5'
+ {39.0638, 9.8199, 44.2296}, % H5'
+ {40.0757, 9.0713, 45.6029}, % H5''
+ {38.3102, 8.0414, 45.0789}, % C4'
+ {37.7842, 8.4637, 45.9351}, % H4'
+ {37.4200, 7.9453, 43.9769}, % O4'
+ {37.2249, 6.5609, 43.6273}, % C1'
+ {36.3360, 6.2168, 44.1561}, % H1'
+ {38.4347, 5.8414, 44.1590}, % C2'
+ {39.2688, 5.9974, 43.4749}, % H2''
+ {38.2344, 4.4907, 44.4348}, % O2'
+ {37.6374, 4.0386, 43.8341}, % H2'
+ {38.6926, 6.6079, 45.4637}, % C3'
+ {39.7585, 6.5640, 45.6877}, % H3'
+ {37.8238, 6.0705, 46.4723}, % O3'
+ {33.9162, 6.2598, 39.7758}, % N1
+ {34.6709, 6.5759, 42.0215}, % N3
+ {33.7257, 6.5186, 41.0858}, % C2
+ {35.8935, 6.3324, 41.5018}, % C4
+ {36.2105, 6.0601, 40.1932}, % C5
+ {35.1538, 6.0151, 39.2537}, % C6
+ a, {
+ {35.3088, 5.7642, 37.9649}, % N6
+ {37.5818, 5.8677, 40.0507}, % N7
+ {37.0932, 6.3197, 42.1810}, % N9
+ {38.0509, 6.0354, 41.2635}, % C8
+ {32.6830, 6.6898, 41.3532}, % H2
+ {36.2305, 5.5855, 37.5925}, % H61
+ {34.5056, 5.7512, 37.3528}, % H62
+ {39.1318, 5.8993, 41.2285}} % H8
+ }.
+
+rA09() ->
+ {
+ {0.8467, 0.4166, -0.3311, % dgf_base_tfo
+ -0.3962, 0.9089, 0.1303,
+ 0.3552, 0.0209, 0.9346,
+ -42.7319, -26.6223, -29.8163},
+ {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo
+ 0.2952, -0.9481, -0.1180,
+ 0.5882, 0.2777, -0.7595,
+ -58.8919, -11.3095, 6.0866},
+ {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo
+ 0.9731, -0.0359, -0.2275,
+ -0.2290, -0.2532, -0.9399,
+ 3.5401, -29.7913, 52.2796},
+ {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo
+ -0.1183, 0.1805, -0.9764,
+ 0.4380, -0.8730, -0.2145,
+ 19.9023, 54.8054, 15.2799},
+ {41.8210, 8.3880, 43.5890}, % P
+ {42.5400, 8.0450, 44.8330}, % O1P
+ {42.2470, 9.6920, 42.9910}, % O2P
+ {40.2550, 8.2030, 43.7340}, % O5'
+ {39.3505, 8.4697, 42.6565}, % C5'
+ {39.1377, 7.5433, 42.1230}, % H5'
+ {39.7203, 9.3119, 42.0717}, % H5''
+ {38.0405, 8.9195, 43.2869}, % C4'
+ {37.6479, 8.1347, 43.9335}, % H4'
+ {38.2691, 10.0933, 44.0524}, % O4'
+ {37.3999, 11.1488, 43.5973}, % C1'
+ {36.5061, 11.1221, 44.2206}, % H1'
+ {37.0364, 10.7838, 42.1836}, % C2'
+ {37.8636, 11.0489, 41.5252}, % H2''
+ {35.8275, 11.3133, 41.7379}, % O2'
+ {35.6214, 12.1896, 42.0714}, % H2'
+ {36.9316, 9.2556, 42.2837}, % C3'
+ {37.1778, 8.8260, 41.3127}, % H3'
+ {35.6285, 8.9334, 42.7926}, % O3'
+ {38.1482, 15.2833, 46.4641}, % N1
+ {37.3641, 13.0968, 45.9007}, % N3
+ {37.5032, 14.1288, 46.7300}, % C2
+ {37.9570, 13.3377, 44.7113}, % C4
+ {38.6397, 14.4660, 44.3267}, % C5
+ {38.7473, 15.5229, 45.2609}, % C6
+ a, {
+ {39.3720, 16.6649, 45.0297}, % N6
+ {39.1079, 14.3351, 43.0223}, % N7
+ {38.0132, 12.4868, 43.6280}, % N9
+ {38.7058, 13.1402, 42.6620}, % C8
+ {37.0731, 14.0857, 47.7306}, % H2
+ {39.8113, 16.8281, 44.1350}, % H61
+ {39.4100, 17.3741, 45.7478}, % H62
+ {39.0412, 12.9660, 41.6397}} % H8
+ }.
+
+rA10() ->
+ {
+ {0.7063, 0.6317, -0.3196, % dgf_base_tfo
+ -0.0403, -0.4149, -0.9090,
+ -0.7068, 0.6549, -0.2676,
+ 6.4402, -52.1496, 30.8246},
+ {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo
+ 0.2952, -0.9481, -0.1180,
+ 0.5882, 0.2777, -0.7595,
+ -58.8919, -11.3095, 6.0866},
+ {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo
+ 0.9731, -0.0359, -0.2275,
+ -0.2290, -0.2532, -0.9399,
+ 3.5401, -29.7913, 52.2796},
+ {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo
+ -0.1183, 0.1805, -0.9764,
+ 0.4380, -0.8730, -0.2145,
+ 19.9023, 54.8054, 15.2799},
+ {41.8210, 8.3880, 43.5890}, % P
+ {42.5400, 8.0450, 44.8330}, % O1P
+ {42.2470, 9.6920, 42.9910}, % O2P
+ {40.2550, 8.2030, 43.7340}, % O5'
+ {39.4850, 8.9301, 44.6977}, % C5'
+ {39.0638, 9.8199, 44.2296}, % H5'
+ {40.0757, 9.0713, 45.6029}, % H5''
+ {38.3102, 8.0414, 45.0789}, % C4'
+ {37.7099, 7.8166, 44.1973}, % H4'
+ {38.8012, 6.8321, 45.6380}, % O4'
+ {38.2431, 6.6413, 46.9529}, % C1'
+ {37.3505, 6.0262, 46.8385}, % H1'
+ {37.8484, 8.0156, 47.4214}, % C2'
+ {38.7381, 8.5406, 47.7690}, % H2''
+ {36.8286, 8.0368, 48.3701}, % O2'
+ {36.8392, 7.3063, 48.9929}, % H2'
+ {37.3576, 8.6512, 46.1132}, % C3'
+ {37.5207, 9.7275, 46.1671}, % H3'
+ {35.9985, 8.2392, 45.9032}, % O3'
+ {39.9117, 2.2278, 48.8527}, % N1
+ {38.6207, 3.6941, 47.4757}, % N3
+ {38.9872, 2.4888, 47.9057}, % C2
+ {39.2961, 4.6720, 48.1174}, % C4
+ {40.2546, 4.5307, 49.0912}, % C5
+ {40.5932, 3.2189, 49.4985}, % C6
+ a, {
+ {41.4938, 2.9317, 50.4229}, % N6
+ {40.7195, 5.7755, 49.5060}, % N7
+ {39.1730, 6.0305, 47.9170}, % N9
+ {40.0413, 6.6250, 48.7728}, % C8
+ {38.5257, 1.5960, 47.4838}, % H2
+ {41.9907, 3.6753, 50.8921}, % H61
+ {41.6848, 1.9687, 50.6599}, % H62
+ {40.3571, 7.6321, 49.0452}} % H8
+ }.
+
+rAs() -> [rA01(),rA02(),rA03(),rA04(),rA05(),rA06(),rA07(),
+ rA08(),rA09(),rA10()].
+
+rC() ->
+ {
+ {-0.0359, -0.8071, 0.5894, % dgf_base_tfo
+ -0.2669, 0.5761, 0.7726,
+ -0.9631, -0.1296, -0.2361,
+ 0.1584, 8.3434, 0.5434},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {5.2430, -8.2420, 2.8260}, % C5'
+ {5.1974, -8.8497, 1.9223}, % H5'
+ {5.5548, -8.7348, 3.7469}, % H5''
+ {6.3140, -7.2060, 2.5510}, % C4'
+ {7.2954, -7.6762, 2.4898}, % H4'
+ {6.0140, -6.5420, 1.2890}, % O4'
+ {6.4190, -5.1840, 1.3620}, % C1'
+ {7.1608, -5.0495, 0.5747}, % H1'
+ {7.0760, -4.9560, 2.7270}, % C2'
+ {6.7770, -3.9803, 3.1099}, % H2''
+ {8.4500, -5.1930, 2.5810}, % O2'
+ {8.8309, -4.8755, 1.7590}, % H2'
+ {6.4060, -6.0590, 3.5580}, % C3'
+ {5.4021, -5.7313, 3.8281}, % H3'
+ {7.1570, -6.4240, 4.7070}, % O3'
+ {5.2170, -4.3260, 1.1690}, % N1
+ {4.2960, -2.2560, 0.6290}, % N3
+ {5.4330, -3.0200, 0.7990}, % C2
+ {2.9930, -2.6780, 0.7940}, % C4
+ {2.8670, -4.0630, 1.1830}, % C5
+ {3.9570, -4.8300, 1.3550}, % C6
+ c, {
+ {2.0187, -1.8047, 0.5874}, % N4
+ {6.5470, -2.5560, 0.6290}, % O2
+ {1.0684, -2.1236, 0.7109}, % H41
+ {2.2344, -0.8560, 0.3162}, % H42
+ {1.8797, -4.4972, 1.3404}, % H5
+ {3.8479, -5.8742, 1.6480}} % H6
+ }.
+
+rC01() ->
+ {
+ {-0.0137, -0.8012, 0.5983, % dgf_base_tfo
+ -0.2523, 0.5817, 0.7733,
+ -0.9675, -0.1404, -0.2101,
+ 0.2031, 8.3874, 0.4228},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {5.2416, -8.2422, 2.8181}, % C5'
+ {5.2050, -8.8128, 1.8901}, % H5'
+ {5.5368, -8.7738, 3.7227}, % H5''
+ {6.3232, -7.2037, 2.6002}, % C4'
+ {7.3048, -7.6757, 2.5577}, % H4'
+ {6.0635, -6.5092, 1.3456}, % O4'
+ {6.4697, -5.1547, 1.4629}, % C1'
+ {7.2354, -5.0043, 0.7018}, % H1'
+ {7.0856, -4.9610, 2.8521}, % C2'
+ {6.7777, -3.9935, 3.2487}, % H2''
+ {8.4627, -5.1992, 2.7423}, % O2'
+ {8.8693, -4.8638, 1.9399}, % H2'
+ {6.3877, -6.0809, 3.6362}, % C3'
+ {5.3770, -5.7562, 3.8834}, % H3'
+ {7.1024, -6.4754, 4.7985}, % O3'
+ {5.2764, -4.2883, 1.2538}, % N1
+ {4.3777, -2.2062, 0.7229}, % N3
+ {5.5069, -2.9779, 0.9088}, % C2
+ {3.0693, -2.6246, 0.8500}, % C4
+ {2.9279, -4.0146, 1.2149}, % C5
+ {4.0101, -4.7892, 1.4017}, % C6
+ c, {
+ {2.1040, -1.7437, 0.6331}, % N4
+ {6.6267, -2.5166, 0.7728}, % O2
+ {1.1496, -2.0600, 0.7287}, % H41
+ {2.3303, -0.7921, 0.3815}, % H42
+ {1.9353, -4.4465, 1.3419}, % H5
+ {3.8895, -5.8371, 1.6762}} % H6
+ }.
+
+rC02() ->
+ {
+ {0.5141, 0.0246, 0.8574, % dgf_base_tfo
+ -0.5547, -0.7529, 0.3542,
+ 0.6542, -0.6577, -0.3734,
+ -9.1111, -3.4598, -3.2939},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {4.3825, -6.6585, 4.0489}, % C5'
+ {4.6841, -7.2019, 4.9443}, % H5'
+ {3.6189, -5.8889, 4.1625}, % H5''
+ {5.6255, -5.9175, 3.5998}, % C4'
+ {5.8732, -5.1228, 4.3034}, % H4'
+ {6.7337, -6.8605, 3.5222}, % O4'
+ {7.5932, -6.4923, 2.4548}, % C1'
+ {8.5661, -6.2983, 2.9064}, % H1'
+ {7.0527, -5.2012, 1.8322}, % C2'
+ {7.1627, -5.2525, 0.7490}, % H2''
+ {7.6666, -4.1249, 2.4880}, % O2'
+ {8.5944, -4.2543, 2.6981}, % H2'
+ {5.5661, -5.3029, 2.2009}, % C3'
+ {5.0841, -6.0018, 1.5172}, % H3'
+ {4.9062, -4.0452, 2.2042}, % O3'
+ {7.6298, -7.6136, 1.4752}, % N1
+ {8.6945, -8.7046, -0.2857}, % N3
+ {8.6943, -7.6514, 0.6066}, % C2
+ {7.7426, -9.6987, -0.3801}, % C4
+ {6.6642, -9.5742, 0.5722}, % C5
+ {6.6391, -8.5592, 1.4526}, % C6
+ c, {
+ {7.9033, -10.6371, -1.3010}, % N4
+ {9.5840, -6.8186, 0.6136}, % O2
+ {7.2009, -11.3604, -1.3619}, % H41
+ {8.7058, -10.6168, -1.9140}, % H42
+ {5.8585, -10.3083, 0.5822}, % H5
+ {5.8197, -8.4773, 2.1667}} % H6
+ }.
+
+rC03() ->
+ {
+ {-0.4993, 0.0476, 0.8651, % dgf_base_tfo
+ 0.8078, -0.3353, 0.4847,
+ 0.3132, 0.9409, 0.1290,
+ 6.2989, -5.2303, -3.8577},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {3.9938, -6.7042, 1.9023}, % C5'
+ {3.2332, -5.9343, 2.0319}, % H5'
+ {3.9666, -7.2863, 0.9812}, % H5''
+ {5.3098, -5.9546, 1.8564}, % C4'
+ {5.3863, -5.3702, 0.9395}, % H4'
+ {5.3851, -5.0642, 3.0076}, % O4'
+ {6.7315, -4.9724, 3.4462}, % C1'
+ {7.0033, -3.9202, 3.3619}, % H1'
+ {7.5997, -5.8018, 2.4948}, % C2'
+ {8.3627, -6.3254, 3.0707}, % H2''
+ {8.0410, -4.9501, 1.4724}, % O2'
+ {8.2781, -4.0644, 1.7570}, % H2'
+ {6.5701, -6.8129, 1.9714}, % C3'
+ {6.4186, -7.5809, 2.7299}, % H3'
+ {6.9357, -7.3841, 0.7235}, % O3'
+ {6.8024, -5.4718, 4.8475}, % N1
+ {7.9218, -5.5700, 6.8877}, % N3
+ {7.8908, -5.0886, 5.5944}, % C2
+ {6.9789, -6.3827, 7.4823}, % C4
+ {5.8742, -6.7319, 6.6202}, % C5
+ {5.8182, -6.2769, 5.3570}, % C6
+ c, {
+ {7.1702, -6.7511, 8.7402}, % N4
+ {8.7747, -4.3728, 5.1568}, % O2
+ {6.4741, -7.3461, 9.1662}, % H41
+ {7.9889, -6.4396, 9.2429}, % H42
+ {5.0736, -7.3713, 6.9922}, % H5
+ {4.9784, -6.5473, 4.7170}} % H6
+ }.
+
+rC04() ->
+ {
+ {-0.5669, -0.8012, 0.1918, % dgf_base_tfo
+ -0.8129, 0.5817, 0.0273,
+ -0.1334, -0.1404, -0.9811,
+ -0.3279, 8.3874, 0.3355},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {5.2416, -8.2422, 2.8181}, % C5'
+ {5.2050, -8.8128, 1.8901}, % H5'
+ {5.5368, -8.7738, 3.7227}, % H5''
+ {6.3232, -7.2037, 2.6002}, % C4'
+ {7.3048, -7.6757, 2.5577}, % H4'
+ {6.0635, -6.5092, 1.3456}, % O4'
+ {6.4697, -5.1547, 1.4629}, % C1'
+ {7.2354, -5.0043, 0.7018}, % H1'
+ {7.0856, -4.9610, 2.8521}, % C2'
+ {6.7777, -3.9935, 3.2487}, % H2''
+ {8.4627, -5.1992, 2.7423}, % O2'
+ {8.8693, -4.8638, 1.9399}, % H2'
+ {6.3877, -6.0809, 3.6362}, % C3'
+ {5.3770, -5.7562, 3.8834}, % H3'
+ {7.1024, -6.4754, 4.7985}, % O3'
+ {5.2764, -4.2883, 1.2538}, % N1
+ {3.8961, -3.0896, -0.1893}, % N3
+ {5.0095, -3.8907, -0.0346}, % C2
+ {3.0480, -2.6632, 0.8116}, % C4
+ {3.4093, -3.1310, 2.1292}, % C5
+ {4.4878, -3.9124, 2.3088}, % C6
+ c, {
+ {2.0216, -1.8941, 0.4804}, % N4
+ {5.7005, -4.2164, -0.9842}, % O2
+ {1.4067, -1.5873, 1.2205}, % H41
+ {1.8721, -1.6319, -0.4835}, % H42
+ {2.8048, -2.8507, 2.9918}, % H5
+ {4.7491, -4.2593, 3.3085}} % H6
+ }.
+
+rC05() ->
+ {
+ {-0.6298, 0.0246, 0.7763, % dgf_base_tfo
+ -0.5226, -0.7529, -0.4001,
+ 0.5746, -0.6577, 0.4870,
+ -0.0208, -3.4598, -9.6882},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {4.3825, -6.6585, 4.0489}, % C5'
+ {4.6841, -7.2019, 4.9443}, % H5'
+ {3.6189, -5.8889, 4.1625}, % H5''
+ {5.6255, -5.9175, 3.5998}, % C4'
+ {5.8732, -5.1228, 4.3034}, % H4'
+ {6.7337, -6.8605, 3.5222}, % O4'
+ {7.5932, -6.4923, 2.4548}, % C1'
+ {8.5661, -6.2983, 2.9064}, % H1'
+ {7.0527, -5.2012, 1.8322}, % C2'
+ {7.1627, -5.2525, 0.7490}, % H2''
+ {7.6666, -4.1249, 2.4880}, % O2'
+ {8.5944, -4.2543, 2.6981}, % H2'
+ {5.5661, -5.3029, 2.2009}, % C3'
+ {5.0841, -6.0018, 1.5172}, % H3'
+ {4.9062, -4.0452, 2.2042}, % O3'
+ {7.6298, -7.6136, 1.4752}, % N1
+ {8.5977, -9.5977, 0.7329}, % N3
+ {8.5951, -8.5745, 1.6594}, % C2
+ {7.7372, -9.7371, -0.3364}, % C4
+ {6.7596, -8.6801, -0.4476}, % C5
+ {6.7338, -7.6721, 0.4408}, % C6
+ c, {
+ {7.8849, -10.7881, -1.1289}, % N4
+ {9.3993, -8.5377, 2.5743}, % O2
+ {7.2499, -10.8809, -1.9088}, % H41
+ {8.6122, -11.4649, -0.9468}, % H42
+ {6.0317, -8.6941, -1.2588}, % H5
+ {5.9901, -6.8809, 0.3459}} % H6
+ }.
+
+rC06() ->
+ {
+ {-0.9837, 0.0476, -0.1733, % dgf_base_tfo
+ -0.1792, -0.3353, 0.9249,
+ -0.0141, 0.9409, 0.3384,
+ 5.7793, -5.2303, 4.5997},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {3.9938, -6.7042, 1.9023}, % C5'
+ {3.2332, -5.9343, 2.0319}, % H5'
+ {3.9666, -7.2863, 0.9812}, % H5''
+ {5.3098, -5.9546, 1.8564}, % C4'
+ {5.3863, -5.3702, 0.9395}, % H4'
+ {5.3851, -5.0642, 3.0076}, % O4'
+ {6.7315, -4.9724, 3.4462}, % C1'
+ {7.0033, -3.9202, 3.3619}, % H1'
+ {7.5997, -5.8018, 2.4948}, % C2'
+ {8.3627, -6.3254, 3.0707}, % H2''
+ {8.0410, -4.9501, 1.4724}, % O2'
+ {8.2781, -4.0644, 1.7570}, % H2'
+ {6.5701, -6.8129, 1.9714}, % C3'
+ {6.4186, -7.5809, 2.7299}, % H3'
+ {6.9357, -7.3841, 0.7235}, % O3'
+ {6.8024, -5.4718, 4.8475}, % N1
+ {6.6920, -5.0495, 7.1354}, % N3
+ {6.6201, -4.5500, 5.8506}, % C2
+ {6.9254, -6.3614, 7.4926}, % C4
+ {7.1046, -7.2543, 6.3718}, % C5
+ {7.0391, -6.7951, 5.1106}, % C6
+ c, {
+ {6.9614, -6.6648, 8.7815}, % N4
+ {6.4083, -3.3696, 5.6340}, % O2
+ {7.1329, -7.6280, 9.0324}, % H41
+ {6.8204, -5.9469, 9.4777}, % H42
+ {7.2954, -8.3135, 6.5440}, % H5
+ {7.1753, -7.4798, 4.2735}} % H6
+ }.
+
+rC07() ->
+ {
+ {0.0033, 0.2720, -0.9623, % dgf_base_tfo
+ 0.3013, -0.9179, -0.2584,
+ -0.9535, -0.2891, -0.0850,
+ 43.0403, 13.7233, 34.5710},
+ {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo
+ 0.0302, -0.7316, 0.6811,
+ 0.3938, -0.6176, -0.6808,
+ -48.4330, 26.3254, 13.6383},
+ {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo
+ 0.7581, 0.4893, 0.4311,
+ 0.6345, -0.4010, -0.6607,
+ -31.9784, -13.4285, 44.9650},
+ {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo
+ -0.6890, 0.5694, -0.4484,
+ 0.3694, -0.2564, -0.8932,
+ 12.1105, 30.8774, 46.0946},
+ {33.3400, 11.0980, 46.1750}, % P
+ {34.5130, 10.2320, 46.4660}, % O1P
+ {33.4130, 12.3960, 46.9340}, % O2P
+ {31.9810, 10.3390, 46.4820}, % O5'
+ {30.8152, 11.1619, 46.2003}, % C5'
+ {30.4519, 10.9454, 45.1957}, % H5'
+ {31.0379, 12.2016, 46.4400}, % H5''
+ {29.7081, 10.7448, 47.1428}, % C4'
+ {28.8710, 11.4416, 47.0982}, % H4'
+ {29.2550, 9.4394, 46.8162}, % O4'
+ {29.3907, 8.5625, 47.9460}, % C1'
+ {28.4416, 8.5669, 48.4819}, % H1'
+ {30.4468, 9.2031, 48.7952}, % C2'
+ {31.4222, 8.9651, 48.3709}, % H2''
+ {30.3701, 8.9157, 50.1624}, % O2'
+ {30.0652, 8.0304, 50.3740}, % H2'
+ {30.1622, 10.6879, 48.6120}, % C3'
+ {31.0952, 11.2399, 48.7254}, % H3'
+ {29.1076, 11.1535, 49.4702}, % O3'
+ {29.7883, 7.2209, 47.5235}, % N1
+ {29.1825, 5.0438, 46.8275}, % N3
+ {28.8008, 6.2912, 47.2263}, % C2
+ {30.4888, 4.6890, 46.7186}, % C4
+ {31.5034, 5.6405, 47.0249}, % C5
+ {31.1091, 6.8691, 47.4156}, % C6
+ c, {
+ {30.8109, 3.4584, 46.3336}, % N4
+ {27.6171, 6.5989, 47.3189}, % O2
+ {31.7923, 3.2301, 46.2638}, % H41
+ {30.0880, 2.7857, 46.1215}, % H42
+ {32.5542, 5.3634, 46.9395}, % H5
+ {31.8523, 7.6279, 47.6603}} % H6
+ }.
+
+rC08() ->
+ {
+ {0.0797, -0.6026, -0.7941, % dgf_base_tfo
+ 0.7939, 0.5201, -0.3150,
+ 0.6028, -0.6054, 0.5198,
+ -36.8341, 41.5293, 1.6628},
+ {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo
+ 0.0302, -0.7316, 0.6811,
+ 0.3938, -0.6176, -0.6808,
+ -48.4330, 26.3254, 13.6383},
+ {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo
+ 0.7581, 0.4893, 0.4311,
+ 0.6345, -0.4010, -0.6607,
+ -31.9784, -13.4285, 44.9650},
+ {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo
+ -0.6890, 0.5694, -0.4484,
+ 0.3694, -0.2564, -0.8932,
+ 12.1105, 30.8774, 46.0946},
+ {33.3400, 11.0980, 46.1750}, % P
+ {34.5130, 10.2320, 46.4660}, % O1P
+ {33.4130, 12.3960, 46.9340}, % O2P
+ {31.9810, 10.3390, 46.4820}, % O5'
+ {31.8779, 9.9369, 47.8760}, % C5'
+ {31.3239, 10.6931, 48.4322}, % H5'
+ {32.8647, 9.6624, 48.2489}, % H5''
+ {31.0429, 8.6773, 47.9401}, % C4'
+ {31.0779, 8.2331, 48.9349}, % H4'
+ {29.6956, 8.9669, 47.5983}, % O4'
+ {29.2784, 8.1700, 46.4782}, % C1'
+ {28.8006, 7.2731, 46.8722}, % H1'
+ {30.5544, 7.7940, 45.7875}, % C2'
+ {30.8837, 8.6410, 45.1856}, % H2''
+ {30.5100, 6.6007, 45.0582}, % O2'
+ {29.6694, 6.4168, 44.6326}, % H2'
+ {31.5146, 7.5954, 46.9527}, % C3'
+ {32.5255, 7.8261, 46.6166}, % H3'
+ {31.3876, 6.2951, 47.5516}, % O3'
+ {28.3976, 8.9302, 45.5933}, % N1
+ {26.2155, 9.6135, 44.9910}, % N3
+ {27.0281, 8.8961, 45.8192}, % C2
+ {26.7044, 10.3489, 43.9595}, % C4
+ {28.1088, 10.3837, 43.7247}, % C5
+ {28.8978, 9.6708, 44.5535}, % C6
+ c, {
+ {25.8715, 11.0249, 43.1749}, % N4
+ {26.5733, 8.2371, 46.7484}, % O2
+ {26.2707, 11.5609, 42.4177}, % H41
+ {24.8760, 10.9939, 43.3427}, % H42
+ {28.5089, 10.9722, 42.8990}, % H5
+ {29.9782, 9.6687, 44.4097}} % H6
+ }.
+
+rC09() ->
+ {
+ {0.8727, 0.4760, -0.1091, % dgf_base_tfo
+ -0.4188, 0.6148, -0.6682,
+ -0.2510, 0.6289, 0.7359,
+ -8.1687, -52.0761, -25.0726},
+ {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo
+ 0.0302, -0.7316, 0.6811,
+ 0.3938, -0.6176, -0.6808,
+ -48.4330, 26.3254, 13.6383},
+ {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo
+ 0.7581, 0.4893, 0.4311,
+ 0.6345, -0.4010, -0.6607,
+ -31.9784, -13.4285, 44.9650},
+ {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo
+ -0.6890, 0.5694, -0.4484,
+ 0.3694, -0.2564, -0.8932,
+ 12.1105, 30.8774, 46.0946},
+ {33.3400, 11.0980, 46.1750}, % P
+ {34.5130, 10.2320, 46.4660}, % O1P
+ {33.4130, 12.3960, 46.9340}, % O2P
+ {31.9810, 10.3390, 46.4820}, % O5'
+ {30.8152, 11.1619, 46.2003}, % C5'
+ {30.4519, 10.9454, 45.1957}, % H5'
+ {31.0379, 12.2016, 46.4400}, % H5''
+ {29.7081, 10.7448, 47.1428}, % C4'
+ {29.4506, 9.6945, 47.0059}, % H4'
+ {30.1045, 10.9634, 48.4885}, % O4'
+ {29.1794, 11.8418, 49.1490}, % C1'
+ {28.4388, 11.2210, 49.6533}, % H1'
+ {28.5211, 12.6008, 48.0367}, % C2'
+ {29.1947, 13.3949, 47.7147}, % H2''
+ {27.2316, 13.0683, 48.3134}, % O2'
+ {27.0851, 13.3391, 49.2227}, % H2'
+ {28.4131, 11.5507, 46.9391}, % C3'
+ {28.4451, 12.0512, 45.9713}, % H3'
+ {27.2707, 10.6955, 47.1097}, % O3'
+ {29.8751, 12.7405, 50.0682}, % N1
+ {30.7172, 13.1841, 52.2328}, % N3
+ {30.0617, 12.3404, 51.3847}, % C2
+ {31.1834, 14.3941, 51.8297}, % C4
+ {30.9913, 14.8074, 50.4803}, % C5
+ {30.3434, 13.9610, 49.6548}, % C6
+ c, {
+ {31.8090, 15.1847, 52.6957}, % N4
+ {29.6470, 11.2494, 51.7616}, % O2
+ {32.1422, 16.0774, 52.3606}, % H41
+ {31.9392, 14.8893, 53.6527}, % H42
+ {31.3632, 15.7771, 50.1491}, % H5
+ {30.1742, 14.2374, 48.6141}} % H6
+ }.
+
+rC10() ->
+ {
+ {0.1549, 0.8710, -0.4663, % dgf_base_tfo
+ 0.6768, -0.4374, -0.5921,
+ -0.7197, -0.2239, -0.6572,
+ 25.2447, -14.1920, 50.3201},
+ {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo
+ 0.0302, -0.7316, 0.6811,
+ 0.3938, -0.6176, -0.6808,
+ -48.4330, 26.3254, 13.6383},
+ {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo
+ 0.7581, 0.4893, 0.4311,
+ 0.6345, -0.4010, -0.6607,
+ -31.9784, -13.4285, 44.9650},
+ {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo
+ -0.6890, 0.5694, -0.4484,
+ 0.3694, -0.2564, -0.8932,
+ 12.1105, 30.8774, 46.0946},
+ {33.3400, 11.0980, 46.1750}, % P
+ {34.5130, 10.2320, 46.4660}, % O1P
+ {33.4130, 12.3960, 46.9340}, % O2P
+ {31.9810, 10.3390, 46.4820}, % O5'
+ {31.8779, 9.9369, 47.8760}, % C5'
+ {31.3239, 10.6931, 48.4322}, % H5'
+ {32.8647, 9.6624, 48.2489}, % H5''
+ {31.0429, 8.6773, 47.9401}, % C4'
+ {30.0440, 8.8473, 47.5383}, % H4'
+ {31.6749, 7.6351, 47.2119}, % O4'
+ {31.9159, 6.5022, 48.0616}, % C1'
+ {31.0691, 5.8243, 47.9544}, % H1'
+ {31.9300, 7.0685, 49.4493}, % C2'
+ {32.9024, 7.5288, 49.6245}, % H2''
+ {31.5672, 6.1750, 50.4632}, % O2'
+ {31.8416, 5.2663, 50.3200}, % H2'
+ {30.8618, 8.1514, 49.3749}, % C3'
+ {31.1122, 8.9396, 50.0850}, % H3'
+ {29.5351, 7.6245, 49.5409}, % O3'
+ {33.1890, 5.8629, 47.7343}, % N1
+ {34.4004, 4.2636, 46.4828}, % N3
+ {33.2062, 4.8497, 46.7851}, % C2
+ {35.5600, 4.6374, 47.0822}, % C4
+ {35.5444, 5.6751, 48.0577}, % C5
+ {34.3565, 6.2450, 48.3432}, % C6
+ c, {
+ {36.6977, 4.0305, 46.7598}, % N4
+ {32.1661, 4.5034, 46.2348}, % O2
+ {37.5405, 4.3347, 47.2259}, % H41
+ {36.7033, 3.2923, 46.0706}, % H42
+ {36.4713, 5.9811, 48.5428}, % H5
+ {34.2986, 7.0426, 49.0839}} % H6
+ }.
+
+rCs() -> [rC01(),rC02(),rC03(),rC04(),rC05(),rC06(),rC07(),
+ rC08(),rC09(),rC10()].
+
+rG() ->
+ {
+ {-0.0018, -0.8207, 0.5714, % dgf_base_tfo
+ 0.2679, -0.5509, -0.7904,
+ 0.9634, 0.1517, 0.2209,
+ 0.0073, 8.4030, 0.6232},
+ {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo
+ -0.0433, -0.4257, 0.9038,
+ -0.5788, 0.7480, 0.3246,
+ 1.5227, 6.9114, -7.0765},
+ {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo
+ 0.4552, 0.6637, 0.5935,
+ -0.8042, 0.0203, 0.5941,
+ -6.9472, -4.1186, -5.9108},
+ {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo
+ -0.8247, 0.5587, -0.0878,
+ 0.0426, 0.2162, 0.9754,
+ 6.2694, -7.0540, 3.3316},
+ {2.8930, 8.5380, -3.3280}, % P
+ {1.6980, 7.6960, -3.5570}, % O1P
+ {3.2260, 9.5010, -4.4020}, % O2P
+ {4.1590, 7.6040, -3.0340}, % O5'
+ {5.4550, 8.2120, -2.8810}, % C5'
+ {5.4546, 8.8508, -1.9978}, % H5'
+ {5.7588, 8.6625, -3.8259}, % H5''
+ {6.4970, 7.1480, -2.5980}, % C4'
+ {7.4896, 7.5919, -2.5214}, % H4'
+ {6.1630, 6.4860, -1.3440}, % O4'
+ {6.5400, 5.1200, -1.4190}, % C1'
+ {7.2763, 4.9681, -0.6297}, % H1'
+ {7.1940, 4.8830, -2.7770}, % C2'
+ {6.8667, 3.9183, -3.1647}, % H2''
+ {8.5860, 5.0910, -2.6140}, % O2'
+ {8.9510, 4.7626, -1.7890}, % H2'
+ {6.5720, 6.0040, -3.6090}, % C3'
+ {5.5636, 5.7066, -3.8966}, % H3'
+ {7.3801, 6.3562, -4.7350}, % O3'
+ {4.7150, 0.4910, -0.1360}, % N1
+ {6.3490, 2.1730, -0.6020}, % N3
+ {5.9530, 0.9650, -0.2670}, % C2
+ {5.2900, 2.9790, -0.8260}, % C4
+ {3.9720, 2.6390, -0.7330}, % C5
+ {3.6770, 1.3160, -0.3660}, % C6
+ g, {
+ {6.8426, 0.0056, -0.0019}, % N2
+ {3.1660, 3.7290, -1.0360}, % N7
+ {5.3170, 4.2990, -1.1930}, % N9
+ {4.0100, 4.6780, -1.2990}, % C8
+ {2.4280, 0.8450, -0.2360}, % O6
+ {4.6151, -0.4677, 0.1305}, % H1
+ {6.6463, -0.9463, 0.2729}, % H21
+ {7.8170, 0.2642, -0.0640}, % H22
+ {3.4421, 5.5744, -1.5482}} % H8
+ }.
+
+rU() ->
+ {
+ {-0.0359, -0.8071, 0.5894, % dgf_base_tfo
+ -0.2669, 0.5761, 0.7726,
+ -0.9631, -0.1296, -0.2361,
+ 0.1584, 8.3434, 0.5434},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {5.2430, -8.2420, 2.8260}, % C5'
+ {5.1974, -8.8497, 1.9223}, % H5'
+ {5.5548, -8.7348, 3.7469}, % H5''
+ {6.3140, -7.2060, 2.5510}, % C4'
+ {7.2954, -7.6762, 2.4898}, % H4'
+ {6.0140, -6.5420, 1.2890}, % O4'
+ {6.4190, -5.1840, 1.3620}, % C1'
+ {7.1608, -5.0495, 0.5747}, % H1'
+ {7.0760, -4.9560, 2.7270}, % C2'
+ {6.7770, -3.9803, 3.1099}, % H2''
+ {8.4500, -5.1930, 2.5810}, % O2'
+ {8.8309, -4.8755, 1.7590}, % H2'
+ {6.4060, -6.0590, 3.5580}, % C3'
+ {5.4021, -5.7313, 3.8281}, % H3'
+ {7.1570, -6.4240, 4.7070}, % O3'
+ {5.2170, -4.3260, 1.1690}, % N1
+ {4.2960, -2.2560, 0.6290}, % N3
+ {5.4330, -3.0200, 0.7990}, % C2
+ {2.9930, -2.6780, 0.7940}, % C4
+ {2.8670, -4.0630, 1.1830}, % C5
+ {3.9570, -4.8300, 1.3550}, % C6
+ u, {
+ {6.5470, -2.5560, 0.6290}, % O2
+ {2.0540, -1.9000, 0.6130}, % O4
+ {4.4300, -1.3020, 0.3600}, % H3
+ {1.9590, -4.4570, 1.3250}, % H5
+ {3.8460, -5.7860, 1.6240}} % H6
+ }.
+
+rU01() ->
+ {
+ {-0.0137, -0.8012, 0.5983, % dgf_base_tfo
+ -0.2523, 0.5817, 0.7733,
+ -0.9675, -0.1404, -0.2101,
+ 0.2031, 8.3874, 0.4228},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {5.2416, -8.2422, 2.8181}, % C5'
+ {5.2050, -8.8128, 1.8901}, % H5'
+ {5.5368, -8.7738, 3.7227}, % H5''
+ {6.3232, -7.2037, 2.6002}, % C4'
+ {7.3048, -7.6757, 2.5577}, % H4'
+ {6.0635, -6.5092, 1.3456}, % O4'
+ {6.4697, -5.1547, 1.4629}, % C1'
+ {7.2354, -5.0043, 0.7018}, % H1'
+ {7.0856, -4.9610, 2.8521}, % C2'
+ {6.7777, -3.9935, 3.2487}, % H2''
+ {8.4627, -5.1992, 2.7423}, % O2'
+ {8.8693, -4.8638, 1.9399}, % H2'
+ {6.3877, -6.0809, 3.6362}, % C3'
+ {5.3770, -5.7562, 3.8834}, % H3'
+ {7.1024, -6.4754, 4.7985}, % O3'
+ {5.2764, -4.2883, 1.2538}, % N1
+ {4.3777, -2.2062, 0.7229}, % N3
+ {5.5069, -2.9779, 0.9088}, % C2
+ {3.0693, -2.6246, 0.8500}, % C4
+ {2.9279, -4.0146, 1.2149}, % C5
+ {4.0101, -4.7892, 1.4017}, % C6
+ u, {
+ {6.6267, -2.5166, 0.7728}, % O2
+ {2.1383, -1.8396, 0.6581}, % O4
+ {4.5223, -1.2489, 0.4716}, % H3
+ {2.0151, -4.4065, 1.3290}, % H5
+ {3.8886, -5.7486, 1.6535}} % H6
+ }.
+
+rU02() ->
+ {
+ {0.5141, 0.0246, 0.8574, % dgf_base_tfo
+ -0.5547, -0.7529, 0.3542,
+ 0.6542, -0.6577, -0.3734,
+ -9.1111, -3.4598, -3.2939},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {4.3825, -6.6585, 4.0489}, % C5'
+ {4.6841, -7.2019, 4.9443}, % H5'
+ {3.6189, -5.8889, 4.1625}, % H5''
+ {5.6255, -5.9175, 3.5998}, % C4'
+ {5.8732, -5.1228, 4.3034}, % H4'
+ {6.7337, -6.8605, 3.5222}, % O4'
+ {7.5932, -6.4923, 2.4548}, % C1'
+ {8.5661, -6.2983, 2.9064}, % H1'
+ {7.0527, -5.2012, 1.8322}, % C2'
+ {7.1627, -5.2525, 0.7490}, % H2''
+ {7.6666, -4.1249, 2.4880}, % O2'
+ {8.5944, -4.2543, 2.6981}, % H2'
+ {5.5661, -5.3029, 2.2009}, % C3'
+ {5.0841, -6.0018, 1.5172}, % H3'
+ {4.9062, -4.0452, 2.2042}, % O3'
+ {7.6298, -7.6136, 1.4752}, % N1
+ {8.6945, -8.7046, -0.2857}, % N3
+ {8.6943, -7.6514, 0.6066}, % C2
+ {7.7426, -9.6987, -0.3801}, % C4
+ {6.6642, -9.5742, 0.5722}, % C5
+ {6.6391, -8.5592, 1.4526}, % C6
+ u, {
+ {9.5840, -6.8186, 0.6136}, % O2
+ {7.8505, -10.5925, -1.2223}, % O4
+ {9.4601, -8.7514, -0.9277}, % H3
+ {5.9281, -10.2509, 0.5782}, % H5
+ {5.8831, -8.4931, 2.1028}} % H6
+ }.
+
+rU03() ->
+ {
+ {-0.4993, 0.0476, 0.8651, % dgf_base_tfo
+ 0.8078, -0.3353, 0.4847,
+ 0.3132, 0.9409, 0.1290,
+ 6.2989, -5.2303, -3.8577},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {3.9938, -6.7042, 1.9023}, % C5'
+ {3.2332, -5.9343, 2.0319}, % H5'
+ {3.9666, -7.2863, 0.9812}, % H5''
+ {5.3098, -5.9546, 1.8564}, % C4'
+ {5.3863, -5.3702, 0.9395}, % H4'
+ {5.3851, -5.0642, 3.0076}, % O4'
+ {6.7315, -4.9724, 3.4462}, % C1'
+ {7.0033, -3.9202, 3.3619}, % H1'
+ {7.5997, -5.8018, 2.4948}, % C2'
+ {8.3627, -6.3254, 3.0707}, % H2''
+ {8.0410, -4.9501, 1.4724}, % O2'
+ {8.2781, -4.0644, 1.7570}, % H2'
+ {6.5701, -6.8129, 1.9714}, % C3'
+ {6.4186, -7.5809, 2.7299}, % H3'
+ {6.9357, -7.3841, 0.7235}, % O3'
+ {6.8024, -5.4718, 4.8475}, % N1
+ {7.9218, -5.5700, 6.8877}, % N3
+ {7.8908, -5.0886, 5.5944}, % C2
+ {6.9789, -6.3827, 7.4823}, % C4
+ {5.8742, -6.7319, 6.6202}, % C5
+ {5.8182, -6.2769, 5.3570}, % C6
+ u, {
+ {8.7747, -4.3728, 5.1568}, % O2
+ {7.1154, -6.7509, 8.6509}, % O4
+ {8.7055, -5.3037, 7.4491}, % H3
+ {5.1416, -7.3178, 6.9665}, % H5
+ {5.0441, -6.5310, 4.7784}} % H6
+ }.
+
+rU04() ->
+ {
+ {-0.5669, -0.8012, 0.1918, % dgf_base_tfo
+ -0.8129, 0.5817, 0.0273,
+ -0.1334, -0.1404, -0.9811,
+ -0.3279, 8.3874, 0.3355},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {5.2416, -8.2422, 2.8181}, % C5'
+ {5.2050, -8.8128, 1.8901}, % H5'
+ {5.5368, -8.7738, 3.7227}, % H5''
+ {6.3232, -7.2037, 2.6002}, % C4'
+ {7.3048, -7.6757, 2.5577}, % H4'
+ {6.0635, -6.5092, 1.3456}, % O4'
+ {6.4697, -5.1547, 1.4629}, % C1'
+ {7.2354, -5.0043, 0.7018}, % H1'
+ {7.0856, -4.9610, 2.8521}, % C2'
+ {6.7777, -3.9935, 3.2487}, % H2''
+ {8.4627, -5.1992, 2.7423}, % O2'
+ {8.8693, -4.8638, 1.9399}, % H2'
+ {6.3877, -6.0809, 3.6362}, % C3'
+ {5.3770, -5.7562, 3.8834}, % H3'
+ {7.1024, -6.4754, 4.7985}, % O3'
+ {5.2764, -4.2883, 1.2538}, % N1
+ {3.8961, -3.0896, -0.1893}, % N3
+ {5.0095, -3.8907, -0.0346}, % C2
+ {3.0480, -2.6632, 0.8116}, % C4
+ {3.4093, -3.1310, 2.1292}, % C5
+ {4.4878, -3.9124, 2.3088}, % C6
+ u, {
+ {5.7005, -4.2164, -0.9842}, % O2
+ {2.0800, -1.9458, 0.5503}, % O4
+ {3.6834, -2.7882, -1.1190}, % H3
+ {2.8508, -2.8721, 2.9172}, % H5
+ {4.7188, -4.2247, 3.2295}} % H6
+ }.
+
+rU05() ->
+ {
+ {-0.6298, 0.0246, 0.7763, % dgf_base_tfo
+ -0.5226, -0.7529, -0.4001,
+ 0.5746, -0.6577, 0.4870,
+ -0.0208, -3.4598, -9.6882},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {4.3825, -6.6585, 4.0489}, % C5'
+ {4.6841, -7.2019, 4.9443}, % H5'
+ {3.6189, -5.8889, 4.1625}, % H5''
+ {5.6255, -5.9175, 3.5998}, % C4'
+ {5.8732, -5.1228, 4.3034}, % H4'
+ {6.7337, -6.8605, 3.5222}, % O4'
+ {7.5932, -6.4923, 2.4548}, % C1'
+ {8.5661, -6.2983, 2.9064}, % H1'
+ {7.0527, -5.2012, 1.8322}, % C2'
+ {7.1627, -5.2525, 0.7490}, % H2''
+ {7.6666, -4.1249, 2.4880}, % O2'
+ {8.5944, -4.2543, 2.6981}, % H2'
+ {5.5661, -5.3029, 2.2009}, % C3'
+ {5.0841, -6.0018, 1.5172}, % H3'
+ {4.9062, -4.0452, 2.2042}, % O3'
+ {7.6298, -7.6136, 1.4752}, % N1
+ {8.5977, -9.5977, 0.7329}, % N3
+ {8.5951, -8.5745, 1.6594}, % C2
+ {7.7372, -9.7371, -0.3364}, % C4
+ {6.7596, -8.6801, -0.4476}, % C5
+ {6.7338, -7.6721, 0.4408}, % C6
+ u, {
+ {9.3993, -8.5377, 2.5743}, % O2
+ {7.8374, -10.6990, -1.1008}, % O4
+ {9.2924, -10.3081, 0.8477}, % H3
+ {6.0932, -8.6982, -1.1929}, % H5
+ {6.0481, -6.9515, 0.3446}} % H6
+ }.
+
+rU06() ->
+ {
+ {-0.9837, 0.0476, -0.1733, % dgf_base_tfo
+ -0.1792, -0.3353, 0.9249,
+ -0.0141, 0.9409, 0.3384,
+ 5.7793, -5.2303, 4.5997},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {3.9938, -6.7042, 1.9023}, % C5'
+ {3.2332, -5.9343, 2.0319}, % H5'
+ {3.9666, -7.2863, 0.9812}, % H5''
+ {5.3098, -5.9546, 1.8564}, % C4'
+ {5.3863, -5.3702, 0.9395}, % H4'
+ {5.3851, -5.0642, 3.0076}, % O4'
+ {6.7315, -4.9724, 3.4462}, % C1'
+ {7.0033, -3.9202, 3.3619}, % H1'
+ {7.5997, -5.8018, 2.4948}, % C2'
+ {8.3627, -6.3254, 3.0707}, % H2''
+ {8.0410, -4.9501, 1.4724}, % O2'
+ {8.2781, -4.0644, 1.7570}, % H2'
+ {6.5701, -6.8129, 1.9714}, % C3'
+ {6.4186, -7.5809, 2.7299}, % H3'
+ {6.9357, -7.3841, 0.7235}, % O3'
+ {6.8024, -5.4718, 4.8475}, % N1
+ {6.6920, -5.0495, 7.1354}, % N3
+ {6.6201, -4.5500, 5.8506}, % C2
+ {6.9254, -6.3614, 7.4926}, % C4
+ {7.1046, -7.2543, 6.3718}, % C5
+ {7.0391, -6.7951, 5.1106}, % C6
+ u, {
+ {6.4083, -3.3696, 5.6340}, % O2
+ {6.9679, -6.6901, 8.6800}, % O4
+ {6.5626, -4.3957, 7.8812}, % H3
+ {7.2781, -8.2254, 6.5350}, % H5
+ {7.1657, -7.4312, 4.3503}} % H6
+ }.
+
+rU07() ->
+ {
+ {-0.9434, 0.3172, 0.0971, % dgf_base_tfo
+ 0.2294, 0.4125, 0.8816,
+ 0.2396, 0.8539, -0.4619,
+ 8.3625, -52.7147, 1.3745},
+ {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo
+ -0.8297, 0.4733, -0.2959,
+ 0.4850, 0.8737, 0.0379,
+ -14.7774, -45.2464, 21.9088},
+ {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo
+ -0.5932, -0.6591, 0.4624,
+ -0.7980, 0.4055, -0.4458,
+ 43.7634, 4.3296, 28.4890},
+ {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo
+ 0.6803, 0.3317, 0.6536,
+ -0.1673, -0.7979, 0.5791,
+ -17.1858, 41.4390, -27.0751},
+ {21.3880, 15.0780, 45.5770}, % P
+ {21.9980, 14.5500, 46.8210}, % O1P
+ {21.1450, 14.0270, 44.5420}, % O2P
+ {22.1250, 16.3600, 44.9460}, % O5'
+ {21.5037, 16.8594, 43.7323}, % C5'
+ {20.8147, 17.6663, 43.9823}, % H5'
+ {21.1086, 16.0230, 43.1557}, % H5''
+ {22.5654, 17.4874, 42.8616}, % C4'
+ {22.1584, 17.7243, 41.8785}, % H4'
+ {23.0557, 18.6826, 43.4751}, % O4'
+ {24.4788, 18.6151, 43.6455}, % C1'
+ {24.9355, 19.0840, 42.7739}, % H1'
+ {24.7958, 17.1427, 43.6474}, % C2'
+ {24.5652, 16.7400, 44.6336}, % H2''
+ {26.1041, 16.8773, 43.2455}, % O2'
+ {26.7516, 17.5328, 43.5149}, % H2'
+ {23.8109, 16.5979, 42.6377}, % C3'
+ {23.5756, 15.5686, 42.9084}, % H3'
+ {24.2890, 16.7447, 41.2729}, % O3'
+ {24.9420, 19.2174, 44.8923}, % N1
+ {25.2655, 20.5636, 44.8883}, % N3
+ {25.1663, 21.2219, 43.8561}, % C2
+ {25.6911, 21.1219, 46.0494}, % C4
+ {25.8051, 20.4068, 47.2048}, % C5
+ {26.2093, 20.9962, 48.2534}, % C6
+ u, {
+ {25.4692, 19.0221, 47.2053}, % O2
+ {25.0502, 18.4827, 46.0370}, % O4
+ {25.9599, 22.1772, 46.0966}, % H3
+ {25.5545, 18.4409, 48.1234}, % H5
+ {24.7854, 17.4265, 45.9883}} % H6
+ }.
+
+rU08() ->
+ {
+ {-0.0080, -0.7928, 0.6094, % dgf_base_tfo
+ -0.7512, 0.4071, 0.5197,
+ -0.6601, -0.4536, -0.5988,
+ 44.1482, 30.7036, 2.1088},
+ {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo
+ -0.8297, 0.4733, -0.2959,
+ 0.4850, 0.8737, 0.0379,
+ -14.7774, -45.2464, 21.9088},
+ {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo
+ -0.5932, -0.6591, 0.4624,
+ -0.7980, 0.4055, -0.4458,
+ 43.7634, 4.3296, 28.4890},
+ {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo
+ 0.6803, 0.3317, 0.6536,
+ -0.1673, -0.7979, 0.5791,
+ -17.1858, 41.4390, -27.0751},
+ {21.3880, 15.0780, 45.5770}, % P
+ {21.9980, 14.5500, 46.8210}, % O1P
+ {21.1450, 14.0270, 44.5420}, % O2P
+ {22.1250, 16.3600, 44.9460}, % O5'
+ {23.5096, 16.1227, 44.5783}, % C5'
+ {23.5649, 15.8588, 43.5222}, % H5'
+ {23.9621, 15.4341, 45.2919}, % H5''
+ {24.2805, 17.4138, 44.7151}, % C4'
+ {25.3492, 17.2309, 44.6030}, % H4'
+ {23.8497, 18.3471, 43.7208}, % O4'
+ {23.4090, 19.5681, 44.3321}, % C1'
+ {24.2595, 20.2496, 44.3524}, % H1'
+ {23.0418, 19.1813, 45.7407}, % C2'
+ {22.0532, 18.7224, 45.7273}, % H2''
+ {23.1307, 20.2521, 46.6291}, % O2'
+ {22.8888, 21.1051, 46.2611}, % H2'
+ {24.0799, 18.1326, 46.0700}, % C3'
+ {23.6490, 17.4370, 46.7900}, % H3'
+ {25.3329, 18.7227, 46.5109}, % O3'
+ {22.2515, 20.1624, 43.6698}, % N1
+ {22.4760, 21.0609, 42.6406}, % N3
+ {23.6229, 21.3462, 42.3061}, % C2
+ {21.3986, 21.6081, 42.0236}, % C4
+ {20.1189, 21.3012, 42.3804}, % C5
+ {19.1599, 21.8516, 41.7578}, % C6
+ u, {
+ {19.8919, 20.3745, 43.4387}, % O2
+ {20.9790, 19.8423, 44.0440}, % O4
+ {21.5235, 22.3222, 41.2097}, % H3
+ {18.8732, 20.1200, 43.7312}, % H5
+ {20.8545, 19.1313, 44.8608}} % H6
+ }.
+
+rU09() ->
+ {
+ {-0.0317, 0.1374, 0.9900, % dgf_base_tfo
+ -0.3422, -0.9321, 0.1184,
+ 0.9391, -0.3351, 0.0765,
+ -32.1929, 25.8198, -28.5088},
+ {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo
+ -0.8297, 0.4733, -0.2959,
+ 0.4850, 0.8737, 0.0379,
+ -14.7774, -45.2464, 21.9088},
+ {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo
+ -0.5932, -0.6591, 0.4624,
+ -0.7980, 0.4055, -0.4458,
+ 43.7634, 4.3296, 28.4890},
+ {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo
+ 0.6803, 0.3317, 0.6536,
+ -0.1673, -0.7979, 0.5791,
+ -17.1858, 41.4390, -27.0751},
+ {21.3880, 15.0780, 45.5770}, % P
+ {21.9980, 14.5500, 46.8210}, % O1P
+ {21.1450, 14.0270, 44.5420}, % O2P
+ {22.1250, 16.3600, 44.9460}, % O5'
+ {21.5037, 16.8594, 43.7323}, % C5'
+ {20.8147, 17.6663, 43.9823}, % H5'
+ {21.1086, 16.0230, 43.1557}, % H5''
+ {22.5654, 17.4874, 42.8616}, % C4'
+ {23.0565, 18.3036, 43.3915}, % H4'
+ {23.5375, 16.5054, 42.4925}, % O4'
+ {23.6574, 16.4257, 41.0649}, % C1'
+ {24.4701, 17.0882, 40.7671}, % H1'
+ {22.3525, 16.9643, 40.5396}, % C2'
+ {21.5993, 16.1799, 40.6133}, % H2''
+ {22.4693, 17.4849, 39.2515}, % O2'
+ {23.0899, 17.0235, 38.6827}, % H2'
+ {22.0341, 18.0633, 41.5279}, % C3'
+ {20.9509, 18.1709, 41.5846}, % H3'
+ {22.7249, 19.3020, 41.2100}, % O3'
+ {23.8580, 15.0648, 40.5757}, % N1
+ {25.1556, 14.5982, 40.4523}, % N3
+ {26.1047, 15.3210, 40.7448}, % C2
+ {25.3391, 13.3315, 40.0020}, % C4
+ {24.2974, 12.5148, 39.6749}, % C5
+ {24.5450, 11.3410, 39.2610}, % C6
+ u, {
+ {22.9633, 12.9979, 39.8053}, % O2
+ {22.8009, 14.2648, 40.2524}, % O4
+ {26.3414, 12.9194, 39.8855}, % H3
+ {22.1227, 12.3533, 39.5486}, % H5
+ {21.7989, 14.6788, 40.3650}} % H6
+ }.
+
+rU10() ->
+ {
+ {-0.9674, 0.1021, -0.2318, % dgf_base_tfo
+ -0.2514, -0.2766, 0.9275,
+ 0.0306, 0.9555, 0.2933,
+ 27.8571, -42.1305, -24.4563},
+ {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo
+ -0.8297, 0.4733, -0.2959,
+ 0.4850, 0.8737, 0.0379,
+ -14.7774, -45.2464, 21.9088},
+ {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo
+ -0.5932, -0.6591, 0.4624,
+ -0.7980, 0.4055, -0.4458,
+ 43.7634, 4.3296, 28.4890},
+ {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo
+ 0.6803, 0.3317, 0.6536,
+ -0.1673, -0.7979, 0.5791,
+ -17.1858, 41.4390, -27.0751},
+ {21.3880, 15.0780, 45.5770}, % P
+ {21.9980, 14.5500, 46.8210}, % O1P
+ {21.1450, 14.0270, 44.5420}, % O2P
+ {22.1250, 16.3600, 44.9460}, % O5'
+ {23.5096, 16.1227, 44.5783}, % C5'
+ {23.5649, 15.8588, 43.5222}, % H5'
+ {23.9621, 15.4341, 45.2919}, % H5''
+ {24.2805, 17.4138, 44.7151}, % C4'
+ {23.8509, 18.1819, 44.0720}, % H4'
+ {24.2506, 17.8583, 46.0741}, % O4'
+ {25.5830, 18.0320, 46.5775}, % C1'
+ {25.8569, 19.0761, 46.4256}, % H1'
+ {26.4410, 17.1555, 45.7033}, % C2'
+ {26.3459, 16.1253, 46.0462}, % H2''
+ {27.7649, 17.5888, 45.6478}, % O2'
+ {28.1004, 17.9719, 46.4616}, % H2'
+ {25.7796, 17.2997, 44.3513}, % C3'
+ {25.9478, 16.3824, 43.7871}, % H3'
+ {26.2154, 18.4984, 43.6541}, % O3'
+ {25.7321, 17.6281, 47.9726}, % N1
+ {25.5136, 18.5779, 48.9560}, % N3
+ {25.2079, 19.7276, 48.6503}, % C2
+ {25.6482, 18.1987, 50.2518}, % C4
+ {25.9847, 16.9266, 50.6092}, % C5
+ {26.0918, 16.6439, 51.8416}, % C6
+ u, {
+ {26.2067, 15.9515, 49.5943}, % O2
+ {26.0713, 16.3497, 48.3080}, % O4
+ {25.4890, 18.9105, 51.0618}, % H3
+ {26.4742, 14.9310, 49.8682}, % H5
+ {26.2346, 15.6394, 47.4975}} % H6
+ }.
+
+rUs() -> [rU01(),rU02(),rU03(),rU04(),rU05(),rU06(),rU07(),
+ rU08(),rU09(),rU10()].
+
+rG_() ->
+ {
+ {-0.2067, -0.0264, 0.9780, % dgf_base_tfo
+ 0.9770, -0.0586, 0.2049,
+ 0.0519, 0.9979, 0.0379,
+ 1.0331, -46.8078, -36.4742},
+ {-0.8644, -0.4956, -0.0851, % p_o3'_275_tfo
+ -0.0427, 0.2409, -0.9696,
+ 0.5010, -0.8345, -0.2294,
+ 4.0167, 54.5377, 12.4779},
+ {0.3706, -0.6167, 0.6945, % p_o3'_180_tfo
+ -0.2867, -0.7872, -0.5460,
+ 0.8834, 0.0032, -0.4686,
+ -52.9020, 18.6313, -0.6709},
+ {0.4155, 0.9025, -0.1137, % p_o3'_60_tfo
+ 0.9040, -0.4236, -0.0582,
+ -0.1007, -0.0786, -0.9918,
+ -7.6624, -25.2080, 49.5181},
+ {31.3810, 0.1400, 47.5810}, % P
+ {29.9860, 0.6630, 47.6290}, % O1P
+ {31.7210, -0.6460, 48.8090}, % O2P
+ {32.4940, 1.2540, 47.2740}, % O5'
+ {32.1610, 2.2370, 46.2560}, % C5'
+ {31.2986, 2.8190, 46.5812}, % H5'
+ {32.0980, 1.7468, 45.2845}, % H5''
+ {33.3476, 3.1959, 46.1947}, % C4'
+ {33.2668, 3.8958, 45.3630}, % H4'
+ {33.3799, 3.9183, 47.4216}, % O4'
+ {34.6515, 3.7222, 48.0398}, % C1'
+ {35.2947, 4.5412, 47.7180}, % H1'
+ {35.1756, 2.4228, 47.4827}, % C2'
+ {34.6778, 1.5937, 47.9856}, % H2''
+ {36.5631, 2.2672, 47.4798}, % O2'
+ {37.0163, 2.6579, 48.2305}, % H2'
+ {34.6953, 2.5043, 46.0448}, % C3'
+ {34.5444, 1.4917, 45.6706}, % H3'
+ {35.6679, 3.3009, 45.3487}, % O3'
+ {37.4804, 4.0914, 52.2559}, % N1
+ {36.9670, 4.1312, 49.9281}, % N3
+ {37.8045, 4.2519, 50.9550}, % C2
+ {35.7171, 3.8264, 50.3222}, % C4
+ {35.2668, 3.6420, 51.6115}, % C5
+ {36.2037, 3.7829, 52.6706}, % C6
+ g, {
+ {39.0869, 4.5552, 50.7092}, % N2
+ {33.9075, 3.3338, 51.6102}, % N7
+ {34.6126, 3.6358, 49.5108}, % N9
+ {33.5805, 3.3442, 50.3425}, % C8
+ {35.9958, 3.6512, 53.8724}, % O6
+ {38.2106, 4.2053, 52.9295}, % H1
+ {39.8218, 4.6863, 51.3896}, % H21
+ {39.3420, 4.6857, 49.7407}, % H22
+ {32.5194, 3.1070, 50.2664}} % H8
+ }.
+
+rU_() ->
+ {
+ {-0.0109, 0.5907, 0.8068, % dgf_base_tfo
+ 0.2217, -0.7853, 0.5780,
+ 0.9751, 0.1852, -0.1224,
+ -1.4225, -11.0956, -2.5217},
+ {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo
+ 0.0649, 0.4366, -0.8973,
+ 0.5521, -0.7648, -0.3322,
+ 1.6833, 6.8060, -7.0011},
+ {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo
+ -0.4628, -0.6450, -0.6082,
+ 0.8168, -0.0436, -0.5753,
+ -6.8179, -3.9778, -5.9887},
+ {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo
+ 0.8103, -0.5790, 0.0906,
+ -0.0255, -0.1894, -0.9816,
+ 6.1203, -7.1051, 3.1984},
+ {2.6760, -8.4960, 3.2880}, % P
+ {1.4950, -7.6230, 3.4770}, % O1P
+ {2.9490, -9.4640, 4.3740}, % O2P
+ {3.9730, -7.5950, 3.0340}, % O5'
+ {5.2430, -8.2420, 2.8260}, % C5'
+ {5.1974, -8.8497, 1.9223}, % H5'
+ {5.5548, -8.7348, 3.7469}, % H5''
+ {6.3140, -7.2060, 2.5510}, % C4'
+ {5.8744, -6.2116, 2.4731}, % H4'
+ {7.2798, -7.2260, 3.6420}, % O4'
+ {8.5733, -6.9410, 3.1329}, % C1'
+ {8.9047, -6.0374, 3.6446}, % H1'
+ {8.4429, -6.6596, 1.6327}, % C2'
+ {9.2880, -7.1071, 1.1096}, % H2''
+ {8.2502, -5.2799, 1.4754}, % O2'
+ {8.7676, -4.7284, 2.0667}, % H2'
+ {7.1642, -7.4416, 1.3021}, % C3'
+ {7.4125, -8.5002, 1.2260}, % H3'
+ {6.5160, -6.9772, 0.1267}, % O3'
+ {9.4531, -8.1107, 3.4087}, % N1
+ {11.5931, -9.0015, 3.6357}, % N3
+ {10.8101, -7.8950, 3.3748}, % C2
+ {11.1439, -10.2744, 3.9206}, % C4
+ {9.7056, -10.4026, 3.9332}, % C5
+ {8.9192, -9.3419, 3.6833}, % C6
+ u, {
+ {11.3013, -6.8063, 3.1326}, % O2
+ {11.9431, -11.1876, 4.1375}, % O4
+ {12.5840, -8.8673, 3.6158}, % H3
+ {9.2891, -11.2898, 4.1313}, % H5
+ {7.9263, -9.4537, 3.6977}} % H6
+ }.
+
+
+% -- PARTIAL INSTANTIATIONS --------------------------------------------------
+
+%var ::= {Int, Tfo, Nuc}
+
+absolute_pos({_I,T,_N}, P) -> tfo_apply(T, P).
+
+atom_pos(Atom, {I,T,N}) ->
+ absolute_pos({I,T,N}, p_apply(Atom, N)).
+
+get_var(Id,[{Id,T,N}|_]) -> {Id,T,N};
+get_var(Id,[_|Lst]) -> get_var(Id,Lst).
+
+
+% -- SEARCH ------------------------------------------------------------------
+
+% Sequential backtracking algorithm
+
+search(Partial_inst,[],_) ->
+ [Partial_inst];
+search(Partial_inst,[{F,Arg0,Arg1}|T],Constraint) ->
+ try_assignments(p_apply(F, Arg0,Arg1,Partial_inst),
+ Constraint,
+ Partial_inst,
+ T);
+search(Partial_inst,[{F,Arg0,Arg1,Arg2}|T],Constraint) ->
+ try_assignments(p_apply(F, Arg0,Arg1,Arg2,Partial_inst),
+ Constraint,
+ Partial_inst,
+ T).
+
+try_assignments([],_,_,_) -> [];
+try_assignments([V|Vs], Constraint, Partial_inst,T) ->
+ case p_apply(Constraint, V, Partial_inst) of
+ true -> append(search([V|Partial_inst],T,Constraint),
+ try_assignments(Vs, Constraint, Partial_inst,T));
+ _ -> try_assignments(Vs, Constraint, Partial_inst,T)
+ end.
+
+
+% -- DOMAINS -----------------------------------------------------------------
+
+% Primary structure: strand A CUGCCACGUCUG, strand B CAGACGUGGCAG
+%
+% Secondary structure: strand A CUGCCACGUCUG
+% ||||||
+% GACGGUGCAGAC strand B
+%
+% Tertiary structure:
+%
+% 5' end of strand A C1----G12 3' end of strand B
+% U2-------A11
+% G3-------C10
+% C4-----G9
+% C5---G8
+% A6
+% G6-C7
+% C5----G8
+% A4-------U9
+% G3--------C10
+% A2-------U11
+% 5' end of strand B C1----G12 3' end of strand A
+%
+% "helix", "stacked" and "connected" describe the spatial relationship
+% between two consecutive nucleotides. E.g. the nucleotides C1 and U2
+% from the strand A.
+%
+% "wc" (stands for Watson-Crick and is a type of base-pairing),
+% and "wc-dumas" describe the spatial relationship between
+% nucleotides from two chains that are growing in opposite directions.
+% E.g. the nucleotides C1 from strand A and G12 from strand B.
+
+% Dynamic Domains
+
+% Given,
+% "ref" a nucleotide which is already positioned,
+% "nuc" the nucleotide to be placed,
+% and "tfo" a transformation matrix which expresses the desired
+% relationship between "ref" and "nuc",
+% the function "dgf-base" computes the transformation matrix that
+% places the nucleotide "nuc" in the given relationship to "ref".
+
+dgf_base(Tfo, V, Nuc) ->
+ {_I,_T,N} = V,
+ tfo_combine(nuc_dgf_base_tfo(Nuc),
+ tfo_combine(Tfo,tfo_inv_ortho(process_type(type(N),V)))).
+
+process_type(a,V) ->
+ tfo_align(atom_pos(nuc_C1_, V),atom_pos(rA_N9, V),atom_pos(nuc_C4, V));
+process_type(c,V) ->
+ tfo_align(atom_pos(nuc_C1_, V),atom_pos(nuc_N1, V),atom_pos(nuc_C2, V));
+process_type(g,V) ->
+ tfo_align(atom_pos(nuc_C1_, V),atom_pos(rG_N9, V),atom_pos(nuc_C4, V));
+process_type(_,V) ->
+ tfo_align(atom_pos(nuc_C1_, V),atom_pos(nuc_N1, V),atom_pos(nuc_C2, V)).
+
+
+% Placement of first nucleotide.
+
+reference(Nuc,I,_) ->
+ [{I,tfo_id(),Nuc}].
+
+% The transformation matrix for wc is from:
+%
+% Chandrasekaran R. et al (1989) A Re-Examination of the Crystal
+% Structure of A-DNA Using Fiber Diffraction Data. J. Biomol.
+% Struct. & Dynamics 6(6):1189-1202.
+
+wc_tfo() ->
+ {
+ -1.0000, 0.0028, -0.0019,
+ 0.0028, 0.3468, -0.9379,
+ -0.0019, -0.9379, -0.3468,
+ -0.0080, 6.0730, 8.7208
+ }.
+
+wc(Nuc,I,J,Partial_inst) ->
+ [{I,dgf_base(wc_tfo(),get_var(J,Partial_inst),Nuc),Nuc}].
+
+wc_dumas_tfo() ->
+ {
+ -0.9737, -0.1834, 0.1352,
+ -0.1779, 0.2417, -0.9539,
+ 0.1422, -0.9529, -0.2679,
+ 0.4837, 6.2649, 8.0285
+ }.
+
+wc_dumas(Nuc,I,J,Partial_inst) ->
+ [{I,dgf_base(wc_dumas_tfo(),get_var(J,Partial_inst),Nuc),Nuc}].
+
+helix5__tfo() ->
+ {
+ 0.9886, -0.0961, 0.1156,
+ 0.1424, 0.8452, -0.5152,
+ -0.0482, 0.5258, 0.8492,
+ -3.8737, 0.5480, 3.8024
+ }.
+
+helix5_(Nuc,I,J,Partial_inst) ->
+ [{I,dgf_base(helix5__tfo(),get_var(J,Partial_inst),Nuc),Nuc}].
+
+helix3__tfo() ->
+ {
+ 0.9886, 0.1424, -0.0482,
+ -0.0961, 0.8452, 0.5258,
+ 0.1156, -0.5152, 0.8492,
+ 3.4426, 2.0474, -3.7042
+ }.
+
+helix3_(Nuc,I,J,Partial_inst) ->
+ [{I,dgf_base(helix3__tfo(),get_var(J,Partial_inst),Nuc),Nuc}].
+
+g37_a38_tfo() ->
+ {
+ 0.9991, 0.0164, -0.0387,
+ -0.0375, 0.7616, -0.6470,
+ 0.0189, 0.6478, 0.7615,
+ -3.3018, 0.9975, 2.5585
+ }.
+
+g37_a38(Nuc,I,J,Partial_inst) ->
+ {I,dgf_base(g37_a38_tfo(),get_var(J,Partial_inst),Nuc),Nuc}.
+
+stacked5_(Nuc,I,J,Partial_inst) ->
+ [g37_a38(Nuc,I,J,Partial_inst) | helix5_(Nuc,I,J,Partial_inst)].
+
+a38_g37_tfo() ->
+ {
+ 0.9991, -0.0375, 0.0189,
+ 0.0164, 0.7616, 0.6478,
+ -0.0387, -0.6470, 0.7615,
+ 3.3819, 0.7718, -2.5321
+ }.
+
+a38_g37(Nuc,I,J,Partial_inst) ->
+ {I,dgf_base(a38_g37_tfo(),get_var(J,Partial_inst),Nuc),Nuc}.
+
+stacked3_(Nuc,I,J,Partial_inst) ->
+ [a38_g37(Nuc,I,J,Partial_inst) | helix3_(Nuc,I,J,Partial_inst)].
+
+p_o3_(Nucs,I,J,Partial_inst) ->
+ generate([],Nucs,I,J,Partial_inst).
+
+
+generate(Domains,[],_,_,_) ->
+ Domains;
+generate(Domains,[N|Ns],I,J,Partial_inst) ->
+ Ref = get_var(J,Partial_inst),
+ Align = tfo_inv_ortho(tfo_align(atom_pos(nuc_O3_,Ref),
+ atom_pos(nuc_C3_,Ref),
+ atom_pos(nuc_C4_,Ref))),
+ generate([{I,tfo_combine(nuc_p_o3__60_tfo(N),Align),N},
+ {I,tfo_combine(nuc_p_o3__180_tfo(N),Align),N},
+ {I,tfo_combine(nuc_p_o3__275_tfo(N),Align),N} | Domains],
+ Ns,I,J,Partial_inst).
+
+
+% -- PROBLEM STATEMENT -------------------------------------------------------
+
+% Define anticodon problem -- Science 253:1255 Figure 3a, 3b and 3c
+
+% anticodon_domains() ->
+% [
+% {reference, rC(), 27},
+% {helix5_, rC(), 28, 27},
+% {helix5_, rA(), 29, 28},
+% {helix5_, rG(), 30, 29},
+% {helix5_, rA(), 31, 30},
+% {wc, rU(), 39, 31},
+% {helix5_, rC(), 40, 39},
+% {helix5_, rU(), 41, 40},
+% {helix5_, rG(), 42, 41},
+% {helix5_, rG(), 43, 42},
+% {stacked3_, rA(), 38, 39},
+% {stacked3_, rG(), 37, 38},
+% {stacked3_, rA(), 36, 37},
+% {stacked3_, rA(), 35, 36},
+% {stacked3_, rG(), 34, 35}, %<-. Distance
+% {p_o3_, rCs(), 32, 31}, % | Constraint
+% {p_o3_, rUs(), 33, 32} %<-' 3.0 Angstroms
+% ].
+
+% Anticodon constraint
+
+anticodon_constraint({33,T,N},Partial_inst) ->
+ check0(dist(34,{33,T,N},Partial_inst));
+anticodon_constraint(_,_) -> true.
+
+check0(Dist) when is_float(Dist), Dist =< 3.0 -> true;
+check0(_) -> false.
+
+dist(J,V,Partial_inst) ->
+ pt_dist(atom_pos(nuc_P, get_var(J,Partial_inst)),
+ atom_pos(nuc_O3_,V)).
+
+% anticodon() -> search([], anticodon_domains(), anticodon_constraint).
+
+% Define pseudoknot problem -- Science 253:1255 Figure 4a and 4b
+pseudoknot_domains() ->
+ [
+ {reference, rA(), 23},
+ {wc_dumas, rU(), 8, 23},
+ {helix3_, rG(), 22, 23},
+ {wc_dumas, rC(), 9, 22},
+ {helix3_, rG(), 21, 22},
+ {wc_dumas, rC(), 10, 21},
+ {helix3_, rC(), 20, 21},
+ {wc_dumas, rG(), 11, 20},
+ {helix3_, rU_(), 19, 20}, %<-.
+ {wc_dumas, rA(), 12, 19}, % | Distance
+% % | Constraint
+% Helix 1 % | 4.0 Angstroms
+ {helix3_, rC(), 3, 19}, % |
+ {wc_dumas, rG(), 13, 3}, % |
+ {helix3_, rC(), 2, 3}, % |
+ {wc_dumas, rG(), 14, 2}, % |
+ {helix3_, rC(), 1, 2}, % |
+ {wc_dumas, rG_(), 15, 1}, % |
+% % |
+% L2 LOOP % |
+ {p_o3_, rUs(), 16, 15}, % |
+ {p_o3_, rCs(), 17, 16}, % |
+ {p_o3_, rAs(), 18, 17}, %<-'
+%
+% L1 LOOP
+ {helix3_, rU(), 7, 8}, %<-.
+ {p_o3_, rCs(), 4, 3}, % | Constraint
+ {stacked5_, rU(), 5, 4}, % | 4.5 Angstroms
+ {stacked5_, rC(), 6, 5} %<-'
+ ].
+
+% Pseudoknot constraint
+
+pseudoknot_constraint({18,T,N}, Partial_inst) ->
+ check1(dist(19, {18,T,N}, Partial_inst));
+pseudoknot_constraint({6,T,N}, Partial_inst) ->
+ check2(dist(7, {6,T,N}, Partial_inst));
+pseudoknot_constraint(_,_) -> true.
+
+check1(Dist) when is_float(Dist), Dist =< 4.0 -> true;
+check1(_) -> false.
+
+check2(Dist) when is_float(Dist), Dist =< 4.5 -> true;
+check2(_) -> false.
+
+do_pseudoknot() -> search([], pseudoknot_domains(), pseudoknot_constraint).
+
+% -- TESTING -----------------------------------------------------------------
+
+list_of_atoms(N) ->
+ append(list_of_common_atoms(N),list_of_specific_atoms(N)).
+
+list_of_common_atoms
+ ({
+ _,_,_,_,
+ P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_,
+ C3_,H3_,O3_,N1,N3,C2,C4,C5,C6,
+ _,_
+ }) ->
+ [P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_,
+ C3_,H3_,O3_,N1,N3,C2,C4,C5,C6].
+
+list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,a,
+ {N6,N7,N9,C8,H2,H61,H62,H8}}) ->
+ [N6,N7,N9,C8,H2,H61,H62,H8];
+list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,c,
+ {N4,O2,H41,H42,H5,H6}}) ->
+ [N4,O2,H41,H42,H5,H6];
+list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,g,
+ {N2,N7,N9,C8,O6,H1,H21,H22,H8}}) ->
+ [N2,N7,N9,C8,O6,H1,H21,H22,H8];
+list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,u,
+ {O2,O4,H3,H5,H6}}) ->
+ [O2,O4,H3,H5,H6].
+
+var_most_distant_atom(V) ->
+ {_,_,N} = V,
+ maximum(map(distance,V,list_of_atoms(N))).
+
+distance(V,P) ->
+ {X,Y,Z} = absolute_pos(V,P),
+ distance(X,Y,Z).
+
+distance(X,Y,Z) when is_float(X), is_float(Y), is_float(Z) ->
+ math:sqrt(X * X + Y * Y + Z * Z).
+
+sol_most_distant_atom(S) ->
+ maximum(map(var_most_distant_atom,S)).
+
+most_distant_atom(Sols) ->
+ maximum(map(sol_most_distant_atom, Sols)).
+
+maximum([H|T]) ->
+ max(T,H).
+
+max([H|T],M) when is_float(H), is_float(M), H > M ->
+ max(T,H);
+max([_|T],M) ->
+ max(T,M);
+max([],M) -> M.
+
+%%
+%% The map/2,3 functions rewritten to use a list comprehension,
+%% just to cover the letrec handling in the inliner.
+%%
+map(Func, L) ->
+ [p_apply(Func, H) || H <- L].
+
+map(Func, Arg, L) ->
+ [p_apply(Func, Arg, H) || H <- L].
+
+% p_apply implements higher order functions
+p_apply(sol_most_distant_atom, S) -> sol_most_distant_atom(S);
+p_apply(var_most_distant_atom, V) -> var_most_distant_atom(V);
+p_apply(nuc_C1_, X) -> nuc_C1_(X);
+p_apply(nuc_C2, X) -> nuc_C2(X);
+p_apply(nuc_C3_, X) -> nuc_C3_(X);
+p_apply(nuc_C4, X) -> nuc_C4(X);
+p_apply(nuc_C4_, X) -> nuc_C4_(X);
+p_apply(nuc_N1, X) -> nuc_N1(X);
+p_apply(nuc_O3_, X) -> nuc_O3_(X);
+p_apply(nuc_P, X) -> nuc_P(X);
+p_apply(nuc_dgf_base_tfo, X) -> nuc_dgf_base_tfo(X);
+p_apply(nuc_p_o3__180_tfo, X) -> nuc_p_o3__180_tfo(X);
+p_apply(nuc_p_o3__275_tfo, X) -> nuc_p_o3__275_tfo(X);
+p_apply(nuc_p_o3__60_tfo, X) -> nuc_p_o3__60_tfo(X);
+p_apply(rA_N9, X) -> rA_N9(X);
+p_apply(rG_N9, X) -> rG_N9(X).
+
+p_apply(anticodon_constraint, V, P) -> anticodon_constraint(V, P);
+p_apply(pseudoknot_constraint, V, P) -> pseudoknot_constraint(V, P);
+p_apply(distance, V, P) -> distance(V, P).
+
+p_apply(reference, A1, A2, A3) -> reference(A1, A2, A3).
+
+p_apply(helix5_, A1, A2, A3, A4) -> helix5_(A1, A2, A3, A4);
+p_apply(wc, A1, A2, A3, A4) -> wc(A1, A2, A3, A4);
+p_apply(stacked3_, A1, A2, A3, A4) -> stacked3_(A1, A2, A3, A4);
+p_apply(p_o3_, A1, A2, A3, A4) -> p_o3_(A1, A2, A3, A4);
+p_apply(wc_dumas, A1, A2, A3, A4) -> wc_dumas(A1, A2, A3, A4);
+p_apply(helix3_, A1, A2, A3, A4) -> helix3_(A1, A2, A3, A4);
+p_apply(stacked5_, A1, A2, A3, A4) -> stacked5_(A1, A2, A3, A4).
+
+loop(0, R) -> R;
+loop(N, _R) -> loop(N-1,most_distant_atom(do_pseudoknot())).
diff --git a/lib/compiler/test/inline_SUITE_data/smith.erl b/lib/compiler/test/inline_SUITE_data/smith.erl
new file mode 100644
index 0000000000..6aec7ad295
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/smith.erl
@@ -0,0 +1,95 @@
+% file: "smith.erl"
+
+-ifdef(ETOS).
+-define(IS_INTEGER(X),is_integer(X)).
+-else.
+-define(IS_INTEGER(X),integer(X)).
+-endif.
+
+-module(smith).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ Tops = generate_sequences(100,32,1),
+ Side = generate_sequence(32,0),
+ statistics(runtime),
+ R = loop(2,Tops,Side,0),
+ {R,R =:= 16}.
+
+max(A,B) when ?IS_INTEGER(A), ?IS_INTEGER(B) ->
+ if
+ A > B -> A;
+ true -> B
+ end.
+
+alpha_beta_penalty(A,B) when ?IS_INTEGER(A), ?IS_INTEGER(B) -> max(A-4,B-1).
+
+generate_sequence(Length,R) when ?IS_INTEGER(Length) ->
+ if
+ Length == 0 -> [];
+ true -> [R rem 10 | generate_sequence(Length-1,
+ (R * 11 + 1237501)
+ rem 10067)]
+ end.
+
+generate_sequences(0,_,_) -> [];
+generate_sequences(N,Length,R) when ?IS_INTEGER(N), ?IS_INTEGER(Length) ->
+ [generate_sequence(Length, R) | generate_sequences(N-1,Length,R+1)].
+
+match_entry(Top,Side,UpperLeft,Upper,Left) when ?IS_INTEGER(Top), ?IS_INTEGER(Side) ->
+ MeLeft = alpha_beta_penalty(element(3, Left), element(1, Left)),
+ MeUpper = alpha_beta_penalty(element(3, Upper), element(2, Upper)),
+ MeUpperLeft =
+ if
+ Top == Side ->
+ max(MeLeft,
+ max(MeUpper,
+ max(element(3,UpperLeft)+1,0)));
+ true ->
+ max(MeLeft,
+ max(MeUpper,
+ max(element(3,UpperLeft),0)))
+ end,
+ {MeLeft, MeUpper, MeUpperLeft,
+ max(MeUpperLeft,
+ max(element(4,Left),
+ max(element(4,Upper),element(4,UpperLeft))))}.
+
+match_zero_entry(Top,Side,{Left,_,UpperLeft,Max}) when ?IS_INTEGER(Top), ?IS_INTEGER(Side) ->
+ ELeft = alpha_beta_penalty(UpperLeft, Left),
+ Weight = max(1-abs(Side-Top),0),
+ EUpperLeft = max(max(ELeft,max(1-abs(Side-Top),0)),0),
+ EMax = max(max(Max,EUpperLeft),0),
+ {ELeft, -1, EUpperLeft, EMax}.
+
+match(Tops,Side,Prev,UpperLeft,Left) ->
+ match0(Tops, Side, Prev, UpperLeft, Left, [], none).
+
+match0([],_,_,_,_,Acc,Last) -> {Acc,Last};
+match0([Top|Tops],Side,[Upper|Prev],UpperLeft,Left,Acc,Last) when
+ ?IS_INTEGER(Top), ?IS_INTEGER(Side) ->
+ E = match_entry(Top, Side, UpperLeft, Upper, Left),
+ match0(Tops, Side, Prev, Upper, E, [E|Acc], E);
+match0([Top|Tops],Side,none,UpperLeft,Left,Acc,Last) when
+ ?IS_INTEGER(Top), ?IS_INTEGER(Side) ->
+ E = match_zero_entry(Top, Side, Left),
+ match0(Tops, Side, none, UpperLeft, E, [E|Acc], E).
+
+match_two_seq(Side,Top,Prev) ->
+ match_two_seq0(Side, Top, Prev, none).
+
+match_two_seq0([],_,_,Result) -> Result;
+match_two_seq0([S|Side],Top,Prev,Acc) when ?IS_INTEGER(S) ->
+ {Row,Result} = match(Top,S,Prev,{0,0,0,0},{0,0,0,0}),
+ match_two_seq0(Side, Top, Row, Result).
+
+match_sequences(Tops,Side) ->
+ match_sequences0(Tops, Side, -9999999).
+
+match_sequences0([],_,MaxResult) -> MaxResult;
+match_sequences0([Top|Tops],Side,CrntResult) ->
+ Result = element(4, match_two_seq(Top, Side, none)),
+ match_sequences0(Tops, Side, max(CrntResult, Result)).
+
+loop(0,Tops,Side,R) -> R;
+loop(N,Tops,Side,R) -> loop(N-1,Tops,Side,match_sequences(Tops,Side)).
diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl
new file mode 100644
index 0000000000..e62b2cd77e
--- /dev/null
+++ b/lib/compiler/test/lc_SUITE.erl
@@ -0,0 +1,162 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(lc_SUITE).
+
+-author('[email protected]').
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ basic/1,deeply_nested/1,no_generator/1,
+ empty_generator/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [basic,deeply_nested,no_generator,empty_generator].
+
+init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+basic(Config) when is_list(Config) ->
+ ?line L0 = lists:seq(1, 10),
+ ?line L1 = my_map(fun(X) -> {x,X} end, L0),
+ ?line L1 = [{x,X} || X <- L0],
+ ?line L0 = my_map(fun({x,X}) -> X end, L1),
+ ?line [1,2,3,4,5] = [X || X <- L0, X < 6],
+ ?line [4,5,6] = [X || X <- L0, X > 3, X < 7],
+ ?line [] = [X || X <- L0, X > 32, X < 7],
+ ?line [1,3,5,7,9] = [X || X <- L0, odd(X)],
+ ?line [2,4,6,8,10] = [X || X <- L0, not odd(X)],
+ ?line [1,3,5,9] = [X || X <- L0, odd(X), X =/= 7],
+ ?line [2,4,8,10] = [X || X <- L0, not odd(X), X =/= 6],
+
+ %% Append is specially handled.
+ ?line [1,3,5,9,2,4,8,10] = [X || X <- L0, odd(X), X =/= 7] ++
+ [X || X <- L0, not odd(X), X =/= 6],
+
+ %% Guards BIFs are evaluated in guard context. Weird, but true.
+ ?line [{a,b,true},{x,y,true,true}] = [X || X <- tuple_list(), element(3, X)],
+
+ %% Filter expressions with andalso/orelse.
+ ?line "abc123" = alphanum("?abc123.;"),
+
+ %% Error cases.
+ ?line [] = [{xx,X} || X <- L0, element(2, X) == no_no_no],
+ ?line {'EXIT',_} = (catch [X || X <- L1, list_to_atom(X) == dum]),
+ ?line [] = [X || X <- L1, X+1 < 2],
+ ?line {'EXIT',_} = (catch [X || X <- L1, odd(X)]),
+ ?line {'EXIT',{function_clause,[{?MODULE,_,[x]}|_]}} =
+ (catch [E || E <- id(x)]),
+ ok.
+
+tuple_list() ->
+ [{a,b,true},[a,b,c],glurf,{a,b,false,xx},{a,b},{x,y,true,true},{a,b,d,ddd}].
+
+my_map(F, L) ->
+ [F(X) || X <- L].
+
+odd(X) ->
+ X rem 2 == 1.
+
+alphanum(Str) ->
+ [C || C <- Str, ((C >= $0) andalso (C =< $9))
+ orelse ((C >= $a) andalso (C =< $z))
+ orelse ((C >= $A) andalso (C =< $Z))].
+
+deeply_nested(Config) when is_list(Config) ->
+ [[99,98,97,96,42,17,1764,12,11,10,9,8,7,6,5,4,3,7,2,1]] = deeply_nested_1(),
+ ok.
+
+deeply_nested_1() ->
+ %% This used to compile really, really SLOW before R11B-1...
+ [[X1,X2,X3,X4,X5,X6,X7(),X8,X9,X10,X11,X12,X13,X14,X15,X16,X17,X18(),X19,X20] ||
+ X1 <- [99],X2 <- [98],X3 <- [97],X4 <- [96],X5 <- [42],X6 <- [17],
+ X7 <- [fun() -> X5*X5 end],X8 <- [12],X9 <- [11],X10 <- [10],
+ X11 <- [9],X12 <- [8],X13 <- [7],X14 <- [6],X15 <- [5],
+ X16 <- [4],X17 <- [3],X18 <- [fun() -> X16+X17 end],X19 <- [2],X20 <- [1]].
+
+no_generator(Config) when is_list(Config) ->
+ ?line Seq = lists:seq(-10, 17),
+ ?line [no_gen_verify(no_gen(A, B), A, B) || A <- Seq, B <- Seq],
+
+ %% Literal expression, for coverage.
+ ?line [a] = [a || true],
+ ?line [a,b,c] = [a || true] ++ [b,c],
+ ok.
+
+no_gen(A, B) ->
+ [{A,B} || A+B =:= 0] ++
+ [{A,B} || A*B =:= 0] ++
+ [{A,B} || A rem B =:= 3] ++
+ [{A,B} || A =:= B] ++
+ [{one_more,A,B} || no_gen_one_more(A, B)] ++
+ [A || A =:= 1] ++
+ [A || A =:= 2] ++
+ [A || A =:= 3] ++
+ [A || A =:= 4] ++
+ [A || A =:= 5] ++
+ [A || A =:= 6] ++
+ [A || A =:= 7] ++
+ [A || A =:= 8] ++
+ [A || A =:= 9] ++
+ [B || B =:= 1] ++
+ [B || B =:= 2] ++
+ [B || B =:= 3] ++
+ [B || B =:= 4] ++
+ [B || B =:= 5] ++
+ [B || B =:= 6] ++
+ [B || B =:= 7] ++
+ [B || B =:= 8] ++
+ [B || B =:= 9].
+
+no_gen_verify(Res, A, B) ->
+ Pair = {A,B},
+ ShouldBe = no_gen_eval(fun() -> A+B =:= 0 end, Pair) ++
+ no_gen_eval(fun() -> A*B =:= 0 end, Pair) ++
+ no_gen_eval(fun() -> B =/= 0 andalso A rem B =:= 3 end, Pair) ++
+ no_gen_eval(fun() -> A =:= B end, Pair) ++
+ no_gen_eval(fun() -> A + 1 =:= B end, {one_more,A,B}) ++
+ no_gen_eval(fun() -> 1 =< A andalso A =< 9 end, A) ++
+ no_gen_eval(fun() -> 1 =< B andalso B =< 9 end, B),
+ case Res of
+ ShouldBe -> ok;
+ _ ->
+ io:format("A = ~p; B = ~p; Expected = ~p, actual = ~p", [A,B,ShouldBe,Res]),
+ ?t:fail()
+ end.
+
+no_gen_eval(Fun, Res) ->
+ case Fun() of
+ true -> [Res];
+ false -> []
+ end.
+
+no_gen_one_more(A, B) -> A + 1 =:= B.
+
+empty_generator(Config) when is_list(Config) ->
+ ?line [] = [X || {X} <- [], (false or (X/0 > 3))],
+ ok.
+
+id(I) -> I.
+
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
new file mode 100644
index 0000000000..20969c0b26
--- /dev/null
+++ b/lib/compiler/test/match_SUITE.erl
@@ -0,0 +1,355 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(match_SUITE).
+
+-export([all/1,
+ pmatch/1,mixed/1,aliases/1,match_in_call/1,
+ untuplify/1,shortcut_boolean/1,letify_guard/1,
+ selectify/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [pmatch,mixed,aliases,match_in_call,untuplify,shortcut_boolean,
+ letify_guard,selectify].
+
+pmatch(Config) when is_list(Config) ->
+ ?line ok = doit(1),
+ ?line ok = doit(2),
+ ?line {error,baz} = doit(3),
+ ?line {error,foobar} = doit(4),
+ ok.
+
+%% Thanks to Tobias Lindahl (HiPE).
+-define(FOO(X),
+ case X of
+ 1 -> foo;
+ 2 -> bar;
+ 3 -> baz;
+ 4 -> foobar
+ end).
+
+doit(X) ->
+ case ?FOO(X) of
+ foo -> ok;
+ bar -> ok;
+ Other -> {error, Other}
+ end.
+
+mixed(Config) when is_list(Config) ->
+ ?line glufs = mixit(1),
+ ?line klafs = mixit(2),
+ ?line fnurra = mixit(3),
+ ?line usch = mixit(4),
+ ?line {error,blurf} = mixit(5),
+ ?line {error,87987987} = mixit(6),
+ ?line {error,{a,b,c}} = mixit(7),
+ ok.
+
+mixit(X) ->
+ case case X of
+ 1 -> a;
+ 2 -> b;
+ 3 -> 42;
+ 4 -> 77;
+ 5 -> blurf;
+ 6 -> 87987987;
+ 7 -> {a,b,c}
+ end of
+ a -> glufs;
+ b -> klafs;
+ 42 -> fnurra;
+ 77 -> usch;
+ Other -> {error,Other}
+ end.
+
+aliases(Config) when is_list(Config) ->
+ %% Lists/strings.
+ ?line ok = str_alias("abc"),
+ ?line ok = str_alias("def"),
+ ?line ok = str_alias("ghi"),
+ ?line ok = str_alias("klm"),
+ ?line ok = str_alias("qrs"),
+ ?line ok = str_alias("xy"),
+ ?line ok = str_alias(""),
+ ?line ok = str_alias([]),
+ ?line error = str_alias("blurf"),
+
+ %% Characters/integers.
+ ?line ok = char_alias($v),
+ ?line ok = char_alias(118),
+ ?line ok = char_alias($w),
+ ?line ok = char_alias(119),
+ ?line ok = char_alias(42),
+ ?line ok = char_alias(3.0),
+ ?line error = char_alias($_),
+ ?line error = char_alias(0),
+
+ ?line {42,42,42} = three(42),
+
+ ?line {1,42,99,1,42,99} = tuple_alias({1,42,99}),
+ ?line {-10,20,-10,20,-10,20} = tuple_alias({-10,20}),
+ ?line 6 = tup_lit_alias({1,2,3}),
+ ?line 6 = tup_lit_alias_rev({1,2,3}),
+
+ ?line {42,42,42,42} = multiple_aliases_1(42),
+ ?line {7,7,7} = multiple_aliases_2(7),
+ ?line {{a,b},{a,b},{a,b}} = multiple_aliases_3({a,b}),
+ ok.
+
+str_alias(V) ->
+ Res = str_alias_1(V),
+ Res = str_alias_2(V).
+
+str_alias_1([$a,$b,$c]="abc"="a"++[$b,$c]=[97,98,99]) -> ok;
+str_alias_1([$d|"ef"]="def") -> ok;
+str_alias_1([$g|"hi"]="g"++"hi"="gh"++"i"="ghi"++"") -> ok;
+str_alias_1("k"++"lm"=[$k|"lm"]) -> ok;
+str_alias_1([113,114,115]="qrs"=[$q,$r,$s]="q"++"r"++"s") -> ok;
+str_alias_1([$x,$y]="xy") -> ok;
+str_alias_1(""=[]) -> ok;
+str_alias_1(_) -> error.
+
+%% Make sure that different line numbers do not matter.
+
+str_alias_2([$a,$b,$c]=
+ "abc"=
+ "a"++[$b,$c
+ ]=
+ [97,98,99
+ ]) -> ok;
+str_alias_2([$d|"ef"]=
+ "def") -> ok;
+str_alias_2([$g|"hi"]=
+ "g"++"hi"=
+ "gh"++"i"=
+ "ghi"++"") -> ok;
+str_alias_2("k"++"lm"=
+ [$k|"lm"
+ ]) -> ok;
+str_alias_2([113,114,115]=
+ "qrs"=[$q,$r,$s
+ ]=
+ "q"++"r"++"s") -> ok;
+str_alias_2([$x,$y]=
+ "xy") -> ok;
+str_alias_2(""=
+ []) -> ok;
+str_alias_2(_) -> error.
+
+char_alias(V) ->
+ Res = char_alias_1(V),
+ Res = char_alias_2(V).
+
+char_alias_1(118=$v) -> ok;
+char_alias_1($w=119) -> ok;
+char_alias_1(42=42) -> ok;
+char_alias_1(3.0=3.0) -> ok;
+char_alias_1(_) -> error.
+
+char_alias_2(118=
+ $v) -> ok;
+char_alias_2($w=
+ 119) -> ok;
+char_alias_2(42=
+ 42) -> ok;
+char_alias_2(3.0=
+ 3.0) -> ok;
+char_alias_2(_) -> error.
+
+three(V) ->
+ Res = three_1(V),
+ Res = three_2(V).
+
+three_1(A=B=C) ->
+ {A,B,C}.
+
+three_2(A=
+ B=
+ C) ->
+ {A,B,C}.
+
+tuple_alias({A,B,C}={X,Y,Z}) ->
+ {A,B,C,X,Y,Z};
+tuple_alias({A,B}={C,D}={E,F}) ->
+ {A,B,C,D,E,F}.
+
+tup_lit_alias({A,B,C}={1,2,3}) ->
+ A+B+C.
+
+tup_lit_alias_rev({1,2,3}={A,B,C}) ->
+ A+B+C.
+
+multiple_aliases_1((A=B)=(C=D)) ->
+ {A,B,C,D}.
+
+multiple_aliases_2((A=B)=(A=C)) ->
+ {A,B,C}.
+
+multiple_aliases_3((A={_,_}=B)={_,_}=C) ->
+ {A,B,C}.
+
+%% OTP-7018.
+
+match_in_call(Config) when is_list(Config) ->
+ ?line mac_a(0),
+ ?line mac_b(1),
+ ?line mac_c(42),
+ ?line mac_d(42),
+ ?line mac_e({gurka,42}),
+
+ ?line [{2,2},{2,2}] = mac_lc([{2,any},{2,2}]),
+ ?line {'EXIT',_} = (catch mac_lc([{1,1}])),
+
+ ok.
+
+mac_a(X) ->
+ id(_Gurka = {gurka,X}),
+ ok.
+
+mac_b(X) ->
+ id(Gurka = {gurka,X}),
+ gurka(Gurka, X),
+ ok.
+
+mac_c(X) ->
+ id(Gurka = Yxa = {gurka,X}),
+ id({Gurka,Yxa}),
+ ok.
+
+mac_d(X) ->
+ id({gurka,42} = {gurka,X}),
+ ok.
+
+mac_e(X) ->
+ id({gurka,42} = X),
+ ok.
+
+mac_lc(E) ->
+ Res = mac_lc1(E),
+ Res = mac_lc2(E).
+
+mac_lc1(E) ->
+ [{X,Y} ||
+ {X,_} <- E,
+ (Y = X) =:= (Y = 1 + 1)].
+
+mac_lc2(E) ->
+ [{X,Y} ||
+ {X,_} <- E,
+ (Y = X) =:= (Y = 2)].
+
+gurka({gurka,X}, X) -> ok.
+
+
+untuplify(Config) when is_list(Config) ->
+ %% We do this to cover sys_core_fold:unalias_pat/1.
+ ?line {1,2,3,4,alias,{[1,2],{3,4},alias}} = untuplify_1([1,2], {3,4}, alias),
+ ?line error = untuplify_1([1,2], {3,4}, 42),
+ ok.
+
+untuplify_1(A, B, C) ->
+ case {A,B,C} of
+ {[X,Y],{Z,W},alias=Alias}=Top ->
+ {X,Y,Z,W,Alias,Top};
+ [_,_]=CantMatch ->
+ CantMatch;
+ _ ->
+ error
+ end.
+
+%% Coverage of beam_dead:shortcut_boolean_label/4.
+shortcut_boolean(Config) when is_list(Config) ->
+ ?line false = shortcut_boolean_1([0]),
+ ?line true = shortcut_boolean_1({42}),
+ ?line maybe = shortcut_boolean_1(self()),
+ ?line {'EXIT',_} = (catch shortcut_boolean_1([a,b])),
+ ?line {'EXIT',_} = (catch shortcut_boolean_1({a,b})),
+ ok.
+
+shortcut_boolean_1(X) ->
+ Outer = case not is_pid(X) of
+ true ->
+ V = case X of
+ [_] -> true;
+ {_} -> false
+ end,
+ not V;
+ false ->
+ maybe
+ end,
+ id(Outer).
+
+
+%% Test sys_core_fold:letify_guard/3.
+letify_guard(Config) when is_list(Config) ->
+ ?line {-15,a} = letify_guard(-15, a),
+ ?line 5 = letify_guard(2, 3),
+ ok.
+
+letify_guard(A, B) ->
+ case {A,B} of
+ %% The tuple will be built in the guard...
+ Z when tuple_size(Z) =:= 2, element(1, Z) < 0 ->
+ %% ... and again here.
+ Z;
+ {X,Y} -> X+Y
+ end.
+
+%% Test combining of is_eq_exact instructions to select_val
+%% instructions in beam_dead and beam_peep.
+
+selectify(Config) when is_list(Config) ->
+ ?line integer = sel_different_types({r,42}),
+ ?line atom = sel_different_types({r,forty_two}),
+ ?line none = sel_different_types({r,18}),
+ ?line {'EXIT',_} = (catch sel_different_types([a,b,c])),
+
+ ?line integer = sel_same_value({r,42}),
+ ?line error = sel_same_value({r,100}),
+ ?line error = sel_same_value(a),
+
+ ?line integer42 = sel_same_value2(42),
+ ?line integer43 = sel_same_value2(43),
+ ?line error = sel_same_value2(44),
+ ok.
+
+sel_different_types({r,_}=T) when element(2, T) =:= forty_two ->
+ atom;
+sel_different_types({r,_}=T) when element(2, T) =:= 42 ->
+ integer;
+sel_different_types({r,_}) ->
+ none.
+
+sel_same_value({r,V}) when V =:= 42 ->
+ integer;
+sel_same_value({r,V}) when V =:= 42 ->
+ integer42;
+sel_same_value(_) ->
+ error.
+
+sel_same_value2(V) when V =:= 42 ->
+ integer42;
+sel_same_value2(V) when V =:= 42; V =:= 43 ->
+ integer43;
+sel_same_value2(_) ->
+ error.
+
+id(I) -> I.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
new file mode 100644
index 0000000000..e096571d50
--- /dev/null
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -0,0 +1,241 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(misc_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ tobias/1,empty_string/1,md5/1,silly_coverage/1,
+ confused_literals/1,integer_encoding/1]).
+
+-include("test_server.hrl").
+
+init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = test_server:timetrap(?t:minutes(10)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [tobias,empty_string,md5,silly_coverage,confused_literals,
+ integer_encoding].
+
+%% A bug reported by Tobias Lindahl for a development version of R11B.
+
+tobias(Config) when is_list(Config) ->
+ ?line 1 = tobias_1([1,2,3]),
+ ok.
+
+tobias_1([H|_T]) ->
+ %% In an R11B compiler, the move optimizer in beam_block would
+ %% confuse H and _T.
+ tobias_2(0, 0),
+ H.
+
+tobias_2(_, _) ->
+ 2.
+
+
+%% A bug reported by Richard Carlsson. Used to crash beam_asm
+%% because of a put_string instruction with an empty string.
+%% The real problem was in sys_core_fold (empty strings should
+%% be replaced by []).
+
+-record(r, {s = ""}).
+
+empty_string(Config) when is_list(Config) ->
+ ?line #r{s="x"} = empty_string_1(#r{}),
+ ok.
+
+empty_string_1(T) ->
+ case T of
+ #r{s = ""} -> T #r{s = "x"}
+ end.
+
+md5(Config) when is_list(Config) ->
+ case ?MODULE of
+ misc_SUITE -> md5();
+ _ -> {skip,"Enough to run this case once."}
+ end.
+
+md5() ->
+ ?line Dir = filename:dirname(code:which(?MODULE)),
+ ?line Beams = filelib:wildcard(filename:join(Dir, "*.beam")),
+ ?line io:format("Found ~w beam files", [length(Beams)]),
+ ?line lists:foreach(fun md5_1/1, Beams).
+
+md5_1(Beam) ->
+ ?line {ok,{Mod,[Vsn]}} = beam_lib:version(Beam),
+ ?line {ok,Code} = file:read_file(Beam),
+ ?line {Mod,<<Vsn:128>>} = {Mod,code:module_md5(Code)}.
+
+%% Cover some code that handles internal errors.
+
+silly_coverage(Config) when is_list(Config) ->
+ %% sys_core_fold, sys_core_setel, v3_kernel
+ BadCoreErlang = {c_module,[],
+ name,exports,attrs,
+ [{{c_var,[],{foo,2}},seriously_bad_body}]},
+ ?line expect_error(fun() -> sys_core_fold:module(BadCoreErlang, []) end),
+ ?line expect_error(fun() -> sys_core_dsetel:module(BadCoreErlang, []) end),
+ ?line expect_error(fun() -> v3_kernel:module(BadCoreErlang, []) end),
+
+ %% v3_codgen
+ CodegenInput = {?MODULE,[{foo,0}],[],[{function,foo,0,[a|b],a,b}]},
+ ?line expect_error(fun() -> v3_codegen:module(CodegenInput, []) end),
+
+ %% beam_block
+ BlockInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2}|non_proper_list],99}]},
+ ?line expect_error(fun() -> beam_block:module(BlockInput, []) end),
+
+ %% beam_bool
+ BoolInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2}|non_proper_list]}],99},
+ ?line expect_error(fun() -> beam_bool:module(BoolInput, []) end),
+
+ %% beam_dead
+ DeadInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2},
+ {jump,bad}]}],99},
+ ?line expect_error(fun() -> beam_block:module(DeadInput, []) end),
+
+ %% beam_clean
+ CleanInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2},
+ {jump,{f,42}}]}],99},
+ ?line expect_error(fun() -> beam_clean:module(CleanInput, []) end),
+
+ %% beam_peep
+ PeepInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2}|non_proper_list]}],99},
+ ?line expect_error(fun() -> beam_peep:module(PeepInput, []) end),
+
+ %% beam_bsm. This is tricky. Our function must be sane enough to not crash
+ %% btb_index/1, but must crash the main optimization pass.
+ BsmInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2},
+ {test,bs_get_binary2,{f,99},0,[{x,0},{atom,all},1,[]],{x,0}},
+ {block,[a|b]}]}],0},
+ ?line expect_error(fun() -> beam_bsm:module(BsmInput, []) end),
+ ok.
+
+expect_error(Fun) ->
+ try Fun() of
+ Any ->
+ io:format("~p", [Any]),
+ ?t:fail(call_was_supposed_to_fail)
+ catch
+ _:_ ->
+ io:format("~p\n", [erlang:get_stacktrace()])
+ end.
+
+confused_literals(Config) when is_list(Config) ->
+ ?line {0,infinity} = confused_literals_1(int),
+ ?line {0.0,infinity} = confused_literals_1(float),
+ ok.
+
+confused_literals_1(int) -> {0,infinity};
+confused_literals_1(float) -> {0.0,infinity}.
+
+integer_encoding(Config) when is_list(Config) ->
+ case ?MODULE of
+ misc_SUITE -> integer_encoding_1(Config);
+ _ -> {skip,"Enough to run this case once."}
+ end.
+
+integer_encoding_1(Config) ->
+ Dog = test_server:timetrap(?t:minutes(4)),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line SrcFile = filename:join(PrivDir, "misc_SUITE_integer_encoding.erl"),
+ ?line DataFile = filename:join(PrivDir, "integer_encoding.data"),
+ Mod = misc_SUITE_integer_encoding,
+
+ %% Create files.
+ ?line {ok,Src} = file:open(SrcFile, [write]),
+ ?line {ok,Data} = file:open(DataFile, [write]),
+ io:format(Src, "-module(~s).\n", [Mod]),
+ io:put_chars(Src, "-export([t/1]).\n"),
+ io:put_chars(Src, "t(Last) ->[\n"),
+ io:put_chars(Data, "[\n"),
+
+ ?line do_integer_encoding(-(id(1) bsl 10000), Src, Data),
+ ?line do_integer_encoding(id(1) bsl 10000, Src, Data),
+ ?line do_integer_encoding(2048, 0, Src, Data),
+
+ io:put_chars(Src, "Last].\n\n"),
+ ?line ok = file:close(Src),
+ io:put_chars(Data, "0].\n\n"),
+ ?line ok = file:close(Data),
+
+ %% Compile and load Erlang module.
+ ?line SrcRoot = filename:rootname(SrcFile),
+ ?line {ok,Mod,Binary} = compile:file(SrcRoot, [binary,report]),
+ ?line {module,Mod} = code:load_binary(Mod, SrcRoot, Binary),
+
+ %% Compare lists.
+ ?line List = Mod:t(0),
+ ?line {ok,[List]} = file:consult(DataFile),
+ OneBsl10000 = id(1) bsl 10000,
+ ?line [-(1 bsl 10000),OneBsl10000|_] = List,
+
+ %% Cleanup.
+ ?line file:delete(SrcFile),
+ ?line file:delete(DataFile),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+do_integer_encoding(0, _, _, _) -> ok;
+do_integer_encoding(N, I0, Src, Data) ->
+ I1 = (I0 bsl 5) bor (random:uniform(32) - 1),
+ do_integer_encoding(I1, Src, Data),
+ I2 = -(I1 bxor (random:uniform(32) - 1)),
+ do_integer_encoding(I2, Src, Data),
+ do_integer_encoding(N-1, I1, Src, Data).
+
+do_integer_encoding(I, Src, Data) ->
+ Str = integer_to_list(I),
+ io:put_chars(Src, Str),
+ io:put_chars(Src, ", \n"),
+ io:put_chars(Data, Str),
+ io:put_chars(Data, ", \n").
+
+
+id(I) -> I.
+
diff --git a/lib/compiler/test/nested_call_in_case.core b/lib/compiler/test/nested_call_in_case.core
new file mode 100644
index 0000000000..5c6b6909bd
--- /dev/null
+++ b/lib/compiler/test/nested_call_in_case.core
@@ -0,0 +1,21 @@
+module 'nested_call_in_case' ['a'/2]
+ attributes []
+
+'a'/2 =
+ fun (_x,_y) ->
+ case call 'erlang':'>'
+ (call 'erlang':'length'
+ (_x), _y) of
+ <'true'> when 'true' ->
+ 'yes'
+ <'false'> when 'true' ->
+ 'no'
+ ( <_omega> when 'true' ->
+ primop 'match_fail'
+ ('if_clause')
+ -| ['compiler_generated'] )
+ end
+end
+
+
+
diff --git a/lib/compiler/test/num_bif_SUITE.erl b/lib/compiler/test/num_bif_SUITE.erl
new file mode 100644
index 0000000000..c246f56611
--- /dev/null
+++ b/lib/compiler/test/num_bif_SUITE.erl
@@ -0,0 +1,265 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(num_bif_SUITE).
+
+-include("test_server.hrl").
+
+%% Tests optimization of the BIFs:
+%% abs/1
+%% float/1
+%% float_to_list/1
+%% integer_to_list/1
+%% list_to_float/1
+%% list_to_integer/1
+%% round/1
+%% trunc/1
+
+-export([all/1, t_abs/1, t_float/1,
+ t_float_to_list/1, t_integer_to_list/1,
+ t_list_to_integer/1,
+ t_list_to_float/1, t_list_to_float_safe/1, t_list_to_float_risky/1,
+ t_round/1, t_trunc/1]).
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [t_abs, t_float, t_float_to_list, t_integer_to_list,
+ t_list_to_float, t_list_to_integer,
+ t_round, t_trunc].
+
+t_abs(Config) when is_list(Config) ->
+ %% Floats.
+ ?line 5.5 = abs(5.5),
+ ?line 0.0 = abs(0.0),
+ ?line 100.0 = abs(-100.0),
+
+ %% Integers.
+ ?line 5 = abs(5),
+ ?line 0 = abs(0),
+ ?line 100 = abs(-100),
+
+ %% The largest smallnum. OTP-3190.
+ ?line X = (1 bsl 27) - 1,
+ ?line X = abs(X),
+ ?line X = abs(X-1)+1,
+ ?line X = abs(X+1)-1,
+ ?line X = abs(-X),
+ ?line X = abs(-X-1)-1,
+ ?line X = abs(-X+1)+1,
+
+ %% Bignums.
+ BigNum = 13984792374983749,
+ ?line BigNum = abs(BigNum),
+ ?line BigNum = abs(-BigNum),
+ ok.
+
+t_float(Config) when is_list(Config) ->
+ ?line 0.0 = float(0),
+ ?line 2.5 = float(2.5),
+ ?line 0.0 = float(0.0),
+ ?line -100.55 = float(-100.55),
+ ?line 42.0 = float(42),
+ ?line -100.0 = float(-100),
+
+ %% Bignums.
+ ?line 4294967305.0 = float(4294967305),
+ ?line -4294967305.0 = float(-4294967305),
+
+ %% Extremly big bignums.
+ ?line Big = list_to_integer(lists:duplicate(2000, $1)),
+ ?line {'EXIT', {badarg, _}} = (catch float(Big)),
+
+ %% Invalid types and lists.
+ ?line {'EXIT', {badarg, _}} = (catch list_to_integer(atom)),
+ ?line {'EXIT', {badarg, _}} = (catch list_to_integer(123)),
+ ?line {'EXIT', {badarg, _}} = (catch list_to_integer([$1, [$2]])),
+ ?line {'EXIT', {badarg, _}} = (catch list_to_integer("1.2")),
+ ?line {'EXIT', {badarg, _}} = (catch list_to_integer("a")),
+ ?line {'EXIT', {badarg, _}} = (catch list_to_integer("")),
+ ok.
+
+
+%% Tests float_to_list/1.
+
+t_float_to_list(Config) when is_list(Config) ->
+ ?line test_ftl("0.0e+0", 0.0),
+ ?line test_ftl("2.5e+1", 25.0),
+ ?line test_ftl("2.5e+0", 2.5),
+ ?line test_ftl("2.5e-1", 0.25),
+ ?line test_ftl("-3.5e+17", -350.0e15),
+ ok.
+
+test_ftl(Expect, Float) ->
+ %% No ?line on the next line -- we want the line number from t_float_to_list.
+ Expect = remove_zeros(lists:reverse(float_to_list(Float)), []).
+
+%% Removes any non-significant zeros in a floating point number.
+%% Example: 2.500000e+01 -> 2.5e+1
+
+remove_zeros([$+, $e|Rest], [$0, X|Result]) ->
+ remove_zeros([$+, $e|Rest], [X|Result]);
+remove_zeros([$-, $e|Rest], [$0, X|Result]) ->
+ remove_zeros([$-, $e|Rest], [X|Result]);
+remove_zeros([$0, $.|Rest], [$e|Result]) ->
+ remove_zeros(Rest, [$., $0, $e|Result]);
+remove_zeros([$0|Rest], [$e|Result]) ->
+ remove_zeros(Rest, [$e|Result]);
+remove_zeros([Char|Rest], Result) ->
+ remove_zeros(Rest, [Char|Result]);
+remove_zeros([], Result) ->
+ Result.
+
+%% Tests integer_to_list/1.
+
+t_integer_to_list(Config) when is_list(Config) ->
+ ?line "0" = integer_to_list(0),
+ ?line "42" = integer_to_list(42),
+ ?line "-42" = integer_to_list(-42),
+ ?line "-42" = integer_to_list(-42),
+ ?line "32768" = integer_to_list(32768),
+ ?line "268435455" = integer_to_list(268435455),
+ ?line "-268435455" = integer_to_list(-268435455),
+ ?line "123456932798748738738" = integer_to_list(123456932798748738738),
+ ?line Big_List = lists:duplicate(2000, $1),
+ ?line Big = list_to_integer(Big_List),
+ ?line Big_List = integer_to_list(Big),
+ ok.
+
+%% Tests list_to_float/1.
+
+t_list_to_float(suite) -> [t_list_to_float_safe, t_list_to_float_risky].
+
+t_list_to_float_safe(Config) when is_list(Config) ->
+ ?line 0.0 = list_to_float("0.0"),
+ ?line 0.0 = list_to_float("-0.0"),
+ ?line 0.5 = list_to_float("0.5"),
+ ?line -0.5 = list_to_float("-0.5"),
+ ?line 100.0 = list_to_float("1.0e2"),
+ ?line 127.5 = list_to_float("127.5"),
+ ?line -199.5 = list_to_float("-199.5"),
+
+ ?line {'EXIT', {badarg, _}} = (catch list_to_float("0")),
+ ?line {'EXIT', {badarg, _}} = (catch list_to_float("0..0")),
+ ?line {'EXIT', {badarg, _}} = (catch list_to_float("0e12")),
+ ?line {'EXIT', {badarg, _}} = (catch list_to_float("--0.0")),
+%% ?line {'EXIT', {badarg, _}} = (catch list_to_float("0.0e+99999999")),
+
+ ok.
+
+%% This might crash the emulator...
+%% (Known to crash the Unix version of Erlang 4.4.1)
+
+t_list_to_float_risky(Config) when is_list(Config) ->
+ ?line Many_Ones = lists:duplicate(25000, $1),
+ ?line list_to_float("2."++Many_Ones),
+ ?line {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)),
+ ok.
+
+%% Tests list_to_integer/1.
+
+t_list_to_integer(Config) when is_list(Config) ->
+ ?line 0 = list_to_integer("0"),
+ ?line 0 = list_to_integer("00"),
+ ?line 0 = list_to_integer("-0"),
+ ?line 1 = list_to_integer("1"),
+ ?line -1 = list_to_integer("-1"),
+ ?line 42 = list_to_integer("42"),
+ ?line -12 = list_to_integer("-12"),
+ ?line 32768 = list_to_integer("32768"),
+ ?line 268435455 = list_to_integer("268435455"),
+ ?line -268435455 = list_to_integer("-268435455"),
+
+ %% Bignums.
+ ?line 123456932798748738738 = list_to_integer("123456932798748738738"),
+ ?line list_to_integer(lists:duplicate(2000, $1)),
+ ok.
+
+%% Tests round/1.
+
+t_round(Config) when is_list(Config) ->
+ ?line 0 = round(0.0),
+ ?line 0 = round(0.4),
+ ?line 1 = round(0.5),
+ ?line 0 = round(-0.4),
+ ?line -1 = round(-0.5),
+ ?line 255 = round(255.3),
+ ?line 256 = round(255.6),
+ ?line -1033 = round(-1033.3),
+ ?line -1034 = round(-1033.6),
+
+ % OTP-3722:
+ ?line X = (1 bsl 27) - 1,
+ ?line MX = -X,
+ ?line MXm1 = -X-1,
+ ?line MXp1 = -X+1,
+ ?line F = X + 0.0,
+ ?line X = round(F),
+ ?line X = round(F+1)-1,
+ ?line X = round(F-1)+1,
+ ?line MX = round(-F),
+ ?line MXm1 = round(-F-1),
+ ?line MXp1 = round(-F+1),
+
+ ?line X = round(F+0.1),
+ ?line X = round(F+1+0.1)-1,
+ ?line X = round(F-1+0.1)+1,
+ ?line MX = round(-F+0.1),
+ ?line MXm1 = round(-F-1+0.1),
+ ?line MXp1 = round(-F+1+0.1),
+
+ ?line X = round(F-0.1),
+ ?line X = round(F+1-0.1)-1,
+ ?line X = round(F-1-0.1)+1,
+ ?line MX = round(-F-0.1),
+ ?line MXm1 = round(-F-1-0.1),
+ ?line MXp1 = round(-F+1-0.1),
+
+ ?line 0.5 = abs(round(F+0.5)-(F+0.5)),
+ ?line 0.5 = abs(round(F-0.5)-(F-0.5)),
+ ?line 0.5 = abs(round(-F-0.5)-(-F-0.5)),
+ ?line 0.5 = abs(round(-F+0.5)-(-F+0.5)),
+
+ %% Bignums.
+ ?line 4294967296 = round(4294967296.1),
+ ?line 4294967297 = round(4294967296.9),
+ ?line -4294967296 = -round(4294967296.1),
+ ?line -4294967297 = -round(4294967296.9),
+ ok.
+
+t_trunc(Config) when is_list(Config) ->
+ ?line 0 = trunc(0.0),
+ ?line 5 = trunc(5.3333),
+ ?line -10 = trunc(-10.978987),
+ % The largest smallnum, converted to float (OTP-3722):
+ ?line X = (1 bsl 27) - 1,
+ ?line F = X + 0.0,
+ io:format("X = ~p/~w/~w, F = ~p/~w/~w, trunc(F) = ~p/~w/~w~n",
+ [X, X, binary_to_list(term_to_binary(X)),
+ F, F, binary_to_list(term_to_binary(F)),
+ trunc(F), trunc(F), binary_to_list(term_to_binary(trunc(F)))]),
+ ?line X = trunc(F),
+ ?line X = trunc(F+1)-1,
+ ?line X = trunc(F-1)+1,
+ ?line X = -trunc(-F),
+ ?line X = -trunc(-F-1)-1,
+ ?line X = -trunc(-F+1)+1,
+
+ %% Bignums.
+ ?line 4294967305 = trunc(4294967305.7),
+ ?line -4294967305 = trunc(-4294967305.7),
+ ok.
diff --git a/lib/compiler/test/parteval_SUITE.erl b/lib/compiler/test/parteval_SUITE.erl
new file mode 100644
index 0000000000..3ef84571b9
--- /dev/null
+++ b/lib/compiler/test/parteval_SUITE.erl
@@ -0,0 +1,46 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(parteval_SUITE).
+
+-include("test_server.hrl").
+
+-export([all/1, pe2/1]).
+
+all(suite) -> [pe2].
+
+%% (This is more general than needed, since we once compiled the same
+%% source code with and without a certain option.)
+compile_and_load(Srcname, Outdir, Module, Options) ->
+ ?line Objname = filename:join(Outdir, "t1") ++ code:objfile_extension(),
+ ?line {ok, Module} =
+ compile:file(Srcname,
+ [{d, 'M', Module}, {outdir, Outdir}] ++ Options),
+ ?line {ok, B} = file:read_file(Objname),
+ ?line {module, Module} = code:load_binary(Module, Objname, B),
+ B.
+
+pe2(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Srcname = filename:join(DataDir, "t1.erl"),
+ ?line compile_and_load(Srcname, PrivDir, t1, []),
+
+ ?line {Correct, Actual} = t1:run(),
+ ?line Correct = Actual,
+ ok.
diff --git a/lib/compiler/test/parteval_SUITE_data/t1.erl b/lib/compiler/test/parteval_SUITE_data/t1.erl
new file mode 100644
index 0000000000..5e4a40f103
--- /dev/null
+++ b/lib/compiler/test/parteval_SUITE_data/t1.erl
@@ -0,0 +1,140 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(?M).
+
+-compile(export_all).
+
+%%% The arity-0 functions are all called from the test suite.
+
+f2() ->
+ size({1,2}).
+
+i() ->
+ case [] of
+ [] ->
+ ok;
+ X ->
+ hopp
+ end.
+
+e() ->
+ case 4+5 of
+% X when X>10 -> kvock; % not removed by BEAM opt.
+ {X,X} when list(X) ->
+ kvack;
+ 9 ->
+ ok;
+ _ ->
+ ko
+ end.
+
+f() ->
+ element(2,{a,b,c,d}),
+ erlang:element(2,{a,b,c,d}),
+ "hej" ++ "hopp".
+
+g(X) ->
+ if
+ float(3.4) ->
+ hej;
+ X == 5, 4==4 ->
+ japp;
+ 4 == 4, size({1,2}) == 1 ->
+ ok
+ end.
+
+g() ->
+ {g(3),g(5)}.
+
+bliff() ->
+ if
+ 3==4 ->
+ himm
+ end.
+
+fi() ->
+ case 4 of
+ X when 4==3 ->
+ {X};
+ 4 ->
+ 4;
+ _ ->
+ ok
+ end.
+
+iff() when 3==2 ->
+ if
+ 3 == 4 ->
+ baff;
+ 3 == 3 ->
+ nipp
+ end.
+
+sleep(I) -> receive after I -> ok end.
+
+sleep() ->
+ sleep(45).
+
+s() ->
+ case 4 of
+ 3 ->
+ ok
+ end.
+
+error_reason(R) when atom(R) ->
+ R;
+error_reason(R) when tuple(R) ->
+ error_reason(element(1, R)).
+
+plusplus() ->
+ ?MODULE ++ " -> mindre snygg felhantering".
+
+call_it(F) ->
+ case (catch apply(?MODULE, F, [])) of
+ {'EXIT', R0} ->
+ {'EXIT', error_reason(R0)};
+ V ->
+ V
+ end.
+
+run() ->
+ L = [{f2, 2},
+ {i, ok},
+ {e, ok},
+ {f, "hejhopp"},
+ {g, {hej, hej}},
+ {bliff, {'EXIT', if_clause}},
+ {fi, 4},
+ {iff, {'EXIT', function_clause}},
+ {sleep, ok},
+ {s, {'EXIT', case_clause},
+ {plusplus, {'EXIT', badarg}}}],
+ Actual = [call_it(F) || {F, _} <- L],
+ Correct = [C || {_, C} <- L],
+ {Correct, Actual}.
+
+
+%%% Don't call, only compile.
+t(A) ->
+ receive
+ A when 1==2 ->
+ ok;
+ B ->
+ B
+ end.
diff --git a/lib/compiler/test/pmod_SUITE.erl b/lib/compiler/test/pmod_SUITE.erl
new file mode 100644
index 0000000000..c8919e5539
--- /dev/null
+++ b/lib/compiler/test/pmod_SUITE.erl
@@ -0,0 +1,90 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(pmod_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ basic/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [basic].
+
+init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+basic(Config) when is_list(Config) ->
+ ?line basic_1(Config, []),
+ ?line basic_1(Config, [inline]),
+ ?line basic_1(Config, [{inline,500}]),
+ ok.
+
+basic_1(Config, Opts) ->
+ io:format("Options: ~p\n", [Opts]),
+ ?line ok = compile_load(pmod_basic, Config, Opts),
+
+ ?line Prop1 = pmod_basic:new([{a,xb},{b,true},{c,false}]),
+ ?line Prop2 = pmod_basic:new([{y,zz}]),
+ ?line io:format("Prop1 = ~p\n", [Prop1]),
+ ?line io:format("Prop2 = ~p\n", [Prop2]),
+
+ ?line {a,xb} = Prop1:lookup(a),
+ ?line none = Prop1:lookup(glurf),
+ ?line false = Prop1:or_props([]),
+ ?line true = Prop1:or_props([b,c]),
+ ?line true = Prop1:or_props([b,d]),
+ ?line false = Prop1:or_props([d]),
+
+ ?line none = Prop2:lookup(kalle),
+ ?line {y,zz} = Prop2:lookup(y),
+ ?line {a,xb} = Prop1:lookup(a),
+
+ ?line Prop3 = Prop1:prepend({blurf,true}),
+ ?line io:format("Prop3 = ~p\n", [Prop3]),
+ ?line {blurf,true} = Prop3:lookup(blurf),
+
+ Prop4 = Prop3:append(42),
+ ?line io:format("Prop4 = ~p\n", [Prop4]),
+ ?line {42,5} = Prop4:stupid_sum(),
+
+ %% Some record guards.
+ ?line ok = Prop4:bar({s,0}),
+ ?line ok = Prop4:bar_bar({s,blurf}),
+ ?line error = Prop4:bar_bar({s,a,b}),
+ ?line error = Prop4:bar_bar([]),
+
+ ok.
+
+compile_load(Module, Conf, Opts) ->
+ ?line Dir = ?config(data_dir,Conf),
+ ?line Src = filename:join(Dir, atom_to_list(Module)),
+ ?line Out = ?config(priv_dir,Conf),
+ ?line CompRc = compile:file(Src, [report,{outdir,Out}|Opts]),
+ ?line {ok,Module} = CompRc,
+ ?line code:purge(Module),
+ ?line {module,Module} =
+ code:load_abs(filename:join(Out, atom_to_list(Module))),
+ ok.
diff --git a/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl b/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl
new file mode 100644
index 0000000000..e6f4c63421
--- /dev/null
+++ b/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl
@@ -0,0 +1,72 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(pmod_basic, [Props]).
+
+-export([lookup/1,or_props/1,prepend/1,append/1,stupid_sum/0]).
+-export([bar/1,bar_bar/1]).
+
+lookup(Key) ->
+ proplists:lookup(Key, Props).
+
+or_props(Keys) ->
+ Res = or_props_1(Keys, false),
+ true = is_bool(Res), %is_bool/1 does not use Props.
+ Res.
+
+prepend(Term) ->
+ new([Term|Props]).
+
+append(Term) ->
+ pmod_basic:new(Props++[Term]).
+
+or_props_1([K|Ks], Acc) ->
+ or_props_1(Ks, proplists:get_bool(K, Props) or Acc);
+or_props_1([], Acc) -> Acc.
+
+is_bool(true) -> true;
+is_bool(false) -> true;
+is_bool(_) -> false.
+
+stupid_sum() ->
+ put(counter, 0),
+ Res = stupid_sum_1(Props, 0),
+ {Res,get(counter)}.
+
+stupid_sum_1([H|T], Sum0) ->
+ try add(Sum0, H) of
+ Sum -> stupid_sum_1(T, Sum)
+ catch
+ error:_ -> stupid_sum_1(T, Sum0)
+ after
+ bump()
+ end;
+stupid_sum_1([], Sum) -> Sum.
+
+bump() ->
+ put(counter, get(counter)+1).
+
+add(A, B) ->
+ A+B.
+
+-record(s, {a}).
+
+bar(S) when S#s.a == 0 -> ok.
+
+bar_bar(S) when is_record(S, s) -> ok;
+bar_bar(_) -> error.
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
new file mode 100644
index 0000000000..cb8833759a
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -0,0 +1,161 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%% Purpose : Compiles various modules with tough code
+
+-module(receive_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ recv/1,coverage/1,otp_7980/1]).
+
+-include("test_server.hrl").
+
+init_per_testcase(_Case, Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(2)),
+ [{watchdog, Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [recv,coverage,otp_7980].
+
+-record(state, {ena = true}).
+
+recv(Config) when is_list(Config) ->
+ ?line Pid = spawn_link(fun() -> loop(#state{}) end),
+ Self = self(),
+ ?line Pid ! {Self,test},
+ receive
+ {ok,test} -> ok;
+ {error,Other} ->
+ io:format("Got unpexected ~p", [Other]),
+ ?line ?t:fail()
+ after 10000 ->
+ ?line ?t:fail(no_answer)
+ end,
+ receive
+ X ->
+ io:format("Unexpected extra message: ~p", [X]),
+ ?line ?t:fail()
+ after 10 ->
+ ok
+ end,
+ ok.
+
+loop(S) ->
+ receive
+ _ when S#state.ena == false ->
+ loop(S);
+ {P,test} ->
+ P ! {ok,test},
+ loop(S);
+ _X ->
+ loop(S)
+ end.
+
+coverage(Config) when is_list(Config) ->
+ do_link(self()),
+ do_unlink(self()),
+ do_monitor_node(node(), true),
+ do_monitor_node(node(), false),
+ do_group_leader(group_leader(), self()),
+ id(node(self())),
+
+ erlang:'!'(self(), {a,10}),
+ self() ! {b,20},
+ [{a,10},{b,20}] = receive_all(),
+ self() ! {c,42},
+ receive
+ {c,42} ->
+ ok
+ after infinity ->
+ exit(cant_happen)
+ end,
+
+ self() ! 17,
+ self() ! 19,
+ ?line 59 = tuple_to_values(infinity, x),
+ ?line 61 = tuple_to_values(999999, x),
+ ?line 0 = tuple_to_values(1, x),
+ ok.
+
+receive_all() ->
+ receive
+ Any ->
+ [Any|receive_all()]
+ after 0 ->
+ []
+ end.
+
+do_monitor_node(Node, Bool) ->
+ monitor_node(Node, Bool).
+
+do_link(Pid) ->
+ link(Pid).
+
+do_unlink(Pid) ->
+ unlink(Pid).
+
+do_group_leader(Leader, Pid) ->
+ group_leader(Leader, Pid).
+
+
+%% cover sys_core_fold:tuple_to_values/2
+tuple_to_values(infinity, X) ->
+ {A,B} = case X of
+ x ->
+ receive
+ Any ->
+ {42,Any}
+ end
+ end,
+ A+B;
+tuple_to_values(Timeout, X) ->
+ {A,B} = case X of
+ x ->
+ receive
+ Any ->
+ {42,Any}
+ after Timeout ->
+ {0,0}
+ end
+ end,
+ A+B.
+
+%% OTP-7980. Thanks to Vincent de Phily. The following code would
+%% be inccorrectly optimized by beam_jump.
+
+otp_7980(Config) when is_list(Config) ->
+ 7 = otp_7980_add_clients(10),
+ ok.
+
+otp_7980_add_clients(Count) ->
+ Timeout = 42,
+ lists:foldl(fun(_, N) ->
+ case N of
+ 1 -> ok;
+ _ -> receive after Timeout -> ok end
+ end,
+ N - 1
+ end, Count, [1,2,3]).
+
+id(I) -> I.
diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl
new file mode 100644
index 0000000000..bd2ffd7f65
--- /dev/null
+++ b/lib/compiler/test/record_SUITE.erl
@@ -0,0 +1,525 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%% Purpose : Test records.
+
+-module(record_SUITE).
+
+-include("test_server.hrl").
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ errors/1,record_test_2/1,record_test_3/1,record_access_in_guards/1,
+ guard_opt/1,eval_once/1,foobar/1,missing_test_heap/1]).
+
+init_per_testcase(_Case, Config) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(2)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [errors,record_test_2,record_test_3,record_access_in_guards,
+ guard_opt,eval_once,foobar,missing_test_heap].
+
+-record(foo, {a,b,c,d}).
+-record(bar, {a,b,c,d}).
+-record(barf, {a,b,c,d,e}).
+
+errors(Config) when is_list(Config) ->
+ Foo = #foo{a=1,b=2,c=3,d=4},
+ ?line #foo{a=19,b=42,c=3,d=4} = update_foo(Foo, 19, 42),
+
+ ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19)),
+ ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35)),
+ ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17)),
+ ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)),
+
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19)),
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35)),
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17)),
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)),
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19,
+ 35, 17, 42, -2)),
+
+ ok.
+
+update_foo(#foo{}=R, A, B) ->
+ R#foo{a=A,b=B}.
+
+update_foo_bar(#foo{}=R, A) ->
+ R#bar{a=A}.
+
+update_foo_bar(#foo{}=R, A, _B) ->
+ R#bar{a=A,b=A}.
+
+update_foo_bar(#foo{}=R, A, _B, C) ->
+ R#bar{a=A,b=A,c=C}.
+
+update_foo_bar(#foo{}=R, A, _B, C, D) ->
+ R#bar{a=A,b=A,c=C,d=D}.
+
+update_foo_barf(#foo{}=R, A) ->
+ R#barf{a=A}.
+
+update_foo_barf(#foo{}=R, A, _B) ->
+ R#barf{a=A,b=A}.
+
+update_foo_barf(#foo{}=R, A, _B, C) ->
+ R#barf{a=A,b=A,c=C}.
+
+update_foo_barf(#foo{}=R, A, _B, C, D) ->
+ R#barf{a=A,b=A,c=C,d=D}.
+
+update_foo_barf(#foo{}=R, A, _B, C, D, E) ->
+ R#barf{a=A,b=A,c=C,d=D,e=E}.
+
+
+-define(TrueGuard(Expr), if Expr -> ok; true -> ?t:fail() end).
+-define(FalseGuard(Expr), if Expr -> ?t:fail(); true -> ok end).
+
+record_test_2(Config) when is_list(Config) ->
+ ?line true = is_record(#foo{}, foo),
+ ?line false = is_record(#foo{}, barf),
+ ?line false = is_record({foo}, foo),
+
+ ?line true = erlang:is_record(#foo{}, foo),
+ ?line false = erlang:is_record(#foo{}, barf),
+ ?line false = erlang:is_record({foo}, foo),
+
+ ?line false = is_record([], foo),
+ ?line false = is_record(Config, foo),
+
+ ?line ?TrueGuard(is_record(#foo{}, foo)),
+ ?line ?FalseGuard(is_record(#foo{}, barf)),
+ ?line ?FalseGuard(is_record({foo}, foo)),
+
+ ?line ?TrueGuard(erlang:is_record(#foo{}, foo)),
+ ?line ?FalseGuard(erlang:is_record(#foo{}, barf)),
+ ?line ?FalseGuard(erlang:is_record({foo}, foo)),
+
+ ?line ?FalseGuard(is_record([], foo)),
+ ?line ?FalseGuard(is_record(Config, foo)),
+
+ %% 'not is_record/2' to test guard optimization.
+
+ ?line ?FalseGuard(not is_record(#foo{}, foo)),
+ ?line ?TrueGuard(not is_record(#foo{}, barf)),
+ ?line ?TrueGuard(not is_record({foo}, foo)),
+
+ ?line ?FalseGuard(not erlang:is_record(#foo{}, foo)),
+ ?line ?TrueGuard(not erlang:is_record(#foo{}, barf)),
+ ?line ?TrueGuard(not erlang:is_record({foo}, foo)),
+
+ Foo = id(#foo{}),
+ ?line ?FalseGuard(not erlang:is_record(Foo, foo)),
+ ?line ?TrueGuard(not erlang:is_record(Foo, barf)),
+
+ ?line ?TrueGuard(not is_record(Config, foo)),
+
+ ?line ?TrueGuard(not is_record(a, foo)),
+ ?line ?TrueGuard(not is_record([], foo)),
+
+ %% Pass non-literal first argument.
+
+ ?line true = is_record(id(#foo{}), foo),
+ ?line false = is_record(id(#foo{}), barf),
+ ?line false = is_record(id({foo}), foo),
+
+ ?line true = erlang:is_record(id(#foo{}), foo),
+ ?line false = erlang:is_record(id(#foo{}), barf),
+ ?line false = erlang:is_record(id({foo}), foo),
+
+ NoRec1 = id(blurf),
+ NoRec2 = id([]),
+
+ ?line ?TrueGuard(not is_record(NoRec1, foo)),
+ ?line ?TrueGuard(not is_record(NoRec2, foo)),
+
+ %% The optimizer attempts to move expressions to guards,
+ %% but it must not move an is_record/2 call that is not
+ %% allowed in a guard in the first place.
+
+ ?line ok = case is_record(id({a}), id(a)) of
+ true -> ok;
+ false -> error
+ end,
+
+ %% Force the use of guard bifs by using the 'xor' operation.
+
+ False = id(false),
+ ?line ?TrueGuard(is_record(#foo{}, foo) xor False),
+ ?line ?FalseGuard(is_record(#foo{}, barf) xor False),
+ ?line ?FalseGuard(is_record({foo}, foo) xor False ),
+
+ ?line ?TrueGuard(is_record(Foo, foo) xor False),
+ ?line ?FalseGuard(is_record(Foo, barf) xor False),
+
+
+ %% Implicit guards by using a list comprehension.
+
+ List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]),
+
+ ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo)],
+ ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar)],
+ ?line [1,#foo{a=2},3,5,#foo{a=6},7] =
+ [X || X <- List, not is_record(X, bar)],
+ ?line [1,3,5,7] =
+ [X || X <- List, ((not is_record(X, bar)) and (not is_record(X, foo)))],
+ ?line [#foo{a=2},#bar{d=4},#foo{a=6}] =
+ [X || X <- List, ((is_record(X, bar)) or (is_record(X, foo)))],
+ ?line [1,3,#bar{d=4}] =
+ [X || X <- List, ((is_record(X, bar)) or (X < 5))],
+
+ ?line MyList = [#foo{a=3},x,[],{a,b}],
+ ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo)],
+ ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo)],
+ ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo) end],
+ ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo) end],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo) or
+ not is_binary(X)],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
+ not is_binary(X)],
+ ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)],
+ ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
+ is_reference(X)],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin is_record(X, foo) or
+ not is_binary(X) end],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo) or
+ not is_binary(X) end],
+ ?line [#foo{a=3}] = [X || X <- MyList,
+ begin is_record(X, foo) or is_reference(X) end],
+ ?line [x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo) or
+ is_reference(X) end],
+
+ %% Call is_record/2 with illegal arguments.
+ ?line [] = [X || X <- [], is_record(t, id(X))],
+ ?line {'EXIT',{badarg,_}} = (catch [X || X <- [1], is_record(t, id(X))]),
+
+ %% Update several fields with a string literal.
+ ?line #barf{} = Barf0 = id(#barf{}),
+ ?line Barf = update_barf(Barf0),
+ ?line #barf{a="abc",b=1} = id(Barf),
+
+ ok.
+
+record_test_3(Config) when is_list(Config) ->
+ ?line true = is_record(#foo{}, foo, 5),
+ ?line false = is_record(#foo{}, barf, 5),
+ ?line false = is_record(#foo{}, barf, 6),
+ ?line false = is_record({foo}, foo, 5),
+
+ ?line true = erlang:is_record(#foo{}, foo, 5),
+ ?line false = erlang:is_record(#foo{}, barf, 5),
+ ?line false = erlang:is_record({foo}, foo, 5),
+
+ ?line false = is_record([], foo),
+ ?line false = is_record(Config, foo),
+
+ ?line ?TrueGuard(is_record(#foo{}, foo, 5)),
+ ?line ?FalseGuard(is_record(#foo{}, barf, 5)),
+ ?line ?FalseGuard(is_record(#foo{}, barf, 6)),
+ ?line ?FalseGuard(is_record({foo}, foo, 5)),
+
+ ?line ?TrueGuard(erlang:is_record(#foo{}, foo, 5)),
+ ?line ?FalseGuard(erlang:is_record(#foo{}, barf, 5)),
+ ?line ?FalseGuard(erlang:is_record(#foo{}, barf, 6)),
+ ?line ?FalseGuard(erlang:is_record({foo}, foo, 5)),
+
+ ?line ?FalseGuard(is_record([], foo, 5)),
+ ?line ?FalseGuard(is_record(Config, foo, 5)),
+
+ %% 'not is_record/2' to test guard optimization.
+
+ ?line ?FalseGuard(not is_record(#foo{}, foo, 5)),
+ ?line ?TrueGuard(not is_record(#foo{}, barf, 6)),
+ ?line ?TrueGuard(not is_record({foo}, foo, 5)),
+
+ ?line ?FalseGuard(not erlang:is_record(#foo{}, foo, 5)),
+ ?line ?TrueGuard(not erlang:is_record(#foo{}, barf, 5)),
+ ?line ?TrueGuard(not erlang:is_record({foo}, foo, 5)),
+
+ Foo = id(#foo{}),
+ ?line ?FalseGuard(not erlang:is_record(Foo, foo, 5)),
+ ?line ?TrueGuard(not erlang:is_record(Foo, barf, 6)),
+
+ ?line ?TrueGuard(not is_record(Config, foo, 5)),
+
+ ?line ?TrueGuard(not is_record(a, foo, 5)),
+ ?line ?TrueGuard(not is_record([], foo, 5)),
+
+ %% Pass non-literal first argument.
+
+ ?line true = is_record(id(#foo{}), foo, 5),
+ ?line false = is_record(id(#foo{}), barf, 6),
+ ?line false = is_record(id({foo}), foo, 5),
+
+ ?line true = erlang:is_record(id(#foo{}), foo, 5),
+ ?line false = erlang:is_record(id(#foo{}), barf, 6),
+ ?line false = erlang:is_record(id({foo}), foo, 5),
+
+ NoRec1 = id(blurf),
+ NoRec2 = id([]),
+
+ ?line ?TrueGuard(not is_record(NoRec1, foo, 5)),
+ ?line ?TrueGuard(not is_record(NoRec2, foo, 5)),
+
+ %% Force the use of guard bifs by using the 'xor' operation.
+
+ False = id(false),
+ ?line ?TrueGuard(is_record(#foo{}, foo, 5) xor False),
+ ?line ?FalseGuard(is_record(#foo{}, barf, 6) xor False),
+ ?line ?FalseGuard(is_record({foo}, foo, 5) xor False ),
+
+ ?line ?TrueGuard(is_record(Foo, foo, 5) xor False),
+ ?line ?FalseGuard(is_record(Foo, barf, 6) xor False),
+
+
+ %% Implicit guards by using a list comprehension.
+
+ List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]),
+
+ ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo, 5)],
+ ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar, 5)],
+ ?line [1,#foo{a=2},3,5,#foo{a=6},7] =
+ [X || X <- List, not is_record(X, bar, 5)],
+ ?line [1,3,5,7] =
+ [X || X <- List, ((not is_record(X, bar, 5)) and (not is_record(X, foo, 5)))],
+ ?line [#foo{a=2},#bar{d=4},#foo{a=6}] =
+ [X || X <- List, ((is_record(X, bar, 5)) or (is_record(X, foo, 5)))],
+ ?line [1,3,#bar{d=4}] =
+ [X || X <- List, ((is_record(X, bar, 5)) or (X < 5))],
+
+ ?line MyList = [#foo{a=3},x,[],{a,b}],
+ ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo, 5)],
+ ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5)],
+ ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo, 5) end],
+ ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo, 5) end],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo, 5) or
+ not is_binary(X)],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5) or
+ not is_binary(X)],
+ ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)],
+ ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
+ is_reference(X)],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin is_record(X, foo, 5) or
+ not is_binary(X) end],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo, 5) or
+ not is_binary(X) end],
+ ?line [#foo{a=3}] = [X || X <- MyList,
+ begin is_record(X, foo, 5) or is_reference(X) end],
+ ?line [x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo, 5) or
+ is_reference(X) end],
+
+ %% Update several fields with a string literal.
+ ?line #barf{} = Barf0 = id(#barf{}),
+ ?line Barf = update_barf(Barf0),
+ ?line #barf{a="abc",b=1} = id(Barf),
+
+ %% Non-literal arguments.
+ ?line true = is_record(id(#barf{}), id(barf), id(6)),
+ ?line false = is_record(id(#barf{}), id(barf), id(42)),
+ ?line false = is_record(id(#barf{}), id(foo), id(6)),
+
+ ok.
+
+record_access_in_guards(Config) when is_list(Config) ->
+ ?line Priv = ?config(priv_dir, Config),
+ ?line file:set_cwd(test_lib:get_data_dir(Config)),
+ ?line Opts0 = [{outdir,Priv},report_errors|test_lib:opt_opts(?MODULE)],
+ M = record_access_in_guards,
+
+ Opts = [strict_record_tests|Opts0],
+ ?line io:format("Options: ~p\n", [Opts]),
+ ?line {ok,M} = c:c(M, Opts),
+ ?line ok = M:t(),
+ ok.
+
+
+%% Test optimization of record access and is_record/2 in guards.
+
+-record(r, {a = 4,b}).
+-record(r1, {a,b}).
+-record(r2, {a = #r1{},b,c=length([1,2,3])}).
+-record(r3, {a = fun(_) -> #r1{} end(1), b}).
+
+guard_opt(Config) when is_list(Config) ->
+ ok = fun() ->
+ F = fun(F, [H,H|T]) when is_record(H, r) ->
+ [H|F(F, T)];
+ (F, [H|T]) when is_record(H, r) ->
+ [H|F(F, T)];
+ (_, []) -> []
+ end,
+ [#r{a=4,b=7},#r{a=1,b=42}] =
+ F(F, [#r{a=4,b=7},#r{a=4,b=7},#r{a=1,b=42}]),
+ {'EXIT',_} = (catch F(F, [#r1{}])),
+ ok
+ end(),
+
+ true = fun() ->
+ R = #r{},
+ if is_record(R, r) -> true; true -> false end
+ end(),
+
+ ok = fun() ->
+ F = fun(true, B) when B#r1.a -> ok;
+ (false, _) -> error
+ end,
+ ok = F(true, #r1{a=true}),
+ error = F(false, anything_goes),
+ {'EXIT',_} = (catch F(true, #r1{})),
+ {'EXIT',_} = (catch F(true, #r{})),
+ ok
+ end(),
+
+ ok = fun() ->
+ F = fun([{a,R}=T]) when R#r.a =:= 42 ->
+ {ok,tuple_size(T)};
+ ([{a,R}=T]) when R#r1.a =:= 7 ->
+ {ok,tuple_size(T)};
+ (_) -> error
+ end,
+ {ok,2} = F([{a,#r{a=42}}]),
+ {ok,2} = F([{a,#r1{a=7}}]),
+ error = F([{a,#r1{}}]),
+ error = F({a,b,c}),
+ error = F([]),
+ ok
+ end(),
+
+ ok = fun() ->
+ F = fun(X, Y, Z) when is_record(X, r1) andalso
+ (is_record(Y, r2) orelse
+ is_record(Z, r3)) -> true;
+ (_, _, _) -> false
+ end,
+ true = F(#r1{}, #r2{}, #r3{}),
+ true = F(#r1{}, #r2{}, blurf),
+ true = F(#r1{}, blurf, #r3{}),
+ false = F(#r1{}, blurf, blurf),
+ false = F(blurf, #r2{}, #r3{}),
+ false = F(blurf, #r2{}, blurf),
+ false = F(blurf, blurf, #r3{}),
+ false = F(blurf, blurf, blurf),
+ ok
+ end(),
+
+ ok = fun() ->
+ F = fun(R=#r{a=42}) when R#r.b =:= 7 ->
+ {ok,R};
+ (_) -> error
+ end,
+ {ok,#r{a=42,b=7}} = F(#r{a=42,b=7}),
+ error = F(#r{}),
+ error = F([a,b,c]),
+ ok
+ end(),
+
+ ok.
+
+update_barf(R) ->
+ R#barf{a="abc",b=1}.
+
+eval_once(Config) when is_list(Config) ->
+ ?line once(fun(GetRec) ->
+ true = erlang:is_record(GetRec(), foo)
+ end, #foo{}),
+ ?line once(fun(GetRec) ->
+ (GetRec())#foo{a=1}
+ end, #foo{}),
+ ?line once(fun(GetRec) ->
+ (GetRec())#foo{a=1,b=2}
+ end, #foo{}),
+ ?line once(fun(GetRec) ->
+ (GetRec())#foo{a=1,b=2,c=3}
+ end, #foo{}),
+ ?line once(fun(GetRec) ->
+ (GetRec())#foo{a=1,b=2,c=3,d=4}
+ end, #foo{}),
+ ok.
+
+once(Test, Record) ->
+ put(?MODULE, 0),
+ GetRec = fun() ->
+ put(?MODULE, 1+get(?MODULE)),
+ Record
+ end,
+ Result = Test(GetRec),
+ case get(?MODULE) of
+ 1 -> ok;
+ N ->
+ io:format("Evaluated ~w times\n", [N]),
+ ?t:fail()
+ end,
+ Result.
+
+%% Thanks to Martin Bjorklund.
+
+-record(foobar, {status}).
+
+foobar(Config) when is_list(Config) ->
+ {ok,_,_} = x({foo, 1}),
+ ok.
+
+get_bar() ->
+ #foobar{status = 1}.
+
+x(Trans) ->
+ {foo, Barno} = Trans,
+ case get_bar() of
+ Bar when Bar#foobar.status == 1 ->
+ noop(Bar),
+ Bar33 = Bar#foobar{status = 1},
+ {ok, Bar33, Barno};
+ _ ->
+ Trans
+ end.
+
+noop(_) ->
+ ok.
+
+-record(foo_rec,
+ {foo_1,
+ foo_2 = 0,
+ foo_3 = 0}).
+
+missing_test_heap(Config) when is_list(Config) ->
+ #foo_rec{foo_2=2,foo_3=5} = missing_test_heap_1(#foo_rec{foo_2=1,foo_3=4}),
+ ok.
+
+
+%% Two test_heap instructions would be incorrectly merged (not allowed
+%% because of gc_bif instructions for addition).
+missing_test_heap_1(A = #foo_rec {foo_1 = _B,
+ foo_3 = C,
+ foo_2 = D}) ->
+ A#foo_rec {foo_1 = {C, D},
+ foo_3 = C + 1,
+ foo_2 = D + 1}.
+
+id(I) -> I.
diff --git a/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl b/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl
new file mode 100644
index 0000000000..c2b3ec2f34
--- /dev/null
+++ b/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl
@@ -0,0 +1,177 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(record_access_in_guards).
+
+-export([t/0]).
+
+-record(r, {a = 4,b}).
+-record(r1, {a,b}).
+-record(r2, {a = #r1{},b,c=length([1,2,3])}).
+-record(r3, {a = fun(_) -> #r1{} end(1), b}).
+
+t() ->
+ foo = fun(A) when A#r1.a > A#r1.b -> foo end(#r1{b = 2}),
+ 0 = fun(A) when A#r2.a -> 0 end(#r2{a = true}),
+ 1 = fun(A) when (#r1{a = A})#r1.a > 2 -> 1 end(3),
+ 2 = fun(N) when ((#r2{a = #r{a = 4}, b = length([a,b,c])})#r2.a)#r.a > N ->
+ 2 end(2),
+ 3 = fun(A) when (A#r2.a)#r1.a =:= 3 -> 3 end(#r2{a = #r1{a = 3}}),
+ ok = fun() ->
+ F = fun(A) when record(A#r.a, r1) -> 4;
+ (A) when record(A#r1.a, r1) -> 5
+ end,
+ 5 = F(#r1{a = #r1{}}),
+ 4 = F(#r{a = #r1{}}),
+ ok
+ end(),
+ 3 = fun(A) when record(A#r1.a, r),
+ (A#r1.a)#r.a > 3 -> 3
+ end(#r1{a = #r{a = 4}}),
+ 7 = fun(A) when record(A#r3.a, r1) -> 7 end(#r3{}),
+ [#r1{a = 2,b = 1}] =
+ fun() ->
+ [A || A <- [#r1{a = 1, b = 3},
+ #r2{a = 2,b = 1},
+ #r1{a = 2, b = 1}],
+ A#r1.a >
+ A#r1.b]
+ end(),
+ {[_],b} =
+ fun(L) ->
+ %% A is checked only once:
+ R1 = [{A,B} || A <- L, A#r1.a, B <- L, A#r1.b],
+ A = #r2{a = true},
+ %% A is checked again:
+ B = if A#r1.a -> a; true -> b end,
+ {R1,B}
+ end([#r1{a = true, b = true}]),
+
+ p = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o;
+ (_) -> p
+ end(#r1{a = 2}),
+
+ o = fun(A) when (A#r1.a =:= 2) orelse (A#r2.a =:= 1) -> o;
+ (_) -> p
+ end(#r1{a = 2}),
+
+ 3 = fun(A) when A#r1.a > 3,
+ record(A, r1) -> 3
+ end(#r1{a = 5}),
+
+ ok = fun() ->
+ F = fun(A) when (A#r2.a =:= 1) orelse (A#r2.a) -> 2;
+ (A) when (A#r1.a =:= 1) orelse (A#r1.a) -> 1;
+ (A) when (A#r2.a =:= 2) andalso (A#r2.b) -> 3
+ end,
+ 1 = F(#r1{a = 1}),
+ 2 = F(#r2{a = true}),
+ 3 = F(#r2{a = 2, b = true}),
+ ok
+ end(),
+
+ b = fun(A) when false or not (A#r.a =:= 1) -> a;
+ (_) -> b
+ end(#r1{a = 1}),
+ b = fun(A) when not (A#r.a =:= 1) or false -> a;
+ (_) -> b
+ end(#r1{a = 1}),
+
+ ok = fun() ->
+ F = fun(A) when not (A#r.a =:= 1) -> yes;
+ (_) -> no
+ end,
+ no = F(#r1{a = 2}),
+ yes = F(#r{a = 2}),
+ no = F(#r{a = 1}),
+ ok
+ end(),
+
+ a = fun(A) when record(A, r),
+ A#r.a =:= 1,
+ A#r.b =:= 2 ->a
+ end(#r{a = 1, b = 2}),
+ a = fun(A) when erlang:is_record(A, r),
+ A#r.a =:= 1,
+ A#r.b =:= 2 -> a
+ end(#r{a = 1, b = 2}),
+ a = fun(A) when is_record(A, r),
+ A#r.a =:= 1,
+ A#r.b =:= 2 -> a
+ end(#r{a = 1, b = 2}),
+
+ nop = fun(A) when (is_record(A, r1) and (A#r1.a > 3)) or (A#r2.a < 1) ->
+ japp;
+ (_) ->
+ nop
+ end(#r2{a = 0}),
+ nop = fun(A) when (A#r1.a > 3) or (A#r2.a < 1) -> japp;
+ (_) ->
+ nop
+ end(#r2{a = 0}),
+
+ ok = fun() ->
+ F = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o;
+ (_) -> p
+ end,
+ p = F(#r2{a = 1}),
+ p = F(#r1{a = 2}),
+ ok
+ end(),
+
+ ok = fun() ->
+ F = fun(A) when fail, A#r1.a; A#r1.a -> ab;
+ (_) -> bu
+ end,
+ ab = F(#r1{a = true}),
+ bu = F(#r2{a = true}),
+ ok
+ end(),
+
+ both = fun(A) when A#r.a, A#r.b -> both
+ end(#r{a = true, b = true}),
+
+ ok = fun() ->
+ F = fun(A, B) when ((A#r1.a) orelse (B#r2.a))
+ or (B#r2.b) or (A#r1.b) -> true;
+ (_, _) -> false
+ end,
+ true = F(#r1{a = false, b = false}, #r2{a = false, b = true}),
+ false = F(#r1{a = true, b = true}, #r1{a = false, b = true}),
+ ok
+ end(),
+
+ ok = fun(R) ->
+ F = fun(Head, Version, Tab) ->
+ VersionOK = (Head#r.a =:= Version),
+ if
+ Tab =:= Head#r.b, VersionOK ->
+ ok;
+ true ->
+ error
+ end
+ end,
+ ok = F(R, 42, tab),
+ error = F(R, 42, a),
+ error = F(R, 0, tab),
+ {'EXIT',{{badrecord,r},_}} = (catch F({x,y,z}, 4, 5)),
+ ok
+ end(#r{a=42,b=tab}),
+
+ ok.
+
diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl
new file mode 100644
index 0000000000..3099538071
--- /dev/null
+++ b/lib/compiler/test/test_lib.erl
@@ -0,0 +1,75 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(test_lib).
+
+-include("test_server.hrl").
+
+-export([recompile/1,opt_opts/1,get_data_dir/1,smoke_disasm/1]).
+
+recompile(Mod) when is_atom(Mod) ->
+ case whereis(cover_server) of
+ undefined -> ok;
+ _ ->
+ %% Re-compile the test suite if the cover server is running.
+ Beam = code:which(Mod),
+ Src = filename:rootname(Beam, ".beam") ++ ".erl",
+ Opts = [bin_opt_info|opt_opts(Mod)],
+ io:format("Recompiling ~p (~p)\n", [Mod,Opts]),
+ c:c(Src, [{outdir,filename:dirname(Src)}|Opts])
+ end,
+
+ %% Smoke-test of beam disassembler.
+ smoke_disasm(Mod).
+
+smoke_disasm(Mod) when is_atom(Mod) ->
+ smoke_disasm(code:which(Mod));
+smoke_disasm(File) when is_list(File) ->
+ Res = beam_disasm:file(File),
+ {beam_file,Mod} = {element(1, Res),element(2, Res)}.
+
+%% Retrieve the "interesting" compiler options (options for optimization
+%% and compatibility) for the given module.
+
+opt_opts(Mod) ->
+ Comp = Mod:module_info(compile),
+ {value,{options,Opts}} = lists:keysearch(options, 1, Comp),
+ lists:filter(fun(no_copt) -> true;
+ (no_postopt) -> true;
+ (no_float_opt) -> true;
+ (no_new_funs) -> true;
+ (no_new_binaries) -> true;
+ (no_new_apply) -> true;
+ (no_gc_bifs) -> true;
+ (no_constant_pool) -> true;
+ (no_stack_trimming) -> true;
+ (no_binaries) -> true;
+ (debug_info) -> true;
+ (_) -> false
+ end, Opts).
+
+%% Some test suites gets cloned (e.g. to "record_SUITE" to "record_no_opt_SUITE"),
+%% but the data directory is not cloned. This function retrieves the path to
+%% the original data directory.
+
+get_data_dir(Config) ->
+ Data0 = ?config(data_dir, Config),
+ {ok,Data1,_} = regexp:sub(Data0, "_no_opt_SUITE", "_SUITE"),
+ {ok,Data2,_} = regexp:sub(Data1, "_post_opt_SUITE", "_SUITE"),
+ {ok,Data,_} = regexp:sub(Data2, "_r11_SUITE", "_SUITE"),
+ Data.
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
new file mode 100644
index 0000000000..c2f6dc24be
--- /dev/null
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -0,0 +1,911 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(trycatch_SUITE).
+
+-export([all/1,basic/1,lean_throw/1,try_of/1,try_after/1,%after_bind/1,
+ catch_oops/1,after_oops/1,eclectic/1,rethrow/1,
+ nested_of/1,nested_catch/1,nested_after/1,
+ nested_horrid/1,last_call_optimization/1,bool/1,
+ plain_catch_coverage/1,andalso_orelse/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [basic,lean_throw,try_of,try_after,%after_bind,
+ catch_oops,after_oops,eclectic,rethrow,
+ nested_of,nested_catch,nested_after,
+ nested_horrid,last_call_optimization,
+ bool,plain_catch_coverage,andalso_orelse].
+
+
+basic(Conf) when is_list(Conf) ->
+ ?line 2 =
+ try my_div(4, 2)
+ catch
+ Class:Reason -> {Class,Reason}
+ end,
+ ?line error =
+ try my_div(1, 0)
+ catch
+ error:badarith -> error
+ end,
+ ?line error =
+ try 1.0 / zero()
+ catch
+ error:badarith -> error
+ end,
+ ?line ok =
+ try my_add(53, atom)
+ catch
+ error:badarith -> ok
+ end,
+ ?line exit_nisse =
+ try exit(nisse)
+ catch
+ exit:nisse -> exit_nisse
+ end,
+ ?line ok =
+ try throw(kalle)
+ catch
+ kalle -> ok
+ end,
+
+ %% Try some stuff where the compiler will optimize away the try.
+
+ V = id({a,variable}),
+ ?line V = try V catch nisse -> error end,
+ ?line 42 = try 42 catch nisse -> error end,
+ ?line [V] = try [V] catch nisse -> error end,
+ ?line {ok,V} = try {ok,V} catch nisse -> error end,
+
+ %% Same idea, but use an after too.
+
+ ?line V = try V catch nisse -> error after after_call() end,
+ ?line after_clean(),
+ ?line 42 = try 42 after after_call() end,
+ ?line after_clean(),
+ ?line [V] = try [V] catch nisse -> error after after_call() end,
+ ?line after_clean(),
+ ?line {ok,V} = try {ok,V} after after_call() end,
+
+ %% Try/of
+ ?line ok = try V of
+ {a,variable} -> ok
+ catch nisse -> erro
+ end,
+
+ ok.
+
+after_call() ->
+ put(basic, after_was_called).
+
+after_clean() ->
+ after_was_called = erase(basic).
+
+
+lean_throw(Conf) when is_list(Conf) ->
+ ?line {throw,kalle} =
+ try throw(kalle)
+ catch
+ Kalle -> {throw,Kalle}
+ end,
+ ?line {exit,kalle} =
+ try exit(kalle)
+ catch
+ Throw1 -> {throw,Throw1};
+ exit:Reason1 -> {exit,Reason1}
+ end,
+ ?line {exit,kalle} =
+ try exit(kalle)
+ catch
+ exit:Reason2 -> {exit,Reason2};
+ Throw2 -> {throw,Throw2}
+ end,
+ ?line {exit,kalle} =
+ try try exit(kalle)
+ catch
+ Throw3 -> {throw,Throw3}
+ end
+ catch
+ exit:Reason3 -> {exit,Reason3}
+ end,
+ ok.
+
+
+
+try_of(Conf) when is_list(Conf) ->
+ ?line {ok,{some,content}} =
+ try_of_1({value,{good,{some,content}}}),
+ ?line {error,[other,content]} =
+ try_of_1({value,{bad,[other,content]}}),
+ ?line {caught,{exit,{ex,it,[reason]}}} =
+ try_of_1({exit,{ex,it,[reason]}}),
+ ?line {caught,{throw,[term,{in,a,{tuple}}]}} =
+ try_of_1({throw,[term,{in,a,{tuple}}]}),
+ ?line {caught,{error,[bad,arg]}} =
+ try_of_1({error,[bad,arg]}),
+ ?line {caught,{error,badarith}} =
+ try_of_1({'div',{1,0}}),
+ ?line {caught,{error,badarith}} =
+ try_of_1({'add',{a,0}}),
+ ?line {caught,{error,badarg}} =
+ try_of_1({'abs',x}),
+ ?line {caught,{error,function_clause}} =
+ try_of_1(illegal),
+ ?line {error,{try_clause,{some,other_garbage}}} =
+ try try_of_1({value,{some,other_garbage}})
+ catch error:Reason -> {error,Reason}
+ end,
+ ok.
+
+try_of_1(X) ->
+ try foo(X) of
+ {good,Y} -> {ok,Y};
+ {bad,Y} -> {error,Y}
+ catch
+ Class:Reason ->
+ {caught,{Class,Reason}}
+ end.
+
+
+
+try_after(Conf) when is_list(Conf) ->
+ ?line {{ok,[some,value],undefined},finalized} =
+ try_after_1({value,{ok,[some,value]}},finalized),
+ ?line {{error,badarith,undefined},finalized} =
+ try_after_1({'div',{1,0}},finalized),
+ ?line {{error,badarith,undefined},finalized} =
+ try_after_1({'add',{1,a}},finalized),
+ ?line {{error,badarg,undefined},finalized} =
+ try_after_1({'abs',a},finalized),
+ ?line {{error,[the,{reason}],undefined},finalized} =
+ try_after_1({error,[the,{reason}]},finalized),
+ ?line {{throw,{thrown,[reason]},undefined},finalized} =
+ try_after_1({throw,{thrown,[reason]}},finalized),
+ ?line {{exit,{exited,{reason}},undefined},finalized} =
+ try_after_1({exit,{exited,{reason}}},finalized),
+ ?line {{error,function_clause,undefined},finalized} =
+ try_after_1(function_clause,finalized),
+ ?line ok =
+ try try_after_1({'add',{1,1}}, finalized)
+ catch
+ error:{try_clause,2} -> ok
+ end,
+ ?line finalized = erase(try_after),
+ ?line ok =
+ try try foo({exit,[reaso,{n}]})
+ after put(try_after, finalized)
+ end
+ catch
+ exit:[reaso,{n}] -> ok
+ end,
+ ok.
+
+try_after_1(X, Y) ->
+ erase(try_after),
+ Try =
+ try foo(X) of
+ {ok,Value} -> {ok,Value,get(try_after)}
+ catch
+ Reason -> {throw,Reason,get(try_after)};
+ error:Reason -> {error,Reason,get(try_after)};
+ exit:Reason -> {exit,Reason,get(try_after)}
+ after
+ put(try_after, Y)
+ end,
+ {Try,erase(try_after)}.
+
+
+
+-ifdef(begone).
+
+after_bind(Conf) when is_list(Conf) ->
+ V = [make_ref(),self()|value],
+ ?line {value,{value,V}} =
+ after_bind_1({value,V}, V, {value,V}),
+ ok.
+
+after_bind_1(X, V, Y) ->
+ try
+ Try =
+ try foo(X) of
+ V -> value
+ catch
+ C1:V -> {caught,C1}
+ after
+ After = foo(Y)
+ end,
+ {Try,After}
+ of
+ V -> {value,V}
+ catch
+ C:D -> {caught,{C,D}}
+ end.
+
+-endif.
+
+
+
+catch_oops(Conf) when is_list(Conf) ->
+ V = {v,[a,l|u],{e},self()},
+ ?line {value,V} = catch_oops_1({value,V}),
+ ?line {value,1} = catch_oops_1({'div',{1,1}}),
+ ?line {error,badarith} = catch_oops_1({'div',{1,0}}),
+ ?line {error,function_clause} = catch_oops_1(function_clause),
+ ?line {throw,V} = catch_oops_1({throw,V}),
+ ?line {exit,V} = catch_oops_1({exit,V}),
+ ok.
+
+catch_oops_1(X) ->
+ Ref = make_ref(),
+ try try foo({error,Ref})
+ catch
+ error:Ref ->
+ foo(X)
+ end of
+ Value -> {value,Value}
+ catch
+ Class:Data -> {Class,Data}
+ end.
+
+
+
+after_oops(Conf) when is_list(Conf) ->
+ V = {self(),make_ref()},
+ ?line {{value,V},V} = after_oops_1({value,V}, {value,V}),
+ ?line {{exit,V},V} = after_oops_1({exit,V}, {value,V}),
+ ?line {{error,V},undefined} = after_oops_1({value,V}, {error,V}),
+ ?line {{error,function_clause},undefined} =
+ after_oops_1({exit,V}, function_clause),
+ ok.
+
+after_oops_1(X, Y) ->
+ erase(after_oops),
+ Try =
+ try try foo(X)
+ after
+ put(after_oops, foo(Y))
+ end of
+ V -> {value,V}
+ catch
+ C:D -> {C,D}
+ end,
+ {Try,erase(after_oops)}.
+
+
+
+eclectic(Conf) when is_list(Conf) ->
+ V = {make_ref(),3.1415926535,[[]|{}]},
+ ?line {{value,{value,V},V},V} =
+ eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}),
+ ?line {{'EXIT',{V,[{?MODULE,foo,1}|_]}},V} =
+ eclectic_1({catch_foo,{error,V}}, undefined, {value,V}),
+ ?line {{error,{exit,V},{'EXIT',V}},V} =
+ eclectic_1({foo,{error,{exit,V}}}, error, {value,V}),
+ ?line {{value,{value,V},V},
+ {'EXIT',{badarith,[{?MODULE,my_add,2}|_]}}} =
+ eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}),
+ ?line {{'EXIT',V},V} =
+ eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}),
+ ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2}|_]}}},
+ {'EXIT',V}} =
+ eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}),
+ ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,1}|_]}}},
+ {'EXIT',V}} =
+ eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}),
+ %%
+ ?line {{value,{value,{value,V},V}},V} =
+ eclectic_2({value,{value,V}}, undefined, {value,V}),
+ ?line {{value,{throw,{value,V},V}},V} =
+ eclectic_2({throw,{value,V}}, throw, {value,V}),
+ ?line {{caught,{'EXIT',V}},undefined} =
+ eclectic_2({value,{value,V}}, undefined, {exit,V}),
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1}|_]}}},undefined} =
+ eclectic_2({error,{value,V}}, throw, {error,V}),
+ ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V]}|_]}}},V} =
+ eclectic_2({value,{'abs',V}}, undefined, {value,V}),
+ ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2}|_]}}},V} =
+ eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}),
+ ?line {{caught,{'EXIT',V}},undefined} =
+ eclectic_2({value,{error,V}}, undefined, {exit,V}),
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1}|_]}}},undefined} =
+ eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}),
+ ok.
+
+eclectic_1(X, C, Y) ->
+ erase(eclectic),
+ Done = make_ref(),
+ Try =
+ try case X of
+ {catch_foo,V} -> catch {Done,foo(V)};
+ {foo,V} -> {Done,foo(V)}
+ end of
+ {Done,D} -> {value,D,catch foo(D)};
+ {'EXIT',_}=Exit -> Exit;
+ D -> {D,catch foo(D)}
+ catch
+ C:D -> {C,D,catch foo(D)}
+ after
+ put(eclectic, catch foo(Y))
+ end,
+ {Try,erase(eclectic)}.
+
+eclectic_2(X, C, Y) ->
+ Done = make_ref(),
+ erase(eclectic),
+ Catch =
+ case
+ catch
+ {Done,
+ try foo(X) of
+ V -> {value,V,foo(V)}
+ catch
+ C:D -> {C,D,foo(D)}
+ after
+ put(eclectic, foo(Y))
+ end} of
+ {Done,Z} -> {value,Z};
+ Z -> {caught,Z}
+ end,
+ {Catch,erase(eclectic)}.
+
+
+
+rethrow(Conf) when is_list(Conf) ->
+ V = {a,[b,{c,self()},make_ref]},
+ ?line {value2,value1} =
+ rethrow_1({value,V}, V),
+ ?line {caught2,{error,V}} =
+ rethrow_2({error,V}, undefined),
+ ?line {caught2,{exit,V}} =
+ rethrow_1({exit,V}, error),
+ ?line {caught2,{throw,V}} =
+ rethrow_1({throw,V}, undefined),
+ ?line {caught2,{throw,V}} =
+ rethrow_2({throw,V}, undefined),
+ ?line {caught2,{error,badarith}} =
+ rethrow_1({'add',{0,a}}, throw),
+ ?line {caught2,{error,function_clause}} =
+ rethrow_2(function_clause, undefined),
+ ?line {caught2,{error,{try_clause,V}}} =
+ rethrow_1({value,V}, exit),
+ ?line {value2,{caught1,V}} =
+ rethrow_1({error,V}, error),
+ ?line {value2,{caught1,V}} =
+ rethrow_1({exit,V}, exit),
+ ?line {value2,caught1} =
+ rethrow_2({throw,V}, V),
+ ok.
+
+rethrow_1(X, C1) ->
+ try try foo(X) of
+ C1 -> value1
+ catch
+ C1:D1 -> {caught1,D1}
+ end of
+ V2 -> {value2,V2}
+ catch
+ C2:D2 -> {caught2,{C2,D2}}
+ end.
+
+rethrow_2(X, C1) ->
+ try try foo(X) of
+ C1 -> value1
+ catch
+ C1 -> caught1 % Implicit class throw:
+ end of
+ V2 -> {value2,V2}
+ catch
+ C2:D2 -> {caught2,{C2,D2}}
+ end.
+
+
+
+nested_of(Conf) when is_list(Conf) ->
+ V = {[self()|make_ref()],1.4142136},
+ ?line {{value,{value1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{throw,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}),
+ %%
+ ?line {{caught,{error,{try_clause,{V,x1}}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,try_clause},
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{exit,{V,x3}}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,try_clause},
+ void, {exit,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{throw,{V,x4}}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,try_clause},
+ void, {exit,{V,x3}}, {throw,{V,x4}}),
+ %%
+ ?line {{value,{caught1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{error,{V,x1}},error,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_of_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_of_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {'div',{17,0}}, {'abs',V}),
+ %%
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{'add',{2,c}},rethrow,void},
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_of_1({{'add',{2,c}},rethrow,void},
+ void, {'abs',V}, {value,{V,x4}}),
+ ?line {{caught,{error,function_clause}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_of_1({{'add',{2,c}},rethrow,void},
+ void, {'abs',V}, function_clause),
+ ok.
+
+nested_of_1({X1,C1,V1},
+ X2, X3, X4) ->
+ erase(nested3),
+ erase(nested4),
+ erase(nested),
+ Self = self(),
+ Try =
+ try
+ try self()
+ of
+ Self ->
+ try
+ foo(X1)
+ of
+ V1 -> {value1,foo(X2)}
+ catch
+ C1:V1 -> {caught1,foo(X2)}
+ after
+ put(nested3, foo(X3))
+ end
+ after
+ put(nested4, foo(X4))
+ end
+ of
+ V -> {value,V}
+ catch
+ C:D -> {caught,{C,D}}
+ after
+ put(nested, finalized)
+ end,
+ {Try,erase(nested3),erase(nested4),erase(nested)}.
+
+
+
+nested_catch(Conf) when is_list(Conf) ->
+ V = {[make_ref(),1.4142136,self()]},
+ ?line {{value,{value1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{throw,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}),
+ %%
+ ?line {{caught,{error,{try_clause,{V,x1}}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,try_clause},
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{exit,{V,x3}}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,try_clause},
+ void, {exit,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{throw,{V,x4}}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,try_clause},
+ void, {exit,{V,x3}}, {throw,{V,x4}}),
+ %%
+ ?line {{value,{caught1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{error,{V,x1}},error,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_catch_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_catch_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {'div',{17,0}}, {'abs',V}),
+ %%
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{'add',{2,c}},rethrow,void},
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_catch_1({{'add',{2,c}},rethrow,void},
+ void, {'abs',V}, {value,{V,x4}}),
+ ?line {{caught,{error,function_clause}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_catch_1({{'add',{2,c}},rethrow,void},
+ void, {'abs',V}, function_clause),
+ ok.
+
+nested_catch_1({X1,C1,V1},
+ X2, X3, X4) ->
+ erase(nested3),
+ erase(nested4),
+ erase(nested),
+ Throw = make_ref(),
+ Try =
+ try
+ try throw(Throw)
+ catch
+ Throw ->
+ try
+ foo(X1)
+ of
+ V1 -> {value1,foo(X2)}
+ catch
+ C1:V1 -> {caught1,foo(X2)}
+ after
+ put(nested3, foo(X3))
+ end
+ after
+ put(nested4, foo(X4))
+ end
+ of
+ V -> {value,V}
+ catch
+ C:D -> {caught,{C,D}}
+ after
+ put(nested, finalized)
+ end,
+ {Try,erase(nested3),erase(nested4),erase(nested)}.
+
+
+
+nested_after(Conf) when is_list(Conf) ->
+ V = [{make_ref(),1.4142136,self()}],
+ ?line {value,
+ {V,x3},
+ {value1,{V,x2}},
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}),
+ ?line {{caught,{error,{V,x2}}},
+ {V,x3},
+ undefined,
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,{V,x1}},
+ {error,{V,x2}}, {value,{V,x3}}),
+ ?line {{caught,{exit,{V,x3}}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,{V,x1}},
+ {error,{V,x2}}, {exit,{V,x3}}),
+ %%
+ ?line {{caught,{error,{try_clause,{V,x1}}}},
+ {V,x3},
+ undefined,
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,try_clause},
+ void, {value,{V,x3}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,try_clause},
+ void, {'div',{17,0}}),
+ %%
+ ?line {value,
+ {V,x3},
+ {caught1,{V,x2}},
+ finalized} =
+ nested_after_1({{throw,{V,x1}},throw,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}),
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ undefined,
+ finalized} =
+ nested_after_1({{throw,{V,x1}},throw,{V,x1}},
+ {'add',{a,b}}, {value,{V,x3}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_after_1({{throw,{V,x1}},throw,{V,x1}},
+ {'add',{a,b}}, {'abs',V}),
+ %%
+ ?line {{caught,{throw,{V,x1}}},
+ {V,x3},
+ undefined,
+ finalized} =
+ nested_after_1({{throw,{V,x1}},rethrow,void},
+ void, {value,{V,x3}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_after_1({{throw,{V,x1}},rethrow,void},
+ void, {'div',{1,0}}),
+ ok.
+
+nested_after_1({X1,C1,V1},
+ X2, X3) ->
+ erase(nested3),
+ erase(nested4),
+ erase(nested),
+ Self = self(),
+ Try =
+ try
+ try self()
+ after
+ After =
+ try
+ foo(X1)
+ of
+ V1 -> {value1,foo(X2)}
+ catch
+ C1:V1 -> {caught1,foo(X2)}
+ after
+ put(nested3, foo(X3))
+ end,
+ put(nested4, After)
+ end
+ of
+ Self -> value
+ catch
+ C:D -> {caught,{C,D}}
+ after
+ put(nested, finalized)
+ end,
+ {Try,erase(nested3),erase(nested4),erase(nested)}.
+
+
+
+nested_horrid(Config) when is_list(Config) ->
+ _V = {make_ref(),nested_horrid,4.711},
+ {[true,true],{[true,1.0],1.0}} =
+ nested_horrid_1({true,void,void}, 1.0),
+ ok.
+
+nested_horrid_1({X1,C1,V1}, X2) ->
+ try A1 = [X1,X1],
+ B1 = if X1 ->
+ A2 = [X1,X2],
+ B2 = foo(X2),
+ {A2,B2};
+ true ->
+ A3 = [X2,X1],
+ B3 = foo(X2),
+ {A3,B3}
+ end,
+ {A1,B1}
+ catch
+ C1:V1 -> caught1
+ end.
+
+
+
+foo({value,Value}) -> Value;
+foo({'div',{A,B}}) ->
+ my_div(A, B);
+foo({'add',{A,B}}) ->
+ my_add(A, B);
+foo({'abs',X}) ->
+ my_abs(X);
+foo({error,Error}) ->
+ erlang:error(Error);
+foo({throw,Throw}) ->
+ erlang:throw(Throw);
+foo({exit,Exit}) ->
+ erlang:exit(Exit);
+foo({raise,{Class,Reason}}) ->
+ erlang:raise(Class, Reason);
+foo(Term) when not is_atom(Term) -> Term.
+%%foo(Atom) when is_atom(Atom) -> % must not be defined!
+
+my_div(A, B) ->
+ A div B.
+
+my_add(A, B) ->
+ A + B.
+
+my_abs(X) -> abs(X).
+
+
+last_call_optimization(Config) when is_list(Config) ->
+ ?line error = in_tail(dum),
+ ?line StkSize0 = in_tail(0),
+ ?line StkSize = in_tail(50000),
+ io:format("StkSize0 = ~p", [StkSize0]),
+ io:format("StkSize = ~p", [StkSize]),
+ ?line StkSize = StkSize0,
+ ok.
+
+in_tail(E) ->
+ try erlang:abs(E) of
+ T ->
+ A = id([]),
+ B = id([]),
+ C = id([]),
+ id([A,B,C]),
+ do_tail(T)
+ catch error:badarg -> error
+ end.
+
+do_tail(0) ->
+ process_info(self(), stack_size);
+do_tail(N) ->
+ in_tail(N-1).
+
+bool(Config) when is_list(Config) ->
+ ok = do_bool(false, false),
+ error = do_bool(false, true),
+ error = do_bool(true, false),
+ error = do_bool(true, true),
+ error = do_bool(true, blurf),
+ {'EXIT',_} = (catch do_bool(blurf, false)),
+ ok.
+
+%% The following function used to cause a crash in beam_bool.
+do_bool(A0, B) ->
+ A = not A0,
+ try
+ id(42),
+ if
+ A, not B -> ok
+ end
+ catch
+ _:_ ->
+ error
+ end.
+
+plain_catch_coverage(Config) when is_list(Config) ->
+ %% Cover some code in beam_block:alloc_may_pass/1.
+ ?line {a,[42]} = do_plain_catch_list(42).
+
+do_plain_catch_list(X) ->
+ B = [X],
+ catch id({a,B}).
+
+andalso_orelse(Config) when is_list(Config) ->
+ ?line {2,{a,42}} = andalso_orelse_1(true, {a,42}),
+ ?line {b,{b}} = andalso_orelse_1(false, {b}),
+ ?line {catched,no_tuple} = andalso_orelse_1(false, no_tuple),
+
+ ?line ok = andalso_orelse_2({type,[a]}),
+ ?line also_ok = andalso_orelse_2({type,[]}),
+ ?line also_ok = andalso_orelse_2({type,{a}}),
+ ok.
+
+andalso_orelse_1(A, B) ->
+ {try
+ if
+ A andalso element(1, B) =:= a ->
+ tuple_size(B);
+ true ->
+ element(1, B)
+ end
+ catch error:_ ->
+ catched
+ end,B}.
+
+id(I) -> I.
+
+andalso_orelse_2({Type,Keyval}) ->
+ try
+ if is_atom(Type) andalso length(Keyval) > 0 -> ok;
+ true -> also_ok
+ end
+ catch
+ _:_ -> fail
+ end.
+
+zero() ->
+ 0.0.
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
new file mode 100644
index 0000000000..6e60ab88cb
--- /dev/null
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -0,0 +1,554 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(warnings_SUITE).
+
+%%-define(STANDALONE, true).
+
+-ifdef(STANDALONE).
+-define(line, put(line, ?LINE), ).
+-define(config(X,Y), foo).
+-define(privdir, "warnings_SUITE_priv").
+-define(t, test_server).
+-else.
+-include("test_server.hrl").
+-define(datadir, ?config(data_dir, Conf)).
+-define(privdir, ?config(priv_dir, Conf)).
+-endif.
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2]).
+
+-export([pattern/1,pattern2/1,pattern3/1,pattern4/1,
+ guard/1,bad_arith/1,bool_cases/1,bad_apply/1,
+ files/1,effect/1,bin_opt_info/1,bin_construction/1]).
+
+% Default timetrap timeout (set in init_per_testcase).
+-define(default_timeout, ?t:minutes(2)).
+
+init_per_testcase(_Case, Config) ->
+ ?line Dog = ?t:timetrap(?default_timeout),
+ [{watchdog, Dog} | Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ test_lib:recompile(?MODULE),
+ [pattern,pattern2,pattern3,pattern4,
+ guard,bad_arith,bool_cases,bad_apply,files,effect,
+ bin_opt_info,bin_construction].
+
+pattern(Config) when is_list(Config) ->
+ %% Test warnings generated by v3_core.
+ Ts = [{pattern,
+ <<"%% Just a comment here.
+ f(a={glurf,2}=A) -> A.
+
+ g(A) ->
+ case A of
+ a=[_|_] -> error;
+ Other -> true
+ end.
+
+ foo(X) ->
+ a = {nisse,b} = X.
+ ">>,
+ [warn_unused_vars],
+ {warnings,
+ [{2,v3_core,nomatch},
+ {6,v3_core,nomatch},
+ {11,v3_core,nomatch} ] }}],
+ ?line [] = run(Config, Ts),
+ ok.
+
+pattern2(Config) when is_list(Config) ->
+ %% Test warnings generated by sys_core_fold.
+ %% If we disable Core Erlang optimizations, we expect that
+ %% v3_kernel should generate some of the warnings.
+ Source = <<"f(A) -> ok;
+ f(B) -> error.
+ t(A, B, C) ->
+ case {A,B,C} of
+ {a,B} -> ok;
+ {_,B} -> ok
+ end.
+ ">>,
+
+ %% Test warnings from sys_core_fold.
+ Ts = [{pattern2,
+ Source,
+ [nowarn_unused_vars],
+ {warnings,[{2,sys_core_fold,{nomatch_shadow,1}},
+ {5,sys_core_fold,nomatch_clause_type},
+ {6,sys_core_fold,nomatch_clause_type}]}}],
+ ?line [] = run(Config, Ts),
+
+ %% Disable Core Erlang optimizations. v3_kernel should produce
+ %% a warning for the clause that didn't match.
+ Ts2 = [{pattern2,
+ Source,
+ [nowarn_unused_vars,no_copt],
+ {warnings,
+ [{2,v3_kernel,{nomatch_shadow,1}}]}}],
+ ?line [] = run(Config, Ts2),
+ ok.
+
+pattern3(Config) when is_list(Config) ->
+ %% Test warnings generated by the pattern matching compiler
+ %% in v3_kernel.
+
+ Ts = [{pattern3,
+ <<"
+ f({A,_}) -> {ok,A};
+ f([_|_]=B) -> {ok,B};
+ f({urk,nisse}) -> urka_glurka.
+ ">>,
+ [nowarn_unused_vars],
+ {warnings,
+ [{4,v3_kernel,{nomatch_shadow,2}}]}}],
+ ?line [] = run(Config, Ts),
+
+ ok.
+
+pattern4(Config) when is_list(Config) ->
+ %% Test warnings for clauses that cannot possibly match.
+
+ Ts = [{pattern4,
+ <<"
+ t() ->
+ case true of
+ false -> a;
+ true -> b
+ end.
+
+ fi() ->
+ case true of
+ false -> a;
+ false -> b
+ end,
+ case true of
+ true -> a;
+ true -> b;
+ X -> X
+ end,
+ case boolean of
+ true -> a;
+ false -> b
+ end.
+ int() ->
+ case 42 of
+ [a|b] -> no;
+ <<1>> -> no;
+ <<X>> -> no;
+ 17 -> no;
+ [] -> no;
+ a -> no;
+ {a,b,c} -> no
+ end.
+ tuple() ->
+ case {x,y,z} of
+ \"xyz\" -> no;
+ [a|b] -> no;
+ <<1>> -> no;
+ <<X>> -> no;
+ 17 -> no;
+ [] -> no;
+ a -> no;
+ {a,b,c} -> no;
+ {x,y} -> no
+ end.
+ ">>,
+ [nowarn_unused_vars],
+ {warnings,
+ [{9,sys_core_fold,no_clause_match},
+ {18,sys_core_fold,no_clause_match},
+ {23,sys_core_fold,no_clause_match},
+ {33,sys_core_fold,no_clause_match}
+ ]}}],
+ ?line [] = run(Config, Ts),
+
+ ok.
+
+guard(Config) when is_list(Config) ->
+ %% Test warnings for false guards.
+
+ Ts = [{guard,
+ <<"
+ t(A, B) when element(x, dum) -> ok.
+
+ tt(A, B) when 1 == 2 -> ok.
+
+ ttt() when element(x, dum) -> ok.
+
+ t4(T, F) when element({F}, T) -> ok.
+ t5(T, F) when element([F], T) -> ok.
+ t6(Pos, F) when element(Pos, [F]) -> ok.
+ t7(Pos) when element(Pos, []) -> ok.
+ ">>,
+ [nowarn_unused_vars],
+ {warnings,
+ [{2,sys_core_fold,no_clause_match},
+ {2,sys_core_fold,nomatch_guard},
+ {2,sys_core_fold,{eval_failure,badarg}},
+ {4,sys_core_fold,no_clause_match},
+ {4,sys_core_fold,nomatch_guard},
+ {6,sys_core_fold,no_clause_match},
+ {6,sys_core_fold,nomatch_guard},
+ {6,sys_core_fold,{eval_failure,badarg}},
+ {8,sys_core_fold,no_clause_match},
+ {8,sys_core_fold,nomatch_guard},
+ {8,sys_core_fold,{eval_failure,badarg}},
+ {9,sys_core_fold,no_clause_match},
+ {9,sys_core_fold,nomatch_guard},
+ {9,sys_core_fold,{eval_failure,badarg}},
+ {10,sys_core_fold,no_clause_match},
+ {10,sys_core_fold,nomatch_guard},
+ {10,sys_core_fold,{eval_failure,badarg}},
+ {11,sys_core_fold,no_clause_match},
+ {11,sys_core_fold,nomatch_guard},
+ {11,sys_core_fold,{eval_failure,badarg}}
+ ]}}],
+ ?line [] = run(Config, Ts),
+
+ ok.
+
+bad_arith(Config) when is_list(Config) ->
+ Ts = [{bad_arith,
+ <<"f() ->
+ if
+ a + 3 > 3 -> ok;
+ true -> error
+ end.
+
+ g(A) ->
+ if
+ is_integer(A), a + 3 > 3 -> ok;
+ a + 3 > 42, is_integer(A) -> ok;
+ true -> error
+ end.
+
+ h(A) ->
+ a + 3 + A.
+ ">>,
+ [],
+ {warnings,
+ [{3,sys_core_fold,nomatch_guard},
+ {3,sys_core_fold,{eval_failure,badarith}},
+ {9,sys_core_fold,nomatch_guard},
+ {9,sys_core_fold,{eval_failure,badarith}},
+ {10,sys_core_fold,nomatch_guard},
+ {10,sys_core_fold,{eval_failure,badarith}},
+ {15,sys_core_fold,{eval_failure,badarith}}
+ ] }}],
+ ?line [] = run(Config, Ts),
+ ok.
+
+bool_cases(Config) when is_list(Config) ->
+ Ts = [{bool_cases,
+ <<"
+ f(A, B) ->
+ case A > B of
+ true -> true;
+ false -> false;
+ Other -> {error,not_bool}
+ end.
+
+ g(A, B) ->
+ case A =/= B of
+ false -> false;
+ true -> true;
+ Other -> {error,not_bool}
+ end.
+
+ h(Bool) ->
+ case not Bool of
+ maybe -> strange;
+ false -> ok;
+ true -> error
+ end.
+ ">>,
+ [nowarn_unused_vars],
+ {warnings,
+ [{6,sys_core_fold,nomatch_shadow},
+ {13,sys_core_fold,nomatch_shadow},
+ {18,sys_core_fold,nomatch_clause_type} ]} }],
+ ?line [] = run(Config, Ts),
+ ok.
+
+bad_apply(Config) when is_list(Config) ->
+ Ts = [{bad_apply,
+ <<"
+ t(1) -> 42:42();
+ t(2) -> erlang:42();
+ t(3) -> 42:start();
+ t(4) -> []:start();
+ t(5) -> erlang:[]().
+ ">>,
+ [],
+ {warnings,
+ [{2,v3_kernel,bad_call},
+ {3,v3_kernel,bad_call},
+ {4,v3_kernel,bad_call},
+ {5,v3_kernel,bad_call},
+ {6,v3_kernel,bad_call}]}}],
+ ?line [] = run(Config, Ts),
+
+ %% Also verify that the generated code generates the correct error.
+ ?line try erlang:42() of
+ _ -> ?line ?t:fail()
+ catch
+ error:badarg -> ok
+ end,
+ ok.
+
+files(Config) when is_list(Config) ->
+ Ts = [{files_1,
+ <<"
+ -file(\"file1\", 14).
+
+ t1() ->
+ 1/0.
+
+ -file(\"file2\", 7).
+
+ t2() ->
+ 1/0.
+ ">>,
+ [],
+ {warnings,
+ [{"file1",[{17,sys_core_fold,{eval_failure,badarith}}]},
+ {"file2",[{10,sys_core_fold,{eval_failure,badarith}}]}]}}],
+
+ ?line [] = run(Config, Ts),
+ ok.
+
+%% Test warnings for term construction and BIF calls in effect context.
+effect(Config) when is_list(Config) ->
+ Ts = [{lc,
+ <<"
+ t(X) ->
+ case X of
+ warn_lc ->
+ [is_integer(Z) || Z <- [1,2,3]];
+ warn_lc_2 ->
+ [{error,Z} || Z <- [1,2,3]];
+ warn_lc_3 ->
+ [{error,abs(Z)} || Z <- [1,2,3]];
+ no_warn_lc ->
+ [put(last_integer, Z) || Z <- [1,2,3]]; %no warning
+ unused_tuple_literal ->
+ {a,b,c};
+ unused_list_literal ->
+ [1,2,3,4];
+ unused_integer ->
+ 42;
+ unused_arith ->
+ X*X;
+ nested ->
+ [{ok,node(),?MODULE:foo(),self(),[time(),date()],time()},
+ is_integer(X)];
+ unused_bit_syntax ->
+ <<X:8>>;
+ unused_fun ->
+ fun() -> {ok,X} end;
+ unused_atom ->
+ ignore; %no warning
+ unused_nil ->
+ []; %no warning
+ comp_op ->
+ X =:= 2;
+ cookie ->
+ erlang:get_cookie()
+ end,
+ ok.
+
+ %% No warnings should be generated in the following functions.
+ m1(X, Sz) ->
+ if
+ Sz =:= 0 -> X = 0;
+ true -> ok
+ end,
+ ok.
+
+ m2(X, Sz) ->
+ if
+ Sz =:= 0 -> X = {a,Sz};
+ true -> ok
+ end,
+ ok.
+
+ m3(X, Sz) ->
+ if
+ Sz =:= 0 -> X = [a,Sz];
+ true -> ok
+ end,
+ ok.
+
+ m4(X, Sz, Var) ->
+ if
+ Sz =:= 0 -> X = Var;
+ true -> ok
+ end,
+ ok.
+
+ m5(X, Sz) ->
+ if
+ Sz =:= 0 -> X = {a,b,c};
+ true -> ok
+ end,
+ ok.
+
+ m6(X, Sz) ->
+ if
+ Sz =:= 0 -> X = {a,Sz,[1,2,3]};
+ true -> ok
+ end,
+ ok.
+
+ m7(X, Sz) ->
+ if
+ Sz =:= 0 -> X = {a,Sz,[1,2,3],abs(Sz)};
+ true -> ok
+ end,
+ ok.
+ ">>,
+ [],
+ {warnings,[{5,sys_core_fold,{no_effect,{erlang,is_integer,1}}},
+ {7,sys_core_fold,useless_building},
+ {9,sys_core_fold,result_ignored},
+ {9,sys_core_fold,useless_building},
+ {13,sys_core_fold,useless_building},
+ {15,sys_core_fold,useless_building},
+ {17,sys_core_fold,useless_building},
+ {19,sys_core_fold,result_ignored},
+ {21,sys_core_fold,useless_building},
+ {21,sys_core_fold,{no_effect,{erlang,date,0}}},
+ {21,sys_core_fold,{no_effect,{erlang,node,0}}},
+ {21,sys_core_fold,{no_effect,{erlang,self,0}}},
+ {21,sys_core_fold,{no_effect,{erlang,time,0}}},
+ {22,sys_core_fold,useless_building},
+ {22,sys_core_fold,{no_effect,{erlang,is_integer,1}}},
+ {24,sys_core_fold,useless_building},
+ {26,sys_core_fold,useless_building},
+ {32,sys_core_fold,{no_effect,{erlang,'=:=',2}}},
+ {34,sys_core_fold,{no_effect,{erlang,get_cookie,0}}}]}}],
+ ?line [] = run(Config, Ts),
+ ok.
+
+bin_opt_info(Config) when is_list(Config) ->
+ Code = <<"
+ t1(Bin) ->
+ case Bin of
+ _ when byte_size(Bin) > 20 -> erlang:error(too_long);
+ <<_,T/binary>> -> t1(T);
+ <<>> -> ok
+ end.
+
+ t2(<<_,T/bytes>>) ->
+ split_binary(T, 4).
+ ">>,
+ Ts1 = [{bsm1,
+ Code,
+ [bin_opt_info],
+ {warnings,
+ [{4,sys_core_fold,orig_bin_var_used_in_guard},
+ {5,beam_bsm,{no_bin_opt,{{t1,1},no_suitable_bs_start_match}}},
+ {9,beam_bsm,{no_bin_opt,
+ {binary_used_in,{extfunc,erlang,split_binary,2}}}} ]}}],
+ ?line [] = run(Config, Ts1),
+
+ %% For coverage: don't give the bin_opt_info option.
+ Ts2 = [{bsm2,
+ Code,
+ [],
+ []}],
+ ?line [] = run(Config, Ts2),
+ ok.
+
+bin_construction(Config) when is_list(Config) ->
+ Ts = [{bin_construction,
+ <<"
+ t() ->
+ Bin = <<1,2,3>>,
+ <<Bin:4/binary>>.
+
+ x() ->
+ Bin = <<1,2,3,7:4>>,
+ <<Bin/binary>>.
+ ">>,
+ [],
+ {warnings,[{4,sys_core_fold,embedded_binary_size},
+ {8,sys_core_fold,{embedded_unit,8,28}}]}}],
+ ?line [] = run(Config, Ts),
+
+ ok.
+
+%%%
+%%% End of test cases.
+%%%
+
+run(Config, Tests) ->
+ F = fun({N,P,Ws,E}, BadL) ->
+ case catch run_test(Config, P, Ws) of
+ E ->
+ BadL;
+ Bad ->
+ ?t:format("~nTest ~p failed. Expected~n ~p~n"
+ "but got~n ~p~n", [N, E, Bad]),
+ fail()
+ end
+ end,
+ lists:foldl(F, [], Tests).
+
+
+%% Compiles a test module and returns the list of errors and warnings.
+
+run_test(Conf, Test0, Warnings) ->
+ Filename = 'warnings_test.erl',
+ ?line DataDir = ?privdir,
+ ?line Test = ["-module(warnings_test). ", Test0],
+ ?line File = filename:join(DataDir, Filename),
+ ?line Opts = [binary,export_all,return|Warnings],
+ ?line ok = file:write_file(File, Test),
+
+ %% Compile once just to print all warnings.
+ ?line compile:file(File, [binary,export_all,report|Warnings]),
+
+ %% Test result of compilation.
+ ?line Res = case compile:file(File, Opts) of
+ {ok, _M, Bin, []} when is_binary(Bin) ->
+ [];
+ {ok, _M, Bin, Ws0} when is_binary(Bin) ->
+ %% We are not interested in warnings from
+ %% erl_lint here.
+ WsL = [{F,[W || {_,Mod,_}=W <- Ws,
+ Mod =/= erl_lint]} ||
+ {F,Ws} <- Ws0],
+ case WsL of
+ [{_File,Ws}] -> {warnings, Ws};
+ _ -> list_to_tuple([warnings, WsL])
+ end
+ end,
+ file:delete(File),
+ Res.
+
+fail() ->
+ io:format("failed~n"),
+ ?t:fail().